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/aes_128_gcm_12_decrypter.h" 6 7 #include <openssl/evp.h> 8 9 #include "base/memory/scoped_ptr.h" 10 11 using base::StringPiece; 12 13 namespace net { 14 15 namespace { 16 17 const size_t kKeySize = 16; 18 const size_t kNoncePrefixSize = 4; 19 const size_t kAESNonceSize = 12; 20 21 } // namespace 22 23 Aes128Gcm12Decrypter::Aes128Gcm12Decrypter() {} 24 25 Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {} 26 27 // static 28 bool Aes128Gcm12Decrypter::IsSupported() { return true; } 29 30 bool Aes128Gcm12Decrypter::SetKey(StringPiece key) { 31 DCHECK_EQ(key.size(), sizeof(key_)); 32 if (key.size() != sizeof(key_)) { 33 return false; 34 } 35 memcpy(key_, key.data(), key.size()); 36 37 // Set the cipher type and the key. 38 if (EVP_EncryptInit_ex(ctx_.get(), EVP_aes_128_gcm(), NULL, key_, 39 NULL) == 0) { 40 return false; 41 } 42 43 // Set the IV (nonce) length. 44 if (EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_GCM_SET_IVLEN, kAESNonceSize, 45 NULL) == 0) { 46 return false; 47 } 48 49 return true; 50 } 51 52 bool Aes128Gcm12Decrypter::SetNoncePrefix(StringPiece nonce_prefix) { 53 DCHECK_EQ(nonce_prefix.size(), kNoncePrefixSize); 54 if (nonce_prefix.size() != kNoncePrefixSize) { 55 return false; 56 } 57 COMPILE_ASSERT(sizeof(nonce_prefix_) == kNoncePrefixSize, bad_nonce_length); 58 memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); 59 return true; 60 } 61 62 bool Aes128Gcm12Decrypter::Decrypt(StringPiece nonce, 63 StringPiece associated_data, 64 StringPiece ciphertext, 65 uint8* output, 66 size_t* output_length) { 67 if (ciphertext.length() < kAuthTagSize || 68 nonce.size() != kNoncePrefixSize + sizeof(QuicPacketSequenceNumber)) { 69 return false; 70 } 71 const size_t plaintext_size = ciphertext.length() - kAuthTagSize; 72 73 // Set the IV (nonce). 74 if (EVP_DecryptInit_ex( 75 ctx_.get(), NULL, NULL, NULL, 76 reinterpret_cast<const uint8*>(nonce.data())) == 0) { 77 return false; 78 } 79 80 // Set the authentication tag. 81 if (EVP_CIPHER_CTX_ctrl( 82 ctx_.get(), EVP_CTRL_GCM_SET_TAG, kAuthTagSize, 83 const_cast<char*>(ciphertext.data()) + plaintext_size) == 0) { 84 return false; 85 } 86 87 // If we pass a NULL, zero-length associated data to OpenSSL then it breaks. 88 // Thus we only set non-empty associated data. 89 if (!associated_data.empty()) { 90 // Set the associated data. The second argument (output buffer) must be 91 // NULL. 92 int unused_len; 93 if (EVP_DecryptUpdate( 94 ctx_.get(), NULL, &unused_len, 95 reinterpret_cast<const uint8*>(associated_data.data()), 96 associated_data.size()) == 0) { 97 return false; 98 } 99 } 100 101 int len; 102 if (EVP_DecryptUpdate( 103 ctx_.get(), output, &len, 104 reinterpret_cast<const uint8*>(ciphertext.data()), 105 plaintext_size) == 0) { 106 return false; 107 } 108 output += len; 109 110 if (EVP_DecryptFinal_ex(ctx_.get(), output, &len) == 0) { 111 return false; 112 } 113 output += len; 114 115 *output_length = plaintext_size; 116 117 return true; 118 } 119 120 QuicData* Aes128Gcm12Decrypter::DecryptPacket( 121 QuicPacketSequenceNumber sequence_number, 122 StringPiece associated_data, 123 StringPiece ciphertext) { 124 if (ciphertext.length() < kAuthTagSize) { 125 return NULL; 126 } 127 size_t plaintext_size; 128 scoped_ptr<char[]> plaintext(new char[ciphertext.length()]); 129 130 uint8 nonce[kNoncePrefixSize + sizeof(sequence_number)]; 131 COMPILE_ASSERT(sizeof(nonce) == kAESNonceSize, bad_sequence_number_size); 132 memcpy(nonce, nonce_prefix_, kNoncePrefixSize); 133 memcpy(nonce + kNoncePrefixSize, &sequence_number, sizeof(sequence_number)); 134 if (!Decrypt(StringPiece(reinterpret_cast<char*>(nonce), sizeof(nonce)), 135 associated_data, ciphertext, 136 reinterpret_cast<uint8*>(plaintext.get()), 137 &plaintext_size)) { 138 return NULL; 139 } 140 return new QuicData(plaintext.release(), plaintext_size, true); 141 } 142 143 StringPiece Aes128Gcm12Decrypter::GetKey() const { 144 return StringPiece(reinterpret_cast<const char*>(key_), sizeof(key_)); 145 } 146 147 StringPiece Aes128Gcm12Decrypter::GetNoncePrefix() const { 148 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), 149 kNoncePrefixSize); 150 } 151 152 } // namespace net 153