~ubuntu-branches/ubuntu/utopic/dropbear/utopic-proposed

« back to all changes in this revision

Viewing changes to libtomcrypt/noekeon.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Johnston
  • Date: 2005-12-08 19:20:21 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051208192021-nyp9rwnt77nsg6ty
Tags: 0.47-1
* New upstream release.
* SECURITY: Fix incorrect buffer sizing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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@iahu.ca, http://libtomcrypt.org
10
 
 */
11
 
/* Implementation of the Noekeon block cipher by Tom St Denis */
12
 
#include "mycrypt.h"
13
 
 
14
 
#ifdef NOEKEON
15
 
 
16
 
const struct _cipher_descriptor noekeon_desc =
17
 
{
18
 
    "noekeon",
19
 
    16,
20
 
    16, 16, 16, 16,
21
 
    &noekeon_setup,
22
 
    &noekeon_ecb_encrypt,
23
 
    &noekeon_ecb_decrypt,
24
 
    &noekeon_test,
25
 
    &noekeon_keysize
26
 
};
27
 
 
28
 
static const ulong32 RC[] = {
29
 
   0x00000080UL, 0x0000001bUL, 0x00000036UL, 0x0000006cUL,
30
 
   0x000000d8UL, 0x000000abUL, 0x0000004dUL, 0x0000009aUL,
31
 
   0x0000002fUL, 0x0000005eUL, 0x000000bcUL, 0x00000063UL,
32
 
   0x000000c6UL, 0x00000097UL, 0x00000035UL, 0x0000006aUL,
33
 
   0x000000d4UL 
34
 
};
35
 
 
36
 
#define kTHETA(a, b, c, d)                                 \
37
 
    temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
38
 
    b ^= temp; d ^= temp;                                  \
39
 
    temp = b^d; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
40
 
    a ^= temp; c ^= temp;
41
 
 
42
 
#define THETA(k, a, b, c, d)                               \
43
 
    temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
44
 
    b ^= temp ^ k[1]; d ^= temp ^ k[3];                    \
45
 
    temp = b^d; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
46
 
    a ^= temp ^ k[0]; c ^= temp ^ k[2];
47
 
    
48
 
#define GAMMA(a, b, c, d)     \
49
 
    b ^= ~(d|c);              \
50
 
    a ^= c&b;                 \
51
 
    temp = d; d = a; a = temp;\
52
 
    c ^= a ^ b ^ d;           \
53
 
    b ^= ~(d|c);              \
54
 
    a ^= c&b;
55
 
    
56
 
#define PI1(a, b, c, d) \
57
 
    a = ROL(a, 1); c = ROL(c, 5); d = ROL(d, 2);
58
 
    
59
 
#define PI2(a, b, c, d) \
60
 
    a = ROR(a, 1); c = ROR(c, 5); d = ROR(d, 2);
61
 
    
62
 
int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
63
 
{
64
 
   ulong32 temp;
65
 
   
66
 
   _ARGCHK(key != NULL);
67
 
   _ARGCHK(skey != NULL);
68
 
   
69
 
   if (keylen != 16) {
70
 
      return CRYPT_INVALID_KEYSIZE;
71
 
   }
72
 
   
73
 
   if (num_rounds != 16 && num_rounds != 0) {
74
 
      return CRYPT_INVALID_ROUNDS;
75
 
   }
76
 
   
77
 
   LOAD32H(skey->noekeon.K[0],&key[0]);
78
 
   LOAD32H(skey->noekeon.K[1],&key[4]);
79
 
   LOAD32H(skey->noekeon.K[2],&key[8]);
80
 
   LOAD32H(skey->noekeon.K[3],&key[12]);
81
 
   
82
 
   LOAD32H(skey->noekeon.dK[0],&key[0]);
83
 
   LOAD32H(skey->noekeon.dK[1],&key[4]);
84
 
   LOAD32H(skey->noekeon.dK[2],&key[8]);
85
 
   LOAD32H(skey->noekeon.dK[3],&key[12]);
86
 
 
87
 
   kTHETA(skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]);
88
 
 
89
 
   return CRYPT_OK;
90
 
}
91
 
 
92
 
#ifdef CLEAN_STACK
93
 
static void _noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
94
 
#else
95
 
void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
96
 
#endif
97
 
{
98
 
   ulong32 a,b,c,d,temp;
99
 
   int r;
100
 
 
101
 
   _ARGCHK(key != NULL);
102
 
   _ARGCHK(pt != NULL);
103
 
   _ARGCHK(ct != NULL);
104
 
   
105
 
   LOAD32H(a,&pt[0]); LOAD32H(b,&pt[4]);
106
 
   LOAD32H(c,&pt[8]); LOAD32H(d,&pt[12]);
107
 
   
108
 
#define ROUND(i) \
109
 
       a ^= RC[i]; \
110
 
       THETA(key->noekeon.K, a,b,c,d); \
111
 
       PI1(a,b,c,d); \
112
 
       GAMMA(a,b,c,d); \
113
 
       PI2(a,b,c,d);
114
 
 
115
 
   for (r = 0; r < 16; ++r) {
116
 
       ROUND(r);
117
 
   }
118
 
 
119
 
#undef ROUND
120
 
 
121
 
   a ^= RC[16];
122
 
   THETA(key->noekeon.K, a, b, c, d);
123
 
   
124
 
   STORE32H(a,&ct[0]); STORE32H(b,&ct[4]);
125
 
   STORE32H(c,&ct[8]); STORE32H(d,&ct[12]);
126
 
}
127
 
 
128
 
#ifdef CLEAN_STACK
129
 
void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
130
 
{
131
 
   _noekeon_ecb_encrypt(pt, ct, key);
132
 
   burn_stack(sizeof(ulong32) * 5 + sizeof(int));
133
 
}
134
 
#endif
135
 
 
136
 
#ifdef CLEAN_STACK
137
 
static void _noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
138
 
#else
139
 
void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
140
 
#endif
141
 
{
142
 
   ulong32 a,b,c,d, temp;
143
 
   int r;
144
 
 
145
 
   _ARGCHK(key != NULL);
146
 
   _ARGCHK(pt != NULL);
147
 
   _ARGCHK(ct != NULL);
148
 
   
149
 
   LOAD32H(a,&ct[0]); LOAD32H(b,&ct[4]);
150
 
   LOAD32H(c,&ct[8]); LOAD32H(d,&ct[12]);
151
 
   
152
 
 
153
 
#define ROUND(i) \
154
 
       THETA(key->noekeon.dK, a,b,c,d); \
155
 
       a ^= RC[i]; \
156
 
       PI1(a,b,c,d); \
157
 
       GAMMA(a,b,c,d); \
158
 
       PI2(a,b,c,d); 
159
 
 
160
 
   for (r = 16; r > 0; --r) {
161
 
       ROUND(r);
162
 
   }
163
 
 
164
 
#undef ROUND
165
 
 
166
 
   THETA(key->noekeon.dK, a,b,c,d);
167
 
   a ^= RC[0];
168
 
   STORE32H(a,&pt[0]); STORE32H(b, &pt[4]);
169
 
   STORE32H(c,&pt[8]); STORE32H(d, &pt[12]);
170
 
}
171
 
 
172
 
#ifdef CLEAN_STACK
173
 
void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
174
 
{
175
 
   _noekeon_ecb_decrypt(ct, pt, key);
176
 
   burn_stack(sizeof(ulong32) * 5 + sizeof(int));
177
 
}
178
 
#endif
179
 
 
180
 
int noekeon_test(void)
181
 
{
182
 
 #ifndef LTC_TEST
183
 
    return CRYPT_NOP;
184
 
 #else
185
 
 static const struct {
186
 
     int keylen;
187
 
     unsigned char key[16], pt[16], ct[16];
188
 
 } tests[] = {
189
 
   {
190
 
      16,
191
 
      { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
192
 
      { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
193
 
      { 0x18, 0xa6, 0xec, 0xe5, 0x28, 0xaa, 0x79, 0x73,
194
 
        0x28, 0xb2, 0xc0, 0x91, 0xa0, 0x2f, 0x54, 0xc5}
195
 
   }
196
 
 };
197
 
 symmetric_key key;
198
 
 unsigned char tmp[2][16];
199
 
 int err, i, y;
200
 
 
201
 
 for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
202
 
    zeromem(&key, sizeof(key));
203
 
    if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { 
204
 
       return err;
205
 
    }
206
 
  
207
 
    noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key);
208
 
    noekeon_ecb_decrypt(tmp[0], tmp[1], &key);
209
 
    if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) { 
210
 
#if 0
211
 
       printf("\n\nTest %d failed\n", i);
212
 
       if (memcmp(tmp[0], tests[i].ct, 16)) {
213
 
          printf("CT: ");
214
 
          for (i = 0; i < 16; i++) {
215
 
             printf("%02x ", tmp[0][i]);
216
 
          }
217
 
          printf("\n");
218
 
       } else {
219
 
          printf("PT: ");
220
 
          for (i = 0; i < 16; i++) {
221
 
             printf("%02x ", tmp[1][i]);
222
 
          }
223
 
          printf("\n");
224
 
       }
225
 
#endif       
226
 
        return CRYPT_FAIL_TESTVECTOR;
227
 
    }
228
 
 
229
 
      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
230
 
      for (y = 0; y < 16; y++) tmp[0][y] = 0;
231
 
      for (y = 0; y < 1000; y++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key);
232
 
      for (y = 0; y < 1000; y++) noekeon_ecb_decrypt(tmp[0], tmp[0], &key);
233
 
      for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
234
 
 }       
235
 
 return CRYPT_OK;
236
 
 #endif
237
 
}
238
 
 
239
 
int noekeon_keysize(int *desired_keysize)
240
 
{
241
 
   _ARGCHK(desired_keysize != NULL);
242
 
   if (*desired_keysize < 16) {
243
 
      return CRYPT_INVALID_KEYSIZE;
244
 
   } else {
245
 
      *desired_keysize = 16;
246
 
      return CRYPT_OK;
247
 
   }
248
 
}
249
 
 
250
 
#endif
251