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 = HmacSha512(
    146       encrypted_pb.iv() + encrypted_pb.encrypted_data(),
    147       aes_key);
    148   if (mac.length() != encrypted_pb.mac().length()) {
    149     LOG(ERROR) << __func__ << ": Corrupted data in encrypted pb.";
    150     return false;
    151   }
    152   if (!crypto::SecureMemEqual(mac.data(), encrypted_pb.mac().data(),
    153                               mac.length())) {
    154     LOG(ERROR) << __func__ << ": Corrupted data in encrypted pb.";
    155     return false;
    156   }
    157   if (!AesDecrypt(encrypted_pb.encrypted_data(), aes_key, encrypted_pb.iv(),
    158                   data)) {
    159     LOG(ERROR) << __func__ << ": AES decryption failed.";
    160     return false;
    161   }
    162   return true;
    163 }
    164 
    165 bool CryptoUtilityImpl::GetRSASubjectPublicKeyInfo(
    166     const std::string& public_key,
    167     std::string* public_key_info) {
    168   auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
    169   crypto::ScopedRSA rsa(d2i_RSAPublicKey(nullptr, &asn1_ptr,
    170                                          public_key.size()));
    171   if (!rsa.get()) {
    172     LOG(ERROR) << __func__ << ": Failed to decode public key: "
    173                << GetOpenSSLError();
    174     return false;
    175   }
    176   unsigned char* buffer = nullptr;
    177   int length = i2d_RSA_PUBKEY(rsa.get(), &buffer);
    178   if (length <= 0) {
    179     LOG(ERROR) << __func__ << ": Failed to encode public key: "
    180                << GetOpenSSLError();
    181     return false;
    182   }
    183   crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
    184   public_key_info->assign(reinterpret_cast<char*>(buffer), length);
    185   return true;
    186 }
    187 
    188 bool CryptoUtilityImpl::GetRSAPublicKey(const std::string& public_key_info,
    189                                         std::string* public_key) {
    190   auto asn1_ptr = reinterpret_cast<const unsigned char*>(
    191       public_key_info.data());
    192   crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr,
    193                                        public_key_info.size()));
    194   if (!rsa.get()) {
    195     LOG(ERROR) << __func__ << ": Failed to decode public key: "
    196                << GetOpenSSLError();
    197     return false;
    198   }
    199   unsigned char* buffer = NULL;
    200   int length = i2d_RSAPublicKey(rsa.get(), &buffer);
    201   if (length <= 0) {
    202     LOG(ERROR) << __func__ << ": Failed to encode public key: "
    203                << GetOpenSSLError();
    204     return false;
    205   }
    206   crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
    207   public_key->assign(reinterpret_cast<char*>(buffer), length);
    208   return true;
    209 }
    210 
    211 bool CryptoUtilityImpl::EncryptIdentityCredential(
    212     const std::string& credential,
    213     const std::string& ek_public_key_info,
    214     const std::string& aik_public_key,
    215     EncryptedIdentityCredential* encrypted) {
    216   const char kAlgAES256 = 9;  // This comes from TPM_ALG_AES256.
    217   const char kEncModeCBC = 2;  // This comes from TPM_SYM_MODE_CBC.
    218   const char kAsymContentHeader[] =
    219       {0, 0, 0, kAlgAES256, 0, kEncModeCBC, 0, kAesKeySize};
    220   const char kSymContentHeader[12] = {};
    221 
    222   // Generate an AES key and encrypt the credential.
    223   std::string aes_key;
    224   if (!GetRandom(kAesKeySize, &aes_key)) {
    225     LOG(ERROR) << __func__ << ": GetRandom failed.";
    226     return false;
    227   }
    228   std::string encrypted_credential;
    229   if (!TssCompatibleEncrypt(credential, aes_key, &encrypted_credential)) {
    230     LOG(ERROR) << __func__ << ": Failed to encrypt credential.";
    231     return false;
    232   }
    233 
    234   // Construct a TPM_ASYM_CA_CONTENTS structure.
    235   std::string asym_header(std::begin(kAsymContentHeader),
    236                           std::end(kAsymContentHeader));
    237   std::string asym_content = asym_header + aes_key +
    238                              base::SHA1HashString(aik_public_key);
    239 
    240   // Encrypt the TPM_ASYM_CA_CONTENTS with the EK public key.
    241   auto asn1_ptr = reinterpret_cast<const unsigned char*>(
    242       ek_public_key_info.data());
    243   crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr,
    244                                        ek_public_key_info.size()));
    245   if (!rsa.get()) {
    246     LOG(ERROR) << __func__ << ": Failed to decode EK public key: "
    247                << GetOpenSSLError();
    248     return false;
    249   }
    250   std::string encrypted_asym_content;
    251   if (!TpmCompatibleOAEPEncrypt(asym_content, rsa.get(),
    252                                 &encrypted_asym_content)) {
    253     LOG(ERROR) << __func__ << ": Failed to encrypt with EK public key.";
    254     return false;
    255   }
    256 
    257   // Construct a TPM_SYM_CA_ATTESTATION structure.
    258   uint32_t length = htonl(encrypted_credential.size());
    259   auto length_bytes = reinterpret_cast<const char*>(&length);
    260   std::string length_blob(length_bytes, sizeof(uint32_t));
    261   std::string sym_header(std::begin(kSymContentHeader),
    262                          std::end(kSymContentHeader));
    263   std::string sym_content = length_blob + sym_header + encrypted_credential;
    264 
    265   encrypted->set_asym_ca_contents(encrypted_asym_content);
    266   encrypted->set_sym_ca_attestation(sym_content);
    267   return true;
    268 }
    269 
    270 bool CryptoUtilityImpl::EncryptForUnbind(const std::string& public_key,
    271                                          const std::string& data,
    272                                          std::string* encrypted_data) {
    273   // Construct a TPM_BOUND_DATA structure.
    274   const char kBoundDataHeader[] = {1, 1, 0, 0, 2 /* TPM_PT_BIND */};
    275   std::string header(std::begin(kBoundDataHeader), std::end(kBoundDataHeader));
    276   std::string bound_data = header + data;
    277 
    278   // Encrypt using the TPM_ES_RSAESOAEP_SHA1_MGF1 scheme.
    279   auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
    280   crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
    281   if (!rsa.get()) {
    282     LOG(ERROR) << __func__ << ": Failed to decode public key: "
    283                << GetOpenSSLError();
    284     return false;
    285   }
    286   if (!TpmCompatibleOAEPEncrypt(bound_data, rsa.get(), encrypted_data)) {
    287     LOG(ERROR) << __func__ << ": Failed to encrypt with public key.";
    288     return false;
    289   }
    290   return true;
    291 }
    292 
    293 bool CryptoUtilityImpl::VerifySignature(const std::string& public_key,
    294                                         const std::string& data,
    295                                         const std::string& signature) {
    296   auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
    297   crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
    298   if (!rsa.get()) {
    299     LOG(ERROR) << __func__ << ": Failed to decode public key: "
    300                << GetOpenSSLError();
    301     return false;
    302   }
    303   std::string digest = crypto::SHA256HashString(data);
    304   auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data());
    305   std::string mutable_signature(signature);
    306   unsigned char* signature_buffer = StringAsOpenSSLBuffer(&mutable_signature);
    307   return (RSA_verify(NID_sha256, digest_buffer, digest.size(),
    308                      signature_buffer, signature.size(), rsa.get()) == 1);
    309 }
    310 
    311 bool CryptoUtilityImpl::AesEncrypt(const std::string& data,
    312                                    const std::string& key,
    313                                    const std::string& iv,
    314                                    std::string* encrypted_data) {
    315   if (key.size() != kAesKeySize || iv.size() != kAesBlockSize) {
    316     return false;
    317   }
    318   if (data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
    319     // EVP_EncryptUpdate takes a signed int.
    320     return false;
    321   }
    322   std::string mutable_data(data);
    323   unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_data);
    324   std::string mutable_key(key);
    325   unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
    326   std::string mutable_iv(iv);
    327   unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
    328   // Allocate enough space for the output (including padding).
    329   encrypted_data->resize(data.size() + kAesBlockSize);
    330   auto output_buffer = reinterpret_cast<unsigned char*>(
    331       string_as_array(encrypted_data));
    332   int output_size = 0;
    333   const EVP_CIPHER* cipher = EVP_aes_256_cbc();
    334   EVP_CIPHER_CTX encryption_context;
    335   EVP_CIPHER_CTX_init(&encryption_context);
    336   if (!EVP_EncryptInit_ex(&encryption_context, cipher, nullptr, key_buffer,
    337                           iv_buffer)) {
    338     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    339     return false;
    340   }
    341   if (!EVP_EncryptUpdate(&encryption_context, output_buffer, &output_size,
    342                          input_buffer, data.size())) {
    343     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    344     EVP_CIPHER_CTX_cleanup(&encryption_context);
    345     return false;
    346   }
    347   size_t total_size = output_size;
    348   output_buffer += output_size;
    349   output_size = 0;
    350   if (!EVP_EncryptFinal_ex(&encryption_context, output_buffer, &output_size)) {
    351     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    352     EVP_CIPHER_CTX_cleanup(&encryption_context);
    353     return false;
    354   }
    355   total_size += output_size;
    356   encrypted_data->resize(total_size);
    357   EVP_CIPHER_CTX_cleanup(&encryption_context);
    358   return true;
    359 }
    360 
    361 bool CryptoUtilityImpl::AesDecrypt(const std::string& encrypted_data,
    362                                    const std::string& key,
    363                                    const std::string& iv,
    364                                    std::string* data) {
    365   if (key.size() != kAesKeySize || iv.size() != kAesBlockSize) {
    366     return false;
    367   }
    368   if (encrypted_data.size() >
    369       static_cast<size_t>(std::numeric_limits<int>::max())) {
    370     // EVP_DecryptUpdate takes a signed int.
    371     return false;
    372   }
    373   std::string mutable_encrypted_data(encrypted_data);
    374   unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_encrypted_data);
    375   std::string mutable_key(key);
    376   unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
    377   std::string mutable_iv(iv);
    378   unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
    379   // Allocate enough space for the output.
    380   data->resize(encrypted_data.size());
    381   unsigned char* output_buffer = StringAsOpenSSLBuffer(data);
    382   int output_size = 0;
    383   const EVP_CIPHER* cipher = EVP_aes_256_cbc();
    384   EVP_CIPHER_CTX decryption_context;
    385   EVP_CIPHER_CTX_init(&decryption_context);
    386   if (!EVP_DecryptInit_ex(&decryption_context, cipher, nullptr, key_buffer,
    387                           iv_buffer)) {
    388     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    389     return false;
    390   }
    391   if (!EVP_DecryptUpdate(&decryption_context, output_buffer, &output_size,
    392                          input_buffer, encrypted_data.size())) {
    393     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    394     EVP_CIPHER_CTX_cleanup(&decryption_context);
    395     return false;
    396   }
    397   size_t total_size = output_size;
    398   output_buffer += output_size;
    399   output_size = 0;
    400   if (!EVP_DecryptFinal_ex(&decryption_context, output_buffer, &output_size)) {
    401     LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    402     EVP_CIPHER_CTX_cleanup(&decryption_context);
    403     return false;
    404   }
    405   total_size += output_size;
    406   data->resize(total_size);
    407   EVP_CIPHER_CTX_cleanup(&decryption_context);
    408   return true;
    409 }
    410 
    411 std::string CryptoUtilityImpl::HmacSha512(const std::string& data,
    412                                           const std::string& key) {
    413   unsigned char mac[SHA512_DIGEST_LENGTH];
    414   std::string mutable_data(data);
    415   unsigned char* data_buffer = StringAsOpenSSLBuffer(&mutable_data);
    416   HMAC(EVP_sha512(), key.data(), key.size(), data_buffer, data.size(), mac,
    417        nullptr);
    418   return std::string(std::begin(mac), std::end(mac));
    419 }
    420 
    421 bool CryptoUtilityImpl::TssCompatibleEncrypt(const std::string& input,
    422                                              const std::string& key,
    423                                              std::string* output) {
    424   CHECK(output);
    425   CHECK_EQ(key.size(), kAesKeySize);
    426   std::string iv;
    427   if (!GetRandom(kAesBlockSize, &iv)) {
    428     LOG(ERROR) << __func__ << ": GetRandom failed.";
    429     return false;
    430   }
    431   std::string encrypted;
    432   if (!AesEncrypt(input, key, iv, &encrypted)) {
    433     LOG(ERROR) << __func__ << ": Encryption failed.";
    434     return false;
    435   }
    436   *output = iv + encrypted;
    437   return true;
    438 }
    439 
    440 bool CryptoUtilityImpl::TpmCompatibleOAEPEncrypt(const std::string& input,
    441                                                  RSA* key,
    442                                                  std::string* output) {
    443   CHECK(output);
    444   // The custom OAEP parameter as specified in TPM Main Part 1, Section 31.1.1.
    445   const unsigned char oaep_param[4] = {'T', 'C', 'P', 'A'};
    446   std::string padded_input;
    447   padded_input.resize(RSA_size(key));
    448   auto padded_buffer = reinterpret_cast<unsigned char*>(
    449       string_as_array(&padded_input));
    450   auto input_buffer = reinterpret_cast<const unsigned char*>(input.data());
    451   int result = RSA_padding_add_PKCS1_OAEP(padded_buffer, padded_input.size(),
    452                                           input_buffer, input.size(),
    453                                           oaep_param, arraysize(oaep_param));
    454   if (!result) {
    455     LOG(ERROR) << __func__ << ": Failed to add OAEP padding: "
    456                << GetOpenSSLError();
    457     return false;
    458   }
    459   output->resize(padded_input.size());
    460   auto output_buffer = reinterpret_cast<unsigned char*>(
    461       string_as_array(output));
    462   result = RSA_public_encrypt(padded_input.size(), padded_buffer,
    463                               output_buffer, key, RSA_NO_PADDING);
    464   if (result == -1) {
    465     LOG(ERROR) << __func__ << ": Failed to encrypt OAEP padded input: "
    466                << GetOpenSSLError();
    467     return false;
    468   }
    469   return true;
    470 }
    471 
    472 }  // namespace attestation
    473