diff libtomcrypt/src/encauth/ccm/ccm_memory.c @ 1471:6dba84798cd5

Update to libtomcrypt 1.18.1, merged with Dropbear changes
author Matt Johnston <matt@ucc.asn.au>
date Fri, 09 Feb 2018 21:44:05 +0800
parents f849a5ca2efc
children e9dba7abd939
line wrap: on
line diff
--- a/libtomcrypt/src/encauth/ccm/ccm_memory.c	Thu Feb 08 23:11:40 2018 +0800
+++ b/libtomcrypt/src/encauth/ccm/ccm_memory.c	Fri Feb 09 21:44:05 2018 +0800
@@ -5,8 +5,6 @@
  *
  * The library is free for all purposes without any express
  * guarantee it works.
- *
- * Tom St Denis, [email protected], http://libtom.org
  */
 #include "tomcrypt.h"
 
@@ -19,6 +17,9 @@
 
 /**
    CCM encrypt/decrypt and produce an authentication tag
+
+     *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction'
+
    @param cipher     The index of the cipher desired
    @param key        The secret key to use
    @param keylen     The length of the secret key (octets)
@@ -27,11 +28,11 @@
    @param noncelen   The length of the nonce
    @param header     The header for the session
    @param headerlen  The length of the header (octets)
-   @param pt         [out] The plaintext
+   @param pt         [*1] The plaintext
    @param ptlen      The length of the plaintext (octets)
-   @param ct         [out] The ciphertext
-   @param tag        [out] The destination tag
-   @param taglen     [in/out] The max size and resulting size of the authentication tag
+   @param ct         [*1] The ciphertext
+   @param tag        [*1] The destination tag
+   @param taglen     The max size and resulting size of the authentication tag
    @param direction  Encrypt or Decrypt direction (0 or 1)
    @return CRYPT_OK if successful
 */
@@ -45,10 +46,15 @@
           unsigned char *tag,    unsigned long *taglen,
                     int  direction)
 {
-   unsigned char  PAD[16], ctr[16], CTRPAD[16], b;
+   unsigned char  PAD[16], ctr[16], CTRPAD[16], ptTag[16], b, *pt_real;
+   unsigned char *pt_work = NULL;
    symmetric_key *skey;
    int            err;
    unsigned long  len, L, x, y, z, CTRlen;
+#ifdef LTC_FAST
+   LTC_FAST_TYPE fastMask = ~0; /* initialize fastMask at all zeroes */
+#endif
+   unsigned char mask = 0xff; /* initialize mask at all zeroes */
 
    if (uskey == NULL) {
       LTC_ARGCHK(key    != NULL);
@@ -62,6 +68,8 @@
    LTC_ARGCHK(tag    != NULL);
    LTC_ARGCHK(taglen != NULL);
 
+   pt_real = pt;
+
 #ifdef LTC_FAST
    if (16 % sizeof(LTC_FAST_TYPE)) {
       return CRYPT_INVALID_ARG;
@@ -95,7 +103,7 @@
            nonce,  noncelen,
            header, headerlen,
            pt,     ptlen,
-           ct, 
+           ct,
            tag,    taglen,
            direction);
    }
@@ -117,11 +125,6 @@
       L = 15 - noncelen;
    }
 
-   /* decrease noncelen to match L */
-   if ((noncelen + L) > 15) {
-      noncelen = 15 - L;
-   }
-
    /* allocate mem for the symmetric key */
    if (uskey == NULL) {
       skey = XMALLOC(sizeof(*skey));
@@ -138,6 +141,15 @@
       skey = uskey;
    }
 
+   /* initialize buffer for pt */
+   if (direction == CCM_DECRYPT && ptlen > 0) {
+      pt_work = XMALLOC(ptlen);
+      if (pt_work == NULL) {
+         goto error;
+      }
+      pt = pt_work;
+   }
+
    /* form B_0 == flags | Nonce N | l(m) */
    x = 0;
    PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) |
@@ -174,7 +186,7 @@
    /* handle header */
    if (headerlen > 0) {
       x = 0;
-      
+
       /* store length */
       if (headerlen < ((1UL<<16) - (1UL<<8))) {
          PAD[x++] ^= (headerlen>>8) & 255;
@@ -200,11 +212,9 @@
           PAD[x++] ^= header[y];
       }
 
-      /* remainder? */
-      if (x != 0) {
-         if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
-            goto error;
-         }
+      /* remainder */
+      if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
+         goto error;
       }
    }
 
@@ -213,7 +223,7 @@
 
    /* flags */
    ctr[x++] = (unsigned char)L-1;
