Exemplo n.º 1
0
Arquivo: spdb.c Projeto: mkj/libreswan
/*
 * this routine takes two proposals and conjoins them (or)
 */
struct db_sa *sa_merge_proposals(struct db_sa *a, struct db_sa *b)
{
	struct db_sa *n;
	unsigned int i, j, k;

	if (a == NULL || a->prop_conj_cnt == 0)
		return sa_copy_sa(b, 0);

	if (b == NULL || b->prop_conj_cnt == 0)
		return sa_copy_sa(a, 0);

	n = clone_thing(*a, "conjoin sa");

	passert(a->prop_conj_cnt == b->prop_conj_cnt);
	passert(a->prop_conj_cnt == 1);

	n->prop_conjs =
		clone_bytes(n->prop_conjs,
			    n->prop_conj_cnt * sizeof(n->prop_conjs[0]),
			    "sa copy prop conj array");

	for (i = 0; i < n->prop_conj_cnt; i++) {
		struct db_prop_conj *pca = &n->prop_conjs[i];
		struct db_prop_conj *pcb = &b->prop_conjs[i];

		passert(pca->prop_cnt == pcb->prop_cnt);
		passert(pca->prop_cnt == 1);

		pca->props = clone_bytes(pca->props,
					 pca->prop_cnt * sizeof(pca->props[0]),
					 "sa copy prop array");

		for (j = 0; j < pca->prop_cnt; j++) {
			struct db_prop *pa = &pca->props[j];
			struct db_prop *pb = &pcb->props[j];
			struct db_trans *t;
			int t_cnt = (pa->trans_cnt + pb->trans_cnt);

			t = alloc_bytes(t_cnt * sizeof(pa->trans[0]),
					"sa copy trans array");

			memcpy(t, pa->trans, (pa->trans_cnt) *
			       sizeof(pa->trans[0]));
			memcpy(t + (pa->trans_cnt),
			       pb->trans,
			       (pb->trans_cnt) * sizeof(pa->trans[0]));

			pa->trans = t;
			pa->trans_cnt = t_cnt;
			for (k = 0; k < pa->trans_cnt; k++)
				clone_trans(&pa->trans[k], 0);
		}
	}

