| Index: base/crypto/rsa_private_key_win.cc
|
| diff --git a/base/crypto/rsa_private_key_win.cc b/base/crypto/rsa_private_key_win.cc
|
| index b1846fa2872057cc855317c63afed6c224b4fa5e..3683d86fbce9655a0a7bf9d401e7e8de78ccc7fb 100644
|
| --- a/base/crypto/rsa_private_key_win.cc
|
| +++ b/base/crypto/rsa_private_key_win.cc
|
| @@ -11,215 +11,15 @@
|
| #include "base/scoped_ptr.h"
|
| #include "base/string_util.h"
|
|
|
| -
|
| -// This file manually encodes and decodes RSA private keys using PrivateKeyInfo
|
| -// from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are:
|
| -//
|
| -// PrivateKeyInfo ::= SEQUENCE {
|
| -// version Version,
|
| -// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
|
| -// privateKey PrivateKey,
|
| -// attributes [0] IMPLICIT Attributes OPTIONAL
|
| -// }
|
| -//
|
| -// RSAPrivateKey ::= SEQUENCE {
|
| -// version Version,
|
| -// modulus INTEGER,
|
| -// publicExponent INTEGER,
|
| -// privateExponent INTEGER,
|
| -// prime1 INTEGER,
|
| -// prime2 INTEGER,
|
| -// exponent1 INTEGER,
|
| -// exponent2 INTEGER,
|
| -// coefficient INTEGER
|
| -// }
|
| -
|
| -
|
| namespace {
|
| -
|
| -// ASN.1 encoding of the AlgorithmIdentifier from PKCS #8.
|
| -const uint8 kRsaAlgorithmIdentifier[] = {
|
| - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
|
| - 0x05, 0x00
|
| -};
|
| -
|
| -// ASN.1 tags for some types we use.
|
| -const uint8 kSequenceTag = 0x30;
|
| -const uint8 kIntegerTag = 0x02;
|
| -const uint8 kNullTag = 0x05;
|
| -const uint8 kOctetStringTag = 0x04;
|
| -
|
| -// Helper function to prepend an array of bytes into a list, reversing their
|
| -// order. This is needed because ASN.1 integers are big-endian, while CryptoAPI
|
| -// uses little-endian.
|
| -static void PrependBytesInReverseOrder(uint8* val, int num_bytes,
|
| - std::list<uint8>* data) {
|
| - for (int i = 0; i < num_bytes; ++i)
|
| - data->push_front(val[i]);
|
| -}
|
| -
|
| -// Helper to prepend an ASN.1 length field.
|
| -static void PrependLength(size_t size, std::list<uint8>* data) {
|
| - // The high bit is used to indicate whether additional octets are needed to
|
| - // represent the length.
|
| - if (size < 0x80) {
|
| - data->push_front(static_cast<uint8>(size));
|
| - } else {
|
| - uint8 num_bytes = 0;
|
| - while (size > 0) {
|
| - data->push_front(static_cast<uint8>(size & 0xFF));
|
| - size >>= 8;
|
| - num_bytes++;
|
| - }
|
| - CHECK(num_bytes <= 4);
|
| - data->push_front(0x80 | num_bytes);
|
| - }
|
| -}
|
| -
|
| -// Helper to prepend an ASN.1 type header.
|
| -static void PrependTypeHeaderAndLength(uint8 type, uint32 length,
|
| - std::list<uint8>* output) {
|
| - PrependLength(length, output);
|
| - output->push_front(type);
|
| -}
|
| -
|
| -// Helper to prepend an ASN.1 integer.
|
| -static void PrependInteger(uint8* val, int num_bytes, std::list<uint8>* data) {
|
| - // Skip trailing null bytes off the MSB end, which is the tail since the input
|
| - // is little endian.
|
| - while (num_bytes > 1 && val[num_bytes - 1] == 0x00)
|
| - num_bytes--;
|
| -
|
| - PrependBytesInReverseOrder(val, num_bytes, data);
|
| -
|
| - // If the MSB is set, we need to add an extra null byte, otherwise the integer
|
| - // could be interpreted as negative.
|
| - if ((val[num_bytes - 1] & 0x80) != 0) {
|
| - data->push_front(0x00);
|
| - num_bytes++;
|
| - }
|
| -
|
| - PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
|
| -}
|
| -
|
| -// Helper for error handling during key import.
|
| + // Helper for error handling during key import.
|
| #define READ_ASSERT(truth) \
|
| if (!(truth)) { \
|
| - NOTREACHED(); \
|
| - return false; \
|
| - }
|
| -
|
| -// Read an ASN.1 length field. This also checks that the length does not extend
|
| -// beyond |end|.
|
| -static bool ReadLength(uint8** pos, uint8* end, uint32* result) {
|
| - READ_ASSERT(*pos < end);
|
| - int length = 0;
|
| -
|
| - // If the MSB is not set, the length is just the byte itself.
|
| - if (!(**pos & 0x80)) {
|
| - length = **pos;
|
| - (*pos)++;
|
| - } else {
|
| - // Otherwise, the lower 7 indicate the length of the length.
|
| - int length_of_length = **pos & 0x7F;
|
| - READ_ASSERT(length_of_length <= 4);
|
| - (*pos)++;
|
| - READ_ASSERT(*pos + length_of_length < end);
|
| -
|
| - length = 0;
|
| - for (int i = 0; i < length_of_length; ++i) {
|
| - length <<= 8;
|
| - length |= **pos;
|
| - (*pos)++;
|
| - }
|
| + NOTREACHED(); \
|
| + return false; \
|
| }
|
| -
|
| - READ_ASSERT(*pos + length <= end);
|
| - if (result) *result = length;
|
| - return true;
|
| -}
|
| -
|
| -// Read an ASN.1 type header and its length.
|
| -static bool ReadTypeHeaderAndLength(uint8** pos, uint8* end,
|
| - uint8 expected_tag, uint32* length) {
|
| - READ_ASSERT(*pos < end);
|
| - READ_ASSERT(**pos == expected_tag);
|
| - (*pos)++;
|
| -
|
| - return ReadLength(pos, end, length);
|
| -}
|
| -
|
| -// Read an ASN.1 sequence declaration. This consumes the type header and length
|
| -// field, but not the contents of the sequence.
|
| -static bool ReadSequence(uint8** pos, uint8* end) {
|
| - return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL);
|
| -}
|
| -
|
| -// Read the RSA AlgorithmIdentifier.
|
| -static bool ReadAlgorithmIdentifier(uint8** pos, uint8* end) {
|
| - READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end);
|
| - READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier,
|
| - sizeof(kRsaAlgorithmIdentifier)) == 0);
|
| - (*pos) += sizeof(kRsaAlgorithmIdentifier);
|
| - return true;
|
| -}
|
| -
|
| -// Read one of the two version fields in PrivateKeyInfo.
|
| -static bool ReadVersion(uint8** pos, uint8* end) {
|
| - uint32 length = 0;
|
| - if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
|
| - return false;
|
| -
|
| - // The version should be zero.
|
| - for (uint32 i = 0; i < length; ++i) {
|
| - READ_ASSERT(**pos == 0x00);
|
| - (*pos)++;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// Read an ASN.1 integer.
|
| -static bool ReadInteger(uint8** pos, uint8* end, std::vector<uint8>* out) {
|
| - uint32 length = 0;
|
| - if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
|
| - return false;
|
| -
|
| - // Read the bytes out in reverse order because of endianness.
|
| - for (uint32 i = length - 1; i > 0; --i)
|
| - out->push_back(*(*pos + i));
|
| -
|
| - // The last byte can be zero to force positiveness. We can ignore this.
|
| - if (**pos != 0x00)
|
| - out->push_back(**pos);
|
| -
|
| - (*pos) += length;
|
| - return true;
|
| -}
|
| -
|
| -static bool ReadIntegerWithExpectedSize(uint8** pos, uint8* end,
|
| - int expected_size,
|
| - std::vector<uint8>* out) {
|
| - if (!ReadInteger(pos, end, out))
|
| - return false;
|
| -
|
| - if (out->size() == expected_size + 1) {
|
| - READ_ASSERT(out->back() == 0x00);
|
| - out->pop_back();
|
| - } else {
|
| - READ_ASSERT(out->size() <= expected_size);
|
| - }
|
| -
|
| - // Pad out any missing bytes with null.
|
| - for (size_t i = out->size(); i < expected_size; ++i)
|
| - out->push_back(0x00);
|
| -
|
| - return true;
|
| -}
|
| -
|
| } // namespace
|
|
|
| -
|
| namespace base {
|
|
|
| // static
|
| @@ -245,46 +45,18 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
|
| if (!result->InitProvider())
|
| return NULL;
|
|
|
| - uint8* src = const_cast<uint8*>(&input.front());
|
| - uint8* end = src + input.size();
|
| - int version = -1;
|
| - std::vector<uint8> modulus;
|
| - std::vector<uint8> public_exponent;
|
| - std::vector<uint8> private_exponent;
|
| - std::vector<uint8> prime1;
|
| - std::vector<uint8> prime2;
|
| - std::vector<uint8> exponent1;
|
| - std::vector<uint8> exponent2;
|
| - std::vector<uint8> coefficient;
|
| -
|
| - if (!ReadSequence(&src, end) ||
|
| - !ReadVersion(&src, end) ||
|
| - !ReadAlgorithmIdentifier(&src, end) ||
|
| - !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
|
| - !ReadSequence(&src, end) ||
|
| - !ReadVersion(&src, end) ||
|
| - !ReadInteger(&src, end, &modulus))
|
| - return false;
|
| -
|
| - int mod_size = modulus.size();
|
| - READ_ASSERT(mod_size % 2 == 0);
|
| - int primes_size = mod_size / 2;
|
| -
|
| - if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent) ||
|
| - !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent) ||
|
| - !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1) ||
|
| - !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2) ||
|
| - !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1) ||
|
| - !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2) ||
|
| - !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient))
|
| - return false;
|
| -
|
| - READ_ASSERT(src == end);
|
| -
|
| - int blob_size = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulus.size() +
|
| - prime1.size() + prime2.size() +
|
| - exponent1.size() + exponent2.size() +
|
| - coefficient.size() + private_exponent.size();
|
| + PrivateKeyInfoCodec pki(false); // Little-Endian
|
| + pki.Import(input);
|
| +
|
| + int blob_size = sizeof(PUBLICKEYSTRUC) +
|
| + sizeof(RSAPUBKEY) +
|
| + pki.modulus()->size() +
|
| + pki.prime1()->size() +
|
| + pki.prime2()->size() +
|
| + pki.exponent1()->size() +
|
| + pki.exponent2()->size() +
|
| + pki.coefficient()->size() +
|
| + pki.private_exponent()->size();
|
| scoped_array<BYTE> blob(new BYTE[blob_size]);
|
|
|
| uint8* dest = blob.get();
|
| @@ -297,29 +69,29 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
|
|
|
| RSAPUBKEY* rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(dest);
|
| rsa_pub_key->magic = 0x32415352;
|
| - rsa_pub_key->bitlen = modulus.size() * 8;
|
| + rsa_pub_key->bitlen = pki.modulus()->size() * 8;
|
| int public_exponent_int = 0;
|
| - for (size_t i = public_exponent.size(); i > 0; --i) {
|
| + for (size_t i = pki.public_exponent()->size(); i > 0; --i) {
|
| public_exponent_int <<= 8;
|
| - public_exponent_int |= public_exponent[i - 1];
|
| + public_exponent_int |= (*pki.public_exponent())[i - 1];
|
| }
|
| rsa_pub_key->pubexp = public_exponent_int;
|
| dest += sizeof(RSAPUBKEY);
|
|
|
| - memcpy(dest, &modulus.front(), modulus.size());
|
| - dest += modulus.size();
|
| - memcpy(dest, &prime1.front(), prime1.size());
|
| - dest += prime1.size();
|
| - memcpy(dest, &prime2.front(), prime2.size());
|
| - dest += prime2.size();
|
| - memcpy(dest, &exponent1.front(), exponent1.size());
|
| - dest += exponent1.size();
|
| - memcpy(dest, &exponent2.front(), exponent2.size());
|
| - dest += exponent2.size();
|
| - memcpy(dest, &coefficient.front(), coefficient.size());
|
| - dest += coefficient.size();
|
| - memcpy(dest, &private_exponent.front(), private_exponent.size());
|
| - dest += private_exponent.size();
|
| + memcpy(dest, &pki.modulus()->front(), pki.modulus()->size());
|
| + dest += pki.modulus()->size();
|
| + memcpy(dest, &pki.prime1()->front(), pki.prime1()->size());
|
| + dest += pki.prime1()->size();
|
| + memcpy(dest, &pki.prime2()->front(), pki.prime2()->size());
|
| + dest += pki.prime2()->size();
|
| + memcpy(dest, &pki.exponent1()->front(), pki.exponent1()->size());
|
| + dest += pki.exponent1()->size();
|
| + memcpy(dest, &pki.exponent2()->front(), pki.exponent2()->size());
|
| + dest += pki.exponent2()->size();
|
| + memcpy(dest, &pki.coefficient()->front(), pki.coefficient()->size());
|
| + dest += pki.coefficient()->size();
|
| + memcpy(dest, &pki.private_exponent()->front(), pki.private_exponent()->size());
|
| + dest += pki.private_exponent()->size();
|
|
|
| READ_ASSERT(dest == blob.get() + blob_size);
|
| if (!CryptImportKey(
|
| @@ -375,59 +147,33 @@ bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) {
|
| int mod_size = rsa_pub_key->bitlen / 8;
|
| int primes_size = rsa_pub_key->bitlen / 16;
|
|
|
| - uint8* modulus = pos;
|
| + PrivateKeyInfoCodec pki(false); // Little-Endian
|
| +
|
| + pki.modulus()->assign(pos, pos + mod_size);
|
| pos += mod_size;
|
|
|
| - uint8* prime1 = pos;
|
| + pki.prime1()->assign(pos, pos + primes_size);
|
| pos += primes_size;
|
| - uint8* prime2 = pos;
|
| + pki.prime2()->assign(pos, pos + primes_size);
|
| pos += primes_size;
|
|
|
| - uint8* exponent1 = pos;
|
| + pki.exponent1()->assign(pos, pos + primes_size);
|
| pos += primes_size;
|
| - uint8* exponent2 = pos;
|
| + pki.exponent2()->assign(pos, pos + primes_size);
|
| pos += primes_size;
|
|
|
| - uint8* coefficient = pos;
|
| + pki.coefficient()->assign(pos, pos + primes_size);
|
| pos += primes_size;
|
|
|
| - uint8* private_exponent = pos;
|
| + pki.private_exponent()->assign(pos, pos + mod_size);
|
| pos += mod_size;
|
|
|
| - CHECK((pos - blob_length) == reinterpret_cast<BYTE*>(publickey_struct));
|
| + pki.public_exponent()->assign(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp),
|
| + reinterpret_cast<uint8*>(&rsa_pub_key->pubexp) + 4);
|
|
|
| - std::list<uint8> content;
|
| -
|
| - // Version (always zero)
|
| - uint8 version = 0;
|
| -
|
| - // We build up the output in reverse order to prevent having to do copies to
|
| - // figure out the length.
|
| - PrependInteger(coefficient, primes_size, &content);
|
| - PrependInteger(exponent2, primes_size, &content);
|
| - PrependInteger(exponent1, primes_size, &content);
|
| - PrependInteger(prime2, primes_size, &content);
|
| - PrependInteger(prime1, primes_size, &content);
|
| - PrependInteger(private_exponent, mod_size, &content);
|
| - PrependInteger(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp), 4, &content);
|
| - PrependInteger(modulus, mod_size, &content);
|
| - PrependInteger(&version, 1, &content);
|
| - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
|
| - PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
|
| -
|
| - // RSA algorithm OID
|
| - for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
|
| - content.push_front(kRsaAlgorithmIdentifier[i - 1]);
|
| -
|
| - PrependInteger(&version, 1, &content);
|
| - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
|
| -
|
| - // Copy everying into the output.
|
| - output->reserve(content.size());
|
| - for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
|
| - output->push_back(*i);
|
| + CHECK((pos - blob_length) == reinterpret_cast<BYTE*>(publickey_struct));
|
|
|
| - return true;
|
| + return pki.Export(output);
|
| }
|
|
|
| bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) {
|
|
|