OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/crypto/rsa_private_key.h" | |
6 | |
7 #include <algorithm> | |
8 #include <list> | |
9 | |
10 #include "base/logging.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/string_util.h" | |
13 | |
14 // This file manually encodes and decodes RSA private keys using PrivateKeyInfo | |
15 // from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are: | |
16 // | |
17 // PrivateKeyInfo ::= SEQUENCE { | |
18 // version Version, | |
19 // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, | |
20 // privateKey PrivateKey, | |
21 // attributes [0] IMPLICIT Attributes OPTIONAL | |
22 // } | |
23 // | |
24 // RSAPrivateKey ::= SEQUENCE { | |
25 // version Version, | |
26 // modulus INTEGER, | |
27 // publicExponent INTEGER, | |
28 // privateExponent INTEGER, | |
29 // prime1 INTEGER, | |
30 // prime2 INTEGER, | |
31 // exponent1 INTEGER, | |
32 // exponent2 INTEGER, | |
33 // coefficient INTEGER | |
34 // } | |
35 | |
36 namespace { | |
37 // Helper for error handling during key import. | |
38 #define READ_ASSERT(truth) \ | |
39 if (!(truth)) { \ | |
40 NOTREACHED(); \ | |
41 return false; \ | |
42 } | |
43 } // namespace | |
44 | |
45 namespace base { | |
46 | |
47 const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { | |
48 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, | |
49 0x05, 0x00 | |
50 }; | |
51 | |
52 PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) | |
53 : big_endian_(big_endian) {} | |
54 | |
55 PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {} | |
56 | |
57 bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) { | |
58 std::list<uint8> content; | |
59 | |
60 // Version (always zero) | |
61 uint8 version = 0; | |
62 | |
63 PrependInteger(coefficient_, &content); | |
64 PrependInteger(exponent2_, &content); | |
65 PrependInteger(exponent1_, &content); | |
66 PrependInteger(prime2_, &content); | |
67 PrependInteger(prime1_, &content); | |
68 PrependInteger(private_exponent_, &content); | |
69 PrependInteger(public_exponent_, &content); | |
70 PrependInteger(modulus_, &content); | |
71 PrependInteger(&version, 1, &content); | |
72 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); | |
73 PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content); | |
74 | |
75 // RSA algorithm OID | |
76 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) | |
77 content.push_front(kRsaAlgorithmIdentifier[i - 1]); | |
78 | |
79 PrependInteger(&version, 1, &content); | |
80 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); | |
81 | |
82 // Copy everying into the output. | |
83 output->reserve(content.size()); | |
84 for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) | |
85 output->push_back(*i); | |
86 | |
87 return true; | |
88 } | |
89 | |
90 bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) { | |
91 // Create a sequence with the modulus (n) and public exponent (e). | |
92 std::vector<uint8> bit_string; | |
93 if (!ExportPublicKey(&bit_string)) | |
94 return false; | |
95 | |
96 // Add the sequence as the contents of a bit string. | |
97 std::list<uint8> content; | |
98 PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()), | |
99 &content); | |
100 | |
101 // Add the RSA algorithm OID. | |
102 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) | |
103 content.push_front(kRsaAlgorithmIdentifier[i - 1]); | |
104 | |
105 // Finally, wrap everything in a sequence. | |
106 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); | |
107 | |
108 // Copy everything into the output. | |
109 output->reserve(content.size()); | |
110 for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) | |
111 output->push_back(*i); | |
112 | |
113 return true; | |
114 } | |
115 | |
116 bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8>* output) { | |
117 // Create a sequence with the modulus (n) and public exponent (e). | |
118 std::list<uint8> content; | |
119 PrependInteger(&public_exponent_[0], | |
120 static_cast<int>(public_exponent_.size()), | |
121 &content); | |
122 PrependInteger(&modulus_[0], static_cast<int>(modulus_.size()), &content); | |
123 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); | |
124 | |
125 // Copy everything into the output. | |
126 output->reserve(content.size()); | |
127 for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) | |
128 output->push_back(*i); | |
129 | |
130 return true; | |
131 } | |
132 | |
133 bool PrivateKeyInfoCodec::Import(const std::vector<uint8>& input) { | |
134 if (input.empty()) { | |
135 return false; | |
136 } | |
137 | |
138 // Parse the private key info up to the public key values, ignoring | |
139 // the subsequent private key values. | |
140 uint8* src = const_cast<uint8*>(&input.front()); | |
141 uint8* end = src + input.size(); | |
142 if (!ReadSequence(&src, end) || | |
143 !ReadVersion(&src, end) || | |
144 !ReadAlgorithmIdentifier(&src, end) || | |
145 !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) || | |
146 !ReadSequence(&src, end) || | |
147 !ReadVersion(&src, end) || | |
148 !ReadInteger(&src, end, &modulus_)) | |
149 return false; | |
150 | |
151 int mod_size = modulus_.size(); | |
152 READ_ASSERT(mod_size % 2 == 0); | |
153 int primes_size = mod_size / 2; | |
154 | |
155 if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) || | |
156 !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) || | |
157 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) || | |
158 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) || | |
159 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) || | |
160 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) || | |
161 !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_)) | |
162 return false; | |
163 | |
164 READ_ASSERT(src == end); | |
165 | |
166 | |
167 return true; | |
168 } | |
169 | |
170 void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8>& in, | |
171 std::list<uint8>* out) { | |
172 uint8* ptr = const_cast<uint8*>(&in.front()); | |
173 PrependIntegerImpl(ptr, in.size(), out, big_endian_); | |
174 } | |
175 | |
176 // Helper to prepend an ASN.1 integer. | |
177 void PrivateKeyInfoCodec::PrependInteger(uint8* val, | |
178 int num_bytes, | |
179 std::list<uint8>* data) { | |
180 PrependIntegerImpl(val, num_bytes, data, big_endian_); | |
181 } | |
182 | |
183 void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val, | |
184 int num_bytes, | |
185 std::list<uint8>* data, | |
186 bool big_endian) { | |
187 // Reverse input if little-endian. | |
188 std::vector<uint8> tmp; | |
189 if (!big_endian) { | |
190 tmp.assign(val, val + num_bytes); | |
191 reverse(tmp.begin(), tmp.end()); | |
192 val = &tmp.front(); | |
193 } | |
194 | |
195 // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes | |
196 // from the most-significant end of the integer. | |
197 int start = 0; | |
198 while (start < (num_bytes - 1) && val[start] == 0x00) { | |
199 start++; | |
200 num_bytes--; | |
201 } | |
202 PrependBytes(val, start, num_bytes, data); | |
203 | |
204 // ASN.1 integers are signed. To encode a positive integer whose sign bit | |
205 // (the most significant bit) would otherwise be set and make the number | |
206 // negative, ASN.1 requires a leading null byte to force the integer to be | |
207 // positive. | |
208 uint8 front = data->front(); | |
209 if ((front & 0x80) != 0) { | |
210 data->push_front(0x00); | |
211 num_bytes++; | |
212 } | |
213 | |
214 PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); | |
215 } | |
216 | |
217 bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, | |
218 uint8* end, | |
219 std::vector<uint8>* out) { | |
220 return ReadIntegerImpl(pos, end, out, big_endian_); | |
221 } | |
222 | |
223 bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, | |
224 uint8* end, | |
225 size_t expected_size, | |
226 std::vector<uint8>* out) { | |
227 std::vector<uint8> temp; | |
228 if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian | |
229 return false; | |
230 | |
231 int pad = expected_size - temp.size(); | |
232 int index = 0; | |
233 if (out->size() == expected_size + 1) { | |
234 READ_ASSERT(out->front() == 0x00); | |
235 pad++; | |
236 index++; | |
237 } else { | |
238 READ_ASSERT(out->size() <= expected_size); | |
239 } | |
240 | |
241 while (pad) { | |
242 out->push_back(0x00); | |
243 pad--; | |
244 } | |
245 out->insert(out->end(), temp.begin(), temp.end()); | |
246 | |
247 // Reverse output if little-endian. | |
248 if (!big_endian_) | |
249 reverse(out->begin(), out->end()); | |
250 return true; | |
251 } | |
252 | |
253 bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, | |
254 uint8* end, | |
255 std::vector<uint8>* out, | |
256 bool big_endian) { | |
257 uint32 length = 0; | |
258 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length) | |
259 return false; | |
260 | |
261 // The first byte can be zero to force positiveness. We can ignore this. | |
262 if (**pos == 0x00) { | |
263 ++(*pos); | |
264 --length; | |
265 } | |
266 | |
267 if (length) | |
268 out->insert(out->end(), *pos, (*pos) + length); | |
269 | |
270 (*pos) += length; | |
271 | |
272 // Reverse output if little-endian. | |
273 if (!big_endian) | |
274 reverse(out->begin(), out->end()); | |
275 return true; | |
276 } | |
277 | |
278 void PrivateKeyInfoCodec::PrependBytes(uint8* val, | |
279 int start, | |
280 int num_bytes, | |
281 std::list<uint8>* data) { | |
282 while (num_bytes > 0) { | |
283 --num_bytes; | |
284 data->push_front(val[start + num_bytes]); | |
285 } | |
286 } | |
287 | |
288 void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8>* data) { | |
289 // The high bit is used to indicate whether additional octets are needed to | |
290 // represent the length. | |
291 if (size < 0x80) { | |
292 data->push_front(static_cast<uint8>(size)); | |
293 } else { | |
294 uint8 num_bytes = 0; | |
295 while (size > 0) { | |
296 data->push_front(static_cast<uint8>(size & 0xFF)); | |
297 size >>= 8; | |
298 num_bytes++; | |
299 } | |
300 CHECK_LE(num_bytes, 4); | |
301 data->push_front(0x80 | num_bytes); | |
302 } | |
303 } | |
304 | |
305 void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, | |
306 uint32 length, | |
307 std::list<uint8>* output) { | |
308 PrependLength(length, output); | |
309 output->push_front(type); | |
310 } | |
311 | |
312 void PrivateKeyInfoCodec::PrependBitString(uint8* val, | |
313 int num_bytes, | |
314 std::list<uint8>* output) { | |
315 // Start with the data. | |
316 PrependBytes(val, 0, num_bytes, output); | |
317 // Zero unused bits. | |
318 output->push_front(0); | |
319 // Add the length. | |
320 PrependLength(num_bytes + 1, output); | |
321 // Finally, add the bit string tag. | |
322 output->push_front((uint8) kBitStringTag); | |
323 } | |
324 | |
325 bool PrivateKeyInfoCodec::ReadLength(uint8** pos, uint8* end, uint32* result) { | |
326 READ_ASSERT(*pos < end); | |
327 int length = 0; | |
328 | |
329 // If the MSB is not set, the length is just the byte itself. | |
330 if (!(**pos & 0x80)) { | |
331 length = **pos; | |
332 (*pos)++; | |
333 } else { | |
334 // Otherwise, the lower 7 indicate the length of the length. | |
335 int length_of_length = **pos & 0x7F; | |
336 READ_ASSERT(length_of_length <= 4); | |
337 (*pos)++; | |
338 READ_ASSERT(*pos + length_of_length < end); | |
339 | |
340 length = 0; | |
341 for (int i = 0; i < length_of_length; ++i) { | |
342 length <<= 8; | |
343 length |= **pos; | |
344 (*pos)++; | |
345 } | |
346 } | |
347 | |
348 READ_ASSERT(*pos + length <= end); | |
349 if (result) *result = length; | |
350 return true; | |
351 } | |
352 | |
353 bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8** pos, | |
354 uint8* end, | |
355 uint8 expected_tag, | |
356 uint32* length) { | |
357 READ_ASSERT(*pos < end); | |
358 READ_ASSERT(**pos == expected_tag); | |
359 (*pos)++; | |
360 | |
361 return ReadLength(pos, end, length); | |
362 } | |
363 | |
364 bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { | |
365 return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); | |
366 } | |
367 | |
368 bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { | |
369 READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); | |
370 READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, | |
371 sizeof(kRsaAlgorithmIdentifier)) == 0); | |
372 (*pos) += sizeof(kRsaAlgorithmIdentifier); | |
373 return true; | |
374 } | |
375 | |
376 bool PrivateKeyInfoCodec::ReadVersion(uint8** pos, uint8* end) { | |
377 uint32 length = 0; | |
378 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length)) | |
379 return false; | |
380 | |
381 // The version should be zero. | |
382 for (uint32 i = 0; i < length; ++i) { | |
383 READ_ASSERT(**pos == 0x00); | |
384 (*pos)++; | |
385 } | |
386 | |
387 return true; | |
388 } | |
389 | |
390 } // namespace base | |
OLD | NEW |