• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 */
pmac_init(pmac_state * pmac,int cipher,const unsigned char * key,unsigned long keylen)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