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 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 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 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 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 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 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 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