diff options
-rw-r--r-- | lib/cipher_int.c | 2 | ||||
-rw-r--r-- | lib/cipher_int.h | 15 | ||||
-rw-r--r-- | lib/crypto-api.c | 27 | ||||
-rw-r--r-- | lib/crypto-backend.h | 1 | ||||
-rw-r--r-- | lib/crypto-selftests.c | 26 | ||||
-rw-r--r-- | lib/fips.c | 6 | ||||
-rw-r--r-- | lib/includes/gnutls/crypto.h | 1 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/nettle/cipher.c | 14 |
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, |