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