示例#1
0
/**
 * create a signed pkcs7 contentInfo object
 */
chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
							   certificate_t *cert, int digest_alg,
							   private_key_t *key)
{
	contentInfo_t pkcs7Data, signedData;
	chunk_t authenticatedAttributes = chunk_empty;
	chunk_t encryptedDigest = chunk_empty;
	chunk_t signerInfo, cInfo, signature, encoding = chunk_empty;;
	signature_scheme_t scheme = signature_scheme_from_oid(digest_alg);

	if (attributes.ptr)
	{
		if (key->sign(key, scheme, attributes, &signature))
		{
			encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
			authenticatedAttributes = chunk_clone(attributes);
			*authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
		}
	}
	else if (data.ptr)
	{
		if (key->sign(key, scheme, data, &signature))
		{
			encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
		}
	}
	signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm"
				, ASN1_INTEGER_1
				, pkcs7_build_issuerAndSerialNumber(cert)
				, asn1_algorithmIdentifier(digest_alg)
				, authenticatedAttributes
				, asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
				, encryptedDigest);

	pkcs7Data.type    = OID_PKCS7_DATA;
	pkcs7Data.content = (data.ptr == NULL)? chunk_empty
				: asn1_simple_object(ASN1_OCTET_STRING, data);

	cert->get_encoding(cert, CERT_ASN1_DER, &encoding);
	signedData.type = OID_PKCS7_SIGNED_DATA;
	signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
				, ASN1_INTEGER_1
				, asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg))
				, pkcs7_build_contentInfo(&pkcs7Data)
				, asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding)
				, asn1_wrap(ASN1_SET, "m", signerInfo));

	cInfo = pkcs7_build_contentInfo(&signedData);
	DBG3(DBG_LIB, "signedData %B", &cInfo);

	free(pkcs7Data.content.ptr);
	free(signedData.content.ptr);
	return cInfo;
}
示例#2
0
/**
 * Generate a transaction id as the MD5 hash of an public key
 * the transaction id is also used as a unique serial number
 */
void scep_generate_transaction_id(public_key_t *key, chunk_t *transID,
								  chunk_t *serialNumber)
{
	chunk_t digest = chunk_alloca(HASH_SIZE_MD5);
	chunk_t keyEncoding = chunk_empty, keyInfo;
	hasher_t *hasher;
	bool msb_set;
	u_char *pos;

	key->get_encoding(key, PUBKEY_ASN1_DER, &keyEncoding);

	keyInfo = asn1_wrap(ASN1_SEQUENCE, "mm",
						asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
						asn1_bitstring("m", keyEncoding));

	hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
	if (!hasher || !hasher->get_hash(hasher, keyInfo, digest.ptr))
	{
		memset(digest.ptr, 0, digest.len);
	}
	DESTROY_IF(hasher);
	free(keyInfo.ptr);

	/* is the most significant bit of the digest set? */
	msb_set = (*digest.ptr & 0x80) == 0x80;

	/* allocate space for the serialNumber */
	serialNumber->len = msb_set + digest.len;
	serialNumber->ptr = malloc(serialNumber->len);

	/* the serial number as the two's complement of the digest */
	pos = serialNumber->ptr;
	if (msb_set)
	{
		*pos++ = 0x00;
	}
	memcpy(pos, digest.ptr, digest.len);

	/* the transaction id is the serial number in hex format */
	*transID = chunk_to_hex(digest, NULL, TRUE);
}
示例#3
0
/**
 * create a symmetrically encrypted pkcs7 contentInfo object
 */
chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg)
{
	encryption_algorithm_t alg;
	size_t alg_key_size;
	chunk_t symmetricKey, protectedKey, iv, in, out;
	crypter_t *crypter;

	alg = encryption_algorithm_from_oid(enc_alg, &alg_key_size);
	crypter = lib->crypto->create_crypter(lib->crypto, alg,
										  alg_key_size/BITS_PER_BYTE);
	if (crypter == NULL)
	{
		DBG1(DBG_LIB, "crypter for %N not available", encryption_algorithm_names, alg);
		return chunk_empty;
	}

	/* generate a true random symmetric encryption key and a pseudo-random iv */
	{
		rng_t *rng;

		rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
		rng->allocate_bytes(rng, crypter->get_key_size(crypter), &symmetricKey);
		DBG4(DBG_LIB, "symmetric encryption key %B", &symmetricKey);
		rng->destroy(rng);

		rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
		rng->allocate_bytes(rng, crypter->get_iv_size(crypter), &iv);
		DBG4(DBG_LIB, "initialization vector: %B", &iv);
		rng->destroy(rng);
	}

	/* pad the data to a multiple of the block size */
	{
		size_t block_size = crypter->get_block_size(crypter);
		size_t padding = block_size - data.len % block_size;

		in.len = data.len + padding;
		in.ptr = malloc(in.len);

		DBG2(DBG_LIB, "padding %u bytes of data to multiple block size of %u bytes",
			 data.len, in.len);

		/* copy data */
		memcpy(in.ptr, data.ptr, data.len);
		/* append padding */
		memset(in.ptr + data.len, padding, padding);
	}
	DBG3(DBG_LIB, "padded unencrypted data %B", &in);

	/* symmetric encryption of data object */
	crypter->set_key(crypter, symmetricKey);
	crypter->encrypt(crypter, in, iv, &out);
	crypter->destroy(crypter);
	chunk_clear(&in);
    DBG3(DBG_LIB, "encrypted data %B", &out);

	/* protect symmetric key by public key encryption */
	{
		public_key_t *key = cert->get_public_key(cert);

		if (key == NULL)
		{
			DBG1(DBG_LIB, "public key not found in encryption certificate");
			chunk_clear(&symmetricKey);
			chunk_free(&iv);
			chunk_free(&out);
			return chunk_empty;
		}
		key->encrypt(key, ENCRYPT_RSA_PKCS1, symmetricKey, &protectedKey);
		key->destroy(key);
	}

	/* build pkcs7 enveloped data object */
	{

		chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm"
					, asn1_build_known_oid(enc_alg)
					, asn1_simple_object(ASN1_OCTET_STRING, iv));

		chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm"
					, asn1_build_known_oid(OID_PKCS7_DATA)
					, contentEncryptionAlgorithm
					, asn1_wrap(ASN1_CONTEXT_S_0, "m", out));

		chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m"
					, protectedKey);

		chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm"
					, ASN1_INTEGER_0
					, pkcs7_build_issuerAndSerialNumber(cert)
					, asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
					, encryptedKey);

		chunk_t cInfo;
		contentInfo_t envelopedData;

		envelopedData.type = OID_PKCS7_ENVELOPED_DATA;
		envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm"
					, ASN1_INTEGER_0
					, asn1_wrap(ASN1_SET, "m", recipientInfo)
					, encryptedContentInfo);

		cInfo = pkcs7_build_contentInfo(&envelopedData);
		DBG3(DBG_LIB, "envelopedData %B", &cInfo);

		chunk_free(&envelopedData.content);
		chunk_free(&iv);
		chunk_clear(&symmetricKey);
		return cInfo;
	}
}