~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to aes_wrap.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * AES-based functions
 
3
 *
 
4
 * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
 
5
 * - One-Key CBC MAC (OMAC1) hash with AES-128
 
6
 * - AES-128 CTR mode encryption
 
7
 * - AES-128 EAX mode encryption/decryption
 
8
 * - AES-128 CBC
 
9
 *
 
10
 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
 
11
 *
 
12
 * This program is free software; you can redistribute it and/or modify
 
13
 * it under the terms of the GNU General Public License version 2 as
 
14
 * published by the Free Software Foundation.
 
15
 *
 
16
 * Alternatively, this software may be distributed under the terms of BSD
 
17
 * license.
 
18
 *
 
19
 * See README and COPYING for more details.
 
20
 */
 
21
 
 
22
#include "includes.h"
 
23
 
 
24
#include "common.h"
 
25
#include "aes_wrap.h"
 
26
#include "crypto.h"
 
27
 
 
28
#ifdef INTERNAL_AES
 
29
#include "aes.c"
 
30
#endif /* INTERNAL_AES */
 
31
 
 
32
 
 
33
#ifndef CONFIG_NO_AES_WRAP
 
34
 
 
35
/**
 
36
 * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
 
37
 * @kek: Key encryption key (KEK)
 
38
 * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
 
39
 * @plain: Plaintext key to be wrapped, n * 64 bit
 
40
 * @cipher: Wrapped key, (n + 1) * 64 bit
 
41
 * Returns: 0 on success, -1 on failure
 
42
 */
 
43
int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
 
44
{
 
45
        u8 *a, *r, b[16];
 
46
        int i, j;
 
47
        void *ctx;
 
48
 
 
49
        a = cipher;
 
50
        r = cipher + 8;
 
51
 
 
52
        /* 1) Initialize variables. */
 
53
        os_memset(a, 0xa6, 8);
 
54
        os_memcpy(r, plain, 8 * n);
 
55
 
 
56
        ctx = aes_encrypt_init(kek, 16);
 
57
        if (ctx == NULL)
 
58
                return -1;
 
59
 
 
60
        /* 2) Calculate intermediate values.
 
61
         * For j = 0 to 5
 
62
         *     For i=1 to n
 
63
         *         B = AES(K, A | R[i])
 
64
         *         A = MSB(64, B) ^ t where t = (n*j)+i
 
65
         *         R[i] = LSB(64, B)
 
66
         */
 
67
        for (j = 0; j <= 5; j++) {
 
68
                r = cipher + 8;
 
69
                for (i = 1; i <= n; i++) {
 
70
                        os_memcpy(b, a, 8);
 
71
                        os_memcpy(b + 8, r, 8);
 
72
                        aes_encrypt(ctx, b, b);
 
73
                        os_memcpy(a, b, 8);
 
74
                        a[7] ^= n * j + i;
 
75
                        os_memcpy(r, b + 8, 8);
 
76
                        r += 8;
 
77
                }
 
78
        }
 
79
        aes_encrypt_deinit(ctx);
 
80
 
 
81
        /* 3) Output the results.
 
82
         *
 
83
         * These are already in @cipher due to the location of temporary
 
84
         * variables.
 
85
         */
 
86
 
 
87
        return 0;
 
88
}
 
89
 
 
90
#endif /* CONFIG_NO_AES_WRAP */
 
91
 
 
92
 
 
93
/**
 
94
 * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
 
95
 * @kek: Key encryption key (KEK)
 
96
 * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
 
97
 * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bit
 
98
 * @plain: Plaintext key, n * 64 bit
 
99
 * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
 
100
 */
 
101
int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
 
