]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Align on 16-byte boundaries the buffers provided to cryptodev.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 15 Dec 2013 20:18:05 +0000 (21:18 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 15 Dec 2013 20:38:12 +0000 (21:38 +0100)
When gnutls is compiled with support for cryptodev, the buffers
provided to crypto backend are ensured to be 16-byte aligned
(except the ones provided by the user). That increases performance
in several crypto accelerators.

lib/algorithms.h
lib/algorithms/ciphers.c
lib/gnutls_buffers.c
lib/gnutls_cipher.c
lib/gnutls_constate.c
lib/gnutls_dtls.c
lib/gnutls_int.h
lib/gnutls_mbuffers.c
lib/gnutls_mbuffers.h
lib/gnutls_record.c
lib/gnutls_record.h

index d57e48fd3f1e567ac4584b94e7ad81b552cdd431..8fff5104dd71dcbe354f65fdb5582958e022efab 100644 (file)
@@ -191,7 +191,23 @@ _gnutls_cipher_get_implicit_iv_size(const cipher_entry_st * e)
 {
        if (unlikely(e == NULL))
                return 0;
-       return e->iv;
+       return e->implicit_iv;
+}
+
+inline static int
+_gnutls_cipher_get_iv_size(const cipher_entry_st * e)
+{
+       if (unlikely(e == NULL))
+               return 0;
+       return e->cipher_iv;
+}
+
+inline static int
+_gnutls_cipher_get_explicit_iv_size(const cipher_entry_st * e)
+{
+       if (unlikely(e == NULL))
+               return 0;
+       return e->explicit_iv;
 }
 
 inline static int _gnutls_cipher_get_key_size(const cipher_entry_st * e)
index a99273fe791c69117d8beb53f60390d524d2d69d..ebec727a7b0cfa89ca444a3ce1104f940216f066 100644 (file)
  */
 static const cipher_entry_st algorithms[] = {
        {"AES-256-CBC", GNUTLS_CIPHER_AES_256_CBC, 16, 32, CIPHER_BLOCK,
-        16, 16, 0},
+        0, 16, 16, 0},
        {"AES-192-CBC", GNUTLS_CIPHER_AES_192_CBC, 16, 24, CIPHER_BLOCK,
-        16, 16, 0},
+        0, 16, 16, 0},
        {"AES-128-CBC", GNUTLS_CIPHER_AES_128_CBC, 16, 16, CIPHER_BLOCK,
-        16, 16, 0},
+        0, 16, 16, 0},
        {"AES-128-GCM", GNUTLS_CIPHER_AES_128_GCM, 16, 16, CIPHER_STREAM,
-        AEAD_IMPLICIT_DATA_SIZE, 12, 1},
+        4, 8, 12, 1},
        {"AES-256-GCM", GNUTLS_CIPHER_AES_256_GCM, 16, 32, CIPHER_STREAM,
-        AEAD_IMPLICIT_DATA_SIZE, 12, 1},
-       {"ARCFOUR-128", GNUTLS_CIPHER_ARCFOUR_128, 1, 16, CIPHER_STREAM, 0,
-        0, 0},
+        4, 8, 12, 1},
+       {"ARCFOUR-128", GNUTLS_CIPHER_ARCFOUR_128, 1, 16, CIPHER_STREAM, 
+        0, 0, 0, 0},
        {"ESTREAM-SALSA20-256", GNUTLS_CIPHER_ESTREAM_SALSA20_256, 64, 32,
-        CIPHER_STREAM, 8, 8, 0},
+        CIPHER_STREAM, 0, 0, 8, 0},
        {"SALSA20-256", GNUTLS_CIPHER_SALSA20_256, 64, 32, CIPHER_STREAM,
-        8, 8, 0},
+        0, 0, 8, 0},
        {"CAMELLIA-256-CBC", GNUTLS_CIPHER_CAMELLIA_256_CBC, 16, 32,
-        CIPHER_BLOCK,
-        16, 16, 0},
+        CIPHER_BLOCK, 0, 16, 16, 0},
        {"CAMELLIA-192-CBC", GNUTLS_CIPHER_CAMELLIA_192_CBC, 16, 24,
-        CIPHER_BLOCK,
-        16, 16, 0},
+        CIPHER_BLOCK, 0, 16, 16, 0},
        {"CAMELLIA-128-CBC", GNUTLS_CIPHER_CAMELLIA_128_CBC, 16, 16,
-        CIPHER_BLOCK,
-        16, 16, 0},
+        CIPHER_BLOCK, 0, 16, 16, 0},
        {"CAMELLIA-128-GCM", GNUTLS_CIPHER_CAMELLIA_128_GCM, 16, 16,
-        CIPHER_STREAM, AEAD_IMPLICIT_DATA_SIZE, 12, 1},
+        CIPHER_STREAM, 4, 8, 12, 1},
        {"CAMELLIA-256-GCM", GNUTLS_CIPHER_CAMELLIA_256_GCM, 16, 32,
-        CIPHER_STREAM, AEAD_IMPLICIT_DATA_SIZE, 12, 1},
-       {"3DES-CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 8, 8, 0},
-       {"DES-CBC", GNUTLS_CIPHER_DES_CBC, 8, 8, CIPHER_BLOCK, 8, 8, 0},
-       {"ARCFOUR-40", GNUTLS_CIPHER_ARCFOUR_40, 1, 5, CIPHER_STREAM, 0, 0,
-        0},
-       {"RC2-40", GNUTLS_CIPHER_RC2_40_CBC, 8, 5, CIPHER_BLOCK, 8, 8, 0},
+        CIPHER_STREAM, 4, 8, 12, 1},
+       {"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},
+       {"RC2-40", GNUTLS_CIPHER_RC2_40_CBC, 8, 5, CIPHER_BLOCK, 0, 8, 8, 0},
 
 #ifdef ENABLE_OPENPGP
        {"IDEA-PGP-CFB", GNUTLS_CIPHER_IDEA_PGP_CFB, 8, 16, CIPHER_BLOCK,
-        8, 8, 0},
+        0, 8, 8, 0},
        {"3DES-PGP-CFB", GNUTLS_CIPHER_3DES_PGP_CFB, 8, 24, CIPHER_BLOCK,
-        8, 8, 0},
+        0, 8, 8, 0},
        {"CAST5-PGP-CFB", GNUTLS_CIPHER_CAST5_PGP_CFB, 8, 16, CIPHER_BLOCK,
-        8, 8, 0},
+        0, 8, 8, 0},
        {"BLOWFISH-PGP-CFB", GNUTLS_CIPHER_BLOWFISH_PGP_CFB, 8,
-        16 /*actually unlimited */ , CIPHER_BLOCK, 8, 8, 0},
+        16 /*actually unlimited */ , CIPHER_BLOCK, 0, 8, 8, 0},
        {"SAFER-SK128-PGP-CFB", GNUTLS_CIPHER_SAFER_SK128_PGP_CFB, 8, 16,
-        CIPHER_BLOCK, 8, 8, 0},
+        CIPHER_BLOCK, 0, 8, 8, 0},
        {"AES-128-PGP-CFB", GNUTLS_CIPHER_AES128_PGP_CFB, 16, 16,
-        CIPHER_BLOCK, 16,
-        16, 0},
+        CIPHER_BLOCK, 0, 16, 16, 0},
        {"AES-192-PGP-CFB", GNUTLS_CIPHER_AES192_PGP_CFB, 16, 24,
-        CIPHER_BLOCK, 16,
-        16, 0},
+        CIPHER_BLOCK, 0, 16, 16, 0},
        {"AES-256-PGP-CFB", GNUTLS_CIPHER_AES256_PGP_CFB, 16, 32,
-        CIPHER_BLOCK, 16,
-        16, 0},
+        CIPHER_BLOCK, 0, 16, 16, 0},
        {"TWOFISH-PGP-CFB", GNUTLS_CIPHER_TWOFISH_PGP_CFB, 16, 16,
-        CIPHER_BLOCK, 16,
-        16, 0},
+        CIPHER_BLOCK, 0, 16, 16, 0},
 #endif
 
 #ifndef ENABLE_FIPS140
