summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/cipher_int.c2
-rw-r--r--lib/cipher_int.h15
-rw-r--r--lib/crypto-api.c27
-rw-r--r--lib/crypto-backend.h1
-rw-r--r--lib/crypto-selftests.c26
-rw-r--r--lib/fips.c6
-rw-r--r--lib/includes/gnutls/crypto.h1
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/nettle/cipher.c14
9 files changed, 93 insertions, 0 deletions
diff --git a/lib/cipher_int.c b/lib/cipher_int.c
index c6032ff053..40bf64f8bc 100644
--- a/lib/cipher_int.c
+++ b/lib/cipher_int.c
@@ -101,6 +101,7 @@ _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e,
handle->auth = cc->auth;
handle->tag = cc->tag;
handle->setiv = cc->setiv;
+ handle->getiv = cc->getiv;
/* if cc->init() returns GNUTLS_E_NEED_FALLBACK we
* use the default ciphers */
@@ -126,6 +127,7 @@ _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e,
handle->auth = _gnutls_cipher_ops.auth;
handle->tag = _gnutls_cipher_ops.tag;
handle->setiv = _gnutls_cipher_ops.setiv;
+ handle->getiv = _gnutls_cipher_ops.getiv;
/* otherwise use generic cipher interface
*/
diff --git a/lib/cipher_int.h b/lib/cipher_int.h
index de83c36362..e3e010a8e7 100644
--- a/lib/cipher_int.h
+++ b/lib/cipher_int.h
@@ -50,6 +50,7 @@ typedef void (*cipher_deinit_func) (void *hd);
typedef int (*cipher_auth_func) (void *hd, const void *data, size_t);
typedef int (*cipher_setiv_func) (void *hd, const void *iv, size_t);
+typedef int (*cipher_getiv_func) (void *hd, void *iv, size_t);
typedef void (*cipher_tag_func) (void *hd, void *tag, size_t);
@@ -63,6 +64,7 @@ typedef struct {
cipher_auth_func auth;
cipher_tag_func tag;
cipher_setiv_func setiv;
+ cipher_getiv_func getiv;
cipher_deinit_func deinit;
} cipher_hd_st;
@@ -76,6 +78,16 @@ inline static int _gnutls_cipher_setiv(const cipher_hd_st * handle,
return handle->setiv(handle->handle, iv, ivlen);
}
+inline static int _gnutls_cipher_getiv(const cipher_hd_st * handle,
+ void *iv, size_t ivlen)
+{
+ if (unlikely(handle == NULL || handle->handle == NULL ||
+ handle->getiv == NULL))
+ return GNUTLS_E_INVALID_REQUEST;
+
+ return handle->getiv(handle->handle, iv, ivlen);
+}
+
inline static int
_gnutls_cipher_encrypt2(const cipher_hd_st * handle, const void *text,
size_t textlen, void *ciphertext,
@@ -158,6 +170,9 @@ inline static void _gnutls_cipher_deinit(cipher_hd_st * handle)
int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher);
+int _gnutls_cipher_get_iv(gnutls_cipher_hd_t handle, void *iv,
+ size_t ivlen);
+
#define _gnutls_cipher_is_aead(h) _gnutls_cipher_algo_is_aead((h)->e)
/* returns the tag in AUTHENC ciphers */
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index ed1499315f..a275a7611f 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -168,6 +168,33 @@ gnutls_cipher_set_iv(gnutls_cipher_hd_t handle, void *iv, size_t ivlen)
}
/**
+ * _gnutls_cipher_get_iv:
+ * @handle: is a #gnutls_cipher_hd_t type
+ * @iv: the IV to set
+ * @ivlen: the length of the IV
+ *
+ * This function will retrieve the internal IV value. @iv must have @ivlen
+ * length at least.
+ *
+ * This is sorely for validation purposes of our crypto
+ * implementation. For other purposes, the IV can be typically
+ * calculated from the initial IV value and the subsequent ciphertext
+ * values. As such, this function only works with the internally
+ * registered ciphers.
+ *
+ * Returns: The length of IV or a negative error code on error.
+ *
+ * Since: 3.6.8
+ **/
+int
+_gnutls_cipher_get_iv(gnutls_cipher_hd_t handle, void *iv, size_t ivlen)
+{
+ api_cipher_hd_st *h = handle;
+
+ return _gnutls_cipher_getiv(&h->ctx_enc, iv, ivlen);
+}
+
+/**
* gnutls_cipher_encrypt:
* @handle: is a #gnutls_cipher_hd_t type
* @ptext: the data to encrypt
diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
index 037241fc18..76004a7211 100644
--- a/lib/crypto-backend.h
+++ b/lib/crypto-backend.h
@@ -33,6 +33,7 @@ typedef struct {
gnutls_cipher_init_func init;
gnutls_cipher_setkey_func setkey;
gnutls_cipher_setiv_func setiv;
+ gnutls_cipher_getiv_func getiv;
gnutls_cipher_encrypt_func encrypt;
gnutls_cipher_decrypt_func decrypt;
gnutls_cipher_aead_encrypt_func aead_encrypt;
diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
index 5d040fb603..66f6db620d 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -52,6 +52,9 @@ struct cipher_vectors_st {
const uint8_t *iv;
unsigned int iv_size;
+
+ const uint8_t *internal_iv;
+ unsigned int internal_iv_size;
};
struct cipher_aead_vectors_st {
@@ -385,6 +388,9 @@ const struct cipher_vectors_st aes128_cfb8_vectors[] = { /* NIST 800-38a */
"\x32\xb9",
STR(iv, iv_size,
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"),
+ /* the least significant 16 bytes of ciphertext */
+ STR(internal_iv, internal_iv_size,
+ "\x42\x4c\x9c\x0d\xd4\x36\xba\xce\x9e\x0e\xd4\x58\x6a\x4f\x32\xb9"),
},
};
@@ -401,6 +407,9 @@ const struct cipher_vectors_st aes192_cfb8_vectors[] = { /* NIST 800-38a */
"\x67\x8a",
STR(iv, iv_size,
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"),
+ /* the least significant 16 bytes of ciphertext */
+ STR(internal_iv, internal_iv_size,
+ "\x52\x1e\xf0\xa9\x05\xca\x44\xcd\x05\x7c\xbf\x0d\x47\xa0\x67\x8a"),
},
};
@@ -417,6 +426,9 @@ const struct cipher_vectors_st aes256_cfb8_vectors[] = { /* NIST 800-38a */
"\x97\x00",
STR(iv, iv_size,
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"),
+ /* the least significant 16 bytes of ciphertext */
+ STR(internal_iv, internal_iv_size,
+ "\x1a\x85\x20\xa6\x4d\xb5\x5f\xcc\x8a\xc5\x54\x84\x4e\x88\x97\x00"),
},
};
@@ -607,6 +619,20 @@ static int test_cipher(gnutls_cipher_algorithm_t cipher,
}
}
+ /* check the internal IV */
+ if (vectors[i].internal_iv_size > 0) {
+ ret = _gnutls_cipher_get_iv(hd, tmp, sizeof(tmp));
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+
+ if (memcmp(tmp, vectors[i].internal_iv, ret) != 0) {
+ _gnutls_debug_log("%s vector %d internal IV check failed!\n",
+ gnutls_cipher_get_name(cipher),
+ i);
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+ }
+
gnutls_cipher_deinit(hd);
}
diff --git a/lib/fips.c b/lib/fips.c
index ef1f7cbc35..b92edbbd79 100644
--- a/lib/fips.c
+++ b/lib/fips.c
@@ -329,6 +329,12 @@ int _gnutls_fips_perform_self_checks2(void)
goto error;
}
+ ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CFB8);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
/* Digest tests */
ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_224);
if (ret < 0) {
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index f6e50df86a..4f70b4a568 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -154,6 +154,7 @@ typedef int (*gnutls_cipher_init_func) (gnutls_cipher_algorithm_t, void **ctx, i
typedef int (*gnutls_cipher_setkey_func) (void *ctx, const void *key, size_t keysize);
/* old style ciphers */
typedef int (*gnutls_cipher_setiv_func) (void *ctx, const void *iv, size_t ivsize);
+typedef int (*gnutls_cipher_getiv_func) (void *ctx, void *iv, size_t ivsize);
typedef int (*gnutls_cipher_encrypt_func) (void *ctx, const void *plain, size_t plainsize,
void *encr, size_t encrsize);
typedef int (*gnutls_cipher_decrypt_func) (void *ctx, const void *encr, size_t encrsize,
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index d10e22b20e..2bc33ee732 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1297,6 +1297,7 @@ GNUTLS_FIPS140_3_4 {
_gnutls_dh_generate_key;
_gnutls_ecdh_generate_key;
_gnutls_ecdh_compute_key;
+ _gnutls_cipher_get_iv;
} GNUTLS_3_4;
GNUTLS_PRIVATE_3_4 {
diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
index 9194fb750c..632528140a 100644
--- a/lib/nettle/cipher.c
+++ b/lib/nettle/cipher.c
@@ -841,6 +841,19 @@ wrap_nettle_cipher_setiv(void *_ctx, const void *iv, size_t iv_size)
}
static int
+wrap_nettle_cipher_getiv(void *_ctx, void *iv, size_t iv_size)
+{
+ struct nettle_cipher_ctx *ctx = _ctx;
+
+ if (iv_size < ctx->iv_size)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ memcpy(iv, ctx->iv, ctx->iv_size);
+
+ return (int) ctx->iv_size;
+}
+
+static int
wrap_nettle_cipher_decrypt(void *_ctx, const void *encr, size_t encr_size,
void *plain, size_t plain_size)
{
@@ -974,6 +987,7 @@ gnutls_crypto_cipher_st _gnutls_cipher_ops = {
.init = wrap_nettle_cipher_init,
.exists = wrap_nettle_cipher_exists,
.setiv = wrap_nettle_cipher_setiv,
+ .getiv = wrap_nettle_cipher_getiv,
.setkey = wrap_nettle_cipher_setkey,
.encrypt = wrap_nettle_cipher_encrypt,
.decrypt = wrap_nettle_cipher_decrypt,