197403Sobrien/*
297403Sobrien * IKEv2 common routines for initiator and responder
3132720Skan * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
4132720Skan *
597403Sobrien * This software may be distributed under the terms of the BSD license.
697403Sobrien * See README for more details.
797403Sobrien */
897403Sobrien
997403Sobrien#include "includes.h"
1097403Sobrien
1197403Sobrien#include "common.h"
1297403Sobrien#include "crypto/crypto.h"
1397403Sobrien#include "crypto/md5.h"
1497403Sobrien#include "crypto/sha1.h"
1597403Sobrien#include "crypto/random.h"
1697403Sobrien#include "ikev2_common.h"
1797403Sobrien
1897403Sobrien
1997403Sobrienstatic struct ikev2_integ_alg ikev2_integ_algs[] = {
2097403Sobrien	{ AUTH_HMAC_SHA1_96, 20, 12 },
2197403Sobrien	{ AUTH_HMAC_MD5_96, 16, 12 }
2297403Sobrien};
2397403Sobrien
2497403Sobrien#define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0]))
2597403Sobrien
2697403Sobrien
2797403Sobrienstatic struct ikev2_prf_alg ikev2_prf_algs[] = {
2897403Sobrien	{ PRF_HMAC_SHA1, 20, 20 },
2997403Sobrien	{ PRF_HMAC_MD5, 16, 16 }
3097403Sobrien};
3197403Sobrien
3297403Sobrien#define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0]))
3397403Sobrien
3497403Sobrien
3597403Sobrienstatic struct ikev2_encr_alg ikev2_encr_algs[] = {
3697403Sobrien	{ ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */
3797403Sobrien	{ ENCR_3DES, 24, 8 }
3897403Sobrien};
3997403Sobrien
40132720Skan#define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0]))
41132720Skan
4297403Sobrien
4397403Sobrienconst struct ikev2_integ_alg * ikev2_get_integ(int id)
4497403Sobrien{
4597403Sobrien	size_t i;
4697403Sobrien
4797403Sobrien	for (i = 0; i < NUM_INTEG_ALGS; i++) {
4897403Sobrien		if (ikev2_integ_algs[i].id == id)
4997403Sobrien			return &ikev2_integ_algs[i];
50117397Skan	}
51117397Skan
52117397Skan	return NULL;
53117397Skan}
54117397Skan
55117397Skan
56117397Skanint ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data,
57117397Skan		     size_t data_len, u8 *hash)
5897403Sobrien{
5997403Sobrien	u8 tmphash[IKEV2_MAX_HASH_LEN];
6097403Sobrien
6197403Sobrien	switch (alg) {
6297403Sobrien	case AUTH_HMAC_SHA1_96:
6397403Sobrien		if (key_len != 20)
6497403Sobrien			return -1;
6597403Sobrien		hmac_sha1(key, key_len, data, data_len, tmphash);
6697403Sobrien		os_memcpy(hash, tmphash, 12);
6797403Sobrien		break;
6897403Sobrien	case AUTH_HMAC_MD5_96:
6997403Sobrien		if (key_len != 16)
7097403Sobrien			return -1;
7197403Sobrien		hmac_md5(key, key_len, data, data_len, tmphash);
7297403Sobrien		os_memcpy(hash, tmphash, 12);
73132720Skan		break;
74132720Skan	default:
7597403Sobrien		return -1;
7697403Sobrien	}
77117397Skan
78117397Skan	return 0;
79117397Skan}
80117397Skan
81117397Skan
82117397Skanconst struct ikev2_prf_alg * ikev2_get_prf(int id)
83117397Skan{
84117397Skan	size_t i;
8597403Sobrien
8697403Sobrien	for (i = 0; i < NUM_PRF_ALGS; i++) {
87117397Skan		if (ikev2_prf_algs[i].id == id)
88117397Skan			return &ikev2_prf_algs[i];
89117397Skan	}
90117397Skan
91117397Skan	return NULL;
92117397Skan}
9397403Sobrien
9497403Sobrien
9597403Sobrienint ikev2_prf_hash(int alg, const u8 *key, size_t key_len,
96117397Skan		   size_t num_elem, const u8 *addr[], const size_t *len,
97117397Skan		   u8 *hash)
98117397Skan{
99117397Skan	switch (alg) {
100117397Skan	case PRF_HMAC_SHA1:
101117397Skan		hmac_sha1_vector(key, key_len, num_elem, addr, len, hash);
102117397Skan		break;
103117397Skan	case PRF_HMAC_MD5:
10497403Sobrien		hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
105132720Skan		break;
106132720Skan	default:
10797403Sobrien		return -1;
108117397Skan	}
109117397Skan
110117397Skan	return 0;
111117397Skan}
112117397Skan
11397403Sobrien
11497403Sobrienint ikev2_prf_plus(int alg, const u8 *key, size_t key_len,
11597403Sobrien		   const u8 *data, size_t data_len,
11697403Sobrien		   u8 *out, size_t out_len)
117117397Skan{
11897403Sobrien	u8 hash[IKEV2_MAX_HASH_LEN];
11997403Sobrien	size_t hash_len;
12097403Sobrien	u8 iter, *pos, *end;
121117397Skan	const u8 *addr[3];
122117397Skan	size_t len[3];
123117397Skan	const struct ikev2_prf_alg *prf;
124117397Skan	int res;
125117397Skan
126117397Skan	prf = ikev2_get_prf(alg);
127117397Skan	if (prf == NULL)
128117397Skan		return -1;
129117397Skan	hash_len = prf->hash_len;
130117397Skan
131132720Skan	addr[0] = hash;
13297403Sobrien	len[0] = hash_len;
13397403Sobrien	addr[1] = data;
134132720Skan	len[1] = data_len;
13597403Sobrien	addr[2] = &iter;
13697403Sobrien	len[2] = 1;
137132720Skan
13897403Sobrien	pos = out;
139117397Skan	end = out + out_len;
14097403Sobrien	iter = 1;
141117397Skan	while (pos < end) {
142117397Skan		size_t clen;
143117397Skan		if (iter == 1)
144117397Skan			res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1],
145117397Skan					     &len[1], hash);
146117397Skan		else
147117397Skan			res = ikev2_prf_hash(alg, key, key_len, 3, addr, len,
148117397Skan					     hash);
149117397Skan		if (res < 0)
150117397Skan			return -1;
151117397Skan		clen = hash_len;
152117397Skan		if ((int) clen > end - pos)
153117397Skan			clen = end - pos;
154117397Skan		os_memcpy(pos, hash, clen);
155117397Skan		pos += clen;
156117397Skan		iter++;
157117397Skan	}
158117397Skan
159117397Skan	return 0;
160117397Skan}
161117397Skan
162117397Skan
163117397Skanconst struct ikev2_encr_alg * ikev2_get_encr(int id)
164117397Skan{
165117397Skan	size_t i;
166117397Skan
167117397Skan	for (i = 0; i < NUM_ENCR_ALGS; i++) {
168117397Skan		if (ikev2_encr_algs[i].id == id)
16997403Sobrien			return &ikev2_encr_algs[i];
17097403Sobrien	}
17197403Sobrien
17297403Sobrien	return NULL;
17397403Sobrien}
17497403Sobrien
17597403Sobrien
17697403Sobrien#ifdef CCNS_PL
17797403Sobrien/* from des.c */
17897403Sobrienstruct des3_key_s {
17997403Sobrien	u32 ek[3][32];
18097403Sobrien	u32 dk[3][32];
18197403Sobrien};
18297403Sobrien
18397403Sobrienvoid des3_key_setup(const u8 *key, struct des3_key_s *dkey);
18497403Sobrienvoid des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
18597403Sobrienvoid des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
18697403Sobrien#endif /* CCNS_PL */
18797403Sobrien
18897403Sobrien
18997403Sobrienint ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
190132720Skan		       const u8 *plain, u8 *crypt, size_t len)
19197403Sobrien{
19297403Sobrien	struct crypto_cipher *cipher;
19397403Sobrien	int encr_alg;
19497403Sobrien
19597403Sobrien#ifdef CCNS_PL
19697403Sobrien	if (alg == ENCR_3DES) {
19797403Sobrien		struct des3_key_s des3key;
19897403Sobrien		size_t i, blocks;
19997403Sobrien		u8 *pos;
20097403Sobrien
20197403Sobrien		/* ECB mode is used incorrectly for 3DES!? */
20297403Sobrien		if (key_len != 24) {
20397403Sobrien			wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
20497403Sobrien			return -1;
20597403Sobrien		}
20697403Sobrien		des3_key_setup(key, &des3key);
20797403Sobrien
20897403Sobrien		blocks = len / 8;
20997403Sobrien		pos = crypt;
210117397Skan		for (i = 0; i < blocks; i++) {
211117397Skan			des3_encrypt(pos, &des3key, pos);
212117397Skan			pos += 8;
213117397Skan		}
214117397Skan	} else {
215132720Skan#endif /* CCNS_PL */
216117397Skan	switch (alg) {
217117397Skan	case ENCR_3DES:
218117397Skan		encr_alg = CRYPTO_CIPHER_ALG_3DES;
219117397Skan		break;
220117397Skan	case ENCR_AES_CBC:
221117397Skan		encr_alg = CRYPTO_CIPHER_ALG_AES;
222117397Skan		break;
223117397Skan	default:
224117397Skan		wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
225117397Skan		return -1;
226117397Skan	}
227117397Skan
228117397Skan	cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
229117397Skan	if (cipher == NULL) {
23097403Sobrien		wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
23197403Sobrien		return -1;
232117397Skan	}
23397403Sobrien
234117397Skan	if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) {
235117397Skan		wpa_printf(MSG_INFO, "IKEV2: Encryption failed");
236117397Skan		crypto_cipher_deinit(cipher);
237117397Skan		return -1;
238117397Skan	}
239117397Skan	crypto_cipher_deinit(cipher);
24097403Sobrien#ifdef CCNS_PL
241117397Skan	}
24297403Sobrien#endif /* CCNS_PL */
24397403Sobrien
244117397Skan	return 0;
245117397Skan}
246117397Skan
247117397Skan
248117397Skanint ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
249117397Skan		       const u8 *crypt, u8 *plain, size_t len)
250117397Skan{
251117397Skan	struct crypto_cipher *cipher;
252117397Skan	int encr_alg;
253117397Skan
254117397Skan#ifdef CCNS_PL
255117397Skan	if (alg == ENCR_3DES) {
256117397Skan		struct des3_key_s des3key;
257117397Skan		size_t i, blocks;
258117397Skan
259117397Skan		/* ECB mode is used incorrectly for 3DES!? */
260117397Skan		if (key_len != 24) {
261117397Skan			wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
262117397Skan			return -1;
263117397Skan		}
264117397Skan		des3_key_setup(key, &des3key);
265117397Skan
266117397Skan		if (len % 8) {
267117397Skan			wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted "
268117397Skan				   "length");
269117397Skan			return -1;
270117397Skan		}
271117397Skan		blocks = len / 8;
27297403Sobrien		for (i = 0; i < blocks; i++) {
273117397Skan			des3_decrypt(crypt, &des3key, plain);
27497403Sobrien			plain += 8;
275117397Skan			crypt += 8;
276117397Skan		}
277117397Skan	} else {
278117397Skan#endif /* CCNS_PL */
279117397Skan	switch (alg) {
280117397Skan	case ENCR_3DES:
281117397Skan		encr_alg = CRYPTO_CIPHER_ALG_3DES;
282117397Skan		break;
283117397Skan	case ENCR_AES_CBC:
284117397Skan		encr_alg = CRYPTO_CIPHER_ALG_AES;
285117397Skan		break;
28697403Sobrien	default:
28797403Sobrien		wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
28897403Sobrien		return -1;
289117397Skan	}
290117397Skan
291117397Skan	cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
292117397Skan	if (cipher == NULL) {
293117397Skan		wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
294117397Skan		return -1;
295117397Skan	}
296117397Skan
297117397Skan	if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) {
298117397Skan		wpa_printf(MSG_INFO, "IKEV2: Decryption failed");
299117397Skan		crypto_cipher_deinit(cipher);
300117397Skan		return -1;
301117397Skan	}
302117397Skan	crypto_cipher_deinit(cipher);
303117397Skan#ifdef CCNS_PL
304117397Skan	}
305117397Skan#endif /* CCNS_PL */
306117397Skan
307117397Skan	return 0;
308117397Skan}
309117397Skan
310117397Skan
311117397Skanint ikev2_parse_payloads(struct ikev2_payloads *payloads,
312117397Skan			 u8 next_payload, const u8 *pos, const u8 *end)
31397403Sobrien{
31497403Sobrien	const struct ikev2_payload_hdr *phdr;
31597403Sobrien
316117397Skan	os_memset(payloads, 0, sizeof(*payloads));
317117397Skan
318117397Skan	while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) {
319117397Skan		int plen, pdatalen;
320117397Skan		const u8 *pdata;
321117397Skan		wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u",
322117397Skan			   next_payload);
323117397Skan		if (end - pos < (int) sizeof(*phdr)) {
32497403Sobrien			wpa_printf(MSG_INFO, "IKEV2:   Too short message for "
32597403Sobrien				   "payload header (left=%ld)",
32697403Sobrien				   (long) (end - pos));
32797403Sobrien		}
328117397Skan		phdr = (const struct ikev2_payload_hdr *) pos;
329117397Skan		plen = WPA_GET_BE16(phdr->payload_length);
330117397Skan		if (plen < (int) sizeof(*phdr) || pos + plen > end) {
331117397Skan			wpa_printf(MSG_INFO, "IKEV2:   Invalid payload header "
332117397Skan				   "length %d", plen);
333117397Skan			return -1;
334117397Skan		}
335117397Skan
336117397Skan		wpa_printf(MSG_DEBUG, "IKEV2:   Next Payload: %u  Flags: 0x%x"
337117397Skan			   "  Payload Length: %d",
338117397Skan			   phdr->next_payload, phdr->flags, plen);
339117397Skan
340117397Skan		pdata = (const u8 *) (phdr + 1);
341117397Skan		pdatalen = plen - sizeof(*phdr);
342117397Skan
343117397Skan		switch (next_payload) {
344117397Skan		case IKEV2_PAYLOAD_SA:
345117397Skan			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Security "
346117397Skan				   "Association");
34797403Sobrien			payloads->sa = pdata;
34897403Sobrien			payloads->sa_len = pdatalen;
34997403Sobrien			break;
350117397Skan		case IKEV2_PAYLOAD_KEY_EXCHANGE:
351117397Skan			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Key "
352117397Skan				   "Exchange");
353117397Skan			payloads->ke = pdata;
354117397Skan			payloads->ke_len = pdatalen;
355117397Skan			break;
356117397Skan		case IKEV2_PAYLOAD_IDi:
35797403Sobrien			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: IDi");
35897403Sobrien			payloads->idi = pdata;
35997403Sobrien			payloads->idi_len = pdatalen;
36097403Sobrien			break;
361117397Skan		case IKEV2_PAYLOAD_IDr:
362117397Skan			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: IDr");
363117397Skan			payloads->idr = pdata;
364117397Skan			payloads->idr_len = pdatalen;
365117397Skan			break;
366117397Skan		case IKEV2_PAYLOAD_CERTIFICATE:
367117397Skan			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Certificate");
368117397Skan			payloads->cert = pdata;
369117397Skan			payloads->cert_len = pdatalen;
370117397Skan			break;
371117397Skan		case IKEV2_PAYLOAD_AUTHENTICATION:
372117397Skan			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: "
373117397Skan				   "Authentication");
374117397Skan			payloads->auth = pdata;
375117397Skan			payloads->auth_len = pdatalen;
376117397Skan			break;
377117397Skan		case IKEV2_PAYLOAD_NONCE:
378117397Skan			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Nonce");
379117397Skan			payloads->nonce = pdata;
380117397Skan			payloads->nonce_len = pdatalen;
381117397Skan			break;
382117397Skan		case IKEV2_PAYLOAD_ENCRYPTED:
383117397Skan			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Encrypted");
384117397Skan			payloads->encrypted = pdata;
385117397Skan			payloads->encrypted_len = pdatalen;
38697403Sobrien			break;
38797403Sobrien		case IKEV2_PAYLOAD_NOTIFICATION:
38897403Sobrien			wpa_printf(MSG_DEBUG, "IKEV2:   Payload: "
389117397Skan				   "Notification");
390117397Skan			payloads->notification = pdata;
391117397Skan			payloads->notification_len = pdatalen;
392117397Skan			break;
393117397Skan		default:
394117397Skan			if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) {
395117397Skan				wpa_printf(MSG_INFO, "IKEV2:   Unsupported "
396117397Skan					   "critical payload %u - reject the "
39797403Sobrien					   "entire message", next_payload);
39897403Sobrien				return -1;
39997403Sobrien			} else {
40097403Sobrien				wpa_printf(MSG_DEBUG, "IKEV2:   Skipped "
401117397Skan					   "unsupported payload %u",
402117397Skan					   next_payload);
403117397Skan			}
404117397Skan		}
405117397Skan
406117397Skan		if (next_payload == IKEV2_PAYLOAD_ENCRYPTED &&
407117397Skan		    pos + plen == end) {
408117397Skan			/*
409117397Skan			 * Next Payload in the case of Encrypted Payload is
410117397Skan			 * actually the payload type for the first embedded
411117397Skan			 * payload.
412117397Skan			 */
413117397Skan			payloads->encr_next_payload = phdr->next_payload;
414117397Skan			next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD;
415117397Skan		} else
41697403Sobrien			next_payload = phdr->next_payload;
41797403Sobrien
41897403Sobrien		pos += plen;
419117397Skan	}
420117397Skan
421117397Skan	if (pos != end) {
422117397Skan		wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after "
423117397Skan			   "payloads");
424117397Skan		return -1;
425117397Skan	}
426117397Skan
42797403Sobrien	return 0;
428117397Skan}
42997403Sobrien
430117397Skan
431117397Skanint ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg,
432117397Skan			   const u8 *ID, size_t ID_len, u8 ID_type,
433117397Skan			   struct ikev2_keys *keys, int initiator,
434117397Skan			   const u8 *shared_secret, size_t shared_secret_len,
435117397Skan			   const u8 *nonce, size_t nonce_len,
436117397Skan			   const u8 *key_pad, size_t key_pad_len,
437117397Skan			   u8 *auth_data)
438117397Skan{
439117397Skan	size_t sign_len, buf_len;
440117397Skan	u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN];
441117397Skan	const struct ikev2_prf_alg *prf;
442117397Skan	const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr;
443117397Skan
444117397Skan	prf = ikev2_get_prf(prf_alg);
44597403Sobrien	if (sign_msg == NULL || ID == NULL || SK_p == NULL ||
44697403Sobrien	    shared_secret == NULL || nonce == NULL || prf == NULL)
44797403Sobrien		return -1;
448117397Skan
449117397Skan	/* prf(SK_pi/r,IDi/r') */
450117397Skan	buf_len = 4 + ID_len;
451117397Skan	buf = os_zalloc(buf_len);
452117397Skan	if (buf == NULL)
453117397Skan		return -1;
454117397Skan	buf[0] = ID_type;
455117397Skan	os_memcpy(buf + 4, ID, ID_len);
456117397Skan	if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len,
457117397Skan			   1, (const u8 **) &buf, &buf_len, hash) < 0) {
458117397Skan		os_free(buf);
459117397Skan		return -1;
460117397Skan	}
461117397Skan	os_free(buf);
462117397Skan
463117397Skan	/* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */
46497403Sobrien	sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len;
46597403Sobrien	sign_data = os_malloc(sign_len);
46697403Sobrien	if (sign_data == NULL)
467117397Skan		return -1;
468117397Skan	pos = sign_data;
469117397Skan	os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg));
470117397Skan	pos += wpabuf_len(sign_msg);
471117397Skan	os_memcpy(pos, nonce, nonce_len);
472117397Skan	pos += nonce_len;
473117397Skan	os_memcpy(pos, hash, prf->hash_len);
474117397Skan
475117397Skan	/* AUTH = prf(prf(Shared Secret, key pad, sign_data) */
476117397Skan	if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1,
477117397Skan			   &key_pad, &key_pad_len, hash) < 0 ||
478117397Skan	    ikev2_prf_hash(prf->id, hash, prf->hash_len, 1,
479117397Skan			   (const u8 **) &sign_data, &sign_len, auth_data) < 0)
48097403Sobrien	{
48197403Sobrien		os_free(sign_data);
48297403Sobrien		return -1;
483117397Skan	}
484117397Skan	os_free(sign_data);
485117397Skan
486117397Skan	return 0;
487117397Skan}
488117397Skan
489117397Skan
490117397Skanu8 * ikev2_decrypt_payload(int encr_id, int integ_id,
491117397Skan			   struct ikev2_keys *keys, int initiator,
492117397Skan			   const struct ikev2_hdr *hdr,
493117397Skan			   const u8 *encrypted, size_t encrypted_len,
494117397Skan			   size_t *res_len)
49597403Sobrien{
496117397Skan	size_t iv_len;
49797403Sobrien	const u8 *pos, *end, *iv, *integ;
498117397Skan	u8 hash[IKEV2_MAX_HASH_LEN], *decrypted;
499117397Skan	size_t decrypted_len, pad_len;
500117397Skan	const struct ikev2_integ_alg *integ_alg;
501117397Skan	const struct ikev2_encr_alg *encr_alg;
502117397Skan	const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
503117397Skan	const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
504117397Skan
505117397Skan	if (encrypted == NULL) {
506117397Skan		wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH");
507117397Skan		return NULL;
508117397Skan	}
509117397Skan
510117397Skan	encr_alg = ikev2_get_encr(encr_id);
511117397Skan	if (encr_alg == NULL) {
512117397Skan		wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
51397403Sobrien		return NULL;
514117397Skan	}
51597403Sobrien	iv_len = encr_alg->block_size;
516117397Skan
517117397Skan	integ_alg = ikev2_get_integ(integ_id);
518117397Skan	if (integ_alg == NULL) {
519117397Skan		wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
520117397Skan		return NULL;
521117397Skan	}
522117397Skan
523117397Skan	if (encrypted_len < iv_len + 1 + integ_alg->hash_len) {
524117397Skan		wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity "
525117397Skan			  "Checksum");
526117397Skan		return NULL;
52797403Sobrien	}
528117397Skan
52997403Sobrien	iv = encrypted;
530117397Skan	pos = iv + iv_len;
531117397Skan	end = encrypted + encrypted_len;
532117397Skan	integ = end - integ_alg->hash_len;
533117397Skan
534117397Skan	if (SK_a == NULL) {
535117397Skan		wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
536117397Skan		return NULL;
537117397Skan	}
538117397Skan	if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
539117397Skan			     (const u8 *) hdr,
540117397Skan			     integ - (const u8 *) hdr, hash) < 0) {
541117397Skan		wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity "
54297403Sobrien			   "hash");
54397403Sobrien		return NULL;
54497403Sobrien	}
545117397Skan	if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) {
546117397Skan		wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum "
547117397Skan			   "Data");
548117397Skan		return NULL;
549117397Skan	}
550117397Skan
551117397Skan	if (SK_e == NULL) {
552117397Skan		wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
553117397Skan		return NULL;
554117397Skan	}
555117397Skan
556117397Skan	decrypted_len = integ - pos;
557117397Skan	decrypted = os_malloc(decrypted_len);
55897403Sobrien	if (decrypted == NULL)
55997403Sobrien		return NULL;
560117397Skan
561132720Skan	if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos,
562132720Skan			       decrypted, decrypted_len) < 0) {
563132720Skan		os_free(decrypted);
564132720Skan		return NULL;
56597403Sobrien	}
56697403Sobrien
567117397Skan	pad_len = decrypted[decrypted_len - 1];
568117397Skan	if (decrypted_len < pad_len + 1) {
569117397Skan		wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted "
570117397Skan			   "payload");
571117397Skan		os_free(decrypted);
572117397Skan		return NULL;
573117397Skan	}
574117397Skan
575117397Skan	decrypted_len -= pad_len + 1;
576117397Skan
577117397Skan	*res_len = decrypted_len;
57897403Sobrien	return decrypted;
57997403Sobrien}
58097403Sobrien
58197403Sobrien
582117397Skanvoid ikev2_update_hdr(struct wpabuf *msg)
58397403Sobrien{
58497403Sobrien	struct ikev2_hdr *hdr;
58597403Sobrien
58697403Sobrien	/* Update lenth field in HDR */
58797403Sobrien	hdr = wpabuf_mhead(msg);
58897403Sobrien	WPA_PUT_BE32(hdr->length, wpabuf_len(msg));
589117397Skan}
590117397Skan
591117397Skan
592117397Skanint ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys,
593117397Skan			  int initiator, struct wpabuf *msg,
594117397Skan			  struct wpabuf *plain, u8 next_payload)
595117397Skan{
596117397Skan	struct ikev2_payload_hdr *phdr;
597117397Skan	size_t plen;
598117397Skan	size_t iv_len, pad_len;
599117397Skan	u8 *icv, *iv;
600117397Skan	const struct ikev2_integ_alg *integ_alg;
601117397Skan	const struct ikev2_encr_alg *encr_alg;
602117397Skan	const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
603117397Skan	const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
604117397Skan
605117397Skan	wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload");
606117397Skan
607117397Skan	/* Encr - RFC 4306, Sect. 3.14 */
608117397Skan
609117397Skan	encr_alg = ikev2_get_encr(encr_id);
61097403Sobrien	if (encr_alg == NULL) {
61197403Sobrien		wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
61297403Sobrien		return -1;
613117397Skan	}
614117397Skan	iv_len = encr_alg->block_size;
615117397Skan
616117397Skan	integ_alg = ikev2_get_integ(integ_id);
617117397Skan	if (integ_alg == NULL) {
618117397Skan		wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
619117397Skan		return -1;
620132720Skan	}
62197403Sobrien
62297403Sobrien	if (SK_e == NULL) {
62397403Sobrien		wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
62497403Sobrien		return -1;
62597403Sobrien	}
626117397Skan
627117397Skan	if (SK_a == NULL) {
628117397Skan		wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
629117397Skan		return -1;
630117397Skan	}
631117397Skan
632117397Skan	phdr = wpabuf_put(msg, sizeof(*phdr));
633117397Skan	phdr->next_payload = next_payload;
634117397Skan	phdr->flags = 0;
635117397Skan
636117397Skan	iv = wpabuf_put(msg, iv_len);
637117397Skan	if (random_get_bytes(iv, iv_len)) {
638117397Skan		wpa_printf(MSG_INFO, "IKEV2: Could not generate IV");
63997403Sobrien		return -1;
64097403Sobrien	}
64197403Sobrien
64297403Sobrien	pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len;
64397403Sobrien	if (pad_len == iv_len)
64497403Sobrien		pad_len = 0;
64597403Sobrien	wpabuf_put(plain, pad_len);
64697403Sobrien	wpabuf_put_u8(plain, pad_len);
64797403Sobrien
64897403Sobrien	if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv,
64997403Sobrien			       wpabuf_head(plain), wpabuf_mhead(plain),
65097403Sobrien			       wpabuf_len(plain)) < 0)
65197403Sobrien		return -1;
652117397Skan
65397403Sobrien	wpabuf_put_buf(msg, plain);
654117397Skan
655117397Skan	/* Need to update all headers (Length fields) prior to hash func */
656117397Skan	icv = wpabuf_put(msg, integ_alg->hash_len);
657117397Skan	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
658117397Skan	WPA_PUT_BE16(phdr->payload_length, plen);
659117397Skan
660117397Skan	ikev2_update_hdr(msg);
661117397Skan
662117397Skan	return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
663117397Skan				wpabuf_head(msg),
664117397Skan				wpabuf_len(msg) - integ_alg->hash_len, icv);
665117397Skan
666117397Skan	return 0;
667117397Skan}
668117397Skan
669117397Skan
670117397Skanint ikev2_keys_set(struct ikev2_keys *keys)
671117397Skan{
672117397Skan	return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei &&
673117397Skan		keys->SK_er && keys->SK_pi && keys->SK_pr;
674117397Skan}
675117397Skan
676117397Skan
677117397Skanvoid ikev2_free_keys(struct ikev2_keys *keys)
678117397Skan{
679117397Skan	os_free(keys->SK_d);
68097403Sobrien	os_free(keys->SK_ai);
68197403Sobrien	os_free(keys->SK_ar);
68297403Sobrien	os_free(keys->SK_ei);
68397403Sobrien	os_free(keys->SK_er);
68497403Sobrien	os_free(keys->SK_pi);
68597403Sobrien	os_free(keys->SK_pr);
68697403Sobrien	keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er =
68797403Sobrien		keys->SK_pi = keys->SK_pr = NULL;
68897403Sobrien}
68997403Sobrien
69097403Sobrien
69197403Sobrienint ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf,
69297403Sobrien			 const struct ikev2_integ_alg *integ,
693117397Skan			 const struct ikev2_encr_alg *encr,
69497403Sobrien			 const u8 *skeyseed, const u8 *data, size_t data_len,
69597403Sobrien			 struct ikev2_keys *keys)
696117397Skan{
697117397Skan	u8 *keybuf, *pos;
698117397Skan	size_t keybuf_len;
699117397Skan
700117397Skan	/*
701117397Skan	 * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } =
70297403Sobrien	 *	prf+(SKEYSEED, Ni | Nr | SPIi | SPIr )
70397403Sobrien	 */
70497403Sobrien	ikev2_free_keys(keys);
70597403Sobrien	keys->SK_d_len = prf->key_len;
70697403Sobrien	keys->SK_integ_len = integ->key_len;
70797403Sobrien	keys->SK_encr_len = encr->key_len;
708132720Skan	keys->SK_prf_len = prf->key_len;
709132720Skan#ifdef CCNS_PL
710102782Skan	/* Uses encryption key length for SK_d; should be PRF length */
711102782Skan	keys->SK_d_len = keys->SK_encr_len;
712102782Skan#endif /* CCNS_PL */
713102782Skan
714102782Skan	keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
715102782Skan		2 * keys->SK_encr_len + 2 * keys->SK_prf_len;
716102782Skan	keybuf = os_malloc(keybuf_len);
71797403Sobrien	if (keybuf == NULL)
71897403Sobrien		return -1;
71997403Sobrien
72097403Sobrien	if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len,
721117397Skan			   data, data_len, keybuf, keybuf_len)) {
722117397Skan		os_free(keybuf);
723117397Skan		return -1;
724117397Skan	}
725117397Skan
726117397Skan	pos = keybuf;
72797403Sobrien
72897403Sobrien	keys->SK_d = os_malloc(keys->SK_d_len);
729132720Skan	if (keys->SK_d) {
730132720Skan		os_memcpy(keys->SK_d, pos, keys->SK_d_len);
73197403Sobrien		wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d",
732117397Skan				keys->SK_d, keys->SK_d_len);
733117397Skan	}
734117397Skan	pos += keys->SK_d_len;
73597403Sobrien
73697403Sobrien	keys->SK_ai = os_malloc(keys->SK_integ_len);
737132720Skan	if (keys->SK_ai) {
738132720Skan		os_memcpy(keys->SK_ai, pos, keys->SK_integ_len);
739132720Skan		wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai",
740132720Skan				keys->SK_ai, keys->SK_integ_len);
741132720Skan	}
74297403Sobrien	pos += keys->SK_integ_len;
74397403Sobrien
744117397Skan	keys->SK_ar = os_malloc(keys->SK_integ_len);
745117397Skan	if (keys->SK_ar) {
746117397Skan		os_memcpy(keys->SK_ar, pos, keys->SK_integ_len);
747117397Skan		wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar",
748117397Skan				keys->SK_ar, keys->SK_integ_len);
749117397Skan	}
750117397Skan	pos += keys->SK_integ_len;
751117397Skan
752117397Skan	keys->SK_ei = os_malloc(keys->SK_encr_len);
753117397Skan	if (keys->SK_ei) {
754117397Skan		os_memcpy(keys->SK_ei, pos, keys->SK_encr_len);
755117397Skan		wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei",
756117397Skan				keys->SK_ei, keys->SK_encr_len);
757117397Skan	}
758117397Skan	pos += keys->SK_encr_len;
759117397Skan
760117397Skan	keys->SK_er = os_malloc(keys->SK_encr_len);
761117397Skan	if (keys->SK_er) {
762117397Skan		os_memcpy(keys->SK_er, pos, keys->SK_encr_len);
763117397Skan		wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er",
764117397Skan				keys->SK_er, keys->SK_encr_len);
76597403Sobrien	}
76697403Sobrien	pos += keys->SK_encr_len;
76797403Sobrien
76897403Sobrien	keys->SK_pi = os_malloc(keys->SK_prf_len);
76997403Sobrien	if (keys->SK_pi) {
770132720Skan		os_memcpy(keys->SK_pi, pos, keys->SK_prf_len);
77197403Sobrien		wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi",
77297403Sobrien				keys->SK_pi, keys->SK_prf_len);
77397403Sobrien	}
774132720Skan	pos += keys->SK_prf_len;
775
776	keys->SK_pr = os_malloc(keys->SK_prf_len);
777	if (keys->SK_pr) {
778		os_memcpy(keys->SK_pr, pos, keys->SK_prf_len);
779		wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr",
780				keys->SK_pr, keys->SK_prf_len);
781	}
782
783	os_free(keybuf);
784
785	if (!ikev2_keys_set(keys)) {
786		ikev2_free_keys(keys);
787		return -1;
788	}
789
790	return 0;
791}
792