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