diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-10-23 15:31:05 +0000 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-10-23 15:31:05 +0000 |
commit | e4a7db34259295ebb32a0255215471323948efbb (patch) | |
tree | 8bf3f5d771be0e0a236db4e2b803c75aa78d3110 | |
parent | 69390cc8a09fcb4167a995e570c7d2163264f4c2 (diff) | |
parent | 01942d357af587ad913154a2222e1a525501b468 (diff) | |
download | gnutls-e4a7db34259295ebb32a0255215471323948efbb.tar.gz |
Merge branch 'tls-continuous-mac' into 'master'
Support GOST cipher suite MAC calculation
See merge request gnutls/gnutls!1098
-rw-r--r-- | lib/algorithms.h | 2 | ||||
-rw-r--r-- | lib/algorithms/ciphers.c | 13 | ||||
-rw-r--r-- | lib/algorithms/mac.c | 13 | ||||
-rw-r--r-- | lib/cipher.c | 4 | ||||
-rw-r--r-- | lib/cipher_int.c | 17 | ||||
-rw-r--r-- | lib/cipher_int.h | 3 | ||||
-rw-r--r-- | lib/crypto-api.c | 8 | ||||
-rw-r--r-- | lib/gnutls_int.h | 12 | ||||
-rw-r--r-- | lib/record.c | 2 |
9 files changed, 46 insertions, 28 deletions
diff --git a/lib/algorithms.h b/lib/algorithms.h index 84271e53b8..a83fec07bb 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -183,7 +183,7 @@ inline static int _gnutls_digest_is_secure(const mac_entry_st * e) if (unlikely(e == NULL)) return 0; else - return (e->preimage_insecure==0); + return !(e->flags & GNUTLS_MAC_FLAG_PREIMAGE_INSECURE); } /* Functions for cipher suites. */ diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c index aab3708128..fd47c13b66 100644 --- a/lib/algorithms/ciphers.c +++ b/lib/algorithms/ciphers.c @@ -86,7 +86,7 @@ static const cipher_entry_st algorithms[] = { .implicit_iv = 4, .explicit_iv = 8, .cipher_iv = 12, - .only_aead = 1, + .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, .tagsize = 16}, { .name = "AES-256-CCM", .id = GNUTLS_CIPHER_AES_256_CCM, @@ -96,7 +96,7 @@ static const cipher_entry_st algorithms[] = { .implicit_iv = 4, .explicit_iv = 8, .cipher_iv = 12, - .only_aead = 1, + .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, .tagsize = 16}, { .name = "AES-128-CCM-8", .id = GNUTLS_CIPHER_AES_128_CCM_8, @@ -106,7 +106,7 @@ static const cipher_entry_st algorithms[] = { .implicit_iv = 4, .explicit_iv = 8, .cipher_iv = 12, - .only_aead = 1, + .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, .tagsize = 8}, { .name = "AES-256-CCM-8", .id = GNUTLS_CIPHER_AES_256_CCM_8, @@ -116,7 +116,7 @@ static const cipher_entry_st algorithms[] = { .implicit_iv = 4, .explicit_iv = 8, .cipher_iv = 12, - .only_aead = 1, + .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, .tagsize = 8}, { .name = "ARCFOUR-128", .id = GNUTLS_CIPHER_ARCFOUR_128, @@ -164,10 +164,9 @@ static const cipher_entry_st algorithms[] = { .type = CIPHER_AEAD, .implicit_iv = 12, .explicit_iv = 0, - .xor_nonce = 1, - .cipher_iv = 12, /* in chacha20 we don't need a rekey after 2^24 messages */ - .no_rekey = 1, + .flags = GNUTLS_CIPHER_FLAG_XOR_NONCE | GNUTLS_CIPHER_FLAG_NO_REKEY, + .cipher_iv = 12, .tagsize = 16 }, { .name = "CAMELLIA-128-GCM", diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c index fc2e99b186..376c76df06 100644 --- a/lib/algorithms/mac.c +++ b/lib/algorithms/mac.c @@ -49,7 +49,7 @@ mac_entry_st hash_algorithms[] = { .id = GNUTLS_MAC_MD5_SHA1, .output_size = 36, .key_size = 36, - .preimage_insecure = 1, + .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE, .block_size = 64}, {.name = "SHA256", .oid = HASH_OID_SHA256, @@ -121,11 +121,11 @@ mac_entry_st hash_algorithms[] = { .id = GNUTLS_MAC_MD5, .output_size = 16, .key_size = 16, - .preimage_insecure = 1, + .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE, .block_size = 64}, {.name = "MD2", .oid = HASH_OID_MD2, - .preimage_insecure = 1, + .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE, .id = GNUTLS_MAC_MD2}, {.name = "RIPEMD160", .oid = HASH_OID_RMD160, @@ -181,7 +181,8 @@ mac_entry_st hash_algorithms[] = { .id = GNUTLS_MAC_GOST28147_TC26Z_IMIT, .output_size = 4, .key_size = 32, - .block_size = 8}, + .block_size = 8, + .flags = GNUTLS_MAC_FLAG_CONTINUOUS_MAC}, {.name = "MAC-NULL", .id = GNUTLS_MAC_NULL}, {0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -276,7 +277,7 @@ int _gnutls_digest_mark_insecure(const char *name) for(p = hash_algorithms; p->name != NULL; p++) { if (p->oid != NULL && c_strcasecmp(p->name, name) == 0) { - p->preimage_insecure = 1; + p->flags |= GNUTLS_MAC_FLAG_PREIMAGE_INSECURE; return 0; } } @@ -291,7 +292,7 @@ unsigned _gnutls_digest_is_insecure(gnutls_digest_algorithm_t dig) for(p = hash_algorithms; p->name != NULL; p++) { if (p->oid != NULL && p->id == (gnutls_mac_algorithm_t)dig) { - return p->preimage_insecure; + return p->flags & GNUTLS_MAC_FLAG_PREIMAGE_INSECURE; } } diff --git a/lib/cipher.c b/lib/cipher.c index 679a5807c1..b69a228db5 100644 --- a/lib/cipher.c +++ b/lib/cipher.c @@ -332,7 +332,7 @@ encrypt_packet(gnutls_session_t session, cipher_data += blocksize; } } else { /* AEAD */ - if (params->cipher->xor_nonce == 0) { + if ((params->cipher->flags & GNUTLS_CIPHER_FLAG_XOR_NONCE) == 0) { /* Values in AEAD are pretty fixed in TLS 1.2 for 128-bit block */ if (params->write.iv_size != imp_iv_size) @@ -602,7 +602,7 @@ decrypt_packet(gnutls_session_t session, if (unlikely(ciphertext->size < (tag_size + exp_iv_size))) return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); - if (params->cipher->xor_nonce == 0) { + if ((params->cipher->flags & GNUTLS_CIPHER_FLAG_XOR_NONCE) == 0) { /* Values in AEAD are pretty fixed in TLS 1.2 for 128-bit block */ if (unlikely(params->read.iv_size != 4)) diff --git a/lib/cipher_int.c b/lib/cipher_int.c index 40bf64f8bc..b5308aa629 100644 --- a/lib/cipher_int.c +++ b/lib/cipher_int.c @@ -218,6 +218,9 @@ int _gnutls_auth_cipher_init(auth_cipher_hd_st * handle, gnutls_assert(); goto cleanup; } +#ifdef ENABLE_GOST + handle->continuous_mac = !!(me->flags & GNUTLS_MAC_FLAG_CONTINUOUS_MAC); +#endif handle->tag_size = _gnutls_mac_get_algo_len(me); } else if (_gnutls_cipher_algo_is_aead(e)) { @@ -422,15 +425,23 @@ int _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void *tag, { if (handle->is_mac) { #ifdef ENABLE_SSL3 - int ret; - if (handle->ssl_hmac) { - ret = + int ret = _gnutls_mac_output_ssl3(&handle->mac.dig, tag); if (ret < 0) return gnutls_assert_val(ret); } else #endif +#ifdef ENABLE_GOST + /* draft-smyshlyaev-tls12-gost-suites section 4.1.2 */ + if (handle->continuous_mac) { + mac_hd_st temp_mac; + int ret = _gnutls_mac_copy(&handle->mac.mac, &temp_mac); + if (ret < 0) + return gnutls_assert_val(ret); + _gnutls_mac_deinit(&temp_mac, tag); + } else +#endif _gnutls_mac_output(&handle->mac.mac, tag); } else if (_gnutls_cipher_is_aead(&handle->cipher)) { _gnutls_cipher_tag(&handle->cipher, tag, tag_size); diff --git a/lib/cipher_int.h b/lib/cipher_int.h index 36c9385fbf..b50a59c64a 100644 --- a/lib/cipher_int.h +++ b/lib/cipher_int.h @@ -211,6 +211,9 @@ typedef struct { #ifdef ENABLE_SSL3 unsigned int ssl_hmac:1; #endif +#ifdef ENABLE_GOST + unsigned int continuous_mac:1; +#endif unsigned int non_null:1; unsigned int etm:1; size_t tag_size; diff --git a/lib/crypto-api.c b/lib/crypto-api.c index 7308d7e7bb..d3e8094563 100644 --- a/lib/crypto-api.c +++ b/lib/crypto-api.c @@ -67,7 +67,7 @@ gnutls_cipher_init(gnutls_cipher_hd_t * handle, return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); e = cipher_to_entry(cipher); - if (e == NULL || e->only_aead) + if (e == NULL || (e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD)) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); *handle = gnutls_calloc(1, sizeof(api_cipher_hd_st)); @@ -1006,7 +1006,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, else if (tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e)) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - if (handle->ctx_enc.e->only_aead || handle->ctx_enc.encrypt == NULL) { + if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) || handle->ctx_enc.encrypt == NULL) { /* ciphertext cannot be produced in a piecemeal approach */ struct iov_store_st auth; struct iov_store_st ptext; @@ -1130,7 +1130,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(), * then this becomes a convenience function as it missed the lower-level primitives * necessary for piecemeal encryption. */ - if (handle->ctx_enc.e->only_aead || handle->ctx_enc.encrypt == NULL) { + if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) || handle->ctx_enc.encrypt == NULL) { /* ciphertext cannot be produced in a piecemeal approach */ struct iov_store_st auth; struct iov_store_st ptext; @@ -1274,7 +1274,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(), * then this becomes a convenience function as it missed the lower-level primitives * necessary for piecemeal encryption. */ - if (handle->ctx_enc.e->only_aead || handle->ctx_enc.encrypt == NULL) { + if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) || handle->ctx_enc.encrypt == NULL) { /* ciphertext cannot be produced in a piecemeal approach */ struct iov_store_st auth; struct iov_store_st ctext; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 7f7b6a7c97..5f1a915a14 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -645,6 +645,10 @@ typedef struct record_state_st record_state_st; struct record_parameters_st; typedef struct record_parameters_st record_parameters_st; +#define GNUTLS_CIPHER_FLAG_ONLY_AEAD (1 << 0) /* When set, this cipher is only available through the new AEAD API */ +#define GNUTLS_CIPHER_FLAG_XOR_NONCE (1 << 1) /* In this TLS AEAD cipher xor the implicit_iv with the nonce */ +#define GNUTLS_CIPHER_FLAG_NO_REKEY (1 << 2) /* whether this tls1.3 cipher doesn't need to rekey after 2^24 messages */ + /* cipher and mac parameters */ typedef struct cipher_entry_st { const char *name; @@ -656,9 +660,7 @@ typedef struct cipher_entry_st { uint16_t explicit_iv; /* the size of explicit IV - the IV stored in record */ uint16_t cipher_iv; /* the size of IV needed by the cipher */ uint16_t tagsize; - bool xor_nonce; /* In this TLS AEAD cipher xor the implicit_iv with the nonce */ - bool only_aead; /* When set, this cipher is only available through the new AEAD API */ - bool no_rekey; /* whether this tls1.3 cipher doesn't need to rekey after 2^24 messages */ + unsigned flags; } cipher_entry_st; typedef struct gnutls_cipher_suite_entry_st { @@ -691,6 +693,8 @@ typedef struct gnutls_group_entry_st { unsigned tls_id; /* The RFC4492 namedCurve ID or TLS 1.3 group ID */ } gnutls_group_entry_st; +#define GNUTLS_MAC_FLAG_PREIMAGE_INSECURE 1 /* if this algorithm should not be trusted for pre-image attacks */ +#define GNUTLS_MAC_FLAG_CONTINUOUS_MAC (1 << 1) /* if this MAC should be used in a 'continuous' way in TLS */ /* This structure is used both for MACs and digests */ typedef struct mac_entry_st { @@ -703,7 +707,7 @@ typedef struct mac_entry_st { unsigned nonce_size; unsigned placeholder; /* if set, then not a real MAC */ unsigned block_size; /* internal block size for HMAC */ - unsigned preimage_insecure; /* if this algorithm should not be trusted for pre-image attacks */ + unsigned flags; } mac_entry_st; typedef struct { diff --git a/lib/record.c b/lib/record.c index 5105c13fdd..ced217c245 100644 --- a/lib/record.c +++ b/lib/record.c @@ -584,7 +584,7 @@ _gnutls_send_tlen_int(gnutls_session_t session, content_type_t type, (int) cipher_size); if (vers->tls13_sem && !(session->internals.flags & GNUTLS_NO_AUTO_REKEY) && - !(record_params->cipher->no_rekey)) { + !(record_params->cipher->flags & GNUTLS_CIPHER_FLAG_NO_REKEY)) { if (unlikely(record_state->sequence_number.i[7] == 0xfd && record_state->sequence_number.i[6] == 0xff && record_state->sequence_number.i[5] == 0xff)) { |