blob: aa2e050c444bff740dd55f8efb735de407d18156 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "hwsec-test-utils/common/attestation_crypto.h"
#include <string>
#include <base/optional.h>
#include <crypto/sha2.h>
#include "hwsec-test-utils/common/openssl_utility.h"
namespace hwsec_test_utils {
namespace attestation_crypto {
namespace {
// Servers prepend these 2 headers to the same seed to calculate AES key and
// HMAC key respectively.
constexpr char kHashHeaderForEncrypt[] = "ENCRYPT";
constexpr char kHashHeaderForMac[] = "MAC";
} // namespace
std::string KeyDeriverDirect::ToAesKey(const std::string& seed) const {
return seed;
}
std::string KeyDeriverDirect::ToHmacKey(const std::string& seed) const {
return seed;
}
std::string KeyDeriverSha256WithHeader::ToAesKey(
const std::string& seed) const {
return crypto::SHA256HashString(kHashHeaderForEncrypt + seed);
}
std::string KeyDeriverSha256WithHeader::ToHmacKey(
const std::string& seed) const {
return crypto::SHA256HashString(kHashHeaderForMac + seed);
}
ReturnStatus Decrypt(const attestation::EncryptedData& encrypted_data_proto,
const crypto::ScopedEVP_PKEY& key,
const KeyDeriverBase& key_deriver,
std::string* decrypted) {
// Decrypt.
base::Optional<std::string> seed = EVPRsaDecrypt(
key, encrypted_data_proto.wrapped_key(), RSA_PKCS1_OAEP_PADDING);
if (!seed) {
return ReturnStatus::kUnwrapKey;
}
const std::string aes_key = key_deriver.ToAesKey(*seed);
base::Optional<std::string> decrypted_data =
EVPAesDecrypt(encrypted_data_proto.encrypted_data(), EVP_aes_256_cbc(),
aes_key, encrypted_data_proto.iv());
if (!decrypted_data) {
LOG(ERROR) << __func__ << ": Failed to decrypt data.";
return ReturnStatus::kDecrypt;
}
// Verify HMAC.
const std::string hmac_key_str = key_deriver.ToHmacKey(*seed);
crypto::ScopedEVP_PKEY hmac_key(EVP_PKEY_new_mac_key(
EVP_PKEY_HMAC, nullptr,
reinterpret_cast<const unsigned char*>(hmac_key_str.data()),
hmac_key_str.length()));
if (!hmac_key) {
LOG(ERROR) << __func__ << ": Failed to call EVP_PKEY_new_mac_key: "
<< GetOpenSSLError();
return ReturnStatus::kFailure;
}
base::Optional<std::string> hmac = EVPDigestSign(
hmac_key, EVP_sha512(),
encrypted_data_proto.iv() + encrypted_data_proto.encrypted_data());
if (!hmac) {
LOG(ERROR) << __func__ << ": Failed to calculate HMAC.";
return ReturnStatus::kFailure;
}
if (*hmac != encrypted_data_proto.mac()) {
LOG(ERROR) << __func__ << ": HMAC mismatch.";
return ReturnStatus::kHmac;
}
*decrypted = *decrypted_data;
return ReturnStatus::kSuccess;
}
} // namespace attestation_crypto
} // namespace hwsec_test_utils