hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// SPDX-License-Identifier: GPL-2.0-or-later
/* Parse a Microsoft Individual Code Signing blob
 *
 * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 */
 
#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(void *_ctx, const void *content_data, size_t data_len,
        size_t asn1hdrlen)
{
   struct pefile_context *ctx = _ctx;
 
   content_data -= asn1hdrlen;
   data_len += asn1hdrlen;
   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 = "md4";
       break;
   case OID_md5:
       ctx->digest_algo = "md5";
       break;
   case OID_sha1:
       ctx->digest_algo = "sha1";
       break;
   case OID_sha256:
       ctx->digest_algo = "sha256";
       break;
   case OID_sha384:
       ctx->digest_algo = "sha384";
       break;
   case OID_sha512:
       ctx->digest_algo = "sha512";
       break;
   case OID_sha224:
       ctx->digest_algo = "sha224";
       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 = kmemdup(value, vlen, GFP_KERNEL);
   if (!ctx->digest)
       return -ENOMEM;
 
   ctx->digest_len = vlen;
 
   return 0;
}