Browse Source

OCBv3: improved handling of taglen in ocb3_done

Karel Miko 8 years ago
parent
commit
af63d0a55f

+ 8 - 6
src/encauth/ocb3/ocb3_done.c

@@ -34,6 +34,12 @@ int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen)
       goto LBL_ERR;
       goto LBL_ERR;
    }
    }
 
 
+   /* check taglen */
+   if ((int)*taglen < ocb->tag_len) {
+      *taglen = (unsigned long)ocb->tag_len;
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
    /* finalize AAD processing */
    /* finalize AAD processing */
 
 
    if (ocb->adata_buffer_bytes>0) {
    if (ocb->adata_buffer_bytes>0) {
@@ -64,13 +70,9 @@ int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen)
    /* tag = tag ^ HASH(K, A) */
    /* tag = tag ^ HASH(K, A) */
    ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len);
    ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len);
 
 
-   /* fix taglen if needed */
-   if ((int)*taglen > ocb->block_len) {
-     *taglen = (unsigned long)ocb->block_len;
-   }
-
    /* copy tag bytes */
    /* copy tag bytes */
-   for(x=0; x<(int)*taglen; x++) tag[x] = tmp[x];
+   for(x = 0; x < ocb->tag_len; x++) tag[x] = tmp[x];
+   *taglen = (unsigned long)ocb->tag_len;
 
 
    err = CRYPT_OK;
    err = CRYPT_OK;
 
 

+ 1 - 0
src/encauth/ocb3/ocb3_init.c

@@ -118,6 +118,7 @@ int ocb3_init(ocb3_state *ocb, int cipher,
    if (taglen > (unsigned long)cipher_descriptor[cipher].block_length) {
    if (taglen > (unsigned long)cipher_descriptor[cipher].block_length) {
       taglen = cipher_descriptor[cipher].block_length;
       taglen = cipher_descriptor[cipher].block_length;
    }
    }
+   ocb->tag_len = taglen;
 
 
    /* determine which polys to use */
    /* determine which polys to use */
    ocb->block_len = cipher_descriptor[cipher].block_length;
    ocb->block_len = cipher_descriptor[cipher].block_length;

+ 23 - 0
src/encauth/ocb3/ocb3_test.c

@@ -205,6 +205,7 @@ int ocb3_test(void)
    int err, x, idx, res;
    int err, x, idx, res;
    unsigned long len;
    unsigned long len;
    unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE];
    unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE];
+   ocb3_state ocb;
 
 
     /* AES can be under rijndael or aes... try to find it */
     /* AES can be under rijndael or aes... try to find it */
     if ((idx = find_cipher("aes")) == -1) {
     if ((idx = find_cipher("aes")) == -1) {
@@ -244,6 +245,8 @@ int ocb3_test(void)
            return CRYPT_FAIL_TESTVECTOR;
            return CRYPT_FAIL_TESTVECTOR;
         }
         }
     }
     }
+
+    /* RFC 7253 - test vector with a tag length of 96 bits - part 1 */
     x = 99;
     x = 99;
     len = 12;
     len = 12;
     if ((err = ocb3_encrypt_authenticate_memory(idx,
     if ((err = ocb3_encrypt_authenticate_memory(idx,
@@ -274,6 +277,26 @@ int ocb3_test(void)
 #endif
 #endif
        return CRYPT_FAIL_TESTVECTOR;
        return CRYPT_FAIL_TESTVECTOR;
     }
     }
+
+    /* RFC 7253 - test vector with a tag length of 96 bits - part 2 */
+    x = 100;
+    if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK)  return err;
+    if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK)                      return err;
+    if ((err = ocb3_encrypt(&ocb, P, 32, outct)) != CRYPT_OK)                      return err;
+    if ((err = ocb3_encrypt_last(&ocb, P+32, sizeof(P)-32, outct+32)) != CRYPT_OK) return err;
+    len = sizeof(outtag); /* intentionally more than 12 */
+    if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK)                         return err;
+    if (compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x))          return CRYPT_FAIL_TESTVECTOR;
+    if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.enc", x))          return CRYPT_FAIL_TESTVECTOR;
+    if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK)  return err;
+    if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK)                      return err;
+    if ((err = ocb3_decrypt(&ocb, C, 32, outct)) != CRYPT_OK)                      return err;
+    if ((err = ocb3_decrypt_last(&ocb, C+32, sizeof(C)-32, outct+32)) != CRYPT_OK) return err;
+    len = sizeof(outtag); /* intentionally more than 12 */
+    if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK)                         return err;
+    if (compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3 PT", x))          return CRYPT_FAIL_TESTVECTOR;
+    if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.dec", x))          return CRYPT_FAIL_TESTVECTOR;
+
     return CRYPT_OK;
     return CRYPT_OK;
 #endif /* LTC_TEST */
 #endif /* LTC_TEST */
 }
 }

+ 1 - 0
src/headers/tomcrypt_mac.h

@@ -266,6 +266,7 @@ typedef struct {
    symmetric_key     key;                     /* scheduled key for cipher */
    symmetric_key     key;                     /* scheduled key for cipher */
    unsigned long     block_index;             /* index # for current data block */
    unsigned long     block_index;             /* index # for current data block */
    int               cipher,                  /* cipher idx */
    int               cipher,                  /* cipher idx */
+                     tag_len,                 /* length of tag */
                      block_len;               /* length of block */
                      block_len;               /* length of block */
 } ocb3_state;
 } ocb3_state;