Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60d65cac authored by David Howells's avatar David Howells
Browse files

PKCS#7: Support CMS messages also [RFC5652]



Since CMS is an evolution of PKCS#7, with much of the ASN.1 being
compatible, add support for CMS signed-data messages also [RFC5652 sec 5].

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Reviewed-By: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent a4c6e57f
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ SignerInfos ::= CHOICE {

SignerInfo ::= SEQUENCE {
	version			INTEGER ({ pkcs7_note_signerinfo_version }),
	issuerAndSerialNumber	IssuerAndSerialNumber,
	sid			SignerIdentifier, -- CMS variant, not PKCS#7
	digestAlgorithm		DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }),
	authenticatedAttributes	CHOICE {
		aaSet		[0] IMPLICIT SetOfAuthenticatedAttribute
@@ -88,6 +88,12 @@ SignerInfo ::= SEQUENCE {
	} OPTIONAL
} ({ pkcs7_note_signed_info })

SignerIdentifier ::= CHOICE {
	-- RFC5652 sec 5.3
	issuerAndSerialNumber IssuerAndSerialNumber,
        subjectKeyIdentifier [0] IMPLICIT SubjectKeyIdentifier
}

IssuerAndSerialNumber ::= SEQUENCE {
	issuer			Name ({ pkcs7_sig_note_issuer }),
	serialNumber		CertificateSerialNumber ({ pkcs7_sig_note_serial })
@@ -95,6 +101,8 @@ IssuerAndSerialNumber ::= SEQUENCE {

CertificateSerialNumber ::= INTEGER

SubjectKeyIdentifier ::= OCTET STRING ({ pkcs7_sig_note_skid })

SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute

AuthenticatedAttribute ::= SEQUENCE {
+55 −7
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ struct pkcs7_parse_context {
	unsigned	raw_serial_size;
	unsigned	raw_issuer_size;
	const void	*raw_issuer;
	const void	*raw_skid;
	unsigned	raw_skid_size;
	bool		expect_skid;
};

/*
@@ -249,15 +252,21 @@ int pkcs7_note_signeddata_version(void *context, size_t hdrlen,
				  unsigned char tag,
				  const void *value, size_t vlen)
{
	struct pkcs7_parse_context *ctx = context;
	unsigned version;

	if (vlen != 1)
		goto unsupported;

	version = *(const u8 *)value;
	ctx->msg->version = version = *(const u8 *)value;
	switch (version) {
	case 1:
		/* PKCS#7 SignedData [RFC2315 sec 9.1] */
		/* PKCS#7 SignedData [RFC2315 sec 9.1]
		 * CMS ver 1 SignedData [RFC5652 sec 5.1]
		 */
		break;
	case 3:
		/* CMS ver 3 SignedData [RFC2315 sec 5.1] */
		break;
	default:
		goto unsupported;
@@ -277,6 +286,7 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
				  unsigned char tag,
				  const void *value, size_t vlen)
{
	struct pkcs7_parse_context *ctx = context;
	unsigned version;

	if (vlen != 1)
@@ -285,7 +295,18 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
	version = *(const u8 *)value;
	switch (version) {
	case 1:
		/* PKCS#7 SignerInfo [RFC2315 sec 9.2] */
		/* PKCS#7 SignerInfo [RFC2315 sec 9.2]
		 * CMS ver 1 SignerInfo [RFC5652 sec 5.3]
		 */
		if (ctx->msg->version != 1)
			goto version_mismatch;
		ctx->expect_skid = false;
		break;
	case 3:
		/* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */
		if (ctx->msg->version == 1)
			goto version_mismatch;
		ctx->expect_skid = true;
		break;
	default:
		goto unsupported;
@@ -296,6 +317,9 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
unsupported:
	pr_warn("Unsupported SignerInfo version\n");
	return -EINVAL;
version_mismatch:
	pr_warn("SignedData-SignerInfo version mismatch\n");
	return -EBADMSG;
}

/*
@@ -439,6 +463,22 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
	return 0;
}

/*
 * Note the issuing cert's subjectKeyIdentifier
 */
int pkcs7_sig_note_skid(void *context, size_t hdrlen,
			unsigned char tag,
			const void *value, size_t vlen)
{
	struct pkcs7_parse_context *ctx = context;

	pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);

	ctx->raw_skid = value;
	ctx->raw_skid_size = vlen;
	return 0;
}

/*
 * Note the signature data
 */
@@ -472,13 +512,21 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
	struct asymmetric_key_id *kid;

	/* Generate cert issuer + serial number key ID */
	if (!ctx->expect_skid) {
		kid = asymmetric_key_generate_id(ctx->raw_serial,
						 ctx->raw_serial_size,
						 ctx->raw_issuer,
						 ctx->raw_issuer_size);
	} else {
		kid = asymmetric_key_generate_id(ctx->raw_skid,
						 ctx->raw_skid_size,
						 "", 0);
	}
	if (IS_ERR(kid))
		return PTR_ERR(kid);

	pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);

	sinfo->signing_cert_id = kid;
	sinfo->index = ++ctx->sinfo_index;
	*ctx->ppsinfo = sinfo;
+4 −1
Original line number Diff line number Diff line
@@ -33,7 +33,9 @@ struct pkcs7_signed_info {
	unsigned	authattrs_len;
	const void	*authattrs;

	/* Issuing cert serial number and issuer's name */
	/* Issuing cert serial number and issuer's name [PKCS#7 or CMS ver 1]
	 * or issuing cert's SKID [CMS ver 3].
	 */
	struct asymmetric_key_id *signing_cert_id;

	/* Message signature.
@@ -50,6 +52,7 @@ struct pkcs7_message {
	struct x509_certificate *certs;	/* Certificate list */
	struct x509_certificate *crl;	/* Revocation list */
	struct pkcs7_signed_info *signed_infos;
	u8		version;	/* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */

	/* Content Data (or NULL) */
	enum OID	data_type;	/* Type of Data */