index b0aa3ae5dad281ea20acfef3d6683b37528a89ea..ec38b1b4bc69cfc27bcf296baa6389e41688ef31 100644 (file)
@@ -218,7 +218,7 @@ _gnutls_dgram_read(gnutls_session_t session, mbuffer_st ** bufel,
                gettime(&t1);
        }
 
-       *bufel = _mbuffer_alloc(max_size);
+       *bufel = _mbuffer_alloc_align16(max_size, get_total_headers(session));
        if (*bufel == NULL)
                return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
@@ -286,7 +286,7 @@ _gnutls_stream_read(gnutls_session_t session, mbuffer_st ** bufel,
 
        session->internals.direction = 0;
 
-       *bufel = _mbuffer_alloc(MAX(max_size, size));
+       *bufel = _mbuffer_alloc_align16(MAX(max_size, size), get_total_headers(session));
        if (!*bufel) {
                gnutls_assert();
                return GNUTLS_E_MEMORY_ERROR;
index 760e6607f367d288fcc2827686bd56408705dcd1..571cd51a291492ea85def4817780789cfe629eef 100644 (file)
@@ -269,13 +269,14 @@ calc_enc_length_block(gnutls_session_t session,
 
 inline static int
 calc_enc_length_stream(gnutls_session_t session, int data_size,
-                      int hash_size, unsigned auth_cipher)
+                      int hash_size, unsigned auth_cipher,
+                      unsigned exp_iv_size)
 {
        unsigned int length;
 
        length = data_size + hash_size;
        if (auth_cipher)
-               length += AEAD_EXPLICIT_DATA_SIZE;
+               length += exp_iv_size;
 
        return length;
 }
@@ -336,12 +337,14 @@ compressed_to_ciphertext(gnutls_session_t session,
        int auth_cipher =
            _gnutls_auth_cipher_is_aead(&params->write.cipher_state);
        uint8_t nonce[MAX_CIPHER_BLOCK_SIZE];
-       unsigned iv_size;
+       unsigned iv_size, imp_iv_size, exp_iv_size;
 
        if (unlikely(ver == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       iv_size = _gnutls_cipher_get_iv_size(params->cipher);
+       imp_iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       exp_iv_size = _gnutls_cipher_get_explicit_iv_size(params->cipher);
 
        _gnutls_hard_log("ENC[%p]: cipher: %s, MAC: %s, Epoch: %u\n",
                         session, _gnutls_cipher_get_name(params->cipher),
@@ -372,7 +375,7 @@ compressed_to_ciphertext(gnutls_session_t session,
                pad = 0;
                length =
                    calc_enc_length_stream(session, compressed->size,
-                                          tag_size, auth_cipher);
+                                          tag_size, auth_cipher, exp_iv_size);
        }
 
        if (length < 0)
@@ -381,11 +384,12 @@ compressed_to_ciphertext(gnutls_session_t session,
        /* 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_INTERNAL_ERROR);
 
        data_ptr = cipher_data;
 
        if (explicit_iv) {      /* TLS 1.1 or later */
+
                if (block_algo == CIPHER_BLOCK) {
                        /* copy the random IV.
                         */
@@ -401,7 +405,7 @@ compressed_to_ciphertext(gnutls_session_t session,
                         */
                        if (params->write.IV.data == NULL
                            || params->write.IV.size !=
-                           AEAD_IMPLICIT_DATA_SIZE)
+                           imp_iv_size)
                                return
                                    gnutls_assert_val
                                    (GNUTLS_E_INTERNAL_ERROR);
@@ -411,21 +415,21 @@ compressed_to_ciphertext(gnutls_session_t session,
                         */
                        memcpy(nonce, params->write.IV.data,
                               params->write.IV.size);
-                       memcpy(&nonce[AEAD_IMPLICIT_DATA_SIZE],
+                       memcpy(&nonce[imp_iv_size],
                               UINT64DATA(params->write.sequence_number),
                               8);
 
                        _gnutls_auth_cipher_setiv(&params->write.
                                                  cipher_state, nonce,
-                                                 AEAD_IMPLICIT_DATA_SIZE +
-                                                 AEAD_EXPLICIT_DATA_SIZE);
+                                                 imp_iv_size +
+                                                 exp_iv_size);
 
                        /* copy the explicit part */
-                       memcpy(data_ptr, &nonce[AEAD_IMPLICIT_DATA_SIZE],
-                              AEAD_EXPLICIT_DATA_SIZE);
+                       memcpy(data_ptr, &nonce[imp_iv_size],
+                              exp_iv_size);
 
-                       data_ptr += AEAD_EXPLICIT_DATA_SIZE;
-                       cipher_data += AEAD_EXPLICIT_DATA_SIZE;
+                       data_ptr += exp_iv_size;
+                       cipher_data += exp_iv_size;
                } else if (iv_size > 0)
                        _gnutls_auth_cipher_setiv(&params->write.
                                                  cipher_state,
@@ -491,12 +495,14 @@ compressed_to_ciphertext_new(gnutls_session_t session,
        int auth_cipher =
            _gnutls_auth_cipher_is_aead(&params->write.cipher_state);
        uint8_t nonce[MAX_CIPHER_BLOCK_SIZE];
-       unsigned iv_size, final_cipher_size;
+       unsigned imp_iv_size, final_cipher_size, iv_size, exp_iv_size;
 
        if (unlikely(ver == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       imp_iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       exp_iv_size = _gnutls_cipher_get_explicit_iv_size(params->cipher);
+       iv_size = _gnutls_cipher_get_iv_size(params->cipher);
 
        _gnutls_hard_log("ENC[%p]: cipher: %s, MAC: %s, Epoch: %u\n",
                         session, _gnutls_cipher_get_name(params->cipher),
@@ -533,7 +539,7 @@ compressed_to_ciphertext_new(gnutls_session_t session,
                         */
                        if (params->write.IV.data == NULL
                            || params->write.IV.size !=
-                           AEAD_IMPLICIT_DATA_SIZE)
+                           imp_iv_size)
                                return
                                    gnutls_assert_val
                                    (GNUTLS_E_INTERNAL_ERROR);
@@ -543,23 +549,23 @@ compressed_to_ciphertext_new(gnutls_session_t session,
                         */
                        memcpy(nonce, params->write.IV.data,
                               params->write.IV.size);
-                       memcpy(&nonce[AEAD_IMPLICIT_DATA_SIZE],
+                       memcpy(&nonce[imp_iv_size],
                               UINT64DATA(params->write.sequence_number),
                               8);
 
                        _gnutls_auth_cipher_setiv(&params->write.
                                                  cipher_state, nonce,
-                                                 AEAD_IMPLICIT_DATA_SIZE +
-                                                 AEAD_EXPLICIT_DATA_SIZE);
+                                                 imp_iv_size +
+                                                 exp_iv_size);
 
                        /* copy the explicit part */
-                       DECR_LEN(cipher_size, AEAD_EXPLICIT_DATA_SIZE);
-                       memcpy(data_ptr, &nonce[AEAD_IMPLICIT_DATA_SIZE],
-                              AEAD_EXPLICIT_DATA_SIZE);
+                       DECR_LEN(cipher_size, exp_iv_size);
+                       memcpy(data_ptr, &nonce[imp_iv_size],
+                              exp_iv_size);
 
-                       data_ptr += AEAD_EXPLICIT_DATA_SIZE;
-                       cipher_data += AEAD_EXPLICIT_DATA_SIZE;
-                       length += AEAD_EXPLICIT_DATA_SIZE;
+                       data_ptr += exp_iv_size;
+                       cipher_data += exp_iv_size;
+                       length += exp_iv_size;
                } else if (iv_size > 0)
                        _gnutls_auth_cipher_setiv(&params->write.
                                                  cipher_state,
@@ -719,12 +725,14 @@ ciphertext_to_compressed(gnutls_session_t session,
        unsigned int tag_size =
            _gnutls_auth_cipher_tag_len(&params->read.cipher_state);
        unsigned int explicit_iv = _gnutls_version_has_explicit_iv(ver);
-       unsigned iv_size;
+       unsigned imp_iv_size, iv_size, exp_iv_size;
 
        if (unlikely(ver == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       imp_iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       exp_iv_size = _gnutls_cipher_get_explicit_iv_size(params->cipher);
+       iv_size = _gnutls_cipher_get_iv_size(params->cipher);
        blocksize = _gnutls_cipher_get_block_size(params->cipher);
 
        /* actual decryption (inplace)
@@ -749,23 +757,23 @@ ciphertext_to_compressed(gnutls_session_t session,
 
                        if (unlikely
                            (ciphertext->size <
-                            tag_size + AEAD_EXPLICIT_DATA_SIZE))
+                            tag_size + exp_iv_size))
                                return
                                    gnutls_assert_val
                                    (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
                        memcpy(nonce, params->read.IV.data,
-                              AEAD_IMPLICIT_DATA_SIZE);
-                       memcpy(&nonce[AEAD_IMPLICIT_DATA_SIZE],
-                              ciphertext->data, AEAD_EXPLICIT_DATA_SIZE);
+                              imp_iv_size);
+                       memcpy(&nonce[imp_iv_size],
+                              ciphertext->data, exp_iv_size);
 
                        _gnutls_auth_cipher_setiv(&params->read.
                                                  cipher_state, nonce,
-                                                 AEAD_EXPLICIT_DATA_SIZE +
-                                                 AEAD_IMPLICIT_DATA_SIZE);
+                                                 exp_iv_size +
+                                                 imp_iv_size);
 
-                       ciphertext->data += AEAD_EXPLICIT_DATA_SIZE;
-                       ciphertext->size -= AEAD_EXPLICIT_DATA_SIZE;
+                       ciphertext->data += exp_iv_size;
+                       ciphertext->size -= exp_iv_size;
 
                        length = length_to_decrypt =
                            ciphertext->size - tag_size;
@@ -974,12 +982,14 @@ ciphertext_to_compressed_new(gnutls_session_t restrict session,
        unsigned int tag_size =
            _gnutls_auth_cipher_tag_len(&params->read.cipher_state);
        unsigned int explicit_iv = _gnutls_version_has_explicit_iv(ver);
-       unsigned iv_size;
+       unsigned imp_iv_size, iv_size, exp_iv_size;
 
        if (unlikely(ver == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       imp_iv_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       exp_iv_size = _gnutls_cipher_get_explicit_iv_size(params->cipher);
+       iv_size = _gnutls_cipher_get_iv_size(params->cipher);
        blocksize = _gnutls_cipher_get_block_size(params->cipher);
 
        /* actual decryption (inplace)
@@ -1002,26 +1012,26 @@ ciphertext_to_compressed_new(gnutls_session_t restrict session,
                                    (GNUTLS_E_INTERNAL_ERROR);
 
                        if (ciphertext->size <
-                           tag_size + AEAD_EXPLICIT_DATA_SIZE + 2)
+                           tag_size + exp_iv_size + 2)
                                return
                                    gnutls_assert_val
                                    (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
                        memcpy(nonce, params->read.IV.data,
-                              AEAD_IMPLICIT_DATA_SIZE);
-                       memcpy(&nonce[AEAD_IMPLICIT_DATA_SIZE],
-                              ciphertext->data, AEAD_EXPLICIT_DATA_SIZE);
+                              imp_iv_size);
+                       memcpy(&nonce[imp_iv_size],
+                              ciphertext->data, exp_iv_size);
 
                        _gnutls_auth_cipher_setiv(&params->read.
                                                  cipher_state, nonce,
-                                                 AEAD_EXPLICIT_DATA_SIZE +
-                                                 AEAD_IMPLICIT_DATA_SIZE);
+                                                 exp_iv_size +
+                                                 imp_iv_size);
 
-                       ciphertext->data += AEAD_EXPLICIT_DATA_SIZE;
-                       ciphertext->size -= AEAD_EXPLICIT_DATA_SIZE;
+                       ciphertext->data += exp_iv_size;
+                       ciphertext->size -= exp_iv_size;
 
                        length_to_decrypt = ciphertext->size - tag_size;
-               } else if (iv_size > 0) {       /* a stream cipher with explicit IV */
+               } else if (iv_size > 0) {       /* a stream cipher with implicit IV */
                        _gnutls_auth_cipher_setiv(&params->read.
                                                  cipher_state,
                                                  UINT64DATA(*sequence),
index 0ea7dae0aecb2288fbe3e8d1a944727ad632c90a..133665255673e1a9e3ca8c7f874934008ed4b379 100644 (file)
@@ -343,7 +343,14 @@ int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch)
                    gnutls_assert_val
                    (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
 
-       IV_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       if (!_gnutls_version_has_explicit_iv(ver)) {
+               if (_gnutls_cipher_is_block(params->cipher) != CIPHER_STREAM) {
+                       IV_size = _gnutls_cipher_get_iv_size(params->cipher);
+               } else
+                       IV_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+       } else
+               IV_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
+
        key_size = _gnutls_cipher_get_key_size(params->cipher);
        hash_size = _gnutls_mac_get_key_size(params->mac);
 
index a8da2f07df421c879e457be583f95a35bdb36627..c1d8727f1a8c330ffde0a69d2d218b3192056b4d 100644 (file)
@@ -584,7 +584,7 @@ static int record_overhead(const cipher_entry_st * cipher,
        int t, ret;
 
        if (_gnutls_cipher_is_block(cipher) == CIPHER_BLOCK) {
-               t = _gnutls_cipher_get_implicit_iv_size(cipher);
+               t = _gnutls_cipher_get_explicit_iv_size(cipher);
                total += t;
 
                /* padding */
index 3d30218cd6b639fd2c0741d06f8e0714e5380ea4..a8b24c72c39b093cf7debf0e543c22e63c7c4a7c 100644 (file)
@@ -444,7 +444,8 @@ typedef struct cipher_entry_st {
        uint16_t blocksize;
        uint16_t keysize;
        bool block;
-       uint16_t iv;            /* the size of implicit IV - TLS related */
+       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 */
 } cipher_entry_st;
@@ -556,7 +557,7 @@ typedef struct {
        /* Holds the signature algorithm used in this session - If any */
        gnutls_sign_algorithm_t server_sign_algo;
        gnutls_sign_algorithm_t client_sign_algo;
-
+       
        /* FIXME: The following are not saved in the session storage
         * for session resumption.
         */
index 7b603437e5fc693e4ab5d5dd76f1d814a49dcf17..a2b6d5a6743e9836901a8cd26ea4d8df4e47fafc 100644 (file)
@@ -275,6 +275,7 @@ mbuffer_st *_mbuffer_alloc(size_t maximum_size)
        return st;
 }
 
+
 /* Copy data into a segment. The segment must not be part of a buffer
  * head when using this function.
  *
@@ -301,24 +302,112 @@ _mbuffer_append_data(mbuffer_st * bufel, void *newdata,
        return 0;
 }
 
+#ifdef ENABLE_CRYPTODEV
+# define ALIGN_SIZE 16
+
+/* Allocate a 16-byte alligned buffer segment. The segment is not initially "owned" by
+ * any buffer.
+ *
+ * maximum_size: Amount of data that this segment can contain.
+ * align_pos: identifies the position of the buffer that will be aligned at 16-bytes
+ *
+ * This function should be used to ensure that encrypted data or data to
+ * be encrypted are properly aligned.
+ *
+ * Returns the segment or NULL on error.
+ *
+ * Cost: O(1)
+ */
+mbuffer_st *_mbuffer_alloc_align16(size_t maximum_size, unsigned align_pos)
+{
+       mbuffer_st *st;
+       size_t cur_alignment;
+
+       st = gnutls_malloc(maximum_size + sizeof(mbuffer_st) + ALIGN_SIZE);
+       if (st == NULL) {
+               gnutls_assert();
+               return NULL;
+       }
+
+       /* set the structure to zero */
+       memset(st, 0, sizeof(*st));
+
+       /* payload points after the mbuffer_st structure */
+       st->msg.data = (uint8_t *) st + sizeof(mbuffer_st);
+       
+       cur_alignment = ((size_t)(st->msg.data+align_pos)) % ALIGN_SIZE;
+       if (cur_alignment > 0)
+               st->msg.data += ALIGN_SIZE - cur_alignment;
+
+       st->msg.size = 0;
+       st->maximum_size = maximum_size;
+
+       return st;
+}
+
+static unsigned is_aligned16(mbuffer_st * bufel, unsigned align_pos)
+{
+uint8_t * ptr = _mbuffer_get_udata_ptr(bufel);
+
+       if (((size_t)(ptr+align_pos)) % ALIGN_SIZE == 0)
+               return 1;
+       else
+               return 0;
+}
+
 /* Takes a buffer in multiple chunks and puts all the data in a single
- * contiguous segment.
+ * contiguous segment, ensuring that the @align_pos is 16-byte aligned.
  *
  * Returns 0 on success or an error code otherwise.
  *
  * Cost: O(n)
  * n: number of segments initially in the buffer
  */
-int _mbuffer_linearize(mbuffer_head_st * buf)
+int _mbuffer_linearize_align16(mbuffer_head_st * buf, unsigned align_pos)
 {
        mbuffer_st *bufel, *cur;
        gnutls_datum_t msg;
        size_t pos = 0;
 
-       if (buf->length <= 1)
+       if (buf->length == 0) {
                /* Nothing to do */
                return 0;
+       }
+       
+       bufel = _mbuffer_head_get_first(buf, NULL);
+       if (buf->length == 1 && is_aligned16(bufel, align_pos))
+               return 0;
 
+       bufel = _mbuffer_alloc_align16(buf->byte_length, align_pos);
+       if (!bufel) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+
+       for (cur = _mbuffer_head_get_first(buf, &msg);
+            msg.data != NULL; cur = _mbuffer_head_get_next(cur, &msg)) {
+               memcpy(&bufel->msg.data[pos], msg.data, msg.size);
+               bufel->msg.size += msg.size;
+               pos += msg.size;
+       }
+
+       _mbuffer_head_clear(buf);
+       _mbuffer_enqueue(buf, bufel);
+
+       return 0;
+}
+#else
+int _mbuffer_linearize(mbuffer_head_st * buf)
+{
+       mbuffer_st *bufel, *cur;
+       gnutls_datum_t msg;
+       size_t pos = 0;
+
+       if (buf->length <= 1) {
+               /* Nothing to do */
+               return 0;
+       }
+       
        bufel = _mbuffer_alloc(buf->byte_length);
        if (!bufel) {
                gnutls_assert();
@@ -337,3 +426,4 @@ int _mbuffer_linearize(mbuffer_head_st * buf)
 
        return 0;
 }
+#endif
index 72f8f6a8d72a18b547652c1d88d9b60f879b7752..a22ebbf5216fd5c6fccaea3abce7202f41d4f81e 100644 (file)
@@ -32,6 +32,7 @@ void _mbuffer_enqueue(mbuffer_head_st * buf, mbuffer_st * bufel);
 mbuffer_st *_mbuffer_dequeue(mbuffer_head_st * buf, mbuffer_st * bufel);
 int _mbuffer_head_remove_bytes(mbuffer_head_st * buf, size_t bytes);
 mbuffer_st *_mbuffer_alloc(size_t maximum_size);
+int _mbuffer_linearize(mbuffer_head_st * buf);
 
 mbuffer_st *_mbuffer_head_get_first(mbuffer_head_st * buf,
                                    gnutls_datum_t * msg);
@@ -44,7 +45,6 @@ mbuffer_st *_mbuffer_head_pop_first(mbuffer_head_st * buf);
  */
 int _mbuffer_append_data(mbuffer_st * bufel, void *newdata,
                         size_t newdata_size);
-int _mbuffer_linearize(mbuffer_head_st * buf);
 
 
 /* For "user" use. One can have buffer data and header.
@@ -133,4 +133,12 @@ inline static void _mbuffer_xfree(mbuffer_st ** bufel)
        *bufel = NULL;
 }
 
+#ifdef ENABLE_CRYPTODEV
+mbuffer_st *_mbuffer_alloc_align16(size_t maximum_size, unsigned align_pos);
+int _mbuffer_linearize_align16(mbuffer_head_st * buf, unsigned align_pos);
+#else
+# define _mbuffer_alloc_align16(x,y) _mbuffer_alloc(x)
+# define _mbuffer_linearize_align16(x,y) _mbuffer_linearize(x)
+#endif
+
 #endif
index 00c9f27f86d2ae55e20e3990ec7619f9f6a09f38..a17d2f51483874fa7f3934233b0d911e1853a6a4 100644 (file)
@@ -501,7 +501,9 @@ _gnutls_send_tlen_int(gnutls_session_t session, content_type_t type,
                /* now proceed to packet encryption
                 */
                cipher_size = MAX_RECORD_SEND_SIZE(session);
-               bufel = _mbuffer_alloc(cipher_size + CIPHER_SLACK_SIZE);
+
+               bufel = _mbuffer_alloc_align16(cipher_size + CIPHER_SLACK_SIZE, 
+                       get_total_headers2(session, record_params));
                if (bufel == NULL)
                        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
@@ -510,7 +512,6 @@ _gnutls_send_tlen_int(gnutls_session_t session, content_type_t type,
                /* Use the default record version, if it is
                 * set. */
                copy_record_version(session, htype, &headers[1]);
-               header_size = RECORD_HEADER_SIZE(session);
                /* Adjust header length and add sequence for DTLS */
                if (IS_DTLS(session))
                        memcpy(&headers[3],
@@ -521,6 +522,7 @@ _gnutls_send_tlen_int(gnutls_session_t session, content_type_t type,
                     session, _gnutls_packet2str(type), type,
                     (int) data_size, (int) min_pad);
 
+               header_size = RECORD_HEADER_SIZE(session);
                _mbuffer_set_udata_size(bufel, cipher_size);
                _mbuffer_set_uhead_size(bufel, header_size);
 
@@ -1020,7 +1022,9 @@ record_read_headers(gnutls_session_t session,
 }
 
 
-static int recv_headers(gnutls_session_t session, content_type_t type,
+static int recv_headers(gnutls_session_t session, 
+                       record_parameters_st *record_params,
+                       content_type_t type,
                        gnutls_handshake_description_t htype,
                        struct tls_record_st *record, unsigned int *ms)
 {
@@ -1045,7 +1049,8 @@ static int recv_headers(gnutls_session_t session, content_type_t type,
                return gnutls_assert_val(ret);
        }
 
-       ret = _mbuffer_linearize(&session->internals.record_recv_buffer);
+       ret = _mbuffer_linearize_align16(&session->internals.record_recv_buffer, 
+               get_total_headers2(session, record_params));
        if (ret < 0)
                return gnutls_assert_val(ret);
 
@@ -1160,7 +1165,7 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
        record_state = &record_params->read;
 
        /* receive headers */
-       ret = recv_headers(session, type, htype, &record, &ms);
+       ret = recv_headers(session, record_params, type, htype, &record, &ms);
        if (ret < 0) {
                ret = gnutls_assert_val_fatal(ret);
                goto recv_error;
@@ -1184,7 +1189,8 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
        /* ok now we are sure that we have read all the data - so
         * move on !
         */
-       ret = _mbuffer_linearize(&session->internals.record_recv_buffer);
+       ret = _mbuffer_linearize_align16(&session->internals.record_recv_buffer, 
+               get_total_headers2(session, record_params));
        if (ret < 0)
                return gnutls_assert_val(ret);
 
@@ -1199,7 +1205,7 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
         * they are encrypted).
         */
        ret = max_decrypted_size(session) + MAX_PAD_SIZE + MAX_HASH_SIZE;
-       decrypted = _mbuffer_alloc(ret);
+       decrypted = _mbuffer_alloc_align16(ret, 0);
        if (decrypted == NULL)
                return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
index 12fcc9b36249b1f95062aa43b023b4cb58687a09..71689b75f0f7be1818239212b2a6c793c64044a7 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <gnutls/gnutls.h>
 #include <gnutls_buffers.h>
+#include <gnutls_constate.h>
 
 ssize_t _gnutls_send_tlen_int(gnutls_session_t session,
                              content_type_t type,
@@ -73,4 +74,35 @@ inline static unsigned max_decrypted_size(gnutls_session_t session)
        return size;
 }
 
+/* Returns the headers + any IV that the ciphersuite
+ * requires */
+inline static
+unsigned int get_total_headers(gnutls_session_t session)
+{
+       int ret;
+       record_parameters_st *params;
+       unsigned total = RECORD_HEADER_SIZE(session);
+
+       if (session->security_parameters.new_record_padding)
+               total += 2;
+
+       ret = _gnutls_epoch_get(session, EPOCH_WRITE_CURRENT, &params);
+       if (ret < 0) {
+               return total;
+       }
+       
+       return total + _gnutls_cipher_get_explicit_iv_size(params->cipher);
+}
+
+inline static
+unsigned int get_total_headers2(gnutls_session_t session, record_parameters_st *params)
+{
+       unsigned total = RECORD_HEADER_SIZE(session);
+
+       if (session->security_parameters.new_record_padding)
+               total += 2;
+
+       return total + _gnutls_cipher_get_explicit_iv_size(params->cipher);
+}
+
 #endif