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_ops.h"
     18 #include "atap_util.h"
     19 #include "libatap.h"
     20 
     21 static uint8_t session_shared_secret[ATAP_ECDH_SHARED_SECRET_LEN];
     22 static uint8_t session_key[ATAP_AES_128_KEY_LEN];
     23 static AtapOperation operation;
     24 
     25 static AtapResult auth_key_signature_generate(
     26     AtapOps* ops,
     27     uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],
     28     uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
     29     uint8_t** signature,
     30     uint32_t* signature_len) {
     31   AtapResult ret = 0;
     32   uint8_t nonce[ATAP_NONCE_LEN];
     33   *signature = (uint8_t*)atap_malloc(ATAP_SIGNATURE_LEN_MAX);
     34   if (*signature == NULL) {
     35     return ATAP_RESULT_ERROR_OOM;
     36   }
     37   /* deriving nonce uses same HKDF as deriving session key */
     38   ret = derive_session_key(ops,
     39                            device_pubkey,
     40                            ca_pubkey,
     41                            session_shared_secret,
     42                            "SIGN",
     43                            nonce,
     44                            ATAP_NONCE_LEN);
     45   if (ret != ATAP_RESULT_OK) {
     46     return ret;
     47   }
     48   return ops->auth_key_sign(
     49       ops, nonce, ATAP_NONCE_LEN, *signature, signature_len);
     50 }
     51 
     52 static AtapResult read_available_public_keys(
     53     AtapOps* ops, AtapInnerCaRequest* inner_ca_request) {
     54   AtapResult ret = 0;
     55 
     56   inner_ca_request->RSA_pubkey.data = (uint8_t*)atap_malloc(ATAP_KEY_LEN_MAX);
     57   inner_ca_request->RSA_pubkey.data_length = ATAP_KEY_LEN_MAX;
     58   inner_ca_request->ECDSA_pubkey.data = (uint8_t*)atap_malloc(ATAP_KEY_LEN_MAX);
     59   inner_ca_request->ECDSA_pubkey.data_length = ATAP_KEY_LEN_MAX;
     60   inner_ca_request->edDSA_pubkey.data = (uint8_t*)atap_malloc(ATAP_KEY_LEN_MAX);
     61   inner_ca_request->edDSA_pubkey.data_length = ATAP_KEY_LEN_MAX;
     62 
     63   if (inner_ca_request->RSA_pubkey.data == NULL ||
     64       inner_ca_request->ECDSA_pubkey.data == NULL ||
     65       inner_ca_request->edDSA_pubkey.data == NULL) {
     66     return ATAP_RESULT_ERROR_OOM;
     67   }
     68   ret = ops->read_attestation_public_key(
     69       ops,
     70       ATAP_KEY_TYPE_RSA,
     71       inner_ca_request->RSA_pubkey.data,
     72       &inner_ca_request->RSA_pubkey.data_length);
     73   if (ret != ATAP_RESULT_OK) {
     74     return ret;
     75   }
     76   ret = ops->read_attestation_public_key(
     77       ops,
     78       ATAP_KEY_TYPE_ECDSA,
     79       inner_ca_request->ECDSA_pubkey.data,
     80       &inner_ca_request->ECDSA_pubkey.data_length);
     81   if (ret != ATAP_RESULT_OK) {
     82     return ret;
     83   }
     84   ret = ops->read_attestation_public_key(
     85       ops,
     86       ATAP_KEY_TYPE_edDSA,
     87       inner_ca_request->edDSA_pubkey.data,
     88       &inner_ca_request->edDSA_pubkey.data_length);
     89   /* edDSA support is not required in the initial version */
     90   if (ret == ATAP_RESULT_ERROR_UNSUPPORTED_OPERATION) {
     91     atap_free(inner_ca_request->edDSA_pubkey.data);
     92     inner_ca_request->edDSA_pubkey.data = NULL;
     93     inner_ca_request->edDSA_pubkey.data_length = 0;
     94     ret = ATAP_RESULT_OK;
     95   }
     96   return ret;
     97 }
     98 
     99 static AtapResult initialize_session(AtapOps* ops,
    100                                      const uint8_t* operation_start,
    101                                      uint32_t operation_start_size,
    102                                      AtapKeyType* auth_key_type,
    103                                      uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
    104                                      AtapCaRequest* ca_request,
    105                                      AtapInnerCaRequest* inner_ca_request) {
    106   uint32_t message_length = 0;
    107   AtapCurveType curve_type = 0;
    108   AtapResult ret = 0;
    109   uint8_t* buf_ptr = (uint8_t*)operation_start + 4;
    110 
    111   atap_memset(ca_request, 0, sizeof(AtapCaRequest));
    112   atap_memset(inner_ca_request, 0, sizeof(AtapInnerCaRequest));
    113 
    114   if (operation_start_size != ATAP_OPERATION_START_LEN) {
    115     return ATAP_RESULT_ERROR_INVALID_INPUT;
    116   }
    117   if (operation_start[0] != ATAP_PROTOCOL_VERSION) {
    118     return ATAP_RESULT_ERROR_INVALID_INPUT;
    119   }
    120   copy_uint32_from_buf(&buf_ptr, &message_length);
    121   if (message_length != ATAP_ECDH_KEY_LEN + 2) {
    122     return ATAP_RESULT_ERROR_INVALID_INPUT;
    123   }
    124   curve_type = operation_start[ATAP_HEADER_LEN];
    125   operation = operation_start[ATAP_HEADER_LEN + 1];
    126   if (!validate_operation(operation)) {
    127     return ATAP_RESULT_ERROR_UNSUPPORTED_OPERATION;
    128   }
    129   if (!validate_curve(curve_type)) {
    130     return ATAP_RESULT_ERROR_UNSUPPORTED_ALGORITHM;
    131   }
    132 
    133   atap_memcpy(ca_pubkey, &operation_start[10], ATAP_ECDH_KEY_LEN);
    134 
    135   ret = ops->get_auth_key_type(ops, auth_key_type);
    136   if (ret != ATAP_RESULT_OK) {
    137     return ret;
    138   }
    139 
    140   ret = ops->ecdh_shared_secret_compute(ops,
    141                                         curve_type,
    142                                         ca_pubkey,
    143                                         ca_request->device_pubkey,
    144                                         session_shared_secret);
    145   if (ret != ATAP_RESULT_OK) {
    146     return ret;
    147   }
    148 
    149   return derive_session_key(ops,
    150                             ca_request->device_pubkey,
    151                             ca_pubkey,
    152                             session_shared_secret,
    153                             "KEY",
    154                             session_key,
    155                             ATAP_AES_128_KEY_LEN);
    156 }
    157 
    158 static AtapResult compute_auth_signature(
    159     AtapOps* ops,
    160     uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
    161     uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],
    162     AtapInnerCaRequest* inner_ca_request) {
    163   AtapResult ret = 0;
    164   /* read auth key cert chain */
    165   ret = ops->read_auth_key_cert_chain(ops,
    166                                       &inner_ca_request->auth_key_cert_chain);
    167   if (ret != ATAP_RESULT_OK) {
    168     return ret;
    169   }
    170   /* generate auth key signature */
    171   return auth_key_signature_generate(ops,
    172                                      device_pubkey,
    173                                      ca_pubkey,
    174                                      &inner_ca_request->signature.data,
    175                                      &inner_ca_request->signature.data_length);
    176 }
    177 
    178 static AtapResult read_product_id_hash(AtapOps* ops,
    179                                        AtapInnerCaRequest* inner_ca_request) {
    180   AtapResult ret = 0;
    181   uint8_t product_id[ATAP_PRODUCT_ID_LEN];
    182 
    183   ret = ops->read_product_id(ops, product_id);
    184   if (ret != ATAP_RESULT_OK) {
    185     return ret;
    186   }
    187   return ops->sha256(
    188       ops, product_id, ATAP_PRODUCT_ID_LEN, inner_ca_request->product_id_hash);
    189 }
    190 
    191 static AtapResult encrypt_inner_ca_request(
    192     AtapOps* ops,
    193     const AtapInnerCaRequest* inner_ca_request,
    194     AtapCaRequest* ca_request) {
    195   AtapResult ret = 0;
    196   uint32_t inner_ca_request_len = 0;
    197   uint8_t* inner_ca_request_buf = NULL;
    198 
    199   inner_ca_request_len = inner_ca_request_serialized_size(inner_ca_request);
    200   inner_ca_request_buf = (uint8_t*)atap_malloc(inner_ca_request_len);
    201   ca_request->encrypted_inner_ca_request.data =
    202       (uint8_t*)atap_malloc(inner_ca_request_len);
    203   ca_request->encrypted_inner_ca_request.data_length = inner_ca_request_len;
    204   if (inner_ca_request_buf == NULL ||
    205       ca_request->encrypted_inner_ca_request.data == NULL) {
    206     return ATAP_RESULT_ERROR_OOM;
    207   }
    208   append_inner_ca_request_to_buf(inner_ca_request_buf, inner_ca_request);
    209 
    210   /* generate IV */
    211   ret = ops->get_random_bytes(ops, ca_request->iv, ATAP_GCM_IV_LEN);
    212   if (ret != ATAP_RESULT_OK) {
    213     goto out;
    214   }
    215 
    216   /* encrypt inner CA request with shared key */
    217   ret = ops->aes_gcm_128_encrypt(ops,
    218                                  inner_ca_request_buf,
    219                                  inner_ca_request_len,
    220                                  ca_request->iv,
    221                                  session_key,
    222                                  ca_request->encrypted_inner_ca_request.data,
    223                                  ca_request->tag);
    224 out:
    225   atap_free(inner_ca_request_buf);
    226   return ret;
    227 }
    228 
    229 static AtapResult decrypt_encrypted_message(AtapOps* ops,
    230                                             const uint8_t* buf,
    231                                             uint32_t buf_size,
    232                                             uint8_t* key,
    233                                             uint8_t** plaintext,
    234                                             uint32_t* plaintext_len) {
    235   const uint8_t *iv = NULL, *tag = NULL, *ciphertext = NULL;
    236   uint32_t encrypted_len = 0;
    237   uint8_t* buf_ptr = (uint8_t*)buf + ATAP_HEADER_LEN;
    238 
    239   if (!validate_encrypted_message(buf, buf_size)) {
    240     return ATAP_RESULT_ERROR_INVALID_INPUT;
    241   }
    242 
    243   iv = buf_ptr;
    244   buf_ptr += ATAP_GCM_IV_LEN;
    245   copy_uint32_from_buf(&buf_ptr, &encrypted_len);
    246   ciphertext = buf_ptr;
    247   buf_ptr += encrypted_len;
    248   tag = buf_ptr;
    249 
    250   *plaintext = (uint8_t*)atap_malloc(encrypted_len);
    251   if (*plaintext == NULL) {
    252     return ATAP_RESULT_ERROR_OOM;
    253   }
    254   *plaintext_len = encrypted_len;
    255 
    256   return ops->aes_gcm_128_decrypt(
    257       ops, ciphertext, *plaintext_len, iv, session_key, tag, *plaintext);
    258 }
    259 
    260 static AtapResult write_attestation_data(AtapOps* ops,
    261                                          uint8_t** buf_ptr,
    262                                          AtapKeyType key_type) {
    263   AtapBlob key;
    264   AtapCertChain cert_chain;
    265   AtapResult ret = ATAP_RESULT_OK;
    266 
    267   atap_memset(&key, 0, sizeof(key));
    268   atap_memset(&cert_chain, 0, sizeof(cert_chain));
    269 
    270   if (!copy_cert_chain_from_buf(buf_ptr, &cert_chain)) {
    271     ret = ATAP_RESULT_ERROR_OOM;
    272     goto out;
    273   }
    274   if (!copy_blob_from_buf(buf_ptr, &key)) {
    275     ret = ATAP_RESULT_ERROR_OOM;
    276     goto out;
    277   }
    278   if (key.data_length == 0 && cert_chain.entry_count) {
    279     ret = ops->write_attestation_key(ops, key_type, NULL, &cert_chain);
    280   } else if (key.data_length && cert_chain.entry_count) {
    281     ret = ops->write_attestation_key(ops, key_type, &key, &cert_chain);
    282   } else if (key.data_length && cert_chain.entry_count == 0) {
    283     /* We never issue a key without a certificate chain */
    284     ret = ATAP_RESULT_ERROR_INVALID_INPUT;
    285   } else if (key_type != ATAP_KEY_TYPE_edDSA &&
    286              key_type != ATAP_KEY_TYPE_SPECIAL &&
    287              key_type != ATAP_KEY_TYPE_EPID) {
    288     /* edDSA, EPID, and special purpose key are optional in version 1*/
    289     ret = ATAP_RESULT_ERROR_INVALID_INPUT;
    290   }
    291 
    292 out:
    293   free_blob(key);
    294   free_cert_chain(cert_chain);
    295   return ret;
    296 }
    297 
    298 static AtapResult write_inner_ca_response(AtapOps* ops,
    299                                           uint8_t* inner_ca_resp_ptr,
    300                                           uint32_t inner_ca_resp_len) {
    301   AtapResult ret = 0;
    302   uint8_t** buf_ptr = &inner_ca_resp_ptr;
    303 
    304   if (!validate_inner_ca_response(
    305           inner_ca_resp_ptr, inner_ca_resp_len, operation)) {
    306     return ATAP_RESULT_ERROR_INVALID_INPUT;
    307   }
    308   ret = ops->write_hex_uuid(ops, &inner_ca_resp_ptr[ATAP_HEADER_LEN]);
    309   if (ret != ATAP_RESULT_OK) {
    310     return ret;
    311   }
    312   *buf_ptr += (ATAP_HEADER_LEN + ATAP_HEX_UUID_LEN);
    313   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_RSA);
    314   if (ret != ATAP_RESULT_OK) {
    315     return ret;
    316   }
    317   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_ECDSA);
    318   if (ret != ATAP_RESULT_OK) {
    319     return ret;
    320   }
    321   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_edDSA);
    322   /* Device may not support edDSA */
    323   if (ret != ATAP_RESULT_OK && ret != ATAP_RESULT_ERROR_UNSUPPORTED_ALGORITHM) {
    324     return ret;
    325   }
    326   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_EPID);
    327   if (ret != ATAP_RESULT_OK) {
    328     return ret;
    329   }
    330   /* Device may not support Special Cast key */
    331   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_SPECIAL);
    332   if (ret != ATAP_RESULT_OK) {
    333     return ret;
    334   }
    335   return ATAP_RESULT_OK;
    336 }
    337 
    338 AtapResult atap_get_ca_request(AtapOps* ops,
    339                                const uint8_t* operation_start,
    340                                uint32_t operation_start_size,
    341                                uint8_t** ca_request_p,
    342                                uint32_t* ca_request_size_p) {
    343   AtapResult ret = 0;
    344   AtapKeyType auth_key_type = 0;
    345   AtapCaRequest ca_request;
    346   AtapInnerCaRequest inner_ca_request;
    347   uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN];
    348 
    349   ret = initialize_session(ops,
    350                            operation_start,
    351                            operation_start_size,
    352                            &auth_key_type,
    353                            ca_pubkey,
    354                            &ca_request,
    355                            &inner_ca_request);
    356   if (ret != ATAP_RESULT_OK) {
    357     goto err;
    358   }
    359 
    360   if (auth_key_type != ATAP_KEY_TYPE_NONE) {
    361     ret = compute_auth_signature(
    362         ops, ca_pubkey, ca_request.device_pubkey, &inner_ca_request);
    363     if (ret != ATAP_RESULT_OK) {
    364       goto err;
    365     }
    366   }
    367 
    368   if (operation == ATAP_OPERATION_CERTIFY) {
    369     ret = read_available_public_keys(ops, &inner_ca_request);
    370     if (ret != ATAP_RESULT_OK) {
    371       goto err;
    372     }
    373   }
    374 
    375   ret = read_product_id_hash(ops, &inner_ca_request);
    376   if (ret != ATAP_RESULT_OK) {
    377     goto err;
    378   }
    379 
    380   ret = encrypt_inner_ca_request(ops, &inner_ca_request, &ca_request);
    381   if (ret != ATAP_RESULT_OK) {
    382     goto err;
    383   }
    384 
    385   *ca_request_size_p = ca_request_serialized_size(&ca_request);
    386   *ca_request_p = (uint8_t*)atap_malloc(*ca_request_size_p);
    387   if (*ca_request_p == NULL) {
    388     *ca_request_size_p = 0;
    389     ret = ATAP_RESULT_ERROR_OOM;
    390     goto err;
    391   }
    392   append_ca_request_to_buf(*ca_request_p, &ca_request);
    393   goto out;
    394 
    395 err:
    396   /* clear global secrets */
    397   atap_memset(session_shared_secret, 0, ATAP_ECDH_SHARED_SECRET_LEN);
    398   atap_memset(session_key, 0, ATAP_AES_128_KEY_LEN);
    399   *ca_request_p = NULL;
    400   *ca_request_size_p = 0;
    401 out:
    402   free_inner_ca_request(inner_ca_request);
    403   free_ca_request(ca_request);
    404   return ret;
    405 }
    406 
    407 AtapResult atap_set_ca_response(AtapOps* ops,
    408                                 const uint8_t* ca_response,
    409                                 uint32_t ca_response_size) {
    410   AtapResult ret = 0;
    411   uint8_t* inner_ca_resp = NULL;
    412   uint8_t* inner_inner_ca_resp = NULL;
    413   uint8_t* inner_ca_resp_ptr = NULL;
    414   uint32_t inner_ca_resp_len = 0;
    415   uint32_t inner_inner_ca_resp_len = 0;
    416   uint8_t soc_global_key[ATAP_AES_128_KEY_LEN];
    417 
    418   ret = decrypt_encrypted_message(ops,
    419                                   ca_response,
    420                                   ca_response_size,
    421                                   session_key,
    422                                   &inner_ca_resp,
    423                                   &inner_ca_resp_len);
    424   if (ret != ATAP_RESULT_OK) {
    425     goto out;
    426   }
    427   inner_ca_resp_ptr = inner_ca_resp;
    428   if (operation == ATAP_OPERATION_ISSUE_ENCRYPTED) {
    429     /* Decrypt Encrypted Inner CA Response (encrypted) with SoC global key */
    430     ret = ops->read_soc_global_key(ops, soc_global_key);
    431     if (ret != ATAP_RESULT_OK) {
    432       goto out;
    433     }
    434     ret = decrypt_encrypted_message(ops,
    435                                     inner_ca_resp,
    436                                     inner_ca_resp_len,
    437                                     soc_global_key,
    438                                     &inner_inner_ca_resp,
    439                                     &inner_inner_ca_resp_len);
    440     if (ret != ATAP_RESULT_OK) {
    441       goto out;
    442     }
    443     inner_ca_resp_ptr = inner_inner_ca_resp;
    444     inner_ca_resp_len = inner_inner_ca_resp_len;
    445   }
    446   ret = write_inner_ca_response(ops, inner_ca_resp_ptr, inner_ca_resp_len);
    447 
    448 out:
    449   if (inner_ca_resp) {
    450     atap_free(inner_ca_resp);
    451   }
    452   if (inner_inner_ca_resp) {
    453     atap_free(inner_inner_ca_resp);
    454   }
    455   return ret;
    456 }
    457