OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // Contains the implementation of class Crypto |
| 6 |
| 7 #include "crypto.h" |
| 8 |
| 9 #include <openssl/err.h> |
| 10 #include <openssl/evp.h> |
| 11 #include <openssl/rand.h> |
| 12 #include <openssl/rsa.h> |
| 13 #include <openssl/sha.h> |
| 14 |
| 15 #include <base/file_util.h> |
| 16 #include <base/logging.h> |
| 17 #include <chromeos/utility.h> |
| 18 |
| 19 using std::string; |
| 20 |
| 21 namespace tpm_init { |
| 22 |
| 23 const std::string kDefaultEntropySource = "/dev/urandom"; |
| 24 const int kWellKnownExponent = 65537; |
| 25 |
| 26 Crypto::Crypto() |
| 27 : entropy_source_(kDefaultEntropySource) { |
| 28 } |
| 29 |
| 30 Crypto::~Crypto() { |
| 31 } |
| 32 |
| 33 bool Crypto::Init() { |
| 34 SeedRng(); |
| 35 return true; |
| 36 } |
| 37 |
| 38 void Crypto::SeedRng() const { |
| 39 // TODO(fes): Get assistance from the TPM? |
| 40 while (!RAND_status()) { |
| 41 char buffer[256]; |
| 42 file_util::ReadFile(FilePath(entropy_source_), buffer, sizeof(buffer)); |
| 43 RAND_add(buffer, sizeof(buffer), sizeof(buffer)); |
| 44 } |
| 45 } |
| 46 |
| 47 void Crypto::GetSecureRandom(unsigned char *rand, int length) const { |
| 48 SeedRng(); |
| 49 // Have OpenSSL generate the random bytes |
| 50 RAND_bytes(rand, length); |
| 51 } |
| 52 |
| 53 void Crypto::GetSha1(const chromeos::Blob& data, int start, int count, |
| 54 SecureBlob* hash) const { |
| 55 SHA_CTX sha_ctx; |
| 56 unsigned char md_value[SHA_DIGEST_LENGTH]; |
| 57 |
| 58 SHA1_Init(&sha_ctx); |
| 59 SHA1_Update(&sha_ctx, &data[start], count); |
| 60 SHA1_Final(md_value, &sha_ctx); |
| 61 hash->resize(sizeof(md_value)); |
| 62 memcpy(hash->data(), md_value, sizeof(md_value)); |
| 63 } |
| 64 |
| 65 bool Crypto::CreateRsaKey(int key_bits, SecureBlob* n, SecureBlob* p) const { |
| 66 SeedRng(); |
| 67 |
| 68 RSA* rsa = RSA_generate_key(key_bits, kWellKnownExponent, NULL, NULL); |
| 69 |
| 70 if (rsa == NULL) { |
| 71 LOG(ERROR) << "RSA key generation failed."; |
| 72 return false; |
| 73 } |
| 74 |
| 75 SecureBlob local_n(BN_num_bytes(rsa->n)); |
| 76 if (BN_bn2bin(rsa->n, static_cast<unsigned char*>(local_n.data())) <= 0) { |
| 77 LOG(ERROR) << "Unable to get modulus from RSA key."; |
| 78 RSA_free(rsa); |
| 79 return false; |
| 80 } |
| 81 |
| 82 SecureBlob local_p(BN_num_bytes(rsa->p)); |
| 83 if (BN_bn2bin(rsa->p, static_cast<unsigned char*>(local_p.data())) <= 0) { |
| 84 LOG(ERROR) << "Unable to get private key from RSA key."; |
| 85 RSA_free(rsa); |
| 86 return false; |
| 87 } |
| 88 |
| 89 RSA_free(rsa); |
| 90 n->swap(local_n); |
| 91 p->swap(local_p); |
| 92 return true; |
| 93 } |
| 94 |
| 95 void Crypto::AsciiEncodeToBuffer(const chromeos::Blob& blob, char* buffer, |
| 96 int buffer_length) { |
| 97 const char hex_chars[] = "0123456789abcdef"; |
| 98 int i = 0; |
| 99 for (chromeos::Blob::const_iterator it = blob.begin(); |
| 100 it < blob.end() && (i + 1) < buffer_length; ++it) { |
| 101 buffer[i++] = hex_chars[((*it) >> 4) & 0x0f]; |
| 102 buffer[i++] = hex_chars[(*it) & 0x0f]; |
| 103 } |
| 104 if (i < buffer_length) { |
| 105 buffer[i] = '\0'; |
| 106 } |
| 107 } |
| 108 |
| 109 } // namespace tpm_init |
OLD | NEW |