TianoCore EDK2 master
Loading...
Searching...
No Matches
CryptAuthenticode.c
Go to the documentation of this file.
1
17#include "InternalCryptLib.h"
18
19#include <openssl/objects.h>
20#include <openssl/x509.h>
21#include <openssl/pkcs7.h>
22
23//
24// OID ASN.1 Value for SPC_INDIRECT_DATA_OBJID
25//
26GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSpcIndirectOidValue[] = {
27 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04
28};
29
56BOOLEAN
57EFIAPI
59 IN CONST UINT8 *AuthData,
60 IN UINTN DataSize,
61 IN CONST UINT8 *TrustedCert,
62 IN UINTN CertSize,
63 IN CONST UINT8 *ImageHash,
64 IN UINTN HashSize
65 )
66{
67 BOOLEAN Status;
68 PKCS7 *Pkcs7;
69 CONST UINT8 *Temp;
70 CONST UINT8 *OrigAuthData;
71 UINT8 *SpcIndirectDataContent;
72 UINT8 Asn1Byte;
73 UINTN ContentSize;
74 CONST UINT8 *SpcIndirectDataOid;
75
76 //
77 // Check input parameters.
78 //
79 if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) {
80 return FALSE;
81 }
82
83 if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) {
84 return FALSE;
85 }
86
87 Status = FALSE;
88 Pkcs7 = NULL;
89 OrigAuthData = AuthData;
90
91 //
92 // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature
93 //
94 Temp = AuthData;
95 Pkcs7 = d2i_PKCS7 (NULL, &Temp, (int)DataSize);
96 if (Pkcs7 == NULL) {
97 goto _Exit;
98 }
99
100 //
101 // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
102 //
103 if (!PKCS7_type_is_signed (Pkcs7) || PKCS7_get_detached (Pkcs7)) {
104 goto _Exit;
105 }
106
107 //
108 // NOTE: OpenSSL PKCS7 Decoder didn't work for Authenticode-format signed data due to
109 // some authenticode-specific structure. Use opaque ASN.1 string to retrieve
110 // PKCS#7 ContentInfo here.
111 //
112 SpcIndirectDataOid = OBJ_get0_data (Pkcs7->d.sign->contents->type);
113 if ((OBJ_length (Pkcs7->d.sign->contents->type) != sizeof (mSpcIndirectOidValue)) ||
114 (CompareMem (
115 SpcIndirectDataOid,
116 mSpcIndirectOidValue,
117 sizeof (mSpcIndirectOidValue)
118 ) != 0))
119 {
120 //
121 // Un-matched SPC_INDIRECT_DATA_OBJID.
122 //
123 goto _Exit;
124 }
125
126 SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data);
127
128 //
129 // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent.
130 //
131 Asn1Byte = *(SpcIndirectDataContent + 1);
132
133 if ((Asn1Byte & 0x80) == 0) {
134 //
135 // Short Form of Length Encoding (Length < 128)
136 //
137 ContentSize = (UINTN)(Asn1Byte & 0x7F);
138 //
139 // Skip the SEQUENCE Tag;
140 //
141 SpcIndirectDataContent += 2;
142 } else if ((Asn1Byte & 0x81) == 0x81) {
143 //
144 // Long Form of Length Encoding (128 <= Length < 255, Single Octet)
145 //
146 ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));
147 //
148 // Skip the SEQUENCE Tag;
149 //
150 SpcIndirectDataContent += 3;
151 } else if ((Asn1Byte & 0x82) == 0x82) {
152 //
153 // Long Form of Length Encoding (Length > 255, Two Octet)
154 //
155 ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));
156 ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3));
157 //
158 // Skip the SEQUENCE Tag;
159 //
160 SpcIndirectDataContent += 4;
161 } else {
162 goto _Exit;
163 }
164
165 //
166 // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent
167 // defined in Authenticode
168 // NOTE: Need to double-check HashLength here!
169 //
170 if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) {
171 //
172 // Un-matched PE/COFF Hash Value
173 //
174 goto _Exit;
175 }
176
177 //
178 // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature
179 //
180 Status = (BOOLEAN)Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize);
181
182_Exit:
183 //
184 // Release Resources
185 //
186 PKCS7_free (Pkcs7);
187
188 return Status;
189}
UINT64 UINTN
BOOLEAN EFIAPI Pkcs7Verify(IN CONST UINT8 *P7Data, IN UINTN P7Length, IN CONST UINT8 *TrustedCert, IN UINTN CertLength, IN CONST UINT8 *InData, IN UINTN DataLength)
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
BOOLEAN EFIAPI AuthenticodeVerify(IN CONST UINT8 *AuthData, IN UINTN DataSize, IN CONST UINT8 *TrustedCert, IN UINTN CertSize, IN CONST UINT8 *ImageHash, IN UINTN HashSize)