1 /*############################################################################
2 # Copyright 2016-2017 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ############################################################################*/
16
17 /*!
18 * \file
19 *
20 * \brief Implementation of issuer material file parsing utilities.
21 *
22 */
23 #include "epid/common/file_parser.h"
24
25 #include <string.h>
26
27 #include "epid/common/math/ecdsa.h"
28 #include "epid/common/src/file_parser-internal.h"
29 #include "epid/common/src/memory.h"
30
31 const OctStr16 kEpidVersionCode[kNumEpidVersions] = {
32 {0x01, 0x00}, {0x02, 0x00},
33 };
34
35 const OctStr16 kEpidFileTypeCode[kNumFileTypes] = {
36 {0x00, 0x11}, {0x00, 0x0C}, {0x00, 0x0D}, {0x00, 0x0E},
37 {0x00, 0x0F}, {0x00, 0x03}, {0x00, 0x0B}, {0x00, 0x13},
38 };
39
40 /// Intel(R) EPID 2.0 Group Public Key binary format
41 typedef struct EpidGroupPubKeyCertificate {
42 EpidFileHeader header; ///< Intel(R) EPID binary file header
43 GroupId gid; ///< group ID
44 G1ElemStr h1; ///< an element in G1
45 G1ElemStr h2; ///< an element in G1
46 G2ElemStr w; ///< an element in G2
47 EcdsaSignature signature; ///< ECDSA Signature on SHA-256 of above values
48 } EpidGroupPubKeyCertificate;
49
50 /// Intel(R) EPID version
51 static const OctStr16 kEpidVersion = {0x02, 0x00};
52
53 /// Verify that certificate contains of EC secp256r1 parameters
EpidVerifyCaCertificate(EpidCaCertificate const * cert)54 EpidStatus EpidVerifyCaCertificate(EpidCaCertificate const* cert) {
55 // Prime of GF(p) for secp256r1
56 static const unsigned char secp256r1_p[] = {
57 // 2^256 -2^224 +2^192 +2^96 -1
58 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
61
62 // Coefficient of E Curve secp256r1
63 static const unsigned char secp256r1_a[] = {
64 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc};
67
68 // Coefficient of E Curve secp256r1
69 static const unsigned char secp256r1_b[] = {
70 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
71 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
72 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b};
73
74 // X coordinate of Base point G of secp256r1
75 static const unsigned char secp256r1_gx[] = {
76 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
77 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
78 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96};
79
80 // Y coordinate of Base point G of secp256r1
81 static const unsigned char secp256r1_gy[] = {
82 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
83 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
84 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5};
85
86 // Order of base point of secp256r1
87 static const unsigned char secp256r1_r[] = {
88 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
89 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
90 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
91 };
92
93 if (!cert) return kEpidBadArgErr;
94
95 // Verify that certificate contains of correct file header
96 if (0 !=
97 memcmp(&cert->header.epid_version, &kEpidVersion, sizeof(kEpidVersion))) {
98 return kEpidBadArgErr;
99 }
100 if (0 != memcmp(&cert->header.file_type,
101 &kEpidFileTypeCode[kIssuingCaPubKeyFile],
102 sizeof(cert->header.file_type))) {
103 return kEpidBadArgErr;
104 }
105
106 // Verify that certificate contains of EC secp256r1 parameters
107 if (0 != memcmp(&cert->prime, secp256r1_p, sizeof(secp256r1_p))) {
108 return kEpidBadArgErr;
109 }
110 if (0 != memcmp(&cert->a, secp256r1_a, sizeof(secp256r1_a))) {
111 return kEpidBadArgErr;
112 }
113 if (0 != memcmp(&cert->b, secp256r1_b, sizeof(secp256r1_b))) {
114 return kEpidBadArgErr;
115 }
116 if (0 != memcmp(&cert->x, secp256r1_gx, sizeof(secp256r1_gx))) {
117 return kEpidBadArgErr;
118 }
119 if (0 != memcmp(&cert->y, secp256r1_gy, sizeof(secp256r1_gy))) {
120 return kEpidBadArgErr;
121 }
122 if (0 != memcmp(&cert->r, secp256r1_r, sizeof(secp256r1_r))) {
123 return kEpidBadArgErr;
124 }
125
126 return kEpidNoErr;
127 }
128
EpidParseFileHeader(void const * buf,size_t len,EpidVersion * epid_version,EpidFileType * file_type)129 EpidStatus EpidParseFileHeader(void const* buf, size_t len,
130 EpidVersion* epid_version,
131 EpidFileType* file_type) {
132 EpidFileHeader* header = (EpidFileHeader*)buf;
133 if (!buf || len < sizeof(EpidFileHeader)) return kEpidBadArgErr;
134
135 if (epid_version) {
136 if (0 == memcmp((void*)&header->epid_version, &kEpidVersionCode[kEpid1x],
137 sizeof(header->epid_version))) {
138 *epid_version = kEpid1x;
139 } else if (0 == memcmp((void*)&header->epid_version,
140 &kEpidVersionCode[kEpid2x],
141 sizeof(header->epid_version))) {
142 *epid_version = kEpid2x;
143 } else {
144 // set default value
145 *epid_version = kNumEpidVersions;
146 }
147 }
148 if (file_type) {
149 if (0 == memcmp((void*)&header->file_type,
150 &kEpidFileTypeCode[kIssuingCaPubKeyFile],
151 sizeof(header->file_type))) {
152 *file_type = kIssuingCaPubKeyFile;
153 } else if (0 == memcmp((void*)&header->file_type,
154 &kEpidFileTypeCode[kGroupPubKeyFile],
155 sizeof(header->file_type))) {
156 *file_type = kGroupPubKeyFile;
157 } else if (0 == memcmp((void*)&header->file_type,
158 &kEpidFileTypeCode[kPrivRlFile],
159 sizeof(header->file_type))) {
160 *file_type = kPrivRlFile;
161 } else if (0 == memcmp((void*)&header->file_type,
162 &kEpidFileTypeCode[kSigRlFile],
163 sizeof(header->file_type))) {
164 *file_type = kSigRlFile;
165 } else if (0 == memcmp((void*)&header->file_type,
166 &kEpidFileTypeCode[kGroupRlFile],
167 sizeof(header->file_type))) {
168 *file_type = kGroupRlFile;
169 } else if (0 == memcmp((void*)&header->file_type,
170 &kEpidFileTypeCode[kPrivRlRequestFile],
171 sizeof(header->file_type))) {
172 *file_type = kPrivRlRequestFile;
173 } else if (0 == memcmp((void*)&header->file_type,
174 &kEpidFileTypeCode[kSigRlRequestFile],
175 sizeof(header->file_type))) {
176 *file_type = kSigRlRequestFile;
177 } else if (0 == memcmp((void*)&header->file_type,
178 &kEpidFileTypeCode[kGroupRlRequestFile],
179 sizeof(header->file_type))) {
180 *file_type = kGroupRlRequestFile;
181 } else {
182 // set default value
183 *file_type = kNumFileTypes;
184 }
185 }
186 return kEpidNoErr;
187 }
188
189 /// Parse a file with a revocation list of any type
EpidParseRlFile(void const * buf,size_t len,EpidCaCertificate const * cert,void * rl,size_t * rl_len,EpidFileType file_type)190 static EpidStatus EpidParseRlFile(void const* buf, size_t len,
191 EpidCaCertificate const* cert, void* rl,
192 size_t* rl_len, EpidFileType file_type) {
193 size_t min_rl_file_size = 0;
194 size_t empty_rl_size = 0;
195 size_t rl_entry_size = 0;
196 EpidStatus result = kEpidErr;
197 EpidFileHeader const* file_header = (EpidFileHeader*)buf;
198 void const* buf_rl =
199 (void const*)((unsigned char*)buf + sizeof(EpidFileHeader));
200 size_t buf_rl_len = 0;
201 EcdsaSignature const* signature = NULL;
202
203 if (!buf || !cert || !rl_len) return kEpidBadArgErr;
204
205 switch (file_type) {
206 case kPrivRlFile:
207 empty_rl_size = sizeof(PrivRl) - sizeof(((PrivRl*)0)->f[0]);
208 rl_entry_size = sizeof(((PrivRl*)0)->f[0]);
209 min_rl_file_size = sizeof(EpidFileHeader) + sizeof(PrivRl) -
210 sizeof(((PrivRl*)0)->f[0]) + sizeof(EcdsaSignature);
211 break;
212 case kSigRlFile:
213 empty_rl_size = sizeof(SigRl) - sizeof(((SigRl*)0)->bk[0]);
214 rl_entry_size = sizeof(((SigRl*)0)->bk[0]);
215 min_rl_file_size = sizeof(EpidFileHeader) + sizeof(SigRl) -
216 sizeof(((SigRl*)0)->bk[0]) + sizeof(EcdsaSignature);
217 break;
218 case kGroupRlFile:
219 empty_rl_size = sizeof(GroupRl) - sizeof(((GroupRl*)0)->gid[0]);
220 rl_entry_size = sizeof(((GroupRl*)0)->gid[0]);
221 min_rl_file_size = sizeof(EpidFileHeader) + sizeof(GroupRl) -
222 sizeof(((GroupRl*)0)->gid[0]) + sizeof(EcdsaSignature);
223 break;
224 default:
225 return kEpidErr;
226 }
227
228 if (min_rl_file_size > len) return kEpidBadArgErr;
229
230 // Verify that Intel(R) EPID file header in the buffer is correct
231 if (0 !=
232 memcmp(&file_header->epid_version, &kEpidVersion, sizeof(kEpidVersion))) {
233 return kEpidBadArgErr;
234 }
235 if (0 != memcmp(&file_header->file_type, &kEpidFileTypeCode[file_type],
236 sizeof(file_header->file_type))) {
237 return kEpidBadArgErr;
238 }
239
240 // Verify that CA certificate is correct
241 result = EpidVerifyCaCertificate(cert);
242 if (kEpidNoErr != result) return result;
243
244 // Verify that RL in file buffer contains of integer number of entries
245 buf_rl_len = len - sizeof(EpidFileHeader) - sizeof(EcdsaSignature);
246 if (0 != ((buf_rl_len - empty_rl_size) % rl_entry_size)) {
247 return kEpidBadArgErr;
248 }
249
250 signature =
251 (EcdsaSignature*)((unsigned char*)buf + len - sizeof(EcdsaSignature));
252 // Authenticate signature for buffer
253 result = EcdsaVerifyBuffer(buf, len - sizeof(EcdsaSignature),
254 (EcdsaPublicKey*)&cert->pubkey, signature);
255 if (kEpidSigValid != result) return result;
256
257 buf_rl_len = len - sizeof(EpidFileHeader) - sizeof(EcdsaSignature);
258
259 // If pointer to output buffer is NULL it should return required size of RL
260 if (!rl) {
261 *rl_len = buf_rl_len;
262 return kEpidNoErr;
263 }
264
265 if (*rl_len < buf_rl_len) return kEpidBadArgErr;
266 *rl_len = buf_rl_len;
267
268 // Copy revocation list from file buffer to output
269 // Memory copy is used to copy a revocation list of variable length
270 if (0 != memcpy_S(rl, *rl_len, buf_rl, buf_rl_len)) return kEpidBadArgErr;
271
272 return kEpidNoErr;
273 }
274
EpidParseGroupPubKeyFile(void const * buf,size_t len,EpidCaCertificate const * cert,GroupPubKey * pubkey)275 EpidStatus EpidParseGroupPubKeyFile(void const* buf, size_t len,
276 EpidCaCertificate const* cert,
277 GroupPubKey* pubkey) {
278 EpidStatus result;
279 EpidGroupPubKeyCertificate* buf_pubkey = (EpidGroupPubKeyCertificate*)buf;
280
281 if (!buf || !cert || !pubkey) {
282 return kEpidBadArgErr;
283 }
284
285 if (len == 0 || len % sizeof(EpidGroupPubKeyCertificate) != 0) {
286 return kEpidBadArgErr;
287 }
288
289 // Verify that Intel(R) EPID file header in the buffer is correct
290 if (0 != memcmp(&buf_pubkey->header.epid_version, &kEpidVersion,
291 sizeof(kEpidVersion))) {
292 return kEpidBadArgErr;
293 }
294 if (0 != memcmp(&buf_pubkey->header.file_type,
295 &kEpidFileTypeCode[kGroupPubKeyFile],
296 sizeof(buf_pubkey->header.file_type))) {
297 return kEpidBadArgErr;
298 }
299
300 // Verify that CA certificate is correct
301 result = EpidVerifyCaCertificate(cert);
302 if (kEpidNoErr != result) return result;
303
304 // Authenticate signature for buffer
305 result = EcdsaVerifyBuffer(
306 buf_pubkey, sizeof(EpidGroupPubKeyCertificate) - sizeof(EcdsaSignature),
307 (EcdsaPublicKey*)&cert->pubkey, &buf_pubkey->signature);
308 if (kEpidSigValid != result) return result;
309
310 // Copy public from the buffer to output
311 pubkey->gid = buf_pubkey->gid;
312 pubkey->h1 = buf_pubkey->h1;
313 pubkey->h2 = buf_pubkey->h2;
314 pubkey->w = buf_pubkey->w;
315
316 return kEpidNoErr;
317 }
318
EpidParsePrivRlFile(void const * buf,size_t len,EpidCaCertificate const * cert,PrivRl * rl,size_t * rl_len)319 EpidStatus EpidParsePrivRlFile(void const* buf, size_t len,
320 EpidCaCertificate const* cert, PrivRl* rl,
321 size_t* rl_len) {
322 return EpidParseRlFile(buf, len, cert, rl, rl_len, kPrivRlFile);
323 }
324
EpidParseSigRlFile(void const * buf,size_t len,EpidCaCertificate const * cert,SigRl * rl,size_t * rl_len)325 EpidStatus EpidParseSigRlFile(void const* buf, size_t len,
326 EpidCaCertificate const* cert, SigRl* rl,
327 size_t* rl_len) {
328 return EpidParseRlFile(buf, len, cert, rl, rl_len, kSigRlFile);
329 }
330
EpidParseGroupRlFile(void const * buf,size_t len,EpidCaCertificate const * cert,GroupRl * rl,size_t * rl_len)331 EpidStatus EpidParseGroupRlFile(void const* buf, size_t len,
332 EpidCaCertificate const* cert, GroupRl* rl,
333 size_t* rl_len) {
334 return EpidParseRlFile(buf, len, cert, rl, rl_len, kGroupRlFile);
335 }
336