2 * SHA1 hash implementation and interface functions
3 * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
26 * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104)
27 * @key: Key for HMAC operations
28 * @key_len: Length of the key in bytes
29 * @num_elem: Number of elements in the data vector
30 * @addr: Pointers to the data areas
31 * @len: Lengths of the data blocks
32 * @mac: Buffer for the hash (20 bytes)
34 void hmac_sha1_vector(const u8
*key
, size_t key_len
, size_t num_elem
,
35 const u8
*addr
[], const size_t *len
, u8
*mac
)
37 unsigned char k_pad
[64]; /* padding - key XORd with ipad/opad */
45 * Fixed limit on the number of fragments to avoid having to
46 * allocate memory (which could fail).
51 /* if key is longer than 64 bytes reset it to key = SHA1(key) */
53 sha1_vector(1, &key
, &key_len
, tk
);
58 /* the HMAC_SHA1 transform looks like:
60 * SHA1(K XOR opad, SHA1(K XOR ipad, text))
62 * where K is an n byte key
63 * ipad is the byte 0x36 repeated 64 times
64 * opad is the byte 0x5c repeated 64 times
65 * and text is the data being protected */
67 /* start out by storing key in ipad */
68 memset(k_pad
, 0, sizeof(k_pad
));
69 memcpy(k_pad
, key
, key_len
);
70 /* XOR key with ipad values */
71 for (i
= 0; i
< 64; i
++)
74 /* perform inner SHA1 */
77 for (i
= 0; i
< num_elem
; i
++) {
78 _addr
[i
+ 1] = addr
[i
];
81 sha1_vector(1 + num_elem
, _addr
, _len
, mac
);
83 memset(k_pad
, 0, sizeof(k_pad
));
84 memcpy(k_pad
, key
, key_len
);
85 /* XOR key with opad values */
86 for (i
= 0; i
< 64; i
++)
89 /* perform outer SHA1 */
93 _len
[1] = SHA1_MAC_LEN
;
94 sha1_vector(2, _addr
, _len
, mac
);
99 * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104)
100 * @key: Key for HMAC operations
101 * @key_len: Length of the key in bytes
102 * @data: Pointers to the data area
103 * @data_len: Length of the data area
104 * @mac: Buffer for the hash (20 bytes)
106 void hmac_sha1(const u8
*key
, size_t key_len
, const u8
*data
, size_t data_len
,
109 hmac_sha1_vector(key
, key_len
, 1, &data
, &data_len
, mac
);
114 * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1)
116 * @key_len: Length of the key in bytes
117 * @label: A unique label for each purpose of the PRF
118 * @data: Extra data to bind into the key
119 * @data_len: Length of the data
120 * @buf: Buffer for the generated pseudo-random key
121 * @buf_len: Number of bytes of key to generate
123 * This function is used to derive new, cryptographically separate keys from a
124 * given key (e.g., PMK in IEEE 802.11i).
126 void sha1_prf(const u8
*key
, size_t key_len
, const char *label
,
127 const u8
*data
, size_t data_len
, u8
*buf
, size_t buf_len
)
129 u8 zero
= 0, counter
= 0;
131 u8 hash
[SHA1_MAC_LEN
];
132 size_t label_len
= strlen(label
);
133 const unsigned char *addr
[4];
136 addr
[0] = (u8
*) label
;
146 while (pos
< buf_len
) {
147 plen
= buf_len
- pos
;
148 if (plen
>= SHA1_MAC_LEN
) {
149 hmac_sha1_vector(key
, key_len
, 4, addr
, len
,
153 hmac_sha1_vector(key
, key_len
, 4, addr
, len
,
155 memcpy(&buf
[pos
], hash
, plen
);
164 * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF)
166 * @key_len: Length of the key in bytes
167 * @label: A unique label for each purpose of the PRF
168 * @seed: Seed value to bind into the key
169 * @seed_len: Length of the seed
170 * @buf: Buffer for the generated pseudo-random key
171 * @buf_len: Number of bytes of key to generate
173 * This function is used to derive new, cryptographically separate keys from a
174 * given key for EAP-FAST. T-PRF is defined in
175 * draft-cam-winget-eap-fast-02.txt, Appendix B.
177 void sha1_t_prf(const u8
*key
, size_t key_len
, const char *label
,
178 const u8
*seed
, size_t seed_len
, u8
*buf
, size_t buf_len
)
180 unsigned char counter
= 0;
182 u8 hash
[SHA1_MAC_LEN
];
183 size_t label_len
= strlen(label
);
185 const unsigned char *addr
[5];
190 addr
[1] = (unsigned char *) label
;
191 len
[1] = label_len
+ 1;
194 addr
[3] = output_len
;
199 output_len
[0] = (buf_len
>> 8) & 0xff;
200 output_len
[1] = buf_len
& 0xff;
202 while (pos
< buf_len
) {
204 plen
= buf_len
- pos
;
205 hmac_sha1_vector(key
, key_len
, 5, addr
, len
, hash
);
206 if (plen
>= SHA1_MAC_LEN
) {
207 memcpy(&buf
[pos
], hash
, SHA1_MAC_LEN
);
210 memcpy(&buf
[pos
], hash
, plen
);
213 len
[0] = SHA1_MAC_LEN
;
219 * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
220 * @secret: Key for PRF
221 * @secret_len: Length of the key in bytes
222 * @label: A unique label for each purpose of the PRF
223 * @seed: Seed value to bind into the key
224 * @seed_len: Length of the seed
225 * @out: Buffer for the generated pseudo-random key
226 * @outlen: Number of bytes of key to generate
228 * This function is used to derive new, cryptographically separate keys from a
229 * given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
231 int tls_prf(const u8
*secret
, size_t secret_len
, const char *label
,
232 const u8
*seed
, size_t seed_len
, u8
*out
, size_t outlen
)
236 u8 A_MD5
[MD5_MAC_LEN
], A_SHA1
[SHA1_MAC_LEN
];
237 u8 P_MD5
[MD5_MAC_LEN
], P_SHA1
[SHA1_MAC_LEN
];
238 int i
, MD5_pos
, SHA1_pos
;
239 const u8
*MD5_addr
[3];
241 const unsigned char *SHA1_addr
[3];
248 MD5_len
[0] = MD5_MAC_LEN
;
249 MD5_addr
[1] = (unsigned char *) label
;
250 MD5_len
[1] = strlen(label
);
252 MD5_len
[2] = seed_len
;
254 SHA1_addr
[0] = A_SHA1
;
255 SHA1_len
[0] = SHA1_MAC_LEN
;
256 SHA1_addr
[1] = (unsigned char *) label
;
257 SHA1_len
[1] = strlen(label
);
259 SHA1_len
[2] = seed_len
;
261 /* RFC 2246, Chapter 5
262 * A(0) = seed, A(i) = HMAC(secret, A(i-1))
263 * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + ..
264 * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed)
267 L_S1
= L_S2
= (secret_len
+ 1) / 2;
271 hmac_md5_vector(S1
, L_S1
, 2, &MD5_addr
[1], &MD5_len
[1], A_MD5
);
272 hmac_sha1_vector(S2
, L_S2
, 2, &SHA1_addr
[1], &SHA1_len
[1], A_SHA1
);
274 MD5_pos
= MD5_MAC_LEN
;
275 SHA1_pos
= SHA1_MAC_LEN
;
276 for (i
= 0; i
< outlen
; i
++) {
277 if (MD5_pos
== MD5_MAC_LEN
) {
278 hmac_md5_vector(S1
, L_S1
, 3, MD5_addr
, MD5_len
, P_MD5
);
280 hmac_md5(S1
, L_S1
, A_MD5
, MD5_MAC_LEN
, A_MD5
);
282 if (SHA1_pos
== SHA1_MAC_LEN
) {
283 hmac_sha1_vector(S2
, L_S2
, 3, SHA1_addr
, SHA1_len
,
286 hmac_sha1(S2
, L_S2
, A_SHA1
, SHA1_MAC_LEN
, A_SHA1
);
289 out
[i
] = P_MD5
[MD5_pos
] ^ P_SHA1
[SHA1_pos
];
299 static void pbkdf2_sha1_f(const char *passphrase
, const char *ssid
,
300 size_t ssid_len
, int iterations
, int count
,
303 unsigned char tmp
[SHA1_MAC_LEN
], tmp2
[SHA1_MAC_LEN
];
305 unsigned char count_buf
[4];
308 size_t passphrase_len
= strlen(passphrase
);
310 addr
[0] = (u8
*) ssid
;
315 /* F(P, S, c, i) = U1 xor U2 xor ... Uc
316 * U1 = PRF(P, S || i)
321 count_buf
[0] = (count
>> 24) & 0xff;
322 count_buf
[1] = (count
>> 16) & 0xff;
323 count_buf
[2] = (count
>> 8) & 0xff;
324 count_buf
[3] = count
& 0xff;
325 hmac_sha1_vector((u8
*) passphrase
, passphrase_len
, 2, addr
, len
, tmp
);
326 memcpy(digest
, tmp
, SHA1_MAC_LEN
);
328 for (i
= 1; i
< iterations
; i
++) {
329 hmac_sha1((u8
*) passphrase
, passphrase_len
, tmp
, SHA1_MAC_LEN
,
331 memcpy(tmp
, tmp2
, SHA1_MAC_LEN
);
332 for (j
= 0; j
< SHA1_MAC_LEN
; j
++)
333 digest
[j
] ^= tmp2
[j
];
339 * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
340 * @passphrase: ASCII passphrase
342 * @ssid_len: SSID length in bytes
343 * @interations: Number of iterations to run
344 * @buf: Buffer for the generated key
345 * @buflen: Length of the buffer in bytes
347 * This function is used to derive PSK for WPA-PSK. For this protocol,
348 * iterations is set to 4096 and buflen to 32. This function is described in
349 * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
351 void pbkdf2_sha1(const char *passphrase
, const char *ssid
, size_t ssid_len
,
352 int iterations
, u8
*buf
, size_t buflen
)
355 unsigned char *pos
= buf
;
356 size_t left
= buflen
, plen
;
357 unsigned char digest
[SHA1_MAC_LEN
];
361 pbkdf2_sha1_f(passphrase
, ssid
, ssid_len
, iterations
, count
,
363 plen
= left
> SHA1_MAC_LEN
? SHA1_MAC_LEN
: left
;
364 memcpy(pos
, digest
, plen
);
371 #ifndef EAP_TLS_FUNCS
376 unsigned char buffer
[64];
379 static void SHA1Init(SHA1_CTX
*context
);
380 static void SHA1Update(SHA1_CTX
*context
, const void *data
, u32 len
);
381 static void SHA1Final(unsigned char digest
[20], SHA1_CTX
* context
);
382 static void SHA1Transform(u32 state
[5], const unsigned char buffer
[64]);
386 * sha1_vector - SHA-1 hash for data vector
387 * @num_elem: Number of elements in the data vector
388 * @addr: Pointers to the data areas
389 * @len: Lengths of the data blocks
390 * @mac: Buffer for the hash
392 void sha1_vector(size_t num_elem
, const u8
*addr
[], const size_t *len
,
399 for (i
= 0; i
< num_elem
; i
++)
400 SHA1Update(&ctx
, addr
[i
], len
[i
]);
401 SHA1Final(mac
, &ctx
);
406 * sha1_transform - Perform one SHA-1 transform step
407 * @state: SHA-1 state
408 * @data: Input data for the SHA-1 transform
410 * This function is used to implement random number generation specified in
411 * NIST FIPS Publication 186-2 for EAP-SIM. This PRF uses a function that is
412 * similar to SHA-1, but has different message padding and as such, access to
413 * just part of the SHA-1 is needed.
415 void sha1_transform(u8
*state
, const u8 data
[64])
417 SHA1Transform((u32
*) state
, data
);
421 /* ===== start - public domain SHA1 implementation ===== */
425 By Steve Reid <sreid@sea-to-sky.net>
430 By James H. Brown <jbrown@burgoyne.com>
431 Still 100% Public Domain
433 Corrected a problem which generated improper hash values on 16 bit machines
434 Routine SHA1Update changed from
435 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
438 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
441 The 'len' parameter was declared an int which works fine on 32 bit machines.
442 However, on 16 bit machines an int is too small for the shifts being done
444 it. This caused the hash function to generate incorrect values if len was
445 greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
447 Since the file IO in main() reads 16K at a time, any file 8K or larger would
448 be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
451 I also changed the declaration of variables i & j in SHA1Update to
452 unsigned long from unsigned int for the same reason.
454 These changes should make no difference to any 32 bit implementations since
456 int and a long are the same size in those environments.
459 I also corrected a few compiler warnings generated by Borland C.
460 1. Added #include <process.h> for exit() prototype
461 2. Removed unused variable 'j' in SHA1Final
462 3. Changed exit(0) to return(0) at end of main.
464 ALL changes I made can be located by searching for comments containing 'JHB'
467 By Steve Reid <sreid@sea-to-sky.net>
468 Still 100% public domain
470 1- Removed #include <process.h> and used return() instead of exit()
471 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
472 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
476 By Saul Kravitz <Saul.Kravitz@celera.com>
478 Modified to run on Compaq Alpha hardware.
482 By Jouni Malinen <jkmaline@cc.hut.fi>
483 Minor changes to match the coding style used in Dynamics.
485 Modified September 24, 2004
486 By Jouni Malinen <jkmaline@cc.hut.fi>
487 Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
492 Test Vectors (from FIPS PUB 180-1)
494 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
495 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
496 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
497 A million repetitions of "a"
498 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
503 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
505 /* blk0() and blk() perform the initial expand. */
506 /* I got the idea of expanding during the round function from SSLeay */
507 #ifndef WORDS_BIGENDIAN
508 #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
509 (rol(block->l[i], 8) & 0x00FF00FF))
511 #define blk0(i) block->l[i]
513 #define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
514 block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
516 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
517 #define R0(v,w,x,y,z,i) \
518 z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
520 #define R1(v,w,x,y,z,i) \
521 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
523 #define R2(v,w,x,y,z,i) \
524 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
525 #define R3(v,w,x,y,z,i) \
526 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
528 #define R4(v,w,x,y,z,i) \
529 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
533 #ifdef VERBOSE /* SAK */
534 void SHAPrintContext(SHA1_CTX
*context
, char *msg
)
536 printf("%s (%d,%d) %x %x %x %x %x\n",
538 context
->count
[0], context
->count
[1],
547 /* Hash a single 512-bit block. This is the core of the algorithm. */
549 static void SHA1Transform(u32 state
[5], const unsigned char buffer
[64])
559 block
= (CHAR64LONG16
*) workspace
;
560 memcpy(block
, buffer
, 64);
562 block
= (CHAR64LONG16
*) buffer
;
564 /* Copy context->state[] to working vars */
570 /* 4 rounds of 20 operations each. Loop unrolled. */
571 R0(a
,b
,c
,d
,e
, 0); R0(e
,a
,b
,c
,d
, 1); R0(d
,e
,a
,b
,c
, 2); R0(c
,d
,e
,a
,b
, 3);
572 R0(b
,c
,d
,e
,a
, 4); R0(a
,b
,c
,d
,e
, 5); R0(e
,a
,b
,c
,d
, 6); R0(d
,e
,a
,b
,c
, 7);
573 R0(c
,d
,e
,a
,b
, 8); R0(b
,c
,d
,e
,a
, 9); R0(a
,b
,c
,d
,e
,10); R0(e
,a
,b
,c
,d
,11);
574 R0(d
,e
,a
,b
,c
,12); R0(c
,d
,e
,a
,b
,13); R0(b
,c
,d
,e
,a
,14); R0(a
,b
,c
,d
,e
,15);
575 R1(e
,a
,b
,c
,d
,16); R1(d
,e
,a
,b
,c
,17); R1(c
,d
,e
,a
,b
,18); R1(b
,c
,d
,e
,a
,19);
576 R2(a
,b
,c
,d
,e
,20); R2(e
,a
,b
,c
,d
,21); R2(d
,e
,a
,b
,c
,22); R2(c
,d
,e
,a
,b
,23);
577 R2(b
,c
,d
,e
,a
,24); R2(a
,b
,c
,d
,e
,25); R2(e
,a
,b
,c
,d
,26); R2(d
,e
,a
,b
,c
,27);
578 R2(c
,d
,e
,a
,b
,28); R2(b
,c
,d
,e
,a
,29); R2(a
,b
,c
,d
,e
,30); R2(e
,a
,b
,c
,d
,31);
579 R2(d
,e
,a
,b
,c
,32); R2(c
,d
,e
,a
,b
,33); R2(b
,c
,d
,e
,a
,34); R2(a
,b
,c
,d
,e
,35);
580 R2(e
,a
,b
,c
,d
,36); R2(d
,e
,a
,b
,c
,37); R2(c
,d
,e
,a
,b
,38); R2(b
,c
,d
,e
,a
,39);
581 R3(a
,b
,c
,d
,e
,40); R3(e
,a
,b
,c
,d
,41); R3(d
,e
,a
,b
,c
,42); R3(c
,d
,e
,a
,b
,43);
582 R3(b
,c
,d
,e
,a
,44); R3(a
,b
,c
,d
,e
,45); R3(e
,a
,b
,c
,d
,46); R3(d
,e
,a
,b
,c
,47);
583 R3(c
,d
,e
,a
,b
,48); R3(b
,c
,d
,e
,a
,49); R3(a
,b
,c
,d
,e
,50); R3(e
,a
,b
,c
,d
,51);
584 R3(d
,e
,a
,b
,c
,52); R3(c
,d
,e
,a
,b
,53); R3(b
,c
,d
,e
,a
,54); R3(a
,b
,c
,d
,e
,55);
585 R3(e
,a
,b
,c
,d
,56); R3(d
,e
,a
,b
,c
,57); R3(c
,d
,e
,a
,b
,58); R3(b
,c
,d
,e
,a
,59);
586 R4(a
,b
,c
,d
,e
,60); R4(e
,a
,b
,c
,d
,61); R4(d
,e
,a
,b
,c
,62); R4(c
,d
,e
,a
,b
,63);
587 R4(b
,c
,d
,e
,a
,64); R4(a
,b
,c
,d
,e
,65); R4(e
,a
,b
,c
,d
,66); R4(d
,e
,a
,b
,c
,67);
588 R4(c
,d
,e
,a
,b
,68); R4(b
,c
,d
,e
,a
,69); R4(a
,b
,c
,d
,e
,70); R4(e
,a
,b
,c
,d
,71);
589 R4(d
,e
,a
,b
,c
,72); R4(c
,d
,e
,a
,b
,73); R4(b
,c
,d
,e
,a
,74); R4(a
,b
,c
,d
,e
,75);
590 R4(e
,a
,b
,c
,d
,76); R4(d
,e
,a
,b
,c
,77); R4(c
,d
,e
,a
,b
,78); R4(b
,c
,d
,e
,a
,79);
591 /* Add the working vars back into context.state[] */
598 a
= b
= c
= d
= e
= 0;
600 memset(block
, 0, 64);
605 /* SHA1Init - Initialize new context */
607 static void SHA1Init(SHA1_CTX
* context
)
609 /* SHA1 initialization constants */
610 context
->state
[0] = 0x67452301;
611 context
->state
[1] = 0xEFCDAB89;
612 context
->state
[2] = 0x98BADCFE;
613 context
->state
[3] = 0x10325476;
614 context
->state
[4] = 0xC3D2E1F0;
615 context
->count
[0] = context
->count
[1] = 0;
619 /* Run your data through this. */
621 static void SHA1Update(SHA1_CTX
* context
, const void *_data
, u32 len
)
624 const unsigned char *data
= _data
;
627 SHAPrintContext(context
, "before");
629 j
= (context
->count
[0] >> 3) & 63;
630 if ((context
->count
[0] += len
<< 3) < (len
<< 3))
632 context
->count
[1] += (len
>> 29);
633 if ((j
+ len
) > 63) {
634 memcpy(&context
->buffer
[j
], data
, (i
= 64-j
));
635 SHA1Transform(context
->state
, context
->buffer
);
636 for ( ; i
+ 63 < len
; i
+= 64) {
637 SHA1Transform(context
->state
, &data
[i
]);
642 memcpy(&context
->buffer
[j
], &data
[i
], len
- i
);
644 SHAPrintContext(context
, "after ");
649 /* Add padding and return the message digest. */
651 static void SHA1Final(unsigned char digest
[20], SHA1_CTX
* context
)
654 unsigned char finalcount
[8];
656 for (i
= 0; i
< 8; i
++) {
657 finalcount
[i
] = (unsigned char)
658 ((context
->count
[(i
>= 4 ? 0 : 1)] >>
659 ((3-(i
& 3)) * 8) ) & 255); /* Endian independent */
661 SHA1Update(context
, (unsigned char *) "\200", 1);
662 while ((context
->count
[0] & 504) != 448) {
663 SHA1Update(context
, (unsigned char *) "\0", 1);
665 SHA1Update(context
, finalcount
, 8); /* Should cause a SHA1Transform()
667 for (i
= 0; i
< 20; i
++) {
668 digest
[i
] = (unsigned char)
669 ((context
->state
[i
>> 2] >> ((3 - (i
& 3)) * 8)) &
674 memset(context
->buffer
, 0, 64);
675 memset(context
->state
, 0, 20);
676 memset(context
->count
, 0, 8);
677 memset(finalcount
, 0, 8);
680 /* ===== end - public domain SHA1 implementation ===== */
682 #endif /* EAP_TLS_FUNCS */
689 static int test_eap_fast(void)
691 /* draft-cam-winget-eap-fast-01.txt */
692 const u8 pac_key
[] = {
693 0x0B, 0x97, 0x39, 0x0F, 0x37, 0x51, 0x78, 0x09,
694 0x81, 0x1E, 0xFD, 0x9C, 0x6E, 0x65, 0x94, 0x2B,
695 0x63, 0x2C, 0xE9, 0x53, 0x89, 0x38, 0x08, 0xBA,
696 0x36, 0x0B, 0x03, 0x7C, 0xD1, 0x85, 0xE4, 0x14
699 0x3F, 0xFB, 0x11, 0xC4, 0x6C, 0xBF, 0xA5, 0x7A,
700 0x54, 0x40, 0xDA, 0xE8, 0x22, 0xD3, 0x11, 0xD3,
701 0xF7, 0x6D, 0xE4, 0x1D, 0xD9, 0x33, 0xE5, 0x93,
702 0x70, 0x97, 0xEB, 0xA9, 0xB3, 0x66, 0xF4, 0x2A,
703 0x00, 0x00, 0x00, 0x02, 0x6A, 0x66, 0x43, 0x2A,
704 0x8D, 0x14, 0x43, 0x2C, 0xEC, 0x58, 0x2D, 0x2F,
705 0xC7, 0x9C, 0x33, 0x64, 0xBA, 0x04, 0xAD, 0x3A,
706 0x52, 0x54, 0xD6, 0xA5, 0x79, 0xAD, 0x1E, 0x00
708 const u8 master_secret
[] = {
709 0x4A, 0x1A, 0x51, 0x2C, 0x01, 0x60, 0xBC, 0x02,
710 0x3C, 0xCF, 0xBC, 0x83, 0x3F, 0x03, 0xBC, 0x64,
711 0x88, 0xC1, 0x31, 0x2F, 0x0B, 0xA9, 0xA2, 0x77,
712 0x16, 0xA8, 0xD8, 0xE8, 0xBD, 0xC9, 0xD2, 0x29,
713 0x38, 0x4B, 0x7A, 0x85, 0xBE, 0x16, 0x4D, 0x27,
714 0x33, 0xD5, 0x24, 0x79, 0x87, 0xB1, 0xC5, 0xA2
716 const u8 key_block
[] = {
717 0x59, 0x59, 0xBE, 0x8E, 0x41, 0x3A, 0x77, 0x74,
718 0x8B, 0xB2, 0xE5, 0xD3, 0x60, 0xAC, 0x4D, 0x35,
719 0xDF, 0xFB, 0xC8, 0x1E, 0x9C, 0x24, 0x9C, 0x8B,
720 0x0E, 0xC3, 0x1D, 0x72, 0xC8, 0x84, 0x9D, 0x57,
721 0x48, 0x51, 0x2E, 0x45, 0x97, 0x6C, 0x88, 0x70,
722 0xBE, 0x5F, 0x01, 0xD3, 0x64, 0xE7, 0x4C, 0xBB,
723 0x11, 0x24, 0xE3, 0x49, 0xE2, 0x3B, 0xCD, 0xEF,
724 0x7A, 0xB3, 0x05, 0x39, 0x5D, 0x64, 0x8A, 0x44,
725 0x11, 0xB6, 0x69, 0x88, 0x34, 0x2E, 0x8E, 0x29,
726 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05,
727 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96,
728 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84,
729 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98,
730 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71
733 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05,
734 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96,
735 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84,
736 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98,
737 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
746 0x16, 0x15, 0x3C, 0x3F, 0x21, 0x55, 0xEF, 0xD9,
747 0x7F, 0x34, 0xAE, 0xC8, 0x1A, 0x4E, 0x66, 0x80,
748 0x4C, 0xC3, 0x76, 0xF2, 0x8A, 0xA9, 0x6F, 0x96,
749 0xC2, 0x54, 0x5F, 0x8C, 0xAB, 0x65, 0x02, 0xE1,
750 0x18, 0x40, 0x7B, 0x56, 0xBE, 0xEA, 0xA7, 0xC5,
751 0x76, 0x5D, 0x8F, 0x0B, 0xC5, 0x07, 0xC6, 0xB9,
752 0x04, 0xD0, 0x69, 0x56, 0x72, 0x8B, 0x6B, 0xB8,
753 0x15, 0xEC, 0x57, 0x7B
756 0x4D, 0x83, 0xA9, 0xBE, 0x6F, 0x8A, 0x74, 0xED,
757 0x6A, 0x02, 0x66, 0x0A, 0x63, 0x4D, 0x2C, 0x33,
758 0xC2, 0xDA, 0x60, 0x15, 0xC6, 0x37, 0x04, 0x51,
759 0x90, 0x38, 0x63, 0xDA, 0x54, 0x3E, 0x14, 0xB9,
760 0x27, 0x99, 0x18, 0x1E, 0x07, 0xBF, 0x0F, 0x5A,
761 0x5E, 0x3C, 0x32, 0x93, 0x80, 0x8C, 0x6C, 0x49,
762 0x67, 0xED, 0x24, 0xFE, 0x45, 0x40, 0xA0, 0x59,
763 0x5E, 0x37, 0xC2, 0xE9, 0xD0, 0x5D, 0x0A, 0xE3
766 0x80, 0x0C, 0x00, 0x38, 0x00, 0x01, 0x01, 0x00,
767 0xD8, 0x6A, 0x8C, 0x68, 0x3C, 0x32, 0x31, 0xA8,
768 0x56, 0x63, 0xB6, 0x40, 0x21, 0xFE, 0x21, 0x14,
769 0x4E, 0xE7, 0x54, 0x20, 0x79, 0x2D, 0x42, 0x62,
770 0xC9, 0xBF, 0x53, 0x7F, 0x54, 0xFD, 0xAC, 0x58,
771 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF,
772 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC,
773 0x05, 0xC5, 0x5B, 0xB7
775 const u8 compound_mac
[] = {
776 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF,
777 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC,
778 0x05, 0xC5, 0x5B, 0xB7
781 const u8
*simck
, *cmk
;
784 printf("EAP-FAST test cases\n");
786 printf("- T-PRF (SHA1) test case / master_secret\n");
787 sha1_t_prf(pac_key
, sizeof(pac_key
), "PAC to master secret label hash",
788 seed
, sizeof(seed
), buf
, sizeof(master_secret
));
789 if (memcmp(master_secret
, buf
, sizeof(master_secret
)) != 0) {
790 printf("T-PRF test - FAILED!\n");
794 printf("- PRF (TLS, SHA1/MD5) test case / key_block\n");
795 tls_prf(master_secret
, sizeof(master_secret
), "key expansion",
796 seed
, sizeof(seed
), buf
, sizeof(key_block
));
797 if (memcmp(key_block
, buf
, sizeof(key_block
)) != 0) {
798 printf("PRF test - FAILED!\n");
802 printf("- T-PRF (SHA1) test case / IMCK\n");
803 sha1_t_prf(sks
, sizeof(sks
), "Inner Methods Compound Keys",
804 isk
, sizeof(isk
), buf
, sizeof(imck
));
805 if (memcmp(imck
, buf
, sizeof(imck
)) != 0) {
806 printf("T-PRF test - FAILED!\n");
813 printf("- T-PRF (SHA1) test case / MSK\n");
814 sha1_t_prf(simck
, 40, "Session Key Generating Function",
815 "", 0, buf
, sizeof(msk
));
816 if (memcmp(msk
, buf
, sizeof(msk
)) != 0) {
817 printf("T-PRF test - FAILED!\n");
821 printf("- Compound MAC test case\n");
822 memset(tlv
+ sizeof(tlv
) - 20, 0, 20);
823 hmac_sha1(cmk
, 20, tlv
, sizeof(tlv
), tlv
+ sizeof(tlv
) - 20);
824 if (memcmp(tlv
+ sizeof(tlv
) - 20, compound_mac
, sizeof(compound_mac
))
826 printf("Compound MAC test - FAILED!\n");
836 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
837 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
838 0x0b, 0x0b, 0x0b, 0x0b
840 static u8 data0
[] = "Hi There";
843 0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84,
844 0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54,
845 0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06,
846 0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee,
847 0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88,
848 0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb,
849 0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e,
850 0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a
853 static u8 key1
[] = "Jefe";
854 static u8 data1
[] = "what do ya want for nothing?";
857 0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad,
858 0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4,
859 0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58,
860 0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09,
861 0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa,
862 0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02,
863 0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7,
864 0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc
870 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
871 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
872 0xaa, 0xaa, 0xaa, 0xaa
876 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
877 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
878 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
879 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
880 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
881 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
886 0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f,
887 0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1,
888 0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1,
889 0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce,
890 0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc,
891 0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae,
892 0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6,
893 0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07
897 struct passphrase_test
{
903 static struct passphrase_test passphrase_tests
[] =
909 0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef,
910 0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90,
911 0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2,
912 0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e
919 0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6,
920 0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3,
921 0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08,
922 0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf
926 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
927 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
929 0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83,
930 0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c,
931 0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48,
932 0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62
937 #define NUM_PASSPHRASE_TESTS \
938 (sizeof(passphrase_tests) / sizeof(passphrase_tests[0]))
941 int main(int argc
, char *argv
[])
946 printf("PRF-SHA1 test cases:\n");
948 sha1_prf(key0
, sizeof(key0
), "prefix", data0
, sizeof(data0
) - 1,
950 if (memcmp(res
, prf0
, sizeof(prf0
)) == 0)
951 printf("Test case 0 - OK\n");
953 printf("Test case 0 - FAILED!\n");
957 sha1_prf(key1
, sizeof(key1
) - 1, "prefix", data1
, sizeof(data1
) - 1,
959 if (memcmp(res
, prf1
, sizeof(prf1
)) == 0)
960 printf("Test case 1 - OK\n");
962 printf("Test case 1 - FAILED!\n");
966 sha1_prf(key2
, sizeof(key2
), "prefix", data2
, sizeof(data2
),
968 if (memcmp(res
, prf2
, sizeof(prf2
)) == 0)
969 printf("Test case 2 - OK\n");
971 printf("Test case 2 - FAILED!\n");
975 ret
+= test_eap_fast();
977 printf("PBKDF2-SHA1 Passphrase test cases:\n");
978 for (i
= 0; i
< NUM_PASSPHRASE_TESTS
; i
++) {
980 struct passphrase_test
*test
= &passphrase_tests
[i
];
981 pbkdf2_sha1(test
->passphrase
,
982 test
->ssid
, strlen(test
->ssid
),
984 if (memcmp(psk
, test
->psk
, 32) == 0)
985 printf("Test case %d - OK\n", i
);
987 printf("Test case %d - FAILED!\n", i
);
994 #endif /* TEST_MAIN */