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