Ejemplo n.º 1
0
void ikev2_derive_child_keys(struct state *st, enum phase1_role role)
{
	struct v2prf_stuff childsacalc;
	
	chunk_t ikeymat,rkeymat;
	struct ipsec_proto_info *ipi = &st->st_esp;
	
	ipi->attrs.transattrs.ei=kernel_alg_esp_info(
		ipi->attrs.transattrs.encrypt, 
		ipi->attrs.transattrs.enckeylen,
		ipi->attrs.transattrs.integ_hash);

	passert(ipi->attrs.transattrs.ei != NULL);
	memset(&childsacalc, 0, sizeof(childsacalc));
	childsacalc.prf_hasher = st->st_oakley.prf_hasher;

	setchunk(childsacalc.ni, st->st_ni.ptr, st->st_ni.len);
	setchunk(childsacalc.nr, st->st_nr.ptr, st->st_nr.len);
	childsacalc.spii.len=0;
	childsacalc.spir.len=0;
	
	childsacalc.counter[0] = 1;
	childsacalc.skeyseed = &st->st_skey_d;
	
	st->st_esp.present = TRUE;
	st->st_esp.keymat_len = st->st_esp.attrs.transattrs.ei->enckeylen+
		st->st_esp.attrs.transattrs.ei->authkeylen;
	
	
/*
 *
 * Keying material MUST be taken from the expanded KEYMAT in the
 * following order:
 *
 *    All keys for SAs carrying data from the initiator to the responder
 *    are taken before SAs going in the reverse direction.
 *
 *    If multiple IPsec protocols are negotiated, keying material is
 *    taken in the order in which the protocol headers will appear in
 *    the encapsulated packet.
 *
 *    If a single protocol has both encryption and authentication keys,
 *    the encryption key is taken from the first octets of KEYMAT and
 *    the authentication key is taken from the next octets.
 *
 */
	
	v2genbytes(&ikeymat, st->st_esp.keymat_len
		   , "initiator keys", &childsacalc);

	v2genbytes(&rkeymat, st->st_esp.keymat_len
		   , "responder keys", &childsacalc);

	/* This should really be role == INITIATOR, but then our keys are
	 * installed reversed. This is a workaround until we locate the
	 * real problem. It's better not to release copies of our code
	 * that will be incompatible with everything else, including our
	 * own updated version
	 * Found by Herbert Xu
	 * if(role == INITIATOR) {
	 */
	if(role != INITIATOR) {
	    DBG(DBG_CRYPT,
		DBG_dump_chunk("our  keymat", ikeymat);
		DBG_dump_chunk("peer keymat", rkeymat);
	    );
Ejemplo n.º 2
0
void ikev2_derive_child_keys(struct state *st, enum original_role role)
{
	chunk_t ikeymat, rkeymat;
	/* ??? note assumption that AH and ESP cannot be combined */
	struct ipsec_proto_info *ipi =
		st->st_esp.present? &st->st_esp :
		st->st_ah.present? &st->st_ah :
		NULL;
	struct esp_info *ei;

	passert(ipi != NULL);	/* ESP or AH must be present */
	passert(st->st_esp.present != st->st_ah.present);	/* only one */

	/* ??? there is no kernel_alg_ah_info */
	/* ??? will this work if the result of kernel_alg_esp_info
	 * is a pointer into its own static buffer (therefore ephemeral)?
	 */
	ei = kernel_alg_esp_info(
		ipi->attrs.transattrs.encrypt,
		ipi->attrs.transattrs.enckeylen,
		ipi->attrs.transattrs.integ_hash);

	passert(ei != NULL);
	ipi->attrs.transattrs.ei = ei;

	/* ipi->attrs.transattrs.integ_hasher->hash_key_size / BITS_PER_BYTE; */
	unsigned authkeylen = ikev1_auth_kernel_attrs(ei->auth, NULL);
	/* ??? no account is taken of AH */
	/* transid is same as esp_ealg_id */
	switch (ei->transid) {
	case IKEv2_ENCR_reserved:
		/* AH */
		ipi->keymat_len = authkeylen;
		break;

	case IKEv2_ENCR_AES_CTR:
		ipi->keymat_len = ei->enckeylen + authkeylen + AES_CTR_SALT_BYTES;;
		break;

	case IKEv2_ENCR_AES_GCM_8:
	case IKEv2_ENCR_AES_GCM_12:
	case IKEv2_ENCR_AES_GCM_16:
		/* aes_gcm does not use an integ (auth) algo - see RFC 4106 */
		ipi->keymat_len = ei->enckeylen + AES_GCM_SALT_BYTES;
		break;

	case IKEv2_ENCR_AES_CCM_8:
	case IKEv2_ENCR_AES_CCM_12:
	case IKEv2_ENCR_AES_CCM_16:
		/* aes_ccm does not use an integ (auth) algo - see RFC 4309 */
		ipi->keymat_len = ei->enckeylen + AES_CCM_SALT_BYTES;
		break;

	default:
		/* ordinary ESP */
		ipi->keymat_len = ei->enckeylen + authkeylen;
		break;
	}

	DBG(DBG_CONTROL,
		DBG_log("enckeylen=%" PRIu32 ", authkeylen=%u, keymat_len=%" PRIu16,
			ei->enckeylen, authkeylen, ipi->keymat_len));

	/*
	 *
	 * Keying material MUST be taken from the expanded KEYMAT in the
	 * following order:
	 *
	 *    All keys for SAs carrying data from the initiator to the responder
	 *    are taken before SAs going in the reverse direction.
	 *
	 *    If multiple IPsec protocols are negotiated, keying material is
	 *    taken in the order in which the protocol headers will appear in
	 *    the encapsulated packet.
	 *
	 *    If a single protocol has both encryption and authentication keys,
	 *    the encryption key is taken from the first octets of KEYMAT and
	 *    the authentication key is taken from the next octets.
	 *
	 *    For AES GCM (RFC 4106 Section 8,1) we need to add 4 bytes for
	 *    salt (AES_GCM_SALT_BYTES)
	 */
	chunk_t ni;
	chunk_t nr;
	setchunk(ni, st->st_ni.ptr, st->st_ni.len);
	setchunk(nr, st->st_nr.ptr, st->st_nr.len);

	PK11SymKey *keymat = ikev2_child_sa_keymat(st->st_oakley.prf_hasher,
						   st->st_skey_d_nss,
						   NULL/*dh*/, ni, nr,
						   ipi->keymat_len * 2);
	PK11SymKey *ikey = key_from_symkey_bytes(keymat, 0, ipi->keymat_len);
	ikeymat = chunk_from_symkey("initiator keys", ikey);
	free_any_symkey("ikey:", &ikey);

	PK11SymKey *rkey = key_from_symkey_bytes(keymat, ipi->keymat_len,
						 ipi->keymat_len);
	rkeymat = chunk_from_symkey("responder keys:", rkey);
	free_any_symkey("rkey:", &rkey);

	free_any_symkey("keymat", &keymat);

	if (role != ORIGINAL_INITIATOR) {
		DBG(DBG_PRIVATE, {
			    DBG_dump_chunk("our  keymat", ikeymat);
			    DBG_dump_chunk("peer keymat", rkeymat);
		    });