Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / gcm_driver / crypto / gcm_message_cryptographer_openssl.cc
blob46c13f7ee90e40efabd0f696fb128bee4c69cd78
1 // Copyright 2015 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.
5 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
7 #include <openssl/aead.h>
9 #include "base/logging.h"
10 #include "base/numerics/safe_math.h"
11 #include "base/strings/string_util.h"
13 namespace gcm {
15 namespace {
17 // The BoringSSL functions used to seal (encrypt) and open (decrypt) a payload
18 // follow the same prototype, declared as follows.
19 using EVP_AEAD_CTX_TransformFunction =
20 int(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
21 size_t max_out_len, const uint8_t *nonce, size_t nonce_len,
22 const uint8_t *in, size_t in_len, const uint8_t *ad, size_t ad_len);
24 } // namespace
26 bool GCMMessageCryptographer::EncryptDecryptRecordInternal(
27 Mode mode,
28 const base::StringPiece& input,
29 const base::StringPiece& key,
30 const base::StringPiece& nonce,
31 std::string* output) const {
32 DCHECK(output);
34 const EVP_AEAD* aead = EVP_aead_aes_128_gcm();
36 EVP_AEAD_CTX context;
37 if (!EVP_AEAD_CTX_init(&context, aead,
38 reinterpret_cast<const uint8_t*>(key.data()),
39 key.size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
40 return false;
43 base::CheckedNumeric<size_t> maximum_output_length(input.size());
44 if (mode == ENCRYPT)
45 maximum_output_length += kAuthenticationTagBytes;
47 // WriteInto requires the buffer to finish with a NULL-byte.
48 maximum_output_length += 1;
50 size_t output_length = 0;
51 uint8_t* raw_output = reinterpret_cast<uint8_t*>(
52 base::WriteInto(output, maximum_output_length.ValueOrDie()));
54 EVP_AEAD_CTX_TransformFunction* transform_function =
55 mode == ENCRYPT ? EVP_AEAD_CTX_seal : EVP_AEAD_CTX_open;
57 if (!transform_function(
58 &context, raw_output, &output_length, output->size(),
59 reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
60 reinterpret_cast<const uint8_t*>(input.data()), input.size(),
61 nullptr, 0)) {
62 EVP_AEAD_CTX_cleanup(&context);
63 return false;
66 EVP_AEAD_CTX_cleanup(&context);
68 base::CheckedNumeric<size_t> expected_output_length(input.size());
69 if (mode == ENCRYPT)
70 expected_output_length += kAuthenticationTagBytes;
71 else
72 expected_output_length -= kAuthenticationTagBytes;
74 DCHECK_EQ(expected_output_length.ValueOrDie(), output_length);
76 output->resize(output_length);
77 return true;
80 } // namespace gcm