18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IKEv2 common routines for initiator and responder 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ikev2_common.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct ikev2_integ_alg ikev2_integ_algs[] = { 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { AUTH_HMAC_SHA1_96, 20, 12 }, 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { AUTH_HMAC_MD5_96, 16, 12 } 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define NUM_INTEG_ALGS ARRAY_SIZE(ikev2_integ_algs) 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct ikev2_prf_alg ikev2_prf_algs[] = { 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { PRF_HMAC_SHA1, 20, 20 }, 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { PRF_HMAC_MD5, 16, 16 } 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define NUM_PRF_ALGS ARRAY_SIZE(ikev2_prf_algs) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct ikev2_encr_alg ikev2_encr_algs[] = { 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { ENCR_3DES, 24, 8 } 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define NUM_ENCR_ALGS ARRAY_SIZE(ikev2_encr_algs) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct ikev2_integ_alg * ikev2_get_integ(int id) 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < NUM_INTEG_ALGS; i++) { 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_integ_algs[i].id == id) 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &ikev2_integ_algs[i]; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data, 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len, u8 *hash) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 tmphash[IKEV2_MAX_HASH_LEN]; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AUTH_HMAC_SHA1_96: 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len != 20) 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1(key, key_len, data, data_len, tmphash); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hash, tmphash, 12); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AUTH_HMAC_MD5_96: 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len != 16) 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_md5(key, key_len, data, data_len, tmphash); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hash, tmphash, 12); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct ikev2_prf_alg * ikev2_get_prf(int id) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < NUM_PRF_ALGS; i++) { 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_algs[i].id == id) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &ikev2_prf_algs[i]; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_prf_hash(int alg, const u8 *key, size_t key_len, 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_elem, const u8 *addr[], const size_t *len, 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *hash) 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PRF_HMAC_SHA1: 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(key, key_len, num_elem, addr, len, hash); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PRF_HMAC_MD5: 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_md5_vector(key, key_len, num_elem, addr, len, hash); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_prf_plus(int alg, const u8 *key, size_t key_len, 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t data_len, 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *out, size_t out_len) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[IKEV2_MAX_HASH_LEN]; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hash_len; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 iter, *pos, *end; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_prf_alg *prf; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prf = ikev2_get_prf(alg); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prf == NULL) 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = prf->hash_len; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = hash; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = hash_len; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = data; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = data_len; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = &iter; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = 1; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = out; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = out + out_len; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iter = 1; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < end) { 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t clen; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iter == 1) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1], 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len[1], hash); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = ikev2_prf_hash(alg, key, key_len, 3, addr, len, 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clen = hash_len; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((int) clen > end - pos) 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clen = end - pos; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, hash, clen); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += clen; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iter++; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct ikev2_encr_alg * ikev2_get_encr(int id) 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < NUM_ENCR_ALGS; i++) { 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_encr_algs[i].id == id) 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &ikev2_encr_algs[i]; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *plain, u8 *crypt, size_t len) 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_cipher *cipher; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encr_alg; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_3DES: 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_3DES; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_AES_CBC: 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_AES; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = crypto_cipher_init(encr_alg, iv, key, key_len); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == NULL) { 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) { 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Encryption failed"); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *crypt, u8 *plain, size_t len) 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_cipher *cipher; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encr_alg; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_3DES: 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_3DES; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_AES_CBC: 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_AES; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = crypto_cipher_init(encr_alg, iv, key, key_len); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == NULL) { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Decryption failed"); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_parse_payloads(struct ikev2_payloads *payloads, 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 next_payload, const u8 *pos, const u8 *end) 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_payload_hdr *phdr; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(payloads, 0, sizeof(*payloads)); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) { 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int plen, pdatalen; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pdata; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u", 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) sizeof(*phdr)) { 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short message for " 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payload header (left=%ld)", 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long) (end - pos)); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = (const struct ikev2_payload_hdr *) pos; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = WPA_GET_BE16(phdr->payload_length); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plen < (int) sizeof(*phdr) || pos + plen > end) { 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid payload header " 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length %d", plen); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x" 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Payload Length: %d", 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload, phdr->flags, plen); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pdata = (const u8 *) (phdr + 1); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pdatalen = plen - sizeof(*phdr); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (next_payload) { 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_SA: 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security " 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Association"); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->sa = pdata; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->sa_len = pdatalen; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_KEY_EXCHANGE: 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key " 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Exchange"); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->ke = pdata; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->ke_len = pdatalen; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_IDi: 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi"); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idi = pdata; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idi_len = pdatalen; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_IDr: 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr"); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idr = pdata; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idr_len = pdatalen; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_CERTIFICATE: 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate"); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->cert = pdata; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->cert_len = pdatalen; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_AUTHENTICATION: 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: " 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Authentication"); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->auth = pdata; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->auth_len = pdatalen; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_NONCE: 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce"); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->nonce = pdata; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->nonce_len = pdatalen; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_ENCRYPTED: 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted"); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->encrypted = pdata; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->encrypted_len = pdatalen; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_NOTIFICATION: 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: " 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Notification"); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->notification = pdata; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->notification_len = pdatalen; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) { 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported " 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "critical payload %u - reject the " 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "entire message", next_payload); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Skipped " 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unsupported payload %u", 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (next_payload == IKEV2_PAYLOAD_ENCRYPTED && 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + plen == end) { 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Next Payload in the case of Encrypted Payload is 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * actually the payload type for the first embedded 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * payload. 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->encr_next_payload = phdr->next_payload; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload = phdr->next_payload; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += plen; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos != end) { 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after " 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payloads"); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg, 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ID, size_t ID_len, u8 ID_type, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_keys *keys, int initiator, 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, size_t shared_secret_len, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce, size_t nonce_len, 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_pad, size_t key_pad_len, 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *auth_data) 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t sign_len, buf_len; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN]; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_prf_alg *prf; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prf = ikev2_get_prf(prf_alg); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sign_msg == NULL || ID == NULL || SK_p == NULL || 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret == NULL || nonce == NULL || prf == NULL) 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* prf(SK_pi/r,IDi/r') */ 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 4 + ID_len; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(buf_len); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[0] = ID_type; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf + 4, ID, ID_len); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len, 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1, (const u8 **) &buf, &buf_len, hash) < 0) { 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */ 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sign_data = os_malloc(sign_len); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sign_data == NULL) 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = sign_data; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg)); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpabuf_len(sign_msg); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, nonce, nonce_len); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += nonce_len; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, hash, prf->hash_len); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */ 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1, 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &key_pad, &key_pad_len, hash) < 0 || 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_prf_hash(prf->id, hash, prf->hash_len, 1, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 **) &sign_data, &sign_len, auth_data) < 0) 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sign_data); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sign_data); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * ikev2_decrypt_payload(int encr_id, int integ_id, 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_keys *keys, int initiator, 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_hdr *hdr, 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *encrypted, size_t encrypted_len, 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *res_len) 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t iv_len; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *iv, *integ; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[IKEV2_MAX_HASH_LEN], *decrypted; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t decrypted_len, pad_len; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ_alg; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_encr_alg *encr_alg; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypted == NULL) { 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH"); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = ikev2_get_encr(encr_id); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr_alg == NULL) { 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv_len = encr_alg->block_size; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ_alg = ikev2_get_integ(integ_id); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (integ_alg == NULL) { 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypted_len < iv_len + 1 + integ_alg->hash_len) { 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity " 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Checksum"); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv = encrypted; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = iv + iv_len; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = encrypted + encrypted_len; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ = end - integ_alg->hash_len; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_a == NULL) { 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 *) hdr, 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ - (const u8 *) hdr, hash) < 0) { 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity " 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hash"); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 480c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(integ, hash, integ_alg->hash_len) != 0) { 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum " 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Data"); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_e == NULL) { 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted_len = integ - pos; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = os_malloc(decrypted_len); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos, 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted, decrypted_len) < 0) { 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = decrypted[decrypted_len - 1]; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted_len < pad_len + 1) { 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted " 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payload"); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted_len -= pad_len + 1; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *res_len = decrypted_len; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return decrypted; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ikev2_update_hdr(struct wpabuf *msg) 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_hdr *hdr; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Update lenth field in HDR */ 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = wpabuf_mhead(msg); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(hdr->length, wpabuf_len(msg)); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int initiator, struct wpabuf *msg, 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain, u8 next_payload) 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t iv_len, pad_len; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *icv, *iv; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ_alg; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_encr_alg *encr_alg; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload"); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Encr - RFC 4306, Sect. 3.14 */ 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = ikev2_get_encr(encr_id); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr_alg == NULL) { 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv_len = encr_alg->block_size; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ_alg = ikev2_get_integ(integ_id); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (integ_alg == NULL) { 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_e == NULL) { 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_a == NULL) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv = wpabuf_put(msg, iv_len); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(iv, iv_len)) { 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Could not generate IV"); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len == iv_len) 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = 0; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(plain, pad_len); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(plain, pad_len); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(plain), wpabuf_mhead(plain), 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(plain)) < 0) 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(msg, plain); 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need to update all headers (Length fields) prior to hash func */ 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icv = wpabuf_put(msg, integ_alg->hash_len); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_update_hdr(msg); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(msg), 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(msg) - integ_alg->hash_len, icv); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_keys_set(struct ikev2_keys *keys) 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei && 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_er && keys->SK_pi && keys->SK_pr; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ikev2_free_keys(struct ikev2_keys *keys) 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_d); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_ai); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_ar); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_ei); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_er); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_pi); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_pr); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er = 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pi = keys->SK_pr = NULL; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf, 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ, 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_encr_alg *encr, 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *skeyseed, const u8 *data, size_t data_len, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_keys *keys) 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *keybuf, *pos; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t keybuf_len; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * prf+(SKEYSEED, Ni | Nr | SPIi | SPIr ) 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_free_keys(keys); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d_len = prf->key_len; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_integ_len = integ->key_len; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_encr_len = encr->key_len; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_prf_len = prf->key_len; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len + 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 * keys->SK_encr_len + 2 * keys->SK_prf_len; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keybuf = os_malloc(keybuf_len); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keybuf == NULL) 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len, 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, data_len, keybuf, keybuf_len)) { 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keybuf); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = keybuf; 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d = os_malloc(keys->SK_d_len); 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_d) { 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_d, pos, keys->SK_d_len); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d", 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d, keys->SK_d_len); 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_d_len; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ai = os_malloc(keys->SK_integ_len); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_ai) { 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_ai, pos, keys->SK_integ_len); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai", 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ai, keys->SK_integ_len); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_integ_len; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ar = os_malloc(keys->SK_integ_len); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_ar) { 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_ar, pos, keys->SK_integ_len); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar", 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ar, keys->SK_integ_len); 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_integ_len; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ei = os_malloc(keys->SK_encr_len); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_ei) { 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_ei, pos, keys->SK_encr_len); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei", 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ei, keys->SK_encr_len); 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_encr_len; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_er = os_malloc(keys->SK_encr_len); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_er) { 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_er, pos, keys->SK_encr_len); 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er", 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_er, keys->SK_encr_len); 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_encr_len; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pi = os_malloc(keys->SK_prf_len); 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_pi) { 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_pi, pos, keys->SK_prf_len); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi", 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pi, keys->SK_prf_len); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_prf_len; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pr = os_malloc(keys->SK_prf_len); 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_pr) { 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_pr, pos, keys->SK_prf_len); 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr", 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pr, keys->SK_prf_len); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keybuf); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ikev2_keys_set(keys)) { 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_free_keys(keys); 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 723