Esempio n. 1
0
/**
 * Parse X.501 attributes
 */
bool parse_attributes(chunk_t blob, scep_attributes_t *attrs)
{
	asn1_parser_t *parser;
	chunk_t object;
	int oid = OID_UNKNOWN;
	int objectID;
	bool success = FALSE;

	parser = asn1_parser_create(attributesObjects, blob);
	DBG(DBG_CONTROL | DBG_PARSING,
		DBG_log("parsing attributes")
	)

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
		case ATTRIBUTE_OBJ_TYPE:
			oid = asn1_known_oid(object);
			break;
		case ATTRIBUTE_OBJ_VALUE:
			if (!extract_attribute(oid, object, parser->get_level(parser), attrs))
			{
				goto end;
			}
		}
	}
	success = parser->success(parser);

end:
	parser->destroy(parser);
	return success;
}
Esempio n. 2
0
/**
 * Load a RSA public key from an ASN.1 encoded blob.
 */
static public_key_t *parse_rsa_public_key(chunk_t blob)
{
	chunk_t n, e;
	asn1_parser_t *parser;
	chunk_t object;
	int objectID;
	bool success = FALSE;

	parser = asn1_parser_create(pubkeyObjects, blob);

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
			case PUB_KEY_MODULUS:
				n = object;
				break;
			case PUB_KEY_EXPONENT:
				e = object;
				break;
		}
	}
	success = parser->success(parser);
	parser->destroy(parser);

	if (!success)
	{
		return NULL;
	}
	return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
						BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
}
Esempio n. 3
0
/**
 * Parse PKCS#7 ContentInfo object
 */
bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo)
{
	asn1_parser_t *parser;
	chunk_t object;
	int objectID;
	bool success = FALSE;

	parser = asn1_parser_create(contentInfoObjects, blob);
	parser->set_top_level(parser, level0);

	while (parser->iterate(parser, &objectID, &object))
	{
		if (objectID == PKCS7_INFO_TYPE)
		{
			cInfo->type = asn1_known_oid(object);
			if (cInfo->type < OID_PKCS7_DATA
			||  cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
			{
				DBG1(DBG_LIB, "unknown pkcs7 content type");
				goto end;
			}
		}
		else if (objectID == PKCS7_INFO_CONTENT)
		{
			cInfo->content = object;
		}
	}
	success = parser->success(parser);

end:
	parser->destroy(parser);
	return success;
}
Esempio n. 4
0
/**
 * Load a generic private key from an ASN.1 encoded blob
 */
static private_key_t *parse_private_key(chunk_t blob)
{
	asn1_parser_t *parser;
	chunk_t object, params = chunk_empty;
	int objectID;
	private_key_t *key = NULL;
	key_type_t type = KEY_ANY;

	parser = asn1_parser_create(pkinfoObjects, blob);
	parser->set_flags(parser, FALSE, TRUE);

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
			case PKINFO_PRIVATE_KEY_ALGORITHM:
			{
				int oid = asn1_parse_algorithmIdentifier(object,
									parser->get_level(parser) + 1, &params);

				switch (oid)
				{
					case OID_RSA_ENCRYPTION:
						type = KEY_RSA;
						break;
					case OID_EC_PUBLICKEY:
						type = KEY_ECDSA;
						break;
					default:
						/* key type not supported */
						goto end;
				}
				break;
			}
			case PKINFO_PRIVATE_KEY:
			{
				DBG2(DBG_ASN, "-- > --");
				if (params.ptr)
				{
					key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
											 type, BUILD_BLOB_ALGID_PARAMS,
											 params, BUILD_BLOB_ASN1_DER,
											 object, BUILD_END);
				}
				else
				{
					key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
											 type, BUILD_BLOB_ASN1_DER, object,
											 BUILD_END);
				}
				DBG2(DBG_ASN, "-- < --");
				break;
			}
		}
	}

end:
	parser->destroy(parser);
	return key;
}
Esempio n. 5
0
/**
 * Load a generic public key from an ASN.1 encoded blob
 */
