OLD | NEW |
| (Empty) |
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 | |
OLD | NEW |