Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(529)

Unified Diff: base/crypto/rsa_private_key_mac.cc

Issue 242136: Refactor ASN1 parsing/serializationg (Closed)
Patch Set: more cr changes Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/crypto/rsa_private_key.cc ('k') | base/crypto/rsa_private_key_nss.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « base/crypto/rsa_private_key.cc ('k') | base/crypto/rsa_private_key_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698