aead_base_decrypter_openssl.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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 12using base::StringPiece; 13 14namespace net { 15 16namespace { 17 18// Clear OpenSSL error stack. 19void ClearOpenSslErrors() { 20 while (ERR_get_error()) {} 21} 22 23// In debug builds only, log OpenSSL error stack. Then clear OpenSSL error 24// stack. 25void 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 39AeadBaseDecrypter::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 51AeadBaseDecrypter::~AeadBaseDecrypter() {} 52 53bool 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 70bool 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 79bool 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 ssize_t len = EVP_AEAD_CTX_open( 90 ctx_.get(), output, 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 96 if (len < 0) { 97 // Because QuicFramer does trial decryption, decryption errors are expected 98 // when encryption level changes. So we don't log decryption errors. 99 ClearOpenSslErrors(); 100 return false; 101 } 102 103 *output_length = len; 104 return true; 105} 106 107QuicData* AeadBaseDecrypter::DecryptPacket( 108 QuicPacketSequenceNumber sequence_number, 109 StringPiece associated_data, 110 StringPiece ciphertext) { 111 if (ciphertext.length() < auth_tag_size_) { 112 return NULL; 113 } 114 size_t plaintext_size = ciphertext.length(); 115 scoped_ptr<char[]> plaintext(new char[plaintext_size]); 116 117 uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)]; 118 const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number); 119 DCHECK_LE(nonce_size, sizeof(nonce)); 120 memcpy(nonce, nonce_prefix_, nonce_prefix_size_); 121 memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number)); 122 if (!Decrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size), 123 associated_data, ciphertext, 124 reinterpret_cast<uint8*>(plaintext.get()), 125 &plaintext_size)) { 126 return NULL; 127 } 128 return new QuicData(plaintext.release(), plaintext_size, true); 129} 130 131StringPiece AeadBaseDecrypter::GetKey() const { 132 return StringPiece(reinterpret_cast<const char*>(key_), key_size_); 133} 134 135StringPiece AeadBaseDecrypter::GetNoncePrefix() const { 136 if (nonce_prefix_size_ == 0) { 137 return StringPiece(); 138 } 139 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), 140 nonce_prefix_size_); 141} 142 143} // namespace net 144