Example #1
0
/* MUST BE THREAD-SAFE */
void calc_dh(struct pluto_crypto_req *r)
{
	/* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */
	struct pcr_skeyid_q dhq;
	memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq));

	/* clear out the reply */
	struct pcr_skeyid_r *skr = &r->pcr_d.dhr;
	zero(skr);	/* ??? pointer fields might not be NULLed */
	INIT_WIRE_ARENA(*skr);

	const struct oakley_group_desc *group = lookup_group(dhq.oakley_group);
	passert(group != NULL);

	SECKEYPrivateKey *ltsecret = dhq.secret;
	SECKEYPublicKey *pubk = dhq.pubk;

	/* now calculate the (g^x)(g^y) */

	chunk_t g;

	setchunk_from_wire(g, &dhq, dhq.role == ORIGINAL_RESPONDER ? &dhq.gi : &dhq.gr);

	DBG(DBG_CRYPT, DBG_dump_chunk("peer's g: ", g));

	const char *story;	/* we ignore the value */

	skr->shared = calc_dh_shared(g, ltsecret, group, pubk, &story);
}
Example #2
0
/* MUST BE THREAD-SAFE */
void calc_dh_v2(struct pluto_crypto_req *r, const char **story)
{
	struct pcr_skeycalc_v2_r *const skr = &r->pcr_d.dhv2;

	/* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */
	struct pcr_skeyid_q dhq;
	memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq));

	/* clear out the reply (including pointers) */
	static const struct pcr_skeycalc_v2_r zero_pcr_skeycalc_v2_r;
	*skr = zero_pcr_skeycalc_v2_r;
	INIT_WIRE_ARENA(*skr);

	const struct oakley_group_desc *group = lookup_group(dhq.oakley_group);
	passert(group != NULL);

	SECKEYPrivateKey *ltsecret = dhq.secret;
	SECKEYPublicKey *pubk = dhq.pubk;

	/* now calculate the (g^x)(g^y) --- need gi on responder, gr on initiator */

	chunk_t g;
	setchunk_from_wire(g, &dhq, dhq.role == ORIGINAL_RESPONDER ? &dhq.gi : &dhq.gr);

	DBG(DBG_CRYPT, DBG_dump_chunk("peer's g: ", g));

	skr->shared = calc_dh_shared(g, ltsecret, group, pubk, story);

	if (skr->shared != NULL) {
	/* okay, so now all the shared key material */
	calc_skeyseed_v2(&dhq,  /* input */
		skr->shared,   /* input */
		dhq.key_size,  /* input */
		dhq.salt_size, /* input */

		&skr->skeyseed,        /* output */
		&skr->skeyid_d,        /* output */
		&skr->skeyid_ai,       /* output */
		&skr->skeyid_ar,       /* output */
		&skr->skeyid_ei,       /* output */
		&skr->skeyid_er,       /* output */
		&skr->skeyid_pi,       /* output */
		&skr->skeyid_pr,       /* output */
		&skr->skey_initiator_salt, /* output */
		&skr->skey_responder_salt, /* output */
		&skr->skey_chunk_SK_pi, /* output */
		&skr->skey_chunk_SK_pr); /* output */
	}
}
Example #3
0
/* MUST BE THREAD-SAFE */
static void calc_skeyseed_v2(struct pcr_skeyid_q *skq,
			     PK11SymKey *shared,
			     const size_t key_size,
			     const size_t salt_size,
			     PK11SymKey **skeyseed_out,
			     PK11SymKey **SK_d_out,
			     PK11SymKey **SK_ai_out,
			     PK11SymKey **SK_ar_out,
			     PK11SymKey **SK_ei_out,
			     PK11SymKey **SK_er_out,
			     PK11SymKey **SK_pi_out,
			     PK11SymKey **SK_pr_out,
			     chunk_t *initiator_salt_out,
			     chunk_t *responder_salt_out,
			     chunk_t *chunk_SK_pi_out,
			     chunk_t *chunk_SK_pr_out)
{
	DBG(DBG_CRYPT, DBG_log("NSS: Started key computation"));

	PK11SymKey
		*skeyseed_k,
		*SK_d_k,
		*SK_ai_k,
		*SK_ar_k,
		*SK_ei_k,
		*SK_er_k,
		*SK_pi_k,
		*SK_pr_k;
	chunk_t initiator_salt;
	chunk_t responder_salt;
	chunk_t chunk_SK_pi;
	chunk_t chunk_SK_pr;

	/* this doesn't take any memory, it's just moving pointers around */
	chunk_t ni;
	chunk_t nr;
	chunk_t spii;
	chunk_t spir;
	setchunk_from_wire(ni, skq, &skq->ni);
	setchunk_from_wire(nr, skq, &skq->nr);
	setchunk_from_wire(spii, skq, &skq->icookie);
	setchunk_from_wire(spir, skq, &skq->rcookie);

	DBG(DBG_CONTROLMORE,
	    DBG_log("calculating skeyseed using prf=%s integ=%s cipherkey-size=%zu salt-size=%zu",
		    enum_name(&ikev2_trans_type_prf_names, skq->prf_hash),
		    enum_name(&ikev2_trans_type_integ_names, skq->integ_hash),
		    key_size, salt_size));

	const struct hash_desc *prf_hasher = (struct hash_desc *)
		ikev2_alg_find(IKE_ALG_HASH, skq->prf_hash);
	passert(prf_hasher != NULL);

	const struct encrypt_desc *encrypter = skq->encrypter;
	passert(encrypter != NULL);

	/* generate SKEYSEED from key=(Ni|Nr), hash of shared */
	skeyseed_k = ikev2_ike_sa_skeyseed(prf_hasher, ni, nr, shared);
	passert(skeyseed_k != NULL);
	
	/* now we have to generate the keys for everything */

	/* need to know how many bits to generate */
	/* SK_d needs PRF hasher key bytes */
	/* SK_p needs PRF hasher*2 key bytes */
	/* SK_e needs key_size*2 key bytes */
	/* ..._salt needs salt_size*2 bytes */
	/* SK_a needs integ's key size*2 bytes */

	int skd_bytes = prf_hasher->hash_key_size;
	int skp_bytes = prf_hasher->hash_key_size;
	const struct hash_desc *integ_hasher =
		(struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, skq->integ_hash);
	int integ_size = integ_hasher != NULL ? integ_hasher->hash_key_size : 0;
	size_t total_keysize = skd_bytes + 2*skp_bytes + 2*key_size + 2*salt_size + 2*integ_size;
	PK11SymKey *finalkey = ikev2_ike_sa_keymat(prf_hasher, skeyseed_k,
						   ni, nr, spii, spir,
						   total_keysize);

	size_t next_byte = 0;

	SK_d_k = key_from_symkey_bytes(finalkey, next_byte, skd_bytes);
	next_byte += skd_bytes;

	SK_ai_k = key_from_symkey_bytes(finalkey, next_byte, integ_size);
	next_byte += integ_size;

	SK_ar_k = key_from_symkey_bytes(finalkey, next_byte, integ_size);
	next_byte += integ_size;

	/* The encryption key and salt are extracted together. */
	SK_ei_k = encrypt_key_from_symkey_bytes(finalkey, encrypter,
						next_byte, key_size);
	next_byte += key_size;
	PK11SymKey *initiator_salt_key = key_from_symkey_bytes(finalkey, next_byte,
							       salt_size);
	initiator_salt = chunk_from_symkey("initiator salt", initiator_salt_key);
	free_any_symkey("initiator salt key:", &initiator_salt_key);
						
	next_byte += salt_size;

	/* The encryption key and salt are extracted together. */	
	SK_er_k = encrypt_key_from_symkey_bytes(finalkey, encrypter,
						next_byte, key_size);
	next_byte += key_size;
	PK11SymKey *responder_salt_key = key_from_symkey_bytes(finalkey, next_byte,
							       salt_size);
	responder_salt = chunk_from_symkey("responder salt", responder_salt_key);
	free_any_symkey("responder salt key:", &responder_salt_key);
	next_byte += salt_size;

	SK_pi_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes);
	/* store copy of SK_pi_k for later use in authnull */
	chunk_SK_pi = chunk_from_symkey("chunk_SK_pi", SK_pi_k);
	next_byte += skp_bytes;

	SK_pr_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes);
	/* store copy of SK_pr_k for later use in authnull */
	chunk_SK_pr = chunk_from_symkey("chunk_SK_pr", SK_pr_k);
	next_byte += skp_bytes;	/* next_byte not subsequently used */

	DBG(DBG_CRYPT,
	    DBG_log("NSS ikev2: finished computing individual keys for IKEv2 SA"));
	free_any_symkey("finalkey", &finalkey);

	*skeyseed_out = skeyseed_k;
	*SK_d_out = SK_d_k;
	*SK_ai_out = SK_ai_k;
	*SK_ar_out = SK_ar_k;
	*SK_ei_out = SK_ei_k;
	*SK_er_out = SK_er_k;
	*SK_pi_out = SK_pi_k;
	*SK_pr_out = SK_pr_k;
	*initiator_salt_out = initiator_salt;
	*responder_salt_out = responder_salt;
	*chunk_SK_pi_out = chunk_SK_pi;
	*chunk_SK_pr_out = chunk_SK_pr;

	DBG(DBG_CRYPT,
	    DBG_log("calc_skeyseed_v2 pointers: shared %p, skeyseed %p, SK_d %p, SK_ai %p, SK_ar %p, SK_ei %p, SK_er %p, SK_pi %p, SK_pr %p",
		    shared, skeyseed_k, SK_d_k, SK_ai_k, SK_ar_k, SK_ei_k, SK_er_k, SK_pi_k, SK_pr_k);
	    DBG_dump_chunk("calc_skeyseed_v2 initiator salt", initiator_salt);
	    DBG_dump_chunk("calc_skeyseed_v2 responder salt", responder_salt);
	    DBG_dump_chunk("calc_skeyseed_v2 SK_pi", chunk_SK_pi);
	    DBG_dump_chunk("calc_skeyseed_v2 SK_pr", chunk_SK_pr));
}