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

Side by Side Diff: components/gcm_driver/crypto/gcm_message_cryptographer.h

Issue 2713673002: Separate out the scheme from the GCMMessageCryptographer (Closed)
Patch Set: Separate out the scheme from the GCMMessageCryptographer Created 3 years, 10 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef COMPONENTS_GCM_DRIVER_CRYPTO_GCM_MESSAGE_CRYPTOGRAPHER_H_ 5 #ifndef COMPONENTS_GCM_DRIVER_CRYPTO_GCM_MESSAGE_CRYPTOGRAPHER_H_
6 #define COMPONENTS_GCM_DRIVER_CRYPTO_GCM_MESSAGE_CRYPTOGRAPHER_H_ 6 #define COMPONENTS_GCM_DRIVER_CRYPTO_GCM_MESSAGE_CRYPTOGRAPHER_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 #include <memory>
10 #include <string> 11 #include <string>
11 12
12 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
13 #include "base/gtest_prod_util.h" 14 #include "base/gtest_prod_util.h"
14 #include "base/strings/string_piece.h" 15 #include "base/strings/string_piece.h"
15 16
16 namespace gcm { 17 namespace gcm {
17 18
18 // Messages delivered through GCM may be encrypted according to the IETF Web 19 // Messages delivered through GCM may be encrypted according to the IETF Web
19 // Push protocol, as described in draft-ietf-webpush-encryption: 20 // Push protocol. We support the third draft of ietf-webpush-encryption:
20 // 21 //
21 // https://tools.ietf.org/html/draft-ietf-webpush-encryption 22 // https://tools.ietf.org/html/draft-ietf-webpush-encryption-03
22 // 23 //
23 // This class implements the ability to encrypt or decrypt such messages using 24 // This class implements the ability to encrypt or decrypt such messages using
24 // AEAD_AES_128_GCM with a 16-octet authentication tag. The encrypted payload 25 // AEAD_AES_128_GCM with a 16-octet authentication tag. The encrypted payload
25 // will be stored in a single record as described in 26 // will be stored in a single record.
26 // draft-thomson-http-encryption:
27 //
28 // https://tools.ietf.org/html/draft-thomson-http-encryption
29 // 27 //
30 // Note that while this class is not responsible for creating or storing the 28 // Note that while this class is not responsible for creating or storing the
31 // actual keys, it uses a key derivation function for the actual message 29 // actual keys, it uses a key derivation function for the actual message
32 // encryption/decryption, thus allowing for the safe re-use of keys in multiple 30 // encryption/decryption, thus allowing for the safe re-use of keys in multiple
33 // messages provided that a cryptographically-strong random salt is used. 31 // messages provided that a cryptographically-strong random salt is used.
34 class GCMMessageCryptographer { 32 class GCMMessageCryptographer {
35 public: 33 public:
36 // Salt size, in bytes, that will be used together with the key to create a 34 // Salt size, in bytes, that will be used together with the key to create a
37 // unique content encryption key for a given message. 35 // unique content encryption key for a given message.
38 static const size_t kSaltSize; 36 static const size_t kSaltSize;
39 37
40 // Creates a new cryptographer, identifying the group used for the key 38 // Version of the encryption scheme desired by the consumer.
41 // agreement, and the public keys of both the recipient and sender. 39 enum class Version {
42 GCMMessageCryptographer(const base::StringPiece& recipient_public_key, 40 // https://tools.ietf.org/html/draft-ietf-webpush-encryption-03
43 const base::StringPiece& sender_public_key, 41 DRAFT_03
44 const std::string& auth_secret);
45 42
43 // TODO(peter): Add support for ietf-webpush-encryption-08.
44 };
45
46 // Interface that different versions of the encryption scheme must implement.
47 class EncryptionScheme {
48 public:
49 virtual ~EncryptionScheme() {}
50
51 // Type of encoding to produce in GenerateInfoForContentEncoding().
52 enum class EncodingType { CONTENT_ENCRYPTION_KEY, NONCE };
53
54 // Derives the pseuro random key (PRK) to use for deriving the content
martijnc 2017/03/28 16:26:36 typo: pseudo
Peter Beverloo 2017/04/07 17:48:22 Done.
55 // encryption key and the nonce.
56 virtual std::string DerivePseudoRandomKey(
57 const base::StringPiece& ecdh_shared_secret,
58 const base::StringPiece& auth_secret) = 0;
59
60 // Generates the info string used for generating the content encryption key
61 // and the nonce used for the cryptographic transformation.
62 virtual std::string GenerateInfoForContentEncoding(
63 EncodingType type,
64 const base::StringPiece& recipient_public_key,
65 const base::StringPiece& sender_public_key) = 0;
66
67 // Creates an encryption record to contain the given |plaintext|.
68 virtual std::string CreateRecord(const base::StringPiece& plaintext) = 0;
69
70 // Verifies that the padding included in |record| is valid and removes it
71 // from the StringPiece. Returns whether the padding was valid.
72 virtual bool ValidateAndRemovePadding(base::StringPiece& record) = 0;
73 };
74
75 // Creates a new cryptographer for |version| of the encryption scheme.
76 explicit GCMMessageCryptographer(Version version);
46 ~GCMMessageCryptographer(); 77 ~GCMMessageCryptographer();
47 78
48 // Encrypts |plaintext| using the |ikm| and the |salt|, both of which must be 79 // Encrypts the |plaintext| in accordance with the Web Push Encryption scheme
49 // 16 octets in length. The |plaintext| will be written to a single record, 80 // this cryptographer represents, storing the result in |*record_size| and
50 // and will include a 16 octet authentication tag. The encrypted result will 81 // |*ciphertext|. Returns whether encryption was successful.
51 // be written to |ciphertext|, the record size to |record_size|. This 82 //
52 // implementation does not support prepending padding to the |plaintext|. 83 // |recipient_public_key|: Recipient's key as an uncompressed P-256 EC point.
53 bool Encrypt(const base::StringPiece& plaintext, 84 // |sender_public_key|: Sender's key as an uncompressed P-256 EC point.
54 const base::StringPiece& ikm, 85 // |ecdh_shared_secret|: 32-byte shared secret between the key pairs.
86 // |auth_secret|: 16-byte prearranged secret between recipient and sender.
87 // |salt|: 16-byte cryptographically secure salt unique to the message.
88 // |plaintext|: The plaintext that is to be encrypted.
89 // |*record_size|: Out parameter in which the record size will be written.
90 // |*ciphertext|: Out parameter in which the ciphertext will be written.
91 bool Encrypt(const base::StringPiece& recipient_public_key,
92 const base::StringPiece& sender_public_key,
93 const base::StringPiece& ecdh_shared_secret,
94 const base::StringPiece& auth_secret,
55 const base::StringPiece& salt, 95 const base::StringPiece& salt,
96 const base::StringPiece& plaintext,
56 size_t* record_size, 97 size_t* record_size,
57 std::string* ciphertext) const WARN_UNUSED_RESULT; 98 std::string* ciphertext) const WARN_UNUSED_RESULT;
58 99
59 // Decrypts |ciphertext| using the |ikm| and the |salt|, both of which must be 100 // Decrypts the |ciphertext| in accordance with the Web Push Encryption scheme
60 // 16 octets in length. The result will be stored in |plaintext|. Note that 101 // this cryptographer represents, storing the result in |*plaintext|. Returns
61 // there must only be a single record, per draft-thomson-http-encryption-01. 102 // whether decryption was successful.
62 bool Decrypt(const base::StringPiece& ciphertext, 103 //
63 const base::StringPiece& ikm, 104 // |recipient_public_key|: Recipient's key as an uncompressed P-256 EC point.
105 // |sender_public_key|: Sender's key as an uncompressed P-256 EC point.
106 // |ecdh_shared_secret|: 32-byte shared secret between the key pairs.
107 // |auth_secret|: 16-byte prearranged secret between recipient and sender.
108 // |salt|: 16-byte cryptographically secure salt unique to the message.
109 // |ciphertext|: The ciphertext that is to be decrypted.
110 // |record_size|: Size of a single record. Must be larger than or equal to
111 // len(plaintext) plus the ciphertext's overhead (18 bytes).
112 // |*plaintext|: Out parameter in which the plaintext will be written.
113 bool Decrypt(const base::StringPiece& recipient_public_key,
114 const base::StringPiece& sender_public_key,
115 const base::StringPiece& ecdh_shared_secret,
116 const base::StringPiece& auth_secret,
64 const base::StringPiece& salt, 117 const base::StringPiece& salt,
118 const base::StringPiece& ciphertext,
65 size_t record_size, 119 size_t record_size,
66 std::string* plaintext) const WARN_UNUSED_RESULT; 120 std::string* plaintext) const WARN_UNUSED_RESULT;
67 121
68 private: 122 private:
69 FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, AuthSecretAffectsIKM); 123 FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, AuthSecretAffectsPRK);
70 FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, InvalidRecordPadding); 124 FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, InvalidRecordPadding);
71 FRIEND_TEST_ALL_PREFIXES(GCMMessageCryptographerTest, NonceGeneration);
72 friend class GCMMessageCryptographerReferenceTest;
73 125
74 // Size, in bytes, of the authentication tag included in the messages. 126 // Size, in bytes, of the authentication tag included in the messages.
75 static const size_t kAuthenticationTagBytes; 127 static const size_t kAuthenticationTagBytes;
76 128
77 enum Mode { ENCRYPT, DECRYPT }; 129 enum class Direction { ENCRYPT, DECRYPT };
78 130
79 // Private implementation of the encryption and decryption routines, provided 131 // Derives the content encryption key from |ecdh_shared_secret| and |salt|.
80 // by BoringSSL. 132 std::string DeriveContentEncryptionKey(
81 bool EncryptDecryptRecordInternal(Mode mode, 133 const base::StringPiece& recipient_public_key,
82 const base::StringPiece& input, 134 const base::StringPiece& sender_public_key,
83 const base::StringPiece& key, 135 const base::StringPiece& ecdh_shared_secret,
84 const base::StringPiece& nonce, 136 const base::StringPiece& salt) const;
85 std::string* output) const;
86 137
87 // Derives the pseuro random key (PRK) to use for deriving the content 138 // Derives the nonce from |ecdh_shared_secret| and |salt|.
88 // encryption key and the nonce. If |auth_secret_| is not the empty string, 139 std::string DeriveNonce(const base::StringPiece& recipient_public_key,
89 // another HKDF will be invoked between the |key| and the |auth_secret_|. 140 const base::StringPiece& sender_public_key,
90 std::string DerivePseudoRandomKey(const base::StringPiece& ikm) const; 141 const base::StringPiece& ecdh_shared_secret,
91
92 // Derives the content encryption key from |prk| and |salt|.
93 std::string DeriveContentEncryptionKey(const base::StringPiece& prk,
94 const base::StringPiece& salt) const;
95
96 // Derives the nonce from |prk| and |salt|.
97 std::string DeriveNonce(const base::StringPiece& prk,
98 const base::StringPiece& salt) const; 142 const base::StringPiece& salt) const;
99 143
100 // The info parameters to the HKDFs used for deriving the content encryption 144 // Private implementation of the encryption and decryption routines.
101 // key and the nonce. These contain the label of the used curve, as well as 145 bool TransformRecord(Direction direction,
102 // the sender and recipient's public keys. 146 const base::StringPiece& input,
103 std::string content_encryption_key_info_; 147 const base::StringPiece& key,
104 std::string nonce_info_; 148 const base::StringPiece& nonce,
149 std::string* output) const;
105 150
106 // The pre-shared authentication secret associated with the subscription. 151 // Implementation of the encryption scheme. Set in the constructor depending
107 std::string auth_secret_; 152 // on the version requested by the consumer.
108 153 std::unique_ptr<EncryptionScheme> encryption_scheme_;
109 // Whether an empty auth secret is acceptable when deriving the IKM. This only
110 // is the case when running tests against the reference vectors.
111 bool allow_empty_auth_secret_for_tests_ = false;
112
113 void set_allow_empty_auth_secret_for_tests(bool value) {
114 allow_empty_auth_secret_for_tests_ = value;
115 }
116 }; 154 };
117 155
118 } // namespace gcm 156 } // namespace gcm
119 157
120 #endif // COMPONENTS_GCM_DRIVER_CRYPTO_GCM_MESSAGE_CRYPTOGRAPHER_H_ 158 #endif // COMPONENTS_GCM_DRIVER_CRYPTO_GCM_MESSAGE_CRYPTOGRAPHER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698