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