blob: 7bd4b762b82443a0803a4853f3f4ee22537dc22a [file] [log] [blame]
// Copyright (c) 2009-2010 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.
// Contains the implementation of class Crypto
#include "crypto.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <base/file_util.h>
#include <base/logging.h>
#include <chromeos/utility.h>
using std::string;
namespace tpm_init {
const std::string kDefaultEntropySource = "/dev/urandom";
const int kWellKnownExponent = 65537;
Crypto::Crypto()
: entropy_source_(kDefaultEntropySource) {
}
Crypto::~Crypto() {
}
bool Crypto::Init() {
SeedRng();
return true;
}
void Crypto::SeedRng() const {
// TODO(fes): Get assistance from the TPM?
while (!RAND_status()) {
char buffer[256];
file_util::ReadFile(FilePath(entropy_source_), buffer, sizeof(buffer));
RAND_add(buffer, sizeof(buffer), sizeof(buffer));
}
}
void Crypto::GetSecureRandom(unsigned char *rand, int length) const {
SeedRng();
// Have OpenSSL generate the random bytes
RAND_bytes(rand, length);
}
void Crypto::GetSha1(const chromeos::Blob& data, int start, int count,
SecureBlob* hash) const {
SHA_CTX sha_ctx;
unsigned char md_value[SHA_DIGEST_LENGTH];
SHA1_Init(&sha_ctx);
SHA1_Update(&sha_ctx, &data[start], count);
SHA1_Final(md_value, &sha_ctx);
hash->resize(sizeof(md_value));
memcpy(hash->data(), md_value, sizeof(md_value));
}
bool Crypto::CreateRsaKey(int key_bits, SecureBlob* n, SecureBlob* p) const {
SeedRng();
RSA* rsa = RSA_generate_key(key_bits, kWellKnownExponent, NULL, NULL);
if (rsa == NULL) {
LOG(ERROR) << "RSA key generation failed.";
return false;
}
SecureBlob local_n(BN_num_bytes(rsa->n));
if (BN_bn2bin(rsa->n, static_cast<unsigned char*>(local_n.data())) <= 0) {
LOG(ERROR) << "Unable to get modulus from RSA key.";
RSA_free(rsa);
return false;
}
SecureBlob local_p(BN_num_bytes(rsa->p));
if (BN_bn2bin(rsa->p, static_cast<unsigned char*>(local_p.data())) <= 0) {
LOG(ERROR) << "Unable to get private key from RSA key.";
RSA_free(rsa);
return false;
}
RSA_free(rsa);
n->swap(local_n);
p->swap(local_p);
return true;
}
void Crypto::AsciiEncodeToBuffer(const chromeos::Blob& blob, char* buffer,
int buffer_length) {
const char hex_chars[] = "0123456789abcdef";
int i = 0;
for (chromeos::Blob::const_iterator it = blob.begin();
it < blob.end() && (i + 1) < buffer_length; ++it) {
buffer[i++] = hex_chars[((*it) >> 4) & 0x0f];
buffer[i++] = hex_chars[(*it) & 0x0f];
}
if (i < buffer_length) {
buffer[i] = '\0';
}
}
} // namespace tpm_init