1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file f9_done.c
7   f9 Support, terminate the state
8 */
9 
10 #ifdef LTC_F9_MODE
11 
12 /** Terminate the f9-MAC state
13   @param f9     f9 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 */
f9_done(f9_state * f9,unsigned char * out,unsigned long * outlen)18 int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen)
19 {
20    int err, x;
21    LTC_ARGCHK(f9 != NULL);
22    LTC_ARGCHK(out  != NULL);
23 
24    /* check structure */
25    if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) {
26       return err;
27    }
28 
29    if ((f9->blocksize > cipher_descriptor[f9->cipher]->block_length) || (f9->blocksize < 0) ||
30        (f9->buflen > f9->blocksize) || (f9->buflen < 0)) {
31       return CRYPT_INVALID_ARG;
32    }
33 
34    if (f9->buflen != 0) {
35       /* encrypt */
36       cipher_descriptor[f9->cipher]->ecb_encrypt(f9->IV, f9->IV, &f9->key);
37       f9->buflen = 0;
38       for (x = 0; x < f9->blocksize; x++) {
39          f9->ACC[x] ^= f9->IV[x];
40       }
41    }
42 
43    /* schedule modified key */
44    if ((err = cipher_descriptor[f9->cipher]->setup(f9->akey, f9->keylen, 0, &f9->key)) != CRYPT_OK) {
45       return err;
46    }
47 
48    /* encrypt the ACC */
49    cipher_descriptor[f9->cipher]->ecb_encrypt(f9->ACC, f9->ACC, &f9->key);
50    cipher_descriptor[f9->cipher]->done(&f9->key);
51 
52    /* extract tag */
53    for (x = 0; x < f9->blocksize && (unsigned long)x < *outlen; x++) {
54       out[x] = f9->ACC[x];
55    }
56    *outlen = x;
57 
58 #ifdef LTC_CLEAN_STACK
59    zeromem(f9, sizeof(*f9));
60 #endif
61    return CRYPT_OK;
62 }
63 
64 #endif
65 
66