summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-03 21:35:20 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-03 21:35:20 +0000
commit52e28da70fc4b01c6b17336592c5dae6bb658f80 (patch)
tree59af046f0bbceceaa8308338a0f27c4c67c117b6 /net
parent3969a7882a0dda2816f7513d002f7caac73db348 (diff)
downloadchromium_src-52e28da70fc4b01c6b17336592c5dae6bb658f80.zip
chromium_src-52e28da70fc4b01c6b17336592c5dae6bb658f80.tar.gz
chromium_src-52e28da70fc4b01c6b17336592c5dae6bb658f80.tar.bz2
Switch QUIC encryption to use OpenSSL's AEAD interface.
The AEAD interface is quite a lot cleaner than the EVP_CIPHER one. This change switches the QUIC code over to using it for AES-128-GCM-12. Merge internal CL: 53267501 R=rch@chromium.org,rtenneti@chromium.org BUG=none TEST=net_unittests --gtest_filter=Aes128Gcm12* Review URL: https://codereview.chromium.org/106053013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@242928 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/net.gyp8
-rw-r--r--net/quic/crypto/aes_128_gcm_12_decrypter.h6
-rw-r--r--net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc74
-rw-r--r--net/quic/crypto/aes_128_gcm_12_encrypter.h6
-rw-r--r--net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc59
-rw-r--r--net/quic/crypto/scoped_evp_aead_ctx.cc23
-rw-r--r--net/quic/crypto/scoped_evp_aead_ctx.h27
-rw-r--r--net/quic/crypto/scoped_evp_cipher_ctx.cc22
-rw-r--r--net/quic/crypto/scoped_evp_cipher_ctx.h30
9 files changed, 90 insertions, 165 deletions
diff --git a/net/net.gyp b/net/net.gyp
index 6be4278..a035b7b 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -822,8 +822,8 @@
'quic/crypto/quic_encrypter.h',
'quic/crypto/quic_random.cc',
'quic/crypto/quic_random.h',
- 'quic/crypto/scoped_evp_cipher_ctx.cc',
- 'quic/crypto/scoped_evp_cipher_ctx.h',
+ 'quic/crypto/scoped_evp_aead_ctx.cc',
+ 'quic/crypto/scoped_evp_aead_ctx.h',
'quic/crypto/strike_register.cc',
'quic/crypto/strike_register.h',
'quic/crypto/strike_register_client.h',
@@ -1352,8 +1352,8 @@
'quic/crypto/aes_128_gcm_12_encrypter_openssl.cc',
'quic/crypto/channel_id_openssl.cc',
'quic/crypto/p256_key_exchange_openssl.cc',
- 'quic/crypto/scoped_evp_cipher_ctx.cc',
- 'quic/crypto/scoped_evp_cipher_ctx.h',
+ 'quic/crypto/scoped_evp_aead_ctx.cc',
+ 'quic/crypto/scoped_evp_aead_ctx.h',
'socket/ssl_client_socket_openssl.cc',
'socket/ssl_client_socket_openssl.h',
'socket/ssl_server_socket_openssl.cc',
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter.h b/net/quic/crypto/aes_128_gcm_12_decrypter.h
index aba610f..146a86b 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter.h
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter.h
@@ -11,7 +11,7 @@
#include "net/quic/crypto/quic_decrypter.h"
#if defined(USE_OPENSSL)
-#include "net/quic/crypto/scoped_evp_cipher_ctx.h"
+#include "net/quic/crypto/scoped_evp_aead_ctx.h"
#endif
namespace net {
@@ -60,9 +60,7 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Decrypter : public QuicDecrypter {
unsigned char nonce_prefix_[4];
#if defined(USE_OPENSSL)
- // TODO(rtenneti): when Chromium's version of OpenSSL has EVP_AEAD_CTX, merge
- // internal CL 53267501.
- ScopedEVPCipherCtx ctx_;
+ ScopedEVPAEADCtx ctx_;
#endif
};
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc
index 56317fd..7d761e9 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc
@@ -4,6 +4,7 @@
#include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
+#include <openssl/err.h>
#include <openssl/evp.h>
#include "base/memory/scoped_ptr.h"
@@ -12,9 +13,13 @@ using base::StringPiece;
namespace net {
+namespace {
+
const size_t kNoncePrefixSize = 4;
const size_t kAESNonceSize = 12;
+} // namespace
+
Aes128Gcm12Decrypter::Aes128Gcm12Decrypter() {}
Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {}
@@ -29,15 +34,11 @@ bool Aes128Gcm12Decrypter::SetKey(StringPiece key) {
}
memcpy(key_, key.data(), key.size());
- // Set the cipher type and the key.
- if (EVP_EncryptInit_ex(ctx_.get(), EVP_aes_128_gcm(), NULL, key_,
- NULL) == 0) {
- return false;
- }
-
- // Set the IV (nonce) length.
- if (EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_GCM_SET_IVLEN, kAESNonceSize,
- NULL) == 0) {
+ EVP_AEAD_CTX_cleanup(ctx_.get());
+ if (!EVP_AEAD_CTX_init(ctx_.get(), EVP_aead_aes_128_gcm(), key_,
+ sizeof(key_), kAuthTagSize, NULL)) {
+ // Clear OpenSSL error stack.
+ while (ERR_get_error()) {}
return false;
}
@@ -63,52 +64,21 @@ bool Aes128Gcm12Decrypter::Decrypt(StringPiece nonce,
nonce.size() != kNoncePrefixSize + sizeof(QuicPacketSequenceNumber)) {
return false;
}
- const size_t plaintext_size = ciphertext.length() - kAuthTagSize;
-
- // Set the IV (nonce).
- if (EVP_DecryptInit_ex(
- ctx_.get(), NULL, NULL, NULL,
- reinterpret_cast<const uint8*>(nonce.data())) == 0) {
- return false;
- }
- // Set the authentication tag.
- if (EVP_CIPHER_CTX_ctrl(
- ctx_.get(), EVP_CTRL_GCM_SET_TAG, kAuthTagSize,
- const_cast<char*>(ciphertext.data()) + plaintext_size) == 0) {
- return false;
- }
-
- // If we pass a NULL, zero-length associated data to OpenSSL then it breaks.
- // Thus we only set non-empty associated data.
- if (!associated_data.empty()) {
- // Set the associated data. The second argument (output buffer) must be
- // NULL.
- int unused_len;
- if (EVP_DecryptUpdate(
- ctx_.get(), NULL, &unused_len,
- reinterpret_cast<const uint8*>(associated_data.data()),
- associated_data.size()) == 0) {
- return false;
- }
- }
+ ssize_t len = EVP_AEAD_CTX_open(
+ ctx_.get(), output, ciphertext.size(),
+ reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
+ reinterpret_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(),
+ reinterpret_cast<const uint8_t*>(associated_data.data()),
+ associated_data.size());
- int len;
- if (EVP_DecryptUpdate(
- ctx_.get(), output, &len,
- reinterpret_cast<const uint8*>(ciphertext.data()),
- plaintext_size) == 0) {
+ if (len < 0) {
+ // Clear OpenSSL error stack.
+ while (ERR_get_error()) {}
return false;
}
- output += len;
-
- if (EVP_DecryptFinal_ex(ctx_.get(), output, &len) == 0) {
- return false;
- }
- output += len;
-
- *output_length = plaintext_size;
+ *output_length = len;
return true;
}
@@ -119,8 +89,8 @@ QuicData* Aes128Gcm12Decrypter::DecryptPacket(
if (ciphertext.length() < kAuthTagSize) {
return NULL;
}
- size_t plaintext_size;
- scoped_ptr<char[]> plaintext(new char[ciphertext.length()]);
+ size_t plaintext_size = ciphertext.length();
+ scoped_ptr<char[]> plaintext(new char[plaintext_size]);
uint8 nonce[kNoncePrefixSize + sizeof(sequence_number)];
COMPILE_ASSERT(sizeof(nonce) == kAESNonceSize, bad_sequence_number_size);
diff --git a/net/quic/crypto/aes_128_gcm_12_encrypter.h b/net/quic/crypto/aes_128_gcm_12_encrypter.h
index a2d1dc9..d939b78 100644
--- a/net/quic/crypto/aes_128_gcm_12_encrypter.h
+++ b/net/quic/crypto/aes_128_gcm_12_encrypter.h
@@ -11,7 +11,7 @@
#include "net/quic/crypto/quic_encrypter.h"
#if defined(USE_OPENSSL)
-#include "net/quic/crypto/scoped_evp_cipher_ctx.h"
+#include "net/quic/crypto/scoped_evp_aead_ctx.h"
#endif
namespace net {
@@ -60,9 +60,7 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Encrypter : public QuicEncrypter {
unsigned char nonce_prefix_[4];
#if defined(USE_OPENSSL)
- // TODO(rtenneti): when Chromium's version of OpenSSL has EVP_AEAD_CTX, merge
- // internal CL 53267501.
- ScopedEVPCipherCtx ctx_;
+ ScopedEVPAEADCtx ctx_;
#endif
};
diff --git a/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc b/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc
index 394971a7..dfa990e 100644
--- a/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc
+++ b/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc
@@ -45,16 +45,10 @@ bool Aes128Gcm12Encrypter::SetKey(StringPiece key) {
}
memcpy(key_, key.data(), key.size());
- // Set the cipher type and the key.
- if (EVP_EncryptInit_ex(ctx_.get(), EVP_aes_128_gcm(), NULL, key_,
- NULL) == 0) {
- ClearOpenSslErrors();
- return false;
- }
+ EVP_AEAD_CTX_cleanup(ctx_.get());
- // Set the IV (nonce) length.
- if (EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_GCM_SET_IVLEN, kAESNonceSize,
- NULL) == 0) {
+ if (!EVP_AEAD_CTX_init(ctx_.get(), EVP_aead_aes_128_gcm(), key_,
+ sizeof(key_), kAuthTagSize, NULL)) {
ClearOpenSslErrors();
return false;
}
@@ -80,47 +74,14 @@ bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce,
return false;
}
- // Set the IV (nonce).
- if (EVP_EncryptInit_ex(
- ctx_.get(), NULL, NULL, NULL,
- reinterpret_cast<const unsigned char*>(nonce.data())) == 0) {
- ClearOpenSslErrors();
- return false;
- }
-
- // If we pass a NULL, zero-length associated data to OpenSSL then it breaks.
- // Thus we only set non-empty associated data.
- if (!associated_data.empty()) {
- // Set the associated data. The second argument (output buffer) must be
- // NULL.
- int unused_len;
- if (EVP_EncryptUpdate(
- ctx_.get(), NULL, &unused_len,
- reinterpret_cast<const unsigned char*>(associated_data.data()),
- associated_data.size()) == 0) {
- ClearOpenSslErrors();
- return false;
- }
- }
-
- int len;
- if (EVP_EncryptUpdate(
- ctx_.get(), output, &len,
- reinterpret_cast<const unsigned char*>(plaintext.data()),
- plaintext.size()) == 0) {
- ClearOpenSslErrors();
- return false;
- }
- output += len;
-
- if (EVP_EncryptFinal_ex(ctx_.get(), output, &len) == 0) {
- ClearOpenSslErrors();
- return false;
- }
- output += len;
+ ssize_t len = EVP_AEAD_CTX_seal(
+ ctx_.get(), output, plaintext.size() + kAuthTagSize,
+ reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
+ reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size(),
+ reinterpret_cast<const uint8_t*>(associated_data.data()),
+ associated_data.size());
- if (EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_GCM_GET_TAG, kAuthTagSize,
- output) == 0) {
+ if (len < 0) {
ClearOpenSslErrors();
return false;
}
diff --git a/net/quic/crypto/scoped_evp_aead_ctx.cc b/net/quic/crypto/scoped_evp_aead_ctx.cc
new file mode 100644
index 0000000..2b5feb3
--- /dev/null
+++ b/net/quic/crypto/scoped_evp_aead_ctx.cc
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/crypto/scoped_evp_aead_ctx.h"
+
+namespace net {
+
+ScopedEVPAEADCtx::ScopedEVPAEADCtx() {
+ ctx_.aead = NULL;
+}
+
+ScopedEVPAEADCtx::~ScopedEVPAEADCtx() {
+ if (ctx_.aead != NULL) {
+ EVP_AEAD_CTX_cleanup(&ctx_);
+ }
+}
+
+EVP_AEAD_CTX* ScopedEVPAEADCtx::get() {
+ return &ctx_;
+}
+
+} // namespace net
diff --git a/net/quic/crypto/scoped_evp_aead_ctx.h b/net/quic/crypto/scoped_evp_aead_ctx.h
new file mode 100644
index 0000000..f8bb356
--- /dev/null
+++ b/net/quic/crypto/scoped_evp_aead_ctx.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
+#define NET_QUIC_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
+
+#include <openssl/evp.h>
+
+namespace net {
+
+// ScopedEVPAEADCtx manages an EVP_AEAD_CTX object and calls the needed cleanup
+// functions when it goes out of scope.
+class ScopedEVPAEADCtx {
+ public:
+ ScopedEVPAEADCtx();
+ ~ScopedEVPAEADCtx();
+
+ EVP_AEAD_CTX* get();
+
+ private:
+ EVP_AEAD_CTX ctx_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CRYPTO_SCOPED_EVP_AEAD_CTX_H_
diff --git a/net/quic/crypto/scoped_evp_cipher_ctx.cc b/net/quic/crypto/scoped_evp_cipher_ctx.cc
deleted file mode 100644
index b904f87..0000000
--- a/net/quic/crypto/scoped_evp_cipher_ctx.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/scoped_evp_cipher_ctx.h"
-
-#include <openssl/evp.h>
-
-namespace net {
-
-ScopedEVPCipherCtx::ScopedEVPCipherCtx()
- : ctx_(EVP_CIPHER_CTX_new()) { }
-
-ScopedEVPCipherCtx::~ScopedEVPCipherCtx() {
- EVP_CIPHER_CTX_free(ctx_);
-}
-
-EVP_CIPHER_CTX* ScopedEVPCipherCtx::get() const {
- return ctx_;
-}
-
-} // namespace net
diff --git a/net/quic/crypto/scoped_evp_cipher_ctx.h b/net/quic/crypto/scoped_evp_cipher_ctx.h
deleted file mode 100644
index ec0fd51..0000000
--- a/net/quic/crypto/scoped_evp_cipher_ctx.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_CRYPTO_SCOPED_EVP_CIPHER_CTX_H_
-#define NET_QUIC_CRYPTO_SCOPED_EVP_CIPHER_CTX_H_
-
-typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
-
-namespace net {
-
-// TODO(wtc): this is the same as the ScopedCipherCTX class defined in
-// crypto/encryptor_openssl.cc. Eliminate the duplicate code.
-// crypto::ScopedOpenSSL is not suitable for EVP_CIPHER_CTX because
-// there are no EVP_CIPHER_CTX_create and EVP_CIPHER_CTX_destroy
-// functions.
-class ScopedEVPCipherCtx {
- public:
- ScopedEVPCipherCtx();
- ~ScopedEVPCipherCtx();
-
- EVP_CIPHER_CTX* get() const;
-
- private:
- EVP_CIPHER_CTX* const ctx_;
-};
-
-} // namespace net
-
-#endif // NET_QUIC_CRYPTO_SCOPED_EVP_CIPHER_CTX_H_