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 /* OCB Implementation by Tom St Denis */ |
|
13 #include "mycrypt.h" |
|
14 |
|
15 #ifdef OCB_MODE |
|
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 ocb_init(ocb_state *ocb, int cipher, |
|
36 const unsigned char *key, unsigned long keylen, const unsigned char *nonce) |
|
37 { |
|
38 int poly, x, y, m, err; |
|
39 |
|
40 _ARGCHK(ocb != NULL); |
|
41 _ARGCHK(key != NULL); |
|
42 _ARGCHK(nonce != NULL); |
|
43 |
|
44 /* valid cipher? */ |
|
45 if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { |
|
46 return err; |
|
47 } |
|
48 |
|
49 /* determine which polys to use */ |
|
50 ocb->block_len = cipher_descriptor[cipher].block_length; |
|
51 for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { |
|
52 if (polys[poly].len == ocb->block_len) { |
|
53 break; |
|
54 } |
|
55 } |
|
56 if (polys[poly].len != ocb->block_len) { |
|
57 return CRYPT_INVALID_ARG; |
|
58 } |
|
59 |
|
60 /* schedule the key */ |
|
61 if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { |
|
62 return err; |
|
63 } |
|
64 |
|
65 /* find L = E[0] */ |
|
66 zeromem(ocb->L, ocb->block_len); |
|
67 cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key); |
|
68 |
|
69 /* find R = E[N xor L] */ |
|
70 for (x = 0; x < ocb->block_len; x++) { |
|
71 ocb->R[x] = ocb->L[x] ^ nonce[x]; |
|
72 } |
|
73 cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key); |
|
74 |
|
75 /* find Ls[i] = L << i for i == 0..31 */ |
|
76 memcpy(ocb->Ls[0], ocb->L, ocb->block_len); |
|
77 for (x = 1; x < 32; x++) { |
|
78 m = ocb->Ls[x-1][0] >> 7; |
|
79 for (y = 0; y < ocb->block_len-1; y++) { |
|
80 ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255; |
|
81 } |
|
82 ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255; |
|
83 |
|
84 if (m == 1) { |
|
85 for (y = 0; y < ocb->block_len; y++) { |
|
86 ocb->Ls[x][y] ^= polys[poly].poly_mul[y]; |
|
87 } |
|
88 } |
|
89 } |
|
90 |
|
91 /* find Lr = L / x */ |
|
92 m = ocb->L[ocb->block_len-1] & 1; |
|
93 |
|
94 /* shift right */ |
|
95 for (x = ocb->block_len - 1; x > 0; x--) { |
|
96 ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255; |
|
97 } |
|
98 ocb->Lr[0] = ocb->L[0] >> 1; |
|
99 |
|
100 if (m == 1) { |
|
101 for (x = 0; x < ocb->block_len; x++) { |
|
102 ocb->Lr[x] ^= polys[poly].poly_div[x]; |
|
103 } |
|
104 } |
|
105 |
|
106 /* set Li, checksum */ |
|
107 zeromem(ocb->Li, ocb->block_len); |
|
108 zeromem(ocb->checksum, ocb->block_len); |
|
109 |
|
110 /* set other params */ |
|
111 ocb->block_index = 1; |
|
112 ocb->cipher = cipher; |
|
113 |
|
114 return CRYPT_OK; |
|
115 } |
|
116 |
|
117 #endif |