add -a (assoc only) command line option
[rofl0r-wpakey.git] / wsupp_crypto.c
blobbe14ea56890eb21271635571279881f4404b3173
1 #include <string.h>
2 #include <errno.h>
4 #include "crypto/sha1.h"
5 #include "crypto/aes128.h"
7 #define byte unsigned char
8 #define memzero(a, b) memset(a, 0, b)
10 static void* memadd(void* p, void* src, unsigned len)
12 memcpy(p, src, len);
13 return p + len;
16 static int memxcmp(const void* av, const void* bv, size_t len)
18 const uint8_t* a = (const uint8_t*) av;
19 const uint8_t* b = (const uint8_t*) bv;
20 int ret = 0;
22 while(len-- > 0)
23 ret |= (*a++ - *b++);
25 return ret;
28 /* Supplementary crypto routines for EAPOL negotiations.
29 Ref. IEEE 802.11-2012 11.6.1.2 PRF
31 The standard calls for PRF384 but that's just the same code
32 that truncates the result to 48 bytes. In their terms:
34 PRF-384(K, A, B) = L(PRF-480(K, A, B), 0, 384)
36 To make things a bit easier, K is made 60 bytes (480 bits)
37 long and no explicit truncation is preformed. In the caller,
38 K is a temporary buffer anyway, the useful stuff gets copied
39 out immediately.
41 This function also handles concatenation:
43 A = str
44 B = mac1 | mac2 | nonce1 | nonce2
46 HMAC input is then
48 A | 0 | B | i
50 so there's no point in a dedicated buffer for B. */
52 void PRF480(byte out[60], byte key[32], const char* str,
53 byte mac1[6], byte mac2[6],
54 byte nonce1[32], byte nonce2[32])
56 int slen = strlen(str);
57 int ilen = slen + 1 + 2*6 + 2*32 + 1; /* exact input len */
58 int xlen = ilen + 10; /* guarded buffer len */
60 char ibuf[xlen];
61 char* p = ibuf;
63 p = memadd(p, str, slen + 1);
64 p = memadd(p, mac1, 6);
65 p = memadd(p, mac2, 6);
66 p = memadd(p, nonce1, 32);
67 p = memadd(p, nonce2, 32);
69 for(int i = 0; i < 3; i++) {
70 *p = i;
71 hmac_sha1(out + i*20, key, 32, ibuf, ilen);
75 /* SHA-1 based message integrity code (MIC) for auth and key management
76 scheme (AKM) 00-0F-AC:2, which we requested in association IEs and
77 probably checked in packet 1 payload.
79 Ref. IEEE 802.11-2012 11.6.3 EAPOL-Key frame construction and processing. */
81 void make_mic(byte mic[16], byte kck[16], void* buf, int len)
83 uint8_t hash[20];
84 int kcklen = 16;
85 int miclen = 16;
87 hmac_sha1(hash, kck, kcklen, buf, len);
89 memcpy(mic, hash, miclen);
92 int check_mic(byte mic[16], byte kck[16], void* buf, int len)
94 uint8_t hash[20];
95 uint8_t copy[16];
96 int kcklen = 16;
97 int miclen = 16;
99 memcpy(copy, mic, miclen);
100 memzero(mic, miclen);
102 hmac_sha1(hash, kck, kcklen, buf, len);
104 int ret = memxcmp(hash, copy, miclen);
106 return ret;
109 /* Packet 3 payload (GTK) is wrapped with standard RFC3394 0xA6
110 checkblock. We unwrap it in place, and start parsing 8 bytes
111 into the data. */
113 static const byte iv[8] = {
114 0xA6, 0xA6, 0xA6, 0xA6,
115 0xA6, 0xA6, 0xA6, 0xA6
118 int unwrap_key(uint8_t kek[16], void* buf, int len)
120 if(len % 8 || len < 16)
121 return -1;
123 aes128_unwrap(kek, buf, len);
125 return memxcmp(buf, iv, 8);