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