Index: base/crypto/rsa_private_key_mac.cc |
diff --git a/base/crypto/rsa_private_key_mac.cc b/base/crypto/rsa_private_key_mac.cc |
index f44115ce3ad57756745140a5602a20e898ee7026..61845e34cc41d1bab31114666067475a5e3ac7fd 100644 |
--- a/base/crypto/rsa_private_key_mac.cc |
+++ b/base/crypto/rsa_private_key_mac.cc |
@@ -10,187 +10,6 @@ |
#include "base/logging.h" |
#include "base/scoped_ptr.h" |
-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; |
-const uint8 kBitStringTag = 0x03; |
- |
-// Helper for error handling during key import. |
-#define READ_ASSERT(truth) \ |
- if (!(truth)) { \ |
- NOTREACHED(); \ |
- return false; \ |
- } |
- |
-static void PrependBytesInOrder(uint8* val, int start, int num_bytes, |
- std::list<uint8>* data) { |
- while(num_bytes > start) { |
- --num_bytes; |
- data->push_front(val[num_bytes]); |
- } |
-} |
- |
-// 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 bit string |
-static void PrependBitString(uint8* val, int num_bytes, |
- std::list<uint8>* output) { |
- // Start with the data. |
- PrependBytesInOrder(val, 0, num_bytes, output); |
- // Zero unused bits. |
- output->push_front(0); |
- // Add the length. |
- PrependLength(num_bytes + 1, output); |
- // Finally, add the bit string tag. |
- output->push_front(kBitStringTag); |
-} |
- |
-// Helper to prepend an ASN.1 integer. |
-static void PrependInteger(uint8* val, int num_bytes, std::list<uint8>* data) { |
- // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes |
- // from the most-significant end of the integer. |
- int start = 0; |
- while (start < (num_bytes - 1) && val[start] == 0x00) |
- start++; |
- |
- PrependBytesInOrder(val, start, num_bytes, data); |
- |
- // ASN.1 integers are signed. To encode a positive integer whose sign bit |
- // (the most significant bit) would otherwise be set and make the number |
- // negative, ASN.1 requires a leading null byte to force the integer to be |
- // positive. |
- if ((val[start] & 0x80) != 0) { |
- data->push_front(0x00); |
- num_bytes++; |
- } |
- |
- PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); |
-} |
- |
-// 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)++; |
- } |
- } |
- |
- 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) || !length) |
- return false; |
- |
- // The first byte can be zero to force positiveness. We can ignore this. |
- if (**pos == 0x00) { |
- ++(*pos); |
- --length; |
- } |
- |
- if (length) |
- out->insert(out->end(), *pos, (*pos) + length); |
- |
- (*pos) += length; |
- return true; |
-} |
- |
-} // namespace |
- |
namespace base { |
// static |
@@ -318,55 +137,12 @@ bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { |
} |
bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { |
- if (!key_.KeyData.Data || !key_.KeyData.Length) { |
- return false; |
- } |
- |
- // Parse the private key info up to the public key values, ignoring |
- // the subsequent private key values. |
- uint8* src = key_.KeyData.Data; |
- uint8* end = src + key_.KeyData.Length; |
- std::vector<uint8> modulus; |
- std::vector<uint8> public_exponent; |
- 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) || |
- !ReadInteger(&src, end, &public_exponent)) |
- return false; |
- |
- // Create a sequence with the modulus (n) and public exponent (e). |
- std::list<uint8> content; |
- PrependInteger(&public_exponent[0], static_cast<int>(public_exponent.size()), |
- &content); |
- PrependInteger(&modulus[0], static_cast<int>(modulus.size()), &content); |
- PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); |
- |
- // Copy the sequence with n and e into a buffer. |
- std::vector<uint8> bit_string; |
- for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) |
- bit_string.push_back(*i); |
- content.clear(); |
- // Add the sequence as the contents of a bit string. |
- PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()), |
- &content); |
- |
- // Add the RSA algorithm OID. |
- for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) |
- content.push_front(kRsaAlgorithmIdentifier[i - 1]); |
- |
- // Finally, wrap everything in a sequence. |
- PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); |
- |
- // Copy everything into the output. |
- output->reserve(content.size()); |
- for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) |
- output->push_back(*i); |
- |
- return true; |
+ PrivateKeyInfoCodec private_key_info(true); |
+ std::vector<uint8> private_key_data; |
+ private_key_data.assign(key_.KeyData.Data, |
+ key_.KeyData.Data + key_.KeyData.Length); |
+ return (private_key_info.Import(private_key_data) && |
+ private_key_info.ExportPublicKeyInfo(output)); |
} |
} // namespace base |