Home | History | Annotate | Download | only in src
      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