summaryrefslogtreecommitdiffstats
path: root/base/crypto/rsa_private_key.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/crypto/rsa_private_key.cc')
-rw-r--r--base/crypto/rsa_private_key.cc299
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;
}