1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file xcbc_done.c
7   XCBC Support, terminate the state
8 */
9 
10 #ifdef LTC_XCBC
11 
12 /** Terminate the XCBC-MAC state
13   @param xcbc     XCBC state to terminate
14   @param out      [out] Destination for the MAC tag
15   @param outlen   [in/out] Destination size and final tag size
16   Return CRYPT_OK on success
17 */
xcbc_done(xcbc_state * xcbc,unsigned char * out,unsigned long * outlen)18 int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen)
19 {
20    int err, x;
21    LTC_ARGCHK(xcbc != NULL);
22    LTC_ARGCHK(out  != NULL);
23 
24    /* check structure */
25    if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) {
26       return err;
27    }
28 
29    if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher]->block_length) || (xcbc->blocksize < 0) ||
30        (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) {
31       return CRYPT_INVALID_ARG;
32    }
33 
34    /* which key do we use? */
35    if (xcbc->buflen == xcbc->blocksize) {
36       /* k2 */
37       for (x = 0; x < xcbc->blocksize; x++) {
38          xcbc->IV[x] ^= xcbc->K[1][x];
39       }
40    } else {
41       xcbc->IV[xcbc->buflen] ^= 0x80;
42       /* k3 */
43       for (x = 0; x < xcbc->blocksize; x++) {
44          xcbc->IV[x] ^= xcbc->K[2][x];
45       }
46    }
47 
48    /* encrypt */
49    cipher_descriptor[xcbc->cipher]->ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key);
50    cipher_descriptor[xcbc->cipher]->done(&xcbc->key);
51 
52    /* extract tag */
53    for (x = 0; x < xcbc->blocksize && (unsigned long)x < *outlen; x++) {
54       out[x] = xcbc->IV[x];
55    }
56    *outlen = x;
57 
58 #ifdef LTC_CLEAN_STACK
59    zeromem(xcbc, sizeof(*xcbc));
60 #endif
61    return CRYPT_OK;
62 }
63 
64 #endif
65 
66