Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c0b4b1d authored by David Howells's avatar David Howells
Browse files

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: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarVivek Goyal <vgoyal@redhat.com>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
parent 3968280c
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -54,4 +54,11 @@ pkcs7_test_key-y := \
obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o

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
+28 −0
Original line number Diff line number Diff line
--- 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
}
+120 −0
Original line number Diff line number Diff line
/* 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;
}
+7 −0
Original line number Diff line number Diff line
@@ -245,6 +245,13 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen,
		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

error:
+5 −0
Original line number Diff line number Diff line
@@ -35,3 +35,8 @@ struct pefile_context {
	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) \
	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)

/*
 * mscode_parser.c
 */
extern int mscode_parse(struct pefile_context *ctx);
Loading