From: Nikos Mavrogiannopoulos Date: Sun, 26 May 2013 17:46:19 +0000 (+0200) Subject: Eliminated memory copy at encryption. X-Git-Tag: gnutls_3_2_2~122 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6fb9273afa06c6ec9822e4e71fad18db5b8fbf54;p=thirdparty%2Fgnutls.git Eliminated memory copy at encryption. --- diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c index a557ca1b2c..022702efb3 100644 --- a/lib/algorithms/ciphers.c +++ b/lib/algorithms/ciphers.c @@ -40,8 +40,8 @@ static const cipher_entry_st algorithms[] = { {"AES-128-GCM", GNUTLS_CIPHER_AES_128_GCM, 16, 16, CIPHER_STREAM, AEAD_IMPLICIT_DATA_SIZE, 1}, {"AES-256-GCM", GNUTLS_CIPHER_AES_256_GCM, 16, 32, CIPHER_STREAM, AEAD_IMPLICIT_DATA_SIZE, 1}, {"ARCFOUR-128", GNUTLS_CIPHER_ARCFOUR_128, 1, 16, CIPHER_STREAM, 0, 0}, - {"ESTREAM-SALSA20-256", GNUTLS_CIPHER_ESTREAM_SALSA20_256, 1, 32, CIPHER_STREAM, 8, 0}, - {"SALSA20-256", GNUTLS_CIPHER_SALSA20_256, 1, 32, CIPHER_STREAM, 8, 0}, + {"ESTREAM-SALSA20-256", GNUTLS_CIPHER_ESTREAM_SALSA20_256, 64, 32, CIPHER_STREAM, 8, 0}, + {"SALSA20-256", GNUTLS_CIPHER_SALSA20_256, 64, 32, CIPHER_STREAM, 8, 0}, {"CAMELLIA-256-CBC", GNUTLS_CIPHER_CAMELLIA_256_CBC, 16, 32, CIPHER_BLOCK, 16, 0}, {"CAMELLIA-192-CBC", GNUTLS_CIPHER_CAMELLIA_192_CBC, 16, 24, CIPHER_BLOCK, diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c index 2d86c49c30..dd843ddcfb 100644 --- a/lib/gnutls_cipher.c +++ b/lib/gnutls_cipher.c @@ -310,9 +310,8 @@ compressed_to_ciphertext (gnutls_session_t session, content_type_t type, record_parameters_st * params) { - uint8_t * tag_ptr = NULL; uint8_t pad = target_size - compressed->size; - int length, length_to_encrypt, ret; + int length, ret; uint8_t preamble[MAX_PREAMBLE_SIZE]; int preamble_size; int tag_size = _gnutls_auth_cipher_tag_len (¶ms->write.cipher_state); @@ -347,28 +346,24 @@ compressed_to_ciphertext (gnutls_session_t session, if (ret < 0) return gnutls_assert_val(ret); - length_to_encrypt = length = + length = calc_enc_length_block (session, ver, compressed->size, tag_size, &pad, auth_cipher, blocksize); } else { - length_to_encrypt = length = + length = calc_enc_length_stream (session, compressed->size, tag_size, auth_cipher); } if (length < 0) - { - return gnutls_assert_val(length); - } + return gnutls_assert_val(length); /* copy the encrypted data to cipher_data. */ if (cipher_size < length) - { - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - } + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); data_ptr = cipher_data; @@ -383,7 +378,6 @@ compressed_to_ciphertext (gnutls_session_t session, data_ptr += blocksize; cipher_data += blocksize; - length_to_encrypt -= blocksize; } else if (auth_cipher) { @@ -405,9 +399,6 @@ compressed_to_ciphertext (gnutls_session_t session, data_ptr += AEAD_EXPLICIT_DATA_SIZE; cipher_data += AEAD_EXPLICIT_DATA_SIZE; - /* In AEAD ciphers we don't encrypt the tag - */ - length_to_encrypt -= AEAD_EXPLICIT_DATA_SIZE + tag_size; } else if (iv_size > 0) _gnutls_auth_cipher_setiv(¶ms->write.cipher_state, UINT64DATA(params->write.sequence_number), 8); @@ -422,19 +413,6 @@ compressed_to_ciphertext (gnutls_session_t session, _gnutls_auth_cipher_setiv(¶ms->write.cipher_state, UINT64DATA(params->write.sequence_number), 8); } - memcpy (data_ptr, compressed->data, compressed->size); - data_ptr += compressed->size; - - if (tag_size > 0) - { - tag_ptr = data_ptr; - data_ptr += tag_size; - } - if (block_algo == CIPHER_BLOCK && pad > 0) - { - memset (data_ptr, pad - 1, pad); - } - _gnutls_auth_cipher_set_mac_nonce(¶ms->write.cipher_state, UINT64DATA(params->write.sequence_number), 8); /* add the authenticate data */ @@ -442,13 +420,12 @@ compressed_to_ciphertext (gnutls_session_t session, if (ret < 0) return gnutls_assert_val(ret); - /* Actual encryption (inplace). + /* Actual encryption. */ ret = _gnutls_auth_cipher_encrypt2_tag (¶ms->write.cipher_state, - cipher_data, length_to_encrypt, - cipher_data, cipher_size, - tag_ptr, tag_size, compressed->size); + compressed->data, compressed->size, cipher_data, cipher_size, + pad); if (ret < 0) return gnutls_assert_val(ret); @@ -463,7 +440,6 @@ compressed_to_ciphertext_new (gnutls_session_t session, content_type_t type, record_parameters_st * params) { - uint8_t * tag_ptr = NULL; uint16_t pad = target_size - compressed->size; int length, length_to_encrypt, ret; uint8_t preamble[MAX_PREAMBLE_SIZE]; @@ -562,14 +538,12 @@ compressed_to_ciphertext_new (gnutls_session_t session, if (pad > 0) { - DECR_LEN(cipher_size, pad); memset(data_ptr, 0, pad); data_ptr += pad; length_to_encrypt += pad; length += pad; } - DECR_LEN(cipher_size, compressed->size); memcpy (data_ptr, compressed->data, compressed->size); data_ptr += compressed->size; length_to_encrypt += compressed->size; @@ -577,14 +551,10 @@ compressed_to_ciphertext_new (gnutls_session_t session, if (tag_size > 0) { - DECR_LEN(cipher_size, tag_size); - tag_ptr = data_ptr; data_ptr += tag_size; /* In AEAD ciphers we don't encrypt the tag */ - if (!auth_cipher) - length_to_encrypt += tag_size; length += tag_size; } @@ -604,8 +574,7 @@ compressed_to_ciphertext_new (gnutls_session_t session, ret = _gnutls_auth_cipher_encrypt2_tag (¶ms->write.cipher_state, cipher_data, length_to_encrypt, - cipher_data, cipher_size, - tag_ptr, tag_size, compressed->size+2+pad); + cipher_data, cipher_size, 0); if (ret < 0) return gnutls_assert_val(ret); diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c index 4ecded6bfc..79d71fe4ad 100644 --- a/lib/gnutls_cipher_int.c +++ b/lib/gnutls_cipher_int.c @@ -146,12 +146,13 @@ int ret; if (e->id != GNUTLS_CIPHER_NULL) { + handle->non_null = 1; ret = _gnutls_cipher_init(&handle->cipher, e, cipher_key, iv, enc); if (ret < 0) return gnutls_assert_val(ret); } else - handle->is_null = 1; + handle->non_null = 0; if (me->id != GNUTLS_MAC_AEAD) { @@ -183,7 +184,7 @@ int ret; return 0; cleanup: - if (handle->is_null == 0) + if (handle->non_null != 0) _gnutls_cipher_deinit(&handle->cipher); return ret; @@ -205,45 +206,70 @@ int _gnutls_auth_cipher_add_auth (auth_cipher_hd_st * handle, const void *text, return 0; } +/* The caller must make sure that textlen+pad_size+tag_size is divided by the block size of the cipher */ int _gnutls_auth_cipher_encrypt2_tag (auth_cipher_hd_st * handle, const uint8_t *text, - int textlen, void *ciphertext, int ciphertextlen, - void* tag_ptr, int tag_size, - int auth_size) + int textlen, void *_ciphertext, int ciphertextlen, + int pad_size) { int ret; +uint8_t * ciphertext = _ciphertext; +unsigned blocksize = _gnutls_cipher_get_block_size(handle->cipher.e); +unsigned l; if (handle->is_mac) { if (handle->ssl_hmac) - ret = _gnutls_hash(&handle->mac.dig, text, auth_size); + ret = _gnutls_hash(&handle->mac.dig, text, textlen); else - ret = _gnutls_mac(&handle->mac.mac, text, auth_size); - if (ret < 0) - { - gnutls_assert(); - return ret; - } - ret = _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size); + ret = _gnutls_mac(&handle->mac.mac, text, textlen); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + + if (unlikely(textlen+pad_size+handle->tag_size) > ciphertextlen) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ret = _gnutls_auth_cipher_tag(handle, ciphertext+textlen, handle->tag_size); if (ret < 0) return gnutls_assert_val(ret); - if (handle->is_null==0) + if (handle->non_null != 0) { - ret = _gnutls_cipher_encrypt2(&handle->cipher, text, textlen, ciphertext, ciphertextlen); + l = (textlen/blocksize)*blocksize; + ret = _gnutls_cipher_encrypt2(&handle->cipher, text, l, ciphertext, ciphertextlen); + if (ret < 0) + return gnutls_assert_val(ret); + + textlen -= l; + text += l; + ciphertext += l; + ciphertextlen -= l; + + if (ciphertext != text && textlen > 0) + memcpy(ciphertext, text, textlen); + + /* TLS 1.0 style padding */ + if (pad_size > 0) + memset (ciphertext+textlen+handle->tag_size, pad_size - 1, pad_size); + + ret = _gnutls_cipher_encrypt2(&handle->cipher, ciphertext, textlen+handle->tag_size+pad_size, ciphertext, ciphertextlen); if (ret < 0) return gnutls_assert_val(ret); } + else if (text != ciphertext) + memcpy(ciphertext, text, textlen); } else if (_gnutls_cipher_is_aead(&handle->cipher)) { ret = _gnutls_cipher_encrypt2(&handle->cipher, text, textlen, ciphertext, ciphertextlen); - if (ret < 0) + if (unlikely(ret < 0)) return gnutls_assert_val(ret); - ret = _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size); - if (ret < 0) + ret = _gnutls_auth_cipher_tag(handle, ciphertext+textlen, handle->tag_size); + if (unlikely(ret < 0)) return gnutls_assert_val(ret); } + else if (handle->non_null == 0 && text != ciphertext) + memcpy(ciphertext, text, textlen); return 0; } @@ -254,7 +280,7 @@ int _gnutls_auth_cipher_decrypt2 (auth_cipher_hd_st * handle, { int ret; - if (handle->is_null==0) + if (handle->non_null != 0) { ret = _gnutls_cipher_decrypt2(&handle->cipher, ciphertext, ciphertextlen, text, textlen); @@ -310,6 +336,6 @@ void _gnutls_auth_cipher_deinit (auth_cipher_hd_st * handle) else _gnutls_mac_deinit(&handle->mac.mac, NULL); } - if (handle->is_null==0) + if (handle->non_null!=0) _gnutls_cipher_deinit(&handle->cipher); } diff --git a/lib/gnutls_cipher_int.h b/lib/gnutls_cipher_int.h index 35b8e6106f..6e1e8b7f4a 100644 --- a/lib/gnutls_cipher_int.h +++ b/lib/gnutls_cipher_int.h @@ -66,7 +66,7 @@ inline static int _gnutls_cipher_encrypt2 (const cipher_hd_st * handle, const void *text, size_t textlen, void *ciphertext, size_t ciphertextlen) { - if (handle != NULL && handle->handle != NULL) + if (unlikely(handle != NULL && handle->handle != NULL)) { return handle->encrypt (handle->handle, text, textlen, ciphertext, ciphertextlen); @@ -79,7 +79,7 @@ inline static int _gnutls_cipher_decrypt2 (const cipher_hd_st * handle, const void *ciphertext, size_t ciphertextlen, void *text, size_t textlen) { - if (handle != NULL && handle->handle != NULL) + if (unlikely(handle != NULL && handle->handle != NULL)) { return handle->decrypt (handle->handle, ciphertext, ciphertextlen, text, textlen); @@ -91,7 +91,7 @@ _gnutls_cipher_decrypt2 (const cipher_hd_st * handle, const void *ciphertext, inline static void _gnutls_cipher_deinit (cipher_hd_st * handle) { - if (handle != NULL && handle->handle != NULL) + if (unlikely(handle != NULL && handle->handle != NULL)) { handle->deinit (handle->handle); handle->handle = NULL; @@ -105,7 +105,7 @@ int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher); /* returns the tag in AUTHENC ciphers */ inline static void _gnutls_cipher_tag( const cipher_hd_st * handle, void* tag, size_t tag_size) { - if (handle != NULL && handle->handle != NULL) + if (unlikely(handle != NULL && handle->handle != NULL)) { handle->tag (handle->handle, tag, tag_size); } @@ -116,7 +116,7 @@ inline static void _gnutls_cipher_tag( const cipher_hd_st * handle, void* tag, s inline static int _gnutls_cipher_auth (const cipher_hd_st * handle, const void *text, size_t textlen) { - if (handle != NULL && handle->handle != NULL) + if (unlikely(handle != NULL && handle->handle != NULL)) { return handle->auth (handle->handle, text, textlen); } @@ -138,7 +138,7 @@ typedef struct } mac; unsigned int is_mac:1; unsigned int ssl_hmac:1; - unsigned int is_null:1; + unsigned int non_null:1; size_t tag_size; } auth_cipher_hd_st; @@ -153,9 +153,8 @@ int _gnutls_auth_cipher_add_auth (auth_cipher_hd_st * handle, const void *text, int textlen); int _gnutls_auth_cipher_encrypt2_tag (auth_cipher_hd_st * handle, const uint8_t *text, - int textlen, void *ciphertext, int ciphertextlen, - void* tag_ptr, int tag_size, - int auth_size); + int textlen, void *ciphertext, int ciphertextlen, + int pad_size); int _gnutls_auth_cipher_decrypt2 (auth_cipher_hd_st * handle, const void *ciphertext, int ciphertextlen, void *text, int textlen);