• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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