3
|
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis |
|
2 * |
|
3 * LibTomCrypt is a library that provides various cryptographic |
|
4 * algorithms in a highly modular and flexible manner. |
|
5 * |
|
6 * The library is free for all purposes without any express |
|
7 * guarantee it works. |
|
8 * |
|
9 * Tom St Denis, [email protected], http://libtomcrypt.org |
|
10 */ |
|
11 |
|
12 /* PMAC implementation by Tom St Denis */ |
|
13 #include "mycrypt.h" |
|
14 |
|
15 #ifdef PMAC |
|
16 |
|
17 static const struct { |
|
18 int len; |
|
19 unsigned char poly_div[MAXBLOCKSIZE], |
|
20 poly_mul[MAXBLOCKSIZE]; |
|
21 } polys[] = { |
|
22 { |
|
23 8, |
|
24 { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, |
|
25 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } |
|
26 }, { |
|
27 16, |
|
28 { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, |
|
30 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } |
|
32 } |
|
33 }; |
|
34 |
|
35 int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen) |
|
36 { |
|
37 int poly, x, y, m, err; |
|
38 unsigned char L[MAXBLOCKSIZE]; |
|
39 |
|
40 _ARGCHK(pmac != NULL); |
|
41 _ARGCHK(key != NULL); |
|
42 |
|
43 /* valid cipher? */ |
|
44 if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { |
|
45 return err; |
|
46 } |
|
47 |
|
48 /* determine which polys to use */ |
|
49 pmac->block_len = cipher_descriptor[cipher].block_length; |
|
50 for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { |
|
51 if (polys[poly].len == pmac->block_len) { |
|
52 break; |
|
53 } |
|
54 } |
|
55 if (polys[poly].len != pmac->block_len) { |
|
56 return CRYPT_INVALID_ARG; |
|
57 } |
|
58 |
|
59 /* schedule the key */ |
|
60 if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) { |
|
61 return err; |
|
62 } |
|
63 |
|
64 /* find L = E[0] */ |
|
65 zeromem(L, pmac->block_len); |
|
66 cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key); |
|
67 |
|
68 /* find Ls[i] = L << i for i == 0..31 */ |
|
69 memcpy(pmac->Ls[0], L, pmac->block_len); |
|
70 for (x = 1; x < 32; x++) { |
|
71 m = pmac->Ls[x-1][0] >> 7; |
|
72 for (y = 0; y < pmac->block_len-1; y++) { |
|
73 pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255; |
|
74 } |
|
75 pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255; |
|
76 |
|
77 if (m == 1) { |
|
78 for (y = 0; y < pmac->block_len; y++) { |
|
79 pmac->Ls[x][y] ^= polys[poly].poly_mul[y]; |
|
80 } |
|
81 } |
|
82 } |
|
83 |
|
84 /* find Lr = L / x */ |
|
85 m = L[pmac->block_len-1] & 1; |
|
86 |
|
87 /* shift right */ |
|
88 for (x = pmac->block_len - 1; x > 0; x--) { |
|
89 pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255; |
|
90 } |
|
91 pmac->Lr[0] = L[0] >> 1; |
|
92 |
|
93 if (m == 1) { |
|
94 for (x = 0; x < pmac->block_len; x++) { |
|
95 pmac->Lr[x] ^= polys[poly].poly_div[x]; |
|
96 } |
|
97 } |
|
98 |
|
99 /* zero buffer, counters, etc... */ |
|
100 pmac->block_index = 1; |
|
101 pmac->cipher_idx = cipher; |
|
102 pmac->buflen = 0; |
|
103 zeromem(pmac->block, sizeof(pmac->block)); |
|
104 zeromem(pmac->Li, sizeof(pmac->Li)); |
|
105 zeromem(pmac->checksum, sizeof(pmac->checksum)); |
|
106 |
|
107 #ifdef CLEAN_STACK |
|
108 zeromem(L, sizeof(L)); |
|
109 #endif |
|
110 |
|
111 return CRYPT_OK; |
|
112 } |
|
113 |
|
114 #endif |