Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/keymat_v2.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2015 Tobias Brunner
! 3: * Copyright (C) 2008 Martin Willi
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "keymat_v2.h"
! 18:
! 19: #include <daemon.h>
! 20: #include <crypto/prf_plus.h>
! 21: #include <crypto/hashers/hash_algorithm_set.h>
! 22:
! 23: typedef struct private_keymat_v2_t private_keymat_v2_t;
! 24:
! 25: /**
! 26: * Private data of an keymat_t object.
! 27: */
! 28: struct private_keymat_v2_t {
! 29:
! 30: /**
! 31: * Public keymat_v2_t interface.
! 32: */
! 33: keymat_v2_t public;
! 34:
! 35: /**
! 36: * IKE_SA Role, initiator or responder
! 37: */
! 38: bool initiator;
! 39:
! 40: /**
! 41: * inbound AEAD
! 42: */
! 43: aead_t *aead_in;
! 44:
! 45: /**
! 46: * outbound AEAD
! 47: */
! 48: aead_t *aead_out;
! 49:
! 50: /**
! 51: * General purpose PRF
! 52: */
! 53: prf_t *prf;
! 54:
! 55: /**
! 56: * Negotiated PRF algorithm
! 57: */
! 58: pseudo_random_function_t prf_alg;
! 59:
! 60: /**
! 61: * Key to derive key material from for CHILD_SAs, rekeying
! 62: */
! 63: chunk_t skd;
! 64:
! 65: /**
! 66: * Key to build outgoing authentication data (SKp)
! 67: */
! 68: chunk_t skp_build;
! 69:
! 70: /**
! 71: * Key to verify incoming authentication data (SKp)
! 72: */
! 73: chunk_t skp_verify;
! 74:
! 75: /**
! 76: * Set of hash algorithms supported by peer for signature authentication
! 77: */
! 78: hash_algorithm_set_t *hash_algorithms;
! 79: };
! 80:
! 81: METHOD(keymat_t, get_version, ike_version_t,
! 82: private_keymat_v2_t *this)
! 83: {
! 84: return IKEV2;
! 85: }
! 86:
! 87: METHOD(keymat_t, create_dh, diffie_hellman_t*,
! 88: private_keymat_v2_t *this, diffie_hellman_group_t group)
! 89: {
! 90: return lib->crypto->create_dh(lib->crypto, group);
! 91: }
! 92:
! 93: METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
! 94: private_keymat_v2_t *this)
! 95: {
! 96: return lib->crypto->create_nonce_gen(lib->crypto);
! 97: }
! 98:
! 99: /**
! 100: * Derive IKE keys for a combined AEAD algorithm
! 101: */
! 102: static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
! 103: uint16_t key_size, prf_plus_t *prf_plus)
! 104: {
! 105: aead_t *aead_i, *aead_r;
! 106: chunk_t sk_ei = chunk_empty, sk_er = chunk_empty;
! 107: u_int salt_size;
! 108:
! 109: switch (alg)
! 110: {
! 111: case ENCR_AES_GCM_ICV8:
! 112: case ENCR_AES_GCM_ICV12:
! 113: case ENCR_AES_GCM_ICV16:
! 114: /* RFC 4106 */
! 115: case ENCR_CHACHA20_POLY1305:
! 116: salt_size = 4;
! 117: break;
! 118: case ENCR_AES_CCM_ICV8:
! 119: case ENCR_AES_CCM_ICV12:
! 120: case ENCR_AES_CCM_ICV16:
! 121: /* RFC 4309 */
! 122: case ENCR_CAMELLIA_CCM_ICV8:
! 123: case ENCR_CAMELLIA_CCM_ICV12:
! 124: case ENCR_CAMELLIA_CCM_ICV16:
! 125: /* RFC 5529 */
! 126: salt_size = 3;
! 127: break;
! 128: default:
! 129: DBG1(DBG_IKE, "nonce size for %N unknown!",
! 130: encryption_algorithm_names, alg);
! 131: return FALSE;
! 132: }
! 133:
! 134: /* SK_ei/SK_er used for encryption */
! 135: aead_i = lib->crypto->create_aead(lib->crypto, alg, key_size / 8, salt_size);
! 136: aead_r = lib->crypto->create_aead(lib->crypto, alg, key_size / 8, salt_size);
! 137: if (aead_i == NULL || aead_r == NULL)
! 138: {
! 139: DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
! 140: transform_type_names, ENCRYPTION_ALGORITHM,
! 141: encryption_algorithm_names, alg, key_size);
! 142: goto failure;
! 143: }
! 144: key_size = aead_i->get_key_size(aead_i);
! 145: if (key_size != aead_r->get_key_size(aead_r))
! 146: {
! 147: goto failure;
! 148: }
! 149: if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ei))
! 150: {
! 151: goto failure;
! 152: }
! 153: DBG4(DBG_IKE, "Sk_ei secret %B", &sk_ei);
! 154: if (!aead_i->set_key(aead_i, sk_ei))
! 155: {
! 156: goto failure;
! 157: }
! 158:
! 159: if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_er))
! 160: {
! 161: goto failure;
! 162: }
! 163: DBG4(DBG_IKE, "Sk_er secret %B", &sk_er);
! 164: if (!aead_r->set_key(aead_r, sk_er))
! 165: {
! 166: goto failure;
! 167: }
! 168:
! 169: if (this->initiator)
! 170: {
! 171: this->aead_in = aead_r;
! 172: this->aead_out = aead_i;
! 173: }
! 174: else
! 175: {
! 176: this->aead_in = aead_i;
! 177: this->aead_out = aead_r;
! 178: }
! 179: aead_i = aead_r = NULL;
! 180: charon->bus->ike_derived_keys(charon->bus, sk_ei, sk_er, chunk_empty,
! 181: chunk_empty);
! 182:
! 183: failure:
! 184: DESTROY_IF(aead_i);
! 185: DESTROY_IF(aead_r);
! 186: chunk_clear(&sk_ei);
! 187: chunk_clear(&sk_er);
! 188: return this->aead_in && this->aead_out;
! 189: }
! 190:
! 191: /**
! 192: * Derive IKE keys for traditional encryption and MAC algorithms
! 193: */
! 194: static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
! 195: uint16_t enc_size, uint16_t int_alg, prf_plus_t *prf_plus)
! 196: {
! 197: crypter_t *crypter_i = NULL, *crypter_r = NULL;
! 198: signer_t *signer_i, *signer_r;
! 199: iv_gen_t *ivg_i, *ivg_r;
! 200: size_t key_size;
! 201: chunk_t sk_ei = chunk_empty, sk_er = chunk_empty,
! 202: sk_ai = chunk_empty, sk_ar = chunk_empty;
! 203:
! 204: signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
! 205: signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
! 206: crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
! 207: crypter_r = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_size / 8);
! 208: if (signer_i == NULL || signer_r == NULL)
! 209: {
! 210: DBG1(DBG_IKE, "%N %N not supported!",
! 211: transform_type_names, INTEGRITY_ALGORITHM,
! 212: integrity_algorithm_names, int_alg);
! 213: goto failure;
! 214: }
! 215: if (crypter_i == NULL || crypter_r == NULL)
! 216: {
! 217: DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
! 218: transform_type_names, ENCRYPTION_ALGORITHM,
! 219: encryption_algorithm_names, enc_alg, enc_size);
! 220: goto failure;
! 221: }
! 222:
! 223: /* SK_ai/SK_ar used for integrity protection */
! 224: key_size = signer_i->get_key_size(signer_i);
! 225:
! 226: if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ai))
! 227: {
! 228: goto failure;
! 229: }
! 230: DBG4(DBG_IKE, "Sk_ai secret %B", &sk_ai);
! 231: if (!signer_i->set_key(signer_i, sk_ai))
! 232: {
! 233: goto failure;
! 234: }
! 235:
! 236: if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ar))
! 237: {
! 238: goto failure;
! 239: }
! 240: DBG4(DBG_IKE, "Sk_ar secret %B", &sk_ar);
! 241: if (!signer_r->set_key(signer_r, sk_ar))
! 242: {
! 243: goto failure;
! 244: }
! 245:
! 246: /* SK_ei/SK_er used for encryption */
! 247: key_size = crypter_i->get_key_size(crypter_i);
! 248:
! 249: if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ei))
! 250: {
! 251: goto failure;
! 252: }
! 253: DBG4(DBG_IKE, "Sk_ei secret %B", &sk_ei);
! 254: if (!crypter_i->set_key(crypter_i, sk_ei))
! 255: {
! 256: goto failure;
! 257: }
! 258:
! 259: if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_er))
! 260: {
! 261: goto failure;
! 262: }
! 263: DBG4(DBG_IKE, "Sk_er secret %B", &sk_er);
! 264: if (!crypter_r->set_key(crypter_r, sk_er))
! 265: {
! 266: goto failure;
! 267: }
! 268:
! 269: ivg_i = iv_gen_create_for_alg(enc_alg);
! 270: ivg_r = iv_gen_create_for_alg(enc_alg);
! 271: if (!ivg_i || !ivg_r)
! 272: {
! 273: goto failure;
! 274: }
! 275: if (this->initiator)
! 276: {
! 277: this->aead_in = aead_create(crypter_r, signer_r, ivg_r);
! 278: this->aead_out = aead_create(crypter_i, signer_i, ivg_i);
! 279: }
! 280: else
! 281: {
! 282: this->aead_in = aead_create(crypter_i, signer_i, ivg_i);
! 283: this->aead_out = aead_create(crypter_r, signer_r, ivg_r);
! 284: }
! 285: signer_i = signer_r = NULL;
! 286: crypter_i = crypter_r = NULL;
! 287: charon->bus->ike_derived_keys(charon->bus, sk_ei, sk_er, sk_ai, sk_ar);
! 288:
! 289: failure:
! 290: chunk_clear(&sk_ai);
! 291: chunk_clear(&sk_ar);
! 292: chunk_clear(&sk_ei);
! 293: chunk_clear(&sk_er);
! 294: DESTROY_IF(signer_i);
! 295: DESTROY_IF(signer_r);
! 296: DESTROY_IF(crypter_i);
! 297: DESTROY_IF(crypter_r);
! 298: return this->aead_in && this->aead_out;
! 299: }
! 300:
! 301: METHOD(keymat_v2_t, derive_ike_keys, bool,
! 302: private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
! 303: chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
! 304: pseudo_random_function_t rekey_function, chunk_t rekey_skd)
! 305: {
! 306: chunk_t skeyseed = chunk_empty, key, secret, full_nonce, fixed_nonce;
! 307: chunk_t prf_plus_seed, spi_i, spi_r;
! 308: prf_plus_t *prf_plus = NULL;
! 309: uint16_t alg, key_size, int_alg;
! 310: prf_t *rekey_prf = NULL;
! 311:
! 312: spi_i = chunk_alloca(sizeof(uint64_t));
! 313: spi_r = chunk_alloca(sizeof(uint64_t));
! 314:
! 315: if (!dh->get_shared_secret(dh, &secret))
! 316: {
! 317: return FALSE;
! 318: }
! 319:
! 320: /* Create SAs general purpose PRF first, we may use it here */
! 321: if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
! 322: {
! 323: DBG1(DBG_IKE, "no %N selected",
! 324: transform_type_names, PSEUDO_RANDOM_FUNCTION);
! 325: chunk_clear(&secret);
! 326: return FALSE;
! 327: }
! 328: this->prf_alg = alg;
! 329: this->prf = lib->crypto->create_prf(lib->crypto, alg);
! 330: if (this->prf == NULL)
! 331: {
! 332: DBG1(DBG_IKE, "%N %N not supported!",
! 333: transform_type_names, PSEUDO_RANDOM_FUNCTION,
! 334: pseudo_random_function_names, alg);
! 335: chunk_clear(&secret);
! 336: return FALSE;
! 337: }
! 338: DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
! 339: /* full nonce is used as seed for PRF+ ... */
! 340: full_nonce = chunk_cat("cc", nonce_i, nonce_r);
! 341: /* but the PRF may need a fixed key which only uses the first bytes of
! 342: * the nonces. */
! 343: switch (alg)
! 344: {
! 345: case PRF_AES128_CMAC:
! 346: /* while variable keys may be used according to RFC 4615, RFC 7296
! 347: * explicitly limits the key size to 128 bit for this application */
! 348: case PRF_AES128_XCBC:
! 349: /* while RFC 4434 defines variable keys for AES-XCBC, RFC 3664 does
! 350: * not and therefore fixed key semantics apply to XCBC for key
! 351: * derivation, which is also reinforced by RFC 7296 */
! 352: case PRF_CAMELLIA128_XCBC:
! 353: /* draft-kanno-ipsecme-camellia-xcbc refers to rfc 4434, we
! 354: * assume fixed key length. */
! 355: key_size = this->prf->get_key_size(this->prf)/2;
! 356: nonce_i.len = min(nonce_i.len, key_size);
! 357: nonce_r.len = min(nonce_r.len, key_size);
! 358: break;
! 359: default:
! 360: /* all other algorithms use variable key length, full nonce */
! 361: break;
! 362: }
! 363: fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
! 364: *((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
! 365: *((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
! 366: prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
! 367:
! 368: /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
! 369: *
! 370: * if we are rekeying, SKEYSEED is built on another way
! 371: */
! 372: if (rekey_function == PRF_UNDEFINED) /* not rekeying */
! 373: {
! 374: /* SKEYSEED = prf(Ni | Nr, g^ir) */
! 375: if (this->prf->set_key(this->prf, fixed_nonce) &&
! 376: this->prf->allocate_bytes(this->prf, secret, &skeyseed) &&
! 377: this->prf->set_key(this->prf, skeyseed))
! 378: {
! 379: prf_plus = prf_plus_create(this->prf, TRUE, prf_plus_seed);
! 380: }
! 381: }
! 382: else
! 383: {
! 384: /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
! 385: * use OLD SAs PRF functions for both prf_plus and prf */
! 386: rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function);
! 387: if (!rekey_prf)
! 388: {
! 389: DBG1(DBG_IKE, "PRF of old SA %N not supported!",
! 390: pseudo_random_function_names, rekey_function);
! 391: chunk_clear(&secret);
! 392: chunk_free(&full_nonce);
! 393: chunk_free(&fixed_nonce);
! 394: chunk_clear(&prf_plus_seed);
! 395: return FALSE;
! 396: }
! 397: secret = chunk_cat("mc", secret, full_nonce);
! 398: if (rekey_prf->set_key(rekey_prf, rekey_skd) &&
! 399: rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed) &&
! 400: rekey_prf->set_key(rekey_prf, skeyseed))
! 401: {
! 402: prf_plus = prf_plus_create(rekey_prf, TRUE, prf_plus_seed);
! 403: }
! 404: }
! 405: DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
! 406:
! 407: chunk_clear(&skeyseed);
! 408: chunk_clear(&secret);
! 409: chunk_free(&full_nonce);
! 410: chunk_free(&fixed_nonce);
! 411: chunk_clear(&prf_plus_seed);
! 412:
! 413: if (!prf_plus)
! 414: {
! 415: goto failure;
! 416: }
! 417:
! 418: /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
! 419:
! 420: /* SK_d is used for generating CHILD_SA key mat => store for later use */
! 421: key_size = this->prf->get_key_size(this->prf);
! 422: if (!prf_plus->allocate_bytes(prf_plus, key_size, &this->skd))
! 423: {
! 424: goto failure;
! 425: }
! 426: DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
! 427:
! 428: if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
! 429: {
! 430: DBG1(DBG_IKE, "no %N selected",
! 431: transform_type_names, ENCRYPTION_ALGORITHM);
! 432: goto failure;
! 433: }
! 434:
! 435: if (encryption_algorithm_is_aead(alg))
! 436: {
! 437: if (!derive_ike_aead(this, alg, key_size, prf_plus))
! 438: {
! 439: goto failure;
! 440: }
! 441: }
! 442: else
! 443: {
! 444: if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
! 445: &int_alg, NULL))
! 446: {
! 447: DBG1(DBG_IKE, "no %N selected",
! 448: transform_type_names, INTEGRITY_ALGORITHM);
! 449: goto failure;
! 450: }
! 451: if (!derive_ike_traditional(this, alg, key_size, int_alg, prf_plus))
! 452: {
! 453: goto failure;
! 454: }
! 455: }
! 456:
! 457: /* SK_pi/SK_pr used for authentication => stored for later */
! 458: key_size = this->prf->get_key_size(this->prf);
! 459: if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
! 460: {
! 461: goto failure;
! 462: }
! 463: DBG4(DBG_IKE, "Sk_pi secret %B", &key);
! 464: if (this->initiator)
! 465: {
! 466: this->skp_build = key;
! 467: }
! 468: else
! 469: {
! 470: this->skp_verify = key;
! 471: }
! 472: if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
! 473: {
! 474: goto failure;
! 475: }
! 476: DBG4(DBG_IKE, "Sk_pr secret %B", &key);
! 477: if (this->initiator)
! 478: {
! 479: this->skp_verify = key;
! 480: }
! 481: else
! 482: {
! 483: this->skp_build = key;
! 484: }
! 485:
! 486: /* all done, prf_plus not needed anymore */
! 487: failure:
! 488: DESTROY_IF(prf_plus);
! 489: DESTROY_IF(rekey_prf);
! 490:
! 491: return this->skp_build.len && this->skp_verify.len;
! 492: }
! 493:
! 494: /**
! 495: * Derives a key from the given key and a PRF that was initialized with a PPK
! 496: */
! 497: static bool derive_ppk_key(prf_t *prf, char *name, chunk_t key,
! 498: chunk_t *new_key)
! 499: {
! 500: prf_plus_t *prf_plus;
! 501:
! 502: prf_plus = prf_plus_create(prf, TRUE, key);
! 503: if (!prf_plus ||
! 504: !prf_plus->allocate_bytes(prf_plus, key.len, new_key))
! 505: {
! 506: DBG1(DBG_IKE, "unable to derive %s with PPK", name);
! 507: DESTROY_IF(prf_plus);
! 508: return FALSE;
! 509: }
! 510: prf_plus->destroy(prf_plus);
! 511: return TRUE;
! 512: }
! 513:
! 514: /**
! 515: * Use the given PPK to derive a new SK_pi/r
! 516: */
! 517: static bool derive_skp_ppk(private_keymat_v2_t *this, chunk_t ppk, chunk_t skp,
! 518: chunk_t *new_skp)
! 519: {
! 520: if (!this->prf->set_key(this->prf, ppk))
! 521: {
! 522: DBG1(DBG_IKE, "unable to set PPK in PRF");
! 523: return FALSE;
! 524: }
! 525: return derive_ppk_key(this->prf, "SK_p", skp, new_skp);
! 526: }
! 527:
! 528: METHOD(keymat_v2_t, derive_ike_keys_ppk, bool,
! 529: private_keymat_v2_t *this, chunk_t ppk)
! 530: {
! 531: chunk_t skd = chunk_empty, new_skpi = chunk_empty, new_skpr = chunk_empty;
! 532: chunk_t *skpi, *skpr;
! 533:
! 534: if (!this->skd.ptr)
! 535: {
! 536: return FALSE;
! 537: }
! 538:
! 539: if (this->initiator)
! 540: {
! 541: skpi = &this->skp_build;
! 542: skpr = &this->skp_verify;
! 543: }
! 544: else
! 545: {
! 546: skpi = &this->skp_verify;
! 547: skpr = &this->skp_build;
! 548: }
! 549:
! 550: DBG4(DBG_IKE, "derive keys using PPK %B", &ppk);
! 551:
! 552: if (!this->prf->set_key(this->prf, ppk))
! 553: {
! 554: DBG1(DBG_IKE, "unable to set PPK in PRF");
! 555: return FALSE;
! 556: }
! 557: if (!derive_ppk_key(this->prf, "Sk_d", this->skd, &skd) ||
! 558: !derive_ppk_key(this->prf, "Sk_pi", *skpi, &new_skpi) ||
! 559: !derive_ppk_key(this->prf, "Sk_pr", *skpr, &new_skpr))
! 560: {
! 561: chunk_clear(&skd);
! 562: chunk_clear(&new_skpi);
! 563: chunk_clear(&new_skpr);
! 564: return FALSE;
! 565: }
! 566:
! 567: DBG4(DBG_IKE, "Sk_d secret %B", &skd);
! 568: chunk_clear(&this->skd);
! 569: this->skd = skd;
! 570:
! 571: DBG4(DBG_IKE, "Sk_pi secret %B", &new_skpi);
! 572: chunk_clear(skpi);
! 573: *skpi = new_skpi;
! 574:
! 575: DBG4(DBG_IKE, "Sk_pr secret %B", &new_skpr);
! 576: chunk_clear(skpr);
! 577: *skpr = new_skpr;
! 578: return TRUE;
! 579: }
! 580:
! 581: METHOD(keymat_v2_t, derive_child_keys, bool,
! 582: private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
! 583: chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
! 584: chunk_t *encr_r, chunk_t *integ_r)
! 585: {
! 586: uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
! 587: chunk_t seed, secret = chunk_empty;
! 588: prf_plus_t *prf_plus;
! 589:
! 590: if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
! 591: &enc_alg, &enc_size))
! 592: {
! 593: DBG2(DBG_CHD, " using %N for encryption",
! 594: encryption_algorithm_names, enc_alg);
! 595:
! 596: if (!enc_size)
! 597: {
! 598: enc_size = keymat_get_keylen_encr(enc_alg);
! 599: }
! 600: if (enc_alg != ENCR_NULL && !enc_size)
! 601: {
! 602: DBG1(DBG_CHD, "no keylength defined for %N",
! 603: encryption_algorithm_names, enc_alg);
! 604: return FALSE;
! 605: }
! 606: /* to bytes */
! 607: enc_size /= 8;
! 608:
! 609: /* CCM/GCM/CTR/GMAC needs additional bytes */
! 610: switch (enc_alg)
! 611: {
! 612: case ENCR_AES_CCM_ICV8:
! 613: case ENCR_AES_CCM_ICV12:
! 614: case ENCR_AES_CCM_ICV16:
! 615: case ENCR_CAMELLIA_CCM_ICV8:
! 616: case ENCR_CAMELLIA_CCM_ICV12:
! 617: case ENCR_CAMELLIA_CCM_ICV16:
! 618: enc_size += 3;
! 619: break;
! 620: case ENCR_AES_GCM_ICV8:
! 621: case ENCR_AES_GCM_ICV12:
! 622: case ENCR_AES_GCM_ICV16:
! 623: case ENCR_AES_CTR:
! 624: case ENCR_CAMELLIA_CTR:
! 625: case ENCR_NULL_AUTH_AES_GMAC:
! 626: case ENCR_CHACHA20_POLY1305:
! 627: enc_size += 4;
! 628: break;
! 629: default:
! 630: break;
! 631: }
! 632: }
! 633:
! 634: if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
! 635: &int_alg, &int_size))
! 636: {
! 637: DBG2(DBG_CHD, " using %N for integrity",
! 638: integrity_algorithm_names, int_alg);
! 639:
! 640: if (!int_size)
! 641: {
! 642: int_size = keymat_get_keylen_integ(int_alg);
! 643: }
! 644: if (!int_size)
! 645: {
! 646: DBG1(DBG_CHD, "no keylength defined for %N",
! 647: integrity_algorithm_names, int_alg);
! 648: return FALSE;
! 649: }
! 650: /* to bytes */
! 651: int_size /= 8;
! 652: }
! 653:
! 654: if (!this->prf->set_key(this->prf, this->skd))
! 655: {
! 656: return FALSE;
! 657: }
! 658:
! 659: if (dh)
! 660: {
! 661: if (!dh->get_shared_secret(dh, &secret))
! 662: {
! 663: return FALSE;
! 664: }
! 665: DBG4(DBG_CHD, "DH secret %B", &secret);
! 666: }
! 667: seed = chunk_cata("scc", secret, nonce_i, nonce_r);
! 668: DBG4(DBG_CHD, "seed %B", &seed);
! 669:
! 670: prf_plus = prf_plus_create(this->prf, TRUE, seed);
! 671: memwipe(seed.ptr, seed.len);
! 672:
! 673: if (!prf_plus)
! 674: {
! 675: return FALSE;
! 676: }
! 677:
! 678: *encr_i = *integ_i = *encr_r = *integ_r = chunk_empty;
! 679: if (!prf_plus->allocate_bytes(prf_plus, enc_size, encr_i) ||
! 680: !prf_plus->allocate_bytes(prf_plus, int_size, integ_i) ||
! 681: !prf_plus->allocate_bytes(prf_plus, enc_size, encr_r) ||
! 682: !prf_plus->allocate_bytes(prf_plus, int_size, integ_r))
! 683: {
! 684: chunk_free(encr_i);
! 685: chunk_free(integ_i);
! 686: chunk_free(encr_r);
! 687: chunk_free(integ_r);
! 688: prf_plus->destroy(prf_plus);
! 689: return FALSE;
! 690: }
! 691:
! 692: prf_plus->destroy(prf_plus);
! 693:
! 694: if (enc_size)
! 695: {
! 696: DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
! 697: DBG4(DBG_CHD, "encryption responder key %B", encr_r);
! 698: }
! 699: if (int_size)
! 700: {
! 701: DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
! 702: DBG4(DBG_CHD, "integrity responder key %B", integ_r);
! 703: }
! 704: return TRUE;
! 705: }
! 706:
! 707: METHOD(keymat_v2_t, get_skd, pseudo_random_function_t,
! 708: private_keymat_v2_t *this, chunk_t *skd)
! 709: {
! 710: *skd = this->skd;
! 711: return this->prf_alg;
! 712: }
! 713:
! 714: METHOD(keymat_t, get_aead, aead_t*,
! 715: private_keymat_v2_t *this, bool in)
! 716: {
! 717: return in ? this->aead_in : this->aead_out;
! 718: }
! 719:
! 720: METHOD(keymat_v2_t, get_auth_octets, bool,
! 721: private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
! 722: chunk_t nonce, chunk_t ppk, identification_t *id, char reserved[3],
! 723: chunk_t *octets, array_t *schemes)
! 724: {
! 725: chunk_t chunk, idx;
! 726: chunk_t skp_ppk = chunk_empty;
! 727: chunk_t skp;
! 728:
! 729: skp = verify ? this->skp_verify : this->skp_build;
! 730: if (ppk.ptr)
! 731: {
! 732: DBG4(DBG_IKE, "PPK %B", &ppk);
! 733: if (!derive_skp_ppk(this, ppk, skp, &skp_ppk))
! 734: {
! 735: return FALSE;
! 736: }
! 737: skp = skp_ppk;
! 738: }
! 739:
! 740: chunk = chunk_alloca(4);
! 741: chunk.ptr[0] = id->get_type(id);
! 742: memcpy(chunk.ptr + 1, reserved, 3);
! 743: idx = chunk_cata("cc", chunk, id->get_encoding(id));
! 744:
! 745: DBG3(DBG_IKE, "IDx' %B", &idx);
! 746: DBG4(DBG_IKE, "SK_p %B", &skp);
! 747: if (!this->prf->set_key(this->prf, skp) ||
! 748: !this->prf->allocate_bytes(this->prf, idx, &chunk))
! 749: {
! 750: chunk_clear(&skp_ppk);
! 751: return FALSE;
! 752: }
! 753: chunk_clear(&skp_ppk);
! 754: *octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
! 755: DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", octets);
! 756: return TRUE;
! 757: }
! 758:
! 759: /**
! 760: * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
! 761: */
! 762: #define IKEV2_KEY_PAD "Key Pad for IKEv2"
! 763: #define IKEV2_KEY_PAD_LENGTH 17
! 764:
! 765: METHOD(keymat_v2_t, get_psk_sig, bool,
! 766: private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce,
! 767: chunk_t secret, chunk_t ppk, identification_t *id, char reserved[3],
! 768: chunk_t *sig)
! 769: {
! 770: chunk_t skp_ppk = chunk_empty, key = chunk_empty, octets = chunk_empty;
! 771: chunk_t key_pad;
! 772: bool success = FALSE;
! 773:
! 774: if (!secret.len)
! 775: { /* EAP uses SK_p if no MSK has been established */
! 776: secret = verify ? this->skp_verify : this->skp_build;
! 777: if (ppk.ptr)
! 778: {
! 779: if (!derive_skp_ppk(this, ppk, secret, &skp_ppk))
! 780: {
! 781: return FALSE;
! 782: }
! 783: secret = skp_ppk;
! 784: }
! 785: }
! 786: if (!get_auth_octets(this, verify, ike_sa_init, nonce, ppk, id, reserved,
! 787: &octets, NULL))
! 788: {
! 789: goto failure;
! 790: }
! 791: /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
! 792: key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
! 793: if (!this->prf->set_key(this->prf, secret) ||
! 794: !this->prf->allocate_bytes(this->prf, key_pad, &key))
! 795: {
! 796: goto failure;
! 797: }
! 798: if (!this->prf->set_key(this->prf, key) ||
! 799: !this->prf->allocate_bytes(this->prf, octets, sig))
! 800: {
! 801: goto failure;
! 802: }
! 803: DBG4(DBG_IKE, "secret %B", &secret);
! 804: DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
! 805: DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", sig);
! 806: success = TRUE;
! 807:
! 808: failure:
! 809: chunk_clear(&skp_ppk);
! 810: chunk_free(&octets);
! 811: chunk_free(&key);
! 812: return success;
! 813:
! 814: }
! 815:
! 816: METHOD(keymat_v2_t, hash_algorithm_supported, bool,
! 817: private_keymat_v2_t *this, hash_algorithm_t hash)
! 818: {
! 819: if (!this->hash_algorithms)
! 820: {
! 821: return FALSE;
! 822: }
! 823: return this->hash_algorithms->contains(this->hash_algorithms, hash);
! 824: }
! 825:
! 826: METHOD(keymat_v2_t, add_hash_algorithm, void,
! 827: private_keymat_v2_t *this, hash_algorithm_t hash)
! 828: {
! 829: if (!this->hash_algorithms)
! 830: {
! 831: this->hash_algorithms = hash_algorithm_set_create();
! 832: }
! 833: this->hash_algorithms->add(this->hash_algorithms, hash);
! 834: }
! 835:
! 836: METHOD(keymat_t, destroy, void,
! 837: private_keymat_v2_t *this)
! 838: {
! 839: DESTROY_IF(this->aead_in);
! 840: DESTROY_IF(this->aead_out);
! 841: DESTROY_IF(this->prf);
! 842: chunk_clear(&this->skd);
! 843: chunk_clear(&this->skp_verify);
! 844: chunk_clear(&this->skp_build);
! 845: DESTROY_IF(this->hash_algorithms);
! 846: free(this);
! 847: }
! 848:
! 849: /**
! 850: * See header
! 851: */
! 852: keymat_v2_t *keymat_v2_create(bool initiator)
! 853: {
! 854: private_keymat_v2_t *this;
! 855:
! 856: INIT(this,
! 857: .public = {
! 858: .keymat = {
! 859: .get_version = _get_version,
! 860: .create_dh = _create_dh,
! 861: .create_nonce_gen = _create_nonce_gen,
! 862: .get_aead = _get_aead,
! 863: .destroy = _destroy,
! 864: },
! 865: .derive_ike_keys = _derive_ike_keys,
! 866: .derive_ike_keys_ppk = _derive_ike_keys_ppk,
! 867: .derive_child_keys = _derive_child_keys,
! 868: .get_skd = _get_skd,
! 869: .get_auth_octets = _get_auth_octets,
! 870: .get_psk_sig = _get_psk_sig,
! 871: .add_hash_algorithm = _add_hash_algorithm,
! 872: .hash_algorithm_supported = _hash_algorithm_supported,
! 873:
! 874: },
! 875: .initiator = initiator,
! 876: .prf_alg = PRF_UNDEFINED,
! 877: );
! 878:
! 879: return &this->public;
! 880: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>