]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c
0370fd77a5de077d560fd4951e6436040bc87317
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptAuthenticode.c
1 /** @file
2 Authenticode Portable Executable Signature Verification over OpenSSL.
3
4 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "InternalCryptLib.h"
16
17 #include <openssl/objects.h>
18 #include <openssl/x509.h>
19 #include <openssl/pkcs7.h>
20
21
22 /**
23 Verifies the validility of a PE/COFF Authenticode Signature as described in "Windows
24 Authenticode Portable Executable Signature Format".
25
26 If AuthData is NULL, then ASSERT().
27 If ImageHash is NULL, then ASSERT().
28
29 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed
30 PE/COFF image to be verified.
31 @param[in] DataSize Size of the Authenticode Signature in bytes.
32 @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which
33 is used for certificate chain verification.
34 @param[in] CertSize Size of the trusted certificate in bytes.
35 @param[in] ImageHash Pointer to the original image file hash value. The procudure
36 for calculating the image hash value is described in Authenticode
37 specification.
38 @param[in] HashSize Size of Image hash value in bytes.
39
40 @retval TRUE The specified Authenticode Signature is valid.
41 @retval FALSE Invalid Authenticode Signature.
42
43 **/
44 BOOLEAN
45 EFIAPI
46 AuthenticodeVerify (
47 IN CONST UINT8 *AuthData,
48 IN UINTN DataSize,
49 IN CONST UINT8 *TrustedCert,
50 IN UINTN CertSize,
51 IN CONST UINT8 *ImageHash,
52 IN UINTN HashSize
53 )
54 {
55 BOOLEAN Status;
56 PKCS7 *Pkcs7;
57 CONST UINT8 *OrigAuthData;
58 UINT8 *SpcIndirectDataContent;
59 UINT8 Asn1Byte;
60 UINTN ContentSize;
61
62 //
63 // ASSERT if Authenticode Signature Data or PE Image Hash is NULL
64 //
65 ASSERT (AuthData != NULL);
66 ASSERT (ImageHash != NULL);
67
68 if (DataSize > INT_MAX) {
69 return FALSE;
70 }
71
72 Status = FALSE;
73 Pkcs7 = NULL;
74 OrigAuthData = AuthData;
75
76 //
77 // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature
78 //
79 Pkcs7 = d2i_PKCS7 (NULL, &AuthData, (int)DataSize);
80 if (Pkcs7 == NULL) {
81 goto _Exit;
82 }
83
84 //
85 // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
86 //
87 if (!PKCS7_type_is_signed (Pkcs7)) {
88 goto _Exit;
89 }
90
91 //
92 // NOTE: OpenSSL PKCS7 Decoder didn't work for Authenticode-format signed data due to
93 // some authenticode-specific structure. Use opaque ASN.1 string to retrieve
94 // PKCS#7 ContentInfo here.
95 //
96 SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data);
97
98 //
99 // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent.
100 //
101 Asn1Byte = *(SpcIndirectDataContent + 1);
102 if ((Asn1Byte & 0x80) == 0) {
103 //
104 // Short Form of Length Encoding
105 //
106 ContentSize = (UINTN) (Asn1Byte & 0x7F);
107 //
108 // Skip the SEQUENCE Tag;
109 //
110 SpcIndirectDataContent += 2;
111 } else {
112 //
113 // Long Form of Length Encoding (Assume Only two bytes here)
114 //
115 ContentSize = (UINTN) (*(SpcIndirectDataContent + 2));
116 ContentSize = (ContentSize << 8) + (UINTN)(*(SpcIndirectDataContent + 3));
117 //
118 // Skip the SEQUENCE Tag;
119 //
120 SpcIndirectDataContent += 4;
121 }
122
123 //
124 // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent
125 // defined in Authenticode
126 // NOTE: Need to double-check HashLength here!
127 //
128 if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) {
129 //
130 // Un-matched PE/COFF Hash Value
131 //
132 goto _Exit;
133 }
134
135 //
136 // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature
137 //
138 Status = (BOOLEAN) Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize);
139
140 _Exit:
141 //
142 // Release Resources
143 //
144 PKCS7_free (Pkcs7);
145
146 return Status;
147 }