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 3 // found in the LICENSE file. 4 5 #include "net/quic/crypto/aead_base_decrypter.h" 6 7 #include <openssl/err.h> 8 #include <openssl/evp.h> 9 10 #include "base/memory/scoped_ptr.h" 11 12 using base::StringPiece; 13 14 namespace net { 15 16 namespace { 17 18 // Clear OpenSSL error stack. 19 void ClearOpenSslErrors() { 20 while (ERR_get_error()) {} 21 } 22 23 // In debug builds only, log OpenSSL error stack. Then clear OpenSSL error 24 // stack. 25 void DLogOpenSslErrors() { 26 #ifdef NDEBUG 27 ClearOpenSslErrors(); 28 #else 29 while (unsigned long error = ERR_get_error()) { 30 char buf[120]; 31 ERR_error_string_n(error, buf, arraysize(buf)); 32 DLOG(ERROR) << "OpenSSL error: " << buf; 33 } 34 #endif 35 } 36 37 } // namespace 38 39 AeadBaseDecrypter::AeadBaseDecrypter(const EVP_AEAD* aead_alg, 40 size_t key_size, 41 size_t auth_tag_size, 42 size_t nonce_prefix_size) 43 : aead_alg_(aead_alg), 44 key_size_(key_size), 45 auth_tag_size_(auth_tag_size), 46 nonce_prefix_size_(nonce_prefix_size) { 47 DCHECK_LE(key_size_, sizeof(key_)); 48 DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_)); 49 } 50 51 AeadBaseDecrypter::~AeadBaseDecrypter() {} 52 53 bool AeadBaseDecrypter::SetKey(StringPiece key) { 54 DCHECK_EQ(key.size(), key_size_); 55 if (key.size() != key_size_) { 56 return false; 57 } 58 memcpy(key_, key.data(), key.size()); 59 60 EVP_AEAD_CTX_cleanup(ctx_.get()); 61 if (!EVP_AEAD_CTX_init(ctx_.get(), aead_alg_, key_, key_size_, 62 auth_tag_size_, NULL)) { 63 DLogOpenSslErrors(); 64 return false; 65 } 66 67 return true; 68 } 69 70 bool AeadBaseDecrypter::SetNoncePrefix(StringPiece nonce_prefix) { 71 DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_); 72 if (nonce_prefix.size() != nonce_prefix_size_) { 73 return false; 74 } 75 memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); 76 return true; 77 } 78 79 bool AeadBaseDecrypter::Decrypt(StringPiece nonce, 80 StringPiece associated_data, 81 StringPiece ciphertext, 82 uint8* output, 83 size_t* output_length) { 84 if (ciphertext.length() < auth_tag_size_ || 85 nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketSequenceNumber)) { 86 return false; 87 } 88 89 if (!EVP_AEAD_CTX_open( 90 ctx_.get(), output, output_length, ciphertext.size(), 91 reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(), 92 reinterpret_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(), 93 reinterpret_cast<const uint8_t*>(associated_data.data()), 94 associated_data.size())) { 95 // Because QuicFramer does trial decryption, decryption errors are expected 96 // when encryption level changes. So we don't log decryption errors. 97 ClearOpenSslErrors(); 98 return false; 99 } 100 101 return true; 102 } 103 104 QuicData* AeadBaseDecrypter::DecryptPacket( 105 QuicPacketSequenceNumber sequence_number, 106 StringPiece associated_data, 107 StringPiece ciphertext) { 108 if (ciphertext.length() < auth_tag_size_) { 109 return NULL; 110 } 111 size_t plaintext_size = ciphertext.length(); 112 scoped_ptr<char[]> plaintext(new char[plaintext_size]); 113 114 uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)]; 115 const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number); 116 DCHECK_LE(nonce_size, sizeof(nonce)); 117 memcpy(nonce, nonce_prefix_, nonce_prefix_size_); 118 memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number)); 119 if (!Decrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size), 120 associated_data, ciphertext, 121 reinterpret_cast<uint8*>(plaintext.get()), 122 &plaintext_size)) { 123 return NULL; 124 } 125 return new QuicData(plaintext.release(), plaintext_size, true); 126 } 127 128 StringPiece AeadBaseDecrypter::GetKey() const { 129 return StringPiece(reinterpret_cast<const char*>(key_), key_size_); 130 } 131 132 StringPiece AeadBaseDecrypter::GetNoncePrefix() const { 133 if (nonce_prefix_size_ == 0) { 134 return StringPiece(); 135 } 136 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), 137 nonce_prefix_size_); 138 } 139 140 } // namespace net 141