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