예제 #1
0
static struct sc_asn1_pkcs15_algorithm_info *
sc_asn1_get_algorithm_info(const struct sc_algorithm_id *id)
{
	struct sc_asn1_pkcs15_algorithm_info *aip = NULL;

	for (aip = algorithm_table; aip->id >= 0; aip++)   {
		if ((int) id->algorithm < 0 && sc_compare_oid(&id->oid, &aip->oid))
			return aip;

		if (aip->id == (int)id->algorithm)
			return aip;
	}

	return NULL;
}
예제 #2
0
파일: card.c 프로젝트: AktivCo/OpenSC
sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card,
		unsigned int algorithm, unsigned int key_length, void *param)
{
	int i;

	for (i = 0; i < card->algorithm_count; i++) {
		sc_algorithm_info_t *info = &card->algorithms[i];

		if (info->algorithm != algorithm)
			continue;
		if (info->key_length != key_length)
			continue;
		if (param)   {
			if (info->algorithm == SC_ALGORITHM_EC)
				if(!sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id))
					continue;
		}
		return info;
	}
	return NULL;
}
예제 #3
0
/* Get a specific extension from the cert.
 * The extension is identified by it's oid value.
 * NOTE: extensions can occur in any number or any order, which is why we
 *	can't parse them with a single pass of the asn1 decoder.
 * If is_critical is supplied, then it is set to 1 if the extention is critical
 * and 0 if it is not.
 * The data in the extension is extension specific.
 * The following are common extension values:
 *   Subject Key ID:		struct sc_object_id type = {{2, 5, 29, 14, -1}};
 *   Key Usage:			struct sc_object_id type = {{2, 5, 29, 15, -1}};
 *   Subject Alt Name:		struct sc_object_id type = {{2, 5, 29, 17, -1}};
 *   Basic Constraints:		struct sc_object_id type = {{2, 5, 29, 19, -1}};
 *   CRL Distribution Points:	struct sc_object_id type = {{2, 5, 29, 31, -1}};
 *   Certificate Policies:	struct sc_object_id type = {{2, 5, 29, 32, -1}};
 *   Extended Key Usage:	struct sc_object_id type = {{2, 5, 29, 37, -1}};
 *
 * if *ext_val is NULL, sc_pkcs15_get_extension will allocate space for ext_val.
 */
int
sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert,
	const struct sc_object_id *type, u8 **ext_val,
	size_t *ext_val_len, int *is_critical)
{
	const u8 *ext = NULL;
	const u8 *next_ext = NULL;
	size_t ext_len = 0;
	size_t next_ext_len = 0;
	struct sc_object_id oid;
	u8 *val = NULL;
	size_t val_len = 0;
	int critical;
	int r;
	struct sc_asn1_entry asn1_cert_ext[] = {
		{ "x509v3 entry OID", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, &oid, 0 },
		{ "criticalFlag",  SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, SC_ASN1_OPTIONAL, &critical, NULL },
		{ "extensionValue",SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, &val, &val_len },
		{ NULL, 0, 0, 0, NULL, NULL }
	};

	for (next_ext = cert->extensions, next_ext_len = cert->extensions_len; next_ext_len; ) {
		/* unwrap the set and point to the next ava */
		ext = sc_asn1_skip_tag(ctx, &next_ext, &next_ext_len,
			SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &ext_len);
		if (ext == NULL)
			LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA");

		/*
		 * use the sc_asn1_decoder for clarity. NOTE it would be more efficient to do this by hand
		 * so we avoid the man malloc/frees here, but one hopes that one day the asn1_decode will allow
		 * a 'static pointer' flag that returns a const pointer to the actual asn1 space so we only need
		 * to make a final copy of the extension value before we return */
		critical = 0;
		r = sc_asn1_decode(ctx, asn1_cert_ext, ext, ext_len, NULL, NULL);
		if (r < 0)
			LOG_FUNC_RETURN(ctx, r);

		/* is it the RN we are looking for */
		if (sc_compare_oid(&oid, type) != 0) {
			if (*ext_val == NULL) {
				*ext_val = val;
				val = NULL;
				*ext_val_len = val_len;
				/* do not free here -- return the allocated value to caller */
			}
			else {
				*ext_val_len = MIN(*ext_val_len, val_len);
				memcpy(*ext_val, val, *ext_val_len);
				free(val);
			}

			if (is_critical)
				*is_critical = critical;

			r = val_len;
			LOG_FUNC_RETURN(ctx, r);
		}
		if (val) {
			free(val);
			val = NULL;
		}
	}
	if (val)
	    free(val);

	LOG_FUNC_RETURN(ctx, SC_ERROR_ASN1_OBJECT_NOT_FOUND);
}
예제 #4
0
/* Get a component of Distinguished Name (e.i. subject or issuer) USING the oid tag.
 * dn can be either cert->subject or cert->issuer.
 * dn_len would be cert->subject_len or cert->issuer_len.
 *
 * Common types:
 *   CN:      struct sc_object_id type = {{2, 5, 4, 3, -1}};
 *   Country: struct sc_object_id type = {{2, 5, 4, 6, -1}};
 *   L:       struct sc_object_id type = {{2, 5, 4, 7, -1}};
 *   S:       struct sc_object_id type = {{2, 5, 4, 8, -1}};
 *   O:       struct sc_object_id type = {{2, 5, 4, 10, -1}};
 *   OU:      struct sc_object_id type = {{2, 5, 4, 11, -1}};
 *
 * if *name is NULL, sc_pkcs15_get_name_from_dn will allocate space for name.
 */
