Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Unified Diff: components/gcm_driver/crypto/gcm_message_cryptographer.h

Issue 2713673002: Separate out the scheme from the GCMMessageCryptographer (Closed)
Patch Set: comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/gcm_driver/crypto/gcm_message_cryptographer.h
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer.h b/components/gcm_driver/crypto/gcm_message_cryptographer.h
index 5aaf083cc27eec05cd3afddd6623a63e29897de7..52402c39fe010968e2ccb554e096f9b122e26023 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer.h
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer.h
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/compiler_specific.h"
@@ -16,16 +17,13 @@
namespace gcm {
// Messages delivered through GCM may be encrypted according to the IETF Web
-// Push protocol, as described in draft-ietf-webpush-encryption:
+// Push protocol. We support the third draft of ietf-webpush-encryption:
//
-// https://tools.ietf.org/html/draft-ietf-webpush-encryption
+// https://tools.ietf.org/html/draft-ietf-webpush-encryption-03
//
// This class implements the ability to encrypt or decrypt such messages using
// AEAD_AES_128_GCM with a 16-octet authentication tag. The encrypted payload
-// will be stored in a single record as described in
-// draft-thomson-http-encryption:
-//
-// https://tools.ietf.org/html/draft-thomson-http-encryption
+// will be stored in a single record.
//
// Note that while this class is not responsible for creating or storing the
// actual keys, it uses a key derivation function for the actual message
@@ -37,82 +35,122 @@ class GCMMessageCryptographer {
// unique content encryption key for a given message.
static const size_t kSaltSize;
- // Creates a new cryptographer, identifying the group used for the key
- // agreement, and the public keys of both the recipient and sender.
- GCMMessageCryptographer(const base::StringPiece& recipient_public_key,
- const base::StringPiece& sender_public_key,
- const std::string& auth_secret);
-
+ // Version of the encryption scheme desired by the consumer.
+ enum class Version {
+ // https://tools.ietf.org/html/draft-ietf-webpush-encryption-03
+ DRAFT_03
+
+ // TODO(peter): Add support for ietf-webpush-encryption-08.
+ };
+
+ // Interface that different versions of the encryption scheme must implement.
+ class EncryptionScheme {
+ public:
+ virtual ~EncryptionScheme() {}
+
+ // Type of encoding to produce in GenerateInfoForContentEncoding().
+ enum class EncodingType { CONTENT_ENCRYPTION_KEY, NONCE };
+
+ // Derives the pseudo random key (PRK) to use for deriving the content
+ // encryption key and the nonce.
+ virtual std::string DerivePseudoRandomKey(
+ const base::StringPiece& ecdh_shared_secret,
+ const base::StringPiece& auth_secret) = 0;
+
+ // Generates the info string used for generating the content encryption key
+ // and the nonce used for the cryptographic transformation.
+ virtual std::string GenerateInfoForContentEncoding(
+ EncodingType type,
+ const base::StringPiece& recipient_public_key,
+ const base::StringPiece& sender_public_key) = 0;
+
+ // Creates an encryption record to contain the given |plaintext|.
+ virtual std::string CreateRecord(const base::StringPiece& plaintext) = 0;
+
+ // Verifies that the padding included in |record| is valid and removes it
+ // from the StringPiece. Returns whether the padding was valid.
+ virtual bool ValidateAndRemovePadding(base::StringPiece& record) = 0;
+ };
+
+ // Creates a new cryptographer for |version| of the encryption scheme.
+ explicit GCMMessageCryptographer(Version version);
~GCMMessageCryptographer();
- // Encrypts |plaintext| using the |ikm| and the |salt|, both of which must be
- // 16 octets in length. The |plaintext| will be written to a single record,
- // and will include a 16 octet authentication tag. The encrypted result will
- // be written to |ciphertext|, the record size to |record_size|. This
- // implementation does not support prepending padding to the |plaintext|.
- bool Encrypt(const base::StringPiece& plaintext,
- const base::StringPiece& ikm,
+ // Encrypts the |plaintext| in accordance with the Web Push Encryption scheme
+ // this cryptographer represents, storing the result in |*record_size| and
+ // |*ciphertext|. Returns whether encryption was successful.
+ //
+ // |recipient_public_key|: Recipient's key as an uncompressed P-256 EC point.
+ // |sender_public_key|: Sender's key as an uncompressed P-256 EC point.
+ // |ecdh_shared_secret|: 32-byte shared secret between the key pairs.
+ // |auth_secret|: 16-byte prearranged secret between recipient and sender.
+ // |salt|: 16-byte cryptographically secure salt unique to the message.
+ // |plaintext|: The plaintext that is to be encrypted.
+ // |*record_size|: Out parameter in which the record size will be written.
+ // |*ciphertext|: Out parameter in which the ciphertext will be written.
+ bool Encrypt(const base::StringPiece& recipient_public_key,
+ const base::StringPiece& sender_public_key,
+ const base::StringPiece& ecdh_shared_secret,
+ const base::StringPiece& auth_secret,
const base::StringPiece& salt,
+ const base::StringPiece& plaintext,
size_t* record_size,
std::string* ciphertext) const WARN_UNUSED_RESULT;
- // Decrypts |ciphertext| using the |ikm| and the |salt|, both of which must be
- // 16 octets in length. The result will be stored in |plaintext|. Note that
- // there must only be a single record, per draft-thomson-http-encryption-01.
- bool Decrypt(const base::StringPiece& ciphertext,
- const base::StringPiece& ikm,
+ // Decrypts the |ciphertext| in accordance with the Web Push Encryption scheme
+ // this cryptographer represents, storing the result in |*plaintext|. Returns
+ // whether decryption was successful.
+ //
+ // |recipient_public_key|: Recipient's key as an uncompressed P-256 EC point.
+ // |sender_public_key|: Sender's key as an uncompressed P-256 EC point.
+ // |ecdh_shared_secret|: 32-byte shared secret between the key pairs.
+ // |auth_secret|: 16-byte prearranged secret between recipient and sender.
+ // |salt|: 16-byte cryptographically secure salt unique to the message.
+ // |ciphertext|: The ciphertext that is to be decrypted.
+ // |record_size|: Size of a single record. Must be larger than or equal to
+ // len(plaintext) plus the ciphertext's overhead (18 bytes).
+ // |*plaintext|: Out parameter in which the plaintext will be written.
+ bool Decrypt(const base::StringPiece& recipient_public_key,
+ const base::StringPiece& sender_public_key,
+ const base::StringPiece& ecdh_shared_secret,
+ const base::StringPiece& auth_secret,
const base::StringPiece& salt,
+ const base::StringPiece& ciphertext,
size_t record_size,
std::string* plaintext) const WARN_UNUSED_RESULT;
private:
- FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, AuthSecretAffectsIKM);
+ FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, AuthSecretAffectsPRK);
FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, InvalidRecordPadding);
- FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, NonceGeneration);
- friend class GCMMessageCryptographerReferenceTest;
// Size, in bytes, of the authentication tag included in the messages.
static const size_t kAuthenticationTagBytes;
- enum Mode { ENCRYPT, DECRYPT };
-
- // Private implementation of the encryption and decryption routines, provided
- // by BoringSSL.
- bool EncryptDecryptRecordInternal(Mode mode,
- const base::StringPiece& input,
- const base::StringPiece& key,
- const base::StringPiece& nonce,
- std::string* output) const;
+ enum class Direction { ENCRYPT, DECRYPT };
- // Derives the pseuro random key (PRK) to use for deriving the content
- // encryption key and the nonce. If |auth_secret_| is not the empty string,
- // another HKDF will be invoked between the |key| and the |auth_secret_|.
- std::string DerivePseudoRandomKey(const base::StringPiece& ikm) const;
+ // Derives the content encryption key from |ecdh_shared_secret| and |salt|.
+ std::string DeriveContentEncryptionKey(
+ const base::StringPiece& recipient_public_key,
+ const base::StringPiece& sender_public_key,
+ const base::StringPiece& ecdh_shared_secret,
+ const base::StringPiece& salt) const;
- // Derives the content encryption key from |prk| and |salt|.
- std::string DeriveContentEncryptionKey(const base::StringPiece& prk,
- const base::StringPiece& salt) const;
-
- // Derives the nonce from |prk| and |salt|.
- std::string DeriveNonce(const base::StringPiece& prk,
+ // Derives the nonce from |ecdh_shared_secret| and |salt|.
+ std::string DeriveNonce(const base::StringPiece& recipient_public_key,
+ const base::StringPiece& sender_public_key,
+ const base::StringPiece& ecdh_shared_secret,
const base::StringPiece& salt) const;
- // The info parameters to the HKDFs used for deriving the content encryption
- // key and the nonce. These contain the label of the used curve, as well as
- // the sender and recipient's public keys.
- std::string content_encryption_key_info_;
- std::string nonce_info_;
-
- // The pre-shared authentication secret associated with the subscription.
- std::string auth_secret_;
-
- // Whether an empty auth secret is acceptable when deriving the IKM. This only
- // is the case when running tests against the reference vectors.
- bool allow_empty_auth_secret_for_tests_ = false;
+ // Private implementation of the encryption and decryption routines.
+ bool TransformRecord(Direction direction,
+ const base::StringPiece& input,
+ const base::StringPiece& key,
+ const base::StringPiece& nonce,
+ std::string* output) const;
- void set_allow_empty_auth_secret_for_tests(bool value) {
- allow_empty_auth_secret_for_tests_ = value;
- }
+ // Implementation of the encryption scheme. Set in the constructor depending
+ // on the version requested by the consumer.
+ std::unique_ptr<EncryptionScheme> encryption_scheme_;
};
} // namespace gcm

Powered by Google App Engine
This is Rietveld 408576698