- 
+
    /* nonce */
    for (y = 0; y < (16 - (L+1)); ++y) {
       ctr[x++] = nonce[y];
@@ -244,14 +254,14 @@
 
                 /* xor the PT against the pad first */
                 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
-                    *((LTC_FAST_TYPE*)(&PAD[z]))  ^= *((LTC_FAST_TYPE*)(&pt[y+z]));
-                    *((LTC_FAST_TYPE*)(&ct[y+z])) = *((LTC_FAST_TYPE*)(&pt[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z]));
+                    *(LTC_FAST_TYPE_PTR_CAST(&PAD[z]))  ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z]));
+                    *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z]));
                 }
                 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
                    goto error;
                 }
              }
-         } else {
+          } else { /* direction == CCM_DECRYPT */
              for (; y < (ptlen & ~15); y += 16) {
                 /* increment the ctr? */
                 for (z = 15; z > 15-L; z--) {
@@ -264,15 +274,15 @@
 
                 /* xor the PT against the pad last */
                 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
-                    *((LTC_FAST_TYPE*)(&pt[y+z])) = *((LTC_FAST_TYPE*)(&ct[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z]));
-                    *((LTC_FAST_TYPE*)(&PAD[z]))  ^= *((LTC_FAST_TYPE*)(&pt[y+z]));
+                    *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z]));
+                    *(LTC_FAST_TYPE_PTR_CAST(&PAD[z]))  ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z]));
                 }
                 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
                    goto error;
                 }
              }
-         }
-     }
+          }
+      }
 #endif
 
       for (; y < ptlen; y++) {
@@ -305,7 +315,7 @@
           }
           PAD[x++] ^= b;
       }
-             
+
       if (x != 0) {
          if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
             goto error;
@@ -323,20 +333,66 @@
 
    if (skey != uskey) {
       cipher_descriptor[cipher].done(skey);
+#ifdef LTC_CLEAN_STACK
+      zeromem(skey,   sizeof(*skey));
+#endif
    }
 
-   /* store the TAG */
-   for (x = 0; x < 16 && x < *taglen; x++) {
-       tag[x] = PAD[x] ^ CTRPAD[x];
+   if (direction == CCM_ENCRYPT) {
+      /* store the TAG */
+      for (x = 0; x < 16 && x < *taglen; x++) {
+          tag[x] = PAD[x] ^ CTRPAD[x];
+      }
+      *taglen = x;
+   } else { /* direction == CCM_DECRYPT */
+      /* decrypt the tag */
+      for (x = 0; x < 16 && x < *taglen; x++) {
+         ptTag[x] = tag[x] ^ CTRPAD[x];
+      }
+      *taglen = x;
+
+      /* check validity of the decrypted tag against the computed PAD (in constant time) */
+      /* HACK: the boolean value of XMEM_NEQ becomes either 0 (CRYPT_OK) or 1 (CRYPT_ERR).
+       *       there should be a better way of setting the correct error code in constant
+       *       time.
+       */
+      err = XMEM_NEQ(ptTag, PAD, *taglen);
+
+      /* Zero the plaintext if the tag was invalid (in constant time) */
+      if (ptlen > 0) {
+         y = 0;
+         mask *= 1 - err; /* mask = ( err ? 0 : 0xff ) */
+#ifdef LTC_FAST
+         fastMask *= 1 - err;
+         if (ptlen & ~15) {
+            for (; y < (ptlen & ~15); y += 16) {
+              for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
+                *(LTC_FAST_TYPE_PTR_CAST(&pt_real[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) & fastMask;
+              }
+            }
+         }
+#endif
+         for (; y < ptlen; y++) {
+            pt_real[y] = pt[y] & mask;
+         }
+      }
    }
-   *taglen = x;
 
 #ifdef LTC_CLEAN_STACK
-   zeromem(skey,   sizeof(*skey));
+#ifdef LTC_FAST
+   fastMask = 0;
+#endif
+   mask = 0;
    zeromem(PAD,    sizeof(PAD));
    zeromem(CTRPAD, sizeof(CTRPAD));
+   if (pt_work != NULL) {
+     zeromem(pt_work, ptlen);
+   }
 #endif
 error:
+   if (pt_work) {
+      XFREE(pt_work);
+   }
    if (skey != uskey) {
       XFREE(skey);
    }
@@ -346,6 +402,6 @@
 
 #endif
 
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref:         $Format:%D$ */
+/* git commit:  $Format:%H$ */
+/* commit time: $Format:%ai$ */