summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2015-04-07 15:39:18 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2015-04-07 15:41:36 +0200
commit35d47fa659ad3509a888b4555f90e9b413af84c7 (patch)
tree7612fa33710c2c7fad7393b234840e79b7a303d3
parentad4cac84dd32edf79827c48d549e0ddef7dbd669 (diff)
downloadgnutls-35d47fa659ad3509a888b4555f90e9b413af84c7.tar.gz
introduced GNUTLS_E_NEED_FALLBACK to allow falling back from registered ciphers
That allows a registered cipher to indicate that it cannot operate (e.g., due to memory constraints, or internal limits), and gnutls should proceed with the default algorithms.
-rw-r--r--lib/crypto-backend.c9
-rw-r--r--lib/gnutls_cipher_int.c13
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
3 files changed, 23 insertions, 1 deletions
diff --git a/lib/crypto-backend.c b/lib/crypto-backend.c
index a4415169ca..b509fabdc7 100644
--- a/lib/crypto-backend.c
+++ b/lib/crypto-backend.c
@@ -151,6 +151,9 @@ void _gnutls_crypto_deregister(void)
* priority of 90 and CPU-assisted of 80. The algorithm with the lowest priority will be
* used by gnutls.
*
+ * In the case the registered init function return %GNUTLS_E_NEED_FALLBACK
+ * then GnuTLS will attempt to use the next in priority registered cipher.
+ *
* This function should be called before gnutls_global_init().
*
* For simplicity you can use the convenience
@@ -193,6 +196,9 @@ const gnutls_crypto_cipher_st
* priority of 90 and CPU-assisted of 80. The algorithm with the lowest priority will be
* used by gnutls.
*
+ * In the case the registered init function return %GNUTLS_E_NEED_FALLBACK
+ * then GnuTLS will attempt to use the next in priority registered cipher.
+ *
* The functions which are marked as non-AEAD they are not required when
* registering a cipher to be used with the new AEAD API introduced in
* GnuTLS 3.4.0. Internally GnuTLS uses the new AEAD API.
@@ -241,6 +247,9 @@ gnutls_crypto_register_cipher(gnutls_cipher_algorithm_t algorithm,
* priority of 90 and CPU-assisted of 80. The algorithm with the lowest priority will be
* used by gnutls.
*
+ * In the case the registered init function return %GNUTLS_E_NEED_FALLBACK
+ * then GnuTLS will attempt to use the next in priority registered cipher.
+ *
* The functions registered will be used with the new AEAD API introduced in
* GnuTLS 3.4.0. Internally GnuTLS uses the new AEAD API.
*
diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c
index 3368bae5b4..6670023c8c 100644
--- a/lib/gnutls_cipher_int.c
+++ b/lib/gnutls_cipher_int.c
@@ -30,6 +30,14 @@
#include <fips.h>
#include <algorithms.h>
+#define SR_FB(x, cleanup) ret=(x); if ( ret<0 ) { \
+ if (ret == GNUTLS_E_NEED_FALLBACK) \
+ goto fallback; \
+ gnutls_assert(); \
+ ret = GNUTLS_E_INTERNAL_ERROR; \
+ goto cleanup; \
+ }
+
#define SR(x, cleanup) if ( (x)<0 ) { \
gnutls_assert(); \
ret = GNUTLS_E_INTERNAL_ERROR; \
@@ -80,7 +88,9 @@ _gnutls_cipher_init(cipher_hd_st * handle, const cipher_entry_st * e,
handle->tag = cc->tag;
handle->setiv = cc->setiv;
- SR(cc->init(e->id, &handle->handle, enc), cc_cleanup);
+ /* if cc->init() returns GNUTLS_E_NEED_FALLBACK we
+ * use the default ciphers */
+ SR_FB(cc->init(e->id, &handle->handle, enc), cc_cleanup);
SR(cc->setkey(handle->handle, key->data, key->size),
cc_cleanup);
if (iv) {
@@ -91,6 +101,7 @@ _gnutls_cipher_init(cipher_hd_st * handle, const cipher_entry_st * e,
return 0;
}
+ fallback:
handle->encrypt = _gnutls_cipher_ops.encrypt;
handle->decrypt = _gnutls_cipher_ops.decrypt;
handle->aead_encrypt = _gnutls_cipher_ops.aead_encrypt;
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 2511b99915..a4bb933500 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -2507,6 +2507,8 @@ int gnutls_fips140_mode_enabled(void);
#define GNUTLS_E_PK_GENERATION_ERROR -403
#define GNUTLS_E_IDNA_ERROR -404
+#define GNUTLS_E_NEED_FALLBACK -405
+
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250