diff options
Diffstat (limited to 'chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc')
-rw-r--r-- | chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc | 188 |
1 files changed, 19 insertions, 169 deletions
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc index 2cd072af461..09901a47672 100644 --- a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc +++ b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc @@ -4,12 +4,10 @@ #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" -#include <nss.h> #include <pk11pub.h> #include <secerr.h> #include "base/lazy_instance.h" -#include "base/memory/scoped_ptr.h" #include "crypto/ghash.h" #include "crypto/scoped_nss_types.h" @@ -23,31 +21,8 @@ namespace net { namespace { -// The pkcs11t.h header in NSS versions older than 3.14 does not have the CTR -// and GCM types, so define them here. -#if !defined(CKM_AES_CTR) -#define CKM_AES_CTR 0x00001086 -#define CKM_AES_GCM 0x00001087 - -struct CK_AES_CTR_PARAMS { - CK_ULONG ulCounterBits; - CK_BYTE cb[16]; -}; - -struct CK_GCM_PARAMS { - CK_BYTE_PTR pIv; - CK_ULONG ulIvLen; - CK_BYTE_PTR pAAD; - CK_ULONG ulAADLen; - CK_ULONG ulTagBits; -}; -#endif // CKM_AES_CTR - -typedef SECStatus -(*PK11_EncryptFunction)( - PK11SymKey* symKey, CK_MECHANISM_TYPE mechanism, SECItem* param, - unsigned char* out, unsigned int* outLen, unsigned int maxLen, - const unsigned char* data, unsigned int dataLen); +const size_t kKeySize = 16; +const size_t kNoncePrefixSize = 4; // On Linux, dynamically link against the system version of libnss3.so. In // order to continue working on systems without up-to-date versions of NSS, @@ -61,10 +36,6 @@ class GcmSupportChecker { return pk11_encrypt_func_; } - static CK_MECHANISM_TYPE aes_key_mechanism() { - return aes_key_mechanism_; - } - private: friend struct base::DefaultLazyInstanceTraits<GcmSupportChecker>; @@ -80,34 +51,19 @@ class GcmSupportChecker { // AES-GCM directly. This was introduced in NSS 3.15. pk11_encrypt_func_ = (PK11_EncryptFunction)dlsym(RTLD_DEFAULT, "PK11_Encrypt"); - if (pk11_encrypt_func_ == NULL) { - aes_key_mechanism_ = CKM_AES_ECB; - } #endif } // |pk11_encrypt_func_| stores the runtime symbol resolution of PK11_Encrypt. static PK11_EncryptFunction pk11_encrypt_func_; - - // The correct value for |aes_key_mechanism_| is CKM_AES_GCM, but because of - // NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=853285 (to be fixed in - // NSS 3.15), use CKM_AES_ECB for NSS versions older than 3.15. - static CK_MECHANISM_TYPE aes_key_mechanism_; }; // static PK11_EncryptFunction GcmSupportChecker::pk11_encrypt_func_ = NULL; -// static -CK_MECHANISM_TYPE GcmSupportChecker::aes_key_mechanism_ = CKM_AES_GCM; - base::LazyInstance<GcmSupportChecker>::Leaky g_gcm_support_checker = LAZY_INSTANCE_INITIALIZER; -const size_t kKeySize = 16; -const size_t kNoncePrefixSize = 4; -const size_t kAESNonceSize = 12; - // Calls PK11_Encrypt if it's available. Otherwise, emulates CKM_AES_GCM using // CKM_AES_CTR and the GaloisHash class. SECStatus My_Encrypt(PK11SymKey* key, @@ -250,136 +206,30 @@ SECStatus My_Encrypt(PK11SymKey* key, } // namespace -Aes128Gcm12Encrypter::Aes128Gcm12Encrypter() { +Aes128Gcm12Encrypter::Aes128Gcm12Encrypter() + : AeadBaseEncrypter(CKM_AES_GCM, My_Encrypt, kKeySize, kAuthTagSize, + kNoncePrefixSize) { + COMPILE_ASSERT(kKeySize <= kMaxKeySize, key_size_too_big); + COMPILE_ASSERT(kNoncePrefixSize <= kMaxNoncePrefixSize, + nonce_prefix_size_too_big); ignore_result(g_gcm_support_checker.Get()); } Aes128Gcm12Encrypter::~Aes128Gcm12Encrypter() {} -bool Aes128Gcm12Encrypter::SetKey(StringPiece key) { - DCHECK_EQ(key.size(), sizeof(key_)); - if (key.size() != sizeof(key_)) { - return false; - } - memcpy(key_, key.data(), key.size()); - return true; -} - -bool Aes128Gcm12Encrypter::SetNoncePrefix(StringPiece nonce_prefix) { - DCHECK_EQ(nonce_prefix.size(), kNoncePrefixSize); - if (nonce_prefix.size() != kNoncePrefixSize) { - return false; - } - COMPILE_ASSERT(sizeof(nonce_prefix_) == kNoncePrefixSize, bad_nonce_length); - memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); - return true; -} - -bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce, - StringPiece associated_data, - StringPiece plaintext, - unsigned char* output) { - if (nonce.size() != kNoncePrefixSize + sizeof(QuicPacketSequenceNumber)) { - return false; - } - - size_t ciphertext_size = GetCiphertextSize(plaintext.length()); - - // Import key_ into NSS. - SECItem key_item; - key_item.type = siBuffer; - key_item.data = key_; - key_item.len = sizeof(key_); - PK11SlotInfo* slot = PK11_GetInternalSlot(); - // The exact value of the |origin| argument doesn't matter to NSS as long as - // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a - // placeholder. - crypto::ScopedPK11SymKey aes_key(PK11_ImportSymKey( - slot, GcmSupportChecker::aes_key_mechanism(), PK11_OriginUnwrap, - CKA_ENCRYPT, &key_item, NULL)); - PK11_FreeSlot(slot); - slot = NULL; - if (!aes_key) { - DVLOG(1) << "PK11_ImportSymKey failed"; - return false; - } - - CK_GCM_PARAMS gcm_params = {0}; - gcm_params.pIv = +void Aes128Gcm12Encrypter::FillAeadParams(StringPiece nonce, + StringPiece associated_data, + size_t auth_tag_size, + AeadParams* aead_params) const { + aead_params->len = sizeof(aead_params->data.gcm_params); + CK_GCM_PARAMS* gcm_params = &aead_params->data.gcm_params; + gcm_params->pIv = reinterpret_cast<CK_BYTE*>(const_cast<char*>(nonce.data())); - gcm_params.ulIvLen = nonce.size(); - gcm_params.pAAD = + gcm_params->ulIvLen = nonce.size(); + gcm_params->pAAD = reinterpret_cast<CK_BYTE*>(const_cast<char*>(associated_data.data())); - gcm_params.ulAADLen = associated_data.size(); - gcm_params.ulTagBits = kAuthTagSize * 8; - - SECItem param; - param.type = siBuffer; - param.data = reinterpret_cast<unsigned char*>(&gcm_params); - param.len = sizeof(gcm_params); - - unsigned int output_len; - if (My_Encrypt(aes_key.get(), CKM_AES_GCM, ¶m, - output, &output_len, ciphertext_size, - reinterpret_cast<const unsigned char*>(plaintext.data()), - plaintext.size()) != SECSuccess) { - DVLOG(1) << "My_Encrypt failed"; - return false; - } - - if (output_len != ciphertext_size) { - DVLOG(1) << "Wrong output length"; - return false; - } - - return true; -} - -QuicData* Aes128Gcm12Encrypter::EncryptPacket( - QuicPacketSequenceNumber sequence_number, - StringPiece associated_data, - StringPiece plaintext) { - size_t ciphertext_size = GetCiphertextSize(plaintext.length()); - scoped_ptr<char[]> ciphertext(new char[ciphertext_size]); - - // TODO(ianswett): Introduce a check to ensure that we don't encrypt with the - // same sequence number twice. - uint8 nonce[kNoncePrefixSize + sizeof(sequence_number)]; - COMPILE_ASSERT(sizeof(nonce) == kAESNonceSize, bad_sequence_number_size); - memcpy(nonce, nonce_prefix_, kNoncePrefixSize); - memcpy(nonce + kNoncePrefixSize, &sequence_number, sizeof(sequence_number)); - if (!Encrypt(StringPiece(reinterpret_cast<char*>(nonce), sizeof(nonce)), - associated_data, plaintext, - reinterpret_cast<unsigned char*>(ciphertext.get()))) { - return NULL; - } - - return new QuicData(ciphertext.release(), ciphertext_size, true); -} - -size_t Aes128Gcm12Encrypter::GetKeySize() const { return kKeySize; } - -size_t Aes128Gcm12Encrypter::GetNoncePrefixSize() const { - return kNoncePrefixSize; -} - -size_t Aes128Gcm12Encrypter::GetMaxPlaintextSize(size_t ciphertext_size) const { - return ciphertext_size - kAuthTagSize; -} - -// An AEAD_AES_128_GCM_12 ciphertext is exactly 12 bytes longer than its -// corresponding plaintext. -size_t Aes128Gcm12Encrypter::GetCiphertextSize(size_t plaintext_size) const { - return plaintext_size + kAuthTagSize; -} - -StringPiece Aes128Gcm12Encrypter::GetKey() const { - return StringPiece(reinterpret_cast<const char*>(key_), sizeof(key_)); -} - -StringPiece Aes128Gcm12Encrypter::GetNoncePrefix() const { - return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), - kNoncePrefixSize); + gcm_params->ulAADLen = associated_data.size(); + gcm_params->ulTagBits = auth_tag_size * 8; } } // namespace net |