static public_key_t *parse_public_key(chunk_t blob)
{
	asn1_parser_t *parser;
	chunk_t object;
	int objectID;
	public_key_t *key = NULL;
	key_type_t type = KEY_ANY;

	parser = asn1_parser_create(pkinfoObjects, blob);

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
			case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
			{
				int oid = asn1_parse_algorithmIdentifier(object,
										parser->get_level(parser)+1, NULL);

				if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP)
				{
					type = KEY_RSA;
				}
				else if (oid == OID_EC_PUBLICKEY)
				{
					/* we need the whole subjectPublicKeyInfo for EC public keys */
					key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
								KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
					goto end;
				}
				else
				{
					/* key type not supported */
					goto end;
				}
				break;
			}
			case PKINFO_SUBJECT_PUBLIC_KEY:
				if (object.len > 0 && *object.ptr == 0x00)
				{
					/* skip initial bit string octet defining 0 unused bits */
					object = chunk_skip(object, 1);
				}
				DBG2(DBG_ASN, "-- > --");
				key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
										 BUILD_BLOB_ASN1_DER, object, BUILD_END);
				DBG2(DBG_ASN, "-- < --");
				break;
		}
	}

end:
	parser->destroy(parser);
	return key;
}
Esempio n. 6
0
static void run_parser_test(const asn1Object_t *objects, int id,
							asn1_test_t *test)
{
	asn1_parser_t *parser;
	chunk_t object;
	int objectID, count = 0;
	bool success;

	parser = asn1_parser_create(objects, test->blob);
	while (parser->iterate(parser, &objectID, &object))
	{
		if (objectID == id)
		{
			count++;
		}
	}
	success = parser->success(parser);
	parser->destroy(parser);

	ck_assert(success == test->success && count == test->count);
}
Esempio n. 7
0
/**
 * Load an encrypted private key from an ASN.1 encoded blob
 * Schemes per PKCS#5 (RFC 2898)
 */
static private_key_t *parse_encrypted_private_key(chunk_t blob)
{
	asn1_parser_t *parser;
	chunk_t object;
	int objectID;
	private_key_t *key = NULL;
	pkcs5_t *pkcs5 = NULL;

	parser = asn1_parser_create(encryptedPKIObjects, blob);

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
			case EPKINFO_ENCRYPTION_ALGORITHM:
			{
				pkcs5 = pkcs5_from_algorithmIdentifier(object,
												parser->get_level(parser) + 1);
				if (!pkcs5)
				{
					goto end;
				}
				break;
			}
			case EPKINFO_ENCRYPTED_DATA:
			{
				key = decrypt_private_key(pkcs5, object);
				break;
			}
		}
	}

end:
	DESTROY_IF(pkcs5);
	parser->destroy(parser);
	return key;
}
Esempio n. 8
0
/**
 * Load a RSA private key from a ASN1 encoded blob.
 */
static private_key_t *parse_rsa_private_key(chunk_t blob)
{
	chunk_t n, e, d, p, q, exp1, exp2, coeff;
	asn1_parser_t *parser;
	chunk_t object;
	int objectID ;
	bool success = FALSE;

	parser = asn1_parser_create(privkeyObjects, blob);
	parser->set_flags(parser, FALSE, TRUE);

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
			case PRIV_KEY_VERSION:
				if (object.len > 0 && *object.ptr != 0)
				{
					DBG1(DBG_ASN, "PKCS#1 private key format is not version 1");
					goto end;
				}
				break;
			case PRIV_KEY_MODULUS:
				n = object;
				break;
			case PRIV_KEY_PUB_EXP:
				e = object;
				break;
			case PRIV_KEY_PRIV_EXP:
				d = object;
				break;
			case PRIV_KEY_PRIME1:
				p = object;
				break;
			case PRIV_KEY_PRIME2:
				q = object;
				break;
			case PRIV_KEY_EXP1:
				exp1 = object;
				break;
			case PRIV_KEY_EXP2:
				exp2 = object;
				break;
			case PRIV_KEY_COEFF:
				coeff = object;
				break;
		}
	}
	success = parser->success(parser);

