Home | History | Annotate | Download | only in libatap
      1 /*
      2  * Copyright 2017 The Android Open Source Project
      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 #include "atap_util.h"
     18 
     19 #include "atap_ops.h"
     20 
     21 const char* atap_basename(const char* str) {
     22   int64_t n = 0;
     23   size_t len = atap_strlen(str);
     24 
     25   if (len >= 2) {
     26     for (n = len - 2; n >= 0; n--) {
     27       if (str[n] == '/') {
     28         return str + n + 1;
     29       }
     30     }
     31   }
     32   return str;
     33 }
     34 
     35 uint8_t* append_to_buf(uint8_t* buf, const void* data, uint32_t data_size) {
     36   atap_memcpy(buf, data, data_size);
     37   return buf + data_size;
     38 }
     39 
     40 uint8_t* append_uint32_to_buf(uint8_t* buf, uint32_t x) {
     41   return append_to_buf(buf, &x, sizeof(uint32_t));
     42 }
     43 
     44 uint8_t* append_header_to_buf(uint8_t* buf, uint32_t message_length) {
     45   buf[0] = ATAP_PROTOCOL_VERSION;
     46   atap_memset(&buf[1], 0, 3);  // reserved
     47   buf += 4;
     48   return append_uint32_to_buf(buf, message_length);
     49 }
     50 
     51 uint8_t* append_blob_to_buf(uint8_t* buf, const AtapBlob* blob) {
     52   atap_assert(blob->data_length == 0 || blob->data);
     53   buf = append_uint32_to_buf(buf, blob->data_length);
     54   if (blob->data_length > 0) {
     55     buf = append_to_buf(buf, blob->data, blob->data_length);
     56   }
     57   return buf;
     58 }
     59 
     60 uint8_t* append_cert_chain_to_buf(uint8_t* buf,
     61                                   const AtapCertChain* cert_chain) {
     62   uint32_t cert_chain_size =
     63       cert_chain_serialized_size(cert_chain) - sizeof(uint32_t);
     64   uint32_t i = 0;
     65   uint8_t* local_buf = buf;
     66 
     67   /* Append size of cert chain, as it is a Variable field. */
     68   local_buf = append_uint32_to_buf(local_buf, cert_chain_size);
     69 
     70   for (i = 0; i < cert_chain->entry_count; ++i) {
     71     local_buf = append_blob_to_buf(local_buf, &cert_chain->entries[i]);
     72   }
     73   atap_assert(local_buf == (buf + cert_chain_size + sizeof(uint32_t)));
     74   return local_buf;
     75 }
     76 
     77 uint8_t* append_ca_request_to_buf(uint8_t* buf,
     78                                   const AtapCaRequest* ca_request) {
     79   uint32_t ca_request_len = ca_request_serialized_size(ca_request);
     80 
     81   buf = append_header_to_buf(buf, ca_request_len - ATAP_HEADER_LEN);
     82   buf = append_to_buf(buf, ca_request->device_pubkey, ATAP_ECDH_KEY_LEN);
     83   buf = append_to_buf(buf, ca_request->iv, ATAP_GCM_IV_LEN);
     84   buf = append_blob_to_buf(buf, &ca_request->encrypted_inner_ca_request);
     85   return append_to_buf(buf, ca_request->tag, ATAP_GCM_TAG_LEN);
     86 }
     87 
     88 uint8_t* append_inner_ca_request_to_buf(
     89     uint8_t* buf, const AtapInnerCaRequest* inner_ca_request) {
     90   uint32_t inner_ca_request_len =
     91       inner_ca_request_serialized_size(inner_ca_request);
     92 
     93   buf = append_header_to_buf(buf, inner_ca_request_len - ATAP_HEADER_LEN);
     94   buf = append_cert_chain_to_buf(buf, &inner_ca_request->auth_key_cert_chain);
     95   buf = append_blob_to_buf(buf, &inner_ca_request->signature);
     96   buf = append_to_buf(
     97       buf, inner_ca_request->product_id_hash, ATAP_SHA256_DIGEST_LEN);
     98   buf = append_blob_to_buf(buf, &inner_ca_request->RSA_pubkey);
     99   buf = append_blob_to_buf(buf, &inner_ca_request->ECDSA_pubkey);
    100   return append_blob_to_buf(buf, &inner_ca_request->edDSA_pubkey);
    101 }
    102 
    103 void copy_from_buf(uint8_t** buf_ptr, void* data, uint32_t data_size) {
    104   atap_memcpy(data, *buf_ptr, data_size);
    105   *buf_ptr += data_size;
    106 }
    107 
    108 void copy_uint32_from_buf(uint8_t** buf_ptr, uint32_t* x) {
    109   copy_from_buf(buf_ptr, x, sizeof(uint32_t));
    110 }
    111 
    112 bool copy_blob_from_buf(uint8_t** buf_ptr, AtapBlob* blob) {
    113   atap_memset(blob, 0, sizeof(AtapBlob));
    114   copy_uint32_from_buf(buf_ptr, &blob->data_length);
    115   if (blob->data_length > ATAP_BLOB_LEN_MAX) {
    116     return false;
    117   }
    118   if (blob->data_length) {
    119     blob->data = (uint8_t*)atap_malloc(blob->data_length);
    120     if (blob->data == NULL) {
    121       return false;
    122     }
    123     copy_from_buf(buf_ptr, blob->data, blob->data_length);
    124   }
    125   return true;
    126 }
    127 
    128 bool copy_cert_chain_from_buf(uint8_t** buf_ptr, AtapCertChain* cert_chain) {
    129   uint32_t cert_chain_size = 0;
    130   int32_t bytes_remaining = 0;
    131   size_t i = 0;
    132   bool retval = true;
    133 
    134   atap_memset(cert_chain, 0, sizeof(AtapCertChain));
    135 
    136   /* Copy size of cert chain, as it is a Variable field. */
    137   copy_from_buf(buf_ptr, &cert_chain_size, sizeof(cert_chain_size));
    138 
    139   if (cert_chain_size > ATAP_CERT_CHAIN_LEN_MAX) {
    140     return false;
    141   }
    142   if (cert_chain_size == 0) {
    143     return true;
    144   }
    145   bytes_remaining = cert_chain_size;
    146   for (i = 0; i < ATAP_CERT_CHAIN_ENTRIES_MAX; ++i) {
    147     if (!copy_blob_from_buf(buf_ptr, &cert_chain->entries[i])) {
    148       retval = false;
    149       break;
    150     }
    151     ++cert_chain->entry_count;
    152     bytes_remaining -= (sizeof(uint32_t) + cert_chain->entries[i].data_length);
    153     if (bytes_remaining <= 0) {
    154       retval = (bytes_remaining == 0);
    155       break;
    156     }
    157   }
    158   if (retval == false) {
    159     free_cert_chain(*cert_chain);
    160   }
    161   return retval;
    162 }
    163 
    164 uint32_t blob_serialized_size(const AtapBlob* blob) {
    165   return sizeof(uint32_t) + blob->data_length;
    166 }
    167 
    168 uint32_t cert_chain_serialized_size(const AtapCertChain* cert_chain) {
    169   uint32_t size = sizeof(uint32_t);
    170   uint32_t i = 0;
    171 
    172   for (i = 0; i < cert_chain->entry_count; ++i) {
    173     size += sizeof(uint32_t) + cert_chain->entries[i].data_length;
    174   }
    175   return size;
    176 }
    177 
    178 uint32_t ca_request_serialized_size(const AtapCaRequest* ca_request) {
    179   uint32_t size =
    180       ATAP_HEADER_LEN + ATAP_ECDH_KEY_LEN + ATAP_GCM_IV_LEN + ATAP_GCM_TAG_LEN;
    181 
    182   size += blob_serialized_size(&ca_request->encrypted_inner_ca_request);
    183   return size;
    184 }
    185 
    186 uint32_t inner_ca_request_serialized_size(
    187     const AtapInnerCaRequest* inner_ca_request) {
    188   uint32_t size = ATAP_HEADER_LEN + ATAP_SHA256_DIGEST_LEN;
    189 
    190   size += cert_chain_serialized_size(&inner_ca_request->auth_key_cert_chain);
    191   size += blob_serialized_size(&inner_ca_request->signature);
    192   size += blob_serialized_size(&inner_ca_request->RSA_pubkey);
    193   size += blob_serialized_size(&inner_ca_request->ECDSA_pubkey);
    194   size += blob_serialized_size(&inner_ca_request->edDSA_pubkey);
    195   return size;
    196 }
    197 
    198 void free_blob(AtapBlob blob) {
    199   if (blob.data) {
    200     atap_free(blob.data);
    201   }
    202   blob.data_length = 0;
    203 }
    204 
    205 void free_cert_chain(AtapCertChain cert_chain) {
    206   unsigned int i = 0;
    207 
    208   for (i = 0; i < cert_chain.entry_count; ++i) {
    209     if (cert_chain.entries[i].data) {
    210       atap_free(cert_chain.entries[i].data);
    211     }
    212     cert_chain.entries[i].data_length = 0;
    213   }
    214   atap_memset(&cert_chain, 0, sizeof(AtapCertChain));
    215 }
    216 
    217 void free_ca_request(AtapCaRequest ca_request) {
    218   free_blob(ca_request.encrypted_inner_ca_request);
    219 }
    220 
    221 void free_inner_ca_request(AtapInnerCaRequest inner_ca_request) {
    222   free_cert_chain(inner_ca_request.auth_key_cert_chain);
    223   free_blob(inner_ca_request.signature);
    224   free_blob(inner_ca_request.RSA_pubkey);
    225   free_blob(inner_ca_request.ECDSA_pubkey);
    226   free_blob(inner_ca_request.edDSA_pubkey);
    227 }
    228 
    229 bool validate_operation(AtapOperation operation) {
    230   if (operation != ATAP_OPERATION_CERTIFY &&
    231       operation != ATAP_OPERATION_ISSUE &&
    232       operation != ATAP_OPERATION_ISSUE_ENCRYPTED) {
    233     return false;
    234   }
    235   return true;
    236 }
    237 
    238 bool validate_curve(AtapCurveType curve) {
    239   if (curve != ATAP_CURVE_TYPE_P256 && curve != ATAP_CURVE_TYPE_X25519) {
    240     return false;
    241   }
    242   return true;
    243 }
    244 
    245 bool validate_encrypted_message(const uint8_t* buf, uint32_t buf_size) {
    246   uint32_t encrypted_len, message_len;
    247   uint8_t* buf_ptr = (uint8_t*)buf;
    248 
    249   if (buf_size <
    250       ATAP_HEADER_LEN + ATAP_GCM_IV_LEN + sizeof(uint32_t) + ATAP_GCM_TAG_LEN) {
    251     return false;
    252   }
    253   if (buf[0] != ATAP_PROTOCOL_VERSION) {
    254     return false;
    255   }
    256   buf_ptr += 4;
    257   copy_uint32_from_buf(&buf_ptr, &message_len);
    258   if (message_len != buf_size - ATAP_HEADER_LEN) {
    259     return false;
    260   }
    261   buf_ptr += ATAP_GCM_IV_LEN;
    262   copy_uint32_from_buf(&buf_ptr, &encrypted_len);
    263   if (encrypted_len !=
    264       message_len - ATAP_GCM_IV_LEN - sizeof(uint32_t) - ATAP_GCM_TAG_LEN) {
    265     return false;
    266   }
    267   return true;
    268 }
    269 
    270 bool validate_inner_ca_response(const uint8_t* buf,
    271                                 uint32_t buf_size,
    272                                 AtapOperation operation) {
    273   uint32_t cert_chain_len = 0, len = 0;
    274   size_t i = 0;
    275   int tmp = 0;
    276   uint8_t* buf_ptr = (uint8_t*)buf;
    277 
    278   if (buf_size < ATAP_HEADER_LEN + ATAP_HEX_UUID_LEN +
    279                      ATAP_INNER_CA_RESPONSE_FIELDS * sizeof(uint32_t)) {
    280     return false;
    281   }
    282   if (buf[0] != ATAP_PROTOCOL_VERSION) {
    283     return false;
    284   }
    285   buf_ptr += 4;
    286   copy_uint32_from_buf(&buf_ptr, &len);
    287   if (len != buf_size - ATAP_HEADER_LEN) {
    288     return false;
    289   }
    290   buf_ptr += ATAP_HEX_UUID_LEN;
    291   for (i = 0; i < ATAP_INNER_CA_RESPONSE_FIELDS; ++i) {
    292     /* Odd indices are private keys */
    293     if (i % 2) {
    294       copy_uint32_from_buf(&buf_ptr, &len);
    295       /* Product keys (non special purpose) are omitted on certify operation. */
    296       if (operation == ATAP_OPERATION_CERTIFY &&
    297           i != ATAP_INNER_CA_RESPONSE_FIELDS - 1 && len != 0) {
    298         return false;
    299       }
    300       if (len > ATAP_KEY_LEN_MAX) {
    301         return false;
    302       }
    303       buf_ptr += len;
    304     } else {
    305       copy_uint32_from_buf(&buf_ptr, &cert_chain_len);
    306       if (cert_chain_len > ATAP_CERT_CHAIN_LEN_MAX) {
    307         return false;
    308       }
    309       tmp = cert_chain_len;
    310       while (tmp) {
    311         copy_uint32_from_buf(&buf_ptr, &len);
    312         if (len > ATAP_CERT_LEN_MAX) {
    313           return false;
    314         }
    315         buf_ptr += len;
    316         tmp -= (sizeof(uint32_t) + len);
    317         /* Length value list was not constructed correctly. */
    318         if (tmp < 0) {
    319           return false;
    320         }
    321       }
    322     }
    323   }
    324   if (buf_ptr != buf + buf_size) {
    325     return false;
    326   }
    327   return true;
    328 }
    329 
    330 AtapResult derive_session_key(
    331     AtapOps* ops,
    332     const uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],
    333     const uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
    334     const uint8_t shared_secret[ATAP_ECDH_SHARED_SECRET_LEN],
    335     const char* info,
    336     uint8_t* okm,
    337     uint32_t okm_len) {
    338   uint8_t salt[2 * ATAP_ECDH_KEY_LEN];
    339 
    340   atap_memcpy(salt, ca_pubkey, ATAP_ECDH_KEY_LEN);
    341   atap_memcpy(salt + ATAP_ECDH_KEY_LEN, device_pubkey, ATAP_ECDH_KEY_LEN);
    342 
    343   return ops->hkdf_sha256(ops,
    344                           salt,
    345                           sizeof(salt),
    346                           shared_secret,
    347                           ATAP_ECDH_SHARED_SECRET_LEN,
    348                           (const uint8_t*)info,
    349                           atap_strlen(info),
    350                           okm,
    351                           okm_len);
    352 }
    353