Home | History | Annotate | Download | only in common
      1 //
      2 // Copyright (C) 2015 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 "attestation/common/crypto_utility_impl.h"
     18 
     19 #include <limits>
     20 #include <string>
     21 
     22 #include <arpa/inet.h>
     23 #include <base/sha1.h>
     24 #include <base/stl_util.h>
     25 #include <crypto/scoped_openssl_types.h>
     26 #include <crypto/secure_util.h>
     27 #include <crypto/sha2.h>
     28 #include <openssl/bio.h>
     29 #include <openssl/err.h>
     30 #include <openssl/evp.h>
     31 #include <openssl/hmac.h>
     32 #include <openssl/rand.h>
     33 #include <openssl/rsa.h>
     34 #include <openssl/sha.h>
     35 #include <openssl/x509.h>
     36 
     37 namespace {
     38 
     39 const size_t kAesKeySize = 32;
     40 const size_t kAesBlockSize = 16;
     41 
     42 std::string GetOpenSSLError() {
     43   BIO* bio = BIO_new(BIO_s_mem());
     44   ERR_print_errors(bio);
     45   char* data = nullptr;
     46   int data_len = BIO_get_mem_data(bio, &data);
     47   std::string error_string(data, data_len);
     48   BIO_free(bio);
     49   return error_string;
     50 }
     51 
     52 unsigned char* StringAsOpenSSLBuffer(std::string* s) {
     53   return reinterpret_cast<unsigned char*>(string_as_array(s));
     54 }
     55 
     56 }  // namespace
     57 
     58 namespace attestation {
     59 
     60 CryptoUtilityImpl::CryptoUtilityImpl(TpmUtility* tpm_utility)
     61     : tpm_utility_(tpm_utility) {
     62   OpenSSL_add_all_algorithms();
     63   ERR_load_crypto_strings();
     64 }
     65 
     66 CryptoUtilityImpl::~CryptoUtilityImpl() {
     67   EVP_cleanup();
     68   ERR_free_strings();
     69 }
     70 
     71 bool CryptoUtilityImpl::GetRandom(size_t num_bytes,
     72                                   std::string* random_data) const {
     73   // OpenSSL takes a signed integer.
     74   if (num_bytes > static_cast<size_t>(std::numeric_limits<int>::max())) {
     75     return false;
     76   }
     77   random_data->resize(num_bytes);
     78   unsigned char* buffer = StringAsOpenSSLBuffer(random_data);
     79   return (RAND_bytes(buffer, num_bytes) == 1);
     80 }
     81 
     82 bool CryptoUtilityImpl::CreateSealedKey(std::string* aes_key,
     83                                         std::string* sealed_key) {
     84   if (!GetRandom(kAesKeySize, aes_key)) {
     85     LOG(ERROR) << __func__ << ": GetRandom failed.";
     86     return false;
     87   }
     88   if (!tpm_utility_->SealToPCR0(*aes_key, sealed_key)) {
     89     LOG(ERROR) << __func__ << ": Failed to seal cipher key.";
     90     return false;
     91   }
     92   return true;
     93 }
     94 
     95 bool CryptoUtilityImpl::EncryptData(const std::string& data,
     96                                     const std::string& aes_key,
     97                                     const std::string& sealed_key,
     98                                     std::string* encrypted_data) {
     99   std::string iv;
    100   if (!GetRandom(kAesBlockSize, &iv)) {
    101     LOG(ERROR) << __func__ << ": GetRandom failed.";
    102     return false;
    103   }
    104   std::string raw_encrypted_data;
    105   if (!AesEncrypt(data, aes_key, iv, &raw_encrypted_data)) {
    106     LOG(ERROR) << __func__ << ": AES encryption failed.";
    107     return false;
    108   }
    109   EncryptedData encrypted_pb;
    110   encrypted_pb.set_wrapped_key(sealed_key);
    111   encrypted_pb.set_iv(iv);
    112   encrypted_pb.set_encrypted_data(raw_encrypted_data);
    113   encrypted_pb.set_mac(HmacSha512(iv + raw_encrypted_data, aes_key));
    114   if (!encrypted_pb.SerializeToString(encrypted_data)) {
    115     LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    116     return false;
    117   }
    118   return true;
    119 }
    120 
    121 bool CryptoUtilityImpl::UnsealKey(const std::string& encrypted_data,
    122                                   std::string* aes_key,
    123                                   std::string* sealed_key) {
    124   EncryptedData encrypted_pb;
    125   if (!encrypted_pb.ParseFromString(encrypted_data)) {
    126     LOG(ERROR) << __func__ << ": Failed to parse protobuf.";
    127     return false;
    128   }
    129   *sealed_key = encrypted_pb.wrapped_key();
    130   if (!tpm_utility_->Unseal(*sealed_key, aes_key)) {
    131     LOG(ERROR) << __func__ << ": Cannot unseal aes key.";
    132     return false;
    133   }
    134   return true;
    135 }
    136 
    137 bool CryptoUtilityImpl::DecryptData(const std::string& encrypted_data,
    138                                     const std::string& aes_key,
    139                                     std::string* data) {
    140   EncryptedData encrypted_pb;
    141   if (!encrypted_pb.ParseFromString(encrypted_data)) {
    142     LOG(ERROR) << __func__ << ": Failed to parse protobuf.";
    143     return false;
    144   }
    145   std::string mac =
    146       HmacSha512(encrypted_pb.iv() + encrypted_pb.encrypted_data(), aes_key);
    147   if (mac.length() != encrypted_pb.mac().length()) {
    148     LOG(ERROR) << __func__ << ": Corrupted data in encrypted pb.";
    149     return false;
    150   }
    151   if (!crypto::SecureMemEqual(mac.data(), encrypted_pb.mac().data(),
    152                               mac.length())) {
    153     LOG(ERROR) << __func__ << ": Corrupted data in encrypted pb.";
    154     return false;
    155   }
    156   if (!AesDecrypt(encrypted_pb.encrypted_data(), aes_key, encrypted_pb.iv(),
    157                   data)) {
    158     LOG(ERROR) << __func__ << ": AES decryption failed.";
    159     return false;
    160   }
    161   return true;
    162 }
    163 
    164 bool CryptoUtilityImpl::GetRSASubjectPublicKeyInfo(
    165     const std::string& public_key,
    166     std::string* public_key_info) {
    167   auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
    168   crypto::ScopedRSA rsa(
    169       d2i_RSAPublicKey(nullptr, &asn1_ptr, public_key.size()));
    170   if (!rsa.get()) {
    171     LOG(ERROR) << __func__
    172                << ": Failed to decode public key: " << GetOpenSSLError();
    173     return false;
    174   }
    175   unsigned char* buffer = nullptr;
    176   int length = i2d_RSA_PUBKEY(rsa.get(), &buffer);
    177   if (length <= 0) {
    178     LOG(ERROR) << __func__
    179                << ": Failed to encode public key: " << GetOpenSSLError();
    180     return false;
    181   }
    182   crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
    183   public_key_info->assign(reinterpret_cast<char*>(buffer), length);
    184   return true;
    185 }
    186 
    187 bool CryptoUtilityImpl::GetRSAPublicKey(const std::string& public_key_info,
    188                                         std::string* public_key) {
    189   auto asn1_ptr =
    190       reinterpret_cast<const unsigned char*>(public_key_info.data());
    191   crypto::ScopedRSA rsa(
    192       d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key_info.size()));
    193   if (!rsa.get()) {
    194     LOG(ERROR) << __func__
    195                << ": Failed to decode public key: " << GetOpenSSLError();
    196     return false;
    197   }
    198   unsigned char* buffer = NULL;
    199   int length = i2d_RSAPublicKey(rsa.get(), &buffer);
    200   if (length <= 0) {
    201     LOG(ERROR) << __func__
    202                << ": Failed to encode public key: " << GetOpenSSLError();
    203     return false;
    204   }
    205   crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
    206   public_key->assign(reinterpret_cast<char*>(buffer), length);
    207   return true;
    208 }
    209 
    210 bool CryptoUtilityImpl::EncryptIdentityCredential(
    211     const std::string& credential,
    212     const std::string& ek_public_key_info,
    213     const std::string& aik_public_key,
    214     EncryptedIdentityCredential* encrypted) {
    215   const char kAlgAES256 = 9;   // This comes from TPM_ALG_AES256.
    216   const char kEncModeCBC = 2;  // This comes from TPM_SYM_MODE_CBC.
    217   const char kAsymContentHeader[] = {0, 0,           0, kAlgAES256,
    218                                      0, kEncModeCBC, 0, kAesKeySize};
    219   const char kSymContentHeader[12] = {};
    220 
    221   // Generate an AES key and encrypt the credential.
    222   std::string aes_key;
    223   if (!GetRandom(kAesKeySize, &aes_key)) {
    224     LOG(ERROR) << __func__ << ": GetRandom failed.";
    225     return false;
    226   }
    227   std::string encrypted_credential;
    228   if (!TssCompatibleEncrypt(credential, aes_key, &encrypted_credential)) {
    229     LOG(ERROR) << __func__ << ": Failed to encrypt credential.";
    230     return false;
    231   }
    232 
    233   // Construct a TPM_ASYM_CA_CONTENTS structure.
    234   std::string asym_header(std::begin(kAsymContentHeader),
    235                           std::end(kAsymContentHeader));
    236   std::string asym_content =
    237       asym_header + aes_key + base::SHA1HashString(aik_public_key);
    238 
    239   // Encrypt the TPM_ASYM_CA_CONTENTS with the EK public key.
    240   auto asn1_ptr =
    241       reinterpret_cast<const unsigned char*>(ek_public_key_info.data());
    242   crypto::ScopedRSA rsa(
    243       d2i_RSA_PUBKEY(NULL, &asn1_ptr, ek_public_key_info.size()));
    244   if (!rsa.get()) {
    245     LOG(ERROR) << __func__
    246                << ": Failed to decode EK public key: " << GetOpenSSLError();
    247     return false;
    248   }
    249   std::string encrypted_asym_content;
    250   if (!TpmCompatibleOAEPEncrypt(asym_content, rsa.get(),
    251                                 &encrypted_asym_content)) {
    252     LOG(ERROR) << __func__ << ": Failed to encrypt with EK public key.";
    253     return false;
    254   }
    255 
    256   // Construct a TPM_SYM_CA_ATTESTATION structure.
    257   uint32_t length = htonl(encrypted_credential.size());
    258   auto length_bytes = reinterpret_cast<const char*>(&length);
    259   std::string length_blob(length_bytes, sizeof(uint32_t));
    260   std::string sym_header(std::begin(kSymContentHeader),
    261                          std::end(kSymContentHeader));
    262   std::string sym_content = length_blob + sym_header + encrypted_credential;
    263 
    264   encrypted->set_asym_ca_contents(encrypted_asym_content);
    265   encrypted->set_sym_ca_attestation(sym_content);
    266   return true;
    267 }
    268 
    269 bool CryptoUtilityImpl::EncryptForUnbind(const std::string& public_key,
    270                                          const std::string& data,
    271                                          std::string* encrypted_data) {
    272   // Construct a TPM_BOUND_DATA structure.
    273   const char kBoundDataHeader[] = {1, 1, 0, 0, 2 /* TPM_PT_BIND */};
    274   std::string header(std::begin(kBoundDataHeader), std::end(kBoundDataHeader));
    275   std::string bound_data = header + data;
    276 
    277   // Encrypt using the TPM_ES_RSAESOAEP_SHA1_MGF1 scheme.
    278   auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
    279   crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
    280   if (!rsa.get()) {
    281     LOG(ERROR) << __func__
    282                << ": Failed to decode public key: " << GetOpenSSLError();
    283     return false;
    284   }
    285   if (!TpmCompatibleOAEPEncrypt(bound_data, rsa.get(), encrypted_data)) {
    286     LOG(ERROR) << __func__ << ": Failed to encrypt with public key.";
    287     return false;
    288   }
    289   return true;
    290 }
    291 
    292 bool CryptoUtilityImpl::VerifySignature(const std::string& public_key,
    293                                         const std::string& data,
    294                                         const std::string& signature) {
    295   auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
    296   crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
    297   if (!rsa.get()) {
    298     LOG(ERROR) << __func__
    299                << ": Failed to decode public key: " << GetOpenSSLError();
    300     return false;
    301   }
    302   std::string digest = crypto::SHA256HashString(data);
    303   auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data());
    304   std::string mutable_signature(signature);
    305   unsigned char* signature_buffer = StringAsOpenSSLBuffer(&mutable_signature);
    306   return (RSA_verify(NID_sha256, digest_buffer, digest.size(), signature_buffer,
    307                      signature.size(), rsa.get()) == 1);
    308 }
    309 
    310 bool CryptoUtilityImpl::AesEncrypt(const std::string& data,
    311                                    const std::string& key,
    312                                    const std::string& iv,
    313                                    std::string* encrypted_data) {
    314   if (key.size() != kAesKeySize || iv.size() != kAesBlockSize) {
    315     return false;
    316   }
    317   if (data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
    318     // EVP_EncryptUpdate takes a signed int.
    319     return false;
    320   }
    321   std::string mutable_data(data);
    322   unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_data);
    323   std::string mutable_key(key);
    324   unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
    325   std::string mutable_iv(iv);
    326   unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
    327   // Allocate enough space for the output (including padding).
    328   encrypted_data->resize(data.size() + kAesBlockSize);
    329   auto output_buffer =
    330       reinterpret_cast<unsigned char*>(string_as_array(encrypted_data));
    331   int output_size = 0;
    332   const EVP_CIPHER* cipher = EVP_aes_256_cbc();
    333   EVP_CIPHER_CTX encryption_context;
    334   EVP_CIPHER_CTX_init(&encryption_context);
    335   if (!EVP_EncryptInit_ex(&encryption_context, cipher, nullptr, key_buffer,
    336                           iv_buffer)) {
    337     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    338     return false;
    339   }
    340   if (!EVP_EncryptUpdate(&encryption_context, output_buffer, &output_size,
    341                          input_buffer, data.size())) {
    342     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    343     EVP_CIPHER_CTX_cleanup(&encryption_context);
    344     return false;
    345   }
    346   size_t total_size = output_size;
    347   output_buffer += output_size;
    348   output_size = 0;
    349   if (!EVP_EncryptFinal_ex(&encryption_context, output_buffer, &output_size)) {
    350     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    351     EVP_CIPHER_CTX_cleanup(&encryption_context);
    352     return false;
    353   }
    354   total_size += output_size;
    355   encrypted_data->resize(total_size);
    356   EVP_CIPHER_CTX_cleanup(&encryption_context);
    357   return true;
    358 }
    359 
    360 bool CryptoUtilityImpl::AesDecrypt(const std::string& encrypted_data,
    361                                    const std::string& key,
    362                                    const std::string& iv,
    363                                    std::string* data) {
    364   if (key.size() != kAesKeySize || iv.size() != kAesBlockSize) {
    365     return false;
    366   }
    367   if (encrypted_data.size() >
    368       static_cast<size_t>(std::numeric_limits<int>::max())) {
    369     // EVP_DecryptUpdate takes a signed int.
    370     return false;
    371   }
    372   std::string mutable_encrypted_data(encrypted_data);
    373   unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_encrypted_data);
    374   std::string mutable_key(key);
    375   unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
    376   std::string mutable_iv(iv);
    377   unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
    378   // Allocate enough space for the output.
    379   data->resize(encrypted_data.size());
    380   unsigned char* output_buffer = StringAsOpenSSLBuffer(data);
    381   int output_size = 0;
    382   const EVP_CIPHER* cipher = EVP_aes_256_cbc();
    383   EVP_CIPHER_CTX decryption_context;
    384   EVP_CIPHER_CTX_init(&decryption_context);
    385   if (!EVP_DecryptInit_ex(&decryption_context, cipher, nullptr, key_buffer,
    386                           iv_buffer)) {
    387     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    388     return false;
    389   }
    390   if (!EVP_DecryptUpdate(&decryption_context, output_buffer, &output_size,
    391                          input_buffer, encrypted_data.size())) {
    392     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    393     EVP_CIPHER_CTX_cleanup(&decryption_context);
    394     return false;
    395   }
    396   size_t total_size = output_size;
    397   output_buffer += output_size;
    398   output_size = 0;
    399   if (!EVP_DecryptFinal_ex(&decryption_context, output_buffer, &output_size)) {
    400     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    401     EVP_CIPHER_CTX_cleanup(&decryption_context);
    402     return false;
    403   }
    404   total_size += output_size;
    405   data->resize(total_size);
    406   EVP_CIPHER_CTX_cleanup(&decryption_context);
    407   return true;
    408 }
    409 
    410 std::string CryptoUtilityImpl::HmacSha512(const std::string& data,
    411                                           const std::string& key) {
    412   unsigned char mac[SHA512_DIGEST_LENGTH];
    413   std::string mutable_data(data);
    414   unsigned char* data_buffer = StringAsOpenSSLBuffer(&mutable_data);
    415   HMAC(EVP_sha512(), key.data(), key.size(), data_buffer, data.size(), mac,
    416        nullptr);
    417   return std::string(std::begin(mac), std::end(mac));
    418 }
    419 
    420 bool CryptoUtilityImpl::TssCompatibleEncrypt(const std::string& input,
    421                                              const std::string& key,
    422                                              std::string* output) {
    423   CHECK(output);
    424   CHECK_EQ(key.size(), kAesKeySize);
    425   std::string iv;
    426   if (!GetRandom(kAesBlockSize, &iv)) {
    427     LOG(ERROR) << __func__ << ": GetRandom failed.";
    428     return false;
    429   }
    430   std::string encrypted;
    431   if (!AesEncrypt(input, key, iv, &encrypted)) {
    432     LOG(ERROR) << __func__ << ": Encryption failed.";
    433     return false;
    434   }
    435   *output = iv + encrypted;
    436   return true;
    437 }
    438 
    439 bool CryptoUtilityImpl::TpmCompatibleOAEPEncrypt(const std::string& input,
    440                                                  RSA* key,
    441                                                  std::string* output) {
    442   CHECK(output);
    443   // The custom OAEP parameter as specified in TPM Main Part 1, Section 31.1.1.
    444   const unsigned char oaep_param[4] = {'T', 'C', 'P', 'A'};
    445   std::string padded_input;
    446   padded_input.resize(RSA_size(key));
    447   auto padded_buffer =
    448       reinterpret_cast<unsigned char*>(string_as_array(&padded_input));
    449   auto input_buffer = reinterpret_cast<const unsigned char*>(input.data());
    450   int result = RSA_padding_add_PKCS1_OAEP(padded_buffer, padded_input.size(),
    451                                           input_buffer, input.size(),
    452                                           oaep_param, arraysize(oaep_param));
    453   if (!result) {
    454     LOG(ERROR) << __func__
    455                << ": Failed to add OAEP padding: " << GetOpenSSLError();
    456     return false;
    457   }
    458   output->resize(padded_input.size());
    459   auto output_buffer =
    460       reinterpret_cast<unsigned char*>(string_as_array(output));
    461   result = RSA_public_encrypt(padded_input.size(), padded_buffer, output_buffer,
    462                               key, RSA_NO_PADDING);
    463   if (result == -1) {
    464     LOG(ERROR) << __func__ << ": Failed to encrypt OAEP padded input: "
    465                << GetOpenSSLError();
    466     return false;
    467   }
    468   return true;
    469 }
    470 
    471 }  // namespace attestation
    472