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