1b4d0d230SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24c0b4b1dSDavid Howells /* Parse a Microsoft Individual Code Signing blob
34c0b4b1dSDavid Howells *
44c0b4b1dSDavid Howells * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
54c0b4b1dSDavid Howells * Written by David Howells ([email protected])
64c0b4b1dSDavid Howells */
74c0b4b1dSDavid Howells
84c0b4b1dSDavid Howells #define pr_fmt(fmt) "MSCODE: "fmt
94c0b4b1dSDavid Howells #include <linux/kernel.h>
104c0b4b1dSDavid Howells #include <linux/slab.h>
114c0b4b1dSDavid Howells #include <linux/err.h>
124c0b4b1dSDavid Howells #include <linux/oid_registry.h>
134c0b4b1dSDavid Howells #include <crypto/pkcs7.h>
144c0b4b1dSDavid Howells #include "verify_pefile.h"
154fa8bc94SMasahiro Yamada #include "mscode.asn1.h"
164c0b4b1dSDavid Howells
174c0b4b1dSDavid Howells /*
184c0b4b1dSDavid Howells * Parse a Microsoft Individual Code Signing blob
194c0b4b1dSDavid Howells */
mscode_parse(void * _ctx,const void * content_data,size_t data_len,size_t asn1hdrlen)20e68503bdSDavid Howells int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
21e68503bdSDavid Howells size_t asn1hdrlen)
224c0b4b1dSDavid Howells {
23e68503bdSDavid Howells struct pefile_context *ctx = _ctx;
244c0b4b1dSDavid Howells
25e68503bdSDavid Howells content_data -= asn1hdrlen;
26e68503bdSDavid Howells data_len += asn1hdrlen;
274c0b4b1dSDavid Howells pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
284c0b4b1dSDavid Howells content_data);
294c0b4b1dSDavid Howells
304c0b4b1dSDavid Howells return asn1_ber_decoder(&mscode_decoder, ctx, content_data, data_len);
314c0b4b1dSDavid Howells }
324c0b4b1dSDavid Howells
334c0b4b1dSDavid Howells /*
344c0b4b1dSDavid Howells * Check the content type OID
354c0b4b1dSDavid Howells */
mscode_note_content_type(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)364c0b4b1dSDavid Howells int mscode_note_content_type(void *context, size_t hdrlen,
374c0b4b1dSDavid Howells unsigned char tag,
384c0b4b1dSDavid Howells const void *value, size_t vlen)
394c0b4b1dSDavid Howells {
404c0b4b1dSDavid Howells enum OID oid;
414c0b4b1dSDavid Howells
424c0b4b1dSDavid Howells oid = look_up_OID(value, vlen);
434c0b4b1dSDavid Howells if (oid == OID__NR) {
444c0b4b1dSDavid Howells char buffer[50];
454c0b4b1dSDavid Howells
464c0b4b1dSDavid Howells sprint_oid(value, vlen, buffer, sizeof(buffer));
474c0b4b1dSDavid Howells pr_err("Unknown OID: %s\n", buffer);
484c0b4b1dSDavid Howells return -EBADMSG;
494c0b4b1dSDavid Howells }
504c0b4b1dSDavid Howells
51dd7d66f2SVivek Goyal /*
52dd7d66f2SVivek Goyal * pesign utility had a bug where it was putting
53dd7d66f2SVivek Goyal * OID_msIndividualSPKeyPurpose instead of OID_msPeImageDataObjId
54dd7d66f2SVivek Goyal * So allow both OIDs.
55dd7d66f2SVivek Goyal */
56dd7d66f2SVivek Goyal if (oid != OID_msPeImageDataObjId &&
57dd7d66f2SVivek Goyal oid != OID_msIndividualSPKeyPurpose) {
584c0b4b1dSDavid Howells pr_err("Unexpected content type OID %u\n", oid);
594c0b4b1dSDavid Howells return -EBADMSG;
604c0b4b1dSDavid Howells }
614c0b4b1dSDavid Howells
624c0b4b1dSDavid Howells return 0;
634c0b4b1dSDavid Howells }
644c0b4b1dSDavid Howells
654c0b4b1dSDavid Howells /*
664c0b4b1dSDavid Howells * Note the digest algorithm OID
674c0b4b1dSDavid Howells */
mscode_note_digest_algo(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)684c0b4b1dSDavid Howells int mscode_note_digest_algo(void *context, size_t hdrlen,
694c0b4b1dSDavid Howells unsigned char tag,
704c0b4b1dSDavid Howells const void *value, size_t vlen)
714c0b4b1dSDavid Howells {
724c0b4b1dSDavid Howells struct pefile_context *ctx = context;
734c0b4b1dSDavid Howells char buffer[50];
744c0b4b1dSDavid Howells enum OID oid;
754c0b4b1dSDavid Howells
764c0b4b1dSDavid Howells oid = look_up_OID(value, vlen);
774c0b4b1dSDavid Howells switch (oid) {
78*203a6763SEric Biggers case OID_sha1:
79*203a6763SEric Biggers ctx->digest_algo = "sha1";
80*203a6763SEric Biggers break;
814c0b4b1dSDavid Howells case OID_sha256:
824e8ae72aSDavid Howells ctx->digest_algo = "sha256";
834c0b4b1dSDavid Howells break;
8407f081fbSDavid Howells case OID_sha384:
854e8ae72aSDavid Howells ctx->digest_algo = "sha384";
8607f081fbSDavid Howells break;
8707f081fbSDavid Howells case OID_sha512:
884e8ae72aSDavid Howells ctx->digest_algo = "sha512";
8907f081fbSDavid Howells break;
90fdb4f66cSDimitri John Ledkov case OID_sha3_256:
91fdb4f66cSDimitri John Ledkov ctx->digest_algo = "sha3-256";
92fdb4f66cSDimitri John Ledkov break;
93fdb4f66cSDimitri John Ledkov case OID_sha3_384:
94fdb4f66cSDimitri John Ledkov ctx->digest_algo = "sha3-384";
95fdb4f66cSDimitri John Ledkov break;
96fdb4f66cSDimitri John Ledkov case OID_sha3_512:
97fdb4f66cSDimitri John Ledkov ctx->digest_algo = "sha3-512";
98fdb4f66cSDimitri John Ledkov break;
994c0b4b1dSDavid Howells
1004c0b4b1dSDavid Howells case OID__NR:
1014c0b4b1dSDavid Howells sprint_oid(value, vlen, buffer, sizeof(buffer));
1024c0b4b1dSDavid Howells pr_err("Unknown OID: %s\n", buffer);
1034c0b4b1dSDavid Howells return -EBADMSG;
1044c0b4b1dSDavid Howells
1054c0b4b1dSDavid Howells default:
1064c0b4b1dSDavid Howells pr_err("Unsupported content type: %u\n", oid);
1074c0b4b1dSDavid Howells return -ENOPKG;
1084c0b4b1dSDavid Howells }
1094c0b4b1dSDavid Howells
1104c0b4b1dSDavid Howells return 0;
1114c0b4b1dSDavid Howells }
1124c0b4b1dSDavid Howells
1134c0b4b1dSDavid Howells /*
1144c0b4b1dSDavid Howells * Note the digest we're guaranteeing with this certificate
1154c0b4b1dSDavid Howells */
mscode_note_digest(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)1164c0b4b1dSDavid Howells int mscode_note_digest(void *context, size_t hdrlen,
1174c0b4b1dSDavid Howells unsigned char tag,
1184c0b4b1dSDavid Howells const void *value, size_t vlen)
1194c0b4b1dSDavid Howells {
1204c0b4b1dSDavid Howells struct pefile_context *ctx = context;
1214c0b4b1dSDavid Howells
122e68503bdSDavid Howells ctx->digest = kmemdup(value, vlen, GFP_KERNEL);
123d128471aSLans Zhang if (!ctx->digest)
124d128471aSLans Zhang return -ENOMEM;
125d128471aSLans Zhang
126d128471aSLans Zhang ctx->digest_len = vlen;
127d128471aSLans Zhang
128d128471aSLans Zhang return 0;
1294c0b4b1dSDavid Howells }
130