1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file pmac_done.c
7   PMAC implementation, terminate a session, by Tom St Denis
8 */
9 
10 #ifdef LTC_PMAC
11 
pmac_done(pmac_state * pmac,unsigned char * out,unsigned long * outlen)12 int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen)
13 {
14    int err, x;
15 
16    LTC_ARGCHK(pmac != NULL);
17    LTC_ARGCHK(out  != NULL);
18    if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) {
19       return err;
20    }
21 
22    if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) ||
23        (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) {
24       return CRYPT_INVALID_ARG;
25    }
26 
27 
28    /* handle padding.  If multiple xor in L/x */
29 
30    if (pmac->buflen == pmac->block_len) {
31       /* xor Lr against the checksum */
32       for (x = 0; x < pmac->block_len; x++) {
33           pmac->checksum[x] ^= pmac->block[x] ^ pmac->Lr[x];
34       }
35    } else {
36       /* otherwise xor message bytes then the 0x80 byte */
37       for (x = 0; x < pmac->buflen; x++) {
38           pmac->checksum[x] ^= pmac->block[x];
39       }
40       pmac->checksum[x] ^= 0x80;
41    }
42 
43    /* encrypt it */
44    if ((err = cipher_descriptor[pmac->cipher_idx]->ecb_encrypt(pmac->checksum, pmac->checksum, &pmac->key)) != CRYPT_OK) {
45       return err;
46    }
47    cipher_descriptor[pmac->cipher_idx]->done(&pmac->key);
48 
49    /* store it */
50    for (x = 0; x < pmac->block_len && x < (int)*outlen; x++) {
51        out[x] = pmac->checksum[x];
52    }
53    *outlen = x;
54 
55 #ifdef LTC_CLEAN_STACK
56    zeromem(pmac, sizeof(*pmac));
57 #endif
58    return CRYPT_OK;
59 }
60 
61 #endif
62 
63