This repository was archived by the owner on Sep 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwsupp_crypto.c
126 lines (93 loc) · 2.78 KB
/
wsupp_crypto.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <string.h>
#include <errno.h>
#include "common.h"
#include "crypto/sha1.h"
#include "crypto/aes128.h"
#include "wsupp.h"
#include "wsupp_crypto.h"
static void* memadd(void* p, void* src, unsigned len)
{
memcpy(p, src, len);
return p + len;
}
static int memxcmp(const void* av, const void* bv, size_t len)
{
const uint8_t* a = (const uint8_t*) av;
const uint8_t* b = (const uint8_t*) bv;
int ret = 0;
while(len-- > 0)
ret |= (*a++ - *b++);
return ret;
}
/* Supplementary crypto routines for EAPOL negotiations.
Ref. IEEE 802.11-2012 11.6.1.2 PRF
The standard calls for PRF384 but that's just the same code
that truncates the result to 48 bytes. In their terms:
PRF-384(K, A, B) = L(PRF-480(K, A, B), 0, 384)
To make things a bit easier, K is made 60 bytes (480 bits)
long and no explicit truncation is preformed. In the caller,
K is a temporary buffer anyway, the useful stuff gets copied
out immediately.
This function also handles concatenation:
A = str
B = mac1 | mac2 | nonce1 | nonce2
HMAC input is then
A | 0 | B | i
so there's no point in a dedicated buffer for B. */
void PRF480(byte out[60], byte key[32], char* str,
byte mac1[6], byte mac2[6],
byte nonce1[32], byte nonce2[32])
{
int slen = strlen(str);
int ilen = slen + 1 + 2*6 + 2*32 + 1; /* exact input len */
int xlen = ilen + 10; /* guarded buffer len */
char ibuf[xlen];
char* p = ibuf;
p = memadd(p, str, slen + 1);
p = memadd(p, mac1, 6);
p = memadd(p, mac2, 6);
p = memadd(p, nonce1, 32);
p = memadd(p, nonce2, 32);
for(int i = 0; i < 3; i++) {
*p = i;
hmac_sha1(out + i*20, key, 32, ibuf, ilen);
}
}
/* SHA-1 based message integrity code (MIC) for auth and key management
scheme (AKM) 00-0F-AC:2, which we requested in association IEs and
probably checked in packet 1 payload.
Ref. IEEE 802.11-2012 11.6.3 EAPOL-Key frame construction and processing. */
void make_mic(byte mic[16], byte kck[16], void* buf, int len)
{
uint8_t hash[20];
int kcklen = 16;
int miclen = 16;
hmac_sha1(hash, kck, kcklen, buf, len);
memcpy(mic, hash, miclen);
}
int check_mic(byte mic[16], byte kck[16], void* buf, int len)
{
uint8_t hash[20];
uint8_t copy[16];
int kcklen = 16;
int miclen = 16;
memcpy(copy, mic, miclen);
memzero(mic, miclen);
hmac_sha1(hash, kck, kcklen, buf, len);
int ret = memxcmp(hash, copy, miclen);
return ret;
}
/* Packet 3 payload (GTK) is wrapped with standard RFC3394 0xA6
checkblock. We unwrap it in place, and start parsing 8 bytes
into the data. */
static const byte iv[8] = {
0xA6, 0xA6, 0xA6, 0xA6,
0xA6, 0xA6, 0xA6, 0xA6
};
int unwrap_key(uint8_t kek[16], void* buf, int len)
{
if(len % 8 || len < 16)
return -1;
aes128_unwrap(kek, buf, len);
return memxcmp(buf, iv, 8);
}