diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-03 21:35:20 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-03 21:35:20 +0000 |
commit | 52e28da70fc4b01c6b17336592c5dae6bb658f80 (patch) | |
tree | 59af046f0bbceceaa8308338a0f27c4c67c117b6 /net | |
parent | 3969a7882a0dda2816f7513d002f7caac73db348 (diff) | |
download | chromium_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.gyp | 8 | ||||
-rw-r--r-- | net/quic/crypto/aes_128_gcm_12_decrypter.h | 6 | ||||
-rw-r--r-- | net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc | 74 | ||||
-rw-r--r-- | net/quic/crypto/aes_128_gcm_12_encrypter.h | 6 | ||||
-rw-r--r-- | net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc | 59 | ||||
-rw-r--r-- | net/quic/crypto/scoped_evp_aead_ctx.cc | 23 | ||||
-rw-r--r-- | net/quic/crypto/scoped_evp_aead_ctx.h | 27 | ||||
-rw-r--r-- | net/quic/crypto/scoped_evp_cipher_ctx.cc | 22 | ||||
-rw-r--r-- | net/quic/crypto/scoped_evp_cipher_ctx.h | 30 |
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_ |