end:
	parser->destroy(parser);
	if (!success)
	{
		return NULL;
	}
	return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
			BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_RSA_PRIV_EXP, d,
			BUILD_RSA_PRIME1, p,  BUILD_RSA_PRIME2, q, BUILD_RSA_EXP1, exp1,
			BUILD_RSA_EXP2, exp2, BUILD_RSA_COEFF, coeff, BUILD_END);
}
Esempio n. 9
0
/**
 * Load a generic private key from an ASN.1 encoded blob
 */
static private_key_t *parse_private_key(chunk_t blob)
{
	asn1_parser_t *parser;
	chunk_t object, params = chunk_empty;
	int objectID;
	private_key_t *key = NULL;
	key_type_t type = KEY_ANY;
	builder_part_t part = BUILD_BLOB_ASN1_DER;

	parser = asn1_parser_create(pkinfoObjects, blob);
	parser->set_flags(parser, FALSE, TRUE);

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
			case PKINFO_PRIVATE_KEY_ALGORITHM:
			{
				int oid = asn1_parse_algorithmIdentifier(object,
									parser->get_level(parser) + 1, &params);

				switch (oid)
				{
					case OID_RSASSA_PSS:
						/* TODO: parameters associated with such keys should be
						 * treated as restrictions later when signing (the type
						 * itself is already a restriction). However, the
						 * builders currently don't expect any parameters for
						 * RSA keys (we also only pass along the params, not the
						 * exact type, so we'd have to guess that params
						 * indicate RSA/PSS, but they are optional so that won't
						 * work for keys without specific restrictions) */
						params = chunk_empty;
						/* fall-through */
					case OID_RSA_ENCRYPTION:
						type = KEY_RSA;
						break;
					case OID_EC_PUBLICKEY:
						type = KEY_ECDSA;
						break;
					case OID_ED25519:
						type = KEY_ED25519;
						part = BUILD_EDDSA_PRIV_ASN1_DER;
						break;
					case OID_ED448:
						type = KEY_ED448;
						part = BUILD_EDDSA_PRIV_ASN1_DER;
						break;
					default:
						/* key type not supported */
						goto end;
				}
				break;
			}
			case PKINFO_PRIVATE_KEY:
			{
				DBG2(DBG_ASN, "-- > --");
				if (params.ptr)
				{
					key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
											 type, BUILD_BLOB_ALGID_PARAMS,
											 params, part, object, BUILD_END);
				}
				else
				{
					key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
											 type, part, object, BUILD_END);
				}
				DBG2(DBG_ASN, "-- < --");
				break;
			}
		}
	}

end:
	parser->destroy(parser);
	return key;
}
Esempio n. 10
0
/**
 * Parse a PKCS#7 envelopedData object
 */
bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
							   chunk_t serialNumber,
							   private_key_t *key)
{
	asn1_parser_t *parser;
	chunk_t object;
	chunk_t iv                = chunk_empty;
	chunk_t symmetric_key     = chunk_empty;
	chunk_t encrypted_content = chunk_empty;

	crypter_t *crypter = NULL;

	int enc_alg         = OID_UNKNOWN;
	int content_enc_alg = OID_UNKNOWN;
	int version;
	int objectID;
	bool success = FALSE;

	contentInfo_t cInfo = empty_contentInfo;
	*data = chunk_empty;

	if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
	{
		goto failed;
	}
	if (cInfo.type != OID_PKCS7_ENVELOPED_DATA)
	{
		DBG1(DBG_LIB, "pkcs7 content type is not envelopedData");
		goto failed;
	}

	parser = asn1_parser_create(envelopedDataObjects, cInfo.content);
	parser->set_top_level(parser, 2);

	while (parser->iterate(parser, &objectID, &object))
	{
		u_int level = parser->get_level(parser);

		switch (objectID)
		{
		case PKCS7_ENVELOPED_VERSION:
			version = object.len ? (int)*object.ptr : 0;
			DBG2(DBG_LIB, "  v%d", version);
			if (version != 0)
			{
				DBG1(DBG_LIB, "envelopedData version is not 0");
				goto end;
			}
			break;
		case PKCS7_RECIPIENT_INFO_VERSION:
			version = object.len ? (int)*object.ptr : 0;
			DBG2(DBG_LIB, "  v%d", version);
			if (version != 0)
			{
				DBG1(DBG_LIB, "recipient info version is not 0");
				goto end;
			}
			break;
		case PKCS7_ISSUER:
			{
				identification_t *issuer = identification_create_from_encoding(
													ID_DER_ASN1_DN, object);
				DBG2(DBG_LIB, "  \"%Y\"", issuer);
				issuer->destroy(issuer);
				break;
			}
		case PKCS7_SERIAL_NUMBER:
			if (!chunk_equals(serialNumber, object))
			{
				DBG1(DBG_LIB, "serial numbers do not match");
				goto end;
			}
			break;
		case PKCS7_ENCRYPTION_ALG:
			enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
			if (enc_alg != OID_RSA_ENCRYPTION)
			{
				DBG1(DBG_LIB, "only rsa encryption supported");
				goto end;
			}
			break;
		case PKCS7_ENCRYPTED_KEY:
			if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key))
			{
				DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa");
				goto end;
			}
			DBG4(DBG_LIB, "symmetric key %B", &symmetric_key);
			break;
		case PKCS7_CONTENT_TYPE:
			if (asn1_known_oid(object) != OID_PKCS7_DATA)
			{
				 DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
				 goto end;
			}
			break;
		case PKCS7_CONTENT_ENC_ALGORITHM:
			content_enc_alg = asn1_parse_algorithmIdentifier(object, level, &iv);

			if (content_enc_alg == OID_UNKNOWN)
			{
				DBG1(DBG_LIB, "unknown content encryption algorithm");
				goto end;
			}
			if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
			{
				DBG1(DBG_LIB, "IV could not be parsed");
				goto end;
			}
			break;
		case PKCS7_ENCRYPTED_CONTENT:
			encrypted_content = object;
			break;
		}
	}
	success = parser->success(parser);

end:
	parser->destroy(parser);
	if (!success)
	{
		goto failed;
	}
	success = FALSE;

	/* decrypt the content */
	{
		encryption_algorithm_t alg;
		size_t key_size;
		crypter_t *crypter;

		alg = encryption_algorithm_from_oid(content_enc_alg, &key_size);
		if (alg == ENCR_UNDEFINED)
		{
			DBG1(DBG_LIB, "unsupported content encryption algorithm");
			goto failed;
		}
		crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
		if (crypter == NULL)
		{
			DBG1(DBG_LIB, "crypter %N not available", encryption_algorithm_names, alg);
			goto failed;
		}
		if (symmetric_key.len != crypter->get_key_size(crypter))
		{
			DBG1(DBG_LIB, "symmetric key length %d is wrong", symmetric_key.len);
			goto failed;
		}
		if (iv.len != crypter->get_iv_size(crypter))
		{
			DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
			goto failed;
		}
		crypter->set_key(crypter, symmetric_key);
		crypter->decrypt(crypter, encrypted_content, iv, data);
		DBG4(DBG_LIB, "decrypted content with padding: %B", data);
	}

	/* remove the padding */
	{
		u_char *pos = data->ptr + data->len - 1;
		u_char pattern = *pos;
		size_t padding = pattern;

		if (padding > data->len)
		{
			DBG1(DBG_LIB, "padding greater than data length");
			goto failed;
		}
		data->len -= padding;

		while (padding-- > 0)
		{
			if (*pos-- != pattern)
			{
				DBG1(DBG_LIB, "wrong padding pattern");
				goto failed;
			}
		}
	}
	success = TRUE;

failed:
	DESTROY_IF(crypter);
	chunk_clear(&symmetric_key);
	if (!success)
	{
		free(data->ptr);
	}
	return success;
}
Esempio n. 11
0
/**
 * Parse a PKCS#7 signedData object
 */
bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
							linked_list_t *certs,
							chunk_t *attributes, certificate_t *cacert)
{
	asn1_parser_t *parser;
	chunk_t object;
	int digest_alg = OID_UNKNOWN;
	int enc_alg    = OID_UNKNOWN;
	int signerInfos = 0;
	int version;
	int objectID;
	bool success = FALSE;

	contentInfo_t cInfo = empty_contentInfo;
	chunk_t encrypted_digest = chunk_empty;

	if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
	{
		return FALSE;
	}
	if (cInfo.type != OID_PKCS7_SIGNED_DATA)
	{
		DBG1(DBG_LIB, "pkcs7 content type is not signedData");
		return FALSE;
	}

	parser = asn1_parser_create(signedDataObjects, cInfo.content);
	parser->set_top_level(parser, 2);

	while (parser->iterate(parser, &objectID, &object))
	{
		u_int level = parser->get_level(parser);

		switch (objectID)
		{
		case PKCS7_SIGNED_VERSION:
			version = object.len ? (int)*object.ptr : 0;
			DBG2(DBG_LIB, "  v%d", version);
			break;
		case PKCS7_DIGEST_ALG:
			digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
			break;
		case PKCS7_SIGNED_CONTENT_INFO:
			if (data != NULL)
			{
				pkcs7_parse_contentInfo(object, level, data);
			}
			break;
		case PKCS7_SIGNED_CERT:
			{
				certificate_t *cert;

				DBG2(DBG_LIB, "  parsing pkcs7-wrapped certificate");
				cert = lib->creds->create(lib->creds,
								  		  CRED_CERTIFICATE, CERT_X509,
								  		  BUILD_BLOB_ASN1_DER, object,
								  		  BUILD_END);
				if (cert)
				{
					certs->insert_last(certs, cert);
				}
			}
			break;
		case PKCS7_SIGNER_INFO:
			signerInfos++;
			DBG2(DBG_LIB, "  signer #%d", signerInfos);
			break;
		case PKCS7_SIGNER_INFO_VERSION:
			version = object.len ? (int)*object.ptr : 0;
			DBG2(DBG_LIB, "  v%d", version);
			break;
		case PKCS7_SIGNED_ISSUER:
			{
				identification_t *issuer = identification_create_from_encoding(
													ID_DER_ASN1_DN, object);
				DBG2(DBG_LIB, "  \"%Y\"", issuer);
				issuer->destroy(issuer);
				break;
			}
		case PKCS7_AUTH_ATTRIBUTES:
			if (attributes != NULL)
			{
				*attributes = object;
				*attributes->ptr = ASN1_SET;
			}
			break;
		case PKCS7_DIGEST_ALGORITHM:
			digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
			break;
		case PKCS7_DIGEST_ENC_ALGORITHM:
			enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
			break;
		case PKCS7_ENCRYPTED_DIGEST:
			encrypted_digest = object;
		}
	}
	success = parser->success(parser);
	parser->destroy(parser);
	if (!success)
	{
		return FALSE;
	}

	/* check the signature only if a cacert is available */
	if (cacert != NULL)
	{
		public_key_t *key;
		signature_scheme_t scheme;

		scheme = signature_scheme_from_oid(digest_alg);
		if (scheme == SIGN_UNKNOWN)
		{
			DBG1(DBG_LIB, "unsupported signature scheme");
			return FALSE;
		}
		if (signerInfos == 0)
		{
			DBG1(DBG_LIB, "no signerInfo object found");
			return FALSE;
		}
		else if (signerInfos > 1)
		{
			DBG1(DBG_LIB, "more than one signerInfo object found");
			return FALSE;
		}
		if (attributes->ptr == NULL)
		{
			DBG1(DBG_LIB, "no authenticatedAttributes object found");
			return FALSE;
		}
		if (enc_alg != OID_RSA_ENCRYPTION)
		{
			DBG1(DBG_LIB, "only RSA digest encryption supported");
			return FALSE;
		}

		/* verify the signature */
		key = cacert->get_public_key(cacert);
		if (key == NULL)
		{
			DBG1(DBG_LIB, "no public key found in CA certificate");
			return FALSE;
		}
		if (key->verify(key, scheme, *attributes, encrypted_digest))
		{
			DBG2(DBG_LIB, "signature is valid");
		}
		else
		{
			DBG1(DBG_LIB, "invalid signature");
			success = FALSE;
		}
		key->destroy(key);
	}
	return success;
}