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