| // Copyright 2015 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. |
| |
| #ifndef ATTESTATION_COMMON_CRYPTO_UTILITY_IMPL_H_ |
| #define ATTESTATION_COMMON_CRYPTO_UTILITY_IMPL_H_ |
| |
| #include "attestation/common/crypto_utility.h" |
| |
| #include <string> |
| |
| #include <openssl/rsa.h> |
| #include <openssl/ec.h> |
| #include <crypto/scoped_openssl_types.h> |
| |
| #include "attestation/common/tpm_utility.h" |
| |
| namespace attestation { |
| |
| // An implementation of CryptoUtility. |
| class CryptoUtilityImpl : public CryptoUtility { |
| public: |
| // Does not take ownership of pointers. |
| explicit CryptoUtilityImpl(TpmUtility* tpm_utility); |
| ~CryptoUtilityImpl() override; |
| |
| // CryptoUtility methods. |
| bool GetRandom(size_t num_bytes, std::string* random_data) const override; |
| bool CreateSealedKey(std::string* aes_key, std::string* sealed_key) override; |
| bool EncryptData(const std::string& data, |
| const std::string& aes_key, |
| const std::string& sealed_key, |
| std::string* encrypted_data) override; |
| bool UnsealKey(const std::string& encrypted_data, |
| std::string* aes_key, |
| std::string* sealed_key) override; |
| bool DecryptData(const std::string& encrypted_data, |
| const std::string& aes_key, |
| std::string* data) override; |
| bool GetRSASubjectPublicKeyInfo(const std::string& public_key, |
| std::string* spki) override; |
| bool GetRSAPublicKey(const std::string& public_key_info, |
| std::string* public_key) override; |
| bool EncryptIdentityCredential( |
| TpmVersion tpm_version, |
| const std::string& credential, |
| const std::string& ek_public_key_info, |
| const std::string& aik_public_key, |
| EncryptedIdentityCredential* encrypted) override; |
| bool DecryptIdentityCertificateForTpm2( |
| const std::string& credential, |
| const EncryptedData& encrypted_certificate, |
| std::string* certificate) override; |
| bool EncryptForUnbind(const std::string& public_key, |
| const std::string& data, |
| std::string* encrypted_data) override; |
| bool VerifySignature(int digest_nid, |
| const std::string& public_key, |
| const std::string& data, |
| const std::string& signature) override; |
| bool VerifySignatureUsingHexKey(int digest_nid, |
| const std::string& public_key_hex, |
| const std::string& data, |
| const std::string& signature) override; |
| bool EncryptDataForGoogle(const std::string& data, |
| const std::string& public_key_hex, |
| const std::string& key_id, |
| EncryptedData* encrypted_data) override; |
| bool CreateSPKAC(const std::string& key_blob, |
| const std::string& public_key, |
| KeyType key_type, |
| std::string* spkac) override; |
| bool VerifyCertificate(const std::string& certificate, |
| const std::string& ca_public_key_hex) override; |
| bool VerifyCertificateWithSubjectPublicKey( |
| const std::string& certificate, |
| const std::string& ca_public_key_der_hex) override; |
| bool GetCertificateIssuerName(const std::string& certificate, |
| std::string* issuer_name) override; |
| bool GetCertificateSubjectPublicKeyInfo(const std::string& certificate, |
| std::string* public_key) override; |
| bool GetCertificatePublicKey(const std::string& certificate, |
| std::string* public_key) override; |
| bool GetKeyDigest(const std::string& public_key, |
| std::string* key_digest) override; |
| |
| std::string HmacSha256(const std::string& key, |
| const std::string& data) override; |
| |
| std::string HmacSha512(const std::string& key, |
| const std::string& data) override; |
| |
| int DefaultDigestAlgoForSignature() override; |
| |
| private: |
| friend class CryptoUtilityImplTest; |
| |
| enum class KeyDerivationScheme { |
| // No derivation. The seed is used directly has both AES and HMAC keys. Not |
| // recommended for new applications. |
| kNone, |
| // Derive using SHA-256 and the headers 'ENCRYPT' and 'MAC'. |
| kHashWithHeaders, |
| }; |
| |
| // Encrypts |data| using |key|, |iv|, and the given |cipher|. Returns true on |
| // success. |
| bool AesEncrypt(const EVP_CIPHER* cipher, |
| const std::string& data, |
| const std::string& key, |
| const std::string& iv, |
| std::string* encrypted_data); |
| |
| // Decrypts |encrypted_data| using |key|, |iv|, and the given |cipher|. |
| // Returns true on success. |
| bool AesDecrypt(const EVP_CIPHER* cipher, |
| const std::string& encrypted_data, |
| const std::string& key, |
| const std::string& iv, |
| std::string* data); |
| |
| // Encrypt like trousers does. This is like AesEncrypt but a random IV is |
| // included in the output. |
| bool TssCompatibleEncrypt(const std::string& input, |
| const std::string& key, |
| std::string* output); |
| |
| // Encrypts using RSA-OAEP and the TPM-specific OAEP parameter. |
| bool TpmCompatibleOAEPEncrypt(const std::string& input, |
| RSA* key, |
| std::string* output); |
| |
| // Encrypts |input| using AES-256-CBC-PKCS5, a random IV, and HMAC-SHA512 over |
| // the cipher-text. The encryption and mac keys are derived from a |seed| |
| // according to |derivation_scheme|. On success populates |seed| and |output| |
| // and returns true. The output.wrapped_key and output.wrapping_key_id fields |
| // are ignored. |
| bool EncryptWithSeed(KeyDerivationScheme derivation_scheme, |
| const std::string& input, |
| const std::string& seed, |
| EncryptedData* encrypted); |
| |
| // Decrypts |input| using |seed| and |derivation_scheme|. On success populates |
| // |decrypted| and returns true. This method is generally the inverse of |
| // EncryptWithRandomKey() but the seed needs to be provided by the caller. |
| bool DecryptWithSeed(KeyDerivationScheme derivation_scheme, |
| const EncryptedData& input, |
| const std::string& seed, |
| std::string* decrypted); |
| |
| // Wraps |key| with |wrapping_key| using RSA-PKCS1-OAEP. On success populates |
| // output.wrapped_key and output.wrapping_key_id fields (other fields are |
| // ignored). |
| bool WrapKeyOAEP(const std::string& key, |
| RSA* wrapping_key, |
| const std::string& wrapping_key_id, |
| EncryptedData* output); |
| |
| // Computes a key 'Name' given a public key as a serialized TPMT_PUBLIC. The |
| // name algorithm is assumed to be SHA256. |
| std::string GetTpm2KeyNameFromPublicKey( |
| const std::string& public_key_tpm_format); |
| |
| // Computes KDFa as defined in TPM 2.0 specification Part 1 Rev 1.16 Section |
| // 11.4.9.1. It always uses SHA256 as the hash algorithm and outputs a 128-bit |
| // or a 256-bit value, as defined by |bits|. |
| std::string Tpm2CompatibleKDFa(const std::string& key, |
| const std::string& label, |
| const std::string& context, |
| int bits); |
| |
| // Encrypts |input| using RSA-OAEP with a custom |label|. A zero byte will be |
| // appended to the label as described in TPM 2.0 specification Part 1 Rev 1.16 |
| // Annex B.4. |
| bool Tpm2CompatibleOAEPEncrypt(const std::string& label, |
| const std::string& input, |
| RSA* key, |
| std::string* output); |
| |
| // Encrypts |input| using RSA-OAEP with a custom |label|. |
| bool OAEPEncryptWithLabel(const std::string& label, |
| const std::string& input, |
| RSA* key, |
| const EVP_MD* md, |
| const EVP_MD* mgf1md, |
| std::string* output); |
| |
| // Verifies the |signature| for the provided |data| using the |key|. |
| // The digest algorithm depends on OpenSSL nid |digest_nid|. |
| bool VerifySignatureInner(int digest_nid, |
| const crypto::ScopedEVP_PKEY& key, |
| const std::string& data, |
| const std::string& signature); |
| |
| // Creates a SignedPublicKeyAndChallenge signed with |key_blob| from |
| // |public_key| with a random challenge. On success returns true and provides |
| // the |spkac|. |key_blob| is taken from the already loaded CertifiedKey and |
| // |public_key| is the corresponding public part of |key_blob|. |
| bool CreateSPKACInternal(const std::string& key_blob, |
| const crypto::ScopedEVP_PKEY& public_key, |
| std::string* spkac); |
| |
| TpmUtility* tpm_utility_; |
| }; |
| |
| } // namespace attestation |
| |
| #endif // ATTESTATION_COMMON_CRYPTO_UTILITY_IMPL_H_ |