Skip to content

Commit

Permalink
Merge tag 'keys-pefile-20140709' into keys-next
Browse files Browse the repository at this point in the history
Here's a set of changes that implement a PE file signature checker.

This provides the following facility:

 (1) Extract the signature from the PE file.  This is a PKCS#7 message
     containing, as its data, a hash of the signed parts of the file.

 (2) Digest the signed parts of the file.

 (3) Compare the digest with the one from the PKCS#7 message.

 (4) Validate the signatures on the PKCS#7 message and indicate
     whether it was matched by a trusted key.

Signed-off-by: David Howells <[email protected]>
  • Loading branch information
dhowells committed Jul 22, 2014
2 parents 1ca72c9 + 98801c0 commit 6204e00
Show file tree
Hide file tree
Showing 9 changed files with 1,150 additions and 2 deletions.
11 changes: 10 additions & 1 deletion crypto/asymmetric_keys/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ config X509_CERTIFICATE_PARSER
select ASN1
select OID_REGISTRY
help
This option procides support for parsing X.509 format blobs for key
This option provides support for parsing X.509 format blobs for key
data and provides the ability to instantiate a crypto key from a
public key packet found inside the certificate.

Expand All @@ -59,4 +59,13 @@ config PKCS7_TEST_KEY

This is intended for testing the PKCS#7 parser.

config SIGNED_PE_FILE_VERIFICATION
bool "Support for PE file signature verification"
depends on PKCS7_MESSAGE_PARSER=y
select ASN1
select OID_REGISTRY
help
This option provides support for verifying the signature(s) on a
signed PE binary.

endif # ASYMMETRIC_KEY_TYPE
15 changes: 15 additions & 0 deletions crypto/asymmetric_keys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,18 @@ clean-files += pkcs7-asn1.c pkcs7-asn1.h
obj-$(CONFIG_PKCS7_TEST_KEY) += pkcs7_test_key.o
pkcs7_test_key-y := \
pkcs7_key_type.o

#
# Signed PE binary-wrapped key handling
#
obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o

verify_signed_pefile-y := \
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
28 changes: 28 additions & 0 deletions crypto/asymmetric_keys/mscode.asn1
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--- Microsoft individual code signing data blob parser
---
--- Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
--- Written by David Howells ([email protected])
---
--- 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
}
126 changes: 126 additions & 0 deletions crypto/asymmetric_keys/mscode_parser.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/* Parse a Microsoft Individual Code Signing blob
*
* Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
* Written by David Howells ([email protected])
*
* 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;
}

/*
* pesign utility had a bug where it was putting
* OID_msIndividualSPKeyPurpose instead of OID_msPeImageDataObjId
* So allow both OIDs.
*/
if (oid != OID_msPeImageDataObjId &&
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;
}
Loading

0 comments on commit 6204e00

Please sign in to comment.