102
{
 
103
        u8 a[8], *r, b[16];
 
104
        int i, j;
 
105
        void *ctx;
 
106
 
 
107
        /* 1) Initialize variables. */
 
108
        os_memcpy(a, cipher, 8);
 
109
        r = plain;
 
110
        os_memcpy(r, cipher + 8, 8 * n);
 
111
 
 
112
        ctx = aes_decrypt_init(kek, 16);
 
113
        if (ctx == NULL)
 
114
                return -1;
 
115
 
 
116
        /* 2) Compute intermediate values.
 
117
         * For j = 5 to 0
 
118
         *     For i = n to 1
 
119
         *         B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
 
120
         *         A = MSB(64, B)
 
121
         *         R[i] = LSB(64, B)
 
122
         */
 
123
        for (j = 5; j >= 0; j--) {
 
124
                r = plain + (n - 1) * 8;
 
125
                for (i = n; i >= 1; i--) {
 
126
                        os_memcpy(b, a, 8);
 
127
                        b[7] ^= n * j + i;
 
128
 
 
129
                        os_memcpy(b + 8, r, 8);
 
130
                        aes_decrypt(ctx, b, b);
 
131
                        os_memcpy(a, b, 8);
 
132
                        os_memcpy(r, b + 8, 8);
 
133
                        r -= 8;
 
134
                }
 
135
        }
 
136
        aes_decrypt_deinit(ctx);
 
137
 
 
138
        /* 3) Output results.
 
139
         *
 
140
         * These are already in @plain due to the location of temporary
 
141
         * variables. Just verify that the IV matches with the expected value.
 
142
         */
 
143
        for (i = 0; i < 8; i++) {
 
144
                if (a[i] != 0xa6)
 
145
                        return -1;
 
146
        }
 
147
 
 
148
        return 0;
 
149
}
 
150
 
 
151
 
 
152
#define BLOCK_SIZE 16
 
153
 
 
154
#ifndef CONFIG_NO_AES_OMAC1
 
155
 
 
156
static void gf_mulx(u8 *pad)
 
157
{
 
158
        int i, carry;
 
159
 
 
160
        carry = pad[0] & 0x80;
 
161
        for (i = 0; i < BLOCK_SIZE - 1; i++)
 
162
                pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
 
163
        pad[BLOCK_SIZE - 1] <<= 1;
 
164
        if (carry)
 
165
                pad[BLOCK_SIZE - 1] ^= 0x87;
 
166
}
 
167
 
 
168
 
 
169
/**
 
170
 * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
 
171
 * @key: 128-bit key for the hash operation
 
172
 * @data: Data buffer for which a MAC is determined
 
173
 * @data: Length of data buffer in bytes
 
174
 * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
 
175
 * Returns: 0 on success, -1 on failure
 
176
 */
 
177
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
 
178
{
 
179
        void *ctx;
 
180
        u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE];
 
181
        const u8 *pos = data;
 
182
        size_t i, left = data_len;
 
183
 
 
184
        ctx = aes_encrypt_init(key, 16);
 
185
        if (ctx == NULL)
 
186
                return -1;
 
187
        os_memset(cbc, 0, BLOCK_SIZE);
 
188
 
 
189
        while (left >= BLOCK_SIZE) {
 
190
                for (i = 0; i < BLOCK_SIZE; i++)
 
191
                        cbc[i] ^= *pos++;
 
192
                if (left > BLOCK_SIZE)
 
193
                        aes_encrypt(ctx, cbc, cbc);
 
194
                left -= BLOCK_SIZE;
 
195
        }
 
196
 
 
197
        os_memset(pad, 0, BLOCK_SIZE);
 
198
        aes_encrypt(ctx, pad, pad);
 
199
        gf_mulx(pad);
 
200
 
 
201
        if (left || data_len == 0) {
 
202
                for (i = 0; i < left; i++)
 
203
                        cbc[i] ^= *pos++;
 
204
                cbc[left] ^= 0x80;
 
205
                gf_mulx(pad);
 
206
        }
 
207
 
 
208
        for (i = 0; i < BLOCK_SIZE; i++)
 
209
                pad[i] ^= cbc[i];
 
210
        aes_encrypt(ctx, pad, mac);
 
211
        aes_encrypt_deinit(ctx);
 
212
        return 0;
 
213
}
 
214
 
 
215
#endif /* CONFIG_NO_AES_OMAC1 */
 
216
 
 
217
 
 
218
/**
 
219
 * aes_128_encrypt_block - Perform one AES 128-bit block operation
 
220
 * @key: Key for AES
 
221
 * @in: Input data (16 bytes)
 
222
 * @out: Output of the AES block operation (16 bytes)
 
223
 * Returns: 0 on success, -1 on failure
 
224
 */
 
225
int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
 
226
{
 
227
        void *ctx;
 
228
        ctx = aes_encrypt_init(key, 16);
 
229
        if (ctx == NULL)
 
230
                return -1;
 
231
        aes_encrypt(ctx, in, out);
 
232
        aes_encrypt_deinit(ctx);
 
233
        return 0;
 
234
}
 
235
 
 
236
 
 
237
#ifndef CONFIG_NO_AES_CTR
 
