summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/algorithms.h13
-rw-r--r--lib/algorithms/ciphers.c12
-rw-r--r--lib/crypto-api.c12
-rw-r--r--lib/gnutls_cipher.c212
-rw-r--r--lib/gnutls_constate.c4
-rw-r--r--lib/gnutls_dtls.c2
-rw-r--r--lib/gnutls_int.h8
-rw-r--r--lib/gnutls_range.c6
8 files changed, 149 insertions, 120 deletions
diff --git a/lib/algorithms.h b/lib/algorithms.h
index 93ef670d45..205f6f681a 100644
--- a/lib/algorithms.h
+++ b/lib/algorithms.h
@@ -175,11 +175,11 @@ _gnutls_cipher_suite_get_id(gnutls_kx_algorithm_t kx_algorithm,
/* Functions for ciphers. */
const cipher_entry_st *cipher_to_entry(gnutls_cipher_algorithm_t c);
-inline static int _gnutls_cipher_is_block(const cipher_entry_st * e)
+inline static cipher_type_t _gnutls_cipher_type(const cipher_entry_st * e)
{
if (unlikely(e == NULL))
return 0;
- return e->block;
+ return e->type;
}
inline static int _gnutls_cipher_get_block_size(const cipher_entry_st * e)
@@ -232,7 +232,7 @@ inline static int _gnutls_cipher_algo_is_aead(const cipher_entry_st * e)
{
if (unlikely(e == NULL))
return 0;
- return e->aead;
+ return (e->type == CIPHER_AEAD)?1:0;
}
inline static int _gnutls_cipher_is_ok(const cipher_entry_st * e)
@@ -250,11 +250,8 @@ inline static int _gnutls_cipher_get_tag_size(const cipher_entry_st * e)
if (unlikely(e == NULL))
return ret;
- if (e->aead)
- ret = e->blocksize; /* FIXME: happens to be the same for now */
- else
- ret = 0;
- return ret;
+ /* non-AEAD have 0 as tag size */
+ return e->tagsize;
}
/* Functions for key exchange. */
diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c
index ebec727a7b..df202f34aa 100644
--- a/lib/algorithms/ciphers.c
+++ b/lib/algorithms/ciphers.c
@@ -40,10 +40,10 @@ static const cipher_entry_st algorithms[] = {
0, 16, 16, 0},
{"AES-128-CBC", GNUTLS_CIPHER_AES_128_CBC, 16, 16, CIPHER_BLOCK,
0, 16, 16, 0},
- {"AES-128-GCM", GNUTLS_CIPHER_AES_128_GCM, 16, 16, CIPHER_STREAM,
- 4, 8, 12, 1},
- {"AES-256-GCM", GNUTLS_CIPHER_AES_256_GCM, 16, 32, CIPHER_STREAM,
- 4, 8, 12, 1},
+ {"AES-128-GCM", GNUTLS_CIPHER_AES_128_GCM, 16, 16, CIPHER_AEAD,
+ 4, 8, 12, 16},
+ {"AES-256-GCM", GNUTLS_CIPHER_AES_256_GCM, 16, 32, CIPHER_AEAD,
+ 4, 8, 12, 16},
{"ARCFOUR-128", GNUTLS_CIPHER_ARCFOUR_128, 1, 16, CIPHER_STREAM,
0, 0, 0, 0},
{"ESTREAM-SALSA20-256", GNUTLS_CIPHER_ESTREAM_SALSA20_256, 64, 32,
@@ -57,9 +57,9 @@ static const cipher_entry_st algorithms[] = {
{"CAMELLIA-128-CBC", GNUTLS_CIPHER_CAMELLIA_128_CBC, 16, 16,
CIPHER_BLOCK, 0, 16, 16, 0},
{"CAMELLIA-128-GCM", GNUTLS_CIPHER_CAMELLIA_128_GCM, 16, 16,
- CIPHER_STREAM, 4, 8, 12, 1},
+ CIPHER_AEAD, 4, 8, 12, 16},
{"CAMELLIA-256-GCM", GNUTLS_CIPHER_CAMELLIA_256_GCM, 16, 32,
- CIPHER_STREAM, 4, 8, 12, 1},
+ CIPHER_AEAD, 4, 8, 12, 16},
{"3DES-CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 0, 8, 8, 0},
{"DES-CBC", GNUTLS_CIPHER_DES_CBC, 8, 8, CIPHER_BLOCK, 0, 8, 8, 0},
{"ARCFOUR-40", GNUTLS_CIPHER_ARCFOUR_40, 1, 5, CIPHER_STREAM, 0, 0, 0, 0},
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index 70dbb772bb..c7add3e6b9 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -75,7 +75,7 @@ gnutls_cipher_init(gnutls_cipher_hd_t * handle,
_gnutls_cipher_init(&h->ctx_enc, e, key,
iv, 1);
- if (ret >= 0 && _gnutls_cipher_is_block(e) != 0)
+ if (ret >= 0 && _gnutls_cipher_type(e) == CIPHER_BLOCK)
ret =
_gnutls_cipher_init(&h->ctx_dec, e, key, iv, 0);
@@ -156,7 +156,7 @@ gnutls_cipher_set_iv(gnutls_cipher_hd_t handle, void *iv, size_t ivlen)
_gnutls_cipher_setiv(&h->ctx_enc, iv, ivlen);
- if (_gnutls_cipher_is_block(h->ctx_enc.e) != 0)
+ if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK)
_gnutls_cipher_setiv(&h->ctx_dec, iv, ivlen);
}
@@ -204,7 +204,7 @@ gnutls_cipher_decrypt(gnutls_cipher_hd_t handle, void *ctext,
{
api_cipher_hd_st *h = handle;
- if (_gnutls_cipher_is_block(h->ctx_enc.e) == 0)
+ if (_gnutls_cipher_type(h->ctx_enc.e) != CIPHER_BLOCK)
return _gnutls_cipher_decrypt(&h->ctx_enc, ctext,
ctext_len);
else
@@ -262,7 +262,7 @@ gnutls_cipher_decrypt2(gnutls_cipher_hd_t handle, const void *ctext,
{
api_cipher_hd_st *h = handle;
- if (_gnutls_cipher_is_block(h->ctx_enc.e) == 0)
+ if (_gnutls_cipher_type(h->ctx_enc.e) != CIPHER_BLOCK)
return _gnutls_cipher_decrypt2(&h->ctx_enc, ctext,
ctext_len, ptext,
ptext_len);
@@ -286,7 +286,7 @@ void gnutls_cipher_deinit(gnutls_cipher_hd_t handle)
api_cipher_hd_st *h = handle;
_gnutls_cipher_deinit(&h->ctx_enc);
- if (_gnutls_cipher_is_block(h->ctx_enc.e) != 0)
+ if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK)
_gnutls_cipher_deinit(&h->ctx_dec);
gnutls_free(handle);
}
@@ -646,7 +646,7 @@ int gnutls_aead_cipher_init(gnutls_aead_cipher_hd_t * handle,
const cipher_entry_st* e;
e = cipher_to_entry(cipher);
- if (e == NULL || e->aead == 0)
+ if (e == NULL || e->type != CIPHER_AEAD)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
if (tag_size == 0)
diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index 5dbf1c5f7e..e9f76cf39e 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -291,7 +291,7 @@ compressed_to_ciphertext(gnutls_session_t session,
int tag_size =
_gnutls_auth_cipher_tag_len(&params->write.cipher_state);
int blocksize = _gnutls_cipher_get_block_size(params->cipher);
- unsigned block_algo = _gnutls_cipher_is_block(params->cipher);
+ unsigned algo_type = _gnutls_cipher_type(params->cipher);
uint8_t *data_ptr;
const version_entry_st *ver = get_version(session);
int explicit_iv = _gnutls_version_has_explicit_iv(ver);
@@ -318,7 +318,7 @@ compressed_to_ciphertext(gnutls_session_t session,
/* Calculate the encrypted length (padding etc.)
*/
- if (block_algo == CIPHER_BLOCK) {
+ if (algo_type == CIPHER_BLOCK) {
/* Call _gnutls_rnd() once. Get data used for the IV
*/
ret = _gnutls_rnd(GNUTLS_RND_NONCE, nonce, blocksize);
@@ -331,7 +331,7 @@ compressed_to_ciphertext(gnutls_session_t session,
calc_enc_length_block(session, ver, compressed->size,
tag_size, &pad, auth_cipher,
blocksize);
- } else {
+ } else { /* AEAD + STREAM */
pad = 0;
length =
calc_enc_length_stream(session, compressed->size,
@@ -348,49 +348,47 @@ compressed_to_ciphertext(gnutls_session_t session,
data_ptr = cipher_data;
- if (explicit_iv) { /* TLS 1.1 or later */
+ if (algo_type == CIPHER_BLOCK && explicit_iv != 0) {
+ /* copy the random IV.
+ */
+ memcpy(data_ptr, nonce, blocksize);
+ _gnutls_auth_cipher_setiv(&params->write.
+ cipher_state, data_ptr,
+ blocksize);
- if (block_algo == CIPHER_BLOCK) {
- /* copy the random IV.
- */
- memcpy(data_ptr, nonce, blocksize);
- _gnutls_auth_cipher_setiv(&params->write.
- cipher_state, data_ptr,
- blocksize);
+ data_ptr += blocksize;
+ cipher_data += blocksize;
+ } else if (algo_type == CIPHER_AEAD) {
+ /* Values in AEAD are pretty fixed in TLS 1.2 for 128-bit block
+ */
+ if (params->write.IV.data == NULL
+ || params->write.IV.size !=
+ imp_iv_size)
+ return
+ gnutls_assert_val
+ (GNUTLS_E_INTERNAL_ERROR);
- data_ptr += blocksize;
- cipher_data += blocksize;
- } else if (auth_cipher) {
- /* Values in AEAD are pretty fixed in TLS 1.2 for 128-bit block
- */
- if (params->write.IV.data == NULL
- || params->write.IV.size !=
- imp_iv_size)
- return
- gnutls_assert_val
- (GNUTLS_E_INTERNAL_ERROR);
-
- /* Instead of generating a new nonce on every packet, we use the
- * write.sequence_number (It is a MAY on RFC 5288).
- */
- memcpy(nonce, params->write.IV.data,
- params->write.IV.size);
- memcpy(&nonce[imp_iv_size],
- UINT64DATA(params->write.sequence_number),
- 8);
-
- _gnutls_auth_cipher_setiv(&params->write.
- cipher_state, nonce,
- imp_iv_size +
- exp_iv_size);
-
- /* copy the explicit part */
- memcpy(data_ptr, &nonce[imp_iv_size],
- exp_iv_size);
-
- data_ptr += exp_iv_size;
- cipher_data += exp_iv_size;
- }
+ /* Instead of generating a new nonce on every packet, we use the
+ * write.sequence_number (It is a MAY on RFC 5288), and safer
+ * as it will never reuse a value.
+ */
+ memcpy(nonce, params->write.IV.data,
+ params->write.IV.size);
+ memcpy(&nonce[imp_iv_size],
+ UINT64DATA(params->write.sequence_number),
+ 8);
+
+ _gnutls_auth_cipher_setiv(&params->write.
+ cipher_state, nonce,
+ imp_iv_size +
+ exp_iv_size);
+
+ /* copy the explicit part */
+ memcpy(data_ptr, &nonce[imp_iv_size],
+ exp_iv_size);
+
+ data_ptr += exp_iv_size;
+ cipher_data += exp_iv_size;
}
/* add the authenticate data */
@@ -418,7 +416,7 @@ static void dummy_wait(record_parameters_st * params,
unsigned int pad, unsigned total)
{
/* this hack is only needed on CBC ciphers */
- if (_gnutls_cipher_is_block(params->cipher) == CIPHER_BLOCK) {
+ if (_gnutls_cipher_type(params->cipher) == CIPHER_BLOCK) {
unsigned len;
/* force an additional hash compression function evaluation to prevent timing
@@ -460,6 +458,7 @@ ciphertext_to_compressed(gnutls_session_t session,
uint64 * sequence)
{
uint8_t tag[MAX_HASH_SIZE];
+ uint8_t nonce[MAX_CIPHER_BLOCK_SIZE];
const uint8_t *tag_ptr;
unsigned int pad = 0, i;
int length, length_to_decrypt;
@@ -484,58 +483,89 @@ ciphertext_to_compressed(gnutls_session_t session,
/* actual decryption (inplace)
*/
- switch (_gnutls_cipher_is_block(params->cipher)) {
- case CIPHER_STREAM:
+ switch (_gnutls_cipher_type(params->cipher)) {
+ case CIPHER_AEAD:
/* The way AEAD ciphers are defined in RFC5246, it allows
* only stream ciphers.
*/
- if (explicit_iv
- && _gnutls_auth_cipher_is_aead(&params->read.
- cipher_state)) {
- uint8_t nonce[MAX_CIPHER_BLOCK_SIZE];
- /* Values in AEAD are pretty fixed in TLS 1.2 for 128-bit block
- */
- if (unlikely
- (params->read.IV.data == NULL
- || params->read.IV.size != 4))
- return
- gnutls_assert_val
- (GNUTLS_E_INTERNAL_ERROR);
-
- if (unlikely
- (ciphertext->size <
- tag_size + exp_iv_size))
- return
- gnutls_assert_val
- (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
-
- memcpy(nonce, params->read.IV.data,
- imp_iv_size);
- memcpy(&nonce[imp_iv_size],
- ciphertext->data, exp_iv_size);
+ if (unlikely(_gnutls_auth_cipher_is_aead(&params->read.
+ cipher_state) == 0))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
- _gnutls_auth_cipher_setiv(&params->read.
- cipher_state, nonce,
- exp_iv_size +
- imp_iv_size);
-
- ciphertext->data += exp_iv_size;
- ciphertext->size -= exp_iv_size;
-
- length = length_to_decrypt =
- ciphertext->size - tag_size;
- tag_ptr = ciphertext->data + length_to_decrypt;
- } else {
- if (unlikely(ciphertext->size < tag_size))
- return
- gnutls_assert_val
- (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
-
- length_to_decrypt = ciphertext->size;
- length = ciphertext->size - tag_size;
- tag_ptr = compressed->data + length;
+ /* Values in AEAD are pretty fixed in TLS 1.2 for 128-bit block
+ */
+ if (unlikely
+ (params->read.IV.data == NULL
+ || params->read.IV.size != 4))
+ return
+ gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ if (unlikely(ciphertext->size < tag_size + exp_iv_size))
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+ memcpy(nonce, params->read.IV.data,
+ imp_iv_size);
+ memcpy(&nonce[imp_iv_size],
+ ciphertext->data, exp_iv_size);
+
+ _gnutls_auth_cipher_setiv(&params->read.
+ cipher_state, nonce,
+ exp_iv_size +
+ imp_iv_size);
+
+ ciphertext->data += exp_iv_size;
+ ciphertext->size -= exp_iv_size;
+
+ length = length_to_decrypt =
+ ciphertext->size - tag_size;
+ tag_ptr = ciphertext->data + length_to_decrypt;
+
+ /* Pass the type, version, length and compressed through
+ * MAC.
+ */
+ preamble_size =
+ make_preamble(UINT64DATA(*sequence), type,
+ length, ver, preamble);
+
+ ret =
+ _gnutls_auth_cipher_add_auth(&params->read.
+ cipher_state, preamble,
+ preamble_size);
+ if (unlikely(ret < 0))
+ return gnutls_assert_val(ret);
+
+ if (unlikely
+ ((unsigned) length_to_decrypt > compressed->size)) {
+ _gnutls_audit_log(session,
+ "Received %u bytes, while expecting less than %u\n",
+ (unsigned int) length_to_decrypt,
+ (unsigned int) compressed->size);
+ return
+ gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
}
+ ret =
+ _gnutls_auth_cipher_decrypt2(&params->read.
+ cipher_state,
+ ciphertext->data,
+ length_to_decrypt,
+ compressed->data,
+ compressed->size);
+
+ if (unlikely(ret < 0))
+ return gnutls_assert_val(ret);
+
+ break;
+ case CIPHER_STREAM:
+ if (unlikely(ciphertext->size < tag_size))
+ return
+ gnutls_assert_val
+ (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+ length_to_decrypt = ciphertext->size;
+ length = ciphertext->size - tag_size;
+ tag_ptr = compressed->data + length;
+
/* Pass the type, version, length and compressed through
* MAC.
*/
diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c
index e9b9678f42..25299982cb 100644
--- a/lib/gnutls_constate.c
+++ b/lib/gnutls_constate.c
@@ -199,7 +199,7 @@ _gnutls_init_record_state(record_parameters_st * params,
gnutls_datum_t *iv = NULL;
if (!_gnutls_version_has_explicit_iv(ver)) {
- if (_gnutls_cipher_is_block(params->cipher) !=
+ if (_gnutls_cipher_type(params->cipher) !=
CIPHER_STREAM)
iv = &state->IV;
}
@@ -344,7 +344,7 @@ int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch)
(GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
if (!_gnutls_version_has_explicit_iv(ver)) {
- if (_gnutls_cipher_is_block(params->cipher) != CIPHER_STREAM) {
+ if (_gnutls_cipher_type(params->cipher) != CIPHER_STREAM) {
IV_size = _gnutls_cipher_get_iv_size(params->cipher);
} else
IV_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c
index c07f08f6eb..7b359eb768 100644
--- a/lib/gnutls_dtls.c
+++ b/lib/gnutls_dtls.c
@@ -590,7 +590,7 @@ static int record_overhead(const cipher_entry_st * cipher,
int total = 0;
int t, ret;
- if (_gnutls_cipher_is_block(cipher) == CIPHER_BLOCK) {
+ if (_gnutls_cipher_type(cipher) == CIPHER_BLOCK) {
t = _gnutls_cipher_get_explicit_iv_size(cipher);
total += t;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 7faa5ace05..3b9259cf4b 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -290,7 +290,7 @@ typedef enum extensions_t {
GNUTLS_EXTENSION_SAFE_RENEGOTIATION = 65281 /* aka: 0xff01 */
} extensions_t;
-typedef enum { CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t;
+typedef enum { CIPHER_STREAM, CIPHER_BLOCK, CIPHER_AEAD } cipher_type_t;
#define RESUME_TRUE 1
#define RESUME_FALSE 0
@@ -463,11 +463,11 @@ typedef struct cipher_entry_st {
gnutls_cipher_algorithm_t id;
uint16_t blocksize;
uint16_t keysize;
- bool block;
+ cipher_type_t type;
uint16_t implicit_iv; /* the size of implicit IV - the IV generated but not sent */
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 */
- bool aead; /* Whether it is authenc cipher */
+ uint16_t tagsize;
} cipher_entry_st;
/* This structure is used both for MACs and digests
@@ -1080,7 +1080,7 @@ inline static size_t max_user_send_size(gnutls_session_t session,
max = session->security_parameters.max_record_send_size;
/* DTLS data MTU accounts for those */
- if (_gnutls_cipher_is_block(record_params->cipher))
+ if (_gnutls_cipher_type(record_params->cipher) != CIPHER_STREAM)
max -=
_gnutls_cipher_get_block_size(record_params->
cipher);
diff --git a/lib/gnutls_range.c b/lib/gnutls_range.c
index 0e29a8994c..e130431edb 100644
--- a/lib/gnutls_range.c
+++ b/lib/gnutls_range.c
@@ -67,7 +67,8 @@ _gnutls_range_max_lh_pad(gnutls_session_t session, ssize_t data_length,
tag_size =
_gnutls_auth_cipher_tag_len(&record_params->write.
cipher_state);
- switch (_gnutls_cipher_is_block(record_params->cipher)) {
+ switch (_gnutls_cipher_type(record_params->cipher)) {
+ case CIPHER_AEAD:
case CIPHER_STREAM:
return this_pad;
@@ -115,10 +116,11 @@ int gnutls_record_can_use_length_hiding(gnutls_session_t session)
return 0;
}
- switch (_gnutls_cipher_is_block(record_params->cipher)) {
+ switch (_gnutls_cipher_type(record_params->cipher)) {
case CIPHER_BLOCK:
return 1;
case CIPHER_STREAM:
+ case CIPHER_AEAD:
default:
return 0;
}