	n->parentSA = a->parentSA;
	return n;
}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
    int i;
    struct db_sa *sa1 = NULL;
    struct db_sa *sa2 = NULL;

    progname = argv[0];
    leak_detective=1;

    tool_init_log();

    for(i=0; i < elemsof(oakley_sadb); i++) {
	printf("\nmain mode oakley: %u\n", i);
	sa_print(&oakley_sadb[i]);
	sa1 = sa_copy_sa(&oakley_sadb[i], 0);

	if(sa2 != NULL) {
	    free_sa(sa2);
	}
	sa2 = sa_copy_sa(sa1, 0);
	free_sa(sa1);

	printf("copy 2\n");
	sa_print(sa2);
    }

    for(i=0; i < elemsof(oakley_am_sadb); i++) {
	printf("\naggr mode oakley: %u\n", i);
	sa_print(&oakley_am_sadb[i]);
	sa1 = sa_copy_sa(&oakley_am_sadb[i], 0);

	if(sa2 != NULL) {
	    free_sa(sa2);
	}
	sa2 = sa_copy_sa(sa1, 0);
	free_sa(sa1);

	printf("copy 2\n");
	sa_print(sa2);
    }

    if(sa2 != NULL) free_sa(sa2);

    report_leaks();
    tool_close_log();
    exit(0);
}
Exemplo n.º 3
0
main(int argc, char *argv[]){
	int i;
	struct db_sa *gsp = NULL;
	struct db_sa *sa1 = NULL;
	struct db_sa *sa2 = NULL;

	progname = argv[0];
	leak_detective = 1;

	tool_init_log();

	for (i = 0; i < elemsof(oakley_sadb); i++) {
		gsp = sa_copy_sa(&oakley_empty, 0);

		printf("\nmain mode oakley: %u\n", i);
		//sa_print(&oakley_sadb[i]);
		sa1 = sa_copy_sa(&oakley_sadb[i], 0);

		sa2 = sa_merge_proposals(gsp, sa1);

		printf("sa1:\n");
		sa_print(sa1);

		printf("gsp:\n");
		sa_print(gsp);

		printf("sa2:\n");
		sa_print(sa2);

		free_sa(sa1);
		free_sa(sa2);
		free_sa(gsp);
		report_leaks();
	}

	tool_close_log();
	exit(0);
}
Exemplo n.º 4
0
struct db_sa *oakley_alg_mergedb(struct alg_info_ike *ai,
				 enum ikev1_auth_method auth_method,
				 bool single_dh)
{
	passert(ai != NULL);

	struct db_sa *gsp = NULL;

	/* Next two are for multiple proposals in aggressive mode... */
	unsigned last_modp = 0;
	bool warned_dropped_dhgr = FALSE;

	int transcnt = 0;

	/*
	 * for each group, we will create a new proposal item, and then
	 * append it to the list of transforms in the conjoint point.
	 *
	 * when creating each item, we will use the first transform
	 * from the base item as the template.
	 */
	FOR_EACH_IKE_INFO(ai, ike_info) {
		struct db_sa *emp_sp;

		passert(ike_info->ike_encrypt);
		passert(ike_info->ike_prf);
		passert(ike_info->ike_dh_group);

		unsigned ealg = ike_info->ike_encrypt->common.ikev1_oakley_id;
		unsigned halg = ike_info->ike_prf->common.ikev1_oakley_id;
		unsigned modp = ike_info->ike_dh_group->group;
		unsigned eklen = ike_info->ike_eklen;

		DBG(DBG_CONTROL,
		    DBG_log("oakley_alg_makedb() processing ealg=%s=%u halg=%s=%u modp=%s=%u eklen=%u",
			    ike_info->ike_encrypt->common.name, ealg,
			    ike_info->ike_prf->common.name, halg,
			    ike_info->ike_dh_group->common.name, modp,
			    eklen));

		const struct encrypt_desc *enc_desc = ike_info->ike_encrypt;
		if (eklen != 0 && !encrypt_has_key_bit_length(enc_desc, eklen)) {
			PEXPECT_LOG("IKEv1 proposal with ENCRYPT%s (specified) keylen:%d, not valid, should have been dropped",
				    enc_desc->common.name,
				    eklen);
			continue;
		}

		/*
		 * copy the template
		 */
		emp_sp = sa_copy_sa(&oakley_empty);
		passert(emp_sp->dynamic);
		passert(emp_sp->prop_conj_cnt == 1);
		passert(emp_sp->prop_conjs[0].prop_cnt == 1);
		passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);
		struct db_trans *trans = &emp_sp->prop_conjs[0].props[0].trans[0];
		passert(trans->attr_cnt == 5);

		/*
		 * See "struct db_attr otempty" above, and spdb.c, for
		 * where these magic values come from.
		 */
		struct db_attr *enc  = &trans->attrs[0];
		struct db_attr *hash = &trans->attrs[1];
		struct db_attr *auth = &trans->attrs[2];
		struct db_attr *grp  = &trans->attrs[3];

		/*
		 * auth type for IKE must be set.
		 */
		passert(auth->type.oakley == OAKLEY_AUTHENTICATION_METHOD);
		auth->val = auth_method;

		if (eklen > 0) {
			struct db_attr *enc_keylen = &trans->attrs[4];

			passert(trans->attr_cnt == 5);
			passert(enc_keylen->type.oakley == OAKLEY_KEY_LENGTH);
			enc_keylen->val = eklen;
		} else {
			/* truncate */
			trans->attr_cnt = 4;
		}

		passert(enc->type.oakley == OAKLEY_ENCRYPTION_ALGORITHM);
		if (ealg > 0)
			enc->val = ealg;

		/*
		 * Either pass a hash algorithm or a PRF.
		 *
		 * Since AEAD algorithms don't need the hash,
		 * but do need a PRF, the hash field can be
		 * re-purposed as a PRF field.
		 *
		 * [cagney] While I suspect that type will
		 * never initially be OAKLEY_PRF (it is
		 * initialized using "struct db_attr otempty")
		 * it doesn't hurt to be safe.
		 */
		passert(hash->type.oakley == OAKLEY_HASH_ALGORITHM ||
			hash->type.oakley == OAKLEY_PRF);
		if (halg > 0) {
			hash->val = halg;
			if (ike_alg_enc_requires_integ(enc_desc)) {
				hash->type.oakley = OAKLEY_HASH_ALGORITHM;
			} else {
				hash->type.oakley = OAKLEY_PRF;
			}
		}

		passert(grp->type.oakley == OAKLEY_GROUP_DESCRIPTION);
		if (modp > 0)
			grp->val = modp;

		/*
		 * Aggressive mode really only works with a single DH group.
		 * If this is for Aggressive Mode, and we've previously seen
		 * a different DH group, we try to deal with this.
		 */
		if (single_dh && transcnt > 0 &&
		    ike_info->ike_dh_group->group != last_modp) {
			if (last_modp == OAKLEY_GROUP_MODP1024 ||
			    last_modp == OAKLEY_GROUP_MODP1536) {
				/*
				 * The previous group will work on old Cisco gear,
				 * so we can discard this one.
				 */

				if (!warned_dropped_dhgr) {
					/* complain only once */
					loglog(RC_LOG_SERIOUS,
						"multiple DH groups were set in aggressive mode. Only first one used.");
				}

				loglog(RC_LOG_SERIOUS,
				       "transform (%s,%s,%s keylen %ld) ignored.",
				       enum_name(&oakley_enc_names,
						 ike_info->ike_encrypt->common.ikev1_oakley_id),
				       enum_name(&oakley_hash_names,
						 ike_info->ike_prf->common.ikev1_oakley_id),
				       ike_info->ike_dh_group->common.name,
				       (long)ike_info->ike_eklen);
				free_sa(&emp_sp);
			} else {
				/*
				 * The previous group won't work on old Cisco gear,
				 * so we discard the previous ones.
				 * Of course this modp might be just as bad;
				 * we won't look until the next one comes along.
				 *
				 * Lemma: there will be only a single previous
				 * one in gsp (any others were discarded).
				 */
				loglog(RC_LOG_SERIOUS,
				       "multiple DH groups in aggressive mode can cause interop failure");
				loglog(RC_LOG_SERIOUS,
					"Deleting previous proposal in the hopes of selecting DH 2 or DH 5");

				free_sa(&gsp);
			}

			warned_dropped_dhgr = TRUE;
		}

		 if (emp_sp != NULL) {

			 /*
			  * Exclude 3des et.al. which do not include
			  * default key lengths in the proposal.
			  */
			 if (ike_info->ike_eklen == 0
			     && !ike_info->ike_encrypt->keylen_omitted) {

				const struct encrypt_desc *enc_desc = ike_info->ike_encrypt;
				int def_ks = enc_desc->keydeflen;
				passert(def_ks); /* ike=null not supported */
				int max_ks = encrypt_max_key_bit_length(enc_desc);
				int ks;

				passert(emp_sp->dynamic);
				passert(emp_sp->prop_conj_cnt == 1);
				passert(emp_sp->prop_conjs[0].prop_cnt == 1);
				passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);

				if (emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 4) {
					/* add a key length attribute of 0 */
					struct db_trans *tr = &emp_sp->prop_conjs[0].props[0].trans[0];
					const int n = tr->attr_cnt;	/* 4, actually */
					struct db_attr *old_attrs = tr->attrs;
					struct db_attr *new_attrs = alloc_bytes(
						(n + 1) * sizeof(old_attrs[0]),
						"extended trans");

					passert(emp_sp->dynamic);
					passert(old_attrs[0].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[1].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[2].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[3].type.oakley != OAKLEY_KEY_LENGTH);
					memcpy(new_attrs, old_attrs, n * sizeof(old_attrs[0]));
					new_attrs[n].type.oakley = OAKLEY_KEY_LENGTH;
					new_attrs[n].val = 0;

					pfree(old_attrs);
					tr->attrs = new_attrs;
					tr->attr_cnt++;
				}
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 5);
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].type.oakley == OAKLEY_KEY_LENGTH);

				/*
				 * This odd FOR loop executes its body for
				 * exactly two values of ks (max_ks and def_ks)
				 * unless def_ks == max_ks, in which case it is
				 * executed once.
				 */
				for (ks = max_ks; ; ks = def_ks) {
					emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].val = ks;

					if (gsp == NULL) {
						gsp = sa_copy_sa(emp_sp);
					} else {
						struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

						free_sa(&gsp);
						gsp = new;
					}
					if (ks == def_ks)
						break;
				}
				free_sa(&emp_sp);
			} else {
				if (gsp != NULL) {
					/* now merge emp_sa and gsp */
					struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

					free_sa(&gsp);
					free_sa(&emp_sp);
					gsp = new;
				} else {
					gsp = emp_sp;
					emp_sp = NULL;
				}
			}
			last_modp = ike_info->ike_dh_group->group;
		}
