Quickfix for issue #73
The API of the function is changed (for decryption, tag is now an input parameter). With the old API it is impossible to confirm to the NIST specification and a timing sidechannel leak is inevitable.
This commit is contained in:
		
							parent
							
								
									38bfef2996
								
							
						
					
					
						commit
						25af184cd5
					
				@ -20,7 +20,7 @@
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
   CCM encrypt/decrypt and produce an authentication tag
 | 
					   CCM encrypt/decrypt and produce an authentication tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     *1 'pt' and 'ct' can both be 'in' or 'out', depending on 'direction'
 | 
					     *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   @param cipher     The index of the cipher desired
 | 
					   @param cipher     The index of the cipher desired
 | 
				
			||||||
   @param key        The secret key to use
 | 
					   @param key        The secret key to use
 | 
				
			||||||
@ -33,8 +33,8 @@
 | 
				
			|||||||
   @param pt         [*1] The plaintext
 | 
					   @param pt         [*1] The plaintext
 | 
				
			||||||
   @param ptlen      The length of the plaintext (octets)
 | 
					   @param ptlen      The length of the plaintext (octets)
 | 
				
			||||||
   @param ct         [*1] The ciphertext
 | 
					   @param ct         [*1] The ciphertext
 | 
				
			||||||
   @param tag        [out] The destination tag
 | 
					   @param tag        [*1] The destination tag
 | 
				
			||||||
   @param taglen     [in/out] The max size and resulting size of the authentication tag
 | 
					   @param taglen     The max size and resulting size of the authentication tag
 | 
				
			||||||
   @param direction  Encrypt or Decrypt direction (0 or 1)
 | 
					   @param direction  Encrypt or Decrypt direction (0 or 1)
 | 
				
			||||||
   @return CRYPT_OK if successful
 | 
					   @return CRYPT_OK if successful
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
@ -48,7 +48,7 @@ int ccm_memory(int cipher,
 | 
				
			|||||||
          unsigned char *tag,    unsigned long *taglen,
 | 
					          unsigned char *tag,    unsigned long *taglen,
 | 
				
			||||||
                    int  direction)
 | 
					                    int  direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
   unsigned char  PAD[16], ctr[16], CTRPAD[16], b;
 | 
					   unsigned char  PAD[16], ctr[16], CTRPAD[16], ptTag[16], b;
 | 
				
			||||||
   symmetric_key *skey;
 | 
					   symmetric_key *skey;
 | 
				
			||||||
   int            err;
 | 
					   int            err;
 | 
				
			||||||
   unsigned long  len, L, x, y, z, CTRlen;
 | 
					   unsigned long  len, L, x, y, z, CTRlen;
 | 
				
			||||||
@ -203,13 +203,11 @@ int ccm_memory(int cipher,
 | 
				
			|||||||
          PAD[x++] ^= header[y];
 | 
					          PAD[x++] ^= header[y];
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      /* remainder? */
 | 
					      /* remainder */
 | 
				
			||||||
      if (x != 0) {
 | 
					 | 
				
			||||||
      if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
 | 
					      if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
 | 
				
			||||||
         goto error;
 | 
					         goto error;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
   }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   /* setup the ctr counter */
 | 
					   /* setup the ctr counter */
 | 
				
			||||||
   x = 0;
 | 
					   x = 0;
 | 
				
			||||||
@ -254,7 +252,7 @@ int ccm_memory(int cipher,
 | 
				
			|||||||
                   goto error;
 | 
					                   goto error;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
             }
 | 
					             }
 | 
				
			||||||
         } else {
 | 
					          } else { /* direction == CCM_DECRYPT */
 | 
				
			||||||
             for (; y < (ptlen & ~15); y += 16) {
 | 
					             for (; y < (ptlen & ~15); y += 16) {
 | 
				
			||||||
                /* increment the ctr? */
 | 
					                /* increment the ctr? */
 | 
				
			||||||
                for (z = 15; z > 15-L; z--) {
 | 
					                for (z = 15; z > 15-L; z--) {
 | 
				
			||||||
@ -328,11 +326,34 @@ int ccm_memory(int cipher,
 | 
				
			|||||||
      cipher_descriptor[cipher].done(skey);
 | 
					      cipher_descriptor[cipher].done(skey);
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   if (direction == CCM_ENCRYPT) {
 | 
				
			||||||
      /* store the TAG */
 | 
					      /* store the TAG */
 | 
				
			||||||
      for (x = 0; x < 16 && x < *taglen; x++) {
 | 
					      for (x = 0; x < 16 && x < *taglen; x++) {
 | 
				
			||||||
          tag[x] = PAD[x] ^ CTRPAD[x];
 | 
					          tag[x] = PAD[x] ^ CTRPAD[x];
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      *taglen = 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* TODO: pt should not be revealed when the tag is invalid. However, resetting the
 | 
				
			||||||
 | 
					       *       memory should be done in constant time, which is not the case in the
 | 
				
			||||||
 | 
					       *       (commented) code below.
 | 
				
			||||||
 | 
					      if (err != CRYPT_OK) {
 | 
				
			||||||
 | 
					         zeromem(pt, ptlen);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      */
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef LTC_CLEAN_STACK
 | 
					#ifdef LTC_CLEAN_STACK
 | 
				
			||||||
   zeromem(skey,   sizeof(*skey));
 | 
					   zeromem(skey,   sizeof(*skey));
 | 
				
			||||||
 | 
				
			|||||||
@ -195,7 +195,7 @@ int ccm_test(void)
 | 
				
			|||||||
                               tests[x].header, tests[x].headerlen,
 | 
					                               tests[x].header, tests[x].headerlen,
 | 
				
			||||||
                               buf2, tests[x].ptlen,
 | 
					                               buf2, tests[x].ptlen,
 | 
				
			||||||
                               buf,
 | 
					                               buf,
 | 
				
			||||||
                               tag2, &taglen, 1   )) != CRYPT_OK) {
 | 
					                               tests[x].tag, &taglen, 1   )) != CRYPT_OK) {
 | 
				
			||||||
            return err;
 | 
					            return err;
 | 
				
			||||||
         }
 | 
					         }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
@ -224,6 +224,9 @@ int ccm_test(void)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
         return CRYPT_FAIL_TESTVECTOR;
 | 
					         return CRYPT_FAIL_TESTVECTOR;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      /* Only check the tag if ccm_memory was not called: ccm_memory already
 | 
				
			||||||
 | 
					         validates the tag */
 | 
				
			||||||
 | 
					      if (y != 0) {
 | 
				
			||||||
         if (XMEMCMP(tag2, tests[x].tag, tests[x].taglen)) {
 | 
					         if (XMEMCMP(tag2, tests[x].tag, tests[x].taglen)) {
 | 
				
			||||||
#if defined(LTC_TEST_DBG)
 | 
					#if defined(LTC_TEST_DBG)
 | 
				
			||||||
            printf("\n%d: x=%lu y=%lu\n", __LINE__, x, y);
 | 
					            printf("\n%d: x=%lu y=%lu\n", __LINE__, x, y);
 | 
				
			||||||
@ -232,6 +235,7 @@ int ccm_test(void)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
            return CRYPT_FAIL_TESTVECTOR;
 | 
					            return CRYPT_FAIL_TESTVECTOR;
 | 
				
			||||||
         }
 | 
					         }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      if (y == 0) {
 | 
					      if (y == 0) {
 | 
				
			||||||
         cipher_descriptor[idx].done(&skey);
 | 
					         cipher_descriptor[idx].done(&skey);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user