]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Eliminated memory copy at encryption.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 26 May 2013 17:46:19 +0000 (19:46 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 26 May 2013 18:02:13 +0000 (20:02 +0200)
lib/algorithms/ciphers.c
lib/gnutls_cipher.c
lib/gnutls_cipher_int.c
lib/gnutls_cipher_int.h

index a557ca1b2cf64a96e1a2628f9dbe64ce2204ac31..022702efb319946863d95a6a96c84a19931df74d 100644 (file)
@@ -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,
index 2d86c49c305169739709150ff9b7bfc52c050055..dd843ddcfb196890f62068c375caf0636455d891 100644 (file)
@@ -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 (&params->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(&params->write.cipher_state, UINT64DATA(params->write.sequence_number), 8);
@@ -422,19 +413,6 @@ compressed_to_ciphertext (gnutls_session_t session,
         _gnutls_auth_cipher_setiv(&params->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(&params->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 (&params->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 (&params->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);
 
index 4ecded6bfc9e2db3ae2005d65ee3c6240dd5958a..79d71fe4adc0bf44045df7b3ca3c75875517b552 100644 (file)
@@ -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);
 }
index 35b8e6106f8e4208cf4325b2c68e86ac7bc965cc..6e1e8b7f4a8c6ffe31cd9e60ed921513d6d3a560 100644 (file)
@@ -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);