int
sc_pkcs15_get_name_from_dn(struct sc_context *ctx, const u8 *dn, size_t dn_len,
	const struct sc_object_id *type, u8 **name, size_t *name_len)
{
	const u8 *rdn = NULL;
	const u8 *next_ava = NULL;
	size_t rdn_len = 0;
	size_t next_ava_len = 0;
	int rv;

	rdn = sc_asn1_skip_tag(ctx, &dn, &dn_len, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &rdn_len);
	if (rdn == NULL)
		LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of Distiguished Name");

	for (next_ava = rdn, next_ava_len = rdn_len; next_ava_len; ) {
		const u8 *ava, *dummy, *oidp;
		struct sc_object_id oid;
		size_t ava_len, dummy_len, oid_len;

		/* unwrap the set and point to the next ava */
		ava = sc_asn1_skip_tag(ctx, &next_ava, &next_ava_len, SC_ASN1_TAG_SET | SC_ASN1_CONS, &ava_len);
		if (ava == NULL)
			LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA");

		/* It would be nice to use sc_asn1_decode here to parse the entire AVA, but we are missing 1 critical
		 *	function in the templates: the ability to accept any tag for value. This prevents us from just
		 *	grabbing the value as is out of the template. AVA's can have tags of PRINTABLE_STRING,
		 *	TELETEXSTRING, T61STRING or UTF8_STRING with PRINTABLE_STRING and UTF8_STRING being the most common.
		 * The other feature that would be nice is returning a pointer to our requested data using the space
		 *	of the parent (basically what this code is doing here), rather than allocating and copying.
		 */

		/* unwrap the sequence */
		dummy = ava; dummy_len = ava_len;
		ava = sc_asn1_skip_tag(ctx, &dummy, &dummy_len, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &ava_len);
		if (ava == NULL)
			LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA");

		/* unwrap the oid */
		oidp = sc_asn1_skip_tag(ctx, &ava, &ava_len, SC_ASN1_TAG_OBJECT, &oid_len);
		if (ava == NULL)
			LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA OID");

		/* Convert to OID */
		rv = sc_asn1_decode_object_id(oidp, oid_len, &oid);
		if (rv != SC_SUCCESS)
			LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA OID");

		if (sc_compare_oid(&oid, type) == 0)
			continue;

		/* Yes, then return the name */
		dummy = sc_asn1_skip_tag(ctx, &ava, &ava_len, ava[0] & SC_ASN1_TAG_PRIMITIVE, &dummy_len);
		if (*name == NULL) {
			*name = malloc(dummy_len);
			if (*name == NULL)
				LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
			*name_len = dummy_len;
		}

		*name_len = MIN(dummy_len, *name_len);
		memcpy(*name, dummy, *name_len);
		LOG_FUNC_RETURN(ctx, SC_SUCCESS);
	}

	LOG_FUNC_RETURN(ctx, SC_ERROR_ASN1_OBJECT_NOT_FOUND);
}
예제 #5
0
static int sc_obj_app_oid(struct sc_pkcs15_object *obj, const struct sc_object_id *app_oid)
{
	if (obj->type & SC_PKCS15_TYPE_DATA_OBJECT)
		return sc_compare_oid(&((struct sc_pkcs15_data_info *) obj->data)->app_oid, app_oid);
	return 0;
}