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 |