]>
Commit | Line | Data |
---|---|---|
1 | /** @file\r | |
2 | Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.\r | |
3 | \r | |
4 | Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r | |
5 | \r | |
6 | Redistribution and use in source and binary forms, with or without\r | |
7 | modification, are permitted provided that the following conditions are met:\r | |
8 | 1. Redistributions of source code must retain the above copyright notice,\r | |
9 | this list of conditions and the following disclaimer.\r | |
10 | 2. Redistributions in binary form must reproduce the above copyright notice,\r | |
11 | this list of conditions and the following disclaimer in the documentation\r | |
12 | and/or other materials provided with the distribution.\r | |
13 | \r | |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r | |
15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r | |
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r | |
17 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r | |
18 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r | |
19 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r | |
20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r | |
21 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r | |
22 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r | |
23 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r | |
24 | \r | |
25 | **/\r | |
26 | \r | |
27 | #include <PiDxe.h>\r | |
28 | #include <Library/DebugLib.h>\r | |
29 | #include <Library/BaseLib.h>\r | |
30 | #include <Library/BaseMemoryLib.h>\r | |
31 | #include <Library/PcdLib.h>\r | |
32 | #include <Library/MemoryAllocationLib.h>\r | |
33 | #include <Library/BaseCryptLib.h>\r | |
34 | \r | |
35 | /**\r | |
36 | Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches\r | |
37 | the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of\r | |
38 | the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the\r | |
39 | SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the\r | |
40 | SHA256 hash matches or there is then error computing the SHA256 hash, then\r | |
41 | set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already\r | |
42 | TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE\r | |
43 | bytes.\r | |
44 | **/\r | |
45 | VOID\r | |
46 | DetectTestKey (\r | |
47 | VOID\r | |
48 | )\r | |
49 | {\r | |
50 | BOOLEAN TestKeyUsed;\r | |
51 | UINTN PublicKeyDataLength;\r | |
52 | UINT8 *PublicKeyDataXdr;\r | |
53 | UINT8 *PublicKeyDataXdrEnd;\r | |
54 | VOID *HashContext;\r | |
55 | UINT8 Digest[SHA256_DIGEST_SIZE];\r | |
56 | UINTN TestKeyDigestSize;\r | |
57 | \r | |
58 | //\r | |
59 | // If PcdFmpDeviceTestKeySha256Digest is not exacty SHA256_DIGEST_SIZE bytes,\r | |
60 | // then skip the test key detection.\r | |
61 | //\r | |
62 | TestKeyDigestSize = PcdGetSize (PcdFmpDeviceTestKeySha256Digest);\r | |
63 | if (TestKeyDigestSize != SHA256_DIGEST_SIZE) {\r | |
64 | return;\r | |
65 | }\r | |
66 | \r | |
67 | //\r | |
68 | // If PcdTestKeyUsed is already TRUE, then skip test key detection\r | |
69 | //\r | |
70 | TestKeyUsed = PcdGetBool (PcdTestKeyUsed);\r | |
71 | if (TestKeyUsed) {\r | |
72 | return;\r | |
73 | }\r | |
74 | \r | |
75 | //\r | |
76 | // If PcdFmpDevicePkcs7CertBufferXdr is invalid, then skip test key detection\r | |
77 | //\r | |
78 | PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);\r | |
79 | PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);\r | |
80 | if (PublicKeyDataXdr == NULL || PublicKeyDataXdr == PublicKeyDataXdrEnd) {\r | |
81 | return;\r | |
82 | }\r | |
83 | \r | |
84 | //\r | |
85 | // Allocate hash context buffer required for SHA 256\r | |
86 | //\r | |
87 | HashContext = AllocatePool (Sha256GetContextSize ());\r | |
88 | if (HashContext == NULL) {\r | |
89 | TestKeyUsed = TRUE;\r | |
90 | }\r | |
91 | \r | |
92 | //\r | |
93 | // Loop through all keys in PcdFmpDevicePkcs7CertBufferXdr\r | |
94 | //\r | |
95 | while (!TestKeyUsed && PublicKeyDataXdr < PublicKeyDataXdrEnd) {\r | |
96 | if (PublicKeyDataXdr + sizeof (UINT32) > PublicKeyDataXdrEnd) {\r | |
97 | //\r | |
98 | // Key data extends beyond end of PCD\r | |
99 | //\r | |
100 | break;\r | |
101 | }\r | |
102 | //\r | |
103 | // Read key length stored in big endian format\r | |
104 | //\r | |
105 | PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));\r | |
106 | //\r | |
107 | // Point to the start of the key data\r | |
108 | //\r | |
109 | PublicKeyDataXdr += sizeof (UINT32);\r | |
110 | if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {\r | |
111 | //\r | |
112 | // Key data extends beyond end of PCD\r | |
113 | //\r | |
114 | break;\r | |
115 | }\r | |
116 | \r | |
117 | //\r | |
118 | // Hash public key from PcdFmpDevicePkcs7CertBufferXdr using SHA256.\r | |
119 | // If error occurs computing SHA256, then assume test key is in use.\r | |
120 | //\r | |
121 | ZeroMem (Digest, SHA256_DIGEST_SIZE);\r | |
122 | if (!Sha256Init (HashContext)) {\r | |
123 | TestKeyUsed = TRUE;\r | |
124 | break;\r | |
125 | }\r | |
126 | if (!Sha256Update (HashContext, PublicKeyDataXdr, PublicKeyDataLength)) {\r | |
127 | TestKeyUsed = TRUE;\r | |
128 | break;\r | |
129 | }\r | |
130 | if (!Sha256Final (HashContext, Digest)) {\r | |
131 | TestKeyUsed = TRUE;\r | |
132 | break;\r | |
133 | }\r | |
134 | \r | |
135 | //\r | |
136 | // Check if SHA256 hash of public key matches SHA256 hash of test key\r | |
137 | //\r | |
138 | if (CompareMem (Digest, PcdGetPtr (PcdFmpDeviceTestKeySha256Digest), SHA256_DIGEST_SIZE) == 0) {\r | |
139 | TestKeyUsed = TRUE;\r | |
140 | break;\r | |
141 | }\r | |
142 | \r | |
143 | //\r | |
144 | // Point to start of next key\r | |
145 | //\r | |
146 | PublicKeyDataXdr += PublicKeyDataLength;\r | |
147 | PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));\r | |
148 | }\r | |
149 | \r | |
150 | //\r | |
151 | // Free hash context buffer required for SHA 256\r | |
152 | //\r | |
153 | if (HashContext != NULL) {\r | |
154 | FreePool (HashContext);\r | |
155 | HashContext = NULL;\r | |
156 | }\r | |
157 | \r | |
158 | //\r | |
159 | // If test key detected or an error occured checking for the test key, then\r | |
160 | // set PcdTestKeyUsed to TRUE.\r | |
161 | //\r | |
162 | if (TestKeyUsed) {\r | |
163 | DEBUG ((DEBUG_INFO, "FmpDxe: Test key detected in PcdFmpDevicePkcs7CertBufferXdr.\n"));\r | |
164 | PcdSetBoolS (PcdTestKeyUsed, TRUE);\r | |
165 | } else {\r | |
166 | DEBUG ((DEBUG_INFO, "FmpDxe: No test key detected in PcdFmpDevicePkcs7CertBufferXdr.\n"));\r | |
167 | }\r | |
168 | }\r |