diff options
Diffstat (limited to 'base/crypto/rsa_private_key.cc')
-rw-r--r-- | base/crypto/rsa_private_key.cc | 299 |
1 files changed, 155 insertions, 144 deletions
diff --git a/base/crypto/rsa_private_key.cc b/base/crypto/rsa_private_key.cc index 75da7e4..024f741 100644 --- a/base/crypto/rsa_private_key.cc +++ b/base/crypto/rsa_private_key.cc @@ -4,6 +4,7 @@ #include "base/crypto/rsa_private_key.h" +#include <algorithm> #include <list> #include "base/logging.h" @@ -48,118 +49,6 @@ const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { 0x05, 0x00 }; -void PrivateKeyInfoCodec::PrependBytes(uint8* val, - int start, - int num_bytes, - std::list<uint8>* data) { - while (num_bytes > 0) { - --num_bytes; - data->push_front(val[start + num_bytes]); - } -} - -void PrivateKeyInfoCodec::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_LE(num_bytes, 4); - data->push_front(0x80 | num_bytes); - } -} - -void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, - uint32 length, - std::list<uint8>* output) { - PrependLength(length, output); - output->push_front(type); -} - -void PrivateKeyInfoCodec::PrependBitString(uint8* val, - int num_bytes, - std::list<uint8>* output) { - // Start with the data. - PrependBytes(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((uint8) kBitStringTag); -} - -bool PrivateKeyInfoCodec::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; -} - -bool PrivateKeyInfoCodec::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); -} - -bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { - return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); -} - -bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { - READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); - READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, - sizeof(kRsaAlgorithmIdentifier)) == 0); - (*pos) += sizeof(kRsaAlgorithmIdentifier); - return true; -} - -bool PrivateKeyInfoCodec::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; -} - PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) : big_endian_(big_endian) {} @@ -200,19 +89,12 @@ bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) { bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) { // 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(); + if (!ExportPublicKey(&bit_string)) + return false; + // Add the sequence as the contents of a bit string. + std::list<uint8> content; PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()), &content); @@ -231,6 +113,23 @@ bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) { return true; } +bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8>* output) { + // 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 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; +} + bool PrivateKeyInfoCodec::Import(const std::vector<uint8>& input) { if (input.empty()) { return false; @@ -321,6 +220,36 @@ bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, return ReadIntegerImpl(pos, end, out, big_endian_); } +bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, + uint8* end, + size_t expected_size, + std::vector<uint8>* out) { + std::vector<uint8> temp; + if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian + return false; + + int pad = expected_size - temp.size(); + int index = 0; + if (out->size() == expected_size + 1) { + READ_ASSERT(out->front() == 0x00); + pad++; + index++; + } else { + READ_ASSERT(out->size() <= expected_size); + } + + while (pad) { + out->push_back(0x00); + pad--; + } + out->insert(out->end(), temp.begin(), temp.end()); + + // Reverse output if little-endian. + if (!big_endian_) + reverse(out->begin(), out->end()); + return true; +} + bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, uint8* end, std::vector<uint8>* out, @@ -346,33 +275,115 @@ bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, return true; } -bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, - uint8* end, - size_t expected_size, - std::vector<uint8>* out) { - std::vector<uint8> temp; - if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian - return false; +void PrivateKeyInfoCodec::PrependBytes(uint8* val, + int start, + int num_bytes, + std::list<uint8>* data) { + while (num_bytes > 0) { + --num_bytes; + data->push_front(val[start + num_bytes]); + } +} - int pad = expected_size - temp.size(); - int index = 0; - if (out->size() == expected_size + 1) { - READ_ASSERT(out->front() == 0x00); - pad++; - index++; +void PrivateKeyInfoCodec::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 { - READ_ASSERT(out->size() <= expected_size); + uint8 num_bytes = 0; + while (size > 0) { + data->push_front(static_cast<uint8>(size & 0xFF)); + size >>= 8; + num_bytes++; + } + CHECK_LE(num_bytes, 4); + data->push_front(0x80 | num_bytes); } +} - while (pad) { - out->push_back(0x00); - pad--; +void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, + uint32 length, + std::list<uint8>* output) { + PrependLength(length, output); + output->push_front(type); +} + +void PrivateKeyInfoCodec::PrependBitString(uint8* val, + int num_bytes, + std::list<uint8>* output) { + // Start with the data. + PrependBytes(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((uint8) kBitStringTag); +} + +bool PrivateKeyInfoCodec::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; +} + +bool PrivateKeyInfoCodec::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); +} + +bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { + return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); +} + +bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { + READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); + READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, + sizeof(kRsaAlgorithmIdentifier)) == 0); + (*pos) += sizeof(kRsaAlgorithmIdentifier); + return true; +} + +bool PrivateKeyInfoCodec::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)++; } - out->insert(out->end(), temp.begin(), temp.end()); - // Reverse output if little-endian. - if (!big_endian_) - reverse(out->begin(), out->end()); return true; } |