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