Line data Source code
1 : /*
2 : * IKEv2 common routines for initiator and responder
3 : * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "crypto/crypto.h"
13 : #include "crypto/md5.h"
14 : #include "crypto/sha1.h"
15 : #include "crypto/random.h"
16 : #include "ikev2_common.h"
17 :
18 :
19 : static const struct ikev2_integ_alg ikev2_integ_algs[] = {
20 : { AUTH_HMAC_SHA1_96, 20, 12 },
21 : { AUTH_HMAC_MD5_96, 16, 12 }
22 : };
23 :
24 : #define NUM_INTEG_ALGS ARRAY_SIZE(ikev2_integ_algs)
25 :
26 :
27 : static const struct ikev2_prf_alg ikev2_prf_algs[] = {
28 : { PRF_HMAC_SHA1, 20, 20 },
29 : { PRF_HMAC_MD5, 16, 16 }
30 : };
31 :
32 : #define NUM_PRF_ALGS ARRAY_SIZE(ikev2_prf_algs)
33 :
34 :
35 : static const struct ikev2_encr_alg ikev2_encr_algs[] = {
36 : { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */
37 : { ENCR_3DES, 24, 8 }
38 : };
39 :
40 : #define NUM_ENCR_ALGS ARRAY_SIZE(ikev2_encr_algs)
41 :
42 :
43 458 : const struct ikev2_integ_alg * ikev2_get_integ(int id)
44 : {
45 : size_t i;
46 :
47 481 : for (i = 0; i < NUM_INTEG_ALGS; i++) {
48 480 : if (ikev2_integ_algs[i].id == id)
49 457 : return &ikev2_integ_algs[i];
50 : }
51 :
52 1 : return NULL;
53 : }
54 :
55 :
56 260 : int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data,
57 : size_t data_len, u8 *hash)
58 : {
59 : u8 tmphash[IKEV2_MAX_HASH_LEN];
60 :
61 260 : switch (alg) {
62 : case AUTH_HMAC_SHA1_96:
63 255 : if (key_len != 20)
64 0 : return -1;
65 255 : if (hmac_sha1(key, key_len, data, data_len, tmphash) < 0)
66 3 : return -1;
67 252 : os_memcpy(hash, tmphash, 12);
68 252 : break;
69 : case AUTH_HMAC_MD5_96:
70 5 : if (key_len != 16)
71 0 : return -1;
72 5 : if (hmac_md5(key, key_len, data, data_len, tmphash) < 0)
73 0 : return -1;
74 5 : os_memcpy(hash, tmphash, 12);
75 5 : break;
76 : default:
77 0 : return -1;
78 : }
79 :
80 257 : return 0;
81 : }
82 :
83 :
84 458 : const struct ikev2_prf_alg * ikev2_get_prf(int id)
85 : {
86 : size_t i;
87 :
88 477 : for (i = 0; i < NUM_PRF_ALGS; i++) {
89 477 : if (ikev2_prf_algs[i].id == id)
90 458 : return &ikev2_prf_algs[i];
91 : }
92 :
93 0 : return NULL;
94 : }
95 :
96 :
97 1025 : int ikev2_prf_hash(int alg, const u8 *key, size_t key_len,
98 : size_t num_elem, const u8 *addr[], const size_t *len,
99 : u8 *hash)
100 : {
101 1025 : switch (alg) {
102 : case PRF_HMAC_SHA1:
103 989 : return hmac_sha1_vector(key, key_len, num_elem, addr, len,
104 : hash);
105 : case PRF_HMAC_MD5:
106 36 : return hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
107 : default:
108 0 : return -1;
109 : }
110 : }
111 :
112 :
113 105 : int ikev2_prf_plus(int alg, const u8 *key, size_t key_len,
114 : const u8 *data, size_t data_len,
115 : u8 *out, size_t out_len)
116 : {
117 : u8 hash[IKEV2_MAX_HASH_LEN];
118 : size_t hash_len;
119 : u8 iter, *pos, *end;
120 : const u8 *addr[3];
121 : size_t len[3];
122 : const struct ikev2_prf_alg *prf;
123 : int res;
124 :
125 105 : prf = ikev2_get_prf(alg);
126 105 : if (prf == NULL)
127 0 : return -1;
128 105 : hash_len = prf->hash_len;
129 :
130 105 : addr[0] = hash;
131 105 : len[0] = hash_len;
132 105 : addr[1] = data;
133 105 : len[1] = data_len;
134 105 : addr[2] = &iter;
135 105 : len[2] = 1;
136 :
137 105 : pos = out;
138 105 : end = out + out_len;
139 105 : iter = 1;
140 907 : while (pos < end) {
141 : size_t clen;
142 706 : if (iter == 1)
143 105 : res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1],
144 : &len[1], hash);
145 : else
146 601 : res = ikev2_prf_hash(alg, key, key_len, 3, addr, len,
147 : hash);
148 706 : if (res < 0)
149 9 : return -1;
150 697 : clen = hash_len;
151 697 : if ((int) clen > end - pos)
152 92 : clen = end - pos;
153 697 : os_memcpy(pos, hash, clen);
154 697 : pos += clen;
155 697 : iter++;
156 : }
157 :
158 96 : return 0;
159 : }
160 :
161 :
162 357 : const struct ikev2_encr_alg * ikev2_get_encr(int id)
163 : {
164 : size_t i;
165 :
166 376 : for (i = 0; i < NUM_ENCR_ALGS; i++) {
167 376 : if (ikev2_encr_algs[i].id == id)
168 357 : return &ikev2_encr_algs[i];
169 : }
170 :
171 0 : return NULL;
172 : }
173 :
174 :
175 86 : int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
176 : const u8 *plain, u8 *crypt, size_t len)
177 : {
178 : struct crypto_cipher *cipher;
179 : int encr_alg;
180 :
181 86 : switch (alg) {
182 : case ENCR_3DES:
183 4 : encr_alg = CRYPTO_CIPHER_ALG_3DES;
184 4 : break;
185 : case ENCR_AES_CBC:
186 82 : encr_alg = CRYPTO_CIPHER_ALG_AES;
187 82 : break;
188 : default:
189 0 : wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
190 0 : return -1;
191 : }
192 :
193 86 : cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
194 86 : if (cipher == NULL) {
195 3 : wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
196 3 : return -1;
197 : }
198 :
199 83 : if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) {
200 0 : wpa_printf(MSG_INFO, "IKEV2: Encryption failed");
201 0 : crypto_cipher_deinit(cipher);
202 0 : return -1;
203 : }
204 83 : crypto_cipher_deinit(cipher);
205 :
206 83 : return 0;
207 : }
208 :
209 :
210 73 : int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
211 : const u8 *crypt, u8 *plain, size_t len)
212 : {
213 : struct crypto_cipher *cipher;
214 : int encr_alg;
215 :
216 73 : switch (alg) {
217 : case ENCR_3DES:
218 0 : encr_alg = CRYPTO_CIPHER_ALG_3DES;
219 0 : break;
220 : case ENCR_AES_CBC:
221 73 : encr_alg = CRYPTO_CIPHER_ALG_AES;
222 73 : break;
223 : default:
224 0 : wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
225 0 : return -1;
226 : }
227 :
228 73 : cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
229 73 : if (cipher == NULL) {
230 2 : wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
231 2 : return -1;
232 : }
233 :
234 71 : if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) {
235 0 : wpa_printf(MSG_INFO, "IKEV2: Decryption failed");
236 0 : crypto_cipher_deinit(cipher);
237 0 : return -1;
238 : }
239 71 : crypto_cipher_deinit(cipher);
240 :
241 71 : return 0;
242 : }
243 :
244 :
245 240 : int ikev2_parse_payloads(struct ikev2_payloads *payloads,
246 : u8 next_payload, const u8 *pos, const u8 *end)
247 : {
248 : const struct ikev2_payload_hdr *phdr;
249 :
250 240 : os_memset(payloads, 0, sizeof(*payloads));
251 :
252 988 : while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) {
253 : unsigned int plen, pdatalen, left;
254 : const u8 *pdata;
255 512 : wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u",
256 : next_payload);
257 512 : if (end < pos)
258 0 : return -1;
259 512 : left = end - pos;
260 512 : if (left < sizeof(*phdr)) {
261 1 : wpa_printf(MSG_INFO, "IKEV2: Too short message for "
262 : "payload header (left=%ld)",
263 : (long) (end - pos));
264 1 : return -1;
265 : }
266 511 : phdr = (const struct ikev2_payload_hdr *) pos;
267 511 : plen = WPA_GET_BE16(phdr->payload_length);
268 511 : if (plen < sizeof(*phdr) || plen > left) {
269 2 : wpa_printf(MSG_INFO, "IKEV2: Invalid payload header "
270 : "length %d", plen);
271 2 : return -1;
272 : }
273 :
274 1018 : wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x"
275 : " Payload Length: %u",
276 1018 : phdr->next_payload, phdr->flags, plen);
277 :
278 509 : pdata = (const u8 *) (phdr + 1);
279 509 : pdatalen = plen - sizeof(*phdr);
280 :
281 509 : switch (next_payload) {
282 : case IKEV2_PAYLOAD_SA:
283 120 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security "
284 : "Association");
285 120 : payloads->sa = pdata;
286 120 : payloads->sa_len = pdatalen;
287 120 : break;
288 : case IKEV2_PAYLOAD_KEY_EXCHANGE:
289 103 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key "
290 : "Exchange");
291 103 : payloads->ke = pdata;
292 103 : payloads->ke_len = pdatalen;
293 103 : break;
294 : case IKEV2_PAYLOAD_IDi:
295 26 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi");
296 26 : payloads->idi = pdata;
297 26 : payloads->idi_len = pdatalen;
298 26 : break;
299 : case IKEV2_PAYLOAD_IDr:
300 44 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr");
301 44 : payloads->idr = pdata;
302 44 : payloads->idr_len = pdatalen;
303 44 : break;
304 : case IKEV2_PAYLOAD_CERTIFICATE:
305 1 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate");
306 1 : payloads->cert = pdata;
307 1 : payloads->cert_len = pdatalen;
308 1 : break;
309 : case IKEV2_PAYLOAD_AUTHENTICATION:
310 38 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: "
311 : "Authentication");
312 38 : payloads->auth = pdata;
313 38 : payloads->auth_len = pdatalen;
314 38 : break;
315 : case IKEV2_PAYLOAD_NONCE:
316 99 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce");
317 99 : payloads->nonce = pdata;
318 99 : payloads->nonce_len = pdatalen;
319 99 : break;
320 : case IKEV2_PAYLOAD_ENCRYPTED:
321 75 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted");
322 75 : payloads->encrypted = pdata;
323 75 : payloads->encrypted_len = pdatalen;
324 75 : break;
325 : case IKEV2_PAYLOAD_NOTIFICATION:
326 1 : wpa_printf(MSG_DEBUG, "IKEV2: Payload: "
327 : "Notification");
328 1 : payloads->notification = pdata;
329 1 : payloads->notification_len = pdatalen;
330 1 : break;
331 : default:
332 2 : if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) {
333 1 : wpa_printf(MSG_INFO, "IKEV2: Unsupported "
334 : "critical payload %u - reject the "
335 : "entire message", next_payload);
336 1 : return -1;
337 : } else {
338 1 : wpa_printf(MSG_DEBUG, "IKEV2: Skipped "
339 : "unsupported payload %u",
340 : next_payload);
341 : }
342 : }
343 :
344 583 : if (next_payload == IKEV2_PAYLOAD_ENCRYPTED &&
345 75 : pos + plen == end) {
346 : /*
347 : * Next Payload in the case of Encrypted Payload is
348 : * actually the payload type for the first embedded
349 : * payload.
350 : */
351 75 : payloads->encr_next_payload = phdr->next_payload;
352 75 : next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD;
353 : } else
354 433 : next_payload = phdr->next_payload;
355 :
356 508 : pos += plen;
357 : }
358 :
359 236 : if (pos != end) {
360 1 : wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after "
361 : "payloads");
362 1 : return -1;
363 : }
364 :
365 235 : return 0;
366 : }
367 :
368 :
369 83 : int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg,
370 : const u8 *ID, size_t ID_len, u8 ID_type,
371 : struct ikev2_keys *keys, int initiator,
372 : const u8 *shared_secret, size_t shared_secret_len,
373 : const u8 *nonce, size_t nonce_len,
374 : const u8 *key_pad, size_t key_pad_len,
375 : u8 *auth_data)
376 : {
377 : size_t sign_len, buf_len;
378 : u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN];
379 : const struct ikev2_prf_alg *prf;
380 83 : const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr;
381 :
382 83 : prf = ikev2_get_prf(prf_alg);
383 83 : if (sign_msg == NULL || ID == NULL || SK_p == NULL ||
384 83 : shared_secret == NULL || nonce == NULL || prf == NULL)
385 0 : return -1;
386 :
387 : /* prf(SK_pi/r,IDi/r') */
388 83 : buf_len = 4 + ID_len;
389 83 : buf = os_zalloc(buf_len);
390 83 : if (buf == NULL)
391 3 : return -1;
392 80 : buf[0] = ID_type;
393 80 : os_memcpy(buf + 4, ID, ID_len);
394 80 : if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len,
395 : 1, (const u8 **) &buf, &buf_len, hash) < 0) {
396 2 : os_free(buf);
397 2 : return -1;
398 : }
399 78 : os_free(buf);
400 :
401 : /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */
402 78 : sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len;
403 78 : sign_data = os_malloc(sign_len);
404 78 : if (sign_data == NULL)
405 0 : return -1;
406 78 : pos = sign_data;
407 78 : os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg));
408 78 : pos += wpabuf_len(sign_msg);
409 78 : os_memcpy(pos, nonce, nonce_len);
410 78 : pos += nonce_len;
411 78 : os_memcpy(pos, hash, prf->hash_len);
412 :
413 : /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */
414 78 : if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1,
415 77 : &key_pad, &key_pad_len, hash) < 0 ||
416 77 : ikev2_prf_hash(prf->id, hash, prf->hash_len, 1,
417 : (const u8 **) &sign_data, &sign_len, auth_data) < 0)
418 : {
419 2 : os_free(sign_data);
420 2 : return -1;
421 : }
422 76 : os_free(sign_data);
423 :
424 76 : return 0;
425 : }
426 :
427 :
428 75 : u8 * ikev2_decrypt_payload(int encr_id, int integ_id,
429 : struct ikev2_keys *keys, int initiator,
430 : const struct ikev2_hdr *hdr,
431 : const u8 *encrypted, size_t encrypted_len,
432 : size_t *res_len)
433 : {
434 : size_t iv_len;
435 : const u8 *pos, *end, *iv, *integ;
436 : u8 hash[IKEV2_MAX_HASH_LEN], *decrypted;
437 : size_t decrypted_len, pad_len;
438 : const struct ikev2_integ_alg *integ_alg;
439 : const struct ikev2_encr_alg *encr_alg;
440 75 : const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
441 75 : const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
442 :
443 75 : if (encrypted == NULL) {
444 0 : wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH");
445 0 : return NULL;
446 : }
447 :
448 75 : encr_alg = ikev2_get_encr(encr_id);
449 75 : if (encr_alg == NULL) {
450 0 : wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
451 0 : return NULL;
452 : }
453 75 : iv_len = encr_alg->block_size;
454 :
455 75 : integ_alg = ikev2_get_integ(integ_id);
456 75 : if (integ_alg == NULL) {
457 0 : wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
458 0 : return NULL;
459 : }
460 :
461 75 : if (encrypted_len < iv_len + 1 + integ_alg->hash_len) {
462 0 : wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity "
463 : "Checksum");
464 0 : return NULL;
465 : }
466 :
467 75 : iv = encrypted;
468 75 : pos = iv + iv_len;
469 75 : end = encrypted + encrypted_len;
470 75 : integ = end - integ_alg->hash_len;
471 :
472 75 : if (SK_a == NULL) {
473 0 : wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
474 0 : return NULL;
475 : }
476 75 : if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
477 : (const u8 *) hdr,
478 75 : integ - (const u8 *) hdr, hash) < 0) {
479 1 : wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity "
480 : "hash");
481 1 : return NULL;
482 : }
483 74 : if (os_memcmp_const(integ, hash, integ_alg->hash_len) != 0) {
484 0 : wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum "
485 : "Data");
486 0 : return NULL;
487 : }
488 :
489 74 : if (SK_e == NULL) {
490 0 : wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
491 0 : return NULL;
492 : }
493 :
494 74 : decrypted_len = integ - pos;
495 74 : decrypted = os_malloc(decrypted_len);
496 74 : if (decrypted == NULL)
497 1 : return NULL;
498 :
499 73 : if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos,
500 : decrypted, decrypted_len) < 0) {
501 2 : os_free(decrypted);
502 2 : return NULL;
503 : }
504 :
505 71 : pad_len = decrypted[decrypted_len - 1];
506 71 : if (decrypted_len < pad_len + 1) {
507 0 : wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted "
508 : "payload");
509 0 : os_free(decrypted);
510 0 : return NULL;
511 : }
512 :
513 71 : decrypted_len -= pad_len + 1;
514 :
515 71 : *res_len = decrypted_len;
516 71 : return decrypted;
517 : }
518 :
519 :
520 189 : void ikev2_update_hdr(struct wpabuf *msg)
521 : {
522 : struct ikev2_hdr *hdr;
523 :
524 : /* Update lenth field in HDR */
525 189 : hdr = wpabuf_mhead(msg);
526 189 : WPA_PUT_BE32(hdr->length, wpabuf_len(msg));
527 189 : }
528 :
529 :
530 87 : int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys,
531 : int initiator, struct wpabuf *msg,
532 : struct wpabuf *plain, u8 next_payload)
533 : {
534 : struct ikev2_payload_hdr *phdr;
535 : size_t plen;
536 : size_t iv_len, pad_len;
537 : u8 *icv, *iv;
538 : const struct ikev2_integ_alg *integ_alg;
539 : const struct ikev2_encr_alg *encr_alg;
540 87 : const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
541 87 : const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
542 :
543 87 : wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload");
544 :
545 : /* Encr - RFC 4306, Sect. 3.14 */
546 :
547 87 : encr_alg = ikev2_get_encr(encr_id);
548 87 : if (encr_alg == NULL) {
549 0 : wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
550 0 : return -1;
551 : }
552 87 : iv_len = encr_alg->block_size;
553 :
554 87 : integ_alg = ikev2_get_integ(integ_id);
555 87 : if (integ_alg == NULL) {
556 0 : wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
557 0 : return -1;
558 : }
559 :
560 87 : if (SK_e == NULL) {
561 0 : wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
562 0 : return -1;
563 : }
564 :
565 87 : if (SK_a == NULL) {
566 0 : wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
567 0 : return -1;
568 : }
569 :
570 87 : phdr = wpabuf_put(msg, sizeof(*phdr));
571 87 : phdr->next_payload = next_payload;
572 87 : phdr->flags = 0;
573 :
574 87 : iv = wpabuf_put(msg, iv_len);
575 87 : if (random_get_bytes(iv, iv_len)) {
576 1 : wpa_printf(MSG_INFO, "IKEV2: Could not generate IV");
577 1 : return -1;
578 : }
579 :
580 86 : pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len;
581 86 : if (pad_len == iv_len)
582 0 : pad_len = 0;
583 86 : wpabuf_put(plain, pad_len);
584 86 : wpabuf_put_u8(plain, pad_len);
585 :
586 172 : if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv,
587 86 : wpabuf_head(plain), wpabuf_mhead(plain),
588 : wpabuf_len(plain)) < 0)
589 3 : return -1;
590 :
591 83 : wpabuf_put_buf(msg, plain);
592 :
593 : /* Need to update all headers (Length fields) prior to hash func */
594 83 : icv = wpabuf_put(msg, integ_alg->hash_len);
595 83 : plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
596 83 : WPA_PUT_BE16(phdr->payload_length, plen);
597 :
598 83 : ikev2_update_hdr(msg);
599 :
600 166 : return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
601 83 : wpabuf_head(msg),
602 83 : wpabuf_len(msg) - integ_alg->hash_len, icv);
603 :
604 : return 0;
605 : }
606 :
607 :
608 74 : int ikev2_keys_set(struct ikev2_keys *keys)
609 : {
610 296 : return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei &&
611 222 : keys->SK_er && keys->SK_pi && keys->SK_pr;
612 : }
613 :
614 :
615 266 : void ikev2_free_keys(struct ikev2_keys *keys)
616 : {
617 266 : os_free(keys->SK_d);
618 266 : os_free(keys->SK_ai);
619 266 : os_free(keys->SK_ar);
620 266 : os_free(keys->SK_ei);
621 266 : os_free(keys->SK_er);
622 266 : os_free(keys->SK_pi);
623 266 : os_free(keys->SK_pr);
624 266 : keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er =
625 266 : keys->SK_pi = keys->SK_pr = NULL;
626 266 : }
627 :
628 :
629 83 : int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf,
630 : const struct ikev2_integ_alg *integ,
631 : const struct ikev2_encr_alg *encr,
632 : const u8 *skeyseed, const u8 *data, size_t data_len,
633 : struct ikev2_keys *keys)
634 : {
635 : u8 *keybuf, *pos;
636 : size_t keybuf_len;
637 :
638 : /*
639 : * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } =
640 : * prf+(SKEYSEED, Ni | Nr | SPIi | SPIr )
641 : */
642 83 : ikev2_free_keys(keys);
643 83 : keys->SK_d_len = prf->key_len;
644 83 : keys->SK_integ_len = integ->key_len;
645 83 : keys->SK_encr_len = encr->key_len;
646 83 : keys->SK_prf_len = prf->key_len;
647 :
648 249 : keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
649 166 : 2 * keys->SK_encr_len + 2 * keys->SK_prf_len;
650 83 : keybuf = os_malloc(keybuf_len);
651 83 : if (keybuf == NULL)
652 1 : return -1;
653 :
654 82 : if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len,
655 : data, data_len, keybuf, keybuf_len)) {
656 8 : os_free(keybuf);
657 8 : return -1;
658 : }
659 :
660 74 : pos = keybuf;
661 :
662 74 : keys->SK_d = os_malloc(keys->SK_d_len);
663 74 : if (keys->SK_d) {
664 74 : os_memcpy(keys->SK_d, pos, keys->SK_d_len);
665 148 : wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d",
666 74 : keys->SK_d, keys->SK_d_len);
667 : }
668 74 : pos += keys->SK_d_len;
669 :
670 74 : keys->SK_ai = os_malloc(keys->SK_integ_len);
671 74 : if (keys->SK_ai) {
672 74 : os_memcpy(keys->SK_ai, pos, keys->SK_integ_len);
673 148 : wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai",
674 74 : keys->SK_ai, keys->SK_integ_len);
675 : }
676 74 : pos += keys->SK_integ_len;
677 :
678 74 : keys->SK_ar = os_malloc(keys->SK_integ_len);
679 74 : if (keys->SK_ar) {
680 74 : os_memcpy(keys->SK_ar, pos, keys->SK_integ_len);
681 148 : wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar",
682 74 : keys->SK_ar, keys->SK_integ_len);
683 : }
684 74 : pos += keys->SK_integ_len;
685 :
686 74 : keys->SK_ei = os_malloc(keys->SK_encr_len);
687 74 : if (keys->SK_ei) {
688 74 : os_memcpy(keys->SK_ei, pos, keys->SK_encr_len);
689 148 : wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei",
690 74 : keys->SK_ei, keys->SK_encr_len);
691 : }
692 74 : pos += keys->SK_encr_len;
693 :
694 74 : keys->SK_er = os_malloc(keys->SK_encr_len);
695 74 : if (keys->SK_er) {
696 74 : os_memcpy(keys->SK_er, pos, keys->SK_encr_len);
697 148 : wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er",
698 74 : keys->SK_er, keys->SK_encr_len);
699 : }
700 74 : pos += keys->SK_encr_len;
701 :
702 74 : keys->SK_pi = os_malloc(keys->SK_prf_len);
703 74 : if (keys->SK_pi) {
704 74 : os_memcpy(keys->SK_pi, pos, keys->SK_prf_len);
705 148 : wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi",
706 74 : keys->SK_pi, keys->SK_prf_len);
707 : }
708 74 : pos += keys->SK_prf_len;
709 :
710 74 : keys->SK_pr = os_malloc(keys->SK_prf_len);
711 74 : if (keys->SK_pr) {
712 74 : os_memcpy(keys->SK_pr, pos, keys->SK_prf_len);
713 148 : wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr",
714 74 : keys->SK_pr, keys->SK_prf_len);
715 : }
716 :
717 74 : os_free(keybuf);
718 :
719 74 : if (!ikev2_keys_set(keys)) {
720 0 : ikev2_free_keys(keys);
721 0 : return -1;
722 : }
723 :
724 74 : return 0;
725 : }
|