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_init.c
14 PMAC implementation, initialize state, by Tom St Denis
15 */
16
17 #ifdef LTC_PMAC
18
19 static const struct {
20 int len;
21 unsigned char poly_div[MAXBLOCKSIZE],
22 poly_mul[MAXBLOCKSIZE];
23 } polys[] = {
24 {
25 8,
26 { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D },
27 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
28 }, {
29 16,
30 { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 },
32 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
34 }
35 };
36
37 /**
38 Initialize a PMAC state
39 @param pmac The PMAC state to initialize
40 @param cipher The index of the desired cipher
41 @param key The secret key
42 @param keylen The length of the secret key (octets)
43 @return CRYPT_OK if successful
44 */
pmac_init(pmac_state * pmac,int cipher,const unsigned char * key,unsigned long keylen)45 int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen)
46 {
47 int poly, x, y, m, err;
48 unsigned char *L;
49
50 LTC_ARGCHK(pmac != NULL);
51 LTC_ARGCHK(key != NULL);
52
53 /* valid cipher? */
54 if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
55 return err;
56 }
57
58 /* determine which polys to use */
59 pmac->block_len = cipher_descriptor[cipher]->block_length;
60 for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) {
61 if (polys[poly].len == pmac->block_len) {
62 break;
63 }
64 }
65 if (poly >= (int)(sizeof(polys)/sizeof(polys[0]))) {
66 return CRYPT_INVALID_ARG;
67 }
68 if (polys[poly].len != pmac->block_len) {
69 return CRYPT_INVALID_ARG;
70 }
71
72 #ifdef LTC_FAST
73 if (pmac->block_len % sizeof(LTC_FAST_TYPE)) {
74 return CRYPT_INVALID_ARG;
75 }
76 #endif
77
78
79 /* schedule the key */
80 if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) {
81 return err;
82 }
83
84 /* allocate L */
85 L = XMALLOC(pmac->block_len);
86 if (L == NULL) {
87 return CRYPT_MEM;
88 }
89
90 /* find L = E[0] */
91 zeromem(L, pmac->block_len);
92 if ((err = cipher_descriptor[cipher]->ecb_encrypt(L, L, &pmac->key)) != CRYPT_OK) {
93 goto error;
94 }
95
96 /* find Ls[i] = L << i for i == 0..31 */
97 XMEMCPY(pmac->Ls[0], L, pmac->block_len);
98 for (x = 1; x < 32; x++) {
99 m = pmac->Ls[x-1][0] >> 7;
100 for (y = 0; y < pmac->block_len-1; y++) {
101 pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255;
102 }
103 pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255;
104
105 if (m == 1) {
106 for (y = 0; y < pmac->block_len; y++) {
107 pmac->Ls[x][y] ^= polys[poly].poly_mul[y];
108 }
109 }
110 }
111
112 /* find Lr = L / x */
113 m = L[pmac->block_len-1] & 1;
114
115 /* shift right */
116 for (x = pmac->block_len - 1; x > 0; x--) {
117 pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255;
118 }
119 pmac->Lr[0] = L[0] >> 1;
120
121 if (m == 1) {
122 for (x = 0; x < pmac->block_len; x++) {
123 pmac->Lr[x] ^= polys[poly].poly_div[x];
124 }
125 }
126
127 /* zero buffer, counters, etc... */
128 pmac->block_index = 1;
129 pmac->cipher_idx = cipher;
130 pmac->buflen = 0;
131 zeromem(pmac->block, sizeof(pmac->block));
132 zeromem(pmac->Li, sizeof(pmac->Li));
133 zeromem(pmac->checksum, sizeof(pmac->checksum));
134 err = CRYPT_OK;
135 error:
136 #ifdef LTC_CLEAN_STACK
137 zeromem(L, pmac->block_len);
138 #endif
139
140 XFREE(L);
141
142 return err;
143 }
144
145 #endif
146
147 /* ref: $Format:%D$ */
148 /* git commit: $Format:%H$ */
149 /* commit time: $Format:%ai$ */
150