238
 
 
239
/**
 
240
 * aes_128_ctr_encrypt - AES-128 CTR mode encryption
 
241
 * @key: Key for encryption (16 bytes)
 
242
 * @nonce: Nonce for counter mode (16 bytes)
 
243
 * @data: Data to encrypt in-place
 
244
 * @data_len: Length of data in bytes
 
245
 * Returns: 0 on success, -1 on failure
 
246
 */
 
247
int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
 
248
                        u8 *data, size_t data_len)
 
249
{
 
250
        void *ctx;
 
251
        size_t j, len, left = data_len;
 
252
        int i;
 
253
        u8 *pos = data;
 
254
        u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE];
 
255
 
 
256
        ctx = aes_encrypt_init(key, 16);
 
257
        if (ctx == NULL)
 
258
                return -1;
 
259
        os_memcpy(counter, nonce, BLOCK_SIZE);
 
260
 
 
261
        while (left > 0) {
 
262
                aes_encrypt(ctx, counter, buf);
 
263
 
 
264
                len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE;
 
265
                for (j = 0; j < len; j++)
 
266
                        pos[j] ^= buf[j];
 
267
                pos += len;
 
268
                left -= len;
 
269
 
 
270
                for (i = BLOCK_SIZE - 1; i >= 0; i--) {
 
271
                        counter[i]++;
 
272
                        if (counter[i])
 
273
                                break;
 
274
                }
 
275
        }
 
276
        aes_encrypt_deinit(ctx);
 
277
        return 0;
 
278
}
 
279
 
 
280
#endif /* CONFIG_NO_AES_CTR */
 
281
 
 
282
 
 
283
#ifndef CONFIG_NO_AES_EAX
 
284
 
 
285
/**
 
286
 * aes_128_eax_encrypt - AES-128 EAX mode encryption
 
287
 * @key: Key for encryption (16 bytes)
 
288
 * @nonce: Nonce for counter mode
 
289
 * @nonce_len: Nonce length in bytes
 
290
 * @hdr: Header data to be authenticity protected
 
291
 * @hdr_len: Length of the header data bytes
 
292
 * @data: Data to encrypt in-place
 
293
 * @data_len: Length of data in bytes
 
294
 * @tag: 16-byte tag value
 
295
 * Returns: 0 on success, -1 on failure
 
296
 */
 
297
int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
 
298
                        const u8 *hdr, size_t hdr_len,
 
299
                        u8 *data, size_t data_len, u8 *tag)
 
300
{
 
301
        u8 *buf;
 
302
        size_t buf_len;
 
303
        u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE];
 
304
        int i;
 
305
 
 
306
        if (nonce_len > data_len)
 
307
                buf_len = nonce_len;
 
308
        else
 
309
                buf_len = data_len;
 
310
        if (hdr_len > buf_len)
 
311
                buf_len = hdr_len;
 
312
        buf_len += 16;
 
313
 
 
314
        buf = os_malloc(buf_len);
 
315
        if (buf == NULL)
 
316
                return -1;
 
317
 
 
318
        os_memset(buf, 0, 15);
 
319
 
 
320
        buf[15] = 0;
 
321
        os_memcpy(buf + 16, nonce, nonce_len);
 
322
        omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
 
323
 
 
324
        buf[15] = 1;
 
325
        os_memcpy(buf + 16, hdr, hdr_len);
 
326
        omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
 
327
 
 
328
        aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
 
329
        buf[15] = 2;
 
330
        os_memcpy(buf + 16, data, data_len);
 
331
        omac1_aes_128(key, buf, 16 + data_len, data_mac);
 
332
 
 
333
        os_free(buf);
 
334
 
 
335
        for (i = 0; i < BLOCK_SIZE; i++)
 
336
                tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
 
337
 
 
338
        return 0;
 
339
}
 
340
 
 
341
 
 
342
/**
 
343
 * aes_128_eax_decrypt - AES-128 EAX mode decryption
 
344
 * @key: Key for decryption (16 bytes)
 
345
 * @nonce: Nonce for counter mode
 
346
 * @nonce_len: Nonce length in bytes
 
347
 * @hdr: Header data to be authenticity protected
 
348
 * @hdr_len: Length of the header data bytes
 
349
 * @data: Data to encrypt in-place
 
350
 * @data_len: Length of data in bytes
 
351
 * @tag: 16-byte tag value
 
352
 * Returns: 0 on success, -1 on failure, -2 if tag does not match
 
353
 */
 
354
int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
 
355
                        const u8 *hdr, size_t hdr_len,
 
356
                        u8 *data, size_t data_len, const u8 *tag)
 
