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 */
pmac_process(pmac_state * pmac,const unsigned char * in,unsigned long inlen)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