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 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0])) 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 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0])) 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 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0])) 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 Shmidt#ifdef CCNS_PL 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* from des.c */ 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct des3_key_s { 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 ek[3][32]; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 dk[3][32]; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid des3_key_setup(const u8 *key, struct des3_key_s *dkey); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *plain, u8 *crypt, size_t len) 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_cipher *cipher; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encr_alg; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alg == ENCR_3DES) { 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct des3_key_s des3key; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, blocks; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ECB mode is used incorrectly for 3DES!? */ 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len != 24) { 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des3_key_setup(key, &des3key); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blocks = len / 8; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = crypt; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < blocks; i++) { 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des3_encrypt(pos, &des3key, pos); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_3DES: 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_3DES; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_AES_CBC: 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_AES; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = crypto_cipher_init(encr_alg, iv, key, key_len); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == NULL) { 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) { 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Encryption failed"); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *crypt, u8 *plain, size_t len) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_cipher *cipher; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encr_alg; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alg == ENCR_3DES) { 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct des3_key_s des3key; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, blocks; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ECB mode is used incorrectly for 3DES!? */ 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len != 24) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des3_key_setup(key, &des3key); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len % 8) { 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted " 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length"); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blocks = len / 8; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < blocks; i++) { 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt des3_decrypt(crypt, &des3key, plain); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plain += 8; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypt += 8; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_3DES: 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_3DES; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ENCR_AES_CBC: 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_AES; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = crypto_cipher_init(encr_alg, iv, key, key_len); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == NULL) { 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) { 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Decryption failed"); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_cipher_deinit(cipher); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_parse_payloads(struct ikev2_payloads *payloads, 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 next_payload, const u8 *pos, const u8 *end) 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_payload_hdr *phdr; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(payloads, 0, sizeof(*payloads)); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) { 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int plen, pdatalen; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pdata; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u", 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) sizeof(*phdr)) { 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short message for " 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payload header (left=%ld)", 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long) (end - pos)); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = (const struct ikev2_payload_hdr *) pos; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = WPA_GET_BE16(phdr->payload_length); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plen < (int) sizeof(*phdr) || pos + plen > end) { 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid payload header " 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length %d", plen); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x" 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Payload Length: %d", 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload, phdr->flags, plen); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pdata = (const u8 *) (phdr + 1); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pdatalen = plen - sizeof(*phdr); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (next_payload) { 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_SA: 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security " 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Association"); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->sa = pdata; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->sa_len = pdatalen; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_KEY_EXCHANGE: 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key " 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Exchange"); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->ke = pdata; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->ke_len = pdatalen; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_IDi: 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi"); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idi = pdata; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idi_len = pdatalen; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_IDr: 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr"); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idr = pdata; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->idr_len = pdatalen; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_CERTIFICATE: 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate"); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->cert = pdata; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->cert_len = pdatalen; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_AUTHENTICATION: 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: " 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Authentication"); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->auth = pdata; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->auth_len = pdatalen; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_NONCE: 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce"); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->nonce = pdata; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->nonce_len = pdatalen; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_ENCRYPTED: 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted"); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->encrypted = pdata; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->encrypted_len = pdatalen; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_PAYLOAD_NOTIFICATION: 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: " 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Notification"); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->notification = pdata; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->notification_len = pdatalen; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) { 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported " 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "critical payload %u - reject the " 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "entire message", next_payload); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Skipped " 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unsupported payload %u", 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (next_payload == IKEV2_PAYLOAD_ENCRYPTED && 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + plen == end) { 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Next Payload in the case of Encrypted Payload is 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * actually the payload type for the first embedded 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * payload. 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payloads->encr_next_payload = phdr->next_payload; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_payload = phdr->next_payload; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += plen; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos != end) { 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after " 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payloads"); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg, 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ID, size_t ID_len, u8 ID_type, 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_keys *keys, int initiator, 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, size_t shared_secret_len, 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce, size_t nonce_len, 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key_pad, size_t key_pad_len, 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *auth_data) 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t sign_len, buf_len; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN]; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_prf_alg *prf; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prf = ikev2_get_prf(prf_alg); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sign_msg == NULL || ID == NULL || SK_p == NULL || 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret == NULL || nonce == NULL || prf == NULL) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* prf(SK_pi/r,IDi/r') */ 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 4 + ID_len; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(buf_len); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[0] = ID_type; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf + 4, ID, ID_len); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len, 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1, (const u8 **) &buf, &buf_len, hash) < 0) { 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */ 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sign_data = os_malloc(sign_len); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sign_data == NULL) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = sign_data; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg)); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpabuf_len(sign_msg); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, nonce, nonce_len); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += nonce_len; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, hash, prf->hash_len); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */ 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1, 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &key_pad, &key_pad_len, hash) < 0 || 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_prf_hash(prf->id, hash, prf->hash_len, 1, 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 **) &sign_data, &sign_len, auth_data) < 0) 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sign_data); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sign_data); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * ikev2_decrypt_payload(int encr_id, int integ_id, 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_keys *keys, int initiator, 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_hdr *hdr, 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *encrypted, size_t encrypted_len, 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *res_len) 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t iv_len; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *iv, *integ; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[IKEV2_MAX_HASH_LEN], *decrypted; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t decrypted_len, pad_len; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ_alg; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_encr_alg *encr_alg; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypted == NULL) { 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH"); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = ikev2_get_encr(encr_id); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr_alg == NULL) { 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv_len = encr_alg->block_size; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ_alg = ikev2_get_integ(integ_id); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (integ_alg == NULL) { 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypted_len < iv_len + 1 + integ_alg->hash_len) { 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity " 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Checksum"); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv = encrypted; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = iv + iv_len; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = encrypted + encrypted_len; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ = end - integ_alg->hash_len; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_a == NULL) { 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 *) hdr, 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ - (const u8 *) hdr, hash) < 0) { 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity " 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hash"); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) { 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum " 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Data"); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_e == NULL) { 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted_len = integ - pos; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = os_malloc(decrypted_len); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos, 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted, decrypted_len) < 0) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = decrypted[decrypted_len - 1]; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted_len < pad_len + 1) { 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted " 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payload"); 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted_len -= pad_len + 1; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *res_len = decrypted_len; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return decrypted; 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ikev2_update_hdr(struct wpabuf *msg) 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_hdr *hdr; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Update lenth field in HDR */ 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = wpabuf_mhead(msg); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(hdr->length, wpabuf_len(msg)); 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int initiator, struct wpabuf *msg, 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain, u8 next_payload) 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t iv_len, pad_len; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *icv, *iv; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ_alg; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_encr_alg *encr_alg; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload"); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Encr - RFC 4306, Sect. 3.14 */ 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_alg = ikev2_get_encr(encr_id); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr_alg == NULL) { 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv_len = encr_alg->block_size; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ_alg = ikev2_get_integ(integ_id); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (integ_alg == NULL) { 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_e == NULL) { 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_a == NULL) { 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv = wpabuf_put(msg, iv_len); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(iv, iv_len)) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Could not generate IV"); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad_len == iv_len) 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = 0; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(plain, pad_len); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(plain, pad_len); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(plain), wpabuf_mhead(plain), 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(plain)) < 0) 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(msg, plain); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need to update all headers (Length fields) prior to hash func */ 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icv = wpabuf_put(msg, integ_alg->hash_len); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_update_hdr(msg); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(msg), 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(msg) - integ_alg->hash_len, icv); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_keys_set(struct ikev2_keys *keys) 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei && 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_er && keys->SK_pi && keys->SK_pr; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ikev2_free_keys(struct ikev2_keys *keys) 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_d); 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_ai); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_ar); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_ei); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_er); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_pi); 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->SK_pr); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er = 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pi = keys->SK_pr = NULL; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf, 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ, 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_encr_alg *encr, 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *skeyseed, const u8 *data, size_t data_len, 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_keys *keys) 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *keybuf, *pos; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t keybuf_len; 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * prf+(SKEYSEED, Ni | Nr | SPIi | SPIr ) 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_free_keys(keys); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d_len = prf->key_len; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_integ_len = integ->key_len; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_encr_len = encr->key_len; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_prf_len = prf->key_len; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Uses encryption key length for SK_d; should be PRF length */ 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d_len = keys->SK_encr_len; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len + 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 * keys->SK_encr_len + 2 * keys->SK_prf_len; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keybuf = os_malloc(keybuf_len); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keybuf == NULL) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len, 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, data_len, keybuf, keybuf_len)) { 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keybuf); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = keybuf; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d = os_malloc(keys->SK_d_len); 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_d) { 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_d, pos, keys->SK_d_len); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d", 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_d, keys->SK_d_len); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_d_len; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ai = os_malloc(keys->SK_integ_len); 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_ai) { 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_ai, pos, keys->SK_integ_len); 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai", 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ai, keys->SK_integ_len); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_integ_len; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ar = os_malloc(keys->SK_integ_len); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_ar) { 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_ar, pos, keys->SK_integ_len); 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar", 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ar, keys->SK_integ_len); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_integ_len; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ei = os_malloc(keys->SK_encr_len); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_ei) { 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_ei, pos, keys->SK_encr_len); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei", 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_ei, keys->SK_encr_len); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_encr_len; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_er = os_malloc(keys->SK_encr_len); 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_er) { 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_er, pos, keys->SK_encr_len); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er", 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_er, keys->SK_encr_len); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_encr_len; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pi = os_malloc(keys->SK_prf_len); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_pi) { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_pi, pos, keys->SK_prf_len); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi", 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pi, keys->SK_prf_len); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += keys->SK_prf_len; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pr = os_malloc(keys->SK_prf_len); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_pr) { 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(keys->SK_pr, pos, keys->SK_prf_len); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr", 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->SK_pr, keys->SK_prf_len); 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keybuf); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ikev2_keys_set(keys)) { 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_free_keys(keys); 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 792