From: David Howells Date: Tue, 15 Jan 2013 15:33:41 +0000 (+0000) Subject: pefile: Parse the "Microsoft individual code signing" data blob X-Git-Tag: next-20130218~61^2~3 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=747762564258e8812e72b6d06f4c1ebcee0d35c1;p=karo-tx-linux.git pefile: Parse the "Microsoft individual code signing" data blob The PKCS#7 certificate should contain a "Microsoft individual code signing" data blob as its signed content. This blob contains a digest of the signed content of the PE binary and the OID of the digest algorithm used (typically SHA256). Signed-off-by: David Howells Reviewed-by: Kees Cook --- diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 2675146a41a9..ddc64bb8c933 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -47,4 +47,11 @@ clean-files += pkcs7-asn1.c pkcs7-asn1.h obj-$(CONFIG_PE_FILE_PARSER) += pefile_key_parser.o pefile_key_parser-y := \ - pefile_parser.o + pefile_parser.o \ + mscode_parser.o \ + mscode-asn1.o + +$(obj)/mscode_parser.o: $(obj)/mscode-asn1.h $(obj)/mscode-asn1.h +$(obj)/mscode-asn1.o: $(obj)/mscode-asn1.c $(obj)/mscode-asn1.h + +clean-files += mscode-asn1.c mscode-asn1.h diff --git a/crypto/asymmetric_keys/mscode.asn1 b/crypto/asymmetric_keys/mscode.asn1 new file mode 100644 index 000000000000..6d09ba48c41c --- /dev/null +++ b/crypto/asymmetric_keys/mscode.asn1 @@ -0,0 +1,28 @@ +--- Microsoft individual code signing data blob parser +--- +--- Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. +--- Written by David Howells (dhowells@redhat.com) +--- +--- This program is free software; you can redistribute it and/or +--- modify it under the terms of the GNU General Public Licence +--- as published by the Free Software Foundation; either version +--- 2 of the Licence, or (at your option) any later version. +--- + +MSCode ::= SEQUENCE { + type SEQUENCE { + contentType ContentType, + parameters ANY + }, + content SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest OCTET STRING ({ mscode_note_digest }) + } +} + +ContentType ::= OBJECT IDENTIFIER ({ mscode_note_content_type }) + +DigestAlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER ({ mscode_note_digest_algo }), + parameters ANY OPTIONAL +} diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c new file mode 100644 index 000000000000..0bd68e0023b5 --- /dev/null +++ b/crypto/asymmetric_keys/mscode_parser.c @@ -0,0 +1,110 @@ +/* Parse a Microsoft Individual Code Signing blob + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#define pr_fmt(fmt) "MSCODE: "fmt +#include +#include +#include +#include +#include "pefile_parser.h" +#include "mscode-asn1.h" + +/* + * Parse a Microsoft Individual Code Signing blob + */ +int mscode_parse(struct pefile_context *ctx) +{ + pr_devel("Data: %zu [%*ph]\n", + ctx->pkcs7->data_len + ctx->pkcs7->data_hdrlen, + (unsigned)(ctx->pkcs7->data_len + ctx->pkcs7->data_hdrlen), + ctx->pkcs7->data - ctx->pkcs7->data_hdrlen); + + return asn1_ber_decoder(&mscode_decoder, ctx, + ctx->pkcs7->data - ctx->pkcs7->data_hdrlen, + ctx->pkcs7->data_len + ctx->pkcs7->data_hdrlen); +} + +/* + * Check the content type OID + */ +int mscode_note_content_type(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + enum OID oid; + + oid = look_up_OID(value, vlen); + if (oid == OID__NR) { + char buffer[50]; + sprint_oid(value, vlen, buffer, sizeof(buffer)); + printk("MSCODE: Unknown OID: %s\n", buffer); + return -EBADMSG; + } + + if (oid != OID_msIndividualSPKeyPurpose) { + printk("MSCODE: Unexpected content type OID %u\n", oid); + return -EBADMSG; + } + + return 0; +} + +/* + * Note the digest algorithm OID + */ +int mscode_note_digest_algo(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + struct pefile_context *ctx = context; + char buffer[50]; + enum OID oid; + + oid = look_up_OID(value, vlen); + switch (oid) { + case OID_md4: + ctx->digest_algo = PKEY_HASH_MD4; + break; + case OID_md5: + ctx->digest_algo = PKEY_HASH_MD5; + break; + case OID_sha1: + ctx->digest_algo = PKEY_HASH_SHA1; + break; + case OID_sha256: + ctx->digest_algo = PKEY_HASH_SHA256; + break; + + case OID__NR: + sprint_oid(value, vlen, buffer, sizeof(buffer)); + printk("MSCODE: Unknown OID: %s\n", buffer); + return -EBADMSG; + + default: + printk("MSCODE: Unsupported content type: %u\n", oid); + return -ENOPKG; + } + + return 0; +} + +/* + * Note the digest we're guaranteeing with this certificate + */ +int mscode_note_digest(void *context, size_t hdrlen, + unsigned char tag, + const void *value, size_t vlen) +{ + struct pefile_context *ctx = context; + ctx->digest = value; + ctx->digest_len = vlen; + return 0; +} diff --git a/crypto/asymmetric_keys/pefile_parser.c b/crypto/asymmetric_keys/pefile_parser.c index 056500f4dd60..f1c8cc1b995d 100644 --- a/crypto/asymmetric_keys/pefile_parser.c +++ b/crypto/asymmetric_keys/pefile_parser.c @@ -231,6 +231,12 @@ static int pefile_key_preparse(struct key_preparsed_payload *prep) goto error; } + ret = mscode_parse(&ctx); + if (ret < 0) + goto error; + + pr_devel("Digest: %u [%*ph]\n", ctx.digest_len, ctx.digest_len, ctx.digest); + ret = -ENOANO; // Not yet complete error: diff --git a/crypto/asymmetric_keys/pefile_parser.h b/crypto/asymmetric_keys/pefile_parser.h index 82bcaf6cd232..c3462b79c158 100644 --- a/crypto/asymmetric_keys/pefile_parser.h +++ b/crypto/asymmetric_keys/pefile_parser.h @@ -29,3 +29,8 @@ struct pefile_context { unsigned digest_len; /* Digest length */ enum pkey_hash_algo digest_algo; /* Digest algorithm */ }; + +/* + * mscode_parser.c + */ +extern int mscode_parse(struct pefile_context *ctx); diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h index edeff85cb1e8..332dcf5fea58 100644 --- a/include/linux/oid_registry.h +++ b/include/linux/oid_registry.h @@ -52,8 +52,12 @@ enum OID { OID_md4, /* 1.2.840.113549.2.4 */ OID_md5, /* 1.2.840.113549.2.5 */ - OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ + /* Microsoft Authenticode & Software Publishing */ + OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */ + OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */ OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ + + OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ OID_sha1, /* 1.3.14.3.2.26 */ OID_sha256, /* 2.16.840.1.101.3.4.2.1 */