1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 
11 /**
12    @file ocb3_done.c
13    OCB implementation, INTERNAL ONLY helper, by Tom St Denis
14 */
15 #include "tomcrypt_private.h"
16 
17 #ifdef LTC_OCB3_MODE
18 
19 /**
20    Finish OCB processing and compute the tag
21    @param ocb     The OCB state
22    @param tag     [out] The destination for the authentication tag
23    @param taglen  [in/out] The max size and resulting size of the authentication tag
24    @return CRYPT_OK if successful
25 */
ocb3_done(ocb3_state * ocb,unsigned char * tag,unsigned long * taglen)26 int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen)
27 {
28    unsigned char tmp[MAXBLOCKSIZE];
29    int err, x;
30 
31    LTC_ARGCHK(ocb    != NULL);
32    LTC_ARGCHK(tag    != NULL);
33    LTC_ARGCHK(taglen != NULL);
34    if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
35       goto LBL_ERR;
36    }
37 
38    /* check taglen */
39    if ((int)*taglen < ocb->tag_len) {
40       *taglen = (unsigned long)ocb->tag_len;
41       return CRYPT_BUFFER_OVERFLOW;
42    }
43 
44    /* finalize AAD processing */
45 
46    if (ocb->adata_buffer_bytes>0) {
47      /* Offset_* = Offset_m xor L_* */
48      ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_star, ocb->block_len);
49 
50      /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */
51      ocb3_int_xor_blocks(tmp, ocb->adata_buffer, ocb->aOffset_current, ocb->adata_buffer_bytes);
52      for(x=ocb->adata_buffer_bytes; x<ocb->block_len; x++) {
53        if (x == ocb->adata_buffer_bytes) {
54          tmp[x] = 0x80 ^ ocb->aOffset_current[x];
55        }
56        else {
57          tmp[x] = 0x00 ^ ocb->aOffset_current[x];
58        }
59      }
60 
61      /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */
62      if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) {
63        goto LBL_ERR;
64      }
65      ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len);
66    }
67 
68    /* finalize TAG computing */
69 
70    /* at this point ocb->aSum_current = HASH(K, A) */
71    /* tag = tag ^ HASH(K, A) */
72    ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len);
73 
74    /* copy tag bytes */
75    for(x = 0; x < ocb->tag_len; x++) tag[x] = tmp[x];
76    *taglen = (unsigned long)ocb->tag_len;
77 
78    err = CRYPT_OK;
79 
80 LBL_ERR:
81 #ifdef LTC_CLEAN_STACK
82    zeromem(tmp, MAXBLOCKSIZE);
83    zeromem(ocb, sizeof(*ocb));
84 #endif
85 
86    return err;
87 }
88 
89 #endif
90 
91 /* ref:         $Format:%D$ */
92 /* git commit:  $Format:%H$ */
93 /* commit time: $Format:%ai$ */
94