Exemplo n.º 5
0
/*
 * Create an OAKLEY proposal based on alg_info and policy
 *
 * single_dh is for Aggressive Mode where we must have exactly
 * one DH group.
 */
struct db_sa *oakley_alg_makedb(struct alg_info_ike *ai,
				struct db_sa *base,
				bool single_dh)
{
	struct db_sa *gsp = NULL;
	struct ike_info *ike_info;

	/* Next two are for multiple proposals in agressive mode... */
	unsigned last_modp = 0;
	bool warned_dropped_dhgr = FALSE;

	int transcnt = 0;
	int i;

	/*
	 * start by copying the proposal that would have been picked by
	 * standard defaults.
	 */

	if (ai == NULL) {
		DBG(DBG_CONTROL, DBG_log(
			    "no specific IKE algorithms specified - using defaults"));
		return NULL;
	}

	/*
	 * for each group, we will create a new proposal item, and then
	 * append it to the list of transforms in the conjoint point.
	 *
	 * when creating each item, we will use the first transform
	 * from the base item as the template.
	 */
	ALG_INFO_IKE_FOREACH(ai, ike_info, i) {
		struct db_sa *emp_sp;

		unsigned ealg = ike_info->ike_ealg;
		unsigned halg = ike_info->ike_halg;
		unsigned modp = ike_info->ike_modp;
		unsigned eklen = ike_info->ike_eklen;

		DBG(DBG_CONTROL,
		    DBG_log("oakley_alg_makedb() "
			    "processing ealg=%u halg=%u modp=%u eklen=%u",
			    ealg, halg, modp, eklen));

		const struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ealg);

		if (enc_desc == NULL) {
			DBG_log("oakley_alg_makedb() "
				"ike enc ealg=%d not present",
				ealg);
			continue;
		}
		passert(enc_desc != NULL);

		if (ike_alg_enc_requires_integ(enc_desc)) {
			if (!ike_alg_hash_present(halg)) {
				DBG_log("oakley_alg_makedb() "
					"ike hash halg=%d not present but required for integrity",
					halg);
				continue;
			}
		} else {
			if (!ike_alg_hash_present(halg)) {
				DBG_log("oakley_alg_makedb() "
					"ike PRF=%d not present but needed for AEAD",
					halg);
				continue;
			}
		}

		if (eklen != 0 &&
		    (eklen < enc_desc->keyminlen ||
		     eklen > enc_desc->keymaxlen)) {
			DBG_log("ike_alg_db_new() ealg=%d (specified) keylen:%d, not valid min=%d, max=%d",
				ealg,
				eklen,
				enc_desc->keyminlen,
				enc_desc->keymaxlen);
			continue;
		}

		/*
		 * copy the basic item, and modify it.
		 *
		 * ??? what are these two cases and why does
		 * eklen select between them?
		 *
		 * [cagney] I suspect that this is to
		 * compensate for logic further down that,
		 * when eklen==0, truncates the attrs array to
		 * 4 elements and sa_copy_sa_first() when
		 * applied to that structure won't allocate
		 * space for the 5th (eklen) element - oops.
		 * To be honest, the attrs should be a list OR
		 * the eklen>0 path should always be taken OR
		 * ...
		 *
		 * The convoluted assignment is copying the
		 * auth field (see "struct db_attr otempty"
		 * above), from base to the new proposal.
		 */
		if (eklen > 0) {
			/* duplicate, but change auth to match template */
			emp_sp = sa_copy_sa(&oakley_empty);
			emp_sp->prop_conjs[0].props[0].trans[0].attrs[2] =
				base->prop_conjs[0].props[0].trans[0].attrs[2];
		} else {
			emp_sp = sa_copy_sa_first(base);
		}

		passert(emp_sp->dynamic);
		passert(emp_sp->prop_conj_cnt == 1);
		passert(emp_sp->prop_conjs[0].prop_cnt == 1);
		passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);

		struct db_trans *trans = &emp_sp->prop_conjs[0].props[0].trans[0];

		/*
		 * See "struct db_attr otempty" above for
		 * where these magic values come from.
		 */
		passert(trans->attr_cnt == 4 || trans->attr_cnt == 5);
		struct db_attr *enc  = &trans->attrs[0];
		struct db_attr *hash = &trans->attrs[1];
		struct db_attr *auth = &trans->attrs[2];
		struct db_attr *grp  = &trans->attrs[3];

		if (eklen > 0) {
			struct db_attr *enc_keylen = &trans->attrs[4];

			passert(trans->attr_cnt == 5);
			passert(enc_keylen->type.oakley == OAKLEY_KEY_LENGTH);
			enc_keylen->val = eklen;
		} else {
			/* truncate */
			trans->attr_cnt = 4;
		}

		passert(enc->type.oakley == OAKLEY_ENCRYPTION_ALGORITHM);
		if (ealg > 0)
			enc->val = ealg;

		/*
		 * Either pass a hash algorithm or a PRF.
		 *
		 * Since AEAD algorithms don't need the hash,
		 * but do need a PRF, the hash field can be
		 * re-purposed as a PRF field.
		 *
		 * [cagney] While I suspect that type will
		 * never initially be OAKLEY_PRF (it is
		 * initialized using "struct db_attr otempty")
		 * it doesn't hurt to be safe.
		 */
		passert(hash->type.oakley == OAKLEY_HASH_ALGORITHM ||
			hash->type.oakley == OAKLEY_PRF);
		if (halg > 0) {
			hash->val = halg;
			if (ike_alg_enc_requires_integ(enc_desc)) {
				hash->type.oakley = OAKLEY_HASH_ALGORITHM;
			} else {
				hash->type.oakley = OAKLEY_PRF;
			}
		}

		/*
		 * auth type for IKE must be set.
		 *
		 * Logic above uses sa_copy_sa or brute force
		 * to copy the field from BASE.
		 *
		 * ??? until we support AES-GCM in IKE
		 *
		 * [cagney] aes-gcm doesn't require HASH, just
		 * the PRF, so auth is unrelated?
		 */
		passert(auth->type.oakley ==
			OAKLEY_AUTHENTICATION_METHOD);

		passert(grp->type.oakley == OAKLEY_GROUP_DESCRIPTION);
		if (modp > 0)
			grp->val = modp;

		/*
		 * Aggressive mode really only works with a single DH group.
		 * If this is for Aggressive Mode, and we've previously seen
		 * a different DH group, we try to deal with this.
		 */
		if (single_dh && transcnt > 0 &&
		    ike_info->ike_modp != last_modp) {
			if (last_modp == OAKLEY_GROUP_MODP1024 ||
			    last_modp == OAKLEY_GROUP_MODP1536) {
				/*
				 * The previous group will work on old Cisco gear,
				 * so we can discard this one.
				 */

				if (!warned_dropped_dhgr) {
					/* complain only once */
					loglog(RC_LOG_SERIOUS,
						"multiple DH groups were set in aggressive mode. Only first one used.");
				}

				loglog(RC_LOG_SERIOUS,
					"transform (%s,%s,%s keylen %ld) ignored.",
					enum_name(&oakley_enc_names, ike_info->ike_ealg),
					enum_name(&oakley_hash_names, ike_info->ike_halg),
					enum_name(&oakley_group_names, ike_info->ike_modp),
					(long)ike_info->ike_eklen);
				free_sa(&emp_sp);
			} else {
				/*
				 * The previous group won't work on old Cisco gear,
				 * so we discard the previous ones.
				 * Of course this modp might be just as bad;
				 * we won't look until the next one comes along.
				 *
				 * Lemma: there will be only a single previous
				 * one in gsp (any others were discarded).
				 */
				loglog(RC_LOG_SERIOUS,
				       "multiple DH groups in aggressive mode can cause interop failure");
				loglog(RC_LOG_SERIOUS,
					"Deleting previous proposal in the hopes of selecting DH 2 or DH 5");

				free_sa(&gsp);
			}

			warned_dropped_dhgr = TRUE;
		}

		 if (emp_sp != NULL) {
			int def_ks = 0;

			if (ike_info->ike_eklen == 0)
				def_ks = crypto_req_keysize(CRK_IKEv1, ike_info->ike_ealg);

			if (def_ks != 0) {
				const struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ike_info->ike_ealg);
				int max_ks = enc_desc->keymaxlen;
				int ks;

				passert(emp_sp->dynamic);
				passert(emp_sp->prop_conj_cnt == 1);
				passert(emp_sp->prop_conjs[0].prop_cnt == 1);
				passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);

				if (emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 4) {
					/* add a key length attribute of 0 */
					struct db_trans *tr = &emp_sp->prop_conjs[0].props[0].trans[0];
					const int n = tr->attr_cnt;	/* 4, actually */
					struct db_attr *old_attrs = tr->attrs;
					struct db_attr *new_attrs = alloc_bytes(
						(n + 1) * sizeof(old_attrs[0]),
						"extended trans");

					passert(emp_sp->dynamic);
					passert(old_attrs[0].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[1].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[2].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[3].type.oakley != OAKLEY_KEY_LENGTH);
					memcpy(new_attrs, old_attrs, n * sizeof(old_attrs[0]));
					new_attrs[n].type.oakley = OAKLEY_KEY_LENGTH;
					new_attrs[n].val = 0;

					pfree(old_attrs);
					tr->attrs = new_attrs;
					tr->attr_cnt++;
				}
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 5);
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].type.oakley == OAKLEY_KEY_LENGTH);

				/*
				 * This odd FOR loop executes its body for
				 * exactly two values of ks (def_ks and max_ks)
				 * unless def_ks == max_ks, in which case it is
				 * executed once.
				 */
				for (ks = def_ks; ; ks = max_ks) {
					emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].val = ks;

					if (gsp == NULL) {
						gsp = sa_copy_sa(emp_sp);
					} else {
						struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

						free_sa(&gsp);
						gsp = new;
					}
					if (ks == max_ks)
						break;
				}
				free_sa(&emp_sp);
			} else {
				if (gsp != NULL) {
					/* now merge emp_sa and gsp */
					struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

					free_sa(&gsp);
					free_sa(&emp_sp);
					gsp = new;
				} else {
					gsp = emp_sp;
					emp_sp = NULL;
				}
			}