357
{
 
358
        u8 *buf;
 
359
        size_t buf_len;
 
360
        u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE];
 
361
        int i;
 
362
 
 
363
        if (nonce_len > data_len)
 
364
                buf_len = nonce_len;
 
365
        else
 
366
                buf_len = data_len;
 
367
        if (hdr_len > buf_len)
 
368
                buf_len = hdr_len;
 
369
        buf_len += 16;
 
370
 
 
371
        buf = os_malloc(buf_len);
 
372
        if (buf == NULL)
 
373
                return -1;
 
374
 
 
375
        os_memset(buf, 0, 15);
 
376
 
 
377
        buf[15] = 0;
 
378
        os_memcpy(buf + 16, nonce, nonce_len);
 
379
        omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
 
380
 
 
381
        buf[15] = 1;
 
382
        os_memcpy(buf + 16, hdr, hdr_len);
 
383
        omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
 
384
 
 
385
        buf[15] = 2;
 
386
        os_memcpy(buf + 16, data, data_len);
 
387
        omac1_aes_128(key, buf, 16 + data_len, data_mac);
 
388
 
 
389
        os_free(buf);
 
390
 
 
391
        for (i = 0; i < BLOCK_SIZE; i++) {
 
392
                if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
 
393
                        return -2;
 
394
        }
 
395
 
 
396
        aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
 
397
 
 
398
        return 0;
 
399
}
 
400
 
 
401
#endif /* CONFIG_NO_AES_EAX */
 
402
 
 
403
 
 
404
#ifndef CONFIG_NO_AES_CBC
 
405
 
 
406
/**
 
407
 * aes_128_cbc_encrypt - AES-128 CBC encryption
 
408
 * @key: Encryption key
 
409
 * @iv: Encryption IV for CBC mode (16 bytes)
 
410
 * @data: Data to encrypt in-place
 
411
 * @data_len: Length of data in bytes (must be divisible by 16)
 
412
 * Returns: 0 on success, -1 on failure
 
413
 */
 
414
int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
 
415
{
 
416
        void *ctx;
 
417
        u8 cbc[BLOCK_SIZE];
 
418
        u8 *pos = data;
 
419
        int i, j, blocks;
 
420
 
 
421
        ctx = aes_encrypt_init(key, 16);
 
422
        if (ctx == NULL)
 
423
                return -1;
 
424
        os_memcpy(cbc, iv, BLOCK_SIZE);
 
425
 
 
426
        blocks = data_len / BLOCK_SIZE;
 
427
        for (i = 0; i < blocks; i++) {
 
428
                for (j = 0; j < BLOCK_SIZE; j++)
 
429
                        cbc[j] ^= pos[j];
 
430
                aes_encrypt(ctx, cbc, cbc);
 
431
                os_memcpy(pos, cbc, BLOCK_SIZE);
 
432
                pos += BLOCK_SIZE;
 
433
        }
 
434
        aes_encrypt_deinit(ctx);
 
435
        return 0;
 
436
}
 
437
 
 
438
 
 
439
/**
 
440
 * aes_128_cbc_decrypt - AES-128 CBC decryption
 
441
 * @key: Decryption key
 
442
 * @iv: Decryption IV for CBC mode (16 bytes)
 
443
 * @data: Data to decrypt in-place
 
444
 * @data_len: Length of data in bytes (must be divisible by 16)
 
445
 * Returns: 0 on success, -1 on failure
 
446
 */
 
447
int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
 
448
{
 
449
        void *ctx;
 
450
        u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE];
 
451
        u8 *pos = data;
 
452
        int i, j, blocks;
 
453
 
 
454
        ctx = aes_decrypt_init(key, 16);
 
455
        if (ctx == NULL)
 
456
                return -1;
 
457
        os_memcpy(cbc, iv, BLOCK_SIZE);
 
458
 
 
459
        blocks = data_len / BLOCK_SIZE;
 
460
        for (i = 0; i < blocks; i++) {
 
461
                os_memcpy(tmp, pos, BLOCK_SIZE);
 
462
                aes_decrypt(ctx, pos, pos);
 
463
                for (j = 0; j < BLOCK_SIZE; j++)
 
464
                        pos[j] ^= cbc[j];
 
465
                os_memcpy(cbc, tmp, BLOCK_SIZE);
 
466
                pos += BLOCK_SIZE;
 
467
        }
 
468
        aes_decrypt_deinit(ctx);
 
469
        return 0;
 
470
}
 
471
 
 
472
#endif /* CONFIG_NO_AES_CBC */