blob: aa90e94e347c102f8c713f0018554762a9ef8dd6 [file] [log] [blame]
// Copyright 2019 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 "cryptohome/tpm1_static_utils.h"
#include <memory>
#include <base/logging.h>
#include <base/memory/free_deleter.h>
#include <base/strings/stringprintf.h>
#include <crypto/libcrypto-compat.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <trousers/trousers.h>
#include "cryptohome/cryptolib.h"
using brillo::Blob;
using ScopedByteArray = std::unique_ptr<BYTE, base::FreeDeleter>;
namespace cryptohome {
std::string FormatTrousersErrorCode(TSS_RESULT result) {
return base::StringPrintf("TPM error 0x%x (%s)", result,
Trspi_Error_String(result));
}
crypto::ScopedRSA ParseRsaFromTpmPubkeyBlob(const Blob& pubkey) {
// Parse the serialized TPM_PUBKEY.
UINT64 offset = 0;
BYTE* buffer = const_cast<BYTE*>(pubkey.data());
TPM_PUBKEY parsed;
TSS_RESULT tss_result = Trspi_UnloadBlob_PUBKEY(&offset, buffer, &parsed);
if (TPM_ERROR(tss_result)) {
LOG(ERROR) << "Failed to parse TPM_PUBKEY: "
<< FormatTrousersErrorCode(tss_result);
return nullptr;
}
ScopedByteArray scoped_key(parsed.pubKey.key);
ScopedByteArray scoped_parms(parsed.algorithmParms.parms);
TPM_RSA_KEY_PARMS* parms =
reinterpret_cast<TPM_RSA_KEY_PARMS*>(parsed.algorithmParms.parms);
// Get the public exponent.
crypto::ScopedRSA rsa(RSA_new());
crypto::ScopedBIGNUM e(BN_new()), n(BN_new());
if (!rsa || !e || !n) {
LOG(ERROR) << "Failed to create RSA or BIGNUM";
return nullptr;
}
if (!parms->exponentSize) {
if (!BN_set_word(e.get(), kWellKnownExponent)) {
LOG(ERROR) << "Failed to set BN exponent to WellKnownExponent";
return nullptr;
}
} else {
if (!BN_bin2bn(parms->exponent, parms->exponentSize, e.get())) {
LOG(ERROR) << "Failed to load BN exponent from TPM_PUBKEY";
return nullptr;
}
}
// Get the modulus.
if (!BN_bin2bn(parsed.pubKey.key, parsed.pubKey.keyLength, n.get())) {
LOG(ERROR) << "Failed to load BN modulus from TPM_PUBKEY";
return nullptr;
}
if (!RSA_set0_key(rsa.get(), n.release(), e.release(), nullptr)) {
LOG(ERROR) << "Failed to set parameters for RSA";
return nullptr;
}
return rsa;
}
} // namespace cryptohome