Ejemplo n.º 1
0
END_TEST

/*******************************************************************************
 * known_oid
 */

START_TEST(test_asn1_known_oid)
{
	typedef struct {
		int n;
		chunk_t oid;
	} testdata_t;

	testdata_t test[] = {
		{ OID_UNKNOWN,    chunk_empty },
		{ OID_UNKNOWN,    chunk_from_chars(0x55, 0x04, 0x02) },
		{ OID_COUNTRY,    chunk_from_chars(0x55, 0x04, 0x06) },
		{ OID_STRONGSWAN, chunk_from_chars(0x2b, 0x06, 0x01, 0x04, 0x01,
										   0x82, 0xa0, 0x2a, 0x01) }
	};

	int i;

	for (i = 0; i < countof(test); i++)
	{
		ck_assert(asn1_known_oid(test[i].oid) == test[i].n);
	}
}
Ejemplo n.º 2
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;
}
Ejemplo 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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
/**
 * Encode the public key as Base64 encoded SSH key blob
 */
static bool build_public_key(chunk_t *encoding, va_list args)
{
	bio_writer_t *writer;
	chunk_t n, e;

	if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
						   CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
	{
		writer = bio_writer_create(0);
		writer->write_data32(writer, chunk_from_str("ssh-rsa"));

		writer->write_data32(writer, e);
		writer->write_data32(writer, n);
		*encoding = chunk_to_base64(writer->get_buf(writer), NULL);
		writer->destroy(writer);
		return TRUE;
	}
	else if (cred_encoding_args(args, CRED_PART_EDDSA_PUB_ASN1_DER, &n,
								CRED_PART_END))
	{
		chunk_t alg;
		char *prefix;
		int oid;

		/* parse subjectPublicKeyInfo */
		if (asn1_unwrap(&n, &n) != ASN1_SEQUENCE)
		{
			return FALSE;
		}
		oid = asn1_parse_algorithmIdentifier(n, 1, NULL);
		switch (oid)
		{
			case OID_ED25519:
				prefix = "ssh-ed25519";
				break;
			case OID_ED448:
				prefix = "ssh-ed448";
				break;
			default:
				return FALSE;
		}
		if (asn1_unwrap(&n, &alg) != ASN1_SEQUENCE ||
			asn1_unwrap(&n, &n) != ASN1_BIT_STRING || !n.len)
		{
			return FALSE;
		}
		writer = bio_writer_create(0);
		writer->write_data32(writer, chunk_from_str(prefix));
		writer->write_data32(writer, chunk_skip(n, 1));
		*encoding = chunk_to_base64(writer->get_buf(writer), NULL);
		writer->destroy(writer);
		return TRUE;
	}
	else if (cred_encoding_args(args, CRED_PART_ECDSA_PUB_ASN1_DER, &n,
								CRED_PART_END))
	{
		chunk_t params, alg, q;
		int oid;

		/* parse subjectPublicKeyInfo */
		if (asn1_unwrap(&n, &n) != ASN1_SEQUENCE)
		{
			return FALSE;
		}
		oid = asn1_parse_algorithmIdentifier(n, 1, &params);
		if (oid != OID_EC_PUBLICKEY ||
			asn1_unwrap(&params, &params) != ASN1_OID)
		{
			return FALSE;
		}
		oid = asn1_known_oid(params);
		if (oid == OID_UNKNOWN)
		{
			return FALSE;
		}
		if (asn1_unwrap(&n, &alg) != ASN1_SEQUENCE ||
			asn1_unwrap(&n, &q) != ASN1_BIT_STRING)
		{
			return FALSE;
		}
		writer = bio_writer_create(0);
		write_ec_identifier(writer, ECDSA_PREFIX, oid, params);
		write_ec_identifier(writer, "", oid, params);

		q = chunk_skip_zero(q);
		writer->write_data32(writer, q);
		*encoding = chunk_to_base64(writer->get_buf(writer), NULL);
		writer->destroy(writer);
		return TRUE;
	}
	return FALSE;
}