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 ccm_memory.c
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  CCM support, process a block of memory, Tom St Denis
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef CCM_MODE
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   CCM encrypt/decrypt and produce an authentication tag
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param cipher     The index of the cipher desired
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param key        The secret key to use
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param keylen     The length of the secret key (octets)
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param uskey      A previously scheduled key [optional can be NULL]
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param nonce      The session nonce [use once]
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param noncelen   The length of the nonce
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param header     The header for the session
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param headerlen  The length of the header (octets)
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param pt         [out] The plaintext
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param ptlen      The length of the plaintext (octets)
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param ct         [out] The ciphertext
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param tag        [out] The destination tag
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param taglen     [in/out] The max size and resulting size of the authentication tag
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param direction  Encrypt or Decrypt direction (0 or 1)
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @return CRYPT_OK if successful
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint ccm_memory(int cipher,
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    const unsigned char *key,    unsigned long keylen,
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    symmetric_key       *uskey,
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    const unsigned char *nonce,  unsigned long noncelen,
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    const unsigned char *header, unsigned long headerlen,
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          unsigned char *pt,     unsigned long ptlen,
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          unsigned char *ct,
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          unsigned char *tag,    unsigned long *taglen,
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    int  direction)
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned char  PAD[16], ctr[16], CTRPAD[16], b;
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   symmetric_key *skey;
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int            err;
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned long  len, L, x, y, z, CTRlen;
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (uskey == NULL) {
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      LTC_ARGCHK(key    != NULL);
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(nonce  != NULL);
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (headerlen > 0) {
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      LTC_ARGCHK(header != NULL);
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(pt     != NULL);
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(ct     != NULL);
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(tag    != NULL);
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(taglen != NULL);
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_FAST
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (16 % sizeof(LTC_FAST_TYPE)) {
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_ARG;
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* check cipher input */
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return err;
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (cipher_descriptor[cipher].block_length != 16) {
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_CIPHER;
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* make sure the taglen is even and <= 16 */
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   *taglen &= ~1;
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (*taglen > 16) {
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      *taglen = 16;
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* can't use < 4 */
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (*taglen < 4) {
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_ARG;
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* is there an accelerator? */
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (cipher_descriptor[cipher].accel_ccm_memory != NULL) {
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return cipher_descriptor[cipher].accel_ccm_memory(
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           key,    keylen,
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           uskey,
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           nonce,  noncelen,
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           header, headerlen,
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           pt,     ptlen,
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           ct,
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           tag,    taglen,
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           direction);
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* let's get the L value */
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   len = ptlen;
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   L   = 0;
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   while (len) {
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      ++L;
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      len >>= 8;
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (L <= 1) {
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      L = 2;
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* increase L to match the nonce len */
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   noncelen = (noncelen > 13) ? 13 : noncelen;
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((15 - noncelen) > L) {
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      L = 15 - noncelen;
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* decrease noncelen to match L */
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((noncelen + L) > 15) {
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      noncelen = 15 - L;
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* allocate mem for the symmetric key */
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (uskey == NULL) {
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      skey = XMALLOC(sizeof(*skey));
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if (skey == NULL) {
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         return CRYPT_MEM;
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* initialize the cipher */
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) {
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         XFREE(skey);
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         return err;
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } else {
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      skey = uskey;
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* form B_0 == flags | Nonce N | l(m) */
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   x = 0;
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) |
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            (((*taglen - 2)>>1)<<3)        |
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            (L-1));
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* nonce */
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (y = 0; y < (16 - (L + 1)); y++) {
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       PAD[x++] = nonce[y];
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* store len */
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   len = ptlen;
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* shift len so the upper bytes of len are the contents of the length */
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (y = L; y < 4; y++) {
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       len <<= 8;
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* store l(m) (only store 32-bits) */
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (y = 0; L > 4 && (L-y)>4; y++) {
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       PAD[x++] = 0;
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (; y < L; y++) {
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       PAD[x++] = (unsigned char)((len >> 24) & 255);
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       len <<= 8;
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* encrypt PAD */
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       goto error;
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* handle header */
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (headerlen > 0) {
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      x = 0;
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* store length */
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if (headerlen < ((1UL<<16) - (1UL<<8))) {
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= (headerlen>>8) & 255;
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= headerlen & 255;
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      } else {
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= 0xFF;
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= 0xFE;
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= (headerlen>>24) & 255;
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= (headerlen>>16) & 255;
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= (headerlen>>8) & 255;
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         PAD[x++] ^= headerlen & 255;
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* now add the data */
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < headerlen; y++) {
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          if (x == 16) {
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             /* full block so let's encrypt it */
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                goto error;
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             }
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             x = 0;
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          }
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          PAD[x++] ^= header[y];
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* remainder? */
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if (x != 0) {
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            goto error;
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         }
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* setup the ctr counter */
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   x = 0;
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* flags */
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   ctr[x++] = (unsigned char)L-1;
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* nonce */
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (y = 0; y < (16 - (L+1)); ++y) {
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      ctr[x++] = nonce[y];
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* offset */
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   while (x < 16) {
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      ctr[x++] = 0;
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   x      = 0;
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   CTRlen = 16;
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* now handle the PT */
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (ptlen > 0) {
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      y = 0;
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_FAST
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if (ptlen & ~15)  {
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          if (direction == CCM_ENCRYPT) {
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             for (; y < (ptlen & ~15); y += 16) {
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                /* increment the ctr? */
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                for (z = 15; z > 15-L; z--) {
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    ctr[z] = (ctr[z] + 1) & 255;
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    if (ctr[z]) break;
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                   goto error;
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                /* xor the PT against the pad first */
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    *((LTC_FAST_TYPE*)(&PAD[z]))  ^= *((LTC_FAST_TYPE*)(&pt[y+z]));
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    *((LTC_FAST_TYPE*)(&ct[y+z])) = *((LTC_FAST_TYPE*)(&pt[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z]));
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                   goto error;
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             }
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         } else {
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             for (; y < (ptlen & ~15); y += 16) {
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                /* increment the ctr? */
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                for (z = 15; z > 15-L; z--) {
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    ctr[z] = (ctr[z] + 1) & 255;
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    if (ctr[z]) break;
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                   goto error;
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                /* xor the PT against the pad last */
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) {
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    *((LTC_FAST_TYPE*)(&pt[y+z])) = *((LTC_FAST_TYPE*)(&ct[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z]));
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                    *((LTC_FAST_TYPE*)(&PAD[z]))  ^= *((LTC_FAST_TYPE*)(&pt[y+z]));
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                   goto error;
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                }
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             }
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         }
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     }
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (; y < ptlen; y++) {
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          /* increment the ctr? */
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          if (CTRlen == 16) {
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             for (z = 15; z > 15-L; z--) {
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                 ctr[z] = (ctr[z] + 1) & 255;
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                 if (ctr[z]) break;
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             }
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                goto error;
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             }
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             CTRlen = 0;
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          }
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          /* if we encrypt we add the bytes to the MAC first */
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          if (direction == CCM_ENCRYPT) {
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             b     = pt[y];
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             ct[y] = b ^ CTRPAD[CTRlen++];
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          } else {
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             b     = ct[y] ^ CTRPAD[CTRlen++];
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             pt[y] = b;
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          }
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          if (x == 16) {
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                goto error;
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             }
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project             x = 0;
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          }
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          PAD[x++] ^= b;
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if (x != 0) {
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) {
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            goto error;
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         }
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* setup CTR for the TAG (zero the count) */
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (y = 15; y > 15 - L; y--) {
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      ctr[y] = 0x00;
319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) {
321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      goto error;
322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (skey != uskey) {
325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      cipher_descriptor[cipher].done(skey);
326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   /* store the TAG */
329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (x = 0; x < 16 && x < *taglen; x++) {
330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       tag[x] = PAD[x] ^ CTRPAD[x];
331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   *taglen = x;
333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   zeromem(skey,   sizeof(*skey));
336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   zeromem(PAD,    sizeof(PAD));
337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   zeromem(CTRPAD, sizeof(CTRPAD));
338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projecterror:
340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (skey != uskey) {
341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      XFREE(skey);
342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return err;
345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ccm/ccm_memory.c,v $ */
350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.18 $ */
351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/12/04 21:34:03 $ */
352