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 <dhowells@redhat.com> Acked-by: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
parent
3968280c76
commit
4c0b4b1d1a
|
@ -54,4 +54,11 @@ pkcs7_test_key-y := \
|
||||||
obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o
|
obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o
|
||||||
|
|
||||||
verify_signed_pefile-y := \
|
verify_signed_pefile-y := \
|
||||||
verify_pefile.o
|
verify_pefile.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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/* Parse a Microsoft Individual Code Signing blob
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 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 <linux/kernel.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/oid_registry.h>
|
||||||
|
#include <crypto/pkcs7.h>
|
||||||
|
#include "verify_pefile.h"
|
||||||
|
#include "mscode-asn1.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a Microsoft Individual Code Signing blob
|
||||||
|
*/
|
||||||
|
int mscode_parse(struct pefile_context *ctx)
|
||||||
|
{
|
||||||
|
const void *content_data;
|
||||||
|
size_t data_len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
pr_debug("PKCS#7 message does not contain data\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
|
||||||
|
content_data);
|
||||||
|
|
||||||
|
return asn1_ber_decoder(&mscode_decoder, ctx, content_data, data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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));
|
||||||
|
pr_err("Unknown OID: %s\n", buffer);
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oid != OID_msIndividualSPKeyPurpose) {
|
||||||
|
pr_err("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 = HASH_ALGO_MD4;
|
||||||
|
break;
|
||||||
|
case OID_md5:
|
||||||
|
ctx->digest_algo = HASH_ALGO_MD5;
|
||||||
|
break;
|
||||||
|
case OID_sha1:
|
||||||
|
ctx->digest_algo = HASH_ALGO_SHA1;
|
||||||
|
break;
|
||||||
|
case OID_sha256:
|
||||||
|
ctx->digest_algo = HASH_ALGO_SHA256;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OID__NR:
|
||||||
|
sprint_oid(value, vlen, buffer, sizeof(buffer));
|
||||||
|
pr_err("Unknown OID: %s\n", buffer);
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pr_err("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;
|
||||||
|
}
|
|
@ -245,6 +245,13 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = mscode_parse(&ctx);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
pr_debug("Digest: %u [%*ph]\n",
|
||||||
|
ctx.digest_len, ctx.digest_len, ctx.digest);
|
||||||
|
|
||||||
ret = -ENOANO; // Not yet complete
|
ret = -ENOANO; // Not yet complete
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -35,3 +35,8 @@ struct pefile_context {
|
||||||
pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
|
pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
|
||||||
#define kleave(FMT, ...) \
|
#define kleave(FMT, ...) \
|
||||||
pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
|
pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mscode_parser.c
|
||||||
|
*/
|
||||||
|
extern int mscode_parse(struct pefile_context *ctx);
|
||||||
|
|
|
@ -52,8 +52,13 @@ enum OID {
|
||||||
OID_md4, /* 1.2.840.113549.2.4 */
|
OID_md4, /* 1.2.840.113549.2.4 */
|
||||||
OID_md5, /* 1.2.840.113549.2.5 */
|
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_msPeImageDataObjId, /* 1.3.6.1.4.1.311.2.1.15 */
|
||||||
|
OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */
|
||||||
OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */
|
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_sha1, /* 1.3.14.3.2.26 */
|
||||||
OID_sha256, /* 2.16.840.1.101.3.4.2.1 */
|
OID_sha256, /* 2.16.840.1.101.3.4.2.1 */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue