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

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
...@@ -69,7 +69,7 @@ SignerInfos ::= CHOICE { ...@@ -69,7 +69,7 @@ SignerInfos ::= CHOICE {
SignerInfo ::= SEQUENCE { SignerInfo ::= SEQUENCE {
version INTEGER ({ pkcs7_note_signerinfo_version }), version INTEGER ({ pkcs7_note_signerinfo_version }),
issuerAndSerialNumber IssuerAndSerialNumber, sid SignerIdentifier, -- CMS variant, not PKCS#7
digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }), digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }),
authenticatedAttributes CHOICE { authenticatedAttributes CHOICE {
aaSet [0] IMPLICIT SetOfAuthenticatedAttribute aaSet [0] IMPLICIT SetOfAuthenticatedAttribute
...@@ -88,6 +88,12 @@ SignerInfo ::= SEQUENCE { ...@@ -88,6 +88,12 @@ SignerInfo ::= SEQUENCE {
} OPTIONAL } OPTIONAL
} ({ pkcs7_note_signed_info }) } ({ pkcs7_note_signed_info })
SignerIdentifier ::= CHOICE {
-- RFC5652 sec 5.3
issuerAndSerialNumber IssuerAndSerialNumber,
subjectKeyIdentifier [0] IMPLICIT SubjectKeyIdentifier
}
IssuerAndSerialNumber ::= SEQUENCE { IssuerAndSerialNumber ::= SEQUENCE {
issuer Name ({ pkcs7_sig_note_issuer }), issuer Name ({ pkcs7_sig_note_issuer }),
serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial }) serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial })
...@@ -95,6 +101,8 @@ IssuerAndSerialNumber ::= SEQUENCE { ...@@ -95,6 +101,8 @@ IssuerAndSerialNumber ::= SEQUENCE {
CertificateSerialNumber ::= INTEGER CertificateSerialNumber ::= INTEGER
SubjectKeyIdentifier ::= OCTET STRING ({ pkcs7_sig_note_skid })
SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute
AuthenticatedAttribute ::= SEQUENCE { AuthenticatedAttribute ::= SEQUENCE {
......
...@@ -33,6 +33,9 @@ struct pkcs7_parse_context { ...@@ -33,6 +33,9 @@ struct pkcs7_parse_context {
unsigned raw_serial_size; unsigned raw_serial_size;
unsigned raw_issuer_size; unsigned raw_issuer_size;
const void *raw_issuer; 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, ...@@ -249,15 +252,21 @@ int pkcs7_note_signeddata_version(void *context, size_t hdrlen,
unsigned char tag, unsigned char tag,
const void *value, size_t vlen) const void *value, size_t vlen)
{ {
struct pkcs7_parse_context *ctx = context;
unsigned version; unsigned version;
if (vlen != 1) if (vlen != 1)
goto unsupported; goto unsupported;
version = *(const u8 *)value; ctx->msg->version = version = *(const u8 *)value;
switch (version) { switch (version) {
case 1: 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; break;
default: default:
goto unsupported; goto unsupported;
...@@ -277,6 +286,7 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, ...@@ -277,6 +286,7 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
unsigned char tag, unsigned char tag,
const void *value, size_t vlen) const void *value, size_t vlen)
{ {
struct pkcs7_parse_context *ctx = context;
unsigned version; unsigned version;
if (vlen != 1) if (vlen != 1)
...@@ -285,7 +295,18 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, ...@@ -285,7 +295,18 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
version = *(const u8 *)value; version = *(const u8 *)value;
switch (version) { switch (version) {
case 1: 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; break;
default: default:
goto unsupported; goto unsupported;
...@@ -296,6 +317,9 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen, ...@@ -296,6 +317,9 @@ int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
unsupported: unsupported:
pr_warn("Unsupported SignerInfo version\n"); pr_warn("Unsupported SignerInfo version\n");
return -EINVAL; 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, ...@@ -439,6 +463,22 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
return 0; 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 * Note the signature data
*/ */
...@@ -472,13 +512,21 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen, ...@@ -472,13 +512,21 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
struct asymmetric_key_id *kid; struct asymmetric_key_id *kid;
/* Generate cert issuer + serial number key ID */ /* Generate cert issuer + serial number key ID */
if (!ctx->expect_skid) {
kid = asymmetric_key_generate_id(ctx->raw_serial, kid = asymmetric_key_generate_id(ctx->raw_serial,
ctx->raw_serial_size, ctx->raw_serial_size,
ctx->raw_issuer, ctx->raw_issuer,
ctx->raw_issuer_size); ctx->raw_issuer_size);
} else {
kid = asymmetric_key_generate_id(ctx->raw_skid,
ctx->raw_skid_size,
"", 0);
}
if (IS_ERR(kid)) if (IS_ERR(kid))
return PTR_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->signing_cert_id = kid;
sinfo->index = ++ctx->sinfo_index; sinfo->index = ++ctx->sinfo_index;
*ctx->ppsinfo = sinfo; *ctx->ppsinfo = sinfo;
......
...@@ -33,7 +33,9 @@ struct pkcs7_signed_info { ...@@ -33,7 +33,9 @@ struct pkcs7_signed_info {
unsigned authattrs_len; unsigned authattrs_len;
const void *authattrs; 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; struct asymmetric_key_id *signing_cert_id;
/* Message signature. /* Message signature.
...@@ -50,6 +52,7 @@ struct pkcs7_message { ...@@ -50,6 +52,7 @@ struct pkcs7_message {
struct x509_certificate *certs; /* Certificate list */ struct x509_certificate *certs; /* Certificate list */
struct x509_certificate *crl; /* Revocation list */ struct x509_certificate *crl; /* Revocation list */
struct pkcs7_signed_info *signed_infos; struct pkcs7_signed_info *signed_infos;
u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */
/* Content Data (or NULL) */ /* Content Data (or NULL) */
enum OID data_type; /* Type of Data */ enum OID data_type; /* Type of Data */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment