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 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 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 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 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 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 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 138 bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { 139 return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); 140 } 141 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 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 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 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 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 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. 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 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 314 bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, 315 uint8* end, 316 std::vector<uint8>* out) { 317 return ReadIntegerImpl(pos, end, out, big_endian_); 318 } 319 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 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