summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/BUILD.gn4
-rw-r--r--crypto/aead_openssl.cc125
-rw-r--r--crypto/aead_openssl.h48
-rw-r--r--crypto/aead_openssl_unittest.cc54
-rw-r--r--crypto/crypto.gyp3
-rw-r--r--crypto/crypto.gypi2
6 files changed, 236 insertions, 0 deletions
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index 27e786c..c1eabe6 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -8,6 +8,8 @@ import("//testing/test.gni")
component("crypto") {
output_name = "crcrypto" # Avoid colliding with OpenSSL's libcrypto.
sources = [
+ "aead_openssl.cc",
+ "aead_openssl.h",
"apple_keychain.h",
"apple_keychain_ios.mm",
"apple_keychain_mac.mm",
@@ -151,6 +153,8 @@ component("crypto") {
} else {
# Remove OpenSSL when using NSS.
sources -= [
+ "aead_openssl.cc",
+ "aead_openssl.h",
"ec_private_key_openssl.cc",
"ec_signature_creator_openssl.cc",
"encryptor_openssl.cc",
diff --git a/crypto/aead_openssl.cc b/crypto/aead_openssl.cc
new file mode 100644
index 0000000..e32168a
--- /dev/null
+++ b/crypto/aead_openssl.cc
@@ -0,0 +1,125 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/aead_openssl.h"
+
+#if defined(USE_OPENSSL)
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+
+namespace crypto {
+
+Aead::Aead(AeadAlgorithm algorithm) : key_(nullptr) {
+ EnsureOpenSSLInit();
+ switch (algorithm) {
+ case AES_128_CTR_HMAC_SHA256:
+ aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
+ break;
+ }
+}
+
+Aead::~Aead() {
+}
+
+void Aead::Init(const std::string* key) {
+ DCHECK(!key_);
+ DCHECK_EQ(KeyLength(), key->size());
+ key_ = key;
+}
+
+bool Aead::Seal(const base::StringPiece& plaintext,
+ const base::StringPiece& nonce,
+ const base::StringPiece& additional_data,
+ std::string* ciphertext) const {
+ DCHECK(key_);
+ DCHECK_EQ(NonceLength(), nonce.size());
+ EVP_AEAD_CTX ctx;
+
+ if (!EVP_AEAD_CTX_init(&ctx, aead_,
+ reinterpret_cast<const uint8*>(key_->data()),
+ key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
+ return false;
+ }
+
+ std::string result;
+ const size_t max_output_length =
+ EVP_AEAD_max_overhead(aead_) + plaintext.size();
+ size_t output_length;
+ uint8* out_ptr =
+ reinterpret_cast<uint8*>(WriteInto(&result, max_output_length + 1));
+
+ if (!EVP_AEAD_CTX_seal(
+ &ctx, out_ptr, &output_length, max_output_length,
+ reinterpret_cast<const uint8*>(nonce.data()), nonce.size(),
+ reinterpret_cast<const uint8*>(plaintext.data()), plaintext.size(),
+ reinterpret_cast<const uint8*>(additional_data.data()),
+ additional_data.size())) {
+ EVP_AEAD_CTX_cleanup(&ctx);
+ return false;
+ }
+
+ DCHECK_LE(output_length, max_output_length);
+ result.resize(output_length);
+
+ ciphertext->swap(result);
+ EVP_AEAD_CTX_cleanup(&ctx);
+
+ return true;
+}
+
+bool Aead::Open(const base::StringPiece& ciphertext,
+ const base::StringPiece& nonce,
+ const base::StringPiece& additional_data,
+ std::string* plaintext) const {
+ DCHECK(key_);
+ EVP_AEAD_CTX ctx;
+
+ if (!EVP_AEAD_CTX_init(&ctx, aead_,
+ reinterpret_cast<const uint8*>(key_->data()),
+ key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
+ return false;
+ }
+
+ std::string result;
+ const size_t max_output_length = ciphertext.size();
+ size_t output_length;
+ uint8* out_ptr =
+ reinterpret_cast<uint8*>(WriteInto(&result, max_output_length + 1));
+
+ if (!EVP_AEAD_CTX_open(
+ &ctx, out_ptr, &output_length, max_output_length,
+ reinterpret_cast<const uint8*>(nonce.data()), nonce.size(),
+ reinterpret_cast<const uint8*>(ciphertext.data()), ciphertext.size(),
+ reinterpret_cast<const uint8*>(additional_data.data()),
+ additional_data.size())) {
+ EVP_AEAD_CTX_cleanup(&ctx);
+ return false;
+ }
+
+ DCHECK_LE(output_length, max_output_length);
+ result.resize(output_length);
+
+ plaintext->swap(result);
+ EVP_AEAD_CTX_cleanup(&ctx);
+
+ return true;
+}
+
+size_t Aead::KeyLength() const {
+ return EVP_AEAD_key_length(aead_);
+}
+
+size_t Aead::NonceLength() const {
+ return EVP_AEAD_nonce_length(aead_);
+}
+
+} // namespace
+
+#endif
diff --git a/crypto/aead_openssl.h b/crypto/aead_openssl.h
new file mode 100644
index 0000000..773cce1
--- /dev/null
+++ b/crypto/aead_openssl.h
@@ -0,0 +1,48 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_AEAD_H_
+#define CRYPTO_AEAD_H_
+
+#include "base/strings/string_piece.h"
+#include "crypto/crypto_export.h"
+
+struct evp_aead_st;
+
+namespace crypto {
+
+// This class exposes the AES-128-CTR-HMAC-SHA256 AEAD, currently only
+// for OpenSSL builds.
+class CRYPTO_EXPORT Aead {
+ public:
+ enum AeadAlgorithm { AES_128_CTR_HMAC_SHA256 };
+
+ explicit Aead(AeadAlgorithm algorithm);
+
+ ~Aead();
+
+ void Init(const std::string* key);
+
+ bool Seal(const base::StringPiece& plaintext,
+ const base::StringPiece& nonce,
+ const base::StringPiece& additional_data,
+ std::string* ciphertext) const;
+
+ bool Open(const base::StringPiece& ciphertext,
+ const base::StringPiece& nonce,
+ const base::StringPiece& additional_data,
+ std::string* plaintext) const;
+
+ size_t KeyLength() const;
+
+ size_t NonceLength() const;
+
+ private:
+ const std::string* key_;
+ const evp_aead_st* aead_;
+};
+
+} // namespace crypto
+
+#endif // CRYPTO_ENCRYPTOR_H_
diff --git a/crypto/aead_openssl_unittest.cc b/crypto/aead_openssl_unittest.cc
new file mode 100644
index 0000000..446bca2
--- /dev/null
+++ b/crypto/aead_openssl_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/aead_openssl.h"
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+#if defined(USE_OPENSSL)
+
+TEST(AeadTest, SealOpen) {
+ crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
+ std::string key(aead.KeyLength(), 0);
+ aead.Init(&key);
+ std::string nonce(aead.NonceLength(), 0);
+ std::string plaintext("this is the plaintext");
+ std::string ad("this is the additional data");
+ std::string ciphertext;
+ EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext));
+ EXPECT_LT(0U, ciphertext.size());
+
+ std::string decrypted;
+ EXPECT_TRUE(aead.Open(ciphertext, nonce, ad, &decrypted));
+
+ EXPECT_EQ(plaintext, decrypted);
+}
+
+TEST(AeadTest, SealOpenWrongKey) {
+ crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256);
+ std::string key(aead.KeyLength(), 0);
+ std::string wrong_key(aead.KeyLength(), 1);
+ aead.Init(&key);
+ crypto::Aead aead_wrong_key(crypto::Aead::AES_128_CTR_HMAC_SHA256);
+ aead_wrong_key.Init(&wrong_key);
+
+ std::string nonce(aead.NonceLength(), 0);
+ std::string plaintext("this is the plaintext");
+ std::string ad("this is the additional data");
+ std::string ciphertext;
+ EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext));
+ EXPECT_LT(0U, ciphertext.size());
+
+ std::string decrypted;
+ EXPECT_FALSE(aead_wrong_key.Open(ciphertext, nonce, ad, &decrypted));
+ EXPECT_EQ(0U, decrypted.size());
+}
+
+#endif
+
+} // namespace
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index a9cff55..00b59b5 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -125,6 +125,8 @@
],
}, {
'sources!': [
+ 'aead_openssl.cc',
+ 'aead_openssl.h',
'ec_private_key_openssl.cc',
'ec_signature_creator_openssl.cc',
'encryptor_openssl.cc',
@@ -158,6 +160,7 @@
'target_name': 'crypto_unittests',
'type': 'executable',
'sources': [
+ 'aead_openssl_unittest.cc',
'curve25519_unittest.cc',
'ec_private_key_unittest.cc',
'ec_signature_creator_unittest.cc',
diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi
index 6fdbdf4..4456b10 100644
--- a/crypto/crypto.gypi
+++ b/crypto/crypto.gypi
@@ -27,6 +27,8 @@
# NOTE: all transitive dependencies of HMAC on windows need
# to be placed in the source list above.
'<@(hmac_win64_related_sources)',
+ 'aead_openssl.cc',
+ 'aead_openssl.h',
'apple_keychain.h',
'apple_keychain_ios.mm',
'apple_keychain_mac.mm',