00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016
00017 #include "common.h"
00018 #include "crypto/crypto.h"
00019 #include "crypto/md5.h"
00020 #include "crypto/sha1.h"
00021 #include "ikev2_common.h"
00022
00023
00024 static struct ikev2_integ_alg ikev2_integ_algs[] = {
00025 { AUTH_HMAC_SHA1_96, 20, 12 },
00026 { AUTH_HMAC_MD5_96, 16, 12 }
00027 };
00028
00029 #define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0]))
00030
00031
00032 static struct ikev2_prf_alg ikev2_prf_algs[] = {
00033 { PRF_HMAC_SHA1, 20, 20 },
00034 { PRF_HMAC_MD5, 16, 16 }
00035 };
00036
00037 #define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0]))
00038
00039
00040 static struct ikev2_encr_alg ikev2_encr_algs[] = {
00041 { ENCR_AES_CBC, 16, 16 },
00042 { ENCR_3DES, 24, 8 }
00043 };
00044
00045 #define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0]))
00046
00047
00048 const struct ikev2_integ_alg * ikev2_get_integ(int id)
00049 {
00050 size_t i;
00051
00052 for (i = 0; i < NUM_INTEG_ALGS; i++) {
00053 if (ikev2_integ_algs[i].id == id)
00054 return &ikev2_integ_algs[i];
00055 }
00056
00057 return NULL;
00058 }
00059
00060
00061 int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data,
00062 size_t data_len, u8 *hash)
00063 {
00064 u8 tmphash[IKEV2_MAX_HASH_LEN];
00065
00066 switch (alg) {
00067 case AUTH_HMAC_SHA1_96:
00068 if (key_len != 20)
00069 return -1;
00070 hmac_sha1(key, key_len, data, data_len, tmphash);
00071 os_memcpy(hash, tmphash, 12);
00072 break;
00073 case AUTH_HMAC_MD5_96:
00074 if (key_len != 16)
00075 return -1;
00076 hmac_md5(key, key_len, data, data_len, tmphash);
00077 os_memcpy(hash, tmphash, 12);
00078 break;
00079 default:
00080 return -1;
00081 }
00082
00083 return 0;
00084 }
00085
00086
00087 const struct ikev2_prf_alg * ikev2_get_prf(int id)
00088 {
00089 size_t i;
00090
00091 for (i = 0; i < NUM_PRF_ALGS; i++) {
00092 if (ikev2_prf_algs[i].id == id)
00093 return &ikev2_prf_algs[i];
00094 }
00095
00096 return NULL;
00097 }
00098
00099
00100 int ikev2_prf_hash(int alg, const u8 *key, size_t key_len,
00101 size_t num_elem, const u8 *addr[], const size_t *len,
00102 u8 *hash)
00103 {
00104 switch (alg) {
00105 case PRF_HMAC_SHA1:
00106 hmac_sha1_vector(key, key_len, num_elem, addr, len, hash);
00107 break;
00108 case PRF_HMAC_MD5:
00109 hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
00110 break;
00111 default:
00112 return -1;
00113 }
00114
00115 return 0;
00116 }
00117
00118
00119 int ikev2_prf_plus(int alg, const u8 *key, size_t key_len,
00120 const u8 *data, size_t data_len,
00121 u8 *out, size_t out_len)
00122 {
00123 u8 hash[IKEV2_MAX_HASH_LEN];
00124 size_t hash_len;
00125 u8 iter, *pos, *end;
00126 const u8 *addr[3];
00127 size_t len[3];
00128 const struct ikev2_prf_alg *prf;
00129 int res;
00130
00131 prf = ikev2_get_prf(alg);
00132 if (prf == NULL)
00133 return -1;
00134 hash_len = prf->hash_len;
00135
00136 addr[0] = hash;
00137 len[0] = hash_len;
00138 addr[1] = data;
00139 len[1] = data_len;
00140 addr[2] = &iter;
00141 len[2] = 1;
00142
00143 pos = out;
00144 end = out + out_len;
00145 iter = 1;
00146 while (pos < end) {
00147 size_t clen;
00148 if (iter == 1)
00149 res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1],
00150 &len[1], hash);
00151 else
00152 res = ikev2_prf_hash(alg, key, key_len, 3, addr, len,
00153 hash);
00154 if (res < 0)
00155 return -1;
00156 clen = hash_len;
00157 if ((int) clen > end - pos)
00158 clen = end - pos;
00159 os_memcpy(pos, hash, clen);
00160 pos += clen;
00161 iter++;
00162 }
00163
00164 return 0;
00165 }
00166
00167
00168 const struct ikev2_encr_alg * ikev2_get_encr(int id)
00169 {
00170 size_t i;
00171
00172 for (i = 0; i < NUM_ENCR_ALGS; i++) {
00173 if (ikev2_encr_algs[i].id == id)
00174 return &ikev2_encr_algs[i];
00175 }
00176
00177 return NULL;
00178 }
00179
00180
00181 #ifdef CCNS_PL
00182
00183 struct des3_key_s {
00184 u32 ek[3][32];
00185 u32 dk[3][32];
00186 };
00187
00188 void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
00189 void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
00190 void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
00191 #endif
00192
00193
00194 int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
00195 const u8 *plain, u8 *crypt, size_t len)
00196 {
00197 struct crypto_cipher *cipher;
00198 int encr_alg;
00199
00200 #ifdef CCNS_PL
00201 if (alg == ENCR_3DES) {
00202 struct des3_key_s des3key;
00203 size_t i, blocks;
00204 u8 *pos;
00205
00206
00207 if (key_len != 24) {
00208 wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
00209 return -1;
00210 }
00211 des3_key_setup(key, &des3key);
00212
00213 blocks = len / 8;
00214 pos = crypt;
00215 for (i = 0; i < blocks; i++) {
00216 des3_encrypt(pos, &des3key, pos);
00217 pos += 8;
00218 }
00219 } else {
00220 #endif
00221 switch (alg) {
00222 case ENCR_3DES:
00223 encr_alg = CRYPTO_CIPHER_ALG_3DES;
00224 break;
00225 case ENCR_AES_CBC:
00226 encr_alg = CRYPTO_CIPHER_ALG_AES;
00227 break;
00228 default:
00229 wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
00230 return -1;
00231 }
00232
00233 cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
00234 if (cipher == NULL) {
00235 wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
00236 return -1;
00237 }
00238
00239 if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) {
00240 wpa_printf(MSG_INFO, "IKEV2: Encryption failed");
00241 crypto_cipher_deinit(cipher);
00242 return -1;
00243 }
00244 crypto_cipher_deinit(cipher);
00245 #ifdef CCNS_PL
00246 }
00247 #endif
00248
00249 return 0;
00250 }
00251
00252
00253 int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
00254 const u8 *crypt, u8 *plain, size_t len)
00255 {
00256 struct crypto_cipher *cipher;
00257 int encr_alg;
00258
00259 #ifdef CCNS_PL
00260 if (alg == ENCR_3DES) {
00261 struct des3_key_s des3key;
00262 size_t i, blocks;
00263
00264
00265 if (key_len != 24) {
00266 wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
00267 return -1;
00268 }
00269 des3_key_setup(key, &des3key);
00270
00271 if (len % 8) {
00272 wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted "
00273 "length");
00274 return -1;
00275 }
00276 blocks = len / 8;
00277 for (i = 0; i < blocks; i++) {
00278 des3_decrypt(crypt, &des3key, plain);
00279 plain += 8;
00280 crypt += 8;
00281 }
00282 } else {
00283 #endif
00284 switch (alg) {
00285 case ENCR_3DES:
00286 encr_alg = CRYPTO_CIPHER_ALG_3DES;
00287 break;
00288 case ENCR_AES_CBC:
00289 encr_alg = CRYPTO_CIPHER_ALG_AES;
00290 break;
00291 default:
00292 wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
00293 return -1;
00294 }
00295
00296 cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
00297 if (cipher == NULL) {
00298 wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
00299 return -1;
00300 }
00301
00302 if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) {
00303 wpa_printf(MSG_INFO, "IKEV2: Decryption failed");
00304 crypto_cipher_deinit(cipher);
00305 return -1;
00306 }
00307 crypto_cipher_deinit(cipher);
00308 #ifdef CCNS_PL
00309 }
00310 #endif
00311
00312 return 0;
00313 }
00314
00315
00316 int ikev2_parse_payloads(struct ikev2_payloads *payloads,
00317 u8 next_payload, const u8 *pos, const u8 *end)
00318 {
00319 const struct ikev2_payload_hdr *phdr;
00320
00321 os_memset(payloads, 0, sizeof(*payloads));
00322
00323 while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) {
00324 int plen, pdatalen;
00325 const u8 *pdata;
00326 wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u",
00327 next_payload);
00328 if (end - pos < (int) sizeof(*phdr)) {
00329 wpa_printf(MSG_INFO, "IKEV2: Too short message for "
00330 "payload header (left=%ld)",
00331 (long) (end - pos));
00332 }
00333 phdr = (const struct ikev2_payload_hdr *) pos;
00334 plen = WPA_GET_BE16(phdr->payload_length);
00335 if (plen < (int) sizeof(*phdr) || pos + plen > end) {
00336 wpa_printf(MSG_INFO, "IKEV2: Invalid payload header "
00337 "length %d", plen);
00338 return -1;
00339 }
00340
00341 wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x"
00342 " Payload Length: %d",
00343 phdr->next_payload, phdr->flags, plen);
00344
00345 pdata = (const u8 *) (phdr + 1);
00346 pdatalen = plen - sizeof(*phdr);
00347
00348 switch (next_payload) {
00349 case IKEV2_PAYLOAD_SA:
00350 wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security "
00351 "Association");
00352 payloads->sa = pdata;
00353 payloads->sa_len = pdatalen;
00354 break;
00355 case IKEV2_PAYLOAD_KEY_EXCHANGE:
00356 wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key "
00357 "Exchange");
00358 payloads->ke = pdata;
00359 payloads->ke_len = pdatalen;
00360 break;
00361 case IKEV2_PAYLOAD_IDi:
00362 wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi");
00363 payloads->idi = pdata;
00364 payloads->idi_len = pdatalen;
00365 break;
00366 case IKEV2_PAYLOAD_IDr:
00367 wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr");
00368 payloads->idr = pdata;
00369 payloads->idr_len = pdatalen;
00370 break;
00371 case IKEV2_PAYLOAD_CERTIFICATE:
00372 wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate");
00373 payloads->cert = pdata;
00374 payloads->cert_len = pdatalen;
00375 break;
00376 case IKEV2_PAYLOAD_AUTHENTICATION:
00377 wpa_printf(MSG_DEBUG, "IKEV2: Payload: "
00378 "Authentication");
00379 payloads->auth = pdata;
00380 payloads->auth_len = pdatalen;
00381 break;
00382 case IKEV2_PAYLOAD_NONCE:
00383 wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce");
00384 payloads->nonce = pdata;
00385 payloads->nonce_len = pdatalen;
00386 break;
00387 case IKEV2_PAYLOAD_ENCRYPTED:
00388 wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted");
00389 payloads->encrypted = pdata;
00390 payloads->encrypted_len = pdatalen;
00391 break;
00392 case IKEV2_PAYLOAD_NOTIFICATION:
00393 wpa_printf(MSG_DEBUG, "IKEV2: Payload: "
00394 "Notification");
00395 payloads->notification = pdata;
00396 payloads->notification_len = pdatalen;
00397 break;
00398 default:
00399 if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) {
00400 wpa_printf(MSG_INFO, "IKEV2: Unsupported "
00401 "critical payload %u - reject the "
00402 "entire message", next_payload);
00403 return -1;
00404 } else {
00405 wpa_printf(MSG_DEBUG, "IKEV2: Skipped "
00406 "unsupported payload %u",
00407 next_payload);
00408 }
00409 }
00410
00411 if (next_payload == IKEV2_PAYLOAD_ENCRYPTED &&
00412 pos + plen == end) {
00413
00414
00415
00416
00417
00418 payloads->encr_next_payload = phdr->next_payload;
00419 next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD;
00420 } else
00421 next_payload = phdr->next_payload;
00422
00423 pos += plen;
00424 }
00425
00426 if (pos != end) {
00427 wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after "
00428 "payloads");
00429 return -1;
00430 }
00431
00432 return 0;
00433 }
00434
00435
00436 int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg,
00437 const u8 *ID, size_t ID_len, u8 ID_type,
00438 struct ikev2_keys *keys, int initiator,
00439 const u8 *shared_secret, size_t shared_secret_len,
00440 const u8 *nonce, size_t nonce_len,
00441 const u8 *key_pad, size_t key_pad_len,
00442 u8 *auth_data)
00443 {
00444 size_t sign_len, buf_len;
00445 u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN];
00446 const struct ikev2_prf_alg *prf;
00447 const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr;
00448
00449 prf = ikev2_get_prf(prf_alg);
00450 if (sign_msg == NULL || ID == NULL || SK_p == NULL ||
00451 shared_secret == NULL || nonce == NULL || prf == NULL)
00452 return -1;
00453
00454
00455 buf_len = 4 + ID_len;
00456 buf = os_zalloc(buf_len);
00457 if (buf == NULL)
00458 return -1;
00459 buf[0] = ID_type;
00460 os_memcpy(buf + 4, ID, ID_len);
00461 if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len,
00462 1, (const u8 **) &buf, &buf_len, hash) < 0) {
00463 os_free(buf);
00464 return -1;
00465 }
00466 os_free(buf);
00467
00468
00469 sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len;
00470 sign_data = os_malloc(sign_len);
00471 if (sign_data == NULL)
00472 return -1;
00473 pos = sign_data;
00474 os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg));
00475 pos += wpabuf_len(sign_msg);
00476 os_memcpy(pos, nonce, nonce_len);
00477 pos += nonce_len;
00478 os_memcpy(pos, hash, prf->hash_len);
00479
00480
00481 if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1,
00482 &key_pad, &key_pad_len, hash) < 0 ||
00483 ikev2_prf_hash(prf->id, hash, prf->hash_len, 1,
00484 (const u8 **) &sign_data, &sign_len, auth_data) < 0)
00485 {
00486 os_free(sign_data);
00487 return -1;
00488 }
00489 os_free(sign_data);
00490
00491 return 0;
00492 }
00493
00494
00495 u8 * ikev2_decrypt_payload(int encr_id, int integ_id,
00496 struct ikev2_keys *keys, int initiator,
00497 const struct ikev2_hdr *hdr,
00498 const u8 *encrypted, size_t encrypted_len,
00499 size_t *res_len)
00500 {
00501 size_t iv_len;
00502 const u8 *pos, *end, *iv, *integ;
00503 u8 hash[IKEV2_MAX_HASH_LEN], *decrypted;
00504 size_t decrypted_len, pad_len;
00505 const struct ikev2_integ_alg *integ_alg;
00506 const struct ikev2_encr_alg *encr_alg;
00507 const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
00508 const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
00509
00510 if (encrypted == NULL) {
00511 wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH");
00512 return NULL;
00513 }
00514
00515 encr_alg = ikev2_get_encr(encr_id);
00516 if (encr_alg == NULL) {
00517 wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
00518 return NULL;
00519 }
00520 iv_len = encr_alg->block_size;
00521
00522 integ_alg = ikev2_get_integ(integ_id);
00523 if (integ_alg == NULL) {
00524 wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
00525 return NULL;
00526 }
00527
00528 if (encrypted_len < iv_len + 1 + integ_alg->hash_len) {
00529 wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity "
00530 "Checksum");
00531 return NULL;
00532 }
00533
00534 iv = encrypted;
00535 pos = iv + iv_len;
00536 end = encrypted + encrypted_len;
00537 integ = end - integ_alg->hash_len;
00538
00539 if (SK_a == NULL) {
00540 wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
00541 return NULL;
00542 }
00543 if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
00544 (const u8 *) hdr,
00545 integ - (const u8 *) hdr, hash) < 0) {
00546 wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity "
00547 "hash");
00548 return NULL;
00549 }
00550 if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) {
00551 wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum "
00552 "Data");
00553 return NULL;
00554 }
00555
00556 if (SK_e == NULL) {
00557 wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
00558 return NULL;
00559 }
00560
00561 decrypted_len = integ - pos;
00562 decrypted = os_malloc(decrypted_len);
00563 if (decrypted == NULL)
00564 return NULL;
00565
00566 if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos,
00567 decrypted, decrypted_len) < 0) {
00568 os_free(decrypted);
00569 return NULL;
00570 }
00571
00572 pad_len = decrypted[decrypted_len - 1];
00573 if (decrypted_len < pad_len + 1) {
00574 wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted "
00575 "payload");
00576 os_free(decrypted);
00577 return NULL;
00578 }
00579
00580 decrypted_len -= pad_len + 1;
00581
00582 *res_len = decrypted_len;
00583 return decrypted;
00584 }
00585
00586
00587 void ikev2_update_hdr(struct wpabuf *msg)
00588 {
00589 struct ikev2_hdr *hdr;
00590
00591
00592 hdr = wpabuf_mhead(msg);
00593 WPA_PUT_BE32(hdr->length, wpabuf_len(msg));
00594 }
00595
00596
00597 int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys,
00598 int initiator, struct wpabuf *msg,
00599 struct wpabuf *plain, u8 next_payload)
00600 {
00601 struct ikev2_payload_hdr *phdr;
00602 size_t plen;
00603 size_t iv_len, pad_len;
00604 u8 *icv, *iv;
00605 const struct ikev2_integ_alg *integ_alg;
00606 const struct ikev2_encr_alg *encr_alg;
00607 const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
00608 const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
00609
00610 wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload");
00611
00612
00613
00614 encr_alg = ikev2_get_encr(encr_id);
00615 if (encr_alg == NULL) {
00616 wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
00617 return -1;
00618 }
00619 iv_len = encr_alg->block_size;
00620
00621 integ_alg = ikev2_get_integ(integ_id);
00622 if (integ_alg == NULL) {
00623 wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
00624 return -1;
00625 }
00626
00627 if (SK_e == NULL) {
00628 wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
00629 return -1;
00630 }
00631
00632 if (SK_a == NULL) {
00633 wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
00634 return -1;
00635 }
00636
00637 phdr = wpabuf_put(msg, sizeof(*phdr));
00638 phdr->next_payload = next_payload;
00639 phdr->flags = 0;
00640
00641 iv = wpabuf_put(msg, iv_len);
00642 if (os_get_random(iv, iv_len)) {
00643 wpa_printf(MSG_INFO, "IKEV2: Could not generate IV");
00644 return -1;
00645 }
00646
00647 pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len;
00648 if (pad_len == iv_len)
00649 pad_len = 0;
00650 wpabuf_put(plain, pad_len);
00651 wpabuf_put_u8(plain, pad_len);
00652
00653 if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv,
00654 wpabuf_head(plain), wpabuf_mhead(plain),
00655 wpabuf_len(plain)) < 0)
00656 return -1;
00657
00658 wpabuf_put_buf(msg, plain);
00659
00660
00661 icv = wpabuf_put(msg, integ_alg->hash_len);
00662 plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
00663 WPA_PUT_BE16(phdr->payload_length, plen);
00664
00665 ikev2_update_hdr(msg);
00666
00667 return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
00668 wpabuf_head(msg),
00669 wpabuf_len(msg) - integ_alg->hash_len, icv);
00670
00671 return 0;
00672 }
00673
00674
00675 int ikev2_keys_set(struct ikev2_keys *keys)
00676 {
00677 return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei &&
00678 keys->SK_er && keys->SK_pi && keys->SK_pr;
00679 }
00680
00681
00682 void ikev2_free_keys(struct ikev2_keys *keys)
00683 {
00684 os_free(keys->SK_d);
00685 os_free(keys->SK_ai);
00686 os_free(keys->SK_ar);
00687 os_free(keys->SK_ei);
00688 os_free(keys->SK_er);
00689 os_free(keys->SK_pi);
00690 os_free(keys->SK_pr);
00691 keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er =
00692 keys->SK_pi = keys->SK_pr = NULL;
00693 }
00694
00695
00696 int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf,
00697 const struct ikev2_integ_alg *integ,
00698 const struct ikev2_encr_alg *encr,
00699 const u8 *skeyseed, const u8 *data, size_t data_len,
00700 struct ikev2_keys *keys)
00701 {
00702 u8 *keybuf, *pos;
00703 size_t keybuf_len;
00704
00705
00706
00707
00708
00709 ikev2_free_keys(keys);
00710 keys->SK_d_len = prf->key_len;
00711 keys->SK_integ_len = integ->key_len;
00712 keys->SK_encr_len = encr->key_len;
00713 keys->SK_prf_len = prf->key_len;
00714 #ifdef CCNS_PL
00715
00716 keys->SK_d_len = keys->SK_encr_len;
00717 #endif
00718
00719 keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
00720 2 * keys->SK_encr_len + 2 * keys->SK_prf_len;
00721 keybuf = os_malloc(keybuf_len);
00722 if (keybuf == NULL)
00723 return -1;
00724
00725 if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len,
00726 data, data_len, keybuf, keybuf_len)) {
00727 os_free(keybuf);
00728 return -1;
00729 }
00730
00731 pos = keybuf;
00732
00733 keys->SK_d = os_malloc(keys->SK_d_len);
00734 if (keys->SK_d) {
00735 os_memcpy(keys->SK_d, pos, keys->SK_d_len);
00736 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d",
00737 keys->SK_d, keys->SK_d_len);
00738 }
00739 pos += keys->SK_d_len;
00740
00741 keys->SK_ai = os_malloc(keys->SK_integ_len);
00742 if (keys->SK_ai) {
00743 os_memcpy(keys->SK_ai, pos, keys->SK_integ_len);
00744 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai",
00745 keys->SK_ai, keys->SK_integ_len);
00746 }
00747 pos += keys->SK_integ_len;
00748
00749 keys->SK_ar = os_malloc(keys->SK_integ_len);
00750 if (keys->SK_ar) {
00751 os_memcpy(keys->SK_ar, pos, keys->SK_integ_len);
00752 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar",
00753 keys->SK_ar, keys->SK_integ_len);
00754 }
00755 pos += keys->SK_integ_len;
00756
00757 keys->SK_ei = os_malloc(keys->SK_encr_len);
00758 if (keys->SK_ei) {
00759 os_memcpy(keys->SK_ei, pos, keys->SK_encr_len);
00760 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei",
00761 keys->SK_ei, keys->SK_encr_len);
00762 }
00763 pos += keys->SK_encr_len;
00764
00765 keys->SK_er = os_malloc(keys->SK_encr_len);
00766 if (keys->SK_er) {
00767 os_memcpy(keys->SK_er, pos, keys->SK_encr_len);
00768 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er",
00769 keys->SK_er, keys->SK_encr_len);
00770 }
00771 pos += keys->SK_encr_len;
00772
00773 keys->SK_pi = os_malloc(keys->SK_prf_len);
00774 if (keys->SK_pi) {
00775 os_memcpy(keys->SK_pi, pos, keys->SK_prf_len);
00776 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi",
00777 keys->SK_pi, keys->SK_prf_len);
00778 }
00779 pos += keys->SK_prf_len;
00780
00781 keys->SK_pr = os_malloc(keys->SK_prf_len);
00782 if (keys->SK_pr) {
00783 os_memcpy(keys->SK_pr, pos, keys->SK_prf_len);
00784 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr",
00785 keys->SK_pr, keys->SK_prf_len);
00786 }
00787
00788 os_free(keybuf);
00789
00790 if (!ikev2_keys_set(keys)) {
00791 ikev2_free_keys(keys);
00792 return -1;
00793 }
00794
00795 return 0;
00796 }