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