"Das U-Boot" Source Tree
at master 123 lines 3.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * MSCode parser using MbedTLS ASN1 library 4 * 5 * Copyright (c) 2024 Linaro Limited 6 * Author: Raymond Mao <raymond.mao@linaro.org> 7 */ 8 9#include <linux/kernel.h> 10#include <linux/err.h> 11#include <crypto/pkcs7.h> 12#include <crypto/mscode.h> 13 14/* 15 * Parse a Microsoft Individual Code Signing blob 16 * 17 * U.P.SEQUENCE { 18 * U.P.OBJECTIDENTIFIER 1.3.6.1.4.1.311.2.1.15 (SPC_PE_IMAGE_DATA_OBJID) 19 * U.P.SEQUENCE { 20 * U.P.BITSTRING NaN : 0 unused bit(s); 21 * [C.P.0] { 22 * [C.P.2] { 23 * [C.P.0] <arbitrary string> 24 * } 25 * } 26 * } 27 * } 28 * U.P.SEQUENCE { 29 * U.P.SEQUENCE { 30 * U.P.OBJECTIDENTIFIER <digest algorithm OID> 31 * U.P.NULL 32 * } 33 * U.P.OCTETSTRING <PE image digest> 34 * } 35 * 36 * @ctx: PE file context. 37 * @content_data: content data pointer. 38 * @data_len: content data length. 39 * @asn1hdrlen: ASN1 header length. 40 */ 41int mscode_parse(void *ctx, const void *content_data, size_t data_len, 42 size_t asn1hdrlen) 43{ 44 struct pefile_context *_ctx = ctx; 45 unsigned char *p = (unsigned char *)content_data; 46 unsigned char *end = (unsigned char *)content_data + data_len; 47 size_t len = 0; 48 int ret; 49 unsigned char *inner_p; 50 size_t seq_len = 0; 51 52 ret = mbedtls_asn1_get_tag(&p, end, &seq_len, 53 MBEDTLS_ASN1_CONSTRUCTED | 54 MBEDTLS_ASN1_SEQUENCE); 55 if (ret) 56 return ret; 57 58 inner_p = p; 59 ret = mbedtls_asn1_get_tag(&inner_p, inner_p + seq_len, &len, 60 MBEDTLS_ASN1_OID); 61 if (ret) 62 return ret; 63 64 /* Sanity check on the PE Image Data OID (1.3.6.1.4.1.311.2.1.15) */ 65 if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_PEIMAGEDATA, inner_p, 66 len)) 67 return -EINVAL; 68 69 p += seq_len; 70 ret = mbedtls_asn1_get_tag(&p, end, &seq_len, 71 MBEDTLS_ASN1_CONSTRUCTED | 72 MBEDTLS_ASN1_SEQUENCE); 73 if (ret) 74 return ret; 75 76 ret = mbedtls_asn1_get_tag(&p, p + seq_len, &seq_len, 77 MBEDTLS_ASN1_CONSTRUCTED | 78 MBEDTLS_ASN1_SEQUENCE); 79 if (ret) 80 return ret; 81 82 inner_p = p; 83 84 /* 85 * Check if the inner sequence contains a supported hash 86 * algorithm OID 87 */ 88 ret = mbedtls_asn1_get_tag(&inner_p, inner_p + seq_len, &len, 89 MBEDTLS_ASN1_OID); 90 if (ret) 91 return ret; 92 93 if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_DIGEST_ALG_MD5, inner_p, len)) 94 _ctx->digest_algo = "md5"; 95 else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_DIGEST_ALG_SHA1, inner_p, 96 len)) 97 _ctx->digest_algo = "sha1"; 98 else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_DIGEST_ALG_SHA224, inner_p, 99 len)) 100 _ctx->digest_algo = "sha224"; 101 else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_DIGEST_ALG_SHA256, inner_p, 102 len)) 103 _ctx->digest_algo = "sha256"; 104 else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_DIGEST_ALG_SHA384, inner_p, 105 len)) 106 _ctx->digest_algo = "sha384"; 107 else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_DIGEST_ALG_SHA512, inner_p, 108 len)) 109 _ctx->digest_algo = "sha512"; 110 111 if (!_ctx->digest_algo) 112 return -EINVAL; 113 114 p += seq_len; 115 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); 116 if (ret) 117 return ret; 118 119 _ctx->digest = p; 120 _ctx->digest_len = len; 121 122 return 0; 123}