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