1 // Copyright (c) 2012 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/openpgp_symmetric_encryption.h" 6 7 #include <stdlib.h> 8 9 #include <sechash.h> 10 #include <cryptohi.h> 11 12 #include <vector> 13 14 #include "base/logging.h" 15 #include "crypto/random.h" 16 #include "crypto/scoped_nss_types.h" 17 #include "crypto/nss_util.h" 18 19 namespace crypto { 20 21 namespace { 22 23 // Reader wraps a StringPiece and provides methods to read several datatypes 24 // while advancing the StringPiece. 25 class Reader { 26 public: 27 Reader(base::StringPiece input) 28 : data_(input) { 29 } 30 31 bool U8(uint8* out) { 32 if (data_.size() < 1) 33 return false; 34 *out = static_cast<uint8>(data_[0]); 35 data_.remove_prefix(1); 36 return true; 37 } 38 39 bool U32(uint32* out) { 40 if (data_.size() < 4) 41 return false; 42 *out = static_cast<uint32>(data_[0]) << 24 | 43 static_cast<uint32>(data_[1]) << 16 | 44 static_cast<uint32>(data_[2]) << 8 | 45 static_cast<uint32>(data_[3]); 46 data_.remove_prefix(4); 47 return true; 48 } 49 50 // Prefix sets |*out| to the first |n| bytes of the StringPiece and advances 51 // the StringPiece by |n|. 52 bool Prefix(size_t n, base::StringPiece *out) { 53 if (data_.size() < n) 54 return false; 55 *out = base::StringPiece(data_.data(), n); 56 data_.remove_prefix(n); 57 return true; 58 } 59 60 // Remainder returns the remainer of the StringPiece and advances it to the 61 // end. 62 base::StringPiece Remainder() { 63 base::StringPiece ret = data_; 64 data_ = base::StringPiece(); 65 return ret; 66 } 67 68 typedef base::StringPiece Position; 69 70 Position tell() const { 71 return data_; 72 } 73 74 void Seek(Position p) { 75 data_ = p; 76 } 77 78 bool Skip(size_t n) { 79 if (data_.size() < n) 80 return false; 81 data_.remove_prefix(n); 82 return true; 83 } 84 85 bool empty() const { 86 return data_.empty(); 87 } 88 89 size_t size() const { 90 return data_.size(); 91 } 92 93 private: 94 base::StringPiece data_; 95 }; 96 97 // SaltedIteratedS2K implements the salted and iterated string-to-key 98 // convertion. See RFC 4880, section 3.7.1.3. 99 void SaltedIteratedS2K(unsigned cipher_key_length, 100 HASH_HashType hash_function, 101 base::StringPiece passphrase, 102 base::StringPiece salt, 103 unsigned count, 104 uint8 *out_key) { 105 const std::string combined = salt.as_string() + passphrase.as_string(); 106 const size_t combined_len = combined.size(); 107 108 unsigned done = 0; 109 uint8 zero[1] = {0}; 110 111 HASHContext* hash_context = HASH_Create(hash_function); 112 113 for (unsigned i = 0; done < cipher_key_length; i++) { 114 HASH_Begin(hash_context); 115 116 for (unsigned j = 0; j < i; j++) 117 HASH_Update(hash_context, zero, sizeof(zero)); 118 119 unsigned written = 0; 120 while (written < count) { 121 if (written + combined_len > count) { 122 unsigned todo = count - written; 123 HASH_Update(hash_context, 124 reinterpret_cast<const uint8*>(combined.data()), 125 todo); 126 written = count; 127 } else { 128 HASH_Update(hash_context, 129 reinterpret_cast<const uint8*>(combined.data()), 130 combined_len); 131 written += combined_len; 132 } 133 } 134 135 unsigned num_hash_bytes; 136 uint8 digest[HASH_LENGTH_MAX]; 137 HASH_End(hash_context, digest, &num_hash_bytes, sizeof(digest)); 138 139 unsigned todo = cipher_key_length - done; 140 if (todo > num_hash_bytes) 141 todo = num_hash_bytes; 142 memcpy(out_key + done, digest, todo); 143 done += todo; 144 } 145 146 HASH_Destroy(hash_context); 147 } 148 149 // CreateAESContext sets up |out_key| to be an AES context, with the given key, 150 // in ECB mode and with no IV. 151 bool CreateAESContext(const uint8* key, unsigned key_len, 152 ScopedPK11Context* out_decryption_context) { 153 ScopedPK11Slot slot(PK11_GetInternalSlot()); 154 if (!slot.get()) 155 return false; 156 SECItem key_item; 157 key_item.type = siBuffer; 158 key_item.data = const_cast<uint8*>(key); 159 key_item.len = key_len; 160 ScopedPK11SymKey pk11_key(PK11_ImportSymKey( 161 slot.get(), CKM_AES_ECB, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, 162 NULL)); 163 if (!pk11_key.get()) 164 return false; 165 ScopedSECItem iv_param(PK11_ParamFromIV(CKM_AES_ECB, NULL)); 166 out_decryption_context->reset( 167 PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, pk11_key.get(), 168 iv_param.get())); 169 return out_decryption_context->get() != NULL; 170 } 171 172 173 // These constants are the tag numbers for the various packet types that we 174 // use. 175 static const unsigned kSymmetricKeyEncryptedTag = 3; 176 static const unsigned kSymmetricallyEncryptedTag = 18; 177 static const unsigned kCompressedTag = 8; 178 static const unsigned kLiteralDataTag = 11; 179 180 class Decrypter { 181 public: 182 ~Decrypter() { 183 for (std::vector<void*>::iterator 184 i = arena_.begin(); i != arena_.end(); i++) { 185 free(*i); 186 } 187 arena_.clear(); 188 } 189 190 OpenPGPSymmetricEncrytion::Result Decrypt(base::StringPiece in, 191 base::StringPiece passphrase, 192 base::StringPiece *out_contents) { 193 Reader reader(in); 194 unsigned tag; 195 base::StringPiece contents; 196 ScopedPK11Context decryption_context; 197 198 if (!ParsePacket(&reader, &tag, &contents)) 199 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 200 if (tag != kSymmetricKeyEncryptedTag) 201 return OpenPGPSymmetricEncrytion::NOT_SYMMETRICALLY_ENCRYPTED; 202 Reader inner(contents); 203 OpenPGPSymmetricEncrytion::Result result = 204 ParseSymmetricKeyEncrypted(&inner, passphrase, &decryption_context); 205 if (result != OpenPGPSymmetricEncrytion::OK) 206 return result; 207 208 if (!ParsePacket(&reader, &tag, &contents)) 209 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 210 if (tag != kSymmetricallyEncryptedTag) 211 return OpenPGPSymmetricEncrytion::NOT_SYMMETRICALLY_ENCRYPTED; 212 if (!reader.empty()) 213 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 214 inner = Reader(contents); 215 if (!ParseSymmetricallyEncrypted(&inner, &decryption_context, &contents)) 216 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 217 218 reader = Reader(contents); 219 if (!ParsePacket(&reader, &tag, &contents)) 220 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 221 if (tag == kCompressedTag) 222 return OpenPGPSymmetricEncrytion::COMPRESSED; 223 if (tag != kLiteralDataTag) 224 return OpenPGPSymmetricEncrytion::NOT_SYMMETRICALLY_ENCRYPTED; 225 inner = Reader(contents); 226 if (!ParseLiteralData(&inner, out_contents)) 227 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 228 229 return OpenPGPSymmetricEncrytion::OK; 230 } 231 232 private: 233 // ParsePacket parses an OpenPGP packet from reader. See RFC 4880, section 234 // 4.2.2. 235 bool ParsePacket(Reader *reader, 236 unsigned *out_tag, 237 base::StringPiece *out_contents) { 238 uint8 header; 239 if (!reader->U8(&header)) 240 return false; 241 if ((header & 0x80) == 0) { 242 // Tag byte must have MSB set. 243 return false; 244 } 245 246 if ((header & 0x40) == 0) { 247 // Old format packet. 248 *out_tag = (header & 0x3f) >> 2; 249 250 uint8 length_type = header & 3; 251 if (length_type == 3) { 252 *out_contents = reader->Remainder(); 253 return true; 254 } 255 256 const unsigned length_bytes = 1 << length_type; 257 size_t length = 0; 258 for (unsigned i = 0; i < length_bytes; i++) { 259 uint8 length_byte; 260 if (!reader->U8(&length_byte)) 261 return false; 262 length <<= 8; 263 length |= length_byte; 264 } 265 266 return reader->Prefix(length, out_contents); 267 } 268 269 // New format packet. 270 *out_tag = header & 0x3f; 271 size_t length; 272 bool is_partial; 273 if (!ParseLength(reader, &length, &is_partial)) 274 return false; 275 if (is_partial) 276 return ParseStreamContents(reader, length, out_contents); 277 return reader->Prefix(length, out_contents); 278 } 279 280 // ParseStreamContents parses all the chunks of a partial length stream from 281 // reader. See http://tools.ietf.org/html/rfc4880#section-4.2.2.4 282 bool ParseStreamContents(Reader *reader, 283 size_t length, 284 base::StringPiece *out_contents) { 285 const Reader::Position beginning_of_stream = reader->tell(); 286 const size_t first_chunk_length = length; 287 288 // First we parse the stream to find its length. 289 if (!reader->Skip(length)) 290 return false; 291 292 for (;;) { 293 size_t chunk_length; 294 bool is_partial; 295 296 if (!ParseLength(reader, &chunk_length, &is_partial)) 297 return false; 298 if (length + chunk_length < length) 299 return false; 300 length += chunk_length; 301 if (!reader->Skip(chunk_length)) 302 return false; 303 if (!is_partial) 304 break; 305 } 306 307 // Now we have the length of the whole stream in |length|. 308 char* buf = reinterpret_cast<char*>(malloc(length)); 309 arena_.push_back(buf); 310 size_t j = 0; 311 reader->Seek(beginning_of_stream); 312 313 base::StringPiece first_chunk; 314 if (!reader->Prefix(first_chunk_length, &first_chunk)) 315 return false; 316 memcpy(buf + j, first_chunk.data(), first_chunk_length); 317 j += first_chunk_length; 318 319 // Now we parse the stream again, this time copying into |buf| 320 for (;;) { 321 size_t chunk_length; 322 bool is_partial; 323 324 if (!ParseLength(reader, &chunk_length, &is_partial)) 325 return false; 326 base::StringPiece chunk; 327 if (!reader->Prefix(chunk_length, &chunk)) 328 return false; 329 memcpy(buf + j, chunk.data(), chunk_length); 330 j += chunk_length; 331 if (!is_partial) 332 break; 333 } 334 335 *out_contents = base::StringPiece(buf, length); 336 return true; 337 } 338 339 // ParseLength parses an OpenPGP length from reader. See RFC 4880, section 340 // 4.2.2. 341 bool ParseLength(Reader *reader, size_t *out_length, bool *out_is_prefix) { 342 uint8 length_spec; 343 if (!reader->U8(&length_spec)) 344 return false; 345 346 *out_is_prefix = false; 347 if (length_spec < 192) { 348 *out_length = length_spec; 349 return true; 350 } else if (length_spec < 224) { 351 uint8 next_byte; 352 if (!reader->U8(&next_byte)) 353 return false; 354 355 *out_length = (length_spec - 192) << 8; 356 *out_length += next_byte; 357 return true; 358 } else if (length_spec < 255) { 359 *out_length = 1u << (length_spec & 0x1f); 360 *out_is_prefix = true; 361 return true; 362 } else { 363 uint32 length32; 364 if (!reader->U32(&length32)) 365 return false; 366 *out_length = length32; 367 return true; 368 } 369 } 370 371 // ParseSymmetricKeyEncrypted parses a passphrase protected session key. See 372 // RFC 4880, section 5.3. 373 OpenPGPSymmetricEncrytion::Result ParseSymmetricKeyEncrypted( 374 Reader *reader, 375 base::StringPiece passphrase, 376 ScopedPK11Context *decryption_context) { 377 uint8 version, cipher, s2k_type, hash_func_id; 378 if (!reader->U8(&version) || version != 4) 379 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 380 381 if (!reader->U8(&cipher) || 382 !reader->U8(&s2k_type) || 383 !reader->U8(&hash_func_id)) { 384 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 385 } 386 387 uint8 cipher_key_length = OpenPGPCipherIdToKeyLength(cipher); 388 if (cipher_key_length == 0) 389 return OpenPGPSymmetricEncrytion::UNKNOWN_CIPHER; 390 391 HASH_HashType hash_function; 392 switch (hash_func_id) { 393 case 2: // SHA-1 394 hash_function = HASH_AlgSHA1; 395 break; 396 case 8: // SHA-256 397 hash_function = HASH_AlgSHA256; 398 break; 399 default: 400 return OpenPGPSymmetricEncrytion::UNKNOWN_HASH; 401 } 402 403 // This chunk of code parses the S2K specifier. See RFC 4880, section 3.7.1. 404 base::StringPiece salt; 405 uint8 key[32]; 406 uint8 count_spec; 407 switch (s2k_type) { 408 case 1: 409 if (!reader->Prefix(8, &salt)) 410 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 411 // Fall through. 412 case 0: 413 SaltedIteratedS2K(cipher_key_length, hash_function, passphrase, salt, 414 passphrase.size() + salt.size(), key); 415 break; 416 case 3: 417 if (!reader->Prefix(8, &salt) || 418 !reader->U8(&count_spec)) { 419 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 420 } 421 SaltedIteratedS2K( 422 cipher_key_length, hash_function, passphrase, salt, 423 static_cast<unsigned>( 424 16 + (count_spec&15)) << ((count_spec >> 4) + 6), key); 425 break; 426 default: 427 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 428 } 429 430 if (!CreateAESContext(key, cipher_key_length, decryption_context)) 431 return OpenPGPSymmetricEncrytion::INTERNAL_ERROR; 432 433 if (reader->empty()) { 434 // The resulting key is used directly. 435 return OpenPGPSymmetricEncrytion::OK; 436 } 437 438 // The S2K derived key encrypts another key that follows: 439 base::StringPiece encrypted_key = reader->Remainder(); 440 if (encrypted_key.size() < 1) 441 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 442 443 uint8* plaintext_key = reinterpret_cast<uint8*>( 444 malloc(encrypted_key.size())); 445 arena_.push_back(plaintext_key); 446 447 CFBDecrypt(encrypted_key, decryption_context, plaintext_key); 448 449 cipher_key_length = OpenPGPCipherIdToKeyLength(plaintext_key[0]); 450 if (cipher_key_length == 0) 451 return OpenPGPSymmetricEncrytion::UNKNOWN_CIPHER; 452 if (encrypted_key.size() != 1u + cipher_key_length) 453 return OpenPGPSymmetricEncrytion::PARSE_ERROR; 454 if (!CreateAESContext(plaintext_key + 1, cipher_key_length, 455 decryption_context)) { 456 return OpenPGPSymmetricEncrytion::INTERNAL_ERROR; 457 } 458 return OpenPGPSymmetricEncrytion::OK; 459 } 460 461 // CFBDecrypt decrypts the cipher-feedback encrypted data in |in| to |out| 462 // using |decryption_context| and assumes an IV of all zeros. 463 void CFBDecrypt(base::StringPiece in, ScopedPK11Context* decryption_context, 464 uint8* out) { 465 // We need this for PK11_CipherOp to write to, but we never check it as we 466 // work in ECB mode, one block at a time. 467 int out_len; 468 469 uint8 mask[AES_BLOCK_SIZE]; 470 memset(mask, 0, sizeof(mask)); 471 472 unsigned used = AES_BLOCK_SIZE; 473 474 for (size_t i = 0; i < in.size(); i++) { 475 if (used == AES_BLOCK_SIZE) { 476 PK11_CipherOp(decryption_context->get(), mask, &out_len, sizeof(mask), 477 mask, AES_BLOCK_SIZE); 478 used = 0; 479 } 480 481 uint8 t = in[i]; 482 out[i] = t ^ mask[used]; 483 mask[used] = t; 484 used++; 485 } 486 } 487 488 // OpenPGPCipherIdToKeyLength converts an OpenPGP cipher id (see RFC 4880, 489 // section 9.2) to the key length of that cipher. It returns 0 on error. 490 unsigned OpenPGPCipherIdToKeyLength(uint8 cipher) { 491 switch (cipher) { 492 case 7: // AES-128 493 return 16; 494 case 8: // AES-192 495 return 24; 496 case 9: // AES-256 497 return 32; 498 default: 499 return 0; 500 } 501 } 502 503 // ParseSymmetricallyEncrypted parses a Symmetrically Encrypted packet. See 504 // RFC 4880, sections 5.7 and 5.13. 505 bool ParseSymmetricallyEncrypted(Reader *reader, 506 ScopedPK11Context *decryption_context, 507 base::StringPiece *out_plaintext) { 508 // We need this for PK11_CipherOp to write to, but we never check it as we 509 // work in ECB mode, one block at a time. 510 int out_len; 511 512 uint8 version; 513 if (!reader->U8(&version) || version != 1) 514 return false; 515 516 base::StringPiece prefix_sp; 517 if (!reader->Prefix(AES_BLOCK_SIZE + 2, &prefix_sp)) 518 return false; 519 uint8 prefix[AES_BLOCK_SIZE + 2]; 520 memcpy(prefix, prefix_sp.data(), sizeof(prefix)); 521 522 uint8 prefix_copy[AES_BLOCK_SIZE + 2]; 523 uint8 fre[AES_BLOCK_SIZE]; 524 525 memset(prefix_copy, 0, AES_BLOCK_SIZE); 526 PK11_CipherOp(decryption_context->get(), fre, &out_len, sizeof(fre), 527 prefix_copy, AES_BLOCK_SIZE); 528 for (unsigned i = 0; i < AES_BLOCK_SIZE; i++) 529 prefix_copy[i] = fre[i] ^ prefix[i]; 530 PK11_CipherOp(decryption_context->get(), fre, &out_len, sizeof(fre), prefix, 531 AES_BLOCK_SIZE); 532 prefix_copy[AES_BLOCK_SIZE] = prefix[AES_BLOCK_SIZE] ^ fre[0]; 533 prefix_copy[AES_BLOCK_SIZE + 1] = prefix[AES_BLOCK_SIZE + 1] ^ fre[1]; 534 535 if (prefix_copy[AES_BLOCK_SIZE - 2] != prefix_copy[AES_BLOCK_SIZE] || 536 prefix_copy[AES_BLOCK_SIZE - 1] != prefix_copy[AES_BLOCK_SIZE + 1]) { 537 return false; 538 } 539 540 fre[0] = prefix[AES_BLOCK_SIZE]; 541 fre[1] = prefix[AES_BLOCK_SIZE + 1]; 542 543 unsigned out_used = 2; 544 545 const size_t plaintext_size = reader->size(); 546 if (plaintext_size < SHA1_LENGTH + 2) { 547 // Too small to contain an MDC trailer. 548 return false; 549 } 550 551 uint8* plaintext = reinterpret_cast<uint8*>(malloc(plaintext_size)); 552 arena_.push_back(plaintext); 553 554 for (size_t i = 0; i < plaintext_size; i++) { 555 uint8 b; 556 if (!reader->U8(&b)) 557 return false; 558 if (out_used == AES_BLOCK_SIZE) { 559 PK11_CipherOp(decryption_context->get(), fre, &out_len, sizeof(fre), 560 fre, AES_BLOCK_SIZE); 561 out_used = 0; 562 } 563 564 plaintext[i] = b ^ fre[out_used]; 565 fre[out_used++] = b; 566 } 567 568 // The plaintext should be followed by a Modification Detection Code 569 // packet. This packet is specified such that the header is always 570 // serialized as exactly these two bytes: 571 if (plaintext[plaintext_size - SHA1_LENGTH - 2] != 0xd3 || 572 plaintext[plaintext_size - SHA1_LENGTH - 1] != 0x14) { 573 return false; 574 } 575 576 HASHContext* hash_context = HASH_Create(HASH_AlgSHA1); 577 HASH_Begin(hash_context); 578 HASH_Update(hash_context, prefix_copy, sizeof(prefix_copy)); 579 HASH_Update(hash_context, plaintext, plaintext_size - SHA1_LENGTH); 580 uint8 digest[SHA1_LENGTH]; 581 unsigned num_hash_bytes; 582 HASH_End(hash_context, digest, &num_hash_bytes, sizeof(digest)); 583 HASH_Destroy(hash_context); 584 585 if (memcmp(digest, &plaintext[plaintext_size - SHA1_LENGTH], 586 SHA1_LENGTH) != 0) { 587 return false; 588 } 589 590 *out_plaintext = base::StringPiece(reinterpret_cast<char*>(plaintext), 591 plaintext_size - SHA1_LENGTH); 592 return true; 593 } 594 595 // ParseLiteralData parses a Literal Data packet. See RFC 4880, section 5.9. 596 bool ParseLiteralData(Reader *reader, base::StringPiece *out_data) { 597 uint8 is_binary, filename_len; 598 if (!reader->U8(&is_binary) || 599 !reader->U8(&filename_len) || 600 !reader->Skip(filename_len) || 601 !reader->Skip(sizeof(uint32) /* mtime */)) { 602 return false; 603 } 604 605 *out_data = reader->Remainder(); 606 return true; 607 } 608 609 // arena_ contains malloced pointers that are used as temporary space during 610 // the decryption. 611 std::vector<void*> arena_; 612 }; 613 614 class Encrypter { 615 public: 616 // ByteString is used throughout in order to avoid signedness issues with a 617 // std::string. 618 typedef std::basic_string<uint8> ByteString; 619 620 static ByteString Encrypt(base::StringPiece plaintext, 621 base::StringPiece passphrase) { 622 ByteString key; 623 ByteString ske = SerializeSymmetricKeyEncrypted(passphrase, &key); 624 625 ByteString literal_data = SerializeLiteralData(plaintext); 626 ByteString se = SerializeSymmetricallyEncrypted(literal_data, key); 627 return ske + se; 628 } 629 630 private: 631 // MakePacket returns an OpenPGP packet tagged as type |tag|. It always uses 632 // new-format headers. See RFC 4880, section 4.2. 633 static ByteString MakePacket(unsigned tag, const ByteString& contents) { 634 ByteString header; 635 header.push_back(0x80 | 0x40 | tag); 636 637 if (contents.size() < 192) { 638 header.push_back(contents.size()); 639 } else if (contents.size() < 8384) { 640 size_t length = contents.size(); 641 length -= 192; 642 header.push_back(192 + (length >> 8)); 643 header.push_back(length & 0xff); 644 } else { 645 size_t length = contents.size(); 646 header.push_back(255); 647 header.push_back(length >> 24); 648 header.push_back(length >> 16); 649 header.push_back(length >> 8); 650 header.push_back(length); 651 } 652 653 return header + contents; 654 } 655 656 // SerializeLiteralData returns a Literal Data packet containing |contents| 657 // as binary data with no filename nor mtime specified. See RFC 4880, section 658 // 5.9. 659 static ByteString SerializeLiteralData(base::StringPiece contents) { 660 ByteString literal_data; 661 literal_data.push_back(0x74); // text mode 662 literal_data.push_back(0x00); // no filename 663 literal_data.push_back(0x00); // zero mtime 664 literal_data.push_back(0x00); 665 literal_data.push_back(0x00); 666 literal_data.push_back(0x00); 667 literal_data += ByteString(reinterpret_cast<const uint8*>(contents.data()), 668 contents.size()); 669 return MakePacket(kLiteralDataTag, literal_data); 670 } 671 672 // SerializeSymmetricKeyEncrypted generates a random AES-128 key from 673 // |passphrase|, sets |out_key| to it and returns a Symmetric Key Encrypted 674 // packet. See RFC 4880, section 5.3. 675 static ByteString SerializeSymmetricKeyEncrypted(base::StringPiece passphrase, 676 ByteString *out_key) { 677 ByteString ske; 678 ske.push_back(4); // version 4 679 ske.push_back(7); // AES-128 680 ske.push_back(3); // iterated and salted S2K 681 ske.push_back(2); // SHA-1 682 683 uint64 salt64; 684 crypto::RandBytes(&salt64, sizeof(salt64)); 685 ByteString salt(sizeof(salt64), 0); 686 687 // It's a random value, so endianness doesn't matter. 688 ske += ByteString(reinterpret_cast<uint8*>(&salt64), sizeof(salt64)); 689 ske.push_back(96); // iteration count of 65536 690 691 uint8 key[16]; 692 SaltedIteratedS2K( 693 sizeof(key), HASH_AlgSHA1, passphrase, 694 base::StringPiece(reinterpret_cast<char*>(&salt64), sizeof(salt64)), 695 65536, key); 696 *out_key = ByteString(key, sizeof(key)); 697 return MakePacket(kSymmetricKeyEncryptedTag, ske); 698 } 699 700 // SerializeSymmetricallyEncrypted encrypts |plaintext| with |key| and 701 // returns a Symmetrically Encrypted packet containing the ciphertext. See 702 // RFC 4880, section 5.7. 703 static ByteString SerializeSymmetricallyEncrypted(ByteString plaintext, 704 const ByteString& key) { 705 // We need this for PK11_CipherOp to write to, but we never check it as we 706 // work in ECB mode, one block at a time. 707 int out_len; 708 709 ByteString packet; 710 packet.push_back(1); // version 1 711 static const unsigned kBlockSize = 16; // AES block size 712 713 uint8 prefix[kBlockSize + 2], fre[kBlockSize], iv[kBlockSize]; 714 crypto::RandBytes(iv, kBlockSize); 715 memset(fre, 0, sizeof(fre)); 716 717 ScopedPK11Context aes_context; 718 CHECK(CreateAESContext(key.data(), key.size(), &aes_context)); 719 720 PK11_CipherOp(aes_context.get(), fre, &out_len, sizeof(fre), fre, 721 AES_BLOCK_SIZE); 722 for (unsigned i = 0; i < 16; i++) 723 prefix[i] = iv[i] ^ fre[i]; 724 PK11_CipherOp(aes_context.get(), fre, &out_len, sizeof(fre), prefix, 725 AES_BLOCK_SIZE); 726 prefix[kBlockSize] = iv[kBlockSize - 2] ^ fre[0]; 727 prefix[kBlockSize + 1] = iv[kBlockSize - 1] ^ fre[1]; 728 729 packet += ByteString(prefix, sizeof(prefix)); 730 731 ByteString plaintext_copy = plaintext; 732 plaintext_copy.push_back(0xd3); // MDC packet 733 plaintext_copy.push_back(20); // packet length (20 bytes) 734 735 HASHContext* hash_context = HASH_Create(HASH_AlgSHA1); 736 HASH_Begin(hash_context); 737 HASH_Update(hash_context, iv, sizeof(iv)); 738 HASH_Update(hash_context, iv + kBlockSize - 2, 2); 739 HASH_Update(hash_context, plaintext_copy.data(), plaintext_copy.size()); 740 uint8 digest[SHA1_LENGTH]; 741 unsigned num_hash_bytes; 742 HASH_End(hash_context, digest, &num_hash_bytes, sizeof(digest)); 743 HASH_Destroy(hash_context); 744 745 plaintext_copy += ByteString(digest, sizeof(digest)); 746 747 fre[0] = prefix[kBlockSize]; 748 fre[1] = prefix[kBlockSize+1]; 749 unsigned out_used = 2; 750 751 for (size_t i = 0; i < plaintext_copy.size(); i++) { 752 if (out_used == kBlockSize) { 753 PK11_CipherOp(aes_context.get(), fre, &out_len, sizeof(fre), fre, 754 AES_BLOCK_SIZE); 755 out_used = 0; 756 } 757 758 uint8 c = plaintext_copy[i] ^ fre[out_used]; 759 fre[out_used++] = c; 760 packet.push_back(c); 761 } 762 763 return MakePacket(kSymmetricallyEncryptedTag, packet); 764 } 765 }; 766 767 } // anonymous namespace 768 769 // static 770 OpenPGPSymmetricEncrytion::Result OpenPGPSymmetricEncrytion::Decrypt( 771 base::StringPiece encrypted, 772 base::StringPiece passphrase, 773 std::string *out) { 774 EnsureNSSInit(); 775 776 Decrypter decrypter; 777 base::StringPiece result; 778 Result reader = decrypter.Decrypt(encrypted, passphrase, &result); 779 if (reader == OK) 780 *out = result.as_string(); 781 return reader; 782 } 783 784 // static 785 std::string OpenPGPSymmetricEncrytion::Encrypt( 786 base::StringPiece plaintext, 787 base::StringPiece passphrase) { 788 EnsureNSSInit(); 789 790 Encrypter::ByteString b = 791 Encrypter::Encrypt(plaintext, passphrase); 792 return std::string(reinterpret_cast<const char*>(b.data()), b.size()); 793 } 794 795 } // namespace crypto 796