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.
5 #include "crypto/openpgp_symmetric_encryption.h"
14 #include "base/logging.h"
15 #include "crypto/random.h"
16 #include "crypto/scoped_nss_types.h"
17 #include "crypto/nss_util.h"
23 // Reader wraps a StringPiece and provides methods to read several datatypes
24 // while advancing the StringPiece.
27 Reader(base::StringPiece input
)
34 *out
= static_cast<uint8
>(data_
[0]);
35 data_
.remove_prefix(1);
39 bool U32(uint32
* out
) {
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);
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
) {
55 *out
= base::StringPiece(data_
.data(), n
);
56 data_
.remove_prefix(n
);
60 // Remainder returns the remainer of the StringPiece and advances it to the
62 base::StringPiece
Remainder() {
63 base::StringPiece ret
= data_
;
64 data_
= base::StringPiece();
68 typedef base::StringPiece Position
;
70 Position
tell() const {
74 void Seek(Position p
) {
81 data_
.remove_prefix(n
);
94 base::StringPiece data_
;
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
,
105 const std::string combined
= salt
.as_string() + passphrase
.as_string();
106 const size_t combined_len
= combined
.size();
111 HASHContext
* hash_context
= HASH_Create(hash_function
);
113 for (unsigned i
= 0; done
< cipher_key_length
; i
++) {
114 HASH_Begin(hash_context
);
116 for (unsigned j
= 0; j
< i
; j
++)
117 HASH_Update(hash_context
, zero
, sizeof(zero
));
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()),
128 HASH_Update(hash_context
,
129 reinterpret_cast<const uint8
*>(combined
.data()),
131 written
+= combined_len
;
135 unsigned num_hash_bytes
;
136 uint8 digest
[HASH_LENGTH_MAX
];
137 HASH_End(hash_context
, digest
, &num_hash_bytes
, sizeof(digest
));
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
);
146 HASH_Destroy(hash_context
);
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());
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
,
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(),
169 return out_decryption_context
->get() != NULL
;
173 // These constants are the tag numbers for the various packet types that we
175 static const unsigned kSymmetricKeyEncryptedTag
= 3;
176 static const unsigned kSymmetricallyEncryptedTag
= 18;
177 static const unsigned kCompressedTag
= 8;
178 static const unsigned kLiteralDataTag
= 11;
183 for (std::vector
<void*>::iterator
184 i
= arena_
.begin(); i
!= arena_
.end(); i
++) {
190 OpenPGPSymmetricEncrytion::Result
Decrypt(base::StringPiece in
,
191 base::StringPiece passphrase
,
192 base::StringPiece
*out_contents
) {
195 base::StringPiece contents
;
196 ScopedPK11Context decryption_context
;
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
)
208 if (!ParsePacket(&reader
, &tag
, &contents
))
209 return OpenPGPSymmetricEncrytion::PARSE_ERROR
;
210 if (tag
!= kSymmetricallyEncryptedTag
)
211 return OpenPGPSymmetricEncrytion::NOT_SYMMETRICALLY_ENCRYPTED
;
213 return OpenPGPSymmetricEncrytion::PARSE_ERROR
;
214 inner
= Reader(contents
);
215 if (!ParseSymmetricallyEncrypted(&inner
, &decryption_context
, &contents
))
216 return OpenPGPSymmetricEncrytion::PARSE_ERROR
;
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
;
229 return OpenPGPSymmetricEncrytion::OK
;
233 // ParsePacket parses an OpenPGP packet from reader. See RFC 4880, section
235 bool ParsePacket(Reader
*reader
,
237 base::StringPiece
*out_contents
) {
239 if (!reader
->U8(&header
))
241 if ((header
& 0x80) == 0) {
242 // Tag byte must have MSB set.
246 if ((header
& 0x40) == 0) {
247 // Old format packet.
248 *out_tag
= (header
& 0x3f) >> 2;
250 uint8 length_type
= header
& 3;
251 if (length_type
== 3) {
252 *out_contents
= reader
->Remainder();
256 const unsigned length_bytes
= 1 << length_type
;
258 for (unsigned i
= 0; i
< length_bytes
; i
++) {
260 if (!reader
->U8(&length_byte
))
263 length
|= length_byte
;
266 return reader
->Prefix(length
, out_contents
);
269 // New format packet.
270 *out_tag
= header
& 0x3f;
273 if (!ParseLength(reader
, &length
, &is_partial
))
276 return ParseStreamContents(reader
, length
, out_contents
);
277 return reader
->Prefix(length
, out_contents
);
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
,
284 base::StringPiece
*out_contents
) {
285 const Reader::Position beginning_of_stream
= reader
->tell();
286 const size_t first_chunk_length
= length
;
288 // First we parse the stream to find its length.
289 if (!reader
->Skip(length
))
296 if (!ParseLength(reader
, &chunk_length
, &is_partial
))
298 if (length
+ chunk_length
< length
)
300 length
+= chunk_length
;
301 if (!reader
->Skip(chunk_length
))
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
);
311 reader
->Seek(beginning_of_stream
);
313 base::StringPiece first_chunk
;
314 if (!reader
->Prefix(first_chunk_length
, &first_chunk
))
316 memcpy(buf
+ j
, first_chunk
.data(), first_chunk_length
);
317 j
+= first_chunk_length
;
319 // Now we parse the stream again, this time copying into |buf|
324 if (!ParseLength(reader
, &chunk_length
, &is_partial
))
326 base::StringPiece chunk
;
327 if (!reader
->Prefix(chunk_length
, &chunk
))
329 memcpy(buf
+ j
, chunk
.data(), chunk_length
);
335 *out_contents
= base::StringPiece(buf
, length
);
339 // ParseLength parses an OpenPGP length from reader. See RFC 4880, section
341 bool ParseLength(Reader
*reader
, size_t *out_length
, bool *out_is_prefix
) {
343 if (!reader
->U8(&length_spec
))
346 *out_is_prefix
= false;
347 if (length_spec
< 192) {
348 *out_length
= length_spec
;
350 } else if (length_spec
< 224) {
352 if (!reader
->U8(&next_byte
))
355 *out_length
= (length_spec
- 192) << 8;
356 *out_length
+= next_byte
;
358 } else if (length_spec
< 255) {
359 *out_length
= 1u << (length_spec
& 0x1f);
360 *out_is_prefix
= true;
364 if (!reader
->U32(&length32
))
366 *out_length
= length32
;
371 // ParseSymmetricKeyEncrypted parses a passphrase protected session key. See
372 // RFC 4880, section 5.3.
373 OpenPGPSymmetricEncrytion::Result
ParseSymmetricKeyEncrypted(
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
;
381 if (!reader
->U8(&cipher
) ||
382 !reader
->U8(&s2k_type
) ||
383 !reader
->U8(&hash_func_id
)) {
384 return OpenPGPSymmetricEncrytion::PARSE_ERROR
;
387 uint8 cipher_key_length
= OpenPGPCipherIdToKeyLength(cipher
);
388 if (cipher_key_length
== 0)
389 return OpenPGPSymmetricEncrytion::UNKNOWN_CIPHER
;
391 HASH_HashType hash_function
;
392 switch (hash_func_id
) {
394 hash_function
= HASH_AlgSHA1
;
397 hash_function
= HASH_AlgSHA256
;
400 return OpenPGPSymmetricEncrytion::UNKNOWN_HASH
;
403 // This chunk of code parses the S2K specifier. See RFC 4880, section 3.7.1.
404 base::StringPiece salt
;
409 if (!reader
->Prefix(8, &salt
))
410 return OpenPGPSymmetricEncrytion::PARSE_ERROR
;
413 SaltedIteratedS2K(cipher_key_length
, hash_function
, passphrase
, salt
,
414 passphrase
.size() + salt
.size(), key
);
417 if (!reader
->Prefix(8, &salt
) ||
418 !reader
->U8(&count_spec
)) {
419 return OpenPGPSymmetricEncrytion::PARSE_ERROR
;
422 cipher_key_length
, hash_function
, passphrase
, salt
,
423 static_cast<unsigned>(
424 16 + (count_spec
&15)) << ((count_spec
>> 4) + 6), key
);
427 return OpenPGPSymmetricEncrytion::PARSE_ERROR
;
430 if (!CreateAESContext(key
, cipher_key_length
, decryption_context
))
431 return OpenPGPSymmetricEncrytion::INTERNAL_ERROR
;
433 if (reader
->empty()) {
434 // The resulting key is used directly.
435 return OpenPGPSymmetricEncrytion::OK
;
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
;
443 uint8
* plaintext_key
= reinterpret_cast<uint8
*>(
444 malloc(encrypted_key
.size()));
445 arena_
.push_back(plaintext_key
);
447 CFBDecrypt(encrypted_key
, decryption_context
, plaintext_key
);
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
;
458 return OpenPGPSymmetricEncrytion::OK
;
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
,
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.
469 uint8 mask
[AES_BLOCK_SIZE
];
470 memset(mask
, 0, sizeof(mask
));
472 unsigned used
= AES_BLOCK_SIZE
;
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
);
482 out
[i
] = t
^ mask
[used
];
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
) {
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.
513 if (!reader
->U8(&version
) || version
!= 1)
516 base::StringPiece prefix_sp
;
517 if (!reader
->Prefix(AES_BLOCK_SIZE
+ 2, &prefix_sp
))
519 uint8 prefix
[AES_BLOCK_SIZE
+ 2];
520 memcpy(prefix
, prefix_sp
.data(), sizeof(prefix
));
522 uint8 prefix_copy
[AES_BLOCK_SIZE
+ 2];
523 uint8 fre
[AES_BLOCK_SIZE
];
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
,
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];
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]) {
540 fre
[0] = prefix
[AES_BLOCK_SIZE
];
541 fre
[1] = prefix
[AES_BLOCK_SIZE
+ 1];
543 unsigned out_used
= 2;
545 const size_t plaintext_size
= reader
->size();
546 if (plaintext_size
< SHA1_LENGTH
+ 2) {
547 // Too small to contain an MDC trailer.
551 uint8
* plaintext
= reinterpret_cast<uint8
*>(malloc(plaintext_size
));
552 arena_
.push_back(plaintext
);
554 for (size_t i
= 0; i
< plaintext_size
; i
++) {
558 if (out_used
== AES_BLOCK_SIZE
) {
559 PK11_CipherOp(decryption_context
->get(), fre
, &out_len
, sizeof(fre
),
560 fre
, AES_BLOCK_SIZE
);
564 plaintext
[i
] = b
^ fre
[out_used
];
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) {
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
);
585 if (memcmp(digest
, &plaintext
[plaintext_size
- SHA1_LENGTH
],
590 *out_plaintext
= base::StringPiece(reinterpret_cast<char*>(plaintext
),
591 plaintext_size
- SHA1_LENGTH
);
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 */)) {
605 *out_data
= reader
->Remainder();
609 // arena_ contains malloced pointers that are used as temporary space during
611 std::vector
<void*> arena_
;
616 // ByteString is used throughout in order to avoid signedness issues with a
618 typedef std::basic_string
<uint8
> ByteString
;
620 static ByteString
Encrypt(base::StringPiece plaintext
,
621 base::StringPiece passphrase
) {
623 ByteString ske
= SerializeSymmetricKeyEncrypted(passphrase
, &key
);
625 ByteString literal_data
= SerializeLiteralData(plaintext
);
626 ByteString se
= SerializeSymmetricallyEncrypted(literal_data
, key
);
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
) {
635 header
.push_back(0x80 | 0x40 | tag
);
637 if (contents
.size() < 192) {
638 header
.push_back(contents
.size());
639 } else if (contents
.size() < 8384) {
640 size_t length
= contents
.size();
642 header
.push_back(192 + (length
>> 8));
643 header
.push_back(length
& 0xff);
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
);
653 return header
+ contents
;
656 // SerializeLiteralData returns a Literal Data packet containing |contents|
657 // as binary data with no filename nor mtime specified. See RFC 4880, section
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()),
669 return MakePacket(kLiteralDataTag
, literal_data
);
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
) {
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
684 crypto::RandBytes(&salt64
, sizeof(salt64
));
685 ByteString
salt(sizeof(salt64
), 0);
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
693 sizeof(key
), HASH_AlgSHA1
, passphrase
,
694 base::StringPiece(reinterpret_cast<char*>(&salt64
), sizeof(salt64
)),
696 *out_key
= ByteString(key
, sizeof(key
));
697 return MakePacket(kSymmetricKeyEncryptedTag
, ske
);
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.
710 packet
.push_back(1); // version 1
711 static const unsigned kBlockSize
= 16; // AES block size
713 uint8 prefix
[kBlockSize
+ 2], fre
[kBlockSize
], iv
[kBlockSize
];
714 crypto::RandBytes(iv
, kBlockSize
);
715 memset(fre
, 0, sizeof(fre
));
717 ScopedPK11Context aes_context
;
718 CHECK(CreateAESContext(key
.data(), key
.size(), &aes_context
));
720 PK11_CipherOp(aes_context
.get(), fre
, &out_len
, sizeof(fre
), fre
,
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
,
726 prefix
[kBlockSize
] = iv
[kBlockSize
- 2] ^ fre
[0];
727 prefix
[kBlockSize
+ 1] = iv
[kBlockSize
- 1] ^ fre
[1];
729 packet
+= ByteString(prefix
, sizeof(prefix
));
731 ByteString plaintext_copy
= plaintext
;
732 plaintext_copy
.push_back(0xd3); // MDC packet
733 plaintext_copy
.push_back(20); // packet length (20 bytes)
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
);
745 plaintext_copy
+= ByteString(digest
, sizeof(digest
));
747 fre
[0] = prefix
[kBlockSize
];
748 fre
[1] = prefix
[kBlockSize
+1];
749 unsigned out_used
= 2;
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
,
758 uint8 c
= plaintext_copy
[i
] ^ fre
[out_used
];
763 return MakePacket(kSymmetricallyEncryptedTag
, packet
);
767 } // anonymous namespace
770 OpenPGPSymmetricEncrytion::Result
OpenPGPSymmetricEncrytion::Decrypt(
771 base::StringPiece encrypted
,
772 base::StringPiece passphrase
,
777 base::StringPiece result
;
778 Result reader
= decrypter
.Decrypt(encrypted
, passphrase
, &result
);
780 *out
= result
.as_string();
785 std::string
OpenPGPSymmetricEncrytion::Encrypt(
786 base::StringPiece plaintext
,
787 base::StringPiece passphrase
) {
790 Encrypter::ByteString b
=
791 Encrypter::Encrypt(plaintext
, passphrase
);
792 return std::string(reinterpret_cast<const char*>(b
.data()), b
.size());
795 } // namespace crypto