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 */); |