| Index: components/gcm_driver/crypto/gcm_message_cryptographer.cc
|
| diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer.cc b/components/gcm_driver/crypto/gcm_message_cryptographer.cc
|
| index a3bcfad1b7005b680786dac3dcb12567e3df5e05..d2502830c61f9acb28628764f43699fba2435060 100644
|
| --- a/components/gcm_driver/crypto/gcm_message_cryptographer.cc
|
| +++ b/components/gcm_driver/crypto/gcm_message_cryptographer.cc
|
| @@ -5,6 +5,7 @@
|
| #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
|
|
|
| #include <algorithm>
|
| +#include <sstream>
|
|
|
| #include "base/big_endian.h"
|
| #include "base/logging.h"
|
| @@ -23,12 +24,42 @@ const size_t kDefaultRecordSize = 4096;
|
| // Key size, in bytes, of a valid AEAD_AES_128_GCM key.
|
| const size_t kContentEncryptionKeySize = 16;
|
|
|
| +// The label of the curve used by Web Push encryption, as mandated by the
|
| +// draft-ietf-webpush-encryption-01 draft.
|
| +const char kP256Label[] = "P-256";
|
| +
|
| } // namespace
|
|
|
| const size_t GCMMessageCryptographer::kAuthenticationTagBytes = 16;
|
| const size_t GCMMessageCryptographer::kSaltSize = 16;
|
|
|
| -GCMMessageCryptographer::GCMMessageCryptographer() {}
|
| +template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I)<<1) {
|
| + static const char* digits = "0123456789abcdef";
|
| + std::string rc(hex_len,'0');
|
| + for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
|
| + rc[i] = digits[(w>>j) & 0x0f];
|
| + return rc;
|
| +}
|
| +
|
| +GCMMessageCryptographer::GCMMessageCryptographer(
|
| + const base::StringPiece& local_public_key,
|
| + const base::StringPiece& peer_public_key) {
|
| + std::stringstream context_stream;
|
| + context_stream << '\0' << kP256Label << '\0';
|
| + context_stream << '\0' << (char)local_public_key.size() << local_public_key;
|
| + context_stream << '\0' << (char)peer_public_key.size() << peer_public_key;
|
| +
|
| + // TODO: \0 + size is necessary because the length must be written as a two-
|
| + // byte integer in big endian byte order.
|
| +
|
| + // TODO: Without (char) the size is written as two ascii literals: '6' '5',
|
| + // rather than the binary representation of 0x41.
|
| +
|
| + nonce_info_ =
|
| + "Content-Encoding: nonce" + context_stream.str();
|
| + content_encryption_key_info_ =
|
| + "Content-Encoding: aesgcm128" + context_stream.str();
|
| +}
|
|
|
| GCMMessageCryptographer::~GCMMessageCryptographer() {}
|
|
|
| @@ -77,8 +108,10 @@ bool GCMMessageCryptographer::Decrypt(
|
| std::string* plaintext) const {
|
| DCHECK(plaintext);
|
|
|
| - if (salt.size() != kSaltSize || record_size <= 1)
|
| + if (salt.size() != kSaltSize || record_size <= 1) {
|
| + LOG(INFO) << "--1";
|
| return false;
|
| + }
|
|
|
| // The |ciphertext| must be at least kAuthenticationTagBytes + 1 bytes, which
|
| // would be used for an empty message. Per
|
| @@ -86,6 +119,7 @@ bool GCMMessageCryptographer::Decrypt(
|
| // the |record_size| parameter must be large enough to use only one record.
|
| if (ciphertext.size() < kAuthenticationTagBytes + 1 ||
|
| ciphertext.size() >= record_size + kAuthenticationTagBytes + 1) {
|
| + LOG(INFO) << "--2";
|
| return false;
|
| }
|
|
|
| @@ -95,6 +129,7 @@ bool GCMMessageCryptographer::Decrypt(
|
| std::string decrypted_record;
|
| if (!EncryptDecryptRecordInternal(DECRYPT, ciphertext, content_encryption_key,
|
| nonce, &decrypted_record)) {
|
| + LOG(INFO) << "--3";
|
| return false;
|
| }
|
|
|
| @@ -106,12 +141,16 @@ bool GCMMessageCryptographer::Decrypt(
|
| // includes an authentication check, neither verification nor removing the
|
| // padding have to be done in constant time.
|
| size_t padding_length = static_cast<size_t>(decrypted_record[0]);
|
| - if (padding_length >= decrypted_record.size())
|
| + if (padding_length >= decrypted_record.size()) {
|
| + LOG(INFO) << "--4";
|
| return false;
|
| + }
|
|
|
| for (size_t i = 1; i <= padding_length; ++i) {
|
| - if (decrypted_record[i] != 0)
|
| + if (decrypted_record[i] != 0) {
|
| + LOG(INFO) << "--5";
|
| return false;
|
| + }
|
| }
|
|
|
| base::StringPiece decoded_record_string_piece(decrypted_record);
|
| @@ -125,7 +164,7 @@ std::string GCMMessageCryptographer::DeriveContentEncryptionKey(
|
| const base::StringPiece& key,
|
| const base::StringPiece& salt) const {
|
| crypto::HKDF hkdf(key, salt,
|
| - "Content-Encoding: aesgcm128",
|
| + content_encryption_key_info_,
|
| kContentEncryptionKeySize,
|
| 0, /* iv_bytes_to_generate */
|
| 0 /* subkey_secret_bytes_to_generate */);
|
| @@ -137,7 +176,7 @@ std::string GCMMessageCryptographer::DeriveNonce(
|
| const base::StringPiece& key,
|
| const base::StringPiece& salt) const {
|
| crypto::HKDF hkdf(key, salt,
|
| - "Content-Encoding: nonce",
|
| + nonce_info_,
|
| kNonceSize,
|
| 0, /* iv_bytes_to_generate */
|
| 0 /* subkey_secret_bytes_to_generate */);
|
|
|