1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6    @file pmac_process.c
7    PMAC implementation, process data, by Tom St Denis
8 */
9 
10 
11 #ifdef LTC_PMAC
12 
13 /**
14   Process data in a PMAC stream
15   @param pmac     The PMAC state
16   @param in       The data to send through PMAC
17   @param inlen    The length of the data to send through PMAC
18   @return CRYPT_OK if successful
19 */
20 int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen)
21 {
22    int err, n;
23    unsigned long x;
24    unsigned char Z[MAXBLOCKSIZE];
25 
26    LTC_ARGCHK(pmac != NULL);
27    LTC_ARGCHK(in   != NULL);
28    if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) {
29       return err;
30    }
31 
32    if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) ||
33        (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) {
34       return CRYPT_INVALID_ARG;
35    }
36 
37 #ifdef LTC_FAST
38    if (pmac->buflen == 0 && inlen > 16) {
39       unsigned long y;
40       for (x = 0; x < (inlen - 16); x += 16) {
41           pmac_shift_xor(pmac);
42           for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
43               *(LTC_FAST_TYPE_PTR_CAST(&Z[y])) = *(LTC_FAST_TYPE_PTR_CAST(&in[y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&pmac->Li[y]));
44           }
45           if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) {
46              return err;
47           }
48           for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
49               *(LTC_FAST_TYPE_PTR_CAST(&pmac->checksum[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&Z[y]));
50           }
51           in += 16;
52       }
53       inlen -= x;
54    }
55 #endif
56 
57    while (inlen != 0) {
58        /* ok if the block is full we xor in prev, encrypt and replace prev */
59        if (pmac->buflen == pmac->block_len) {
60           pmac_shift_xor(pmac);
61           for (x = 0; x < (unsigned long)pmac->block_len; x++) {
62                Z[x] = pmac->Li[x] ^ pmac->block[x];
63           }
64           if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) {
65              return err;
66            }
67           for (x = 0; x < (unsigned long)pmac->block_len; x++) {
68               pmac->checksum[x] ^= Z[x];
69           }
70           pmac->buflen = 0;
71        }
72 
73        /* add bytes */
74        n = MIN(inlen, (unsigned long)(pmac->block_len - pmac->buflen));
75        XMEMCPY(pmac->block + pmac->buflen, in, n);
76        pmac->buflen  += n;
77        inlen         -= n;
78        in            += n;
79    }
80 
81 #ifdef LTC_CLEAN_STACK
82    zeromem(Z, sizeof(Z));
83 #endif
84 
85    return CRYPT_OK;
86 }
87 
88 #endif
89