summaryrefslogtreecommitdiff
path: root/crypto/asymmetric_keys/pkcs7_parser.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2015-07-20 21:16:33 +0100
committerDavid Howells <dhowells@redhat.com>2015-08-12 17:01:01 +0100
commit60d65cacd7c2d84a6dcad69bcb57bbf0220c8643 (patch)
tree636bda3cc9024a04edf1ae5780266fde743e7b1e /crypto/asymmetric_keys/pkcs7_parser.c
parenta4c6e57f4f5fa65cbdb8cc1c14ff5ca7c56766c3 (diff)
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: David Howells <dhowells@redhat.com> Reviewed-By: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'crypto/asymmetric_keys/pkcs7_parser.c')
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c62
1 files changed, 55 insertions, 7 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index ab427f04b299..826e2f3f507b 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -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;
}
/*
@@ -440,6 +464,22 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
}
/*
+ * 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
*/
int pkcs7_sig_note_signature(void *context, size_t hdrlen,
@@ -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 */
- kid = asymmetric_key_generate_id(ctx->raw_serial,
- ctx->raw_serial_size,
- ctx->raw_issuer,
- ctx->raw_issuer_size);
+ 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;