| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/crypto/rsa_private_key.h" | 5 #include "base/crypto/rsa_private_key.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/scoped_ptr.h" | 10 #include "base/scoped_ptr.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 } | 41 } |
| 42 } // namespace | 42 } // namespace |
| 43 | 43 |
| 44 namespace base { | 44 namespace base { |
| 45 | 45 |
| 46 const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { | 46 const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { |
| 47 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, | 47 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, |
| 48 0x05, 0x00 | 48 0x05, 0x00 |
| 49 }; | 49 }; |
| 50 | 50 |
| 51 void PrivateKeyInfoCodec::PrependBytes(uint8* val, | |
| 52 int start, | |
| 53 int num_bytes, | |
| 54 std::list<uint8>* data) { | |
| 55 while (num_bytes > 0) { | |
| 56 --num_bytes; | |
| 57 data->push_front(val[start + num_bytes]); | |
| 58 } | |
| 59 } | |
| 60 | |
| 61 void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8>* data) { | |
| 62 // The high bit is used to indicate whether additional octets are needed to | |
| 63 // represent the length. | |
| 64 if (size < 0x80) { | |
| 65 data->push_front(static_cast<uint8>(size)); | |
| 66 } else { | |
| 67 uint8 num_bytes = 0; | |
| 68 while (size > 0) { | |
| 69 data->push_front(static_cast<uint8>(size & 0xFF)); | |
| 70 size >>= 8; | |
| 71 num_bytes++; | |
| 72 } | |
| 73 CHECK_LE(num_bytes, 4); | |
| 74 data->push_front(0x80 | num_bytes); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, | |
| 79 uint32 length, | |
| 80 std::list<uint8>* output) { | |
| 81 PrependLength(length, output); | |
| 82 output->push_front(type); | |
| 83 } | |
| 84 | |
| 85 void PrivateKeyInfoCodec::PrependBitString(uint8* val, | |
| 86 int num_bytes, | |
| 87 std::list<uint8>* output) { | |
| 88 // Start with the data. | |
| 89 PrependBytes(val, 0, num_bytes, output); | |
| 90 // Zero unused bits. | |
| 91 output->push_front(0); | |
| 92 // Add the length. | |
| 93 PrependLength(num_bytes + 1, output); | |
| 94 // Finally, add the bit string tag. | |
| 95 output->push_front((uint8) kBitStringTag); | |
| 96 } | |
| 97 | |
| 98 bool PrivateKeyInfoCodec::ReadLength(uint8** pos, uint8* end, uint32* result) { | |
| 99 READ_ASSERT(*pos < end); | |
| 100 int length = 0; | |
| 101 | |
| 102 // If the MSB is not set, the length is just the byte itself. | |
| 103 if (!(**pos & 0x80)) { | |
| 104 length = **pos; | |
| 105 (*pos)++; | |
| 106 } else { | |
| 107 // Otherwise, the lower 7 indicate the length of the length. | |
| 108 int length_of_length = **pos & 0x7F; | |
| 109 READ_ASSERT(length_of_length <= 4); | |
| 110 (*pos)++; | |
| 111 READ_ASSERT(*pos + length_of_length < end); | |
| 112 | |
| 113 length = 0; | |
| 114 for (int i = 0; i < length_of_length; ++i) { | |
| 115 length <<= 8; | |
| 116 length |= **pos; | |
| 117 (*pos)++; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 READ_ASSERT(*pos + length <= end); | |
| 122 if (result) *result = length; | |
| 123 return true; | |
| 124 } | |
| 125 | |
| 126 bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8** pos, | |
| 127 uint8* end, | |
| 128 uint8 expected_tag, | |
| 129 uint32* length) { | |
| 130 READ_ASSERT(*pos < end); | |
| 131 READ_ASSERT(**pos == expected_tag); | |
| 132 (*pos)++; | |
| 133 | |
| 134 return ReadLength(pos, end, length); | |
| 135 } | |
| 136 | |
| 137 bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { | |
| 138 return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); | |
| 139 } | |
| 140 | |
| 141 bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { | |
| 142 READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); | |
| 143 READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, | |
| 144 sizeof(kRsaAlgorithmIdentifier)) == 0); | |
| 145 (*pos) += sizeof(kRsaAlgorithmIdentifier); | |
| 146 return true; | |
| 147 } | |
| 148 | |
| 149 bool PrivateKeyInfoCodec::ReadVersion(uint8** pos, uint8* end) { | |
| 150 uint32 length = 0; | |
| 151 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length)) | |
| 152 return false; | |
| 153 | |
| 154 // The version should be zero. | |
| 155 for (uint32 i = 0; i < length; ++i) { | |
| 156 READ_ASSERT(**pos == 0x00); | |
| 157 (*pos)++; | |
| 158 } | |
| 159 | |
| 160 return true; | |
| 161 } | |
| 162 | |
| 163 PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) | 51 PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) |
| 164 : big_endian_(big_endian) {} | 52 : big_endian_(big_endian) {} |
| 165 | 53 |
| 166 PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {} | 54 PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {} |
| 167 | 55 |
| 168 bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) { | 56 bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) { |
| 169 std::list<uint8> content; | 57 std::list<uint8> content; |
| 170 | 58 |
| 171 // Version (always zero) | 59 // Version (always zero) |
| 172 uint8 version = 0; | 60 uint8 version = 0; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 202 |
| 315 PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); | 203 PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); |
| 316 } | 204 } |
| 317 | 205 |
| 318 bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, | 206 bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, |
| 319 uint8* end, | 207 uint8* end, |
| 320 std::vector<uint8>* out) { | 208 std::vector<uint8>* out) { |
| 321 return ReadIntegerImpl(pos, end, out, big_endian_); | 209 return ReadIntegerImpl(pos, end, out, big_endian_); |
| 322 } | 210 } |
| 323 | 211 |
| 212 bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, |
| 213 uint8* end, |
| 214 size_t expected_size, |
| 215 std::vector<uint8>* out) { |
| 216 std::vector<uint8> temp; |
| 217 if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian |
| 218 return false; |
| 219 |
| 220 int pad = expected_size - temp.size(); |
| 221 int index = 0; |
| 222 if (out->size() == expected_size + 1) { |
| 223 READ_ASSERT(out->front() == 0x00); |
| 224 pad++; |
| 225 index++; |
| 226 } else { |
| 227 READ_ASSERT(out->size() <= expected_size); |
| 228 } |
| 229 |
| 230 while (pad) { |
| 231 out->push_back(0x00); |
| 232 pad--; |
| 233 } |
| 234 out->insert(out->end(), temp.begin(), temp.end()); |
| 235 |
| 236 // Reverse output if little-endian. |
| 237 if (!big_endian_) |
| 238 reverse(out->begin(), out->end()); |
| 239 return true; |
| 240 } |
| 241 |
| 324 bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, | 242 bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, |
| 325 uint8* end, | 243 uint8* end, |
| 326 std::vector<uint8>* out, | 244 std::vector<uint8>* out, |
| 327 bool big_endian) { | 245 bool big_endian) { |
| 328 uint32 length = 0; | 246 uint32 length = 0; |
| 329 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length) | 247 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length) |
| 330 return false; | 248 return false; |
| 331 | 249 |
| 332 // The first byte can be zero to force positiveness. We can ignore this. | 250 // The first byte can be zero to force positiveness. We can ignore this. |
| 333 if (**pos == 0x00) { | 251 if (**pos == 0x00) { |
| 334 ++(*pos); | 252 ++(*pos); |
| 335 --length; | 253 --length; |
| 336 } | 254 } |
| 337 | 255 |
| 338 if (length) | 256 if (length) |
| 339 out->insert(out->end(), *pos, (*pos) + length); | 257 out->insert(out->end(), *pos, (*pos) + length); |
| 340 | 258 |
| 341 (*pos) += length; | 259 (*pos) += length; |
| 342 | 260 |
| 343 // Reverse output if little-endian. | 261 // Reverse output if little-endian. |
| 344 if (!big_endian) | 262 if (!big_endian) |
| 345 reverse(out->begin(), out->end()); | 263 reverse(out->begin(), out->end()); |
| 346 return true; | 264 return true; |
| 347 } | 265 } |
| 348 | 266 |
| 349 bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, | 267 void PrivateKeyInfoCodec::PrependBytes(uint8* val, |
| 350 uint8* end, | 268 int start, |
| 351 size_t expected_size, | 269 int num_bytes, |
| 352 std::vector<uint8>* out) { | 270 std::list<uint8>* data) { |
| 353 std::vector<uint8> temp; | 271 while (num_bytes > 0) { |
| 354 if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian | 272 --num_bytes; |
| 355 return false; | 273 data->push_front(val[start + num_bytes]); |
| 274 } |
| 275 } |
| 356 | 276 |
| 357 int pad = expected_size - temp.size(); | 277 void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8>* data) { |
| 358 int index = 0; | 278 // The high bit is used to indicate whether additional octets are needed to |
| 359 if (out->size() == expected_size + 1) { | 279 // represent the length. |
| 360 READ_ASSERT(out->front() == 0x00); | 280 if (size < 0x80) { |
| 361 pad++; | 281 data->push_front(static_cast<uint8>(size)); |
| 362 index++; | |
| 363 } else { | 282 } else { |
| 364 READ_ASSERT(out->size() <= expected_size); | 283 uint8 num_bytes = 0; |
| 284 while (size > 0) { |
| 285 data->push_front(static_cast<uint8>(size & 0xFF)); |
| 286 size >>= 8; |
| 287 num_bytes++; |
| 288 } |
| 289 CHECK_LE(num_bytes, 4); |
| 290 data->push_front(0x80 | num_bytes); |
| 291 } |
| 292 } |
| 293 |
| 294 void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, |
| 295 uint32 length, |
| 296 std::list<uint8>* output) { |
| 297 PrependLength(length, output); |
| 298 output->push_front(type); |
| 299 } |
| 300 |
| 301 void PrivateKeyInfoCodec::PrependBitString(uint8* val, |
| 302 int num_bytes, |
| 303 std::list<uint8>* output) { |
| 304 // Start with the data. |
| 305 PrependBytes(val, 0, num_bytes, output); |
| 306 // Zero unused bits. |
| 307 output->push_front(0); |
| 308 // Add the length. |
| 309 PrependLength(num_bytes + 1, output); |
| 310 // Finally, add the bit string tag. |
| 311 output->push_front((uint8) kBitStringTag); |
| 312 } |
| 313 |
| 314 bool PrivateKeyInfoCodec::ReadLength(uint8** pos, uint8* end, uint32* result) { |
| 315 READ_ASSERT(*pos < end); |
| 316 int length = 0; |
| 317 |
| 318 // If the MSB is not set, the length is just the byte itself. |
| 319 if (!(**pos & 0x80)) { |
| 320 length = **pos; |
| 321 (*pos)++; |
| 322 } else { |
| 323 // Otherwise, the lower 7 indicate the length of the length. |
| 324 int length_of_length = **pos & 0x7F; |
| 325 READ_ASSERT(length_of_length <= 4); |
| 326 (*pos)++; |
| 327 READ_ASSERT(*pos + length_of_length < end); |
| 328 |
| 329 length = 0; |
| 330 for (int i = 0; i < length_of_length; ++i) { |
| 331 length <<= 8; |
| 332 length |= **pos; |
| 333 (*pos)++; |
| 334 } |
| 365 } | 335 } |
| 366 | 336 |
| 367 while (pad) { | 337 READ_ASSERT(*pos + length <= end); |
| 368 out->push_back(0x00); | 338 if (result) *result = length; |
| 369 pad--; | |
| 370 } | |
| 371 out->insert(out->end(), temp.begin(), temp.end()); | |
| 372 | |
| 373 // Reverse output if little-endian. | |
| 374 if (!big_endian_) | |
| 375 reverse(out->begin(), out->end()); | |
| 376 return true; | 339 return true; |
| 377 } | 340 } |
| 378 | 341 |
| 342 bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8** pos, |
| 343 uint8* end, |
| 344 uint8 expected_tag, |
| 345 uint32* length) { |
| 346 READ_ASSERT(*pos < end); |
| 347 READ_ASSERT(**pos == expected_tag); |
| 348 (*pos)++; |
| 349 |
| 350 return ReadLength(pos, end, length); |
| 351 } |
| 352 |
| 353 bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { |
| 354 return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); |
| 355 } |
| 356 |
| 357 bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { |
| 358 READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); |
| 359 READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, |
| 360 sizeof(kRsaAlgorithmIdentifier)) == 0); |
| 361 (*pos) += sizeof(kRsaAlgorithmIdentifier); |
| 362 return true; |
| 363 } |
| 364 |
| 365 bool PrivateKeyInfoCodec::ReadVersion(uint8** pos, uint8* end) { |
| 366 uint32 length = 0; |
| 367 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length)) |
| 368 return false; |
| 369 |
| 370 // The version should be zero. |
| 371 for (uint32 i = 0; i < length; ++i) { |
| 372 READ_ASSERT(**pos == 0x00); |
| 373 (*pos)++; |
| 374 } |
| 375 |
| 376 return true; |
| 377 } |
| 378 |
| 379 } // namespace base | 379 } // namespace base |
| OLD | NEW |