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