Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/keymat_v1.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011 Tobias Brunner
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "keymat_v1.h"
! 17:
! 18: #include <daemon.h>
! 19: #include <sa/ikev1/iv_manager.h>
! 20: #include <encoding/generator.h>
! 21: #include <encoding/payloads/nonce_payload.h>
! 22:
! 23: typedef struct private_keymat_v1_t private_keymat_v1_t;
! 24:
! 25: /**
! 26: * Private data of an keymat_t object.
! 27: */
! 28: struct private_keymat_v1_t {
! 29:
! 30: /**
! 31: * Public keymat_v1_t interface.
! 32: */
! 33: keymat_v1_t public;
! 34:
! 35: /**
! 36: * IKE_SA Role, initiator or responder
! 37: */
! 38: bool initiator;
! 39:
! 40: /**
! 41: * General purpose PRF
! 42: */
! 43: prf_t *prf;
! 44:
! 45: /**
! 46: * PRF to create Phase 1 HASH payloads
! 47: */
! 48: prf_t *prf_auth;
! 49:
! 50: /**
! 51: * Crypter wrapped in an aead_t interface
! 52: */
! 53: aead_t *aead;
! 54:
! 55: /**
! 56: * Hasher used for IV generation (and other things like e.g. NAT-T)
! 57: */
! 58: hasher_t *hasher;
! 59:
! 60: /**
! 61: * Key to derive key material from for non-ISAKMP SAs, rekeying
! 62: */
! 63: chunk_t skeyid_d;
! 64:
! 65: /**
! 66: * Key used for authentication after main mode
! 67: */
! 68: chunk_t skeyid_a;
! 69:
! 70: /**
! 71: * IV and QM manager
! 72: */
! 73: iv_manager_t *iv_manager;
! 74: };
! 75:
! 76: /**
! 77: * Constants used in key derivation.
! 78: */
! 79: static const chunk_t octet_0 = chunk_from_chars(0x00);
! 80: static const chunk_t octet_1 = chunk_from_chars(0x01);
! 81: static const chunk_t octet_2 = chunk_from_chars(0x02);
! 82:
! 83: /**
! 84: * Simple aead_t implementation without support for authentication.
! 85: */
! 86: typedef struct {
! 87: /** implements aead_t interface */
! 88: aead_t aead;
! 89: /** crypter to be used */
! 90: crypter_t *crypter;
! 91: } private_aead_t;
! 92:
! 93:
! 94: METHOD(aead_t, encrypt, bool,
! 95: private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
! 96: chunk_t *encrypted)
! 97: {
! 98: return this->crypter->encrypt(this->crypter, plain, iv, encrypted);
! 99: }
! 100:
! 101: METHOD(aead_t, decrypt, bool,
! 102: private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
! 103: chunk_t *plain)
! 104: {
! 105: return this->crypter->decrypt(this->crypter, encrypted, iv, plain);
! 106: }
! 107:
! 108: METHOD(aead_t, get_block_size, size_t,
! 109: private_aead_t *this)
! 110: {
! 111: return this->crypter->get_block_size(this->crypter);
! 112: }
! 113:
! 114: METHOD(aead_t, get_icv_size, size_t,
! 115: private_aead_t *this)
! 116: {
! 117: return 0;
! 118: }
! 119:
! 120: METHOD(aead_t, get_iv_size, size_t,
! 121: private_aead_t *this)
! 122: {
! 123: /* in order to create the messages properly we return 0 here */
! 124: return 0;
! 125: }
! 126:
! 127: METHOD(aead_t, get_iv_gen, iv_gen_t*,
! 128: private_aead_t *this)
! 129: {
! 130: /* IVs are retrieved via keymat_v1.get_iv() */
! 131: return NULL;
! 132: }
! 133:
! 134: METHOD(aead_t, get_key_size, size_t,
! 135: private_aead_t *this)
! 136: {
! 137: return this->crypter->get_key_size(this->crypter);
! 138: }
! 139:
! 140: METHOD(aead_t, set_key, bool,
! 141: private_aead_t *this, chunk_t key)
! 142: {
! 143: return this->crypter->set_key(this->crypter, key);
! 144: }
! 145:
! 146: METHOD(aead_t, aead_destroy, void,
! 147: private_aead_t *this)
! 148: {
! 149: this->crypter->destroy(this->crypter);
! 150: free(this);
! 151: }
! 152:
! 153: /**
! 154: * Expand SKEYID_e according to Appendix B in RFC 2409.
! 155: * TODO-IKEv1: verify keys (e.g. for weak keys, see Appendix B)
! 156: */
! 157: static bool expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf,
! 158: chunk_t *ka)
! 159: {
! 160: size_t block_size;
! 161: chunk_t seed;
! 162: int i;
! 163:
! 164: if (skeyid_e.len >= key_size)
! 165: { /* no expansion required, reduce to key_size */
! 166: skeyid_e.len = key_size;
! 167: *ka = skeyid_e;
! 168: return TRUE;
! 169: }
! 170: block_size = prf->get_block_size(prf);
! 171: *ka = chunk_alloc((key_size / block_size + 1) * block_size);
! 172: ka->len = key_size;
! 173:
! 174: /* Ka = K1 | K2 | ..., K1 = prf(SKEYID_e, 0), K2 = prf(SKEYID_e, K1) ... */
! 175: if (!prf->set_key(prf, skeyid_e))
! 176: {
! 177: chunk_clear(ka);
! 178: chunk_clear(&skeyid_e);
! 179: return FALSE;
! 180: }
! 181: seed = octet_0;
! 182: for (i = 0; i < key_size; i += block_size)
! 183: {
! 184: if (!prf->get_bytes(prf, seed, ka->ptr + i))
! 185: {
! 186: chunk_clear(ka);
! 187: chunk_clear(&skeyid_e);
! 188: return FALSE;
! 189: }
! 190: seed = chunk_create(ka->ptr + i, block_size);
! 191: }
! 192: chunk_clear(&skeyid_e);
! 193: return TRUE;
! 194: }
! 195:
! 196: /**
! 197: * Create a simple implementation of the aead_t interface which only encrypts
! 198: * or decrypts data.
! 199: */
! 200: static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e,
! 201: chunk_t *ka)
! 202: {
! 203: private_aead_t *this;
! 204: uint16_t alg, key_size;
! 205: crypter_t *crypter;
! 206:
! 207: if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg,
! 208: &key_size))
! 209: {
! 210: DBG1(DBG_IKE, "no %N selected",
! 211: transform_type_names, ENCRYPTION_ALGORITHM);
! 212: return NULL;
! 213: }
! 214: crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
! 215: if (!crypter)
! 216: {
! 217: DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
! 218: transform_type_names, ENCRYPTION_ALGORITHM,
! 219: encryption_algorithm_names, alg, key_size);
! 220: return NULL;
! 221: }
! 222: if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, ka))
! 223: {
! 224: return NULL;
! 225: }
! 226: DBG4(DBG_IKE, "encryption key Ka %B", ka);
! 227: if (!crypter->set_key(crypter, *ka))
! 228: {
! 229: chunk_clear(ka);
! 230: return NULL;
! 231: }
! 232:
! 233: INIT(this,
! 234: .aead = {
! 235: .encrypt = _encrypt,
! 236: .decrypt = _decrypt,
! 237: .get_block_size = _get_block_size,
! 238: .get_icv_size = _get_icv_size,
! 239: .get_iv_size = _get_iv_size,
! 240: .get_iv_gen = _get_iv_gen,
! 241: .get_key_size = _get_key_size,
! 242: .set_key = _set_key,
! 243: .destroy = _aead_destroy,
! 244: },
! 245: .crypter = crypter,
! 246: );
! 247: return &this->aead;
! 248: }
! 249:
! 250: /**
! 251: * Converts integrity algorithm to PRF algorithm
! 252: */
! 253: static uint16_t auth_to_prf(uint16_t alg)
! 254: {
! 255: switch (alg)
! 256: {
! 257: case AUTH_HMAC_SHA1_96:
! 258: return PRF_HMAC_SHA1;
! 259: case AUTH_HMAC_SHA2_256_128:
! 260: return PRF_HMAC_SHA2_256;
! 261: case AUTH_HMAC_SHA2_384_192:
! 262: return PRF_HMAC_SHA2_384;
! 263: case AUTH_HMAC_SHA2_512_256:
! 264: return PRF_HMAC_SHA2_512;
! 265: case AUTH_HMAC_MD5_96:
! 266: return PRF_HMAC_MD5;
! 267: case AUTH_AES_XCBC_96:
! 268: return PRF_AES128_XCBC;
! 269: default:
! 270: return PRF_UNDEFINED;
! 271: }
! 272: }
! 273:
! 274: /**
! 275: * Converts integrity algorithm to hash algorithm
! 276: */
! 277: static uint16_t auth_to_hash(uint16_t alg)
! 278: {
! 279: switch (alg)
! 280: {
! 281: case AUTH_HMAC_SHA1_96:
! 282: return HASH_SHA1;
! 283: case AUTH_HMAC_SHA2_256_128:
! 284: return HASH_SHA256;
! 285: case AUTH_HMAC_SHA2_384_192:
! 286: return HASH_SHA384;
! 287: case AUTH_HMAC_SHA2_512_256:
! 288: return HASH_SHA512;
! 289: case AUTH_HMAC_MD5_96:
! 290: return HASH_MD5;
! 291: default:
! 292: return HASH_UNKNOWN;
! 293: }
! 294: }
! 295:
! 296: /**
! 297: * Adjust the key length for PRF algorithms that expect a fixed key length.
! 298: */
! 299: static void adjust_keylen(uint16_t alg, chunk_t *key)
! 300: {
! 301: switch (alg)
! 302: {
! 303: case PRF_AES128_XCBC:
! 304: /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
! 305: * not and therefore fixed key semantics apply to XCBC for key
! 306: * derivation. */
! 307: key->len = min(key->len, 16);
! 308: break;
! 309: default:
! 310: /* all other algorithms use variable key length */
! 311: break;
! 312: }
! 313: }
! 314:
! 315: METHOD(keymat_v1_t, derive_ike_keys, bool,
! 316: private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
! 317: chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
! 318: auth_method_t auth, shared_key_t *shared_key)
! 319: {
! 320: chunk_t g_xy, g_xi, g_xr, dh_me, spi_i, spi_r, nonces, data, skeyid_e;
! 321: chunk_t skeyid, ka;
! 322: uint16_t alg;
! 323:
! 324: spi_i = chunk_alloca(sizeof(uint64_t));
! 325: spi_r = chunk_alloca(sizeof(uint64_t));
! 326:
! 327: if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
! 328: { /* no PRF negotiated, use HMAC version of integrity algorithm instead */
! 329: if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)
! 330: || (alg = auth_to_prf(alg)) == PRF_UNDEFINED)
! 331: {
! 332: DBG1(DBG_IKE, "no %N selected",
! 333: transform_type_names, PSEUDO_RANDOM_FUNCTION);
! 334: return FALSE;
! 335: }
! 336: }
! 337: this->prf = lib->crypto->create_prf(lib->crypto, alg);
! 338: if (!this->prf)
! 339: {
! 340: DBG1(DBG_IKE, "%N %N not supported!",
! 341: transform_type_names, PSEUDO_RANDOM_FUNCTION,
! 342: pseudo_random_function_names, alg);
! 343: return FALSE;
! 344: }
! 345: if (this->prf->get_block_size(this->prf) <
! 346: this->prf->get_key_size(this->prf))
! 347: { /* TODO-IKEv1: support PRF output expansion (RFC 2409, Appendix B) */
! 348: DBG1(DBG_IKE, "expansion of %N %N output not supported!",
! 349: transform_type_names, PSEUDO_RANDOM_FUNCTION,
! 350: pseudo_random_function_names, alg);
! 351: return FALSE;
! 352: }
! 353:
! 354: if (!dh->get_shared_secret(dh, &g_xy))
! 355: {
! 356: return FALSE;
! 357: }
! 358: DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &g_xy);
! 359:
! 360: *((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
! 361: *((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
! 362: nonces = chunk_cata("cc", nonce_i, nonce_r);
! 363:
! 364: switch (auth)
! 365: {
! 366: case AUTH_PSK:
! 367: case AUTH_XAUTH_INIT_PSK:
! 368: case AUTH_XAUTH_RESP_PSK:
! 369: { /* SKEYID = prf(pre-shared-key, Ni_b | Nr_b) */
! 370: chunk_t psk;
! 371: if (!shared_key)
! 372: {
! 373: chunk_clear(&g_xy);
! 374: return FALSE;
! 375: }
! 376: psk = shared_key->get_key(shared_key);
! 377: adjust_keylen(alg, &psk);
! 378: if (!this->prf->set_key(this->prf, psk) ||
! 379: !this->prf->allocate_bytes(this->prf, nonces, &skeyid))
! 380: {
! 381: chunk_clear(&g_xy);
! 382: return FALSE;
! 383: }
! 384: break;
! 385: }
! 386: case AUTH_RSA:
! 387: case AUTH_ECDSA_256:
! 388: case AUTH_ECDSA_384:
! 389: case AUTH_ECDSA_521:
! 390: case AUTH_XAUTH_INIT_RSA:
! 391: case AUTH_XAUTH_RESP_RSA:
! 392: case AUTH_HYBRID_INIT_RSA:
! 393: case AUTH_HYBRID_RESP_RSA:
! 394: {
! 395: if (!this->prf->set_key(this->prf, nonces) ||
! 396: !this->prf->allocate_bytes(this->prf, g_xy, &skeyid))
! 397: {
! 398: chunk_clear(&g_xy);
! 399: return FALSE;
! 400: }
! 401: break;
! 402: }
! 403: default:
! 404: /* TODO-IKEv1: implement key derivation for other schemes */
! 405: /* authentication class not supported */
! 406: chunk_clear(&g_xy);
! 407: return FALSE;
! 408: }
! 409: adjust_keylen(alg, &skeyid);
! 410: DBG4(DBG_IKE, "SKEYID %B", &skeyid);
! 411:
! 412: /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */
! 413: data = chunk_cat("cccc", g_xy, spi_i, spi_r, octet_0);
! 414: if (!this->prf->set_key(this->prf, skeyid) ||
! 415: !this->prf->allocate_bytes(this->prf, data, &this->skeyid_d))
! 416: {
! 417: chunk_clear(&g_xy);
! 418: chunk_clear(&data);
! 419: chunk_clear(&skeyid);
! 420: return FALSE;
! 421: }
! 422: chunk_clear(&data);
! 423: DBG4(DBG_IKE, "SKEYID_d %B", &this->skeyid_d);
! 424:
! 425: /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
! 426: data = chunk_cat("ccccc", this->skeyid_d, g_xy, spi_i, spi_r, octet_1);
! 427: if (!this->prf->allocate_bytes(this->prf, data, &this->skeyid_a))
! 428: {
! 429: chunk_clear(&g_xy);
! 430: chunk_clear(&data);
! 431: chunk_clear(&skeyid);
! 432: return FALSE;
! 433: }
! 434: chunk_clear(&data);
! 435: DBG4(DBG_IKE, "SKEYID_a %B", &this->skeyid_a);
! 436:
! 437: /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */
! 438: data = chunk_cat("ccccc", this->skeyid_a, g_xy, spi_i, spi_r, octet_2);
! 439: if (!this->prf->allocate_bytes(this->prf, data, &skeyid_e))
! 440: {
! 441: chunk_clear(&g_xy);
! 442: chunk_clear(&data);
! 443: chunk_clear(&skeyid);
! 444: return FALSE;
! 445: }
! 446: chunk_clear(&data);
! 447: DBG4(DBG_IKE, "SKEYID_e %B", &skeyid_e);
! 448:
! 449: chunk_clear(&g_xy);
! 450:
! 451: switch (auth)
! 452: {
! 453: case AUTH_ECDSA_256:
! 454: alg = PRF_HMAC_SHA2_256;
! 455: break;
! 456: case AUTH_ECDSA_384:
! 457: alg = PRF_HMAC_SHA2_384;
! 458: break;
! 459: case AUTH_ECDSA_521:
! 460: alg = PRF_HMAC_SHA2_512;
! 461: break;
! 462: default:
! 463: /* use proposal algorithm */
! 464: break;
! 465: }
! 466: this->prf_auth = lib->crypto->create_prf(lib->crypto, alg);
! 467: if (!this->prf_auth)
! 468: {
! 469: DBG1(DBG_IKE, "%N %N not supported!",
! 470: transform_type_names, PSEUDO_RANDOM_FUNCTION,
! 471: pseudo_random_function_names, alg);
! 472: chunk_clear(&skeyid);
! 473: return FALSE;
! 474: }
! 475: if (!this->prf_auth->set_key(this->prf_auth, skeyid))
! 476: {
! 477: chunk_clear(&skeyid);
! 478: return FALSE;
! 479: }
! 480: chunk_clear(&skeyid);
! 481:
! 482: this->aead = create_aead(proposal, this->prf, skeyid_e, &ka);
! 483: if (!this->aead)
! 484: {
! 485: return FALSE;
! 486: }
! 487: charon->bus->ike_derived_keys(charon->bus, ka, chunk_empty, this->skeyid_a,
! 488: chunk_empty);
! 489: chunk_clear(&ka);
! 490: if (!this->hasher && !this->public.create_hasher(&this->public, proposal))
! 491: {
! 492: return FALSE;
! 493: }
! 494:
! 495: if (!dh->get_my_public_value(dh, &dh_me))
! 496: {
! 497: return FALSE;
! 498: }
! 499: g_xi = this->initiator ? dh_me : dh_other;
! 500: g_xr = this->initiator ? dh_other : dh_me;
! 501:
! 502: /* initial IV = hash(g^xi | g^xr) */
! 503: data = chunk_cata("cc", g_xi, g_xr);
! 504: chunk_free(&dh_me);
! 505: return this->iv_manager->init_iv_chain(this->iv_manager, data, this->hasher,
! 506: this->aead->get_block_size(this->aead));
! 507: }
! 508:
! 509: METHOD(keymat_v1_t, derive_child_keys, bool,
! 510: private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
! 511: uint32_t spi_i, uint32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
! 512: chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r)
! 513: {
! 514: uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
! 515: uint8_t protocol;
! 516: prf_plus_t *prf_plus;
! 517: chunk_t seed, secret = chunk_empty;
! 518: bool success = FALSE;
! 519:
! 520: if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
! 521: &enc_alg, &enc_size))
! 522: {
! 523: DBG2(DBG_CHD, " using %N for encryption",
! 524: encryption_algorithm_names, enc_alg);
! 525:
! 526: if (!enc_size)
! 527: {
! 528: enc_size = keymat_get_keylen_encr(enc_alg);
! 529: }
! 530: if (enc_alg != ENCR_NULL && !enc_size)
! 531: {
! 532: DBG1(DBG_CHD, "no keylength defined for %N",
! 533: encryption_algorithm_names, enc_alg);
! 534: return FALSE;
! 535: }
! 536: /* to bytes */
! 537: enc_size /= 8;
! 538:
! 539: /* CCM/GCM/CTR/GMAC needs additional bytes */
! 540: switch (enc_alg)
! 541: {
! 542: case ENCR_AES_CCM_ICV8:
! 543: case ENCR_AES_CCM_ICV12:
! 544: case ENCR_AES_CCM_ICV16:
! 545: case ENCR_CAMELLIA_CCM_ICV8:
! 546: case ENCR_CAMELLIA_CCM_ICV12:
! 547: case ENCR_CAMELLIA_CCM_ICV16:
! 548: enc_size += 3;
! 549: break;
! 550: case ENCR_AES_GCM_ICV8:
! 551: case ENCR_AES_GCM_ICV12:
! 552: case ENCR_AES_GCM_ICV16:
! 553: case ENCR_AES_CTR:
! 554: case ENCR_NULL_AUTH_AES_GMAC:
! 555: enc_size += 4;
! 556: break;
! 557: default:
! 558: break;
! 559: }
! 560: }
! 561:
! 562: if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
! 563: &int_alg, &int_size))
! 564: {
! 565: DBG2(DBG_CHD, " using %N for integrity",
! 566: integrity_algorithm_names, int_alg);
! 567:
! 568: if (!int_size)
! 569: {
! 570: int_size = keymat_get_keylen_integ(int_alg);
! 571: }
! 572: if (!int_size)
! 573: {
! 574: DBG1(DBG_CHD, "no keylength defined for %N",
! 575: integrity_algorithm_names, int_alg);
! 576: return FALSE;
! 577: }
! 578: /* to bytes */
! 579: int_size /= 8;
! 580: }
! 581:
! 582: /* KEYMAT = prf+(SKEYID_d, [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b) */
! 583: if (!this->prf->set_key(this->prf, this->skeyid_d))
! 584: {
! 585: return FALSE;
! 586: }
! 587: protocol = proposal->get_protocol(proposal);
! 588: if (dh)
! 589: {
! 590: if (!dh->get_shared_secret(dh, &secret))
! 591: {
! 592: return FALSE;
! 593: }
! 594: DBG4(DBG_CHD, "DH secret %B", &secret);
! 595: }
! 596:
! 597: *encr_r = *integ_r = *encr_i = *integ_i = chunk_empty;
! 598: seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
! 599: chunk_from_thing(spi_r), nonce_i, nonce_r);
! 600: DBG4(DBG_CHD, "initiator SA seed %B", &seed);
! 601:
! 602: prf_plus = prf_plus_create(this->prf, FALSE, seed);
! 603: if (!prf_plus ||
! 604: !prf_plus->allocate_bytes(prf_plus, enc_size, encr_i) ||
! 605: !prf_plus->allocate_bytes(prf_plus, int_size, integ_i))
! 606: {
! 607: goto failure;
! 608: }
! 609:
! 610: seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
! 611: chunk_from_thing(spi_i), nonce_i, nonce_r);
! 612: DBG4(DBG_CHD, "responder SA seed %B", &seed);
! 613: prf_plus->destroy(prf_plus);
! 614: prf_plus = prf_plus_create(this->prf, FALSE, seed);
! 615: if (!prf_plus ||
! 616: !prf_plus->allocate_bytes(prf_plus, enc_size, encr_r) ||
! 617: !prf_plus->allocate_bytes(prf_plus, int_size, integ_r))
! 618: {
! 619: goto failure;
! 620: }
! 621:
! 622: if (enc_size)
! 623: {
! 624: DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
! 625: DBG4(DBG_CHD, "encryption responder key %B", encr_r);
! 626: }
! 627: if (int_size)
! 628: {
! 629: DBG4(DBG_CHD, "integrity initiator key %B", integ_i);
! 630: DBG4(DBG_CHD, "integrity responder key %B", integ_r);
! 631: }
! 632: success = TRUE;
! 633:
! 634: failure:
! 635: if (!success)
! 636: {
! 637: chunk_clear(encr_i);
! 638: chunk_clear(integ_i);
! 639: chunk_clear(encr_r);
! 640: chunk_clear(integ_r);
! 641: }
! 642: DESTROY_IF(prf_plus);
! 643: chunk_clear(&secret);
! 644:
! 645: return success;
! 646: }
! 647:
! 648: METHOD(keymat_v1_t, create_hasher, bool,
! 649: private_keymat_v1_t *this, proposal_t *proposal)
! 650: {
! 651: uint16_t alg;
! 652: if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL) ||
! 653: (alg = auth_to_hash(alg)) == HASH_UNKNOWN)
! 654: {
! 655: DBG1(DBG_IKE, "no %N selected", transform_type_names, HASH_ALGORITHM);
! 656: return FALSE;
! 657: }
! 658: this->hasher = lib->crypto->create_hasher(lib->crypto, alg);
! 659: if (!this->hasher)
! 660: {
! 661: DBG1(DBG_IKE, "%N %N not supported!",
! 662: transform_type_names, HASH_ALGORITHM,
! 663: hash_algorithm_names, alg);
! 664: return FALSE;
! 665: }
! 666: return TRUE;
! 667: }
! 668:
! 669: METHOD(keymat_v1_t, get_hasher, hasher_t*,
! 670: private_keymat_v1_t *this)
! 671: {
! 672: return this->hasher;
! 673: }
! 674:
! 675: METHOD(keymat_v1_t, get_hash, bool,
! 676: private_keymat_v1_t *this, bool initiator, chunk_t dh, chunk_t dh_other,
! 677: ike_sa_id_t *ike_sa_id, chunk_t sa_i, chunk_t id, chunk_t *hash,
! 678: signature_scheme_t *scheme)
! 679: {
! 680: chunk_t data;
! 681: uint64_t spi, spi_other;
! 682:
! 683: /* HASH_I = prf(SKEYID, g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b )
! 684: * HASH_R = prf(SKEYID, g^xr | g^xi | CKY-R | CKY-I | SAi_b | IDir_b )
! 685: */
! 686: if (initiator)
! 687: {
! 688: spi = ike_sa_id->get_initiator_spi(ike_sa_id);
! 689: spi_other = ike_sa_id->get_responder_spi(ike_sa_id);
! 690: }
! 691: else
! 692: {
! 693: spi_other = ike_sa_id->get_initiator_spi(ike_sa_id);
! 694: spi = ike_sa_id->get_responder_spi(ike_sa_id);
! 695: }
! 696: data = chunk_cat("cccccc", dh, dh_other,
! 697: chunk_from_thing(spi), chunk_from_thing(spi_other),
! 698: sa_i, id);
! 699:
! 700: DBG3(DBG_IKE, "HASH_%c data %B", initiator ? 'I' : 'R', &data);
! 701:
! 702: if (!this->prf_auth->allocate_bytes(this->prf_auth, data, hash))
! 703: {
! 704: free(data.ptr);
! 705: return FALSE;
! 706: }
! 707:
! 708: DBG3(DBG_IKE, "HASH_%c %B", initiator ? 'I' : 'R', hash);
! 709:
! 710: free(data.ptr);
! 711: return TRUE;
! 712: }
! 713:
! 714: /**
! 715: * Get the nonce value found in the given message.
! 716: * Returns FALSE if none is found.
! 717: */
! 718: static bool get_nonce(message_t *message, chunk_t *n)
! 719: {
! 720: nonce_payload_t *nonce;
! 721: nonce = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
! 722: if (nonce)
! 723: {
! 724: *n = nonce->get_nonce(nonce);
! 725: return TRUE;
! 726: }
! 727: return FALSE;
! 728: }
! 729:
! 730: /**
! 731: * Generate the message data in order to generate the hashes.
! 732: */
! 733: static chunk_t get_message_data(message_t *message, generator_t *generator)
! 734: {
! 735: payload_t *payload, *next;
! 736: enumerator_t *enumerator;
! 737: uint32_t *lenpos;
! 738:
! 739: if (message->is_encoded(message))
! 740: { /* inbound, although the message is generated, we cannot access the
! 741: * cleartext message data, so generate it anyway */
! 742: enumerator = message->create_payload_enumerator(message);
! 743: while (enumerator->enumerate(enumerator, &payload))
! 744: {
! 745: if (payload->get_type(payload) == PLV1_HASH)
! 746: {
! 747: continue;
! 748: }
! 749: generator->generate_payload(generator, payload);
! 750: }
! 751: enumerator->destroy(enumerator);
! 752: }
! 753: else
! 754: {
! 755: /* outbound, generate the payloads (there is no HASH payload yet) */
! 756: enumerator = message->create_payload_enumerator(message);
! 757: if (enumerator->enumerate(enumerator, &payload))
! 758: {
! 759: while (enumerator->enumerate(enumerator, &next))
! 760: {
! 761: payload->set_next_type(payload, next->get_type(next));
! 762: generator->generate_payload(generator, payload);
! 763: payload = next;
! 764: }
! 765: payload->set_next_type(payload, PL_NONE);
! 766: generator->generate_payload(generator, payload);
! 767: }
! 768: enumerator->destroy(enumerator);
! 769: }
! 770: return generator->get_chunk(generator, &lenpos);
! 771: }
! 772:
! 773: METHOD(keymat_v1_t, get_hash_phase2, bool,
! 774: private_keymat_v1_t *this, message_t *message, chunk_t *hash)
! 775: {
! 776: uint32_t mid, mid_n;
! 777: chunk_t data = chunk_empty, *n_i, *n_r;
! 778: bool add_message = TRUE;
! 779: char *name = "Hash";
! 780:
! 781: if (!this->prf)
! 782: { /* no keys derived yet */
! 783: return FALSE;
! 784: }
! 785:
! 786: mid = message->get_message_id(message);
! 787: mid_n = htonl(mid);
! 788:
! 789: /* Hashes are simple for most exchanges in Phase 2:
! 790: * Hash = prf(SKEYID_a, M-ID | Complete message after HASH payload)
! 791: * For Quick Mode there are three hashes:
! 792: * Hash(1) = same as above
! 793: * Hash(2) = prf(SKEYID_a, M-ID | Ni_b | Message after HASH payload)
! 794: * Hash(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b)
! 795: * So, for Quick Mode we keep track of the nonce values.
! 796: */
! 797: switch (message->get_exchange_type(message))
! 798: {
! 799: case QUICK_MODE:
! 800: {
! 801: this->iv_manager->lookup_quick_mode(this->iv_manager, mid, &n_i,
! 802: &n_r);
! 803: if (!n_i->ptr)
! 804: { /* Hash(1) = prf(SKEYID_a, M-ID | Message after HASH payload) */
! 805: name = "Hash(1)";
! 806: if (!get_nonce(message, n_i))
! 807: {
! 808: return FALSE;
! 809: }
! 810: data = chunk_from_thing(mid_n);
! 811: }
! 812: else if (!n_r->ptr)
! 813: { /* Hash(2) = prf(SKEYID_a, M-ID | Ni_b | Message after HASH) */
! 814: name = "Hash(2)";
! 815: if (!get_nonce(message, n_r))
! 816: {
! 817: return FALSE;
! 818: }
! 819: data = chunk_cata("cc", chunk_from_thing(mid_n), *n_i);
! 820: }
! 821: else
! 822: { /* Hash(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
! 823: name = "Hash(3)";
! 824: data = chunk_cata("cccc", octet_0, chunk_from_thing(mid_n),
! 825: *n_i, *n_r);
! 826: add_message = FALSE;
! 827: /* we don't need the state anymore */
! 828: this->iv_manager->remove_quick_mode(this->iv_manager, mid);
! 829: }
! 830: break;
! 831: }
! 832: case TRANSACTION:
! 833: case INFORMATIONAL_V1:
! 834: /* Hash = prf(SKEYID_a, M-ID | Message after HASH payload) */
! 835: data = chunk_from_thing(mid_n);
! 836: break;
! 837: default:
! 838: return FALSE;
! 839: }
! 840: if (!this->prf->set_key(this->prf, this->skeyid_a))
! 841: {
! 842: return FALSE;
! 843: }
! 844: if (add_message)
! 845: {
! 846: generator_t *generator;
! 847: chunk_t msg;
! 848:
! 849: generator = generator_create_no_dbg();
! 850: msg = get_message_data(message, generator);
! 851: if (!this->prf->allocate_bytes(this->prf, data, NULL) ||
! 852: !this->prf->allocate_bytes(this->prf, msg, hash))
! 853: {
! 854: generator->destroy(generator);
! 855: return FALSE;
! 856: }
! 857: generator->destroy(generator);
! 858: }
! 859: else
! 860: {
! 861: if (!this->prf->allocate_bytes(this->prf, data, hash))
! 862: {
! 863: return FALSE;
! 864: }
! 865: }
! 866: DBG3(DBG_IKE, "%s %B", name, hash);
! 867: return TRUE;
! 868: }
! 869:
! 870: METHOD(keymat_v1_t, get_iv, bool,
! 871: private_keymat_v1_t *this, uint32_t mid, chunk_t *out)
! 872: {
! 873: return this->iv_manager->get_iv(this->iv_manager, mid, out);
! 874: }
! 875:
! 876: METHOD(keymat_v1_t, update_iv, bool,
! 877: private_keymat_v1_t *this, uint32_t mid, chunk_t last_block)
! 878: {
! 879: return this->iv_manager->update_iv(this->iv_manager, mid, last_block);
! 880: }
! 881:
! 882: METHOD(keymat_v1_t, confirm_iv, bool,
! 883: private_keymat_v1_t *this, uint32_t mid)
! 884: {
! 885: return this->iv_manager->confirm_iv(this->iv_manager, mid);
! 886: }
! 887:
! 888: METHOD(keymat_t, get_version, ike_version_t,
! 889: private_keymat_v1_t *this)
! 890: {
! 891: return IKEV1;
! 892: }
! 893:
! 894: METHOD(keymat_t, create_dh, diffie_hellman_t*,
! 895: private_keymat_v1_t *this, diffie_hellman_group_t group)
! 896: {
! 897: return lib->crypto->create_dh(lib->crypto, group);
! 898: }
! 899:
! 900: METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
! 901: private_keymat_v1_t *this)
! 902: {
! 903: return lib->crypto->create_nonce_gen(lib->crypto);
! 904: }
! 905:
! 906: METHOD(keymat_t, get_aead, aead_t*,
! 907: private_keymat_v1_t *this, bool in)
! 908: {
! 909: return this->aead;
! 910: }
! 911:
! 912: METHOD(keymat_t, destroy, void,
! 913: private_keymat_v1_t *this)
! 914: {
! 915: DESTROY_IF(this->prf);
! 916: DESTROY_IF(this->prf_auth);
! 917: DESTROY_IF(this->aead);
! 918: DESTROY_IF(this->hasher);
! 919: chunk_clear(&this->skeyid_d);
! 920: chunk_clear(&this->skeyid_a);
! 921: this->iv_manager->destroy(this->iv_manager);
! 922: free(this);
! 923: }
! 924:
! 925: /**
! 926: * See header
! 927: */
! 928: keymat_v1_t *keymat_v1_create(bool initiator)
! 929: {
! 930: private_keymat_v1_t *this;
! 931:
! 932: INIT(this,
! 933: .public = {
! 934: .keymat = {
! 935: .get_version = _get_version,
! 936: .create_dh = _create_dh,
! 937: .create_nonce_gen = _create_nonce_gen,
! 938: .get_aead = _get_aead,
! 939: .destroy = _destroy,
! 940: },
! 941: .derive_ike_keys = _derive_ike_keys,
! 942: .derive_child_keys = _derive_child_keys,
! 943: .create_hasher = _create_hasher,
! 944: .get_hasher = _get_hasher,
! 945: .get_hash = _get_hash,
! 946: .get_hash_phase2 = _get_hash_phase2,
! 947: .get_iv = _get_iv,
! 948: .update_iv = _update_iv,
! 949: .confirm_iv = _confirm_iv,
! 950: },
! 951: .initiator = initiator,
! 952: .iv_manager = iv_manager_create(0),
! 953: );
! 954: return &this->public;
! 955: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>