OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" | 5 #include "net/quic/crypto/aead_base_encrypter.h" |
6 | 6 |
7 #include <openssl/err.h> | 7 #include <openssl/err.h> |
8 #include <openssl/evp.h> | 8 #include <openssl/evp.h> |
9 #include <string.h> | 9 #include <string.h> |
10 | 10 |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 | 12 |
13 using base::StringPiece; | 13 using base::StringPiece; |
14 | 14 |
15 namespace net { | 15 namespace net { |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
19 const size_t kKeySize = 16; | 19 // Clear OpenSSL error stack. |
20 const size_t kNoncePrefixSize = 4; | |
21 const size_t kAESNonceSize = 12; | |
22 | |
23 void ClearOpenSslErrors() { | 20 void ClearOpenSslErrors() { |
24 #ifdef NDEBUG | 21 #ifdef NDEBUG |
25 while (ERR_get_error()) {} | 22 while (ERR_get_error()) {} |
26 #else | 23 #else |
27 while (long error = ERR_get_error()) { | 24 while (unsigned long error = ERR_get_error()) { |
28 char buf[120]; | 25 char buf[120]; |
29 ERR_error_string_n(error, buf, arraysize(buf)); | 26 ERR_error_string_n(error, buf, arraysize(buf)); |
30 DLOG(ERROR) << "OpenSSL error: " << buf; | 27 DLOG(ERROR) << "OpenSSL error: " << buf; |
31 } | 28 } |
32 #endif | 29 #endif |
33 } | 30 } |
34 | 31 |
35 } // namespace | 32 } // namespace |
36 | 33 |
37 Aes128Gcm12Encrypter::Aes128Gcm12Encrypter() {} | 34 AeadBaseEncrypter::AeadBaseEncrypter(const EVP_AEAD* aead_alg, |
| 35 size_t key_size, |
| 36 size_t auth_tag_size, |
| 37 size_t nonce_prefix_size) |
| 38 : aead_alg_(aead_alg), |
| 39 key_size_(key_size), |
| 40 auth_tag_size_(auth_tag_size), |
| 41 nonce_prefix_size_(nonce_prefix_size) { |
| 42 DCHECK_LE(key_size_, sizeof(key_)); |
| 43 DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_)); |
| 44 } |
38 | 45 |
39 Aes128Gcm12Encrypter::~Aes128Gcm12Encrypter() {} | 46 AeadBaseEncrypter::~AeadBaseEncrypter() {} |
40 | 47 |
41 bool Aes128Gcm12Encrypter::SetKey(StringPiece key) { | 48 bool AeadBaseEncrypter::SetKey(StringPiece key) { |
42 DCHECK_EQ(key.size(), sizeof(key_)); | 49 DCHECK_EQ(key.size(), key_size_); |
43 if (key.size() != sizeof(key_)) { | 50 if (key.size() != key_size_) { |
44 return false; | 51 return false; |
45 } | 52 } |
46 memcpy(key_, key.data(), key.size()); | 53 memcpy(key_, key.data(), key.size()); |
47 | 54 |
48 EVP_AEAD_CTX_cleanup(ctx_.get()); | 55 EVP_AEAD_CTX_cleanup(ctx_.get()); |
49 | 56 |
50 if (!EVP_AEAD_CTX_init(ctx_.get(), EVP_aead_aes_128_gcm(), key_, | 57 if (!EVP_AEAD_CTX_init(ctx_.get(), aead_alg_, key_, key_size_, |
51 sizeof(key_), kAuthTagSize, NULL)) { | 58 auth_tag_size_, NULL)) { |
52 ClearOpenSslErrors(); | 59 ClearOpenSslErrors(); |
53 return false; | 60 return false; |
54 } | 61 } |
55 | 62 |
56 return true; | 63 return true; |
57 } | 64 } |
58 | 65 |
59 bool Aes128Gcm12Encrypter::SetNoncePrefix(StringPiece nonce_prefix) { | 66 bool AeadBaseEncrypter::SetNoncePrefix(StringPiece nonce_prefix) { |
60 DCHECK_EQ(nonce_prefix.size(), kNoncePrefixSize); | 67 DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_); |
61 if (nonce_prefix.size() != kNoncePrefixSize) { | 68 if (nonce_prefix.size() != nonce_prefix_size_) { |
62 return false; | 69 return false; |
63 } | 70 } |
64 COMPILE_ASSERT(sizeof(nonce_prefix_) == kNoncePrefixSize, bad_nonce_length); | |
65 memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); | 71 memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); |
66 return true; | 72 return true; |
67 } | 73 } |
68 | 74 |
69 bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce, | 75 bool AeadBaseEncrypter::Encrypt(StringPiece nonce, |
70 StringPiece associated_data, | 76 StringPiece associated_data, |
71 StringPiece plaintext, | 77 StringPiece plaintext, |
72 unsigned char* output) { | 78 unsigned char* output) { |
73 if (nonce.size() != kNoncePrefixSize + sizeof(QuicPacketSequenceNumber)) { | 79 if (nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketSequenceNumber)) { |
74 return false; | 80 return false; |
75 } | 81 } |
76 | 82 |
77 ssize_t len = EVP_AEAD_CTX_seal( | 83 ssize_t len = EVP_AEAD_CTX_seal( |
78 ctx_.get(), output, plaintext.size() + kAuthTagSize, | 84 ctx_.get(), output, plaintext.size() + auth_tag_size_, |
79 reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(), | 85 reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(), |
80 reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size(), | 86 reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size(), |
81 reinterpret_cast<const uint8_t*>(associated_data.data()), | 87 reinterpret_cast<const uint8_t*>(associated_data.data()), |
82 associated_data.size()); | 88 associated_data.size()); |
83 | 89 |
84 if (len < 0) { | 90 if (len < 0) { |
85 ClearOpenSslErrors(); | 91 ClearOpenSslErrors(); |
86 return false; | 92 return false; |
87 } | 93 } |
88 | 94 |
89 return true; | 95 return true; |
90 } | 96 } |
91 | 97 |
92 QuicData* Aes128Gcm12Encrypter::EncryptPacket( | 98 QuicData* AeadBaseEncrypter::EncryptPacket( |
93 QuicPacketSequenceNumber sequence_number, | 99 QuicPacketSequenceNumber sequence_number, |
94 StringPiece associated_data, | 100 StringPiece associated_data, |
95 StringPiece plaintext) { | 101 StringPiece plaintext) { |
96 size_t ciphertext_size = GetCiphertextSize(plaintext.length()); | 102 size_t ciphertext_size = GetCiphertextSize(plaintext.length()); |
97 scoped_ptr<char[]> ciphertext(new char[ciphertext_size]); | 103 scoped_ptr<char[]> ciphertext(new char[ciphertext_size]); |
98 | 104 |
99 // TODO(ianswett): Introduce a check to ensure that we don't encrypt with the | 105 // TODO(ianswett): Introduce a check to ensure that we don't encrypt with the |
100 // same sequence number twice. | 106 // same sequence number twice. |
101 uint8 nonce[kNoncePrefixSize + sizeof(sequence_number)]; | 107 uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)]; |
102 COMPILE_ASSERT(sizeof(nonce) == kAESNonceSize, bad_sequence_number_size); | 108 const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number); |
103 memcpy(nonce, nonce_prefix_, kNoncePrefixSize); | 109 DCHECK_LE(nonce_size, sizeof(nonce)); |
104 memcpy(nonce + kNoncePrefixSize, &sequence_number, sizeof(sequence_number)); | 110 memcpy(nonce, nonce_prefix_, nonce_prefix_size_); |
105 if (!Encrypt(StringPiece(reinterpret_cast<char*>(nonce), sizeof(nonce)), | 111 memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number)); |
| 112 if (!Encrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size), |
106 associated_data, plaintext, | 113 associated_data, plaintext, |
107 reinterpret_cast<unsigned char*>(ciphertext.get()))) { | 114 reinterpret_cast<unsigned char*>(ciphertext.get()))) { |
108 return NULL; | 115 return NULL; |
109 } | 116 } |
110 | 117 |
111 return new QuicData(ciphertext.release(), ciphertext_size, true); | 118 return new QuicData(ciphertext.release(), ciphertext_size, true); |
112 } | 119 } |
113 | 120 |
114 size_t Aes128Gcm12Encrypter::GetKeySize() const { return kKeySize; } | 121 size_t AeadBaseEncrypter::GetKeySize() const { return key_size_; } |
115 | 122 |
116 size_t Aes128Gcm12Encrypter::GetNoncePrefixSize() const { | 123 size_t AeadBaseEncrypter::GetNoncePrefixSize() const { |
117 return kNoncePrefixSize; | 124 return nonce_prefix_size_; |
118 } | 125 } |
119 | 126 |
120 size_t Aes128Gcm12Encrypter::GetMaxPlaintextSize(size_t ciphertext_size) const { | 127 size_t AeadBaseEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const { |
121 return ciphertext_size - kAuthTagSize; | 128 return ciphertext_size - auth_tag_size_; |
122 } | 129 } |
123 | 130 |
124 // An AEAD_AES_128_GCM_12 ciphertext is exactly 12 bytes longer than its | 131 size_t AeadBaseEncrypter::GetCiphertextSize(size_t plaintext_size) const { |
125 // corresponding plaintext. | 132 return plaintext_size + auth_tag_size_; |
126 size_t Aes128Gcm12Encrypter::GetCiphertextSize(size_t plaintext_size) const { | |
127 return plaintext_size + kAuthTagSize; | |
128 } | 133 } |
129 | 134 |
130 StringPiece Aes128Gcm12Encrypter::GetKey() const { | 135 StringPiece AeadBaseEncrypter::GetKey() const { |
131 return StringPiece(reinterpret_cast<const char*>(key_), sizeof(key_)); | 136 return StringPiece(reinterpret_cast<const char*>(key_), key_size_); |
132 } | 137 } |
133 | 138 |
134 StringPiece Aes128Gcm12Encrypter::GetNoncePrefix() const { | 139 StringPiece AeadBaseEncrypter::GetNoncePrefix() const { |
| 140 if (nonce_prefix_size_ == 0) { |
| 141 return StringPiece(); |
| 142 } |
135 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), | 143 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), |
136 kNoncePrefixSize); | 144 nonce_prefix_size_); |
137 } | 145 } |
138 | 146 |
139 } // namespace net | 147 } // namespace net |
OLD | NEW |