diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn deleted file mode 100644 index 190963170ac12..0000000000000 --- a/crypto/BUILD.gn +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 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. - -component("crypto") { - output_name = "crcrypto" # Avoid colliding with OpenSSL's libcrypto. - sources = [ - "random.cc", - "random.h", - ] - deps = [ - "//base", - ] -} diff --git a/crypto/OWNERS b/crypto/OWNERS deleted file mode 100644 index 3ba4dd39e256c..0000000000000 --- a/crypto/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -agl@chromium.org -davidben@chromium.org -rsleevi@chromium.org -rvargas@chromium.org diff --git a/crypto/aead_openssl.cc b/crypto/aead_openssl.cc deleted file mode 100644 index 54795b8a40607..0000000000000 --- a/crypto/aead_openssl.cc +++ /dev/null @@ -1,125 +0,0 @@ -// 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 -#include -#include - -#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(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(base::WriteInto(&result, max_output_length + 1)); - - if (!EVP_AEAD_CTX_seal( - &ctx, out_ptr, &output_length, max_output_length, - reinterpret_cast(nonce.data()), nonce.size(), - reinterpret_cast(plaintext.data()), plaintext.size(), - reinterpret_cast(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(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(base::WriteInto(&result, max_output_length + 1)); - - if (!EVP_AEAD_CTX_open( - &ctx, out_ptr, &output_length, max_output_length, - reinterpret_cast(nonce.data()), nonce.size(), - reinterpret_cast(ciphertext.data()), ciphertext.size(), - reinterpret_cast(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 deleted file mode 100644 index 773cce1428686..0000000000000 --- a/crypto/aead_openssl.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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 deleted file mode 100644 index 446bca2cb02f3..0000000000000 --- a/crypto/aead_openssl_unittest.cc +++ /dev/null @@ -1,54 +0,0 @@ -// 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 - -#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/aes_128_gcm_helpers_nss.cc b/crypto/aes_128_gcm_helpers_nss.cc deleted file mode 100644 index 621f28b586f18..0000000000000 --- a/crypto/aes_128_gcm_helpers_nss.cc +++ /dev/null @@ -1,374 +0,0 @@ -// 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/aes_128_gcm_helpers_nss.h" - -#include -#include - -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "crypto/ghash.h" -#include "crypto/scoped_nss_types.h" - -#if defined(USE_NSS_CERTS) -#include -#endif - -namespace crypto { -namespace { - -// Declaration of the prototype both PK11_Decrypt and PK11_Encrypt follow. -using PK11_TransformFunction = SECStatus(PK11SymKey* symKey, - CK_MECHANISM_TYPE mechanism, - SECItem* param, - unsigned char* out, - unsigned int* outLen, - unsigned int maxLen, - const unsigned char* data, - unsigned int dataLen); - -// On Linux, dynamically link against the system version of libnss3.so. In -// order to continue working on systems without up-to-date versions of NSS, -// lookup PK11_Decrypt and PK11_Encrypt with dlsym. -// -// GcmSupportChecker is a singleton which caches the results of runtime symbol -// resolution of these symbols. -class GcmSupportChecker { - public: - PK11_TransformFunction* pk11_decrypt_func() { return pk11_decrypt_func_; } - - PK11_TransformFunction* pk11_encrypt_func() { return pk11_encrypt_func_; } - - private: - friend struct base::DefaultLazyInstanceTraits; - - GcmSupportChecker() { -#if !defined(USE_NSS_CERTS) - // Using a bundled version of NSS that is guaranteed to have these symbols. - pk11_decrypt_func_ = PK11_Decrypt; - pk11_encrypt_func_ = PK11_Encrypt; -#else - // Using system NSS libraries and PCKS #11 modules, which may not have the - // necessary functions (PK11_Decrypt and PK11_Encrypt) or mechanism support - // (CKM_AES_GCM). - - // If PK11_Decrypt() and PK11_Encrypt() were successfully resolved, then NSS - // will support AES-GCM directly. This was introduced in NSS 3.15. - pk11_decrypt_func_ = reinterpret_cast( - dlsym(RTLD_DEFAULT, "PK11_Decrypt")); - pk11_encrypt_func_ = reinterpret_cast( - dlsym(RTLD_DEFAULT, "PK11_Encrypt")); -#endif - } - - ~GcmSupportChecker() {} - - // |pk11_decrypt_func_| stores the runtime symbol resolution of PK11_Decrypt. - PK11_TransformFunction* pk11_decrypt_func_; - - // |pk11_encrypt_func_| stores the runtime symbol resolution of PK11_Encrypt. - PK11_TransformFunction* pk11_encrypt_func_; - - DISALLOW_COPY_AND_ASSIGN(GcmSupportChecker); -}; - -base::LazyInstance::Leaky g_gcm_support_checker = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// Calls PK11_Decrypt if it's available. Otherwise, emulates CKM_AES_GCM using -// CKM_AES_CTR and the GaloisHash class. -SECStatus PK11DecryptHelper(PK11SymKey* key, - CK_MECHANISM_TYPE mechanism, - SECItem* param, - unsigned char* out, - unsigned int* out_len, - unsigned int max_len, - const unsigned char* data, - unsigned int data_len) { - // If PK11_Decrypt() was successfully resolved or if bundled version of NSS is - // being used, then NSS will support AES-GCM directly. - PK11_TransformFunction* pk11_decrypt_func = - g_gcm_support_checker.Get().pk11_decrypt_func(); - - if (pk11_decrypt_func != nullptr) { - return pk11_decrypt_func(key, mechanism, param, out, out_len, max_len, data, - data_len); - } - - // Otherwise, the user has an older version of NSS. Regrettably, NSS 3.14.x - // has a bug in the AES GCM code - // (https://bugzilla.mozilla.org/show_bug.cgi?id=853285), as well as missing - // the PK11_Decrypt function - // (https://bugzilla.mozilla.org/show_bug.cgi?id=854063), both of which are - // resolved in NSS 3.15. - - CHECK_EQ(mechanism, static_cast(CKM_AES_GCM)); - CHECK_EQ(param->len, sizeof(CK_GCM_PARAMS)); - - const CK_GCM_PARAMS* gcm_params = - reinterpret_cast(param->data); - - const CK_ULONG auth_tag_size = gcm_params->ulTagBits / 8; - - if (gcm_params->ulIvLen != 12u) { - DVLOG(1) << "ulIvLen is not equal to 12"; - PORT_SetError(SEC_ERROR_INPUT_LEN); - return SECFailure; - } - - SECItem my_param = {siBuffer, nullptr, 0}; - - // Step 2. Let H = CIPH_K(128 '0' bits). - unsigned char ghash_key[16] = {0}; - crypto::ScopedPK11Context ctx( - PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, key, &my_param)); - if (!ctx) { - DVLOG(1) << "PK11_CreateContextBySymKey failed"; - return SECFailure; - } - int output_len; - if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key), - ghash_key, sizeof(ghash_key)) != SECSuccess) { - DVLOG(1) << "PK11_CipherOp failed"; - return SECFailure; - } - - if (PK11_Finalize(ctx.get()) != SECSuccess) { - DVLOG(1) << "PK11_Finalize failed"; - return SECFailure; - } - - if (output_len != sizeof(ghash_key)) { - DVLOG(1) << "Wrong output length"; - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - // Step 3. If len(IV)=96, then let J0 = IV || 31 '0' bits || 1. - CK_AES_CTR_PARAMS ctr_params = {0}; - ctr_params.ulCounterBits = 32; - memcpy(ctr_params.cb, gcm_params->pIv, gcm_params->ulIvLen); - ctr_params.cb[12] = 0; - ctr_params.cb[13] = 0; - ctr_params.cb[14] = 0; - ctr_params.cb[15] = 1; - - my_param.type = siBuffer; - my_param.data = reinterpret_cast(&ctr_params); - my_param.len = sizeof(ctr_params); - - ctx.reset( - PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key, &my_param)); - if (!ctx) { - DVLOG(1) << "PK11_CreateContextBySymKey failed"; - return SECFailure; - } - - // Step 6. Calculate the encryption mask of GCTR_K(J0, ...). - unsigned char tag_mask[16] = {0}; - if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask), - tag_mask, sizeof(tag_mask)) != SECSuccess) { - DVLOG(1) << "PK11_CipherOp failed"; - return SECFailure; - } - if (output_len != sizeof(tag_mask)) { - DVLOG(1) << "Wrong output length"; - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - if (data_len < auth_tag_size) { - PORT_SetError(SEC_ERROR_INPUT_LEN); - return SECFailure; - } - - // The const_cast for |data| can be removed if system NSS libraries are - // NSS 3.14.1 or later (NSS bug - // https://bugzilla.mozilla.org/show_bug.cgi?id=808218). - if (PK11_CipherOp(ctx.get(), out, &output_len, max_len, - const_cast(data), - data_len - auth_tag_size) != SECSuccess) { - DVLOG(1) << "PK11_CipherOp failed"; - return SECFailure; - } - - if (PK11_Finalize(ctx.get()) != SECSuccess) { - DVLOG(1) << "PK11_Finalize failed"; - return SECFailure; - } - - if (static_cast(output_len) != data_len - auth_tag_size) { - DVLOG(1) << "Wrong output length"; - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - crypto::GaloisHash ghash(ghash_key); - ghash.UpdateAdditional(gcm_params->pAAD, gcm_params->ulAADLen); - ghash.UpdateCiphertext(data, output_len); - unsigned char auth_tag[auth_tag_size]; - ghash.Finish(auth_tag, auth_tag_size); - for (unsigned int i = 0; i < auth_tag_size; i++) { - auth_tag[i] ^= tag_mask[i]; - } - - if (NSS_SecureMemcmp(auth_tag, data + output_len, auth_tag_size) != 0) { - PORT_SetError(SEC_ERROR_BAD_DATA); - return SECFailure; - } - - *out_len = output_len; - return SECSuccess; -} - -// Calls PK11_Encrypt if it's available. Otherwise, emulates CKM_AES_GCM using -// CKM_AES_CTR and the GaloisHash class. -SECStatus PK11EncryptHelper(PK11SymKey* key, - CK_MECHANISM_TYPE mechanism, - SECItem* param, - unsigned char* out, - unsigned int* out_len, - unsigned int max_len, - const unsigned char* data, - unsigned int data_len) { - // If PK11_Encrypt() was successfully resolved or if bundled version of NSS is - // being used, then NSS will support AES-GCM directly. - PK11_TransformFunction* pk11_encrypt_func = - g_gcm_support_checker.Get().pk11_encrypt_func(); - - if (pk11_encrypt_func != nullptr) { - return pk11_encrypt_func(key, mechanism, param, out, out_len, max_len, data, - data_len); - } - - // Otherwise, the user has an older version of NSS. Regrettably, NSS 3.14.x - // has a bug in the AES GCM code - // (https://bugzilla.mozilla.org/show_bug.cgi?id=853285), as well as missing - // the PK11_Encrypt function - // (https://bugzilla.mozilla.org/show_bug.cgi?id=854063), both of which are - // resolved in NSS 3.15. - - CHECK_EQ(mechanism, static_cast(CKM_AES_GCM)); - CHECK_EQ(param->len, sizeof(CK_GCM_PARAMS)); - - const CK_GCM_PARAMS* gcm_params = - reinterpret_cast(param->data); - - const CK_ULONG auth_tag_size = gcm_params->ulTagBits / 8; - - if (max_len < auth_tag_size) { - DVLOG(1) << "max_len is less than kAuthTagSize"; - PORT_SetError(SEC_ERROR_OUTPUT_LEN); - return SECFailure; - } - - if (gcm_params->ulIvLen != 12u) { - DVLOG(1) << "ulIvLen is not equal to 12"; - PORT_SetError(SEC_ERROR_INPUT_LEN); - return SECFailure; - } - - SECItem my_param = {siBuffer, nullptr, 0}; - - // Step 1. Let H = CIPH_K(128 '0' bits). - unsigned char ghash_key[16] = {0}; - crypto::ScopedPK11Context ctx( - PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, key, &my_param)); - if (!ctx) { - DVLOG(1) << "PK11_CreateContextBySymKey failed"; - return SECFailure; - } - int output_len; - if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key), - ghash_key, sizeof(ghash_key)) != SECSuccess) { - DVLOG(1) << "PK11_CipherOp failed"; - return SECFailure; - } - - if (PK11_Finalize(ctx.get()) != SECSuccess) { - DVLOG(1) << "PK11_Finalize failed"; - return SECFailure; - } - - if (output_len != sizeof(ghash_key)) { - DVLOG(1) << "Wrong output length"; - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - // Step 2. If len(IV)=96, then let J0 = IV || 31 '0' bits || 1. - CK_AES_CTR_PARAMS ctr_params = {0}; - ctr_params.ulCounterBits = 32; - memcpy(ctr_params.cb, gcm_params->pIv, gcm_params->ulIvLen); - ctr_params.cb[12] = 0; - ctr_params.cb[13] = 0; - ctr_params.cb[14] = 0; - ctr_params.cb[15] = 1; - - my_param.type = siBuffer; - my_param.data = reinterpret_cast(&ctr_params); - my_param.len = sizeof(ctr_params); - - ctx.reset( - PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key, &my_param)); - if (!ctx) { - DVLOG(1) << "PK11_CreateContextBySymKey failed"; - return SECFailure; - } - - // Step 6. Calculate the encryption mask of GCTR_K(J0, ...). - unsigned char tag_mask[16] = {0}; - if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask), - tag_mask, sizeof(tag_mask)) != SECSuccess) { - DVLOG(1) << "PK11_CipherOp failed"; - return SECFailure; - } - if (output_len != sizeof(tag_mask)) { - DVLOG(1) << "Wrong output length"; - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - // The const_cast for |data| can be removed if system NSS libraries are - // NSS 3.14.1 or later (NSS bug - // https://bugzilla.mozilla.org/show_bug.cgi?id=808218). - if (PK11_CipherOp(ctx.get(), out, &output_len, max_len, - const_cast(data), data_len) != SECSuccess) { - DVLOG(1) << "PK11_CipherOp failed"; - return SECFailure; - } - - if (PK11_Finalize(ctx.get()) != SECSuccess) { - DVLOG(1) << "PK11_Finalize failed"; - return SECFailure; - } - - if (static_cast(output_len) != data_len) { - DVLOG(1) << "Wrong output length"; - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - if ((max_len - auth_tag_size) < static_cast(output_len)) { - DVLOG(1) << "(max_len - kAuthTagSize) is less than output_len"; - PORT_SetError(SEC_ERROR_OUTPUT_LEN); - return SECFailure; - } - - crypto::GaloisHash ghash(ghash_key); - ghash.UpdateAdditional(gcm_params->pAAD, gcm_params->ulAADLen); - ghash.UpdateCiphertext(out, output_len); - ghash.Finish(out + output_len, auth_tag_size); - for (unsigned int i = 0; i < auth_tag_size; i++) { - out[output_len + i] ^= tag_mask[i]; - } - - *out_len = output_len + auth_tag_size; - return SECSuccess; -} - -} // namespace crypto diff --git a/crypto/aes_128_gcm_helpers_nss.h b/crypto/aes_128_gcm_helpers_nss.h deleted file mode 100644 index dadc56e0f0d20..0000000000000 --- a/crypto/aes_128_gcm_helpers_nss.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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_AES_128_GCM_HELPERS_NSS_H_ -#define CRYPTO_AES_128_GCM_HELPERS_NSS_H_ - -#include -#include - -#include "crypto/crypto_export.h" - -namespace crypto { - -// When using the CKM_AES_GCM mechanism, one must consider that the mechanism -// had a bug in NSS 3.14.x (https://bugzilla.mozilla.org/show_bug.cgi?id=853285) -// which also lacks the PK11_Decrypt and PK11_Encrypt functions. -// (https://bugzilla.mozilla.org/show_bug.cgi?id=854063) -// -// While both these bugs were resolved in NSS 3.15, certain builds of Chromium -// may still be loading older versions of NSS as the system libraries. These -// helper methods emulate support by using CKM_AES_CTR and the GaloisHash. - -// Helper function for using PK11_Decrypt. |mechanism| must be set to -// CKM_AES_GCM for this method. -CRYPTO_EXPORT SECStatus PK11DecryptHelper(PK11SymKey* key, - CK_MECHANISM_TYPE mechanism, - SECItem* param, - unsigned char* out, - unsigned int* out_len, - unsigned int max_len, - const unsigned char* data, - unsigned int data_len); - -// Helper function for using PK11_Encrypt. |mechanism| must be set to -// CKM_AES_GCM for this method. -CRYPTO_EXPORT SECStatus PK11EncryptHelper(PK11SymKey* key, - CK_MECHANISM_TYPE mechanism, - SECItem* param, - unsigned char* out, - unsigned int* out_len, - unsigned int max_len, - const unsigned char* data, - unsigned int data_len); - -} // namespace crypto - -#endif // CRYPTO_AES_128_GCM_HELPERS_NSS_H_ diff --git a/crypto/aes_128_gcm_helpers_nss_unittest.cc b/crypto/aes_128_gcm_helpers_nss_unittest.cc deleted file mode 100644 index d741b2fe54d07..0000000000000 --- a/crypto/aes_128_gcm_helpers_nss_unittest.cc +++ /dev/null @@ -1,580 +0,0 @@ -// 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/aes_128_gcm_helpers_nss.h" - -#include -#include -#include - -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "crypto/nss_util.h" -#include "crypto/random.h" -#include "crypto/scoped_nss_types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -namespace { - -// The AES GCM test vectors come from the gcmDecrypt128.rsp and -// gcmEncryptExtIV128.rsp files downloaded from -// http://csrc.nist.gov/groups/STM/cavp/index.html on 2013-02-01. The test -// vectors in that file look like this: -// -// [Keylen = 128] -// [IVlen = 96] -// [PTlen = 0] -// [AADlen = 0] -// [Taglen = 128] -// -// Count = 0 -// Key = cf063a34d4a9a76c2c86787d3f96db71 -// IV = 113b9785971864c83b01c787 -// CT = -// AAD = -// Tag = 72ac8493e3a5228b5d130a69d2510e42 -// PT = -// -// Count = 1 -// Key = a49a5e26a2f8cb63d05546c2a62f5343 -// IV = 907763b19b9b4ab6bd4f0281 -// CT = -// AAD = -// Tag = a2be08210d8c470a8df6e8fbd79ec5cf -// FAIL -// -// ... -// -// These files are huge (2.6 MB and 2.8 MB), so this file contains just a -// selection of test vectors. - -// Describes a group of test vectors that all have a given key length, IV -// length, plaintext length, AAD length, and tag length. -struct TestGroupInfo { - size_t key_len; - size_t iv_len; - size_t input_len; - size_t aad_len; - size_t tag_len; -}; - -// Each test vector consists of six strings of lowercase hexadecimal digits. -// The strings may be empty (zero length). A test vector with a NULL |key| -// marks the end of an array of test vectors. -struct TestVector { - // Input: - const char* key; - const char* iv; - const char* input; - const char* aad; - const char* tag; - - // Expected output: - const char* output; // An empty string "" means decryption or encryption - // succeeded and the plaintext is zero-length. NULL means - // that the decryption or encryption failed. -}; - -const TestGroupInfo test_group_info[] = { - {128, 96, 0, 0, 128}, - {128, 96, 0, 128, 128}, - {128, 96, 128, 0, 128}, - {128, 96, 408, 160, 128}, - {128, 96, 408, 720, 128}, - {128, 96, 104, 0, 128}, -}; - -const TestVector decryption_test_group_0[] = { - {"cf063a34d4a9a76c2c86787d3f96db71", - "113b9785971864c83b01c787", - "", - "", - "72ac8493e3a5228b5d130a69d2510e42", - ""}, - { - "a49a5e26a2f8cb63d05546c2a62f5343", - "907763b19b9b4ab6bd4f0281", - "", - "", - "a2be08210d8c470a8df6e8fbd79ec5cf", - NULL // FAIL - }, - {NULL}}; - -const TestVector decryption_test_group_1[] = { - { - "d1f6af919cde85661208bdce0c27cb22", - "898c6929b435017bf031c3c5", - "", - "7c5faa40e636bbc91107e68010c92b9f", - "ae45f11777540a2caeb128be8092468a", - NULL // FAIL - }, - {"2370e320d4344208e0ff5683f243b213", - "04dbb82f044d30831c441228", - "", - "d43a8e5089eea0d026c03a85178b27da", - "2a049c049d25aa95969b451d93c31c6e", - ""}, - {NULL}}; - -const TestVector decryption_test_group_2[] = { - {"e98b72a9881a84ca6b76e0f43e68647a", - "8b23299fde174053f3d652ba", - "5a3c1cf1985dbb8bed818036fdd5ab42", - "", - "23c7ab0f952b7091cd324835043b5eb5", - "28286a321293253c3e0aa2704a278032"}, - {"33240636cd3236165f1a553b773e728e", - "17c4d61493ecdc8f31700b12", - "47bb7e23f7bdfe05a8091ac90e4f8b2e", - "", - "b723c70e931d9785f40fd4ab1d612dc9", - "95695a5b12f2870b9cc5fdc8f218a97d"}, - { - "5164df856f1e9cac04a79b808dc5be39", - "e76925d5355e0584ce871b2b", - "0216c899c88d6e32c958c7e553daa5bc", - "", - "a145319896329c96df291f64efbe0e3a", - NULL // FAIL - }, - {NULL}}; - -const TestVector decryption_test_group_3[] = { - {"af57f42c60c0fc5a09adb81ab86ca1c3", - "a2dc01871f37025dc0fc9a79", - "b9a535864f48ea7b6b1367914978f9bfa087d854bb0e269bed8d279d2eea1210e48947" - "338b22f9bad09093276a331e9c79c7f4", - "41dc38988945fcb44faf2ef72d0061289ef8efd8", - "4f71e72bde0018f555c5adcce062e005", - "3803a0727eeb0ade441e0ec107161ded2d425ec0d102f21f51bf2cf9947c7ec4aa7279" - "5b2f69b041596e8817d0a3c16f8fadeb"}, - {"ebc753e5422b377d3cb64b58ffa41b61", - "2e1821efaced9acf1f241c9b", - "069567190554e9ab2b50a4e1fbf9c147340a5025fdbd201929834eaf6532325899ccb9" - "f401823e04b05817243d2142a3589878", - "b9673412fd4f88ba0e920f46dd6438ff791d8eef", - "534d9234d2351cf30e565de47baece0b", - "39077edb35e9c5a4b1e4c2a6b9bb1fce77f00f5023af40333d6d699014c2bcf4209c18" - "353a18017f5b36bfc00b1f6dcb7ed485"}, - { - "52bdbbf9cf477f187ec010589cb39d58", - "d3be36d3393134951d324b31", - "700188da144fa692cf46e4a8499510a53d90903c967f7f13e8a1bd8151a74adc4fe63e" - "32b992760b3a5f99e9a47838867000a9", - "93c4fc6a4135f54d640b0c976bf755a06a292c33", - "8ca4e38aa3dfa6b1d0297021ccf3ea5f", - NULL // FAIL - }, - {NULL}}; - -const TestVector decryption_test_group_4[] = { - {"da2bb7d581493d692380c77105590201", - "44aa3e7856ca279d2eb020c6", - "9290d430c9e89c37f0446dbd620c9a6b34b1274aeb6f911f75867efcf95b6feda69f1a" - "f4ee16c761b3c9aeac3da03aa9889c88", - "4cd171b23bddb3a53cdf959d5c1710b481eb3785a90eb20a2345ee00d0bb7868c367ab" - "12e6f4dd1dee72af4eee1d197777d1d6499cc541f34edbf45cda6ef90b3c024f9272d7" - "2ec1909fb8fba7db88a4d6f7d3d925980f9f9f72", - "9e3ac938d3eb0cadd6f5c9e35d22ba38", - "9bbf4c1a2742f6ac80cb4e8a052e4a8f4f07c43602361355b717381edf9fabd4cb7e3a" - "d65dbd1378b196ac270588dd0621f642"}, - {"d74e4958717a9d5c0e235b76a926cae8", - "0b7471141e0c70b1995fd7b1", - "e701c57d2330bf066f9ff8cf3ca4343cafe4894651cd199bdaaa681ba486b4a65c5a22" - "b0f1420be29ea547d42c713bc6af66aa", - "4a42b7aae8c245c6f1598a395316e4b8484dbd6e64648d5e302021b1d3fa0a38f46e22" - "bd9c8080b863dc0016482538a8562a4bd0ba84edbe2697c76fd039527ac179ec5506cf" - "34a6039312774cedebf4961f3978b14a26509f96", - "e192c23cb036f0b31592989119eed55d", - "840d9fb95e32559fb3602e48590280a172ca36d9b49ab69510f5bd552bfab7a306f85f" - "f0a34bc305b88b804c60b90add594a17"}, - { - "1986310c725ac94ecfe6422e75fc3ee7", - "93ec4214fa8e6dc4e3afc775", - "b178ec72f85a311ac4168f42a4b2c23113fbea4b85f4b9dabb74e143eb1b8b0a361e02" - "43edfd365b90d5b325950df0ada058f9", - "e80b88e62c49c958b5e0b8b54f532d9ff6aa84c8a40132e93e55b59fc24e8decf28463" - "139f155d1e8ce4ee76aaeefcd245baa0fc519f83a5fb9ad9aa40c4b21126013f576c42" - "72c2cb136c8fd091cc4539877a5d1e72d607f960", - "8b347853f11d75e81e8a95010be81f17", - NULL // FAIL - }, - {NULL}}; - -const TestVector decryption_test_group_5[] = { - {"387218b246c1a8257748b56980e50c94", - "dd7e014198672be39f95b69d", - "cdba9e73eaf3d38eceb2b04a8d", - "", - "ecf90f4a47c9c626d6fb2c765d201556", - "48f5b426baca03064554cc2b30"}, - {"294de463721e359863887c820524b3d4", - "3338b35c9d57a5d28190e8c9", - "2f46634e74b8e4c89812ac83b9", - "", - "dabd506764e68b82a7e720aa18da0abe", - "46a2e55c8e264df211bd112685"}, - {"28ead7fd2179e0d12aa6d5d88c58c2dc", - "5055347f18b4d5add0ae5c41", - "142d8210c3fb84774cdbd0447a", - "", - "5fd321d9cdb01952dc85f034736c2a7d", - "3b95b981086ee73cc4d0cc1422"}, - { - "7d7b6c988137b8d470c57bf674a09c87", - "9edf2aa970d016ac962e1fd8", - "a85b66c3cb5eab91d5bdc8bc0e", - "", - "dc054efc01f3afd21d9c2484819f569a", - NULL // FAIL - }, - {NULL}}; - -const TestVector encryption_test_group_0[] = { - {"11754cd72aec309bf52f7687212e8957", - "3c819d9a9bed087615030b65", - "", - "", - "250327c674aaf477aef2675748cf6971", - ""}, - {"ca47248ac0b6f8372a97ac43508308ed", - "ffd2b598feabc9019262d2be", - "", - "", - "60d20404af527d248d893ae495707d1a", - ""}, - {NULL}}; - -const TestVector encryption_test_group_1[] = { - {"77be63708971c4e240d1cb79e8d77feb", - "e0e00f19fed7ba0136a797f3", - "", - "7a43ec1d9c0a5a78a0b16533a6213cab", - "209fcc8d3675ed938e9c7166709dd946", - ""}, - {"7680c5d3ca6154758e510f4d25b98820", - "f8f105f9c3df4965780321f8", - "", - "c94c410194c765e3dcc7964379758ed3", - "94dca8edfcf90bb74b153c8d48a17930", - ""}, - {NULL}}; - -const TestVector encryption_test_group_2[] = { - {"7fddb57453c241d03efbed3ac44e371c", - "ee283a3fc75575e33efd4887", - "d5de42b461646c255c87bd2962d3b9a2", - "", - "b36d1df9b9d5e596f83e8b7f52971cb3", - "2ccda4a5415cb91e135c2a0f78c9b2fd"}, - {"ab72c77b97cb5fe9a382d9fe81ffdbed", - "54cc7dc2c37ec006bcc6d1da", - "007c5e5b3e59df24a7c355584fc1518d", - "", - "2b4401346697138c7a4891ee59867d0c", - "0e1bde206a07a9c2c1b65300f8c64997"}, - {NULL}}; - -const TestVector encryption_test_group_3[] = { - {"fe47fcce5fc32665d2ae399e4eec72ba", - "5adb9609dbaeb58cbd6e7275", - "7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1" - "b840382c4bccaf3bafb4ca8429bea063", - "88319d6e1d3ffa5f987199166c8a9b56c2aeba5a", - "291ef1982e4defedaa2249f898556b47", - "98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf539304373636525" - "3ddbc5db8778371495da76d269e5db3e"}, - {"ec0c2ba17aa95cd6afffe949da9cc3a8", - "296bce5b50b7d66096d627ef", - "b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987" - "b764b9611f6c0f8641843d5d58f3a242", - "f8d00f05d22bf68599bcdeb131292ad6e2df5d14", - "890147971946b627c40016da1ecf3e77", - "a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a0716299" - "5506fde6309ffc19e716eddf1a828c5a"}, - {NULL}}; - -const TestVector encryption_test_group_4[] = { - {"2c1f21cf0f6fb3661943155c3e3d8492", - "23cb5ff362e22426984d1907", - "42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d6" - "8b5615ba7c1220ff6510e259f06655d8", - "5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e" - "3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f" - "4488f33cfb5e979e42b6e1cfc0a60238982a7aec", - "57a3ee28136e94c74838997ae9823f3a", - "81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222" - "b6ad57af43e1895df9dca2a5344a62cc"}, - {"d9f7d2411091f947b4d6f1e2d1f0fb2e", - "e1934f5db57cc983e6b180e7", - "73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490" - "c2c6f6166f4a59431e182663fcaea05a", - "0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d" - "0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a201" - "15d2e51398344b16bee1ed7c499b353d6c597af8", - "21b51ca862cb637cdd03b99a0f93b134", - "aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d57" - "3c7891c2a91fbc48db29967ec9542b23"}, - {NULL}}; - -const TestVector encryption_test_group_5[] = { - {"fe9bb47deb3a61e423c2231841cfd1fb", - "4d328eb776f500a2f7fb47aa", - "f1cc3818e421876bb6b8bbd6c9", - "", - "43fd4727fe5cdb4b5b42818dea7ef8c9", - "b88c5c1977b35b517b0aeae967"}, - {"6703df3701a7f54911ca72e24dca046a", - "12823ab601c350ea4bc2488c", - "793cd125b0b84a043e3ac67717", - "", - "38e6bcd29962e5f2c13626b85a877101", - "b2051c80014f42f08735a7b0cd"}, - {NULL}}; - -const TestVector* const decryption_test_group_array[] = { - decryption_test_group_0, - decryption_test_group_1, - decryption_test_group_2, - decryption_test_group_3, - decryption_test_group_4, - decryption_test_group_5, -}; - -const TestVector* const encryption_test_group_array[] = { - encryption_test_group_0, - encryption_test_group_1, - encryption_test_group_2, - encryption_test_group_3, - encryption_test_group_4, - encryption_test_group_5, -}; - -bool DecodeHexString(const base::StringPiece& hex, std::string* bytes) { - bytes->clear(); - if (hex.empty()) - return true; - std::vector v; - if (!base::HexStringToBytes(hex.as_string(), &v)) - return false; - if (!v.empty()) - bytes->assign(reinterpret_cast(&v[0]), v.size()); - return true; -} - -class Aes128GcmHelpersTest : public ::testing::Test { - public: - enum Mode { DECRYPT, ENCRYPT }; - - void SetUp() override { EnsureNSSInit(); } - - bool DecryptOrEncrypt(Mode mode, - const base::StringPiece& input, - const base::StringPiece& key, - const base::StringPiece& nonce, - const base::StringPiece& aad, - size_t auth_tag_size, - std::string* output) { - DCHECK(output); - - const CK_ATTRIBUTE_TYPE cka_mode = - mode == DECRYPT ? CKA_DECRYPT : CKA_ENCRYPT; - - SECItem key_item; - key_item.type = siBuffer; - key_item.data = const_cast( - reinterpret_cast(key.data())); - key_item.len = key.size(); - - crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); - DCHECK(slot); - - crypto::ScopedPK11SymKey aead_key( - PK11_ImportSymKey(slot.get(), CKM_AES_GCM, PK11_OriginUnwrap, cka_mode, - &key_item, nullptr)); - - CK_GCM_PARAMS gcm_params; - gcm_params.pIv = const_cast( - reinterpret_cast(nonce.data())); - gcm_params.ulIvLen = nonce.size(); - - gcm_params.pAAD = const_cast( - reinterpret_cast(aad.data())); - - gcm_params.ulAADLen = aad.size(); - - gcm_params.ulTagBits = auth_tag_size * 8; - - SECItem param; - param.type = siBuffer; - param.data = reinterpret_cast(&gcm_params); - param.len = sizeof(CK_GCM_PARAMS); - - size_t maximum_output_length = input.size(); - if (mode == ENCRYPT) - maximum_output_length += auth_tag_size; - - unsigned int output_length = 0; - unsigned char* raw_input = const_cast( - reinterpret_cast(input.data())); - unsigned char* raw_output = reinterpret_cast( - base::WriteInto(output, maximum_output_length + 1 /* null */)); - - PK11Helper_TransformFunction* transform_function = - mode == DECRYPT ? PK11DecryptHelper : PK11EncryptHelper; - - const SECStatus result = transform_function( - aead_key.get(), CKM_AES_GCM, ¶m, raw_output, &output_length, - maximum_output_length, raw_input, input.size()); - - if (result != SECSuccess) - return false; - - const size_t expected_output_length = mode == DECRYPT - ? input.size() - auth_tag_size - : input.size() + auth_tag_size; - - EXPECT_EQ(expected_output_length, output_length); - - output->resize(expected_output_length); - return true; - } - - private: - // The prototype of PK11_Decrypt and PK11_Encrypt. - using PK11Helper_TransformFunction = SECStatus(PK11SymKey* symKey, - CK_MECHANISM_TYPE mechanism, - SECItem* param, - unsigned char* out, - unsigned int* outLen, - unsigned int maxLen, - const unsigned char* data, - unsigned int dataLen); -}; - -} // namespace - -TEST_F(Aes128GcmHelpersTest, RoundTrip) { - const std::string message = "Hello, world!"; - - const size_t kKeySize = 16; - const size_t kNonceSize = 16; - - std::string key, nonce; - RandBytes(base::WriteInto(&key, kKeySize + 1), kKeySize); - RandBytes(base::WriteInto(&nonce, kNonceSize + 1), kNonceSize); - - // AEAD_AES_128_GCM is defined with a default authentication tag size of 16, - // but RFC 5282 extends this to authentication tag sizes of 8 and 12 as well. - size_t auth_tag_size = base::RandInt(2, 4) * 4; - - std::string encrypted; - ASSERT_TRUE(DecryptOrEncrypt(ENCRYPT, message, key, nonce, - base::StringPiece(), auth_tag_size, &encrypted)); - - std::string decrypted; - ASSERT_TRUE(DecryptOrEncrypt(DECRYPT, encrypted, key, nonce, - base::StringPiece(), auth_tag_size, &decrypted)); - - EXPECT_EQ(message, decrypted); -} - -TEST_F(Aes128GcmHelpersTest, DecryptionVectors) { - for (size_t i = 0; i < arraysize(decryption_test_group_array); i++) { - SCOPED_TRACE(i); - const TestVector* test_vectors = decryption_test_group_array[i]; - const TestGroupInfo& test_info = test_group_info[i]; - - for (size_t j = 0; test_vectors[j].key != nullptr; j++) { - // If not present then decryption is expected to fail. - bool has_output = test_vectors[j].output; - - // Decode the test vector. - std::string key, iv, input, aad, tag, expected_output; - ASSERT_TRUE(DecodeHexString(test_vectors[j].key, &key)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].iv, &iv)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].input, &input)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].aad, &aad)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].tag, &tag)); - if (has_output) - ASSERT_TRUE(DecodeHexString(test_vectors[j].output, &expected_output)); - - // The test vector's lengths should look sane. Note that the lengths - // in |test_info| are in bits. - EXPECT_EQ(test_info.key_len, key.length() * 8); - EXPECT_EQ(test_info.iv_len, iv.length() * 8); - EXPECT_EQ(test_info.input_len, input.length() * 8); - EXPECT_EQ(test_info.aad_len, aad.length() * 8); - EXPECT_EQ(test_info.tag_len, tag.length() * 8); - if (has_output) - EXPECT_EQ(test_info.input_len, expected_output.length() * 8); - - const std::string ciphertext = input + tag; - std::string output; - - if (!DecryptOrEncrypt(DECRYPT, ciphertext, key, iv, aad, tag.length(), - &output)) { - EXPECT_FALSE(has_output); - continue; - } - - EXPECT_TRUE(has_output); - EXPECT_EQ(expected_output, output); - } - } -} - -TEST_F(Aes128GcmHelpersTest, EncryptionVectors) { - for (size_t i = 0; i < arraysize(encryption_test_group_array); i++) { - SCOPED_TRACE(i); - const TestVector* test_vectors = encryption_test_group_array[i]; - const TestGroupInfo& test_info = test_group_info[i]; - - for (size_t j = 0; test_vectors[j].key != nullptr; j++) { - // If not present then decryption is expected to fail. - bool has_output = test_vectors[j].output; - - // Decode the test vector. - std::string key, iv, input, aad, tag, expected_output; - ASSERT_TRUE(DecodeHexString(test_vectors[j].key, &key)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].iv, &iv)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].input, &input)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].aad, &aad)); - ASSERT_TRUE(DecodeHexString(test_vectors[j].tag, &tag)); - if (has_output) - ASSERT_TRUE(DecodeHexString(test_vectors[j].output, &expected_output)); - - // The test vector's lengths should look sane. Note that the lengths - // in |test_info| are in bits. - EXPECT_EQ(test_info.key_len, key.length() * 8); - EXPECT_EQ(test_info.iv_len, iv.length() * 8); - EXPECT_EQ(test_info.input_len, input.length() * 8); - EXPECT_EQ(test_info.aad_len, aad.length() * 8); - EXPECT_EQ(test_info.tag_len, tag.length() * 8); - if (has_output) - EXPECT_EQ(test_info.input_len, expected_output.length() * 8); - - std::string output; - - if (!DecryptOrEncrypt(ENCRYPT, input, key, iv, aad, tag.length(), - &output)) { - EXPECT_FALSE(has_output); - continue; - } - - const std::string expected_output_with_tag = expected_output + tag; - - EXPECT_TRUE(has_output); - EXPECT_EQ(expected_output_with_tag, output); - } - } -} - -} // namespace crypto diff --git a/crypto/apple_keychain.h b/crypto/apple_keychain.h deleted file mode 100644 index 840ccee8c2032..0000000000000 --- a/crypto/apple_keychain.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2012 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_KEYCHAIN_MAC_H_ -#define CRYPTO_KEYCHAIN_MAC_H_ - -#include - -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -#if defined (OS_IOS) -typedef void* SecKeychainRef; -typedef void* SecKeychainItemRef; -typedef void SecKeychainAttributeList; -#endif - -namespace crypto { - -// Wraps the KeychainServices API in a very thin layer, to allow it to be -// mocked out for testing. - -// See Keychain Services documentation for function documentation, as these call -// through directly to their Keychain Services equivalents (Foo -> -// SecKeychainFoo). The only exception is Free, which should be used for -// anything returned from this class that would normally be freed with -// CFRelease (to aid in testing). -class CRYPTO_EXPORT AppleKeychain { - public: - AppleKeychain(); - virtual ~AppleKeychain(); - - virtual OSStatus FindGenericPassword(CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const; - - virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const; - - virtual OSStatus AddGenericPassword(SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const; - -#if !defined(OS_IOS) - virtual OSStatus ItemCopyAttributesAndData( - SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const; - - virtual OSStatus ItemModifyAttributesAndData( - SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const; - - virtual OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, - void* data) const; - - virtual OSStatus ItemDelete(SecKeychainItemRef itemRef) const; - - virtual OSStatus SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const; - - virtual OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const; - - virtual OSStatus AddInternetPassword(SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, const char* path, - UInt16 port, SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const; - - // Calls CFRelease on the given ref, after checking that |ref| is non-NULL. - virtual void Free(CFTypeRef ref) const; -#endif // !defined(OS_IOS) - - private: - DISALLOW_COPY_AND_ASSIGN(AppleKeychain); -}; - -} // namespace crypto - -#endif // CRYPTO_KEYCHAIN_MAC_H_ diff --git a/crypto/apple_keychain_ios.mm b/crypto/apple_keychain_ios.mm deleted file mode 100644 index 74cf129ce1fd0..0000000000000 --- a/crypto/apple_keychain_ios.mm +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2012 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/apple_keychain.h" - -#import - -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_nsobject.h" - -namespace { - -enum KeychainAction { - kKeychainActionCreate, - kKeychainActionUpdate -}; - -// Creates a dictionary that can be used to query the keystore. -// Ownership follows the Create rule. -CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName) { - CFMutableDictionaryRef query = - CFDictionaryCreateMutable(NULL, - 5, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - // Type of element is generic password. - CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword); - - // Set the service name. - base::scoped_nsobject service_name_ns( - [[NSString alloc] initWithBytes:serviceName - length:serviceNameLength - encoding:NSUTF8StringEncoding]); - CFDictionarySetValue(query, kSecAttrService, - base::mac::NSToCFCast(service_name_ns)); - - // Set the account name. - base::scoped_nsobject account_name_ns( - [[NSString alloc] initWithBytes:accountName - length:accountNameLength - encoding:NSUTF8StringEncoding]); - CFDictionarySetValue(query, kSecAttrAccount, - base::mac::NSToCFCast(account_name_ns)); - - // Use the proper search constants, return only the data of the first match. - CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); - CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); - return query; -} - -// Creates a dictionary conatining the data to save into the keychain. -// Ownership follows the Create rule. -CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - KeychainAction action) { - CFMutableDictionaryRef keychain_data = - CFDictionaryCreateMutable(NULL, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - // Set the password. - NSData* password = [NSData dataWithBytes:passwordData length:passwordLength]; - CFDictionarySetValue(keychain_data, kSecValueData, - base::mac::NSToCFCast(password)); - - // If this is not a creation, no structural information is needed. - if (action != kKeychainActionCreate) - return keychain_data; - - // Set the type of the data. - CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword); - - // Only allow access when the device has been unlocked. - CFDictionarySetValue(keychain_data, - kSecAttrAccessible, - kSecAttrAccessibleWhenUnlocked); - - // Set the service name. - base::scoped_nsobject service_name_ns( - [[NSString alloc] initWithBytes:serviceName - length:serviceNameLength - encoding:NSUTF8StringEncoding]); - CFDictionarySetValue(keychain_data, kSecAttrService, - base::mac::NSToCFCast(service_name_ns)); - - // Set the account name. - base::scoped_nsobject account_name_ns( - [[NSString alloc] initWithBytes:accountName - length:accountNameLength - encoding:NSUTF8StringEncoding]); - CFDictionarySetValue(keychain_data, kSecAttrAccount, - base::mac::NSToCFCast(account_name_ns)); - - return keychain_data; -} - -} // namespace - -namespace crypto { - -AppleKeychain::AppleKeychain() {} - -AppleKeychain::~AppleKeychain() {} - -OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const { - free(data); - return noErr; -} - -OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - base::ScopedCFTypeRef query(CreateGenericPasswordQuery( - serviceNameLength, serviceName, accountNameLength, accountName)); - // Check that there is not already a password. - OSStatus status = SecItemCopyMatching(query, NULL); - if (status == errSecItemNotFound) { - // A new entry must be created. - base::ScopedCFTypeRef keychain_data( - CreateKeychainData(serviceNameLength, - serviceName, - accountNameLength, - accountName, - passwordLength, - passwordData, - kKeychainActionCreate)); - status = SecItemAdd(keychain_data, NULL); - } else if (status == noErr) { - // The entry must be updated. - base::ScopedCFTypeRef keychain_data( - CreateKeychainData(serviceNameLength, - serviceName, - accountNameLength, - accountName, - passwordLength, - passwordData, - kKeychainActionUpdate)); - status = SecItemUpdate(query, keychain_data); - } - - return status; -} - -OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const { - DCHECK((passwordData && passwordLength) || - (!passwordData && !passwordLength)); - base::ScopedCFTypeRef query(CreateGenericPasswordQuery( - serviceNameLength, serviceName, accountNameLength, accountName)); - - // Get the keychain item containing the password. - CFTypeRef resultRef = NULL; - OSStatus status = SecItemCopyMatching(query, &resultRef); - base::ScopedCFTypeRef result(resultRef); - - if (status != noErr) { - if (passwordData) { - *passwordData = NULL; - *passwordLength = 0; - } - return status; - } - - if (passwordData) { - CFDataRef data = base::mac::CFCast(result); - NSUInteger length = CFDataGetLength(data); - *passwordData = malloc(length * sizeof(UInt8)); - CFDataGetBytes(data, CFRangeMake(0, length), (UInt8*)*passwordData); - *passwordLength = length; - } - return status; -} - -} // namespace crypto diff --git a/crypto/apple_keychain_mac.mm b/crypto/apple_keychain_mac.mm deleted file mode 100644 index 240c32067bcf1..0000000000000 --- a/crypto/apple_keychain_mac.mm +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2012 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/apple_keychain.h" - -#import - -#include "base/synchronization/lock.h" -#include "crypto/mac_security_services_lock.h" - -namespace crypto { - -AppleKeychain::AppleKeychain() {} - -AppleKeychain::~AppleKeychain() {} - -OSStatus AppleKeychain::ItemCopyAttributesAndData( - SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, - attrList, length, outData); -} - -OSStatus AppleKeychain::ItemModifyAttributesAndData( - SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemModifyAttributesAndData(itemRef, attrList, length, - data); -} - -OSStatus AppleKeychain::ItemFreeAttributesAndData( - SecKeychainAttributeList* attrList, - void* data) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemFreeAttributesAndData(attrList, data); -} - -OSStatus AppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemDelete(itemRef); -} - -OSStatus AppleKeychain::SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainSearchCreateFromAttributes(keychainOrArray, itemClass, - attrList, searchRef); -} - -OSStatus AppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainSearchCopyNext(searchRef, itemRef); -} - -OSStatus AppleKeychain::AddInternetPassword( - SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainAddInternetPassword(keychain, - serverNameLength, serverName, - securityDomainLength, securityDomain, - accountNameLength, accountName, - pathLength, path, - port, protocol, authenticationType, - passwordLength, passwordData, - itemRef); -} - -OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainFindGenericPassword(keychainOrArray, - serviceNameLength, - serviceName, - accountNameLength, - accountName, - passwordLength, - passwordData, - itemRef); -} - -OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemFreeContent(attrList, data); -} - -OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainAddGenericPassword(keychain, - serviceNameLength, - serviceName, - accountNameLength, - accountName, - passwordLength, - passwordData, - itemRef); -} - -void AppleKeychain::Free(CFTypeRef ref) const { - if (ref) - CFRelease(ref); -} - -} // namespace crypto diff --git a/crypto/capi_util.cc b/crypto/capi_util.cc deleted file mode 100644 index 2cf10625ec34f..0000000000000 --- a/crypto/capi_util.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2011 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/capi_util.h" - -#include "base/basictypes.h" -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" - -namespace { - -class CAPIUtilSingleton { - public: - static CAPIUtilSingleton* GetInstance() { - return Singleton::get(); - } - - // Returns a lock to guard calls to CryptAcquireContext with - // CRYPT_DELETEKEYSET or CRYPT_NEWKEYSET. - base::Lock& acquire_context_lock() { - return acquire_context_lock_; - } - - private: - friend class Singleton; - friend struct DefaultSingletonTraits; - - CAPIUtilSingleton() {} - - base::Lock acquire_context_lock_; - - DISALLOW_COPY_AND_ASSIGN(CAPIUtilSingleton); -}; - -} // namespace - -namespace crypto { - -BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, - LPCWSTR container, - LPCWSTR provider, - DWORD prov_type, - DWORD flags) { - base::AutoLock lock(CAPIUtilSingleton::GetInstance()->acquire_context_lock()); - return CryptAcquireContext(prov, container, provider, prov_type, flags); -} - -void* WINAPI CryptAlloc(size_t size) { - return malloc(size); -} - -void WINAPI CryptFree(void* p) { - free(p); -} - -} // namespace crypto diff --git a/crypto/capi_util.h b/crypto/capi_util.h deleted file mode 100644 index 9d43293e23121..0000000000000 --- a/crypto/capi_util.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2012 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_CAPI_UTIL_H_ -#define CRYPTO_CAPI_UTIL_H_ - -#include - -#include "crypto/crypto_export.h" -#include "crypto/wincrypt_shim.h" - -namespace crypto { - -// CryptAcquireContext when passed CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET in -// flags is not thread-safe. For such calls, we create a global lock to -// synchronize it. -// -// From "Threading Issues with Cryptographic Service Providers", -// : -// -// "The CryptAcquireContext function is generally thread safe unless -// CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET is specified in the dwFlags -// parameter." -CRYPTO_EXPORT BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, - LPCWSTR container, - LPCWSTR provider, - DWORD prov_type, - DWORD flags); - -// Wrappers of malloc and free for CryptoAPI routines that need memory -// allocators, such as in CRYPT_DECODE_PARA. Such routines require WINAPI -// calling conventions. -CRYPTO_EXPORT void* WINAPI CryptAlloc(size_t size); -CRYPTO_EXPORT void WINAPI CryptFree(void* p); - -} // namespace crypto - -#endif // CRYPTO_CAPI_UTIL_H_ diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp deleted file mode 100644 index 6327ce76dd24b..0000000000000 --- a/crypto/crypto.gyp +++ /dev/null @@ -1,335 +0,0 @@ -# Copyright (c) 2012 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. - -{ - 'variables': { - 'chromium_code': 1, - }, - 'includes': [ - 'crypto.gypi', - ], - 'targets': [ - { - 'target_name': 'crypto', - 'type': '<(component)', - 'product_name': 'crcrypto', # Avoid colliding with OpenSSL's libcrypto - 'dependencies': [ - '../base/base.gyp:base', - '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', - ], - 'defines': [ - 'CRYPTO_IMPLEMENTATION', - ], - 'conditions': [ - [ 'os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', { - 'dependencies': [ - '../build/linux/system.gyp:ssl', - ], - 'export_dependent_settings': [ - '../build/linux/system.gyp:ssl', - ], - 'conditions': [ - [ 'chromeos==1', { - 'sources/': [ ['include', '_chromeos\\.cc$'] ] - }, - ], - ], - }, { # os_posix != 1 or OS == "mac" or OS == "ios" or OS == "android" - 'sources!': [ - 'hmac_win.cc', - 'symmetric_key_win.cc', - ], - }], - [ 'OS != "mac" and OS != "ios"', { - 'sources!': [ - 'apple_keychain.h', - 'mock_apple_keychain.cc', - 'mock_apple_keychain.h', - ], - }], - [ 'OS == "android"', { - 'dependencies': [ - '../build/android/ndk.gyp:cpu_features', - ], - }], - [ 'os_bsd==1', { - 'link_settings': { - 'libraries': [ - '-L/usr/local/lib -lexecinfo', - ], - }, - }, - ], - [ 'OS == "mac"', { - 'link_settings': { - 'libraries': [ - '$(SDKROOT)/System/Library/Frameworks/Security.framework', - ], - }, - }, { # OS != "mac" - 'sources!': [ - 'cssm_init.cc', - 'cssm_init.h', - 'mac_security_services_lock.cc', - 'mac_security_services_lock.h', - ], - }], - [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', { - 'dependencies': [ - '../third_party/nss/nss.gyp:nspr', - '../third_party/nss/nss.gyp:nss', - ], - 'export_dependent_settings': [ - '../third_party/nss/nss.gyp:nspr', - '../third_party/nss/nss.gyp:nss', - ], - }], - [ 'OS != "win"', { - 'sources!': [ - 'capi_util.h', - 'capi_util.cc', - ], - }], - [ 'OS == "win"', { - 'msvs_disabled_warnings': [ - 4267, # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 4018, - ], - }], - [ 'use_openssl==1', { - 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', - ], - # TODO(joth): Use a glob to match exclude patterns once the - # OpenSSL file set is complete. - 'sources!': [ - 'aes_128_gcm_helpers_nss.cc', - 'aes_128_gcm_helpers_nss.h', - 'ec_private_key_nss.cc', - 'ec_signature_creator_nss.cc', - 'encryptor_nss.cc', - 'hmac_nss.cc', - 'rsa_private_key_nss.cc', - 'secure_hash_default.cc', - 'signature_creator_nss.cc', - 'signature_verifier_nss.cc', - 'symmetric_key_nss.cc', - 'third_party/nss/chromium-blapi.h', - 'third_party/nss/chromium-blapit.h', - 'third_party/nss/chromium-nss.h', - 'third_party/nss/chromium-prtypes.h', - 'third_party/nss/chromium-sha256.h', - 'third_party/nss/pk11akey.cc', - 'third_party/nss/rsawrapr.c', - 'third_party/nss/secsign.cc', - 'third_party/nss/sha512.cc', - ], - }, { - 'sources!': [ - 'aead_openssl.cc', - 'aead_openssl.h', - 'ec_private_key_openssl.cc', - 'ec_signature_creator_openssl.cc', - 'encryptor_openssl.cc', - 'hmac_openssl.cc', - 'openssl_bio_string.cc', - 'openssl_bio_string.h', - 'openssl_util.cc', - 'openssl_util.h', - 'rsa_private_key_openssl.cc', - 'secure_hash_openssl.cc', - 'signature_creator_openssl.cc', - 'signature_verifier_openssl.cc', - 'symmetric_key_openssl.cc', - ], - },], - [ 'use_openssl==1 and use_nss_certs==0', { - # Some files are built when NSS is used at all, either for the - # internal crypto library or the platform certificate library. - 'sources!': [ - 'nss_key_util.cc', - 'nss_key_util.h', - 'nss_util.cc', - 'nss_util.h', - 'nss_util_internal.h', - ], - },], - ], - 'sources': [ - '<@(crypto_sources)', - ], - }, - { - 'target_name': 'crypto_unittests', - 'type': 'executable', - 'sources': [ - 'aead_openssl_unittest.cc', - 'aes_128_gcm_helpers_nss_unittest.cc', - 'curve25519_unittest.cc', - 'ec_private_key_unittest.cc', - 'ec_signature_creator_unittest.cc', - 'encryptor_unittest.cc', - 'ghash_unittest.cc', - 'hkdf_unittest.cc', - 'hmac_unittest.cc', - 'nss_key_util_unittest.cc', - 'nss_util_unittest.cc', - 'openssl_bio_string_unittest.cc', - 'p224_unittest.cc', - 'p224_spake_unittest.cc', - 'random_unittest.cc', - 'rsa_private_key_unittest.cc', - 'secure_hash_unittest.cc', - 'sha2_unittest.cc', - 'signature_creator_unittest.cc', - 'signature_verifier_unittest.cc', - 'symmetric_key_unittest.cc', - ], - 'dependencies': [ - 'crypto', - 'crypto_test_support', - '../base/base.gyp:base', - '../base/base.gyp:run_all_unittests', - '../base/base.gyp:test_support_base', - '../testing/gmock.gyp:gmock', - '../testing/gtest.gyp:gtest', - ], - 'conditions': [ - [ 'use_nss_certs == 1', { - 'conditions': [ - [ 'use_allocator!="none"', { - 'dependencies': [ - '../base/allocator/allocator.gyp:allocator', - ], - }, - ], - ], - 'dependencies': [ - '../build/linux/system.gyp:ssl', - ], - }], - [ 'use_openssl == 1 and use_nss_certs == 0', { - # Some files are built when NSS is used at all, either for the - # internal crypto library or the platform certificate library. - 'sources!': [ - 'nss_key_util_unittest.cc', - 'nss_util_unittest.cc', - ], - }], - [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', { - 'dependencies': [ - '../third_party/nss/nss.gyp:nspr', - ], - }], - [ 'OS == "win"', { - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [4267, ], - }], - [ 'use_openssl==1', { - 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', - ], - 'sources!': [ - 'aes_128_gcm_helpers_nss_unittest.cc', - ], - }, { - 'sources!': [ - 'openssl_bio_string_unittest.cc', - ], - }], - ], - }, - ], - 'conditions': [ - ['OS == "win" and target_arch=="ia32"', { - 'targets': [ - { - 'target_name': 'crypto_nacl_win64', - # We do not want nacl_helper to depend on NSS because this would - # require including a 64-bit copy of NSS. Thus, use the native APIs - # for the helper. - 'type': '<(component)', - 'dependencies': [ - '../base/base.gyp:base_win64', - '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64', - ], - 'sources': [ - '<@(nacl_win64_sources)', - ], - 'defines': [ - 'CRYPTO_IMPLEMENTATION', - '<@(nacl_win64_defines)', - ], - 'msvs_disabled_warnings': [ - 4018, - ], - 'configurations': { - 'Common_Base': { - 'msvs_target_platform': 'x64', - }, - }, - }, - ], - }], - ['use_nss_certs==1', { - 'targets': [ - { - 'target_name': 'crypto_test_support', - 'type': 'static_library', - 'dependencies': [ - '../base/base.gyp:base', - 'crypto', - ], - 'sources': [ - 'scoped_test_nss_db.cc', - 'scoped_test_nss_db.h', - 'scoped_test_nss_chromeos_user.cc', - 'scoped_test_nss_chromeos_user.h', - 'scoped_test_system_nss_key_slot.cc', - 'scoped_test_system_nss_key_slot.h', - ], - 'conditions': [ - ['use_nss_certs==0', { - 'sources!': [ - 'scoped_test_nss_db.cc', - 'scoped_test_nss_db.h', - ], - }], - [ 'chromeos==0', { - 'sources!': [ - 'scoped_test_nss_chromeos_user.cc', - 'scoped_test_nss_chromeos_user.h', - 'scoped_test_system_nss_key_slot.cc', - 'scoped_test_system_nss_key_slot.h', - ], - }], - ], - } - ]}, { # use_nss_certs==0 - 'targets': [ - { - 'target_name': 'crypto_test_support', - 'type': 'none', - 'sources': [], - } - ]}], - ['test_isolation_mode != "noop"', { - 'targets': [ - { - 'target_name': 'crypto_unittests_run', - 'type': 'none', - 'dependencies': [ - 'crypto_unittests', - ], - 'includes': [ - '../build/isolate.gypi', - ], - 'sources': [ - 'crypto_unittests.isolate', - ], - }, - ], - }], - ], -} diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi deleted file mode 100644 index 71ffbecad1116..0000000000000 --- a/crypto/crypto.gypi +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 2014 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. - -{ - 'variables': { - # Put all transitive dependencies for Windows HMAC here. - # This is required so that we can build them for nacl win64. - 'variables': { - 'hmac_win64_related_sources': [ - 'hmac.cc', - 'hmac.h', - 'hmac_win.cc', - 'secure_util.cc', - 'secure_util.h', - 'symmetric_key.h', - 'symmetric_key_win.cc', - 'third_party/nss/chromium-blapi.h', - 'third_party/nss/chromium-blapit.h', - 'third_party/nss/chromium-prtypes.h', - 'third_party/nss/chromium-sha256.h', - 'third_party/nss/sha512.cc', - 'wincrypt_shim.h', - ], - }, - 'crypto_sources': [ - # 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', - 'aes_128_gcm_helpers_nss.cc', - 'aes_128_gcm_helpers_nss.h', - 'apple_keychain.h', - 'apple_keychain_ios.mm', - 'apple_keychain_mac.mm', - 'capi_util.cc', - 'capi_util.h', - 'crypto_export.h', - 'cssm_init.cc', - 'cssm_init.h', - 'curve25519.cc', - 'curve25519.h', - 'curve25519-donna.c', - 'ghash.cc', - 'ghash.h', - 'ec_private_key.h', - 'ec_private_key_nss.cc', - 'ec_private_key_openssl.cc', - 'ec_signature_creator.cc', - 'ec_signature_creator.h', - 'ec_signature_creator_impl.h', - 'ec_signature_creator_nss.cc', - 'ec_signature_creator_openssl.cc', - 'encryptor.cc', - 'encryptor.h', - 'encryptor_nss.cc', - 'encryptor_openssl.cc', - 'hkdf.cc', - 'hkdf.h', - 'hmac_nss.cc', - 'hmac_openssl.cc', - 'mac_security_services_lock.cc', - 'mac_security_services_lock.h', - 'mock_apple_keychain.cc', - 'mock_apple_keychain.h', - 'mock_apple_keychain_ios.cc', - 'mock_apple_keychain_mac.cc', - 'p224_spake.cc', - 'p224_spake.h', - 'nss_crypto_module_delegate.h', - 'nss_key_util.cc', - 'nss_key_util.h', - 'nss_util.cc', - 'nss_util.h', - 'nss_util_internal.h', - 'openssl_bio_string.cc', - 'openssl_bio_string.h', - 'openssl_util.cc', - 'openssl_util.h', - 'p224.cc', - 'p224.h', - 'random.h', - 'random.cc', - 'rsa_private_key.cc', - 'rsa_private_key.h', - 'rsa_private_key_nss.cc', - 'rsa_private_key_openssl.cc', - 'scoped_capi_types.h', - 'scoped_nss_types.h', - 'secure_hash.h', - 'secure_hash_default.cc', - 'secure_hash_openssl.cc', - 'sha2.cc', - 'sha2.h', - 'signature_creator.h', - 'signature_creator_nss.cc', - 'signature_creator_openssl.cc', - 'signature_verifier.h', - 'signature_verifier_nss.cc', - 'signature_verifier_openssl.cc', - 'symmetric_key_nss.cc', - 'symmetric_key_openssl.cc', - 'third_party/nss/chromium-nss.h', - 'third_party/nss/pk11akey.cc', - 'third_party/nss/rsawrapr.c', - 'third_party/nss/secsign.cc', - ], - 'nacl_win64_sources': [ - '<@(hmac_win64_related_sources)', - 'random.cc', - 'random.h', - ], - } -} diff --git a/crypto/crypto_export.h b/crypto/crypto_export.h deleted file mode 100644 index 983afe6d09963..0000000000000 --- a/crypto/crypto_export.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 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_CRYPTO_EXPORT_H_ -#define CRYPTO_CRYPTO_EXPORT_H_ - -// Defines CRYPTO_EXPORT so that functionality implemented by the crypto module -// can be exported to consumers, and CRYPTO_EXPORT_PRIVATE that allows unit -// tests to access features not intended to be used directly by real consumers. - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(CRYPTO_IMPLEMENTATION) -#define CRYPTO_EXPORT __declspec(dllexport) -#define CRYPTO_EXPORT_PRIVATE __declspec(dllexport) -#else -#define CRYPTO_EXPORT __declspec(dllimport) -#define CRYPTO_EXPORT_PRIVATE __declspec(dllimport) -#endif // defined(CRYPTO_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(CRYPTO_IMPLEMENTATION) -#define CRYPTO_EXPORT __attribute__((visibility("default"))) -#define CRYPTO_EXPORT_PRIVATE __attribute__((visibility("default"))) -#else -#define CRYPTO_EXPORT -#define CRYPTO_EXPORT_PRIVATE -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define CRYPTO_EXPORT -#define CRYPTO_EXPORT_PRIVATE -#endif - -#endif // CRYPTO_CRYPTO_EXPORT_H_ diff --git a/crypto/crypto_nacl.gyp b/crypto/crypto_nacl.gyp deleted file mode 100644 index 255c42c51d317..0000000000000 --- a/crypto/crypto_nacl.gyp +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2014 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. - -{ - 'variables': { - 'chromium_code': 1, - }, - 'includes': [ - '../native_client/build/untrusted.gypi', - 'crypto.gypi', - ], - 'targets': [ - { - 'target_name': 'crypto_nacl', - 'type': 'none', - 'variables': { - 'nacl_untrusted_build': 1, - 'nlib_target': 'libcrypto_nacl.a', - 'build_glibc': 0, - 'build_newlib': 0, - 'build_pnacl_newlib': 1, - }, - 'dependencies': [ - '../third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', - '../native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', - ], - 'defines': [ - 'CRYPTO_IMPLEMENTATION', - ], - 'sources': [ - '<@(crypto_sources)', - ], - 'sources/': [ - ['exclude', '_nss\.(cc|h)$'], - ['exclude', '^(mock_)?apple_'], - ['exclude', '^capi_'], - ['exclude', '^cssm_'], - ['exclude', '^nss_'], - ['exclude', '^mac_'], - ['exclude', '^third_party/nss/'], - ['include', '^third_party/nss/sha512.cc'], - ], - }, - ], -} diff --git a/crypto/crypto_unittests.isolate b/crypto/crypto_unittests.isolate deleted file mode 100644 index e09095c142bff..0000000000000 --- a/crypto/crypto_unittests.isolate +++ /dev/null @@ -1,44 +0,0 @@ -# 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. -{ - 'variables': { - 'command': [ - '../testing/test_env.py', - '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--msan=<(msan)', - '--tsan=<(tsan)', - ], - }, - 'conditions': [ - ['OS=="linux" or OS=="mac" or OS=="win"', { - 'variables': { - 'files': [ - '../testing/test_env.py', - '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)', - ], - 'read_only': 1, - }, - }], - ['OS=="mac" and asan==1 and fastbuild==0', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/crypto_unittests.dSYM/', - ], - }, - }], - ['OS=="win" and (fastbuild==0 or fastbuild==1)', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/crypto_unittests.exe.pdb', - ], - }, - }], - ], - 'includes': [ - '../base/base.isolate', - ], -} diff --git a/crypto/cssm_init.cc b/crypto/cssm_init.cc deleted file mode 100644 index 208309c351e3a..0000000000000 --- a/crypto/cssm_init.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2012 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/cssm_init.h" - -#include - -#include "base/logging.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/memory/singleton.h" -#include "base/strings/sys_string_conversions.h" - -// When writing crypto code for Mac OS X, you may find the following -// documentation useful: -// - Common Security: CDSA and CSSM, Version 2 (with corrigenda) -// http://www.opengroup.org/security/cdsa.htm -// - Apple Cryptographic Service Provider Functional Specification -// - CryptoSample: http://developer.apple.com/SampleCode/CryptoSample/ - -namespace { - -void* CSSMMalloc(CSSM_SIZE size, void* alloc_ref) { - return malloc(size); -} - -void CSSMFree(void* mem_ptr, void* alloc_ref) { - free(mem_ptr); -} - -void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) { - return realloc(ptr, size); -} - -void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) { - return calloc(num, size); -} - -class CSSMInitSingleton { - public: - static CSSMInitSingleton* GetInstance() { - return Singleton >::get(); - } - - CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; } - CSSM_CL_HANDLE cl_handle() const { return cl_handle_; } - CSSM_TP_HANDLE tp_handle() const { return tp_handle_; } - - private: - CSSMInitSingleton() - : inited_(false), csp_loaded_(false), cl_loaded_(false), - tp_loaded_(false), csp_handle_(CSSM_INVALID_HANDLE), - cl_handle_(CSSM_INVALID_HANDLE), tp_handle_(CSSM_INVALID_HANDLE) { - static CSSM_VERSION version = {2, 0}; - // TODO(wtc): what should our caller GUID be? - static const CSSM_GUID test_guid = { - 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } - }; - CSSM_RETURN crtn; - CSSM_PVC_MODE pvc_policy = CSSM_PVC_NONE; - crtn = CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &test_guid, - CSSM_KEY_HIERARCHY_NONE, &pvc_policy, NULL); - if (crtn) { - NOTREACHED(); - return; - } - inited_ = true; - - crtn = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); - if (crtn) { - NOTREACHED(); - return; - } - csp_loaded_ = true; - crtn = CSSM_ModuleLoad( - &gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); - if (crtn) { - NOTREACHED(); - return; - } - cl_loaded_ = true; - crtn = CSSM_ModuleLoad( - &gGuidAppleX509TP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); - if (crtn) { - NOTREACHED(); - return; - } - tp_loaded_ = true; - - const CSSM_API_MEMORY_FUNCS cssmMemoryFunctions = { - CSSMMalloc, - CSSMFree, - CSSMRealloc, - CSSMCalloc, - NULL - }; - - crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &cssmMemoryFunctions, 0, - CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, - NULL, 0, NULL, &csp_handle_); - DCHECK_EQ(CSSM_OK, crtn); - crtn = CSSM_ModuleAttach(&gGuidAppleX509CL, &version, &cssmMemoryFunctions, - 0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE, - NULL, 0, NULL, &cl_handle_); - DCHECK_EQ(CSSM_OK, crtn); - crtn = CSSM_ModuleAttach(&gGuidAppleX509TP, &version, &cssmMemoryFunctions, - 0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE, - NULL, 0, NULL, &tp_handle_); - DCHECK_EQ(CSSM_OK, crtn); - } - - ~CSSMInitSingleton() { - CSSM_RETURN crtn; - if (csp_handle_) { - CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_); - DCHECK_EQ(CSSM_OK, crtn); - } - if (cl_handle_) { - CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_); - DCHECK_EQ(CSSM_OK, crtn); - } - if (tp_handle_) { - CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_); - DCHECK_EQ(CSSM_OK, crtn); - } - if (csp_loaded_) { - crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL); - DCHECK_EQ(CSSM_OK, crtn); - } - if (cl_loaded_) { - crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); - DCHECK_EQ(CSSM_OK, crtn); - } - if (tp_loaded_) { - crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); - DCHECK_EQ(CSSM_OK, crtn); - } - if (inited_) { - crtn = CSSM_Terminate(); - DCHECK_EQ(CSSM_OK, crtn); - } - } - - bool inited_; // True if CSSM_Init has been called successfully. - bool csp_loaded_; // True if gGuidAppleCSP has been loaded - bool cl_loaded_; // True if gGuidAppleX509CL has been loaded. - bool tp_loaded_; // True if gGuidAppleX509TP has been loaded. - CSSM_CSP_HANDLE csp_handle_; - CSSM_CL_HANDLE cl_handle_; - CSSM_TP_HANDLE tp_handle_; - - friend struct DefaultSingletonTraits; -}; - -} // namespace - -namespace crypto { - -void EnsureCSSMInit() { - CSSMInitSingleton::GetInstance(); -} - -CSSM_CSP_HANDLE GetSharedCSPHandle() { - return CSSMInitSingleton::GetInstance()->csp_handle(); -} - -CSSM_CL_HANDLE GetSharedCLHandle() { - return CSSMInitSingleton::GetInstance()->cl_handle(); -} - -CSSM_TP_HANDLE GetSharedTPHandle() { - return CSSMInitSingleton::GetInstance()->tp_handle(); -} - -void* CSSMMalloc(CSSM_SIZE size) { - return ::CSSMMalloc(size, NULL); -} - -void CSSMFree(void* ptr) { - ::CSSMFree(ptr, NULL); -} - -void LogCSSMError(const char* fn_name, CSSM_RETURN err) { - if (!err) - return; - base::ScopedCFTypeRef cfstr( - SecCopyErrorMessageString(err, NULL)); - LOG(ERROR) << fn_name << " returned " << err - << " (" << base::SysCFStringRefToUTF8(cfstr) << ")"; -} - -ScopedCSSMData::ScopedCSSMData() { - memset(&data_, 0, sizeof(data_)); -} - -ScopedCSSMData::~ScopedCSSMData() { - if (data_.Data) { - CSSMFree(data_.Data); - data_.Data = NULL; - } -} - -} // namespace crypto diff --git a/crypto/cssm_init.h b/crypto/cssm_init.h deleted file mode 100644 index e711099ef08e6..0000000000000 --- a/crypto/cssm_init.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 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_CSSM_INIT_H_ -#define CRYPTO_CSSM_INIT_H_ - -#include - -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// Initialize CSSM if it isn't already initialized. This must be called before -// any other CSSM functions. This function is thread-safe, and CSSM will only -// ever be initialized once. CSSM will be properly shut down on program exit. -CRYPTO_EXPORT void EnsureCSSMInit(); - -// Returns the shared CSP handle used by CSSM functions. -CRYPTO_EXPORT CSSM_CSP_HANDLE GetSharedCSPHandle(); - -// Returns the shared CL handle used by CSSM functions. -CRYPTO_EXPORT CSSM_CL_HANDLE GetSharedCLHandle(); - -// Returns the shared TP handle used by CSSM functions. -CRYPTO_EXPORT CSSM_TP_HANDLE GetSharedTPHandle(); - -// Set of pointers to memory function wrappers that are required for CSSM -extern const CSSM_API_MEMORY_FUNCS kCssmMemoryFunctions; - -// Utility function to log an error message including the error name. -CRYPTO_EXPORT void LogCSSMError(const char *function_name, CSSM_RETURN err); - -// Utility functions to allocate and release CSSM memory. -void* CSSMMalloc(CSSM_SIZE size); -CRYPTO_EXPORT void CSSMFree(void* ptr); - -// Wrapper class for CSSM_DATA type. This should only be used when using the -// CL/TP/CSP handles from above, since that's the only time we're guaranteed (or -// supposed to be guaranteed) that our memory management functions will be used. -// Apple's Sec* APIs manage their own memory so it shouldn't be used for those. -// The constructor initializes data_ to zero and the destructor releases the -// data properly. -class ScopedCSSMData { - public: - ScopedCSSMData(); - ~ScopedCSSMData(); - operator CSSM_DATA*() { return &data_; } - CSSM_DATA* operator ->() { return &data_; } - - private: - CSSM_DATA data_; - - DISALLOW_COPY_AND_ASSIGN(ScopedCSSMData); -}; - -} // namespace crypto - -#endif // CRYPTO_CSSM_INIT_H_ diff --git a/crypto/curve25519-donna.c b/crypto/curve25519-donna.c deleted file mode 100644 index f141ac028b0f7..0000000000000 --- a/crypto/curve25519-donna.c +++ /dev/null @@ -1,592 +0,0 @@ -// Copyright (c) 2013 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. - -/* - * curve25519-donna: Curve25519 elliptic curve, public key function - * - * http://code.google.com/p/curve25519-donna/ - * - * Adam Langley - * - * Derived from public domain C code by Daniel J. Bernstein - * - * More information about curve25519 can be found here - * http://cr.yp.to/ecdh.html - * - * djb's sample implementation of curve25519 is written in a special assembly - * language called qhasm and uses the floating point registers. - * - * This is, almost, a clean room reimplementation from the curve25519 paper. It - * uses many of the tricks described therein. Only the crecip function is taken - * from the sample implementation. - */ - -#include -#include - -typedef uint8_t u8; -typedef int32_t s32; -typedef int64_t limb; - -/* Field element representation: - * - * Field elements are written as an array of signed, 64-bit limbs, least - * significant first. The value of the field element is: - * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ... - * - * i.e. the limbs are 26, 25, 26, 25, ... bits wide. - */ - -/* Sum two numbers: output += in */ -static void fsum(limb *output, const limb *in) { - unsigned i; - for (i = 0; i < 10; i += 2) { - output[0+i] = (output[0+i] + in[0+i]); - output[1+i] = (output[1+i] + in[1+i]); - } -} - -/* Find the difference of two numbers: output = in - output - * (note the order of the arguments!) - */ -static void fdifference(limb *output, const limb *in) { - unsigned i; - for (i = 0; i < 10; ++i) { - output[i] = (in[i] - output[i]); - } -} - -/* Multiply a number my a scalar: output = in * scalar */ -static void fscalar_product(limb *output, const limb *in, const limb scalar) { - unsigned i; - for (i = 0; i < 10; ++i) { - output[i] = in[i] * scalar; - } -} - -/* Multiply two numbers: output = in2 * in - * - * output must be distinct to both inputs. The inputs are reduced coefficient - * form, the output is not. - */ -static void fproduct(limb *output, const limb *in2, const limb *in) { - output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); - output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + - ((limb) ((s32) in2[1])) * ((s32) in[0]); - output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[2]) + - ((limb) ((s32) in2[2])) * ((s32) in[0]); - output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + - ((limb) ((s32) in2[2])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[3]) + - ((limb) ((s32) in2[3])) * ((s32) in[0]); - output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + - 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + - ((limb) ((s32) in2[3])) * ((s32) in[1])) + - ((limb) ((s32) in2[0])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[0]); - output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + - ((limb) ((s32) in2[3])) * ((s32) in[2]) + - ((limb) ((s32) in2[1])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[0]); - output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + - ((limb) ((s32) in2[1])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[1])) + - ((limb) ((s32) in2[2])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[2]) + - ((limb) ((s32) in2[0])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[0]); - output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[3]) + - ((limb) ((s32) in2[2])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[2]) + - ((limb) ((s32) in2[1])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[0]); - output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) + - 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[3]) + - ((limb) ((s32) in2[1])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[1])) + - ((limb) ((s32) in2[2])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[2]) + - ((limb) ((s32) in2[0])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[0]); - output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[4]) + - ((limb) ((s32) in2[3])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[3]) + - ((limb) ((s32) in2[2])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[2]) + - ((limb) ((s32) in2[1])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[0]); - output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) + - ((limb) ((s32) in2[3])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[3]) + - ((limb) ((s32) in2[1])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[1])) + - ((limb) ((s32) in2[4])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[4]) + - ((limb) ((s32) in2[2])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[2]); - output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[5]) + - ((limb) ((s32) in2[4])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[4]) + - ((limb) ((s32) in2[3])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[3]) + - ((limb) ((s32) in2[2])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[2]); - output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) + - 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[5]) + - ((limb) ((s32) in2[3])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[3])) + - ((limb) ((s32) in2[4])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[4]); - output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[6]) + - ((limb) ((s32) in2[5])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[5]) + - ((limb) ((s32) in2[4])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[4]); - output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) + - ((limb) ((s32) in2[5])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[5])) + - ((limb) ((s32) in2[6])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[6]); - output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[7]) + - ((limb) ((s32) in2[6])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[6]); - output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[7])); - output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[8]); - output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); -} - -/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */ -static void freduce_degree(limb *output) { - /* Each of these shifts and adds ends up multiplying the value by 19. */ - output[8] += output[18] << 4; - output[8] += output[18] << 1; - output[8] += output[18]; - output[7] += output[17] << 4; - output[7] += output[17] << 1; - output[7] += output[17]; - output[6] += output[16] << 4; - output[6] += output[16] << 1; - output[6] += output[16]; - output[5] += output[15] << 4; - output[5] += output[15] << 1; - output[5] += output[15]; - output[4] += output[14] << 4; - output[4] += output[14] << 1; - output[4] += output[14]; - output[3] += output[13] << 4; - output[3] += output[13] << 1; - output[3] += output[13]; - output[2] += output[12] << 4; - output[2] += output[12] << 1; - output[2] += output[12]; - output[1] += output[11] << 4; - output[1] += output[11] << 1; - output[1] += output[11]; - output[0] += output[10] << 4; - output[0] += output[10] << 1; - output[0] += output[10]; -} - -/* Reduce all coefficients of the short form input so that |x| < 2^26. - * - * On entry: |output[i]| < 2^62 - */ -static void freduce_coefficients(limb *output) { - unsigned i; - do { - output[10] = 0; - - for (i = 0; i < 10; i += 2) { - limb over = output[i] / 0x4000000l; - output[i+1] += over; - output[i] -= over * 0x4000000l; - - over = output[i+1] / 0x2000000; - output[i+2] += over; - output[i+1] -= over * 0x2000000; - } - output[0] += 19 * output[10]; - } while (output[10]); -} - -/* A helpful wrapper around fproduct: output = in * in2. - * - * output must be distinct to both inputs. The output is reduced degree and - * reduced coefficient. - */ -static void -fmul(limb *output, const limb *in, const limb *in2) { - limb t[19]; - fproduct(t, in, in2); - freduce_degree(t); - freduce_coefficients(t); - memcpy(output, t, sizeof(limb) * 10); -} - -static void fsquare_inner(limb *output, const limb *in) { - output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); - output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); - output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + - ((limb) ((s32) in[0])) * ((s32) in[2])); - output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + - ((limb) ((s32) in[0])) * ((s32) in[3])); - output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + - 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + - 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); - output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + - ((limb) ((s32) in[1])) * ((s32) in[4]) + - ((limb) ((s32) in[0])) * ((s32) in[5])); - output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + - ((limb) ((s32) in[2])) * ((s32) in[4]) + - ((limb) ((s32) in[0])) * ((s32) in[6]) + - 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); - output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + - ((limb) ((s32) in[2])) * ((s32) in[5]) + - ((limb) ((s32) in[1])) * ((s32) in[6]) + - ((limb) ((s32) in[0])) * ((s32) in[7])); - output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + - 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + - ((limb) ((s32) in[0])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + - ((limb) ((s32) in[3])) * ((s32) in[5]))); - output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + - ((limb) ((s32) in[3])) * ((s32) in[6]) + - ((limb) ((s32) in[2])) * ((s32) in[7]) + - ((limb) ((s32) in[1])) * ((s32) in[8]) + - ((limb) ((s32) in[0])) * ((s32) in[9])); - output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + - ((limb) ((s32) in[4])) * ((s32) in[6]) + - ((limb) ((s32) in[2])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + - ((limb) ((s32) in[1])) * ((s32) in[9]))); - output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + - ((limb) ((s32) in[4])) * ((s32) in[7]) + - ((limb) ((s32) in[3])) * ((s32) in[8]) + - ((limb) ((s32) in[2])) * ((s32) in[9])); - output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + - 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + - ((limb) ((s32) in[3])) * ((s32) in[9]))); - output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + - ((limb) ((s32) in[5])) * ((s32) in[8]) + - ((limb) ((s32) in[4])) * ((s32) in[9])); - output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + - ((limb) ((s32) in[6])) * ((s32) in[8]) + - 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); - output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + - ((limb) ((s32) in[6])) * ((s32) in[9])); - output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + - 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); - output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); - output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); -} - -static void -fsquare(limb *output, const limb *in) { - limb t[19]; - fsquare_inner(t, in); - freduce_degree(t); - freduce_coefficients(t); - memcpy(output, t, sizeof(limb) * 10); -} - -/* Take a little-endian, 32-byte number and expand it into polynomial form */ -static void -fexpand(limb *output, const u8 *input) { -#define F(n,start,shift,mask) \ - output[n] = ((((limb) input[start + 0]) | \ - ((limb) input[start + 1]) << 8 | \ - ((limb) input[start + 2]) << 16 | \ - ((limb) input[start + 3]) << 24) >> shift) & mask; - F(0, 0, 0, 0x3ffffff); - F(1, 3, 2, 0x1ffffff); - F(2, 6, 3, 0x3ffffff); - F(3, 9, 5, 0x1ffffff); - F(4, 12, 6, 0x3ffffff); - F(5, 16, 0, 0x1ffffff); - F(6, 19, 1, 0x3ffffff); - F(7, 22, 3, 0x1ffffff); - F(8, 25, 4, 0x3ffffff); - F(9, 28, 6, 0x1ffffff); -#undef F -} - -/* Take a fully reduced polynomial form number and contract it into a - * little-endian, 32-byte array - */ -static void -fcontract(u8 *output, limb *input) { - int i; - - do { - for (i = 0; i < 9; ++i) { - if ((i & 1) == 1) { - while (input[i] < 0) { - input[i] += 0x2000000; - input[i + 1]--; - } - } else { - while (input[i] < 0) { - input[i] += 0x4000000; - input[i + 1]--; - } - } - } - while (input[9] < 0) { - input[9] += 0x2000000; - input[0] -= 19; - } - } while (input[0] < 0); - - input[1] <<= 2; - input[2] <<= 3; - input[3] <<= 5; - input[4] <<= 6; - input[6] <<= 1; - input[7] <<= 3; - input[8] <<= 4; - input[9] <<= 6; -#define F(i, s) \ - output[s+0] |= input[i] & 0xff; \ - output[s+1] = (input[i] >> 8) & 0xff; \ - output[s+2] = (input[i] >> 16) & 0xff; \ - output[s+3] = (input[i] >> 24) & 0xff; - output[0] = 0; - output[16] = 0; - F(0,0); - F(1,3); - F(2,6); - F(3,9); - F(4,12); - F(5,16); - F(6,19); - F(7,22); - F(8,25); - F(9,28); -#undef F -} - -/* Input: Q, Q', Q-Q' - * Output: 2Q, Q+Q' - * - * x2 z3: long form - * x3 z3: long form - * x z: short form, destroyed - * xprime zprime: short form, destroyed - * qmqp: short form, preserved - */ -static void fmonty(limb *x2, limb *z2, /* output 2Q */ - limb *x3, limb *z3, /* output Q + Q' */ - limb *x, limb *z, /* input Q */ - limb *xprime, limb *zprime, /* input Q' */ - const limb *qmqp /* input Q - Q' */) { - limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], - zzprime[19], zzzprime[19], xxxprime[19]; - - memcpy(origx, x, 10 * sizeof(limb)); - fsum(x, z); - fdifference(z, origx); // does x - z - - memcpy(origxprime, xprime, sizeof(limb) * 10); - fsum(xprime, zprime); - fdifference(zprime, origxprime); - fproduct(xxprime, xprime, z); - fproduct(zzprime, x, zprime); - freduce_degree(xxprime); - freduce_coefficients(xxprime); - freduce_degree(zzprime); - freduce_coefficients(zzprime); - memcpy(origxprime, xxprime, sizeof(limb) * 10); - fsum(xxprime, zzprime); - fdifference(zzprime, origxprime); - fsquare(xxxprime, xxprime); - fsquare(zzzprime, zzprime); - fproduct(zzprime, zzzprime, qmqp); - freduce_degree(zzprime); - freduce_coefficients(zzprime); - memcpy(x3, xxxprime, sizeof(limb) * 10); - memcpy(z3, zzprime, sizeof(limb) * 10); - - fsquare(xx, x); - fsquare(zz, z); - fproduct(x2, xx, zz); - freduce_degree(x2); - freduce_coefficients(x2); - fdifference(zz, xx); // does zz = xx - zz - memset(zzz + 10, 0, sizeof(limb) * 9); - fscalar_product(zzz, zz, 121665); - freduce_degree(zzz); - freduce_coefficients(zzz); - fsum(zzz, xx); - fproduct(z2, zz, zzz); - freduce_degree(z2); - freduce_coefficients(z2); -} - -/* Calculates nQ where Q is the x-coordinate of a point on the curve - * - * resultx/resultz: the x coordinate of the resulting curve point (short form) - * n: a little endian, 32-byte number - * q: a point of the curve (short form) - */ -static void -cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { - limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; - limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; - limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; - limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; - - unsigned i, j; - - memcpy(nqpqx, q, sizeof(limb) * 10); - - for (i = 0; i < 32; ++i) { - u8 byte = n[31 - i]; - for (j = 0; j < 8; ++j) { - if (byte & 0x80) { - fmonty(nqpqx2, nqpqz2, - nqx2, nqz2, - nqpqx, nqpqz, - nqx, nqz, - q); - } else { - fmonty(nqx2, nqz2, - nqpqx2, nqpqz2, - nqx, nqz, - nqpqx, nqpqz, - q); - } - - t = nqx; - nqx = nqx2; - nqx2 = t; - t = nqz; - nqz = nqz2; - nqz2 = t; - t = nqpqx; - nqpqx = nqpqx2; - nqpqx2 = t; - t = nqpqz; - nqpqz = nqpqz2; - nqpqz2 = t; - - byte <<= 1; - } - } - - memcpy(resultx, nqx, sizeof(limb) * 10); - memcpy(resultz, nqz, sizeof(limb) * 10); -} - -// ----------------------------------------------------------------------------- -// Shamelessly copied from djb's code -// ----------------------------------------------------------------------------- -static void -crecip(limb *out, const limb *z) { - limb z2[10]; - limb z9[10]; - limb z11[10]; - limb z2_5_0[10]; - limb z2_10_0[10]; - limb z2_20_0[10]; - limb z2_50_0[10]; - limb z2_100_0[10]; - limb t0[10]; - limb t1[10]; - int i; - - /* 2 */ fsquare(z2,z); - /* 4 */ fsquare(t1,z2); - /* 8 */ fsquare(t0,t1); - /* 9 */ fmul(z9,t0,z); - /* 11 */ fmul(z11,z9,z2); - /* 22 */ fsquare(t0,z11); - /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); - - /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); - /* 2^7 - 2^2 */ fsquare(t1,t0); - /* 2^8 - 2^3 */ fsquare(t0,t1); - /* 2^9 - 2^4 */ fsquare(t1,t0); - /* 2^10 - 2^5 */ fsquare(t0,t1); - /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); - - /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); - /* 2^12 - 2^2 */ fsquare(t1,t0); - /* 2^20 - 2^10 */ - for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); - - /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); - /* 2^22 - 2^2 */ fsquare(t1,t0); - /* 2^40 - 2^20 */ - for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); - - /* 2^41 - 2^1 */ fsquare(t1,t0); - /* 2^42 - 2^2 */ fsquare(t0,t1); - /* 2^50 - 2^10 */ - for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } - /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); - - /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); - /* 2^52 - 2^2 */ fsquare(t1,t0); - /* 2^100 - 2^50 */ - for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); - - /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); - /* 2^102 - 2^2 */ fsquare(t0,t1); - /* 2^200 - 2^100 */ - for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } - /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); - - /* 2^201 - 2^1 */ fsquare(t0,t1); - /* 2^202 - 2^2 */ fsquare(t1,t0); - /* 2^250 - 2^50 */ - for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); - - /* 2^251 - 2^1 */ fsquare(t1,t0); - /* 2^252 - 2^2 */ fsquare(t0,t1); - /* 2^253 - 2^3 */ fsquare(t1,t0); - /* 2^254 - 2^4 */ fsquare(t0,t1); - /* 2^255 - 2^5 */ fsquare(t1,t0); - /* 2^255 - 21 */ fmul(out,t1,z11); -} - -int -curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { - limb bp[10], x[10], z[10], zmone[10]; - uint8_t e[32]; - int i; - - for (i = 0; i < 32; ++i) e[i] = secret[i]; - e[0] &= 248; - e[31] &= 127; - e[31] |= 64; - - fexpand(bp, basepoint); - cmult(x, z, e, bp); - crecip(zmone, z); - fmul(z, x, zmone); - fcontract(mypublic, z); - return 0; -} diff --git a/crypto/curve25519.cc b/crypto/curve25519.cc deleted file mode 100644 index 3346df93a1ad7..0000000000000 --- a/crypto/curve25519.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2013 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/curve25519.h" - -// Curve25519 is specified in terms of byte strings, not numbers, so all -// implementations take and return the same sequence of bits. So the byte -// order is implicitly specified as in, say, SHA1. -// -// Prototype for |curve25519_donna| function in -// third_party/curve25519-donna/curve25519-donna.c -extern "C" int curve25519_donna(uint8*, const uint8*, const uint8*); - -namespace crypto { - -namespace curve25519 { - -void ScalarMult(const uint8* private_key, - const uint8* peer_public_key, - uint8* shared_key) { - curve25519_donna(shared_key, private_key, peer_public_key); -} - -// kBasePoint is the base point (generator) of the elliptic curve group. -// It is little-endian version of '9' followed by 31 zeros. -// See "Computing public keys" section of http://cr.yp.to/ecdh.html. -static const unsigned char kBasePoint[32] = {9}; - -void ScalarBaseMult(const uint8* private_key, uint8* public_key) { - curve25519_donna(public_key, private_key, kBasePoint); -} - -} // namespace curve25519 - -} // namespace crypto diff --git a/crypto/curve25519.h b/crypto/curve25519.h deleted file mode 100644 index ba24c92a8778e..0000000000000 --- a/crypto/curve25519.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2013 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_CURVE25519_H -#define CRYPTO_CURVE25519_H - -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// Curve25519 implements the elliptic curve group known as Curve25519, as -// described in "Curve 25519: new Diffie-Hellman Speed Records", -// by D.J. Bernstein. Additional information is available at -// http://cr.yp.to/ecdh.html. -namespace curve25519 { - -// kBytes is the number of bytes in the result of the Diffie-Hellman operation, -// which is an element of GF(2^255-19). -static const size_t kBytes = 32; - -// kScalarBytes is the number of bytes in an element of the scalar field: -// GF(2^252 + 27742317777372353535851937790883648493). -static const size_t kScalarBytes = 32; - -// ScalarMult computes the |shared_key| from |private_key| and -// |peer_public_key|. This method is a wrapper for |curve25519_donna()|. It -// calls that function with |private_key| as |secret| and |peer_public_key| as -// basepoint. |private_key| should be of length |kScalarBytes| and -// |peer_public_key| should be of length |kBytes|. -// See "Computing shared secrets" section of/ http://cr.yp.to/ecdh.html. -CRYPTO_EXPORT void ScalarMult(const uint8* private_key, - const uint8* peer_public_key, - uint8* shared_key); - -// ScalarBaseMult computes the |public_key| from |private_key|. This method is a -// wrapper for |curve25519_donna()|. It calls that function with |private_key| -// as |secret| and |kBasePoint| as basepoint. |private_key| should be of length -// |kScalarBytes|. See "Computing public keys" section of -// http://cr.yp.to/ecdh.html. -CRYPTO_EXPORT void ScalarBaseMult(const uint8* private_key, uint8* public_key); - -} // namespace curve25519 - -} // namespace crypto - -#endif // CRYPTO_CURVE25519_H diff --git a/crypto/curve25519_unittest.cc b/crypto/curve25519_unittest.cc deleted file mode 100644 index 0ddc4224a615a..0000000000000 --- a/crypto/curve25519_unittest.cc +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2013 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/curve25519.h" - -#include - -#include "crypto/random.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -// Test that the basic shared key exchange identity holds: that both parties end -// up with the same shared key. This test starts with a fixed private key for -// two parties: alice and bob. Runs ScalarBaseMult and ScalarMult to compute -// public key and shared key for alice and bob. It asserts that alice and bob -// have the same shared key. -TEST(Curve25519, SharedKeyIdentity) { - uint8 alice_private_key[curve25519::kScalarBytes] = {3}; - uint8 bob_private_key[curve25519::kScalarBytes] = {5}; - - // Get public key for alice and bob. - uint8 alice_public_key[curve25519::kBytes]; - curve25519::ScalarBaseMult(alice_private_key, alice_public_key); - - uint8 bob_public_key[curve25519::kBytes]; - curve25519::ScalarBaseMult(bob_private_key, bob_public_key); - - // Get the shared key for alice, by using alice's private key and bob's - // public key. - uint8 alice_shared_key[curve25519::kBytes]; - curve25519::ScalarMult(alice_private_key, bob_public_key, alice_shared_key); - - // Get the shared key for bob, by using bob's private key and alice's public - // key. - uint8 bob_shared_key[curve25519::kBytes]; - curve25519::ScalarMult(bob_private_key, alice_public_key, bob_shared_key); - - // Computed shared key of alice and bob should be the same. - ASSERT_EQ(0, memcmp(alice_shared_key, bob_shared_key, curve25519::kBytes)); -} - -} // namespace crypto diff --git a/crypto/ec_private_key.h b/crypto/ec_private_key.h deleted file mode 100644 index 87af838904ae6..0000000000000 --- a/crypto/ec_private_key.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2012 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_EC_PRIVATE_KEY_H_ -#define CRYPTO_EC_PRIVATE_KEY_H_ - -#include -#include - -#include "base/basictypes.h" -#include "build/build_config.h" -#include "crypto/crypto_export.h" - -#if defined(USE_OPENSSL) -// Forward declaration for openssl/*.h -typedef struct evp_pkey_st EVP_PKEY; -#else -// Forward declaration. -typedef struct CERTSubjectPublicKeyInfoStr CERTSubjectPublicKeyInfo; -typedef struct PK11SlotInfoStr PK11SlotInfo; -typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey; -typedef struct SECKEYPublicKeyStr SECKEYPublicKey; -#endif - -namespace crypto { - -// Encapsulates an elliptic curve (EC) private key. Can be used to generate new -// keys, export keys to other formats, or to extract a public key. -// TODO(mattm): make this and RSAPrivateKey implement some PrivateKey interface. -// (The difference in types of key() and public_key() make this a little -// tricky.) -class CRYPTO_EXPORT ECPrivateKey { - public: - ~ECPrivateKey(); - - // Returns whether the system supports elliptic curve cryptography. - static bool IsSupported(); - - // Creates a new random instance. Can return NULL if initialization fails. - // The created key will use the NIST P-256 curve. - // TODO(mattm): Add a curve parameter. - static ECPrivateKey* Create(); - - // Creates a new instance by importing an existing key pair. - // The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo - // block and an X.509 SubjectPublicKeyInfo block. - // Returns NULL if initialization fails. - static ECPrivateKey* CreateFromEncryptedPrivateKeyInfo( - const std::string& password, - const std::vector& encrypted_private_key_info, - const std::vector& subject_public_key_info); - -#if !defined(USE_OPENSSL) - // Imports the key pair into |slot| and returns in |public_key| and |key|. - // Shortcut for code that needs to keep a reference directly to NSS types - // without having to create a ECPrivateKey object and make a copy of them. - // TODO(mattm): move this function to some NSS util file. - static bool ImportFromEncryptedPrivateKeyInfo( - PK11SlotInfo* slot, - const std::string& password, - const uint8* encrypted_private_key_info, - size_t encrypted_private_key_info_len, - CERTSubjectPublicKeyInfo* decoded_spki, - bool permanent, - bool sensitive, - SECKEYPrivateKey** key, - SECKEYPublicKey** public_key); -#endif - - // Returns a copy of the object. - ECPrivateKey* Copy() const; - -#if defined(USE_OPENSSL) - EVP_PKEY* key() { return key_; } -#else - SECKEYPrivateKey* key() { return key_; } - SECKEYPublicKey* public_key() { return public_key_; } -#endif - - // Exports the private key as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo - // block and the public key as an X.509 SubjectPublicKeyInfo block. - // The |password| and |iterations| are used as inputs to the key derivation - // function for generating the encryption key. PKCS #5 recommends a minimum - // of 1000 iterations, on modern systems a larger value may be preferrable. - bool ExportEncryptedPrivateKey(const std::string& password, - int iterations, - std::vector* output); - - // Exports the public key to an X.509 SubjectPublicKeyInfo block. - bool ExportPublicKey(std::vector* output); - - // Exports the public key as an EC point in the uncompressed point format. - bool ExportRawPublicKey(std::string* output); - - // Exports private key data for testing. The format of data stored into output - // doesn't matter other than that it is consistent for the same key. - bool ExportValue(std::vector* output); - bool ExportECParams(std::vector* output); - - private: - // Constructor is private. Use one of the Create*() methods above instead. - ECPrivateKey(); - -#if defined(USE_OPENSSL) - EVP_PKEY* key_; -#else - SECKEYPrivateKey* key_; - SECKEYPublicKey* public_key_; -#endif - - DISALLOW_COPY_AND_ASSIGN(ECPrivateKey); -}; - - -} // namespace crypto - -#endif // CRYPTO_EC_PRIVATE_KEY_H_ diff --git a/crypto/ec_private_key_nss.cc b/crypto/ec_private_key_nss.cc deleted file mode 100644 index 5092010c939b5..0000000000000 --- a/crypto/ec_private_key_nss.cc +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2012 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/ec_private_key.h" - -extern "C" { -// Work around NSS missing SEC_BEGIN_PROTOS in secmodt.h. This must come before -// other NSS headers. -#include -} - -#include -#include -#include -#include - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "crypto/nss_util.h" -#include "crypto/nss_util_internal.h" -#include "crypto/scoped_nss_types.h" -#include "crypto/third_party/nss/chromium-nss.h" - -namespace { - -PK11SlotInfo* GetTempKeySlot() { - return PK11_GetInternalSlot(); -} - -class EllipticCurveSupportChecker { - public: - EllipticCurveSupportChecker() { - // NOTE: we can do this check here only because we use the NSS internal - // slot. If we support other slots in the future, checking whether they - // support ECDSA may block NSS, and the value may also change as devices are - // inserted/removed, so we would need to re-check on every use. - crypto::EnsureNSSInit(); - crypto::ScopedPK11Slot slot(GetTempKeySlot()); - supported_ = PK11_DoesMechanism(slot.get(), CKM_EC_KEY_PAIR_GEN) && - PK11_DoesMechanism(slot.get(), CKM_ECDSA); - } - - bool Supported() { - return supported_; - } - - private: - bool supported_; -}; - -static base::LazyInstance::Leaky - g_elliptic_curve_supported = LAZY_INSTANCE_INITIALIZER; - -// Copied from rsa_private_key_nss.cc. -static bool ReadAttribute(SECKEYPrivateKey* key, - CK_ATTRIBUTE_TYPE type, - std::vector* output) { - SECItem item; - SECStatus rv; - rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); - if (rv != SECSuccess) { - DLOG(ERROR) << "PK11_ReadRawAttribute: " << PORT_GetError(); - return false; - } - - output->assign(item.data, item.data + item.len); - SECITEM_FreeItem(&item, PR_FALSE); - return true; -} - -} // namespace - -namespace crypto { - -ECPrivateKey::~ECPrivateKey() { - if (key_) - SECKEY_DestroyPrivateKey(key_); - if (public_key_) - SECKEY_DestroyPublicKey(public_key_); -} - -// static -bool ECPrivateKey::IsSupported() { - return g_elliptic_curve_supported.Get().Supported(); -} - -// static -ECPrivateKey* ECPrivateKey::Create() { - EnsureNSSInit(); - - ScopedPK11Slot slot(GetTempKeySlot()); - if (!slot) - return nullptr; - - scoped_ptr result(new ECPrivateKey); - - SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); - if (!oid_data) { - DLOG(ERROR) << "SECOID_FindOIDByTag: " << PORT_GetError(); - return nullptr; - } - - // SECKEYECParams is a SECItem containing the DER encoded ASN.1 ECParameters - // value. For a named curve, that is just the OBJECT IDENTIFIER of the curve. - // In addition to the oid data, the encoding requires one byte for the ASN.1 - // tag and one byte for the length (assuming the length is <= 127). - CHECK_LE(oid_data->oid.len, 127U); - std::vector parameters_buf(2 + oid_data->oid.len); - SECKEYECParams ec_parameters = { - siDEROID, ¶meters_buf[0], - static_cast(parameters_buf.size()) - }; - - ec_parameters.data[0] = SEC_ASN1_OBJECT_ID; - ec_parameters.data[1] = static_cast(oid_data->oid.len); - memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len); - - result->key_ = PK11_GenerateKeyPair(slot.get(), - CKM_EC_KEY_PAIR_GEN, - &ec_parameters, - &result->public_key_, - PR_FALSE /* not permanent */, - PR_FALSE /* not sensitive */, - NULL); - if (!result->key_) { - DLOG(ERROR) << "PK11_GenerateKeyPair: " << PORT_GetError(); - return nullptr; - } - CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_)); - - return result.release(); -} - -// static -ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - const std::string& password, - const std::vector& encrypted_private_key_info, - const std::vector& subject_public_key_info) { - EnsureNSSInit(); - - ScopedPK11Slot slot(GetTempKeySlot()); - if (!slot) - return nullptr; - - scoped_ptr result(new ECPrivateKey); - - SECItem encoded_spki = { - siBuffer, - const_cast(&subject_public_key_info[0]), - static_cast(subject_public_key_info.size()) - }; - CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( - &encoded_spki); - if (!decoded_spki) { - DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); - return nullptr; - } - - bool success = ImportFromEncryptedPrivateKeyInfo( - slot.get(), - password, - &encrypted_private_key_info[0], - encrypted_private_key_info.size(), - decoded_spki, - false /* not permanent */, - false /* not sensitive */, - &result->key_, - &result->public_key_); - - SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); - - if (success) { - CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_)); - return result.release(); - } - - return nullptr; -} - -// static -bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( - PK11SlotInfo* slot, - const std::string& password, - const uint8* encrypted_private_key_info, - size_t encrypted_private_key_info_len, - CERTSubjectPublicKeyInfo* decoded_spki, - bool permanent, - bool sensitive, - SECKEYPrivateKey** key, - SECKEYPublicKey** public_key) { - if (!slot) - return false; - - *public_key = SECKEY_ExtractPublicKey(decoded_spki); - - if (!*public_key) { - DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); - return false; - } - - if (SECKEY_GetPublicKeyType(*public_key) != ecKey) { - DLOG(ERROR) << "The public key is not an EC key"; - SECKEY_DestroyPublicKey(*public_key); - *public_key = NULL; - return false; - } - - SECItem encoded_epki = { - siBuffer, - const_cast(encrypted_private_key_info), - static_cast(encrypted_private_key_info_len) - }; - SECKEYEncryptedPrivateKeyInfo epki; - memset(&epki, 0, sizeof(epki)); - - ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); - - SECStatus rv = SEC_QuickDERDecodeItem( - arena.get(), - &epki, - SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), - &encoded_epki); - if (rv != SECSuccess) { - DLOG(ERROR) << "SEC_QuickDERDecodeItem: " << PORT_GetError(); - SECKEY_DestroyPublicKey(*public_key); - *public_key = NULL; - return false; - } - - SECItem password_item = { - siBuffer, - reinterpret_cast(const_cast(password.data())), - static_cast(password.size()) - }; - - rv = ImportEncryptedECPrivateKeyInfoAndReturnKey( - slot, - &epki, - &password_item, - NULL, // nickname - &(*public_key)->u.ec.publicValue, - permanent, - sensitive, - key, - NULL); // wincx - if (rv != SECSuccess) { - DLOG(ERROR) << "ImportEncryptedECPrivateKeyInfoAndReturnKey: " - << PORT_GetError(); - SECKEY_DestroyPublicKey(*public_key); - *public_key = NULL; - return false; - } - - return true; -} - -ECPrivateKey* ECPrivateKey::Copy() const { - scoped_ptr copy(new ECPrivateKey); - if (key_) { - copy->key_ = SECKEY_CopyPrivateKey(key_); - if (!copy->key_) - return NULL; - } - if (public_key_) { - copy->public_key_ = SECKEY_CopyPublicKey(public_key_); - if (!copy->public_key_) - return NULL; - } - return copy.release(); -} - -bool ECPrivateKey::ExportEncryptedPrivateKey( - const std::string& password, - int iterations, - std::vector* output) { - // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8 - // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't - // support EC keys. - // https://bugzilla.mozilla.org/show_bug.cgi?id=327773 - SECItem password_item = { - siBuffer, - reinterpret_cast(const_cast(password.data())), - static_cast(password.size()) - }; - - SECKEYEncryptedPrivateKeyInfo* encrypted = PK11_ExportEncryptedPrivKeyInfo( - NULL, // Slot, optional. - SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, - &password_item, - key_, - iterations, - NULL); // wincx. - - if (!encrypted) { - DLOG(ERROR) << "PK11_ExportEncryptedPrivKeyInfo: " << PORT_GetError(); - return false; - } - - ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); - SECItem der_key = {siBuffer, NULL, 0}; - SECItem* encoded_item = SEC_ASN1EncodeItem( - arena.get(), - &der_key, - encrypted, - SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate)); - SECKEY_DestroyEncryptedPrivateKeyInfo(encrypted, PR_TRUE); - if (!encoded_item) { - DLOG(ERROR) << "SEC_ASN1EncodeItem: " << PORT_GetError(); - return false; - } - - output->assign(der_key.data, der_key.data + der_key.len); - - return true; -} - -bool ECPrivateKey::ExportPublicKey(std::vector* output) { - ScopedSECItem der_pubkey( - SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); - if (!der_pubkey.get()) { - return false; - } - - output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len); - return true; -} - -bool ECPrivateKey::ExportRawPublicKey(std::string* output) { - // public_key_->u.ec.publicValue is an ANSI X9.62 public key which, for - // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field - // elements as 32-byte, big-endian numbers. - static const unsigned int kExpectedKeyLength = 65; - - CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(public_key_)); - const unsigned char* const data = public_key_->u.ec.publicValue.data; - const unsigned int len = public_key_->u.ec.publicValue.len; - if (len != kExpectedKeyLength || data[0] != 0x04) - return false; - - output->assign(reinterpret_cast(data + 1), - kExpectedKeyLength - 1); - return true; -} - -bool ECPrivateKey::ExportValue(std::vector* output) { - return ReadAttribute(key_, CKA_VALUE, output); -} - -bool ECPrivateKey::ExportECParams(std::vector* output) { - return ReadAttribute(key_, CKA_EC_PARAMS, output); -} - -ECPrivateKey::ECPrivateKey() : key_(NULL), public_key_(NULL) {} - -} // namespace crypto diff --git a/crypto/ec_private_key_openssl.cc b/crypto/ec_private_key_openssl.cc deleted file mode 100644 index 35403f39ce885..0000000000000 --- a/crypto/ec_private_key_openssl.cc +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2012 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/ec_private_key.h" - -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" - -namespace crypto { - -namespace { - -// Function pointer definition, for injecting the required key export function -// into ExportKeyWithBio, below. |bio| is a temporary memory BIO object, and -// |key| is a handle to the input key object. Return 1 on success, 0 otherwise. -// NOTE: Used with OpenSSL functions, which do not comply with the Chromium -// style guide, hence the unusual parameter placement / types. -typedef int (*ExportBioFunction)(BIO* bio, const void* key); - -using ScopedPKCS8_PRIV_KEY_INFO = - ScopedOpenSSL; -using ScopedX509_SIG = ScopedOpenSSL; - -// Helper to export |key| into |output| via the specified ExportBioFunction. -bool ExportKeyWithBio(const void* key, - ExportBioFunction export_fn, - std::vector* output) { - if (!key) - return false; - - ScopedBIO bio(BIO_new(BIO_s_mem())); - if (!bio.get()) - return false; - - if (!export_fn(bio.get(), key)) - return false; - - char* data = NULL; - long len = BIO_get_mem_data(bio.get(), &data); - if (!data || len < 0) - return false; - - output->assign(data, data + len); - return true; -} - -// Function pointer definition, for injecting the required key export function -// into ExportKey below. |key| is a pointer to the input key object, -// and |data| is either NULL, or the address of an 'unsigned char*' pointer -// that points to the start of the output buffer. The function must return -// the number of bytes required to export the data, or -1 in case of error. -typedef int (*ExportDataFunction)(const void* key, unsigned char** data); - -// Helper to export |key| into |output| via the specified export function. -bool ExportKey(const void* key, - ExportDataFunction export_fn, - std::vector* output) { - if (!key) - return false; - - int data_len = export_fn(key, NULL); - if (data_len < 0) - return false; - - output->resize(static_cast(data_len)); - unsigned char* data = &(*output)[0]; - if (export_fn(key, &data) < 0) - return false; - - return true; -} - -} // namespace - -ECPrivateKey::~ECPrivateKey() { - if (key_) - EVP_PKEY_free(key_); -} - -ECPrivateKey* ECPrivateKey::Copy() const { - scoped_ptr copy(new ECPrivateKey); - if (key_) - copy->key_ = EVP_PKEY_up_ref(key_); - return copy.release(); -} - -// static -bool ECPrivateKey::IsSupported() { return true; } - -// static -ECPrivateKey* ECPrivateKey::Create() { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - ScopedEC_KEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); - if (!ec_key.get() || !EC_KEY_generate_key(ec_key.get())) - return NULL; - - scoped_ptr result(new ECPrivateKey()); - result->key_ = EVP_PKEY_new(); - if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_, ec_key.get())) - return NULL; - - CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_type(result->key_->type)); - return result.release(); -} - -// static -ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - const std::string& password, - const std::vector& encrypted_private_key_info, - const std::vector& subject_public_key_info) { - // NOTE: The |subject_public_key_info| can be ignored here, it is only - // useful for the NSS implementation (which uses the public key's SHA1 - // as a lookup key when storing the private one in its store). - if (encrypted_private_key_info.empty()) - return NULL; - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - const uint8_t* data = &encrypted_private_key_info[0]; - const uint8_t* ptr = data; - ScopedX509_SIG p8_encrypted( - d2i_X509_SIG(NULL, &ptr, encrypted_private_key_info.size())); - if (!p8_encrypted || ptr != data + encrypted_private_key_info.size()) - return NULL; - - ScopedPKCS8_PRIV_KEY_INFO p8_decrypted; - if (password.empty()) { - // Hack for reading keys generated by an older version of the OpenSSL - // code. OpenSSL used to use "\0\0" rather than the empty string because it - // would treat the password as an ASCII string to be converted to UCS-2 - // while NSS used a byte string. - p8_decrypted.reset(PKCS8_decrypt_pbe( - p8_encrypted.get(), reinterpret_cast("\0\0"), 2)); - } - if (!p8_decrypted) { - p8_decrypted.reset(PKCS8_decrypt_pbe( - p8_encrypted.get(), - reinterpret_cast(password.data()), - password.size())); - } - - if (!p8_decrypted) - return NULL; - - // Create a new EVP_PKEY for it. - scoped_ptr result(new ECPrivateKey); - result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); - if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) - return NULL; - - return result.release(); -} - -bool ECPrivateKey::ExportEncryptedPrivateKey( - const std::string& password, - int iterations, - std::vector* output) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - // Convert into a PKCS#8 object. - ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); - if (!pkcs8.get()) - return false; - - // Encrypt the object. - // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC - // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL - // equivalent. - ScopedX509_SIG encrypted(PKCS8_encrypt_pbe( - NID_pbe_WithSHA1And3_Key_TripleDES_CBC, - reinterpret_cast(password.data()), - password.size(), - NULL, - 0, - iterations, - pkcs8.get())); - if (!encrypted.get()) - return false; - - // Write it into |*output| - return ExportKeyWithBio(encrypted.get(), - reinterpret_cast(i2d_PKCS8_bio), - output); -} - -bool ECPrivateKey::ExportPublicKey(std::vector* output) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - return ExportKeyWithBio( - key_, reinterpret_cast(i2d_PUBKEY_bio), output); -} - -bool ECPrivateKey::ExportRawPublicKey(std::string* output) { - // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 - // key, is 0x04 (meaning uncompressed) followed by the x and y field - // elements as 32-byte, big-endian numbers. - static const int kExpectedKeyLength = 65; - - int len = i2d_PublicKey(key_, NULL); - if (len != kExpectedKeyLength) - return false; - - uint8 buf[kExpectedKeyLength]; - uint8* derp = buf; - len = i2d_PublicKey(key_, &derp); - if (len != kExpectedKeyLength) - return false; - - output->assign(reinterpret_cast(buf + 1), kExpectedKeyLength - 1); - return true; -} - -bool ECPrivateKey::ExportValue(std::vector* output) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); - return ExportKey(ec_key.get(), - reinterpret_cast(i2d_ECPrivateKey), - output); -} - -bool ECPrivateKey::ExportECParams(std::vector* output) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); - return ExportKey(ec_key.get(), - reinterpret_cast(i2d_ECParameters), - output); -} - -ECPrivateKey::ECPrivateKey() : key_(NULL) {} - -} // namespace crypto diff --git a/crypto/ec_private_key_unittest.cc b/crypto/ec_private_key_unittest.cc deleted file mode 100644 index cfd08f2d92b57..0000000000000 --- a/crypto/ec_private_key_unittest.cc +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (c) 2011 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/ec_private_key.h" - -#include - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -// Generate random private keys. Export, then re-import. We should get -// back the same exact public key, and the private key should have the same -// value and elliptic curve params. -TEST(ECPrivateKeyUnitTest, InitRandomTest) { - const std::string password1; - const std::string password2 = "test"; - - scoped_ptr keypair1(crypto::ECPrivateKey::Create()); - scoped_ptr keypair2(crypto::ECPrivateKey::Create()); - ASSERT_TRUE(keypair1.get()); - ASSERT_TRUE(keypair2.get()); - - std::vector key1value; - std::vector key2value; - std::vector key1params; - std::vector key2params; - EXPECT_TRUE(keypair1->ExportValue(&key1value)); - EXPECT_TRUE(keypair2->ExportValue(&key2value)); - EXPECT_TRUE(keypair1->ExportECParams(&key1params)); - EXPECT_TRUE(keypair2->ExportECParams(&key2params)); - - std::vector privkey1; - std::vector privkey2; - std::vector pubkey1; - std::vector pubkey2; - std::string raw_pubkey1; - std::string raw_pubkey2; - ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey(password1, 1, &privkey1)); - ASSERT_TRUE(keypair2->ExportEncryptedPrivateKey(password2, 1, &privkey2)); - EXPECT_TRUE(keypair1->ExportPublicKey(&pubkey1)); - EXPECT_TRUE(keypair2->ExportPublicKey(&pubkey2)); - EXPECT_TRUE(keypair1->ExportRawPublicKey(&raw_pubkey1)); - EXPECT_TRUE(keypair2->ExportRawPublicKey(&raw_pubkey2)); - - scoped_ptr keypair3( - crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - password1, privkey1, pubkey1)); - scoped_ptr keypair4( - crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - password2, privkey2, pubkey2)); - ASSERT_TRUE(keypair3.get()); - ASSERT_TRUE(keypair4.get()); - - std::vector key3value; - std::vector key4value; - std::vector key3params; - std::vector key4params; - EXPECT_TRUE(keypair3->ExportValue(&key3value)); - EXPECT_TRUE(keypair4->ExportValue(&key4value)); - EXPECT_TRUE(keypair3->ExportECParams(&key3params)); - EXPECT_TRUE(keypair4->ExportECParams(&key4params)); - - EXPECT_EQ(key1value, key3value); - EXPECT_EQ(key2value, key4value); - EXPECT_EQ(key1params, key3params); - EXPECT_EQ(key2params, key4params); - - std::vector pubkey3; - std::vector pubkey4; - std::string raw_pubkey3; - std::string raw_pubkey4; - EXPECT_TRUE(keypair3->ExportPublicKey(&pubkey3)); - EXPECT_TRUE(keypair4->ExportPublicKey(&pubkey4)); - EXPECT_TRUE(keypair3->ExportRawPublicKey(&raw_pubkey3)); - EXPECT_TRUE(keypair4->ExportRawPublicKey(&raw_pubkey4)); - - EXPECT_EQ(pubkey1, pubkey3); - EXPECT_EQ(pubkey2, pubkey4); - EXPECT_EQ(raw_pubkey1, raw_pubkey3); - EXPECT_EQ(raw_pubkey2, raw_pubkey4); -} - -TEST(ECPrivateKeyUnitTest, Copy) { - scoped_ptr keypair1(crypto::ECPrivateKey::Create()); - scoped_ptr keypair2(keypair1->Copy()); - ASSERT_TRUE(keypair1.get()); - ASSERT_TRUE(keypair2.get()); - - std::vector key1value; - std::vector key2value; - EXPECT_TRUE(keypair1->ExportValue(&key1value)); - EXPECT_TRUE(keypair2->ExportValue(&key2value)); - EXPECT_EQ(key1value, key2value); - - std::vector key1params; - std::vector key2params; - EXPECT_TRUE(keypair1->ExportECParams(&key1params)); - EXPECT_TRUE(keypair2->ExportECParams(&key2params)); - EXPECT_EQ(key1params, key2params); - - std::vector pubkey1; - std::vector pubkey2; - EXPECT_TRUE(keypair1->ExportPublicKey(&pubkey1)); - EXPECT_TRUE(keypair2->ExportPublicKey(&pubkey2)); - EXPECT_EQ(pubkey1, pubkey2); - - std::string raw_pubkey1; - std::string raw_pubkey2; - EXPECT_TRUE(keypair1->ExportRawPublicKey(&raw_pubkey1)); - EXPECT_TRUE(keypair2->ExportRawPublicKey(&raw_pubkey2)); - EXPECT_EQ(raw_pubkey1, raw_pubkey2); -} - -TEST(ECPrivateKeyUnitTest, BadPasswordTest) { - const std::string password1; - const std::string password2 = "test"; - - scoped_ptr keypair1( - crypto::ECPrivateKey::Create()); - ASSERT_TRUE(keypair1.get()); - - std::vector privkey1; - std::vector pubkey1; - ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey( - password1, 1, &privkey1)); - ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1)); - - scoped_ptr keypair2( - crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - password2, privkey1, pubkey1)); - ASSERT_FALSE(keypair2.get()); -} - -TEST(ECPrivateKeyUnitTest, LoadNSSKeyTest) { - static const unsigned char nss_key[] = { - 0x30, 0x81, 0xb8, 0x30, 0x23, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x15, 0x04, 0x10, 0x3f, 0xac, 0xe9, - 0x38, 0xdb, 0x40, 0x6b, 0x26, 0x89, 0x09, 0x73, 0x18, 0x8d, 0x7f, 0x1c, - 0x82, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0x5e, 0x5e, 0x11, 0xef, 0xbb, - 0x7c, 0x4d, 0xec, 0xc0, 0xdc, 0xc7, 0x23, 0xd2, 0xc4, 0x77, 0xbc, 0xf4, - 0x5d, 0x59, 0x4c, 0x07, 0xc2, 0x8a, 0x26, 0xfa, 0x25, 0x1c, 0xaa, 0x42, - 0xed, 0xd0, 0xed, 0xbb, 0x5c, 0xe9, 0x13, 0x07, 0xaa, 0xdd, 0x52, 0x3c, - 0x65, 0x25, 0xbf, 0x94, 0x02, 0xaf, 0xd6, 0x97, 0xe9, 0x33, 0x00, 0x76, - 0x64, 0x4a, 0x73, 0xab, 0xfb, 0x99, 0x6e, 0x83, 0x12, 0x05, 0x86, 0x72, - 0x6c, 0xd5, 0xa4, 0xcf, 0xb1, 0xd5, 0x4d, 0x54, 0x87, 0x8b, 0x4b, 0x95, - 0x1d, 0xcd, 0xf3, 0xfe, 0xa8, 0xda, 0xe0, 0xb6, 0x72, 0x13, 0x3f, 0x2e, - 0x66, 0xe0, 0xb9, 0x2e, 0xfa, 0x69, 0x40, 0xbe, 0xd7, 0x67, 0x6e, 0x53, - 0x2b, 0x3f, 0x53, 0xe5, 0x39, 0x54, 0x77, 0xe1, 0x1d, 0xe6, 0x81, 0x92, - 0x58, 0x82, 0x14, 0xfb, 0x47, 0x85, 0x3c, 0xc3, 0xdf, 0xdd, 0xcc, 0x79, - 0x9f, 0x41, 0x83, 0x72, 0xf2, 0x0a, 0xe9, 0xe1, 0x2c, 0x12, 0xb0, 0xb0, - 0x0a, 0xb2, 0x1d, 0xca, 0x15, 0xb2, 0xca}; - static const unsigned char nss_pub_key[] = { - 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, - 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, - 0x42, 0x00, 0x04, 0x85, 0x92, 0x9e, 0x95, 0x5c, 0x6b, 0x9e, 0xd6, 0x1e, - 0xb8, 0x64, 0xea, 0xc2, 0xb3, 0xef, 0x18, 0xed, 0x3a, 0x5e, 0xc4, 0x5c, - 0x15, 0x37, 0x6a, 0xe9, 0xaa, 0x0b, 0x34, 0x03, 0xfd, 0xca, 0x83, 0x0f, - 0xd7, 0x5c, 0x5d, 0xc5, 0x53, 0x6e, 0xe5, 0xa9, 0x33, 0xd5, 0xcc, 0xab, - 0x53, 0x78, 0xdd, 0xd6, 0x12, 0x3a, 0x5e, 0xeb, 0xbf, 0xdf, 0x16, 0xd3, - 0x2c, 0x3b, 0xe8, 0xdb, 0x19, 0xfc, 0x5e}; - - scoped_ptr keypair_nss( - crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - "", - std::vector(nss_key, nss_key + arraysize(nss_key)), - std::vector(nss_pub_key, - nss_pub_key + arraysize(nss_pub_key)))); - - EXPECT_TRUE(keypair_nss.get()); -} - -// Although the plan is to transition from OpenSSL to NSS, ensure NSS can import -// OpenSSL's format so that it is possible to rollback. -TEST(ECPrivateKeyUnitTest, LoadOpenSSLKeyTest) { - static const unsigned char openssl_key[] = { - 0x30, 0x81, 0xb0, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0xb2, 0xfe, 0x68, - 0xc2, 0xea, 0x0f, 0x10, 0x9c, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0xe2, - 0xf6, 0x1c, 0xca, 0xad, 0x64, 0x30, 0xbf, 0x88, 0x04, 0x35, 0xe5, 0x0f, - 0x11, 0x49, 0x06, 0x01, 0x14, 0x33, 0x80, 0xa2, 0x78, 0x44, 0x5b, 0xaa, - 0x0d, 0xd7, 0x00, 0x36, 0x9d, 0x91, 0x97, 0x37, 0x20, 0x7b, 0x27, 0xc1, - 0xa0, 0xa2, 0x73, 0x06, 0x15, 0xdf, 0xc8, 0x13, 0x9b, 0xc9, 0x8c, 0x9c, - 0xce, 0x00, 0xd0, 0xc8, 0x42, 0xc1, 0xda, 0x2b, 0x07, 0x2b, 0x12, 0xa3, - 0xce, 0x10, 0x39, 0x7a, 0xf1, 0x55, 0x69, 0x8d, 0xa5, 0xc4, 0x2a, 0x00, - 0x0d, 0x94, 0xc6, 0xde, 0x6a, 0x3d, 0xb7, 0xe5, 0x6d, 0x59, 0x3e, 0x09, - 0xb5, 0xe3, 0x3e, 0xfc, 0x50, 0x56, 0xe9, 0x50, 0x42, 0x7c, 0xe7, 0xf0, - 0x19, 0xbd, 0x31, 0xa7, 0x85, 0x47, 0xb3, 0xe9, 0xb3, 0x50, 0x3c, 0xc9, - 0x32, 0x37, 0x1a, 0x93, 0x78, 0x48, 0x78, 0x82, 0xde, 0xad, 0x5c, 0xf2, - 0xcf, 0xf2, 0xbb, 0x2c, 0x44, 0x05, 0x7f, 0x4a, 0xf9, 0xb1, 0x2b, 0xdd, - 0x49, 0xf6, 0x7e, 0xd0, 0x42, 0xaa, 0x14, 0x3c, 0x24, 0x77, 0xb4}; - static const unsigned char openssl_pub_key[] = { - 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, - 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, - 0x42, 0x00, 0x04, 0xb9, 0xda, 0x0d, 0x71, 0x60, 0xb3, 0x63, 0x28, 0x22, - 0x67, 0xe7, 0xe0, 0xa3, 0xf8, 0x00, 0x8e, 0x4c, 0x89, 0xed, 0x31, 0x34, - 0xf6, 0xdb, 0xc4, 0xfe, 0x0b, 0x5d, 0xe1, 0x11, 0x39, 0x49, 0xa6, 0x50, - 0xa8, 0xe3, 0x4a, 0xc0, 0x40, 0x88, 0xb8, 0x38, 0x3f, 0x56, 0xfb, 0x33, - 0x8d, 0xd4, 0x64, 0x91, 0xd6, 0x15, 0x77, 0x42, 0x27, 0xc5, 0xaa, 0x44, - 0xff, 0xab, 0x4d, 0xb5, 0x7e, 0x25, 0x3d}; - - scoped_ptr keypair_openssl( - crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - "", - std::vector(openssl_key, openssl_key + arraysize(openssl_key)), - std::vector(openssl_pub_key, - openssl_pub_key + arraysize(openssl_pub_key)))); - - EXPECT_TRUE(keypair_openssl.get()); -} - -// The Android code writes out Channel IDs differently from the NSS -// implementation; the empty password is converted to "\0\0". The OpenSSL port -// should support either. -#if defined(USE_OPENSSL) -TEST(ECPrivateKeyUnitTest, LoadOldOpenSSLKeyTest) { - static const unsigned char openssl_key[] = { - 0x30, 0x82, 0x01, 0xa1, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0x86, 0xaa, - 0xd7, 0xdf, 0x3b, 0x91, 0x97, 0x60, 0x02, 0x01, 0x01, 0x04, 0x82, 0x01, - 0x80, 0xcb, 0x2a, 0x14, 0xaa, 0x4f, 0x38, 0x4c, 0xe1, 0x49, 0x00, 0xe2, - 0x1a, 0x3a, 0x75, 0x87, 0x7e, 0x3d, 0xea, 0x4d, 0x53, 0xd4, 0x46, 0x47, - 0x23, 0x8f, 0xa1, 0x72, 0x51, 0x92, 0x86, 0x8b, 0xeb, 0x53, 0xe6, 0x6a, - 0x0a, 0x6b, 0xb6, 0xa0, 0xdc, 0x0f, 0xdc, 0x20, 0xc3, 0x45, 0x85, 0xf1, - 0x95, 0x90, 0x5c, 0xf4, 0xfa, 0xee, 0x47, 0xaf, 0x35, 0xd0, 0xd0, 0xd3, - 0x14, 0xde, 0x0d, 0xca, 0x1b, 0xd3, 0xbb, 0x20, 0xec, 0x9d, 0x6a, 0xd4, - 0xc1, 0xce, 0x60, 0x81, 0xab, 0x0c, 0x72, 0x10, 0xfa, 0x28, 0x3c, 0xac, - 0x87, 0x7b, 0x82, 0x85, 0x00, 0xb8, 0x58, 0x9c, 0x07, 0xc4, 0x7d, 0xa9, - 0xc5, 0x94, 0x95, 0xf7, 0x23, 0x93, 0x3f, 0xed, 0xef, 0x92, 0x55, 0x25, - 0x74, 0xbb, 0xd3, 0xd1, 0x67, 0x3b, 0x3d, 0x5a, 0xfe, 0x84, 0xf8, 0x97, - 0x7d, 0x7c, 0x01, 0xc7, 0xd7, 0x0d, 0xf8, 0xc3, 0x6d, 0xd6, 0xf1, 0xaa, - 0x9d, 0x1f, 0x69, 0x97, 0x45, 0x06, 0xc4, 0x1c, 0x95, 0x3c, 0xe0, 0xef, - 0x11, 0xb2, 0xb3, 0x72, 0x91, 0x9e, 0x7d, 0x0f, 0x7f, 0xc8, 0xf6, 0x64, - 0x49, 0x5e, 0x3c, 0x53, 0x37, 0x79, 0x03, 0x1c, 0x3f, 0x29, 0x6c, 0x6b, - 0xea, 0x4c, 0x35, 0x9b, 0x6d, 0x1b, 0x59, 0x43, 0x4c, 0x14, 0x47, 0x2a, - 0x36, 0x39, 0x2a, 0xd8, 0x96, 0x90, 0xdc, 0xfc, 0xd2, 0xdd, 0x23, 0x0e, - 0x2c, 0xb3, 0x83, 0xf9, 0xf2, 0xe3, 0xe6, 0x99, 0x53, 0x57, 0x33, 0xc5, - 0x5f, 0xf9, 0xfd, 0x56, 0x0b, 0x32, 0xd4, 0xf3, 0x9d, 0x5b, 0x34, 0xe5, - 0x94, 0xbf, 0xb6, 0xc0, 0xce, 0xe1, 0x73, 0x5c, 0x02, 0x7a, 0x4c, 0xed, - 0xde, 0x23, 0x38, 0x89, 0x9f, 0xcd, 0x51, 0xf3, 0x90, 0x80, 0xd3, 0x4b, - 0x83, 0xd3, 0xee, 0xf2, 0x9e, 0x35, 0x91, 0xa5, 0xa3, 0xc0, 0x5c, 0xce, - 0xdb, 0xaa, 0x70, 0x1e, 0x1d, 0xc1, 0x44, 0xea, 0x3b, 0xa7, 0x5a, 0x11, - 0xd1, 0xf3, 0xf3, 0xd0, 0xf4, 0x5a, 0xc4, 0x99, 0xaf, 0x8d, 0xe2, 0xbc, - 0xa2, 0xb9, 0x3d, 0x86, 0x5e, 0xba, 0xa0, 0xdf, 0x78, 0x81, 0x7c, 0x54, - 0x31, 0xe3, 0x98, 0xb5, 0x46, 0xcb, 0x4d, 0x26, 0x4b, 0xf8, 0xac, 0x3a, - 0x54, 0x1b, 0x77, 0x5a, 0x18, 0xa5, 0x43, 0x0e, 0x14, 0xde, 0x7b, 0xb7, - 0x4e, 0x45, 0x99, 0x03, 0xd1, 0x3d, 0x18, 0xb2, 0x36, 0x00, 0x48, 0x07, - 0x72, 0xbb, 0x4f, 0x21, 0x25, 0x3e, 0xda, 0x25, 0x24, 0x5b, 0xc8, 0xa0, - 0x28, 0xd5, 0x9b, 0x96, 0x87, 0x07, 0x77, 0x84, 0xff, 0xd7, 0xac, 0x71, - 0xf6, 0x61, 0x63, 0x0b, 0xfb, 0x42, 0xfd, 0x52, 0xf4, 0xc4, 0x35, 0x0c, - 0xc2, 0xc1, 0x55, 0x22, 0x42, 0x2f, 0x13, 0x7d, 0x93, 0x27, 0xc8, 0x11, - 0x35, 0xc5, 0xe3, 0xc5, 0xaa, 0x15, 0x3c, 0xac, 0x30, 0xbc, 0x45, 0x16, - 0xed}; - static const unsigned char openssl_pub_key[] = { - 0x30, 0x82, 0x01, 0x4b, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, - 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, - 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04, - 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x5a, - 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, - 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, - 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d, - 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, 0xe1, 0x13, 0x9d, - 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1, - 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, - 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, - 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, - 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, - 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, - 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, - 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, - 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, - 0x2e, 0x8f, 0x37, 0x9a, 0xd5, 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, - 0x4a, 0xe7, 0x20, 0xcb, 0x90, 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, - 0x88, 0x38, 0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, - 0xe3, 0xd5, 0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, - 0x41, 0x3b, 0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec}; - - scoped_ptr keypair_openssl( - crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - "", - std::vector(openssl_key, openssl_key + arraysize(openssl_key)), - std::vector(openssl_pub_key, - openssl_pub_key + arraysize(openssl_pub_key)))); - - EXPECT_TRUE(keypair_openssl.get()); -} -#endif // defined(USE_OPENSSL) diff --git a/crypto/ec_signature_creator.cc b/crypto/ec_signature_creator.cc deleted file mode 100644 index a6887bc117b7f..0000000000000 --- a/crypto/ec_signature_creator.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012 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/ec_signature_creator.h" - -#include "base/logging.h" -#include "crypto/ec_signature_creator_impl.h" - -namespace crypto { - -namespace { - -ECSignatureCreatorFactory* g_factory_ = NULL; - -} // namespace - -// static -ECSignatureCreator* ECSignatureCreator::Create(ECPrivateKey* key) { - if (g_factory_) - return g_factory_->Create(key); - return new ECSignatureCreatorImpl(key); -} - -// static -void ECSignatureCreator::SetFactoryForTesting( - ECSignatureCreatorFactory* factory) { - // We should always clear the factory after each test to avoid - // use-after-free problems. - DCHECK(!g_factory_ || !factory); - g_factory_ = factory; -} - -} // namespace crypto diff --git a/crypto/ec_signature_creator.h b/crypto/ec_signature_creator.h deleted file mode 100644 index 16e64f5753cb8..0000000000000 --- a/crypto/ec_signature_creator.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 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_EC_SIGNATURE_CREATOR_H_ -#define CRYPTO_EC_SIGNATURE_CREATOR_H_ - -#include -#include - -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -class ECPrivateKey; -class ECSignatureCreator; - -class CRYPTO_EXPORT ECSignatureCreatorFactory { - public: - virtual ~ECSignatureCreatorFactory() {} - - virtual ECSignatureCreator* Create(ECPrivateKey* key) = 0; -}; - -// Signs data using a bare private key (as opposed to a full certificate). -// We need this class because SignatureCreator is hardcoded to use -// RSAPrivateKey. -class CRYPTO_EXPORT ECSignatureCreator { - public: - virtual ~ECSignatureCreator() {} - - // Create an instance. The caller must ensure that the provided PrivateKey - // instance outlives the created ECSignatureCreator. - // TODO(rch): This is currently hard coded to use SHA256. Ideally, we should - // pass in the hash algorithm identifier. - static ECSignatureCreator* Create(ECPrivateKey* key); - - // Set a factory to make the Create function return non-standard - // ECSignatureCreator objects. Because the ECDSA algorithm involves - // randomness, this is useful for higher-level tests that want to have - // deterministic mocked output to compare. - static void SetFactoryForTesting(ECSignatureCreatorFactory* factory); - - // Signs |data_len| bytes from |data| and writes the results into - // |signature| as a DER encoded ECDSA-Sig-Value from RFC 3279. - // - // ECDSA-Sig-Value ::= SEQUENCE { - // r INTEGER, - // s INTEGER } - virtual bool Sign(const uint8* data, - int data_len, - std::vector* signature) = 0; - - // DecodeSignature converts from a DER encoded ECDSA-Sig-Value (as produced - // by Sign) to a `raw' ECDSA signature which consists of a pair of - // big-endian, zero-padded, 256-bit integers, r and s. On success it returns - // true and puts the raw signature into |out_raw_sig|. - // (Only P-256 signatures are supported.) - virtual bool DecodeSignature(const std::vector& signature, - std::vector* out_raw_sig) = 0; -}; - -} // namespace crypto - -#endif // CRYPTO_EC_SIGNATURE_CREATOR_H_ diff --git a/crypto/ec_signature_creator_impl.h b/crypto/ec_signature_creator_impl.h deleted file mode 100644 index 91a60a89963d7..0000000000000 --- a/crypto/ec_signature_creator_impl.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012 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_EC_SIGNATURE_CREATOR_IMPL_H_ -#define CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ - -#include "base/compiler_specific.h" -#include "crypto/ec_signature_creator.h" - -namespace crypto { - -class ECSignatureCreatorImpl : public ECSignatureCreator { - public: - explicit ECSignatureCreatorImpl(ECPrivateKey* key); - ~ECSignatureCreatorImpl() override; - - bool Sign(const uint8* data, - int data_len, - std::vector* signature) override; - - bool DecodeSignature(const std::vector& der_sig, - std::vector* out_raw_sig) override; - - private: - ECPrivateKey* key_; - size_t signature_len_; - - DISALLOW_COPY_AND_ASSIGN(ECSignatureCreatorImpl); -}; - -} // namespace crypto - -#endif // CRYPTO_EC_SIGNATURE_CREATOR_IMPL_H_ diff --git a/crypto/ec_signature_creator_nss.cc b/crypto/ec_signature_creator_nss.cc deleted file mode 100644 index 3e3626f449982..0000000000000 --- a/crypto/ec_signature_creator_nss.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2012 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/ec_signature_creator_impl.h" - -#include -#include -#include -#include -#if defined(OS_POSIX) -#include -#endif - -#include "base/logging.h" -#include "crypto/ec_private_key.h" -#include "crypto/nss_util.h" -#include "crypto/scoped_nss_types.h" - -namespace crypto { - -namespace { - -SECStatus SignData(SECItem* result, - SECItem* input, - SECKEYPrivateKey* key, - HASH_HashType hash_type, - size_t* out_signature_len) { - if (key->keyType != ecKey) { - DLOG(FATAL) << "Should be using an EC key."; - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - // Hash the input. - std::vector hash_data(HASH_ResultLen(hash_type)); - SECStatus rv = HASH_HashBuf( - hash_type, &hash_data[0], input->data, input->len); - if (rv != SECSuccess) - return rv; - SECItem hash = {siBuffer, &hash_data[0], - static_cast(hash_data.size())}; - - // Compute signature of hash. - int signature_len = PK11_SignatureLen(key); - std::vector signature_data(signature_len); - SECItem sig = {siBuffer, &signature_data[0], - static_cast(signature_len)}; - rv = PK11_Sign(key, &sig, &hash); - if (rv != SECSuccess) - return rv; - - *out_signature_len = sig.len; - - // DER encode the signature. - return DSAU_EncodeDerSigWithLen(result, &sig, sig.len); -} - -} // namespace - -ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) - : key_(key), - signature_len_(0) { - EnsureNSSInit(); -} - -ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {} - -bool ECSignatureCreatorImpl::Sign(const uint8* data, - int data_len, - std::vector* signature) { - // Data to be signed - SECItem secret; - secret.type = siBuffer; - secret.len = data_len; - secret.data = const_cast(data); - - // SECItem to receive the output buffer. - SECItem result; - result.type = siBuffer; - result.len = 0; - result.data = NULL; - - // Sign the secret data and save it to |result|. - SECStatus rv = - SignData(&result, &secret, key_->key(), HASH_AlgSHA256, &signature_len_); - if (rv != SECSuccess) { - DLOG(ERROR) << "DerSignData: " << PORT_GetError(); - return false; - } - - // Copy the signed data into the output vector. - signature->assign(result.data, result.data + result.len); - SECITEM_FreeItem(&result, PR_FALSE /* only free |result.data| */); - return true; -} - -bool ECSignatureCreatorImpl::DecodeSignature( - const std::vector& der_sig, - std::vector* out_raw_sig) { - SECItem der_sig_item; - der_sig_item.type = siBuffer; - der_sig_item.len = der_sig.size(); - der_sig_item.data = const_cast(&der_sig[0]); - - SECItem* raw_sig = DSAU_DecodeDerSigToLen(&der_sig_item, signature_len_); - if (!raw_sig) - return false; - out_raw_sig->assign(raw_sig->data, raw_sig->data + raw_sig->len); - SECITEM_FreeItem(raw_sig, PR_TRUE /* free SECItem structure itself. */); - return true; -} - -} // namespace crypto diff --git a/crypto/ec_signature_creator_openssl.cc b/crypto/ec_signature_creator_openssl.cc deleted file mode 100644 index c422cef5f275a..0000000000000 --- a/crypto/ec_signature_creator_openssl.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2012 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/ec_signature_creator_impl.h" - -#include -#include -#include -#include -#include - -#include "base/logging.h" -#include "crypto/ec_private_key.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" - -namespace crypto { - -ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) - : key_(key), signature_len_(0) { - EnsureOpenSSLInit(); -} - -ECSignatureCreatorImpl::~ECSignatureCreatorImpl() {} - -bool ECSignatureCreatorImpl::Sign(const uint8* data, - int data_len, - std::vector* signature) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); - size_t sig_len = 0; - if (!ctx.get() || - !EVP_DigestSignInit(ctx.get(), NULL, EVP_sha256(), NULL, key_->key()) || - !EVP_DigestSignUpdate(ctx.get(), data, data_len) || - !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) { - return false; - } - - signature->resize(sig_len); - if (!EVP_DigestSignFinal(ctx.get(), &signature->front(), &sig_len)) - return false; - - // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter returns - // a maximum allocation size, while the call without a NULL returns the real - // one, which may be smaller. - signature->resize(sig_len); - return true; -} - -bool ECSignatureCreatorImpl::DecodeSignature(const std::vector& der_sig, - std::vector* out_raw_sig) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - // Create ECDSA_SIG object from DER-encoded data. - const unsigned char* der_data = &der_sig.front(); - ScopedECDSA_SIG ecdsa_sig( - d2i_ECDSA_SIG(NULL, &der_data, static_cast(der_sig.size()))); - if (!ecdsa_sig.get()) - return false; - - // The result is made of two 32-byte vectors. - const size_t kMaxBytesPerBN = 32; - std::vector result(2 * kMaxBytesPerBN); - - if (!BN_bn2bin_padded(&result[0], kMaxBytesPerBN, ecdsa_sig->r) || - !BN_bn2bin_padded(&result[kMaxBytesPerBN], kMaxBytesPerBN, - ecdsa_sig->s)) { - return false; - } - out_raw_sig->swap(result); - return true; -} - -} // namespace crypto diff --git a/crypto/ec_signature_creator_unittest.cc b/crypto/ec_signature_creator_unittest.cc deleted file mode 100644 index 2a40cfe0c12a4..0000000000000 --- a/crypto/ec_signature_creator_unittest.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2012 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/ec_signature_creator.h" - -#include -#include - -#include "base/memory/scoped_ptr.h" -#include "crypto/ec_private_key.h" -#include "crypto/signature_verifier.h" -#include "testing/gtest/include/gtest/gtest.h" - -// TODO(rch): Add some exported keys from each to -// test interop between NSS and OpenSSL. - -TEST(ECSignatureCreatorTest, BasicTest) { - // Do a verify round trip. - scoped_ptr key_original( - crypto::ECPrivateKey::Create()); - ASSERT_TRUE(key_original.get()); - - std::vector key_info; - ASSERT_TRUE( - key_original->ExportEncryptedPrivateKey(std::string(), 1000, &key_info)); - std::vector pubkey_info; - ASSERT_TRUE(key_original->ExportPublicKey(&pubkey_info)); - - scoped_ptr key( - crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( - std::string(), key_info, pubkey_info)); - ASSERT_TRUE(key.get()); - ASSERT_TRUE(key->key() != NULL); - - scoped_ptr signer( - crypto::ECSignatureCreator::Create(key.get())); - ASSERT_TRUE(signer.get()); - - std::string data("Hello, World!"); - std::vector signature; - ASSERT_TRUE(signer->Sign(reinterpret_cast(data.c_str()), - data.size(), - &signature)); - - std::vector public_key_info; - ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); - - // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. - // RFC 5758: - // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) - // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } - // ... - // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or - // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field - // as an AlgorithmIdentifier, the encoding MUST omit the parameters - // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one - // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- - // SHA384, or ecdsa-with-SHA512. - // See also RFC 5480, Appendix A. - const uint8 kECDSAWithSHA256AlgorithmID[] = { - 0x30, 0x0a, - 0x06, 0x08, - 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, - }; - crypto::SignatureVerifier verifier; - ASSERT_TRUE(verifier.VerifyInit( - kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID), - &signature[0], signature.size(), - &public_key_info.front(), public_key_info.size())); - - verifier.VerifyUpdate(reinterpret_cast(data.c_str()), - data.size()); - ASSERT_TRUE(verifier.VerifyFinal()); -} diff --git a/crypto/encryptor.cc b/crypto/encryptor.cc deleted file mode 100644 index a673f81c1781d..0000000000000 --- a/crypto/encryptor.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012 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/encryptor.h" - -#include "base/logging.h" -#include "base/sys_byteorder.h" - -namespace crypto { - -///////////////////////////////////////////////////////////////////////////// -// Encyptor::Counter Implementation. -Encryptor::Counter::Counter(const base::StringPiece& counter) { - CHECK(sizeof(counter_) == counter.length()); - - memcpy(&counter_, counter.data(), sizeof(counter_)); -} - -Encryptor::Counter::~Counter() { -} - -bool Encryptor::Counter::Increment() { - uint64 low_num = base::NetToHost64(counter_.components64[1]); - uint64 new_low_num = low_num + 1; - counter_.components64[1] = base::HostToNet64(new_low_num); - - // If overflow occured then increment the most significant component. - if (new_low_num < low_num) { - counter_.components64[0] = - base::HostToNet64(base::NetToHost64(counter_.components64[0]) + 1); - } - - // TODO(hclam): Return false if counter value overflows. - return true; -} - -void Encryptor::Counter::Write(void* buf) { - uint8* buf_ptr = reinterpret_cast(buf); - memcpy(buf_ptr, &counter_, sizeof(counter_)); -} - -size_t Encryptor::Counter::GetLengthInBytes() const { - return sizeof(counter_); -} - -///////////////////////////////////////////////////////////////////////////// -// Partial Encryptor Implementation. - -bool Encryptor::SetCounter(const base::StringPiece& counter) { - if (mode_ != CTR) - return false; - if (counter.length() != 16u) - return false; - - counter_.reset(new Counter(counter)); - return true; -} - -bool Encryptor::GenerateCounterMask(size_t plaintext_len, - uint8* mask, - size_t* mask_len) { - DCHECK_EQ(CTR, mode_); - CHECK(mask); - CHECK(mask_len); - - const size_t kBlockLength = counter_->GetLengthInBytes(); - size_t blocks = (plaintext_len + kBlockLength - 1) / kBlockLength; - CHECK(blocks); - - *mask_len = blocks * kBlockLength; - - for (size_t i = 0; i < blocks; ++i) { - counter_->Write(mask); - mask += kBlockLength; - - bool ret = counter_->Increment(); - if (!ret) - return false; - } - return true; -} - -void Encryptor::MaskMessage(const void* plaintext, - size_t plaintext_len, - const void* mask, - void* ciphertext) const { - DCHECK_EQ(CTR, mode_); - const uint8* plaintext_ptr = reinterpret_cast(plaintext); - const uint8* mask_ptr = reinterpret_cast(mask); - uint8* ciphertext_ptr = reinterpret_cast(ciphertext); - - for (size_t i = 0; i < plaintext_len; ++i) - ciphertext_ptr[i] = plaintext_ptr[i] ^ mask_ptr[i]; -} - -} // namespace crypto diff --git a/crypto/encryptor.h b/crypto/encryptor.h deleted file mode 100644 index 8052a9fd5744f..0000000000000 --- a/crypto/encryptor.h +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2012 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_ENCRYPTOR_H_ -#define CRYPTO_ENCRYPTOR_H_ - -#include - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_piece.h" -#include "build/build_config.h" -#include "crypto/crypto_export.h" - -#if defined(USE_NSS_CERTS) || \ - (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX))) -#include "crypto/scoped_nss_types.h" -#endif - -namespace crypto { - -class SymmetricKey; - -class CRYPTO_EXPORT Encryptor { - public: - enum Mode { - CBC, - CTR, - }; - - // This class implements a 128-bits counter to be used in AES-CTR encryption. - // Only 128-bits counter is supported in this class. - class CRYPTO_EXPORT Counter { - public: - explicit Counter(const base::StringPiece& counter); - ~Counter(); - - // Increment the counter value. - bool Increment(); - - // Write the content of the counter to |buf|. |buf| should have enough - // space for |GetLengthInBytes()|. - void Write(void* buf); - - // Return the length of this counter. - size_t GetLengthInBytes() const; - - private: - union { - uint32 components32[4]; - uint64 components64[2]; - } counter_; - }; - - Encryptor(); - virtual ~Encryptor(); - - // Initializes the encryptor using |key| and |iv|. Returns false if either the - // key or the initialization vector cannot be used. - // - // If |mode| is CBC, |iv| must not be empty; if it is CTR, then |iv| must be - // empty. - bool Init(SymmetricKey* key, Mode mode, const base::StringPiece& iv); - - // Encrypts |plaintext| into |ciphertext|. |plaintext| may only be empty if - // the mode is CBC. - bool Encrypt(const base::StringPiece& plaintext, std::string* ciphertext); - - // Decrypts |ciphertext| into |plaintext|. |ciphertext| must not be empty. - // - // WARNING: In CBC mode, Decrypt() returns false if it detects the padding - // in the decrypted plaintext is wrong. Padding errors can result from - // tampered ciphertext or a wrong decryption key. But successful decryption - // does not imply the authenticity of the data. The caller of Decrypt() - // must either authenticate the ciphertext before decrypting it, or take - // care to not report decryption failure. Otherwise it could inadvertently - // be used as a padding oracle to attack the cryptosystem. - bool Decrypt(const base::StringPiece& ciphertext, std::string* plaintext); - - // Sets the counter value when in CTR mode. Currently only 128-bits - // counter value is supported. - // - // Returns true only if update was successful. - bool SetCounter(const base::StringPiece& counter); - - // TODO(albertb): Support streaming encryption. - - private: - // Generates a mask using |counter_| to be used for encryption in CTR mode. - // Resulting mask will be written to |mask| with |mask_len| bytes. - // - // Make sure there's enough space in mask when calling this method. - // Reserve at least |plaintext_len| + 16 bytes for |mask|. - // - // The generated mask will always have at least |plaintext_len| bytes and - // will be a multiple of the counter length. - // - // This method is used only in CTR mode. - // - // Returns false if this call failed. - bool GenerateCounterMask(size_t plaintext_len, - uint8* mask, - size_t* mask_len); - - // Mask the |plaintext| message using |mask|. The output will be written to - // |ciphertext|. |ciphertext| must have at least |plaintext_len| bytes. - void MaskMessage(const void* plaintext, - size_t plaintext_len, - const void* mask, - void* ciphertext) const; - - SymmetricKey* key_; - Mode mode_; - scoped_ptr counter_; - -#if defined(USE_OPENSSL) - bool Crypt(bool do_encrypt, // Pass true to encrypt, false to decrypt. - const base::StringPiece& input, - std::string* output); - bool CryptCTR(bool do_encrypt, - const base::StringPiece& input, - std::string* output); - std::string iv_; -#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) - bool Crypt(PK11Context* context, - const base::StringPiece& input, - std::string* output); - bool CryptCTR(PK11Context* context, - const base::StringPiece& input, - std::string* output); - ScopedSECItem param_; -#endif -}; - -} // namespace crypto - -#endif // CRYPTO_ENCRYPTOR_H_ diff --git a/crypto/encryptor_nss.cc b/crypto/encryptor_nss.cc deleted file mode 100644 index ca5d5239a2a96..0000000000000 --- a/crypto/encryptor_nss.cc +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2011 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/encryptor.h" - -#include -#include - -#include "base/logging.h" -#include "crypto/nss_util.h" -#include "crypto/symmetric_key.h" - -namespace crypto { - -namespace { - -inline CK_MECHANISM_TYPE GetMechanism(Encryptor::Mode mode) { - switch (mode) { - case Encryptor::CBC: - return CKM_AES_CBC_PAD; - case Encryptor::CTR: - // AES-CTR encryption uses ECB encryptor as a building block since - // NSS doesn't support CTR encryption mode. - return CKM_AES_ECB; - default: - NOTREACHED() << "Unsupported mode of operation"; - break; - } - return static_cast(-1); -} - -} // namespace - -Encryptor::Encryptor() - : key_(NULL), - mode_(CBC) { - EnsureNSSInit(); -} - -Encryptor::~Encryptor() { -} - -bool Encryptor::Init(SymmetricKey* key, - Mode mode, - const base::StringPiece& iv) { - DCHECK(key); - DCHECK(CBC == mode || CTR == mode) << "Unsupported mode of operation"; - - key_ = key; - mode_ = mode; - - if (mode == CBC && iv.size() != AES_BLOCK_SIZE) - return false; - - switch (mode) { - case CBC: - SECItem iv_item; - iv_item.type = siBuffer; - iv_item.data = reinterpret_cast( - const_cast(iv.data())); - iv_item.len = iv.size(); - - param_.reset(PK11_ParamFromIV(GetMechanism(mode), &iv_item)); - break; - case CTR: - param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL)); - break; - } - - return param_ != NULL; -} - -bool Encryptor::Encrypt(const base::StringPiece& plaintext, - std::string* ciphertext) { - CHECK(!plaintext.empty() || (mode_ == CBC)); - ScopedPK11Context context(PK11_CreateContextBySymKey(GetMechanism(mode_), - CKA_ENCRYPT, - key_->key(), - param_.get())); - if (!context.get()) - return false; - - return (mode_ == CTR) ? - CryptCTR(context.get(), plaintext, ciphertext) : - Crypt(context.get(), plaintext, ciphertext); -} - -bool Encryptor::Decrypt(const base::StringPiece& ciphertext, - std::string* plaintext) { - CHECK(!ciphertext.empty()); - ScopedPK11Context context(PK11_CreateContextBySymKey( - GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT), - key_->key(), param_.get())); - if (!context.get()) - return false; - - if (mode_ == CTR) - return CryptCTR(context.get(), ciphertext, plaintext); - - if (ciphertext.size() % AES_BLOCK_SIZE != 0) { - // Decryption will fail if the input is not a multiple of the block size. - // PK11_CipherOp has a bug where it will do an invalid memory access before - // the start of the input, so avoid calling it. (NSS bug 922780). - plaintext->clear(); - return false; - } - - return Crypt(context.get(), ciphertext, plaintext); -} - -bool Encryptor::Crypt(PK11Context* context, - const base::StringPiece& input, - std::string* output) { - size_t output_len = input.size() + AES_BLOCK_SIZE; - CHECK_GT(output_len, input.size()); - - output->resize(output_len); - uint8* output_data = - reinterpret_cast(const_cast(output->data())); - - int input_len = input.size(); - uint8* input_data = - reinterpret_cast(const_cast(input.data())); - - int op_len; - SECStatus rv = PK11_CipherOp(context, - output_data, - &op_len, - output_len, - input_data, - input_len); - - if (SECSuccess != rv) { - output->clear(); - return false; - } - - unsigned int digest_len; - rv = PK11_DigestFinal(context, - output_data + op_len, - &digest_len, - output_len - op_len); - if (SECSuccess != rv) { - output->clear(); - return false; - } - - output->resize(op_len + digest_len); - return true; -} - -bool Encryptor::CryptCTR(PK11Context* context, - const base::StringPiece& input, - std::string* output) { - if (!counter_.get()) { - LOG(ERROR) << "Counter value not set in CTR mode."; - return false; - } - - size_t output_len = ((input.size() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * - AES_BLOCK_SIZE; - CHECK_GE(output_len, input.size()); - output->resize(output_len); - uint8* output_data = - reinterpret_cast(const_cast(output->data())); - - size_t mask_len; - bool ret = GenerateCounterMask(input.size(), output_data, &mask_len); - if (!ret) - return false; - - CHECK_EQ(mask_len, output_len); - int op_len; - SECStatus rv = PK11_CipherOp(context, - output_data, - &op_len, - output_len, - output_data, - mask_len); - if (SECSuccess != rv) - return false; - CHECK_EQ(static_cast(mask_len), op_len); - - unsigned int digest_len; - rv = PK11_DigestFinal(context, - NULL, - &digest_len, - 0); - if (SECSuccess != rv) - return false; - CHECK(!digest_len); - - // Use |output_data| to mask |input|. - MaskMessage( - reinterpret_cast(const_cast(input.data())), - input.length(), output_data, output_data); - output->resize(input.length()); - return true; -} - -} // namespace crypto diff --git a/crypto/encryptor_openssl.cc b/crypto/encryptor_openssl.cc deleted file mode 100644 index 4f0e51137d76d..0000000000000 --- a/crypto/encryptor_openssl.cc +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2011 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/encryptor.h" - -#include -#include - -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "crypto/openssl_util.h" -#include "crypto/symmetric_key.h" - -namespace crypto { - -namespace { - -const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) { - switch (key->key().length()) { - case 16: return EVP_aes_128_cbc(); - case 32: return EVP_aes_256_cbc(); - default: return NULL; - } -} - -// On destruction this class will cleanup the ctx, and also clear the OpenSSL -// ERR stack as a convenience. -class ScopedCipherCTX { - public: - explicit ScopedCipherCTX() { - EVP_CIPHER_CTX_init(&ctx_); - } - ~ScopedCipherCTX() { - EVP_CIPHER_CTX_cleanup(&ctx_); - ClearOpenSSLERRStack(FROM_HERE); - } - EVP_CIPHER_CTX* get() { return &ctx_; } - - private: - EVP_CIPHER_CTX ctx_; -}; - -} // namespace - -Encryptor::Encryptor() - : key_(NULL), - mode_(CBC) { -} - -Encryptor::~Encryptor() { -} - -bool Encryptor::Init(SymmetricKey* key, - Mode mode, - const base::StringPiece& iv) { - DCHECK(key); - DCHECK(mode == CBC || mode == CTR); - - EnsureOpenSSLInit(); - if (mode == CBC && iv.size() != AES_BLOCK_SIZE) - return false; - - if (GetCipherForKey(key) == NULL) - return false; - - key_ = key; - mode_ = mode; - iv.CopyToString(&iv_); - return true; -} - -bool Encryptor::Encrypt(const base::StringPiece& plaintext, - std::string* ciphertext) { - CHECK(!plaintext.empty() || (mode_ == CBC)); - return (mode_ == CTR) ? - CryptCTR(true, plaintext, ciphertext) : - Crypt(true, plaintext, ciphertext); -} - -bool Encryptor::Decrypt(const base::StringPiece& ciphertext, - std::string* plaintext) { - CHECK(!ciphertext.empty()); - return (mode_ == CTR) ? - CryptCTR(false, ciphertext, plaintext) : - Crypt(false, ciphertext, plaintext); -} - -bool Encryptor::Crypt(bool do_encrypt, - const base::StringPiece& input, - std::string* output) { - DCHECK(key_); // Must call Init() before En/De-crypt. - // Work on the result in a local variable, and then only transfer it to - // |output| on success to ensure no partial data is returned. - std::string result; - output->clear(); - - const EVP_CIPHER* cipher = GetCipherForKey(key_); - DCHECK(cipher); // Already handled in Init(); - - const std::string& key = key_->key(); - DCHECK_EQ(EVP_CIPHER_iv_length(cipher), iv_.length()); - DCHECK_EQ(EVP_CIPHER_key_length(cipher), key.length()); - - ScopedCipherCTX ctx; - if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL, - reinterpret_cast(key.data()), - reinterpret_cast(iv_.data()), - do_encrypt)) - return false; - - // When encrypting, add another block size of space to allow for any padding. - const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0); - CHECK_GT(output_size, 0u); - CHECK_GT(output_size + 1, input.size()); - uint8* out_ptr = - reinterpret_cast(base::WriteInto(&result, output_size + 1)); - int out_len; - if (!EVP_CipherUpdate(ctx.get(), out_ptr, &out_len, - reinterpret_cast(input.data()), - input.length())) - return false; - - // Write out the final block plus padding (if any) to the end of the data - // just written. - int tail_len; - if (!EVP_CipherFinal_ex(ctx.get(), out_ptr + out_len, &tail_len)) - return false; - - out_len += tail_len; - DCHECK_LE(out_len, static_cast(output_size)); - result.resize(out_len); - - output->swap(result); - return true; -} - -bool Encryptor::CryptCTR(bool do_encrypt, - const base::StringPiece& input, - std::string* output) { - if (!counter_.get()) { - LOG(ERROR) << "Counter value not set in CTR mode."; - return false; - } - - AES_KEY aes_key; - if (AES_set_encrypt_key(reinterpret_cast(key_->key().data()), - key_->key().size() * 8, &aes_key) != 0) { - return false; - } - - const size_t out_size = input.size(); - CHECK_GT(out_size, 0u); - CHECK_GT(out_size + 1, input.size()); - - std::string result; - uint8* out_ptr = - reinterpret_cast(base::WriteInto(&result, out_size + 1)); - - uint8_t ivec[AES_BLOCK_SIZE] = { 0 }; - uint8_t ecount_buf[AES_BLOCK_SIZE] = { 0 }; - unsigned int block_offset = 0; - - counter_->Write(ivec); - - AES_ctr128_encrypt(reinterpret_cast(input.data()), out_ptr, - input.size(), &aes_key, ivec, ecount_buf, &block_offset); - - // AES_ctr128_encrypt() updates |ivec|. Update the |counter_| here. - SetCounter(base::StringPiece(reinterpret_cast(ivec), - AES_BLOCK_SIZE)); - - output->swap(result); - return true; -} - -} // namespace crypto diff --git a/crypto/encryptor_unittest.cc b/crypto/encryptor_unittest.cc deleted file mode 100644 index 79fe2cca1a675..0000000000000 --- a/crypto/encryptor_unittest.cc +++ /dev/null @@ -1,531 +0,0 @@ -// Copyright (c) 2012 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/encryptor.h" - -#include - -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "crypto/symmetric_key.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(EncryptorTest, EncryptDecrypt) { - scoped_ptr key( - crypto::SymmetricKey::DeriveKeyFromPassword( - crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256)); - EXPECT_TRUE(key.get()); - - crypto::Encryptor encryptor; - // The IV must be exactly as long as the cipher block size. - std::string iv("the iv: 16 bytes"); - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)); - - std::string plaintext("this is the plaintext"); - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - - EXPECT_LT(0U, ciphertext.size()); - - std::string decrypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); - - EXPECT_EQ(plaintext, decrypted); -} - -TEST(EncryptorTest, DecryptWrongKey) { - scoped_ptr key( - crypto::SymmetricKey::DeriveKeyFromPassword( - crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256)); - EXPECT_TRUE(key.get()); - - // A wrong key that can be detected by implementations that validate every - // byte in the padding. - scoped_ptr wrong_key( - crypto::SymmetricKey::DeriveKeyFromPassword( - crypto::SymmetricKey::AES, "wrongword", "sweetest", 1000, 256)); - EXPECT_TRUE(wrong_key.get()); - - // A wrong key that can't be detected by any implementation. The password - // "wrongword;" would also work. - scoped_ptr wrong_key2( - crypto::SymmetricKey::DeriveKeyFromPassword( - crypto::SymmetricKey::AES, "wrongword+", "sweetest", 1000, 256)); - EXPECT_TRUE(wrong_key2.get()); - - // A wrong key that can be detected by all implementations. - scoped_ptr wrong_key3( - crypto::SymmetricKey::DeriveKeyFromPassword( - crypto::SymmetricKey::AES, "wrongwordx", "sweetest", 1000, 256)); - EXPECT_TRUE(wrong_key3.get()); - - crypto::Encryptor encryptor; - // The IV must be exactly as long as the cipher block size. - std::string iv("the iv: 16 bytes"); - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(key.get(), crypto::Encryptor::CBC, iv)); - - std::string plaintext("this is the plaintext"); - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - - static const unsigned char expected_ciphertext[] = { - 0x7D, 0x67, 0x5B, 0x53, 0xE6, 0xD8, 0x0F, 0x27, - 0x74, 0xB1, 0x90, 0xFE, 0x6E, 0x58, 0x4A, 0xA0, - 0x0E, 0x35, 0xE3, 0x01, 0xC0, 0xFE, 0x9A, 0xD8, - 0x48, 0x1D, 0x42, 0xB0, 0xBA, 0x21, 0xB2, 0x0C - }; - - ASSERT_EQ(arraysize(expected_ciphertext), ciphertext.size()); - for (size_t i = 0; i < ciphertext.size(); ++i) { - ASSERT_EQ(expected_ciphertext[i], - static_cast(ciphertext[i])); - } - - std::string decrypted; - - // This wrong key causes the last padding byte to be 5, which is a valid - // padding length, and the second to last padding byte to be 137, which is - // invalid. If an implementation simply uses the last padding byte to - // determine the padding length without checking every padding byte, - // Encryptor::Decrypt() will still return true. This is the case for NSS - // (crbug.com/124434). -#if !defined(USE_NSS_CERTS) && !defined(OS_WIN) && !defined(OS_MACOSX) - crypto::Encryptor decryptor; - EXPECT_TRUE(decryptor.Init(wrong_key.get(), crypto::Encryptor::CBC, iv)); - EXPECT_FALSE(decryptor.Decrypt(ciphertext, &decrypted)); -#endif - - // This demonstrates that not all wrong keys can be detected by padding - // error. This wrong key causes the last padding byte to be 1, which is - // a valid padding block of length 1. - crypto::Encryptor decryptor2; - EXPECT_TRUE(decryptor2.Init(wrong_key2.get(), crypto::Encryptor::CBC, iv)); - EXPECT_TRUE(decryptor2.Decrypt(ciphertext, &decrypted)); - - // This wrong key causes the last padding byte to be 253, which should be - // rejected by all implementations. - crypto::Encryptor decryptor3; - EXPECT_TRUE(decryptor3.Init(wrong_key3.get(), crypto::Encryptor::CBC, iv)); - EXPECT_FALSE(decryptor3.Decrypt(ciphertext, &decrypted)); -} - -namespace { - -// From NIST SP 800-38a test cast: -// - F.5.1 CTR-AES128.Encrypt -// - F.5.6 CTR-AES256.Encrypt -// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf -const unsigned char kAES128CTRKey[] = { - 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c -}; - -const unsigned char kAES256CTRKey[] = { - 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, - 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, - 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, - 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 -}; - -const unsigned char kAESCTRInitCounter[] = { - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -const unsigned char kAESCTRPlaintext[] = { - // Block #1 - 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - // Block #2 - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - // Block #3 - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - // Block #4 - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 -}; - -const unsigned char kAES128CTRCiphertext[] = { - // Block #1 - 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, - 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, - // Block #2 - 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, - 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, - // Block #3 - 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, - 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, - // Block #4 - 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, - 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee -}; - -const unsigned char kAES256CTRCiphertext[] = { - // Block #1 - 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, - 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, - // Block #2 - 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, - 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, - // Block #3 - 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, - 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d, - // Block #4 - 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, - 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6 -}; - -void TestAESCTREncrypt( - const unsigned char* key, size_t key_size, - const unsigned char* init_counter, size_t init_counter_size, - const unsigned char* plaintext, size_t plaintext_size, - const unsigned char* ciphertext, size_t ciphertext_size) { - std::string key_str(reinterpret_cast(key), key_size); - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key_str)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CTR, "")); - - base::StringPiece init_counter_str( - reinterpret_cast(init_counter), init_counter_size); - base::StringPiece plaintext_str( - reinterpret_cast(plaintext), plaintext_size); - - EXPECT_TRUE(encryptor.SetCounter(init_counter_str)); - std::string encrypted; - EXPECT_TRUE(encryptor.Encrypt(plaintext_str, &encrypted)); - - EXPECT_EQ(ciphertext_size, encrypted.size()); - EXPECT_EQ(0, memcmp(encrypted.data(), ciphertext, encrypted.size())); - - std::string decrypted; - EXPECT_TRUE(encryptor.SetCounter(init_counter_str)); - EXPECT_TRUE(encryptor.Decrypt(encrypted, &decrypted)); - - EXPECT_EQ(plaintext_str, decrypted); -} - -void TestAESCTRMultipleDecrypt( - const unsigned char* key, size_t key_size, - const unsigned char* init_counter, size_t init_counter_size, - const unsigned char* plaintext, size_t plaintext_size, - const unsigned char* ciphertext, size_t ciphertext_size) { - std::string key_str(reinterpret_cast(key), key_size); - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key_str)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CTR, "")); - - // Counter is set only once. - EXPECT_TRUE(encryptor.SetCounter(base::StringPiece( - reinterpret_cast(init_counter), init_counter_size))); - - std::string ciphertext_str(reinterpret_cast(ciphertext), - ciphertext_size); - - int kTestDecryptSizes[] = { 32, 16, 8 }; - - int offset = 0; - for (size_t i = 0; i < arraysize(kTestDecryptSizes); ++i) { - std::string decrypted; - size_t len = kTestDecryptSizes[i]; - EXPECT_TRUE( - encryptor.Decrypt(ciphertext_str.substr(offset, len), &decrypted)); - EXPECT_EQ(len, decrypted.size()); - EXPECT_EQ(0, memcmp(decrypted.data(), plaintext + offset, len)); - offset += len; - } -} - -} // namespace - -TEST(EncryptorTest, EncryptAES128CTR) { - TestAESCTREncrypt( - kAES128CTRKey, arraysize(kAES128CTRKey), - kAESCTRInitCounter, arraysize(kAESCTRInitCounter), - kAESCTRPlaintext, arraysize(kAESCTRPlaintext), - kAES128CTRCiphertext, arraysize(kAES128CTRCiphertext)); -} - -TEST(EncryptorTest, EncryptAES256CTR) { - TestAESCTREncrypt( - kAES256CTRKey, arraysize(kAES256CTRKey), - kAESCTRInitCounter, arraysize(kAESCTRInitCounter), - kAESCTRPlaintext, arraysize(kAESCTRPlaintext), - kAES256CTRCiphertext, arraysize(kAES256CTRCiphertext)); -} - -TEST(EncryptorTest, EncryptAES128CTR_MultipleDecrypt) { - TestAESCTRMultipleDecrypt( - kAES128CTRKey, arraysize(kAES128CTRKey), - kAESCTRInitCounter, arraysize(kAESCTRInitCounter), - kAESCTRPlaintext, arraysize(kAESCTRPlaintext), - kAES128CTRCiphertext, arraysize(kAES128CTRCiphertext)); -} - -TEST(EncryptorTest, EncryptAES256CTR_MultipleDecrypt) { - TestAESCTRMultipleDecrypt( - kAES256CTRKey, arraysize(kAES256CTRKey), - kAESCTRInitCounter, arraysize(kAESCTRInitCounter), - kAESCTRPlaintext, arraysize(kAESCTRPlaintext), - kAES256CTRCiphertext, arraysize(kAES256CTRCiphertext)); -} - -TEST(EncryptorTest, EncryptDecryptCTR) { - scoped_ptr key( - crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 128)); - - EXPECT_TRUE(key.get()); - const std::string kInitialCounter = "0000000000000000"; - - crypto::Encryptor encryptor; - EXPECT_TRUE(encryptor.Init(key.get(), crypto::Encryptor::CTR, "")); - EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); - - std::string plaintext("normal plaintext of random length"); - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_LT(0U, ciphertext.size()); - - std::string decrypted; - EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); - EXPECT_EQ(plaintext, decrypted); - - plaintext = "0123456789012345"; - EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_LT(0U, ciphertext.size()); - - EXPECT_TRUE(encryptor.SetCounter(kInitialCounter)); - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); - EXPECT_EQ(plaintext, decrypted); -} - -TEST(EncryptorTest, CTRCounter) { - const int kCounterSize = 16; - const unsigned char kTest1[] = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char buf[16]; - - // Increment 10 times. - crypto::Encryptor::Counter counter1( - std::string(reinterpret_cast(kTest1), kCounterSize)); - for (int i = 0; i < 10; ++i) - counter1.Increment(); - counter1.Write(buf); - EXPECT_EQ(0, memcmp(buf, kTest1, 15)); - EXPECT_TRUE(buf[15] == 10); - - // Check corner cases. - const unsigned char kTest2[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - const unsigned char kExpect2[] = - {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}; - crypto::Encryptor::Counter counter2( - std::string(reinterpret_cast(kTest2), kCounterSize)); - counter2.Increment(); - counter2.Write(buf); - EXPECT_EQ(0, memcmp(buf, kExpect2, kCounterSize)); - - const unsigned char kTest3[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - const unsigned char kExpect3[] = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - crypto::Encryptor::Counter counter3( - std::string(reinterpret_cast(kTest3), kCounterSize)); - counter3.Increment(); - counter3.Write(buf); - EXPECT_EQ(0, memcmp(buf, kExpect3, kCounterSize)); -} - -// TODO(wtc): add more known-answer tests. Test vectors are available from -// http://www.ietf.org/rfc/rfc3602 -// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf -// http://gladman.plushost.co.uk/oldsite/AES/index.php -// http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip - -// NIST SP 800-38A test vector F.2.5 CBC-AES256.Encrypt. -TEST(EncryptorTest, EncryptAES256CBC) { - // From NIST SP 800-38a test cast F.2.5 CBC-AES256.Encrypt. - static const unsigned char kRawKey[] = { - 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, - 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, - 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, - 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 - }; - static const unsigned char kRawIv[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - }; - static const unsigned char kRawPlaintext[] = { - // Block #1 - 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - // Block #2 - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - // Block #3 - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - // Block #4 - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, - }; - static const unsigned char kRawCiphertext[] = { - // Block #1 - 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, - 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, - // Block #2 - 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, - 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, - // Block #3 - 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, - 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, - // Block #4 - 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, - 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b, - // PKCS #5 padding, encrypted. - 0x3f, 0x46, 0x17, 0x96, 0xd6, 0xb0, 0xd6, 0xb2, - 0xe0, 0xc2, 0xa7, 0x2b, 0x4d, 0x80, 0xe6, 0x44 - }; - - std::string key(reinterpret_cast(kRawKey), sizeof(kRawKey)); - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - std::string iv(reinterpret_cast(kRawIv), sizeof(kRawIv)); - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); - - std::string plaintext(reinterpret_cast(kRawPlaintext), - sizeof(kRawPlaintext)); - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - - EXPECT_EQ(sizeof(kRawCiphertext), ciphertext.size()); - EXPECT_EQ(0, memcmp(ciphertext.data(), kRawCiphertext, ciphertext.size())); - - std::string decrypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); - - EXPECT_EQ(plaintext, decrypted); -} - -// Expected output derived from the NSS implementation. -TEST(EncryptorTest, EncryptAES128CBCRegression) { - std::string key = "128=SixteenBytes"; - std::string iv = "Sweet Sixteen IV"; - std::string plaintext = "Plain text with a g-clef U+1D11E \360\235\204\236"; - std::string expected_ciphertext_hex = - "D4A67A0BA33C30F207344D81D1E944BBE65587C3D7D9939A" - "C070C62B9C15A3EA312EA4AD1BC7929F4D3C16B03AD5ADA8"; - - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); - - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), - ciphertext.size())); - - std::string decrypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); - EXPECT_EQ(plaintext, decrypted); -} - -// Symmetric keys with an unsupported size should be rejected. Whether they are -// rejected by SymmetricKey::Import or Encryptor::Init depends on the platform. -TEST(EncryptorTest, UnsupportedKeySize) { - std::string key = "7 = bad"; - std::string iv = "Sweet Sixteen IV"; - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key)); - if (!sym_key.get()) - return; - - crypto::Encryptor encryptor; - // The IV must be exactly as long as the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_FALSE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); -} - -TEST(EncryptorTest, UnsupportedIV) { - std::string key = "128=SixteenBytes"; - std::string iv = "OnlyForteen :("; - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - EXPECT_FALSE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); -} - -TEST(EncryptorTest, EmptyEncrypt) { - std::string key = "128=SixteenBytes"; - std::string iv = "Sweet Sixteen IV"; - std::string plaintext; - std::string expected_ciphertext_hex = "8518B8878D34E7185E300D0FCC426396"; - - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); - - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), - ciphertext.size())); -} - -TEST(EncryptorTest, CipherTextNotMultipleOfBlockSize) { - std::string key = "128=SixteenBytes"; - std::string iv = "Sweet Sixteen IV"; - - scoped_ptr sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); - - // Use a separately allocated array to improve the odds of the memory tools - // catching invalid accesses. - // - // Otherwise when using std::string as the other tests do, accesses several - // bytes off the end of the buffer may fall inside the reservation of - // the string and not be detected. - scoped_ptr ciphertext(new char[1]); - - std::string plaintext; - EXPECT_FALSE( - encryptor.Decrypt(base::StringPiece(ciphertext.get(), 1), &plaintext)); -} diff --git a/crypto/ghash.cc b/crypto/ghash.cc deleted file mode 100644 index 1acd474cbc69a..0000000000000 --- a/crypto/ghash.cc +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) 2012 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/ghash.h" - -#include - -#include "base/logging.h" -#include "base/sys_byteorder.h" - -namespace crypto { - -// GaloisHash is a polynomial authenticator that works in GF(2^128). -// -// Elements of the field are represented in `little-endian' order (which -// matches the description in the paper[1]), thus the most significant bit is -// the right-most bit. (This is backwards from the way that everybody else does -// it.) -// -// We store field elements in a pair of such `little-endian' uint64s. So the -// value one is represented by {low = 2**63, high = 0} and doubling a value -// involves a *right* shift. -// -// [1] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf - -namespace { - -// Get64 reads a 64-bit, big-endian number from |bytes|. -uint64 Get64(const uint8 bytes[8]) { - uint64 t; - memcpy(&t, bytes, sizeof(t)); - return base::NetToHost64(t); -} - -// Put64 writes |x| to |bytes| as a 64-bit, big-endian number. -void Put64(uint8 bytes[8], uint64 x) { - x = base::HostToNet64(x); - memcpy(bytes, &x, sizeof(x)); -} - -// Reverse reverses the order of the bits of 4-bit number in |i|. -int Reverse(int i) { - i = ((i << 2) & 0xc) | ((i >> 2) & 0x3); - i = ((i << 1) & 0xa) | ((i >> 1) & 0x5); - return i; -} - -} // namespace - -GaloisHash::GaloisHash(const uint8 key[16]) { - Reset(); - - // We precompute 16 multiples of |key|. However, when we do lookups into this - // table we'll be using bits from a field element and therefore the bits will - // be in the reverse order. So normally one would expect, say, 4*key to be in - // index 4 of the table but due to this bit ordering it will actually be in - // index 0010 (base 2) = 2. - FieldElement x = {Get64(key), Get64(key+8)}; - product_table_[0].low = 0; - product_table_[0].hi = 0; - product_table_[Reverse(1)] = x; - - for (int i = 0; i < 16; i += 2) { - product_table_[Reverse(i)] = Double(product_table_[Reverse(i/2)]); - product_table_[Reverse(i+1)] = Add(product_table_[Reverse(i)], x); - } -} - -void GaloisHash::Reset() { - state_ = kHashingAdditionalData; - additional_bytes_ = 0; - ciphertext_bytes_ = 0; - buf_used_ = 0; - y_.low = 0; - y_.hi = 0; -} - -void GaloisHash::UpdateAdditional(const uint8* data, size_t length) { - DCHECK_EQ(state_, kHashingAdditionalData); - additional_bytes_ += length; - Update(data, length); -} - -void GaloisHash::UpdateCiphertext(const uint8* data, size_t length) { - if (state_ == kHashingAdditionalData) { - // If there's any remaining additional data it's zero padded to the next - // full block. - if (buf_used_ > 0) { - memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_); - UpdateBlocks(buf_, 1); - buf_used_ = 0; - } - state_ = kHashingCiphertext; - } - - DCHECK_EQ(state_, kHashingCiphertext); - ciphertext_bytes_ += length; - Update(data, length); -} - -void GaloisHash::Finish(void* output, size_t len) { - DCHECK(state_ != kComplete); - - if (buf_used_ > 0) { - // If there's any remaining data (additional data or ciphertext), it's zero - // padded to the next full block. - memset(&buf_[buf_used_], 0, sizeof(buf_)-buf_used_); - UpdateBlocks(buf_, 1); - buf_used_ = 0; - } - - state_ = kComplete; - - // The lengths of the additional data and ciphertext are included as the last - // block. The lengths are the number of bits. - y_.low ^= additional_bytes_*8; - y_.hi ^= ciphertext_bytes_*8; - MulAfterPrecomputation(product_table_, &y_); - - uint8 *result, result_tmp[16]; - if (len >= 16) { - result = reinterpret_cast(output); - } else { - result = result_tmp; - } - - Put64(result, y_.low); - Put64(result + 8, y_.hi); - - if (len < 16) - memcpy(output, result_tmp, len); -} - -// static -GaloisHash::FieldElement GaloisHash::Add( - const FieldElement& x, - const FieldElement& y) { - // Addition in a characteristic 2 field is just XOR. - FieldElement z = {x.low^y.low, x.hi^y.hi}; - return z; -} - -// static -GaloisHash::FieldElement GaloisHash::Double(const FieldElement& x) { - const bool msb_set = x.hi & 1; - - FieldElement xx; - // Because of the bit-ordering, doubling is actually a right shift. - xx.hi = x.hi >> 1; - xx.hi |= x.low << 63; - xx.low = x.low >> 1; - - // If the most-significant bit was set before shifting then it, conceptually, - // becomes a term of x^128. This is greater than the irreducible polynomial - // so the result has to be reduced. The irreducible polynomial is - // 1+x+x^2+x^7+x^128. We can subtract that to eliminate the term at x^128 - // which also means subtracting the other four terms. In characteristic 2 - // fields, subtraction == addition == XOR. - if (msb_set) - xx.low ^= 0xe100000000000000ULL; - - return xx; -} - -void GaloisHash::MulAfterPrecomputation(const FieldElement* table, - FieldElement* x) { - FieldElement z = {0, 0}; - - // In order to efficiently multiply, we use the precomputed table of i*key, - // for i in 0..15, to handle four bits at a time. We could obviously use - // larger tables for greater speedups but the next convenient table size is - // 4K, which is a little large. - // - // In other fields one would use bit positions spread out across the field in - // order to reduce the number of doublings required. However, in - // characteristic 2 fields, repeated doublings are exceptionally cheap and - // it's not worth spending more precomputation time to eliminate them. - for (unsigned i = 0; i < 2; i++) { - uint64 word; - if (i == 0) { - word = x->hi; - } else { - word = x->low; - } - - for (unsigned j = 0; j < 64; j += 4) { - Mul16(&z); - // the values in |table| are ordered for little-endian bit positions. See - // the comment in the constructor. - const FieldElement& t = table[word & 0xf]; - z.low ^= t.low; - z.hi ^= t.hi; - word >>= 4; - } - } - - *x = z; -} - -// kReductionTable allows for rapid multiplications by 16. A multiplication by -// 16 is a right shift by four bits, which results in four bits at 2**128. -// These terms have to be eliminated by dividing by the irreducible polynomial. -// In GHASH, the polynomial is such that all the terms occur in the -// least-significant 8 bits, save for the term at x^128. Therefore we can -// precompute the value to be added to the field element for each of the 16 bit -// patterns at 2**128 and the values fit within 12 bits. -static const uint16 kReductionTable[16] = { - 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, - 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0, -}; - -// static -void GaloisHash::Mul16(FieldElement* x) { - const unsigned msw = x->hi & 0xf; - x->hi >>= 4; - x->hi |= x->low << 60; - x->low >>= 4; - x->low ^= static_cast(kReductionTable[msw]) << 48; -} - -void GaloisHash::UpdateBlocks(const uint8* bytes, size_t num_blocks) { - for (size_t i = 0; i < num_blocks; i++) { - y_.low ^= Get64(bytes); - bytes += 8; - y_.hi ^= Get64(bytes); - bytes += 8; - MulAfterPrecomputation(product_table_, &y_); - } -} - -void GaloisHash::Update(const uint8* data, size_t length) { - if (buf_used_ > 0) { - const size_t n = std::min(length, sizeof(buf_) - buf_used_); - memcpy(&buf_[buf_used_], data, n); - buf_used_ += n; - length -= n; - data += n; - - if (buf_used_ == sizeof(buf_)) { - UpdateBlocks(buf_, 1); - buf_used_ = 0; - } - } - - if (length >= 16) { - const size_t n = length / 16; - UpdateBlocks(data, n); - length -= n*16; - data += n*16; - } - - if (length > 0) { - memcpy(buf_, data, length); - buf_used_ = length; - } -} - -} // namespace crypto diff --git a/crypto/ghash.h b/crypto/ghash.h deleted file mode 100644 index 6dc247be28e94..0000000000000 --- a/crypto/ghash.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2012 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 "base/basictypes.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// GaloisHash implements the polynomial authenticator part of GCM as specified -// in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf -// Specifically it implements the GHASH function, defined in section 2.3 of -// that document. -// -// In SP-800-38D, GHASH is defined differently and takes only a single data -// argument. But it is always called with an argument of a certain form: -// GHASH_H (A || 0^v || C || 0^u || [len(A)]_64 || [len(C)]_64) -// This mirrors how the gcm-revised-spec.pdf version of GHASH handles its two -// data arguments. The two GHASH functions therefore differ only in whether the -// data is formatted inside or outside of the function. -// -// WARNING: do not use this as a generic authenticator. Polynomial -// authenticators must be used in the correct manner and any use outside of GCM -// requires careful consideration. -// -// WARNING: this code is not constant time. However, in all likelihood, nor is -// the implementation of AES that is used. -class CRYPTO_EXPORT_PRIVATE GaloisHash { - public: - explicit GaloisHash(const uint8 key[16]); - - // Reset prepares to digest a fresh message with the same key. This is more - // efficient than creating a fresh object. - void Reset(); - - // UpdateAdditional hashes in `additional' data. This is data that is not - // encrypted, but is covered by the authenticator. All additional data must - // be written before any ciphertext is written. - void UpdateAdditional(const uint8* data, size_t length); - - // UpdateCiphertext hashes in ciphertext to be authenticated. - void UpdateCiphertext(const uint8* data, size_t length); - - // Finish completes the hash computation and writes at most |len| bytes of - // the result to |output|. - void Finish(void* output, size_t len); - - private: - enum State { - kHashingAdditionalData, - kHashingCiphertext, - kComplete, - }; - - struct FieldElement { - uint64 low, hi; - }; - - // Add returns |x|+|y|. - static FieldElement Add(const FieldElement& x, const FieldElement& y); - // Double returns 2*|x|. - static FieldElement Double(const FieldElement& x); - // MulAfterPrecomputation sets |x| = |x|*h where h is |table[1]| and - // table[i] = i*h for i=0..15. - static void MulAfterPrecomputation(const FieldElement* table, - FieldElement* x); - // Mul16 sets |x| = 16*|x|. - static void Mul16(FieldElement* x); - - // UpdateBlocks processes |num_blocks| 16-bytes blocks from |bytes|. - void UpdateBlocks(const uint8* bytes, size_t num_blocks); - // Update processes |length| bytes from |bytes| and calls UpdateBlocks on as - // much data as possible. It uses |buf_| to buffer any remaining data and - // always consumes all of |bytes|. - void Update(const uint8* bytes, size_t length); - - FieldElement y_; - State state_; - size_t additional_bytes_; - size_t ciphertext_bytes_; - uint8 buf_[16]; - size_t buf_used_; - FieldElement product_table_[16]; -}; - -} // namespace crypto diff --git a/crypto/ghash_unittest.cc b/crypto/ghash_unittest.cc deleted file mode 100644 index 5dd88ed5c8d2c..0000000000000 --- a/crypto/ghash_unittest.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2012 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 - -#include "crypto/ghash.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -namespace { - -// Test vectors are taken from Appendix B of -// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf - -static const uint8 kKey1[16] = { - 0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, - 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e, -}; - -static const uint8 kCiphertext2[] = { - 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, - 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78, -}; - -static const uint8 kKey3[16] = { - 0xb8, 0x3b, 0x53, 0x37, 0x08, 0xbf, 0x53, 0x5d, - 0x0a, 0xa6, 0xe5, 0x29, 0x80, 0xd5, 0x3b, 0x78, -}; - -static const uint8 kCiphertext3[] = { - 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, -}; - -static const uint8 kAdditional4[] = { - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2, -}; - -struct TestCase { - const uint8* key; - const uint8* additional; - unsigned additional_length; - const uint8* ciphertext; - unsigned ciphertext_length; - const uint8 expected[16]; -}; - -static const TestCase kTestCases[] = { - { - kKey1, - NULL, - 0, - NULL, - 0, - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, - { - kKey1, - NULL, - 0, - kCiphertext2, - sizeof(kCiphertext2), - { - 0xf3, 0x8c, 0xbb, 0x1a, 0xd6, 0x92, 0x23, 0xdc, - 0xc3, 0x45, 0x7a, 0xe5, 0xb6, 0xb0, 0xf8, 0x85, - }, - }, - { - kKey3, - NULL, - 0, - kCiphertext3, - sizeof(kCiphertext3), - { - 0x7f, 0x1b, 0x32, 0xb8, 0x1b, 0x82, 0x0d, 0x02, - 0x61, 0x4f, 0x88, 0x95, 0xac, 0x1d, 0x4e, 0xac, - }, - }, - { - kKey3, - kAdditional4, - sizeof(kAdditional4), - kCiphertext3, - sizeof(kCiphertext3) - 4, - { - 0x69, 0x8e, 0x57, 0xf7, 0x0e, 0x6e, 0xcc, 0x7f, - 0xd9, 0x46, 0x3b, 0x72, 0x60, 0xa9, 0xae, 0x5f, - }, - }, -}; - -TEST(GaloisHash, TestCases) { - uint8 out[16]; - - for (size_t i = 0; i < arraysize(kTestCases); ++i) { - const TestCase& test = kTestCases[i]; - - GaloisHash hash(test.key); - if (test.additional_length) - hash.UpdateAdditional(test.additional, test.additional_length); - if (test.ciphertext_length) - hash.UpdateCiphertext(test.ciphertext, test.ciphertext_length); - hash.Finish(out, sizeof(out)); - EXPECT_TRUE(0 == memcmp(out, test.expected, 16)); - } -} - -TEST(GaloisHash, VaryLengths) { - uint8 out[16]; - - for (size_t chunk_size = 1; chunk_size < 16; chunk_size++) { - for (size_t i = 0; i < arraysize(kTestCases); ++i) { - const TestCase& test = kTestCases[i]; - - GaloisHash hash(test.key); - for (size_t i = 0; i < test.additional_length;) { - size_t n = std::min(test.additional_length - i, chunk_size); - hash.UpdateAdditional(test.additional + i, n); - i += n; - } - for (size_t i = 0; i < test.ciphertext_length;) { - size_t n = std::min(test.ciphertext_length - i, chunk_size); - hash.UpdateCiphertext(test.ciphertext + i, n); - i += n; - } - hash.Finish(out, sizeof(out)); - EXPECT_TRUE(0 == memcmp(out, test.expected, 16)); - } - } -} - -} // namespace - -} // namespace crypto diff --git a/crypto/hkdf.cc b/crypto/hkdf.cc deleted file mode 100644 index 82aae24679e45..0000000000000 --- a/crypto/hkdf.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2013 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/hkdf.h" - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "crypto/hmac.h" - -namespace crypto { - -const size_t kSHA256HashLength = 32; - -HKDF::HKDF(const base::StringPiece& secret, - const base::StringPiece& salt, - const base::StringPiece& info, - size_t key_bytes_to_generate, - size_t iv_bytes_to_generate, - size_t subkey_secret_bytes_to_generate) { - // https://tools.ietf.org/html/rfc5869#section-2.2 - base::StringPiece actual_salt = salt; - char zeros[kSHA256HashLength]; - if (actual_salt.empty()) { - // If salt is not given, HashLength zeros are used. - memset(zeros, 0, sizeof(zeros)); - actual_salt.set(zeros, sizeof(zeros)); - } - - // Perform the Extract step to transform the input key and - // salt into the pseudorandom key (PRK) used for Expand. - HMAC prk_hmac(HMAC::SHA256); - bool result = prk_hmac.Init(actual_salt); - DCHECK(result); - - // |prk| is a pseudorandom key (of kSHA256HashLength octets). - uint8 prk[kSHA256HashLength]; - DCHECK_EQ(sizeof(prk), prk_hmac.DigestLength()); - result = prk_hmac.Sign(secret, prk, sizeof(prk)); - DCHECK(result); - - // https://tools.ietf.org/html/rfc5869#section-2.3 - // Perform the Expand phase to turn the pseudorandom key - // and info into the output keying material. - const size_t material_length = 2 * key_bytes_to_generate + - 2 * iv_bytes_to_generate + - subkey_secret_bytes_to_generate; - const size_t n = (material_length + kSHA256HashLength-1) / - kSHA256HashLength; - DCHECK_LT(n, 256u); - - output_.resize(n * kSHA256HashLength); - base::StringPiece previous; - - scoped_ptr buf(new char[kSHA256HashLength + info.size() + 1]); - uint8 digest[kSHA256HashLength]; - - HMAC hmac(HMAC::SHA256); - result = hmac.Init(prk, sizeof(prk)); - DCHECK(result); - - for (size_t i = 0; i < n; i++) { - memcpy(buf.get(), previous.data(), previous.size()); - size_t j = previous.size(); - memcpy(buf.get() + j, info.data(), info.size()); - j += info.size(); - buf[j++] = static_cast(i + 1); - - result = hmac.Sign(base::StringPiece(buf.get(), j), digest, sizeof(digest)); - DCHECK(result); - - memcpy(&output_[i*sizeof(digest)], digest, sizeof(digest)); - previous = base::StringPiece(reinterpret_cast(digest), - sizeof(digest)); - } - - size_t j = 0; - // On Windows, when the size of output_ is zero, dereference of 0'th element - // results in a crash. C++11 solves this problem by adding a data() getter - // method to std::vector. - if (key_bytes_to_generate) { - client_write_key_ = base::StringPiece(reinterpret_cast(&output_[j]), - key_bytes_to_generate); - j += key_bytes_to_generate; - server_write_key_ = base::StringPiece(reinterpret_cast(&output_[j]), - key_bytes_to_generate); - j += key_bytes_to_generate; - } - - if (iv_bytes_to_generate) { - client_write_iv_ = base::StringPiece(reinterpret_cast(&output_[j]), - iv_bytes_to_generate); - j += iv_bytes_to_generate; - server_write_iv_ = base::StringPiece(reinterpret_cast(&output_[j]), - iv_bytes_to_generate); - j += iv_bytes_to_generate; - } - if (subkey_secret_bytes_to_generate) { - subkey_secret_ = base::StringPiece(reinterpret_cast(&output_[j]), - subkey_secret_bytes_to_generate); - } -} - -HKDF::~HKDF() { -} - -} // namespace crypto diff --git a/crypto/hkdf.h b/crypto/hkdf.h deleted file mode 100644 index e91bccf5b4f38..0000000000000 --- a/crypto/hkdf.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2013 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_HKDF_H_ -#define CRYPTO_HKDF_H_ - -#include - -#include "base/basictypes.h" -#include "base/strings/string_piece.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// HKDF implements the key derivation function specified in RFC 5869 (using -// SHA-256) and outputs key material, as needed by QUIC. -// See https://tools.ietf.org/html/rfc5869 for details. -class CRYPTO_EXPORT HKDF { - public: - // |secret|: the input shared secret (or, from RFC 5869, the IKM). - // |salt|: an (optional) public salt / non-secret random value. While - // optional, callers are strongly recommended to provide a salt. There is no - // added security value in making this larger than the SHA-256 block size of - // 64 bytes. - // |info|: an (optional) label to distinguish different uses of HKDF. It is - // optional context and application specific information (can be a zero-length - // string). - // |key_bytes_to_generate|: the number of bytes of key material to generate - // for both client and server. - // |iv_bytes_to_generate|: the number of bytes of IV to generate for both - // client and server. - // |subkey_secret_bytes_to_generate|: the number of bytes of subkey secret to - // generate, shared between client and server. - HKDF(const base::StringPiece& secret, - const base::StringPiece& salt, - const base::StringPiece& info, - size_t key_bytes_to_generate, - size_t iv_bytes_to_generate, - size_t subkey_secret_bytes_to_generate); - ~HKDF(); - - base::StringPiece client_write_key() const { - return client_write_key_; - } - base::StringPiece client_write_iv() const { - return client_write_iv_; - } - base::StringPiece server_write_key() const { - return server_write_key_; - } - base::StringPiece server_write_iv() const { - return server_write_iv_; - } - base::StringPiece subkey_secret() const { - return subkey_secret_; - } - - private: - std::vector output_; - - base::StringPiece client_write_key_; - base::StringPiece server_write_key_; - base::StringPiece client_write_iv_; - base::StringPiece server_write_iv_; - base::StringPiece subkey_secret_; -}; - -} // namespace crypto - -#endif // CRYPTO_HKDF_H_ diff --git a/crypto/hkdf_unittest.cc b/crypto/hkdf_unittest.cc deleted file mode 100644 index bcb19c5c10d18..0000000000000 --- a/crypto/hkdf_unittest.cc +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2013 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/hkdf.h" - -#include - -#include "base/strings/string_number_conversions.h" -#include "testing/gtest/include/gtest/gtest.h" - -using crypto::HKDF; - -namespace test { -namespace { - -struct HKDFTest { - const char* key_hex; - const char* salt_hex; - const char* info_hex; - const char* output_hex; -}; - -// These test cases are taken from -// https://tools.ietf.org/html/rfc5869#appendix-A. -static const HKDFTest kHKDFTests[] = {{ - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5" - "b887185865", - }, { - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324" - "25262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849" - "4a4b4c4d4e4f", - "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384" - "85868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9" - "aaabacadaeaf", - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4" - "d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9" - "fafbfcfdfeff", - "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99ca" - "c7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c" - "01d5c1f3434f1d87", - }, { - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "", - "", - "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395fa" - "a4b61a96c8", - }, -}; - -TEST(HKDFTest, HKDF) { - for (size_t i = 0; i < arraysize(kHKDFTests); i++) { - const HKDFTest& test(kHKDFTests[i]); - SCOPED_TRACE(i); - - std::vector data; - ASSERT_TRUE(base::HexStringToBytes(test.key_hex, &data)); - const std::string key(reinterpret_cast(&data[0]), data.size()); - - data.clear(); - // |salt_hex| is optional and may be empty. - std::string salt(test.salt_hex); - if (!salt.empty()) { - ASSERT_TRUE(base::HexStringToBytes(salt, &data)); - salt.assign(reinterpret_cast(&data[0]), data.size()); - } - - data.clear(); - // |info_hex| is optional and may be empty. - std::string info(test.info_hex); - if (!info.empty()) { - ASSERT_TRUE(base::HexStringToBytes(info, &data)); - info.assign(reinterpret_cast(&data[0]), data.size()); - } - - data.clear(); - ASSERT_TRUE(base::HexStringToBytes(test.output_hex, &data)); - const std::string expected(reinterpret_cast(&data[0]), data.size()); - - // We set the key_length to the length of the expected output and then take - // the result from the first key, which is the client write key. - HKDF hkdf(key, salt, info, expected.size(), 0, 0); - - ASSERT_EQ(expected.size(), hkdf.client_write_key().size()); - EXPECT_EQ(0, memcmp(expected.data(), hkdf.client_write_key().data(), - expected.size())); - } -} - -} // namespace -} // namespace test diff --git a/crypto/hmac.cc b/crypto/hmac.cc deleted file mode 100644 index c9a2b74d983ed..0000000000000 --- a/crypto/hmac.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2012 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/hmac.h" - -#include - -#include "base/logging.h" -#include "crypto/secure_util.h" -#include "crypto/symmetric_key.h" - -namespace crypto { - -bool HMAC::Init(SymmetricKey* key) { - std::string raw_key; - bool result = key->GetRawKey(&raw_key) && Init(raw_key); - // Zero out key copy. This might get optimized away, but one can hope. - // Using std::string to store key info at all is a larger problem. - std::fill(raw_key.begin(), raw_key.end(), 0); - return result; -} - -size_t HMAC::DigestLength() const { - switch (hash_alg_) { - case SHA1: - return 20; - case SHA256: - return 32; - default: - NOTREACHED(); - return 0; - } -} - -bool HMAC::Verify(const base::StringPiece& data, - const base::StringPiece& digest) const { - if (digest.size() != DigestLength()) - return false; - return VerifyTruncated(data, digest); -} - -bool HMAC::VerifyTruncated(const base::StringPiece& data, - const base::StringPiece& digest) const { - if (digest.empty()) - return false; - size_t digest_length = DigestLength(); - scoped_ptr computed_digest( - new unsigned char[digest_length]); - if (!Sign(data, computed_digest.get(), digest_length)) - return false; - - return SecureMemEqual(digest.data(), computed_digest.get(), - std::min(digest.size(), digest_length)); -} - -} // namespace crypto diff --git a/crypto/hmac.h b/crypto/hmac.h deleted file mode 100644 index c7b22fa1bdff4..0000000000000 --- a/crypto/hmac.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 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. - -// Utility class for calculating the HMAC for a given message. We currently -// only support SHA1 for the hash algorithm, but this can be extended easily. - -#ifndef CRYPTO_HMAC_H_ -#define CRYPTO_HMAC_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_piece.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// Simplify the interface and reduce includes by abstracting out the internals. -struct HMACPlatformData; -class SymmetricKey; - -class CRYPTO_EXPORT HMAC { - public: - // The set of supported hash functions. Extend as required. - enum HashAlgorithm { - SHA1, - SHA256, - }; - - explicit HMAC(HashAlgorithm hash_alg); - ~HMAC(); - - // Returns the length of digest that this HMAC will create. - size_t DigestLength() const; - - // TODO(abarth): Add a PreferredKeyLength() member function. - - // Initializes this instance using |key| of the length |key_length|. Call Init - // only once. It returns false on the second or later calls. - // - // NOTE: the US Federal crypto standard FIPS 198, Section 3 says: - // The size of the key, K, shall be equal to or greater than L/2, where L - // is the size of the hash function output. - // In FIPS 198-1 (and SP-800-107, which describes key size recommendations), - // this requirement is gone. But a system crypto library may still enforce - // this old requirement. If the key is shorter than this recommended value, - // Init() may fail. - bool Init(const unsigned char* key, size_t key_length) WARN_UNUSED_RESULT; - - // Initializes this instance using |key|. Call Init - // only once. It returns false on the second or later calls. - bool Init(SymmetricKey* key) WARN_UNUSED_RESULT; - - // Initializes this instance using |key|. Call Init only once. It returns - // false on the second or later calls. - bool Init(const base::StringPiece& key) WARN_UNUSED_RESULT { - return Init(reinterpret_cast(key.data()), - key.size()); - } - - // Calculates the HMAC for the message in |data| using the algorithm supplied - // to the constructor and the key supplied to the Init method. The HMAC is - // returned in |digest|, which has |digest_length| bytes of storage available. - bool Sign(const base::StringPiece& data, unsigned char* digest, - size_t digest_length) const WARN_UNUSED_RESULT; - - // Verifies that the HMAC for the message in |data| equals the HMAC provided - // in |digest|, using the algorithm supplied to the constructor and the key - // supplied to the Init method. Use of this method is strongly recommended - // over using Sign() with a manual comparison (such as memcmp), as such - // comparisons may result in side-channel disclosures, such as timing, that - // undermine the cryptographic integrity. |digest| must be exactly - // |DigestLength()| bytes long. - bool Verify(const base::StringPiece& data, - const base::StringPiece& digest) const WARN_UNUSED_RESULT; - - // Verifies a truncated HMAC, behaving identical to Verify(), except - // that |digest| is allowed to be smaller than |DigestLength()|. - bool VerifyTruncated( - const base::StringPiece& data, - const base::StringPiece& digest) const WARN_UNUSED_RESULT; - - private: - HashAlgorithm hash_alg_; - scoped_ptr plat_; - - DISALLOW_COPY_AND_ASSIGN(HMAC); -}; - -} // namespace crypto - -#endif // CRYPTO_HMAC_H_ diff --git a/crypto/hmac_nss.cc b/crypto/hmac_nss.cc deleted file mode 100644 index e14282c916616..0000000000000 --- a/crypto/hmac_nss.cc +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2011 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/hmac.h" - -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "crypto/nss_util.h" -#include "crypto/scoped_nss_types.h" - -namespace crypto { - -struct HMACPlatformData { - CK_MECHANISM_TYPE mechanism_; - ScopedPK11Slot slot_; - ScopedPK11SymKey sym_key_; -}; - -HMAC::HMAC(HashAlgorithm hash_alg) - : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { - // Only SHA-1 and SHA-256 hash algorithms are supported. - switch (hash_alg_) { - case SHA1: - plat_->mechanism_ = CKM_SHA_1_HMAC; - break; - case SHA256: - plat_->mechanism_ = CKM_SHA256_HMAC; - break; - default: - NOTREACHED() << "Unsupported hash algorithm"; - break; - } -} - -HMAC::~HMAC() { -} - -bool HMAC::Init(const unsigned char *key, size_t key_length) { - EnsureNSSInit(); - - if (plat_->slot_.get()) { - // Init must not be called more than twice on the same HMAC object. - NOTREACHED(); - return false; - } - - plat_->slot_.reset(PK11_GetInternalSlot()); - if (!plat_->slot_.get()) { - NOTREACHED(); - return false; - } - - SECItem key_item; - key_item.type = siBuffer; - key_item.data = const_cast(key); // NSS API isn't const. - key_item.len = key_length; - - plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(), - plat_->mechanism_, - PK11_OriginUnwrap, - CKA_SIGN, - &key_item, - NULL)); - if (!plat_->sym_key_.get()) { - NOTREACHED(); - return false; - } - - return true; -} - -bool HMAC::Sign(const base::StringPiece& data, - unsigned char* digest, - size_t digest_length) const { - if (!plat_->sym_key_.get()) { - // Init has not been called before Sign. - NOTREACHED(); - return false; - } - - SECItem param = { siBuffer, NULL, 0 }; - ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_, - CKA_SIGN, - plat_->sym_key_.get(), - ¶m)); - if (!context.get()) { - NOTREACHED(); - return false; - } - - if (PK11_DigestBegin(context.get()) != SECSuccess) { - NOTREACHED(); - return false; - } - - if (PK11_DigestOp(context.get(), - reinterpret_cast(data.data()), - data.length()) != SECSuccess) { - NOTREACHED(); - return false; - } - - unsigned int len = 0; - if (PK11_DigestFinal(context.get(), - digest, &len, digest_length) != SECSuccess) { - NOTREACHED(); - return false; - } - - return true; -} - -} // namespace crypto diff --git a/crypto/hmac_openssl.cc b/crypto/hmac_openssl.cc deleted file mode 100644 index ef20290e22320..0000000000000 --- a/crypto/hmac_openssl.cc +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2011 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/hmac.h" - -#include - -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "crypto/openssl_util.h" - -namespace crypto { - -struct HMACPlatformData { - std::vector key; -}; - -HMAC::HMAC(HashAlgorithm hash_alg) : hash_alg_(hash_alg) { - // Only SHA-1 and SHA-256 hash algorithms are supported now. - DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); -} - -bool HMAC::Init(const unsigned char* key, size_t key_length) { - // Init must not be called more than once on the same HMAC object. - DCHECK(!plat_); - plat_.reset(new HMACPlatformData()); - plat_->key.assign(key, key + key_length); - return true; -} - -HMAC::~HMAC() { - if (plat_) { - // Zero out key copy. - plat_->key.assign(plat_->key.size(), 0); - STLClearObject(&plat_->key); - } -} - -bool HMAC::Sign(const base::StringPiece& data, - unsigned char* digest, - size_t digest_length) const { - DCHECK(plat_); // Init must be called before Sign. - - ScopedOpenSSLSafeSizeBuffer result(digest, digest_length); - return !!::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), - vector_as_array(&plat_->key), plat_->key.size(), - reinterpret_cast(data.data()), - data.size(), result.safe_buffer(), NULL); -} - -} // namespace crypto diff --git a/crypto/hmac_unittest.cc b/crypto/hmac_unittest.cc deleted file mode 100644 index 91eccd68e231d..0000000000000 --- a/crypto/hmac_unittest.cc +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (c) 2011 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 - -#include "crypto/hmac.h" -#include "testing/gtest/include/gtest/gtest.h" - -static const size_t kSHA1DigestSize = 20; -static const size_t kSHA256DigestSize = 32; - -static const char* kSimpleKey = - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; -static const size_t kSimpleKeyLength = 80; - -static const struct { - const char *data; - const int data_len; - const char *digest; -} kSimpleHmacCases[] = { - { "Test Using Larger Than Block-Size Key - Hash Key First", 54, - "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55" - "\xED\x40\x21\x12" }, - { "Test Using Larger Than Block-Size Key and Larger " - "Than One Block-Size Data", 73, - "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08" - "\xBB\xFF\x1A\x91" } -}; - -TEST(HMACTest, HmacSafeBrowsingResponseTest) { - const int kKeySize = 16; - - // Client key. - const unsigned char kClientKey[kKeySize] = - { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd, - 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 }; - - // Expected HMAC result using kMessage and kClientKey. - const unsigned char kReceivedHmac[kSHA1DigestSize] = - { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52, - 0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad, - 0x86, 0xd2, 0x48, 0x85 }; - - const char kMessage[] = -"n:1896\ni:goog-malware-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav" -"ar_s_445-450\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_439-444\nu:s" -".ytimg.com/safebrowsing/rd/goog-malware-shavar_s_437\nu:s.ytimg.com/safebrowsi" -"ng/rd/goog-malware-shavar_s_436\nu:s.ytimg.com/safebrowsing/rd/goog-malware-sh" -"avar_s_433-435\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_431\nu:s.y" -"timg.com/safebrowsing/rd/goog-malware-shavar_s_430\nu:s.ytimg.com/safebrowsing" -"/rd/goog-malware-shavar_s_429\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav" -"ar_s_428\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_426\nu:s.ytimg.c" -"om/safebrowsing/rd/goog-malware-shavar_s_424\nu:s.ytimg.com/safebrowsing/rd/go" -"og-malware-shavar_s_423\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4" -"22\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_420\nu:s.ytimg.com/saf" -"ebrowsing/rd/goog-malware-shavar_s_419\nu:s.ytimg.com/safebrowsing/rd/goog-mal" -"ware-shavar_s_414\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_409-411" -"\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_405\nu:s.ytimg.com/safeb" -"rowsing/rd/goog-malware-shavar_s_404\nu:s.ytimg.com/safebrowsing/rd/goog-malwa" -"re-shavar_s_402\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_401\nu:s." -"ytimg.com/safebrowsing/rd/goog-malware-shavar_a_973-978\nu:s.ytimg.com/safebro" -"wsing/rd/goog-malware-shavar_a_937-972\nu:s.ytimg.com/safebrowsing/rd/goog-mal" -"ware-shavar_a_931-936\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_925" -"-930\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_919-924\ni:goog-phis" -"h-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2633\nu:s.ytimg.co" -"m/safebrowsing/rd/goog-phish-shavar_a_2632\nu:s.ytimg.com/safebrowsing/rd/goog" -"-phish-shavar_a_2629-2631\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2" -"626-2628\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2625\n"; - - std::string message_data(kMessage); - - crypto::HMAC hmac(crypto::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(kClientKey, kKeySize)); - unsigned char calculated_hmac[kSHA1DigestSize]; - - EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize)); -} - -// Test cases from RFC 2202 section 3 -TEST(HMACTest, RFC2202TestCases) { - const struct { - const char *key; - const int key_len; - const char *data; - const int data_len; - const char *digest; - } cases[] = { - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" - "\x0B\x0B\x0B\x0B", 20, - "Hi There", 8, - "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E" - "\xF1\x46\xBE\x00" }, - { "Jefe", 4, - "what do ya want for nothing?", 28, - "\xEF\xFC\xDF\x6A\xE5\xEB\x2F\xA2\xD2\x74\x16\xD5\xF1\x84\xDF\x9C" - "\x25\x9A\x7C\x79" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA", 20, - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD", 50, - "\x12\x5D\x73\x42\xB9\xAC\x11\xCD\x91\xA3\x9A\xF4\x8A\xA1\x7B\x4F" - "\x63\xF1\x75\xD3" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25, - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD", 50, - "\x4C\x90\x07\xF4\x02\x62\x50\xC6\xBC\x84\x14\xF9\xBF\x50\xC8\x6C" - "\x2D\x72\x35\xDA" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" - "\x0C\x0C\x0C\x0C", 20, - "Test With Truncation", 20, - "\x4C\x1A\x03\x42\x4B\x55\xE0\x7F\xE7\xF2\x7B\xE1\xD5\x8B\xB9\x32" - "\x4A\x9A\x5A\x04" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", - 80, - "Test Using Larger Than Block-Size Key - Hash Key First", 54, - "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55" - "\xED\x40\x21\x12" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", - 80, - "Test Using Larger Than Block-Size Key and Larger " - "Than One Block-Size Data", 73, - "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08" - "\xBB\xFF\x1A\x91" } - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - crypto::HMAC hmac(crypto::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(reinterpret_cast(cases[i].key), - cases[i].key_len)); - std::string data_string(cases[i].data, cases[i].data_len); - unsigned char digest[kSHA1DigestSize]; - EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize)); - } -} - -// TODO(wtc): add other test vectors from RFC 4231. -TEST(HMACTest, RFC4231TestCase6) { - unsigned char key[131]; - for (size_t i = 0; i < sizeof(key); ++i) - key[i] = 0xaa; - - std::string data = "Test Using Larger Than Block-Size Key - Hash Key First"; - ASSERT_EQ(54U, data.size()); - - static unsigned char kKnownHMACSHA256[] = { - 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, - 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, - 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, - 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 - }; - - crypto::HMAC hmac(crypto::HMAC::SHA256); - ASSERT_TRUE(hmac.Init(key, sizeof(key))); - unsigned char calculated_hmac[kSHA256DigestSize]; - - EXPECT_EQ(kSHA256DigestSize, hmac.DigestLength()); - EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize)); - EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize)); -} - -// Based on NSS's FIPS HMAC power-up self-test. -TEST(HMACTest, NSSFIPSPowerUpSelfTest) { - static const char kKnownMessage[] = - "The test message for the MD2, MD5, and SHA-1 hashing algorithms."; - - static const unsigned char kKnownSecretKey[] = { - 0x46, 0x69, 0x72, 0x65, 0x66, 0x6f, 0x78, 0x20, - 0x61, 0x6e, 0x64, 0x20, 0x54, 0x68, 0x75, 0x6e, - 0x64, 0x65, 0x72, 0x42, 0x69, 0x72, 0x64, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x61, 0x77, 0x65, 0x73, - 0x6f, 0x6d, 0x65, 0x21, 0x00 - }; - - static const size_t kKnownSecretKeySize = sizeof(kKnownSecretKey); - - // HMAC-SHA-1 known answer (20 bytes). - static const unsigned char kKnownHMACSHA1[] = { - 0xd5, 0x85, 0xf6, 0x5b, 0x39, 0xfa, 0xb9, 0x05, - 0x3b, 0x57, 0x1d, 0x61, 0xe7, 0xb8, 0x84, 0x1e, - 0x5d, 0x0e, 0x1e, 0x11 - }; - - // HMAC-SHA-256 known answer (32 bytes). - static const unsigned char kKnownHMACSHA256[] = { - 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44, - 0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14, 0x22, 0xe0, - 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9, - 0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48 - }; - - std::string message_data(kKnownMessage); - - crypto::HMAC hmac(crypto::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(kKnownSecretKey, kKnownSecretKeySize)); - unsigned char calculated_hmac[kSHA1DigestSize]; - - EXPECT_EQ(kSHA1DigestSize, hmac.DigestLength()); - EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize)); - EXPECT_TRUE(hmac.Verify( - message_data, - base::StringPiece(reinterpret_cast(kKnownHMACSHA1), - kSHA1DigestSize))); - EXPECT_TRUE(hmac.VerifyTruncated( - message_data, - base::StringPiece(reinterpret_cast(kKnownHMACSHA1), - kSHA1DigestSize / 2))); - - crypto::HMAC hmac2(crypto::HMAC::SHA256); - ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize)); - unsigned char calculated_hmac2[kSHA256DigestSize]; - - EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize)); - EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize)); -} - -TEST(HMACTest, HMACObjectReuse) { - crypto::HMAC hmac(crypto::HMAC::SHA1); - ASSERT_TRUE( - hmac.Init(reinterpret_cast(kSimpleKey), - kSimpleKeyLength)); - for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) { - std::string data_string(kSimpleHmacCases[i].data, - kSimpleHmacCases[i].data_len); - unsigned char digest[kSHA1DigestSize]; - EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(kSimpleHmacCases[i].digest, digest, kSHA1DigestSize)); - } -} - -TEST(HMACTest, Verify) { - crypto::HMAC hmac(crypto::HMAC::SHA1); - ASSERT_TRUE( - hmac.Init(reinterpret_cast(kSimpleKey), - kSimpleKeyLength)); - const char empty_digest[kSHA1DigestSize] = { 0 }; - for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) { - // Expected results - EXPECT_TRUE(hmac.Verify( - base::StringPiece(kSimpleHmacCases[i].data, - kSimpleHmacCases[i].data_len), - base::StringPiece(kSimpleHmacCases[i].digest, - kSHA1DigestSize))); - // Mismatched size - EXPECT_FALSE(hmac.Verify( - base::StringPiece(kSimpleHmacCases[i].data, - kSimpleHmacCases[i].data_len), - base::StringPiece(kSimpleHmacCases[i].data, - kSimpleHmacCases[i].data_len))); - - // Expected size, mismatched data - EXPECT_FALSE(hmac.Verify( - base::StringPiece(kSimpleHmacCases[i].data, - kSimpleHmacCases[i].data_len), - base::StringPiece(empty_digest, kSHA1DigestSize))); - } -} - -TEST(HMACTest, EmptyKey) { - // Test vector from https://en.wikipedia.org/wiki/HMAC - const char* kExpectedDigest = - "\xFB\xDB\x1D\x1B\x18\xAA\x6C\x08\x32\x4B\x7D\x64\xB7\x1F\xB7\x63" - "\x70\x69\x0E\x1D"; - base::StringPiece data(""); - - crypto::HMAC hmac(crypto::HMAC::SHA1); - ASSERT_TRUE(hmac.Init(NULL, 0)); - - unsigned char digest[kSHA1DigestSize]; - EXPECT_TRUE(hmac.Sign(data, digest, kSHA1DigestSize)); - EXPECT_EQ(0, memcmp(kExpectedDigest, digest, kSHA1DigestSize)); - - EXPECT_TRUE(hmac.Verify( - data, base::StringPiece(kExpectedDigest, kSHA1DigestSize))); -} diff --git a/crypto/hmac_win.cc b/crypto/hmac_win.cc deleted file mode 100644 index 99b3a60d57efb..0000000000000 --- a/crypto/hmac_win.cc +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2012 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/hmac.h" - -#include - -#include -#include - -#include "base/logging.h" -#include "crypto/scoped_capi_types.h" -#include "crypto/third_party/nss/chromium-blapi.h" -#include "crypto/third_party/nss/chromium-sha256.h" -#include "crypto/wincrypt_shim.h" - -namespace crypto { - -namespace { - -// Implementation of HMAC-SHA-256: -// -// SHA-256 is supported in Windows XP SP3 or later. We still need to support -// Windows XP SP2, so unfortunately we have to implement HMAC-SHA-256 here. - -enum { - SHA256_BLOCK_SIZE = 64 // Block size (in bytes) of the input to SHA-256. -}; - -// NSS doesn't accept size_t for text size, divide the data into smaller -// chunks as needed. -void Wrapped_SHA256_Update(SHA256Context* ctx, const unsigned char* text, - size_t text_len) { - const unsigned int kChunkSize = 1 << 30; - while (text_len > kChunkSize) { - SHA256_Update(ctx, text, kChunkSize); - text += kChunkSize; - text_len -= kChunkSize; - } - SHA256_Update(ctx, text, (unsigned int)text_len); -} - -// See FIPS 198: The Keyed-Hash Message Authentication Code (HMAC). -void ComputeHMACSHA256(const unsigned char* key, size_t key_len, - const unsigned char* text, size_t text_len, - unsigned char* output, size_t output_len) { - SHA256Context ctx; - - // Pre-process the key, if necessary. - unsigned char key0[SHA256_BLOCK_SIZE]; - if (key_len > SHA256_BLOCK_SIZE) { - SHA256_Begin(&ctx); - Wrapped_SHA256_Update(&ctx, key, key_len); - SHA256_End(&ctx, key0, NULL, SHA256_LENGTH); - memset(key0 + SHA256_LENGTH, 0, SHA256_BLOCK_SIZE - SHA256_LENGTH); - } else { - memcpy(key0, key, key_len); - if (key_len < SHA256_BLOCK_SIZE) - memset(key0 + key_len, 0, SHA256_BLOCK_SIZE - key_len); - } - - unsigned char padded_key[SHA256_BLOCK_SIZE]; - unsigned char inner_hash[SHA256_LENGTH]; - - // XOR key0 with ipad. - for (int i = 0; i < SHA256_BLOCK_SIZE; ++i) - padded_key[i] = key0[i] ^ 0x36; - - // Compute the inner hash. - SHA256_Begin(&ctx); - SHA256_Update(&ctx, padded_key, SHA256_BLOCK_SIZE); - Wrapped_SHA256_Update(&ctx, text, text_len); - SHA256_End(&ctx, inner_hash, NULL, SHA256_LENGTH); - - // XOR key0 with opad. - for (int i = 0; i < SHA256_BLOCK_SIZE; ++i) - padded_key[i] = key0[i] ^ 0x5c; - - // Compute the outer hash. - SHA256_Begin(&ctx); - SHA256_Update(&ctx, padded_key, SHA256_BLOCK_SIZE); - SHA256_Update(&ctx, inner_hash, SHA256_LENGTH); - SHA256_End(&ctx, output, NULL, (unsigned int) output_len); -} - -} // namespace - -struct HMACPlatformData { - ~HMACPlatformData() { - if (!raw_key_.empty()) { - SecureZeroMemory(&raw_key_[0], raw_key_.size()); - } - - // Destroy the key before releasing the provider. - key_.reset(); - } - - ScopedHCRYPTPROV provider_; - ScopedHCRYPTKEY key_; - - // For HMAC-SHA-256 only. - std::vector raw_key_; -}; - -HMAC::HMAC(HashAlgorithm hash_alg) - : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { - // Only SHA-1 and SHA-256 hash algorithms are supported now. - DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); -} - -bool HMAC::Init(const unsigned char* key, size_t key_length) { - if (plat_->provider_ || plat_->key_ || !plat_->raw_key_.empty()) { - // Init must not be called more than once on the same HMAC object. - NOTREACHED(); - return false; - } - - if (hash_alg_ == SHA256) { - plat_->raw_key_.assign(key, key + key_length); - return true; - } - - if (!CryptAcquireContext(plat_->provider_.receive(), NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - NOTREACHED(); - return false; - } - - // This code doesn't work on Win2k because PLAINTEXTKEYBLOB and - // CRYPT_IPSEC_HMAC_KEY are not supported on Windows 2000. PLAINTEXTKEYBLOB - // allows the import of an unencrypted key. For Win2k support, a cubmbersome - // exponent-of-one key procedure must be used: - // http://support.microsoft.com/kb/228786/en-us - // CRYPT_IPSEC_HMAC_KEY allows keys longer than 16 bytes. - - struct KeyBlob { - BLOBHEADER header; - DWORD key_size; - BYTE key_data[1]; - }; - size_t key_blob_size = std::max(offsetof(KeyBlob, key_data) + key_length, - sizeof(KeyBlob)); - std::vector key_blob_storage = std::vector(key_blob_size); - KeyBlob* key_blob = reinterpret_cast(&key_blob_storage[0]); - key_blob->header.bType = PLAINTEXTKEYBLOB; - key_blob->header.bVersion = CUR_BLOB_VERSION; - key_blob->header.reserved = 0; - key_blob->header.aiKeyAlg = CALG_RC2; - key_blob->key_size = static_cast(key_length); - memcpy(key_blob->key_data, key, key_length); - - if (!CryptImportKey(plat_->provider_, &key_blob_storage[0], - (DWORD)key_blob_storage.size(), 0, - CRYPT_IPSEC_HMAC_KEY, plat_->key_.receive())) { - NOTREACHED(); - return false; - } - - // Destroy the copy of the key. - SecureZeroMemory(key_blob->key_data, key_length); - - return true; -} - -HMAC::~HMAC() { -} - -bool HMAC::Sign(const base::StringPiece& data, - unsigned char* digest, - size_t digest_length) const { - if (hash_alg_ == SHA256) { - if (plat_->raw_key_.empty()) - return false; - ComputeHMACSHA256(&plat_->raw_key_[0], plat_->raw_key_.size(), - reinterpret_cast(data.data()), - data.size(), digest, digest_length); - return true; - } - - if (!plat_->provider_ || !plat_->key_) - return false; - - if (hash_alg_ != SHA1) { - NOTREACHED(); - return false; - } - - ScopedHCRYPTHASH hash; - if (!CryptCreateHash(plat_->provider_, CALG_HMAC, plat_->key_, 0, - hash.receive())) - return false; - - HMAC_INFO hmac_info; - memset(&hmac_info, 0, sizeof(hmac_info)); - hmac_info.HashAlgid = CALG_SHA1; - if (!CryptSetHashParam(hash, HP_HMAC_INFO, - reinterpret_cast(&hmac_info), 0)) - return false; - - if (!CryptHashData(hash, reinterpret_cast(data.data()), - static_cast(data.size()), 0)) - return false; - - DWORD sha1_size = static_cast(digest_length); - return !!CryptGetHashParam(hash, HP_HASHVAL, digest, &sha1_size, 0); -} - -} // namespace crypto diff --git a/crypto/mac_security_services_lock.cc b/crypto/mac_security_services_lock.cc deleted file mode 100644 index c0b8712089e9c..0000000000000 --- a/crypto/mac_security_services_lock.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2011 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/mac_security_services_lock.h" - -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" - -namespace { - -// This singleton pertains to Apple's wrappers over their own CSSM handles, -// as opposed to our own CSSM_CSP_HANDLE in cssm_init.cc. -class SecurityServicesSingleton { - public: - static SecurityServicesSingleton* GetInstance() { - return Singleton >::get(); - } - - base::Lock& lock() { return lock_; } - - private: - friend struct DefaultSingletonTraits; - - SecurityServicesSingleton() {} - ~SecurityServicesSingleton() {} - - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(SecurityServicesSingleton); -}; - -} // namespace - -namespace crypto { - -base::Lock& GetMacSecurityServicesLock() { - return SecurityServicesSingleton::GetInstance()->lock(); -} - -} // namespace crypto diff --git a/crypto/mac_security_services_lock.h b/crypto/mac_security_services_lock.h deleted file mode 100644 index fe56c6f38e26b..0000000000000 --- a/crypto/mac_security_services_lock.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2012 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_MAC_SECURITY_SERVICES_LOCK_H_ -#define CRYPTO_MAC_SECURITY_SERVICES_LOCK_H_ - -#include "crypto/crypto_export.h" - -namespace base { -class Lock; -} - -namespace crypto { - -// The Mac OS X certificate and key management wrappers over CSSM are not -// thread-safe. In particular, code that accesses the CSSM database is -// problematic. -// -// http://developer.apple.com/mac/library/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html -CRYPTO_EXPORT base::Lock& GetMacSecurityServicesLock(); - -} // namespace crypto - -#endif // CRYPTO_MAC_SECURITY_SERVICES_LOCK_H_ diff --git a/crypto/mock_apple_keychain.cc b/crypto/mock_apple_keychain.cc deleted file mode 100644 index a1faa65382a78..0000000000000 --- a/crypto/mock_apple_keychain.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2012 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 "base/logging.h" -#include "base/metrics/histogram.h" -#include "base/time/time.h" -#include "crypto/mock_apple_keychain.h" - -namespace { - -// Adds an entry to a local histogram to indicate that the Apple Keychain would -// have been accessed, if this class were not a mock of the Apple Keychain. -void IncrementKeychainAccessHistogram() { - // This local histogram is accessed by Telemetry to track the number of times - // the keychain is accessed, since keychain access is known to be synchronous - // and slow. - LOCAL_HISTOGRAM_BOOLEAN("OSX.Keychain.Access", true); -} - -} // namespace - -namespace crypto { - -OSStatus MockAppleKeychain::FindGenericPassword( - CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const { - IncrementKeychainAccessHistogram(); - - // When simulating |noErr|, return canned |passwordData| and - // |passwordLength|. Otherwise, just return given code. - if (find_generic_result_ == noErr) { - static const char kPassword[] = "my_password"; - DCHECK(passwordData); - // The function to free this data is mocked so the cast is fine. - *passwordData = const_cast(kPassword); - DCHECK(passwordLength); - *passwordLength = arraysize(kPassword); - password_data_count_++; - } - - return find_generic_result_; -} - -OSStatus MockAppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const { - // No-op. - password_data_count_--; - return noErr; -} - -OSStatus MockAppleKeychain::AddGenericPassword( - SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - IncrementKeychainAccessHistogram(); - - called_add_generic_ = true; - - DCHECK_GT(passwordLength, 0U); - DCHECK(passwordData); - add_generic_password_ = - std::string(const_cast(static_cast(passwordData)), - passwordLength); - return noErr; -} - -std::string MockAppleKeychain::GetEncryptionPassword() const { - IncrementKeychainAccessHistogram(); - return "mock_password"; -} - -} // namespace crypto diff --git a/crypto/mock_apple_keychain.h b/crypto/mock_apple_keychain.h deleted file mode 100644 index f73d3a6466ed2..0000000000000 --- a/crypto/mock_apple_keychain.h +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (c) 2012 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_MOCK_KEYCHAIN_MAC_H_ -#define CRYPTO_MOCK_KEYCHAIN_MAC_H_ - -#include - -#include -#include -#include -#include - -#include "base/compiler_specific.h" -#include "crypto/apple_keychain.h" - -namespace crypto { - -// Mock Keychain wrapper for testing code that interacts with the OS X -// Keychain. Implemented by storing SecKeychainAttributeList and -// KeychainPasswordData values in separate mutable containers and -// mapping them to integer keys. -// -// Note that "const" is pretty much meaningless for this class; the const-ness -// of AppleKeychain doesn't apply to the actual keychain data, so all of the -// Mock data is mutable; don't assume that it won't change over the life of -// tests. -class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { - public: - MockAppleKeychain(); - ~MockAppleKeychain() override; - - // AppleKeychain implementation. - OSStatus FindGenericPassword(CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const override; - OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const override; - OSStatus AddGenericPassword(SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const override; - - // Returns the password that OSCrypt uses to generate its encryption key. - std::string GetEncryptionPassword() const; - -#if !defined(OS_IOS) - OSStatus ItemCopyAttributesAndData(SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const override; - // Pass "fail_me" as the data to get errSecAuthFailed. - OSStatus ItemModifyAttributesAndData(SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const override; - OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, - void* data) const override; - OSStatus ItemDelete(SecKeychainItemRef itemRef) const override; - OSStatus SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const override; - OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const override; - // Pass "some.domain.com" as the serverName to get errSecDuplicateItem. - OSStatus AddInternetPassword(SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const override; - void Free(CFTypeRef ref) const override; - - // Return the counts of objects returned by Create/Copy functions but never - // Free'd as they should have been. - int UnfreedSearchCount() const; - int UnfreedKeychainItemCount() const; - int UnfreedAttributeDataCount() const; - - // Returns true if all items added with AddInternetPassword have a creator - // code set. - bool CreatorCodesSetForAddedItems() const; - - struct KeychainTestData { - const SecAuthenticationType auth_type; - const char* server; - const SecProtocolType protocol; - const char* path; - const UInt32 port; - const char* security_domain; - const char* creation_date; - const char* username; - const char* password; - const bool negative_item; - }; - // Adds a keychain item with the given info to the test set. - void AddTestItem(const KeychainTestData& item_data); - - void set_locked(bool locked) { locked_ = locked; } -#endif // !defined(OS_IOS) - - // |FindGenericPassword()| can return different results depending on user - // interaction with the system Keychain. For mocking purposes we allow the - // user of this class to specify the result code of the - // |FindGenericPassword()| call so we can simulate the result of different - // user interactions. - void set_find_generic_result(OSStatus result) { - find_generic_result_ = result; - } - - // Returns the true if |AddGenericPassword()| was called. - bool called_add_generic() const { return called_add_generic_; } - - // Returns the value of the password set when |AddGenericPassword()| was - // called. - std::string add_generic_password() const { return add_generic_password_; } - - // Returns the number of allocations - deallocations for password data. - int password_data_count() const { return password_data_count_; } - - private: - // Type used for the keys in the std::map(s) and MockAppleKeychain items. - typedef uintptr_t MockKeychainItemType; - - // Type of the map holding the mock keychain attributes. - typedef std::map - MockKeychainAttributesMap; - -#if !defined(OS_IOS) - // Returns true if the keychain already contains a password that matches the - // attributes provided. - bool AlreadyContainsInternetPassword( - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType) const; - // Initializes storage for keychain data at |key|. - void InitializeKeychainData(MockKeychainItemType key) const; - // Sets the data and length of |tag| in the item-th test item. - void SetTestDataBytes( - MockKeychainItemType item, - UInt32 tag, - const void* data, - size_t length); - // Sets the data and length of |tag| in the item-th test item based on - // |value|. The null-terminator will not be included; the Keychain Services - // docs don't indicate whether it is or not, so clients should not assume - // that it will be. - void SetTestDataString(MockKeychainItemType item, - UInt32 tag, - const char* value); - // Sets the data of the corresponding attribute of the item-th test item to - // |value|. Assumes that the space has alread been allocated, and the length - // set. - void SetTestDataPort(MockKeychainItemType item, UInt32 value); - void SetTestDataProtocol(MockKeychainItemType item, SecProtocolType value); - void SetTestDataAuthType(MockKeychainItemType item, - SecAuthenticationType value); - void SetTestDataNegativeItem(MockKeychainItemType item, Boolean value); - void SetTestDataCreator(MockKeychainItemType item, OSType value); - // Sets the password data and length for the item-th test item. - void SetTestDataPasswordBytes(MockKeychainItemType item, - const void* data, - size_t length); - // Sets the password for the item-th test item. As with SetTestDataString, - // the data will not be null-terminated. - void SetTestDataPasswordString(MockKeychainItemType item, const char* value); - - // Returns the address of the attribute in attribute_list with tag |tag|. - static SecKeychainAttribute* AttributeWithTag( - const SecKeychainAttributeList& attribute_list, - UInt32 tag); - - static const SecKeychainSearchRef kDummySearchRef; - - // Simulates the state when the user refuses to unclock the Keychain. - // If true, reading and modifying a password value result in errSecAuthFailed. - bool locked_; - - typedef struct KeychainPasswordData { - KeychainPasswordData() : data(NULL), length(0) {} - void* data; - UInt32 length; - } KeychainPasswordData; - - // Mutable because the MockAppleKeychain API requires its internal keychain - // storage to be modifiable by users of this class. - mutable MockKeychainAttributesMap keychain_attr_list_; - mutable std::map keychain_data_; - mutable MockKeychainItemType next_item_key_; - - // Tracks the items that should be returned in subsequent calls to - // SearchCopyNext, based on the last call to SearchCreateFromAttributes. - // We can't handle multiple active searches, since we don't track the search - // ref we return, but we don't need to for our mocking. - mutable std::vector remaining_search_results_; - - // Track copies and releases to make sure they balance. Really these should - // be maps to track per item, but this should be good enough to catch - // real mistakes. - mutable int search_copy_count_; - mutable int keychain_item_copy_count_; - mutable int attribute_data_copy_count_; - - // Tracks which items (by key) were added with AddInternetPassword. - mutable std::set added_via_api_; -#endif // !defined(OS_IOS) - - // Result code for the |FindGenericPassword()| method. - OSStatus find_generic_result_; - - // Records whether |AddGenericPassword()| gets called. - mutable bool called_add_generic_; - - // Tracks the allocations and frees of password data in |FindGenericPassword| - // and |ItemFreeContent|. - mutable int password_data_count_; - - // Records the password being set when |AddGenericPassword()| gets called. - mutable std::string add_generic_password_; -}; - -} // namespace crypto - -#endif // CRYPTO_MOCK_KEYCHAIN_MAC_H_ diff --git a/crypto/mock_apple_keychain_ios.cc b/crypto/mock_apple_keychain_ios.cc deleted file mode 100644 index 9e8a164668536..0000000000000 --- a/crypto/mock_apple_keychain_ios.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2012 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 "base/logging.h" -#include "base/time/time.h" -#include "crypto/mock_apple_keychain.h" - -namespace crypto { - -MockAppleKeychain::MockAppleKeychain() - : find_generic_result_(noErr), - called_add_generic_(false), - password_data_count_(0) { -} - -MockAppleKeychain::~MockAppleKeychain() { -} - -} // namespace crypto diff --git a/crypto/mock_apple_keychain_mac.cc b/crypto/mock_apple_keychain_mac.cc deleted file mode 100644 index 5f33e5b209932..0000000000000 --- a/crypto/mock_apple_keychain_mac.cc +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright (c) 2012 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 "base/logging.h" -#include "base/time/time.h" -#include "crypto/mock_apple_keychain.h" - -namespace crypto { - -// static -const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef = - reinterpret_cast(1000); - -MockAppleKeychain::MockAppleKeychain() - : locked_(false), - next_item_key_(0), - search_copy_count_(0), - keychain_item_copy_count_(0), - attribute_data_copy_count_(0), - find_generic_result_(noErr), - called_add_generic_(false), - password_data_count_(0) {} - -void MockAppleKeychain::InitializeKeychainData(MockKeychainItemType key) const { - UInt32 tags[] = { kSecAccountItemAttr, - kSecServerItemAttr, - kSecPortItemAttr, - kSecPathItemAttr, - kSecProtocolItemAttr, - kSecAuthenticationTypeItemAttr, - kSecSecurityDomainItemAttr, - kSecCreationDateItemAttr, - kSecNegativeItemAttr, - kSecCreatorItemAttr }; - keychain_attr_list_[key] = SecKeychainAttributeList(); - keychain_data_[key] = KeychainPasswordData(); - keychain_attr_list_[key].count = arraysize(tags); - keychain_attr_list_[key].attr = static_cast( - calloc(keychain_attr_list_[key].count, sizeof(SecKeychainAttribute))); - for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) { - keychain_attr_list_[key].attr[i].tag = tags[i]; - size_t data_size = 0; - switch (tags[i]) { - case kSecPortItemAttr: - data_size = sizeof(UInt32); - break; - case kSecProtocolItemAttr: - data_size = sizeof(SecProtocolType); - break; - case kSecAuthenticationTypeItemAttr: - data_size = sizeof(SecAuthenticationType); - break; - case kSecNegativeItemAttr: - data_size = sizeof(Boolean); - break; - case kSecCreatorItemAttr: - data_size = sizeof(OSType); - break; - } - if (data_size > 0) { - keychain_attr_list_[key].attr[i].length = data_size; - keychain_attr_list_[key].attr[i].data = calloc(1, data_size); - } - } -} - -MockAppleKeychain::~MockAppleKeychain() { - for (MockKeychainAttributesMap::iterator it = keychain_attr_list_.begin(); - it != keychain_attr_list_.end(); - ++it) { - for (unsigned int i = 0; i < it->second.count; ++i) { - if (it->second.attr[i].data) - free(it->second.attr[i].data); - } - free(it->second.attr); - if (keychain_data_[it->first].data) - free(keychain_data_[it->first].data); - } - keychain_attr_list_.clear(); - keychain_data_.clear(); -} - -SecKeychainAttribute* MockAppleKeychain::AttributeWithTag( - const SecKeychainAttributeList& attribute_list, - UInt32 tag) { - int attribute_index = -1; - for (unsigned int i = 0; i < attribute_list.count; ++i) { - if (attribute_list.attr[i].tag == tag) { - attribute_index = i; - break; - } - } - if (attribute_index == -1) { - NOTREACHED() << "Unsupported attribute: " << tag; - return NULL; - } - return &(attribute_list.attr[attribute_index]); -} - -void MockAppleKeychain::SetTestDataBytes(MockKeychainItemType item, - UInt32 tag, - const void* data, - size_t length) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - tag); - attribute->length = length; - if (length > 0) { - if (attribute->data) - free(attribute->data); - attribute->data = malloc(length); - CHECK(attribute->data); - memcpy(attribute->data, data, length); - } else { - attribute->data = NULL; - } -} - -void MockAppleKeychain::SetTestDataString(MockKeychainItemType item, - UInt32 tag, - const char* value) { - SetTestDataBytes(item, tag, value, value ? strlen(value) : 0); -} - -void MockAppleKeychain::SetTestDataPort(MockKeychainItemType item, - UInt32 value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecPortItemAttr); - UInt32* data = static_cast(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataProtocol(MockKeychainItemType item, - SecProtocolType value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecProtocolItemAttr); - SecProtocolType* data = static_cast(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataAuthType(MockKeychainItemType item, - SecAuthenticationType value) { - SecKeychainAttribute* attribute = AttributeWithTag( - keychain_attr_list_[item], kSecAuthenticationTypeItemAttr); - SecAuthenticationType* data = static_cast( - attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataNegativeItem(MockKeychainItemType item, - Boolean value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecNegativeItemAttr); - Boolean* data = static_cast(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataCreator(MockKeychainItemType item, - OSType value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecCreatorItemAttr); - OSType* data = static_cast(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataPasswordBytes(MockKeychainItemType item, - const void* data, - size_t length) { - keychain_data_[item].length = length; - if (length > 0) { - if (keychain_data_[item].data) - free(keychain_data_[item].data); - keychain_data_[item].data = malloc(length); - memcpy(keychain_data_[item].data, data, length); - } else { - keychain_data_[item].data = NULL; - } -} - -void MockAppleKeychain::SetTestDataPasswordString(MockKeychainItemType item, - const char* value) { - SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0); -} - -OSStatus MockAppleKeychain::ItemCopyAttributesAndData( - SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const { - DCHECK(itemRef); - MockKeychainItemType key = - reinterpret_cast(itemRef) - 1; - if (keychain_attr_list_.find(key) == keychain_attr_list_.end()) - return errSecInvalidItemRef; - - DCHECK(!itemClass); // itemClass not implemented in the Mock. - if (locked_ && outData) - return errSecAuthFailed; - - if (attrList) - *attrList = &(keychain_attr_list_[key]); - if (outData) { - *outData = keychain_data_[key].data; - DCHECK(length); - *length = keychain_data_[key].length; - } - - ++attribute_data_copy_count_; - return noErr; -} - -OSStatus MockAppleKeychain::ItemModifyAttributesAndData( - SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const { - DCHECK(itemRef); - if (locked_) - return errSecAuthFailed; - const char* fail_trigger = "fail_me"; - if (length == strlen(fail_trigger) && - memcmp(data, fail_trigger, length) == 0) { - return errSecAuthFailed; - } - - MockKeychainItemType key = - reinterpret_cast(itemRef) - 1; - if (keychain_attr_list_.find(key) == keychain_attr_list_.end()) - return errSecInvalidItemRef; - - MockAppleKeychain* mutable_this = const_cast(this); - if (attrList) { - for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) { - if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) { - void* data = attrList->attr[change_attr].data; - mutable_this->SetTestDataCreator(key, *(static_cast(data))); - } else { - NOTIMPLEMENTED(); - } - } - } - if (data) - mutable_this->SetTestDataPasswordBytes(key, data, length); - return noErr; -} - -OSStatus MockAppleKeychain::ItemFreeAttributesAndData( - SecKeychainAttributeList* attrList, - void* data) const { - --attribute_data_copy_count_; - return noErr; -} - -OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { - if (locked_) - return errSecAuthFailed; - MockKeychainItemType key = - reinterpret_cast(itemRef) - 1; - - for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) { - if (keychain_attr_list_[key].attr[i].data) - free(keychain_attr_list_[key].attr[i].data); - } - free(keychain_attr_list_[key].attr); - if (keychain_data_[key].data) - free(keychain_data_[key].data); - - keychain_attr_list_.erase(key); - keychain_data_.erase(key); - added_via_api_.erase(key); - return noErr; -} - -OSStatus MockAppleKeychain::SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const { - // Figure out which of our mock items matches, and set up the array we'll use - // to generate results out of SearchCopyNext. - remaining_search_results_.clear(); - for (MockKeychainAttributesMap::const_iterator it = - keychain_attr_list_.begin(); - it != keychain_attr_list_.end(); - ++it) { - bool mock_item_matches = true; - for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) { - SecKeychainAttribute* mock_attribute = - AttributeWithTag(it->second, attrList->attr[search_attr].tag); - if (mock_attribute->length != attrList->attr[search_attr].length || - memcmp(mock_attribute->data, attrList->attr[search_attr].data, - attrList->attr[search_attr].length) != 0) { - mock_item_matches = false; - break; - } - } - if (mock_item_matches) - remaining_search_results_.push_back(it->first); - } - - DCHECK(searchRef); - *searchRef = kDummySearchRef; - ++search_copy_count_; - return noErr; -} - -bool MockAppleKeychain::AlreadyContainsInternetPassword( - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType) const { - for (MockKeychainAttributesMap::const_iterator it = - keychain_attr_list_.begin(); - it != keychain_attr_list_.end(); - ++it) { - SecKeychainAttribute* attribute; - attribute = AttributeWithTag(it->second, kSecServerItemAttr); - if ((attribute->length != serverNameLength) || - (attribute->data == NULL && *serverName != '\0') || - (attribute->data != NULL && *serverName == '\0') || - strncmp(serverName, - (const char*) attribute->data, - serverNameLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecSecurityDomainItemAttr); - if ((attribute->length != securityDomainLength) || - (attribute->data == NULL && *securityDomain != '\0') || - (attribute->data != NULL && *securityDomain == '\0') || - strncmp(securityDomain, - (const char*) attribute->data, - securityDomainLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecAccountItemAttr); - if ((attribute->length != accountNameLength) || - (attribute->data == NULL && *accountName != '\0') || - (attribute->data != NULL && *accountName == '\0') || - strncmp(accountName, - (const char*) attribute->data, - accountNameLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecPathItemAttr); - if ((attribute->length != pathLength) || - (attribute->data == NULL && *path != '\0') || - (attribute->data != NULL && *path == '\0') || - strncmp(path, - (const char*) attribute->data, - pathLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecPortItemAttr); - if ((attribute->data == NULL) || - (port != *(static_cast(attribute->data)))) { - continue; - } - attribute = AttributeWithTag(it->second, kSecProtocolItemAttr); - if ((attribute->data == NULL) || - (protocol != *(static_cast(attribute->data)))) { - continue; - } - attribute = AttributeWithTag(it->second, kSecAuthenticationTypeItemAttr); - if ((attribute->data == NULL) || - (authenticationType != - *(static_cast(attribute->data)))) { - continue; - } - // The keychain already has this item, since all fields other than the - // password match. - return true; - } - return false; -} - -OSStatus MockAppleKeychain::AddInternetPassword( - SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - if (locked_) - return errSecAuthFailed; - - // Check for the magic duplicate item trigger. - if (strcmp(serverName, "some.domain.com") == 0) - return errSecDuplicateItem; - - // If the account already exists in the keychain, we don't add it. - if (AlreadyContainsInternetPassword(serverNameLength, serverName, - securityDomainLength, securityDomain, - accountNameLength, accountName, - pathLength, path, - port, protocol, - authenticationType)) { - return errSecDuplicateItem; - } - - // Pick the next unused slot. - MockKeychainItemType key = next_item_key_++; - - // Initialize keychain data storage at the target location. - InitializeKeychainData(key); - - MockAppleKeychain* mutable_this = const_cast(this); - mutable_this->SetTestDataBytes(key, kSecServerItemAttr, serverName, - serverNameLength); - mutable_this->SetTestDataBytes(key, kSecSecurityDomainItemAttr, - securityDomain, securityDomainLength); - mutable_this->SetTestDataBytes(key, kSecAccountItemAttr, accountName, - accountNameLength); - mutable_this->SetTestDataBytes(key, kSecPathItemAttr, path, pathLength); - mutable_this->SetTestDataPort(key, port); - mutable_this->SetTestDataProtocol(key, protocol); - mutable_this->SetTestDataAuthType(key, authenticationType); - mutable_this->SetTestDataPasswordBytes(key, passwordData, - passwordLength); - base::Time::Exploded exploded_time; - base::Time::Now().UTCExplode(&exploded_time); - char time_string[128]; - snprintf(time_string, sizeof(time_string), "%04d%02d%02d%02d%02d%02dZ", - exploded_time.year, exploded_time.month, exploded_time.day_of_month, - exploded_time.hour, exploded_time.minute, exploded_time.second); - mutable_this->SetTestDataString(key, kSecCreationDateItemAttr, time_string); - - added_via_api_.insert(key); - - if (itemRef) { - *itemRef = reinterpret_cast(key + 1); - ++keychain_item_copy_count_; - } - return noErr; -} - -OSStatus MockAppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const { - if (remaining_search_results_.empty()) - return errSecItemNotFound; - MockKeychainItemType key = remaining_search_results_.front(); - remaining_search_results_.erase(remaining_search_results_.begin()); - *itemRef = reinterpret_cast(key + 1); - ++keychain_item_copy_count_; - return noErr; -} - -void MockAppleKeychain::Free(CFTypeRef ref) const { - if (!ref) - return; - - if (ref == kDummySearchRef) { - --search_copy_count_; - } else { - --keychain_item_copy_count_; - } -} - -int MockAppleKeychain::UnfreedSearchCount() const { - return search_copy_count_; -} - -int MockAppleKeychain::UnfreedKeychainItemCount() const { - return keychain_item_copy_count_; -} - -int MockAppleKeychain::UnfreedAttributeDataCount() const { - return attribute_data_copy_count_; -} - -bool MockAppleKeychain::CreatorCodesSetForAddedItems() const { - for (std::set::const_iterator - i = added_via_api_.begin(); - i != added_via_api_.end(); - ++i) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[*i], - kSecCreatorItemAttr); - OSType* data = static_cast(attribute->data); - if (*data == 0) - return false; - } - return true; -} - -void MockAppleKeychain::AddTestItem(const KeychainTestData& item_data) { - MockKeychainItemType key = next_item_key_++; - - InitializeKeychainData(key); - SetTestDataAuthType(key, item_data.auth_type); - SetTestDataString(key, kSecServerItemAttr, item_data.server); - SetTestDataProtocol(key, item_data.protocol); - SetTestDataString(key, kSecPathItemAttr, item_data.path); - SetTestDataPort(key, item_data.port); - SetTestDataString(key, kSecSecurityDomainItemAttr, - item_data.security_domain); - SetTestDataString(key, kSecCreationDateItemAttr, item_data.creation_date); - SetTestDataString(key, kSecAccountItemAttr, item_data.username); - SetTestDataPasswordString(key, item_data.password); - SetTestDataNegativeItem(key, item_data.negative_item); -} - -} // namespace crypto diff --git a/crypto/nss_crypto_module_delegate.h b/crypto/nss_crypto_module_delegate.h deleted file mode 100644 index 6c1da68161dd5..0000000000000 --- a/crypto/nss_crypto_module_delegate.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 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_NSS_CRYPTO_MODULE_DELEGATE_H_ -#define CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_ - -#include - -#include "base/callback_forward.h" -#include "crypto/scoped_nss_types.h" - -namespace crypto { - -// PK11_SetPasswordFunc is a global setting. An implementation of -// CryptoModuleBlockingPasswordDelegate should be passed using wincx() as the -// user data argument (|wincx|) to relevant NSS functions, which the global -// password handler will call to do the actual work. This delegate should only -// be used in NSS calls on worker threads due to the blocking nature. -class CryptoModuleBlockingPasswordDelegate { - public: - virtual ~CryptoModuleBlockingPasswordDelegate() {} - - // Return a value suitable for passing to the |wincx| argument of relevant NSS - // functions. This should be used instead of passing the object pointer - // directly to avoid accidentally casting a pointer to a subclass to void* and - // then casting back to a pointer of the base class - void* wincx() { return this; } - - // Requests a password to unlock |slot_name|. The interface is synchronous - // because NSS cannot issue an asynchronous request. |retry| is true if this - // is a request for the retry and we previously returned the wrong password. - // The implementation should set |*cancelled| to true if the user cancelled - // instead of entering a password, otherwise it should return the password the - // user entered. - virtual std::string RequestPassword(const std::string& slot_name, bool retry, - bool* cancelled) = 0; - -}; - -// Extends CryptoModuleBlockingPasswordDelegate with the ability to return a -// slot in which to act. (Eg, which slot to store a generated key in.) -class NSSCryptoModuleDelegate : public CryptoModuleBlockingPasswordDelegate { - public: - ~NSSCryptoModuleDelegate() override {} - - // Get the slot to store the generated key. - virtual ScopedPK11Slot RequestSlot() = 0; -}; - -} // namespace crypto - -#endif // CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_ diff --git a/crypto/nss_key_util.cc b/crypto/nss_key_util.cc deleted file mode 100644 index 77435fba36175..0000000000000 --- a/crypto/nss_key_util.cc +++ /dev/null @@ -1,163 +0,0 @@ -// 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/nss_key_util.h" - -#include -#include -#include - -#include "base/logging.h" -#include "base/stl_util.h" -#include "crypto/nss_util.h" - -#if defined(USE_NSS_CERTS) -#include -#include "crypto/nss_util_internal.h" -#endif - -namespace crypto { - -namespace { - -#if defined(USE_NSS_CERTS) - -struct PublicKeyInfoDeleter { - inline void operator()(CERTSubjectPublicKeyInfo* spki) { - SECKEY_DestroySubjectPublicKeyInfo(spki); - } -}; - -typedef scoped_ptr - ScopedPublicKeyInfo; - -// Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing -// the CKA_ID of that public key or nullptr on error. -ScopedSECItem MakeIDFromSPKI(const std::vector& input) { - // First, decode and save the public key. - SECItem key_der; - key_der.type = siBuffer; - key_der.data = const_cast(vector_as_array(&input)); - key_der.len = input.size(); - - ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der)); - if (!spki) - return nullptr; - - ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get())); - if (!result) - return nullptr; - - // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are - // supported. - if (SECKEY_GetPublicKeyType(result.get()) != rsaKey) - return nullptr; - - return ScopedSECItem(PK11_MakeIDFromPubKey(&result->u.rsa.modulus)); -} - -#endif // defined(USE_NSS_CERTS) - -} // namespace - -bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot, - uint16_t num_bits, - bool permanent, - ScopedSECKEYPublicKey* public_key, - ScopedSECKEYPrivateKey* private_key) { - DCHECK(slot); - - PK11RSAGenParams param; - param.keySizeInBits = num_bits; - param.pe = 65537L; - SECKEYPublicKey* public_key_raw = nullptr; - private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, - ¶m, &public_key_raw, permanent, - permanent /* sensitive */, nullptr)); - if (!*private_key) - return false; - - public_key->reset(public_key_raw); - return true; -} - -ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo( - PK11SlotInfo* slot, - const std::vector& input, - bool permanent) { - DCHECK(slot); - - ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); - DCHECK(arena); - - // Excess data is illegal, but NSS silently accepts it, so first ensure that - // |input| consists of a single ASN.1 element. - SECItem input_item; - input_item.data = const_cast(vector_as_array(&input)); - input_item.len = input.size(); - SECItem der_private_key_info; - SECStatus rv = - SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info, - SEC_ASN1_GET(SEC_AnyTemplate), &input_item); - if (rv != SECSuccess) - return nullptr; - - // Allow the private key to be used for key unwrapping, data decryption, - // and signature generation. - const unsigned int key_usage = - KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE; - SECKEYPrivateKey* key_raw = nullptr; - rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( - slot, &der_private_key_info, nullptr, nullptr, permanent, - permanent /* sensitive */, key_usage, &key_raw, nullptr); - if (rv != SECSuccess) - return nullptr; - return ScopedSECKEYPrivateKey(key_raw); -} - -#if defined(USE_NSS_CERTS) - -ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo( - const std::vector& input) { - EnsureNSSInit(); - - ScopedSECItem cka_id(MakeIDFromSPKI(input)); - if (!cka_id) - return nullptr; - - // Search all slots in all modules for the key with the given ID. - AutoSECMODListReadLock auto_lock; - const SECMODModuleList* head = SECMOD_GetDefaultModuleList(); - for (const SECMODModuleList* item = head; item != nullptr; - item = item->next) { - int slot_count = item->module->loaded ? item->module->slotCount : 0; - for (int i = 0; i < slot_count; i++) { - // Look for the key in slot |i|. - ScopedSECKEYPrivateKey key( - PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr)); - if (key) - return key.Pass(); - } - } - - // The key wasn't found in any module. - return nullptr; -} - -ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot( - const std::vector& input, - PK11SlotInfo* slot) { - DCHECK(slot); - - ScopedSECItem cka_id(MakeIDFromSPKI(input)); - if (!cka_id) - return nullptr; - - return ScopedSECKEYPrivateKey( - PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr)); -} - -#endif // defined(USE_NSS_CERTS) - -} // namespace crypto diff --git a/crypto/nss_key_util.h b/crypto/nss_key_util.h deleted file mode 100644 index 12b948d25bb2a..0000000000000 --- a/crypto/nss_key_util.h +++ /dev/null @@ -1,58 +0,0 @@ -// 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_NSS_KEY_UTIL_H_ -#define CRYPTO_NSS_KEY_UTIL_H_ - -#include - -#include - -#include "build/build_config.h" -#include "crypto/crypto_export.h" -#include "crypto/scoped_nss_types.h" - -typedef struct PK11SlotInfoStr PK11SlotInfo; - -namespace crypto { - -// Generates a new RSA keypair of size |num_bits| in |slot|. Returns true on -// success and false on failure. If |permanent| is true, the resulting key is -// permanent and is not exportable in plaintext form. -CRYPTO_EXPORT bool GenerateRSAKeyPairNSS( - PK11SlotInfo* slot, - uint16_t num_bits, - bool permanent, - ScopedSECKEYPublicKey* out_public_key, - ScopedSECKEYPrivateKey* out_private_key); - -// Imports a private key from |input| into |slot|. |input| is interpreted as a -// DER-encoded PrivateKeyInfo block from PKCS #8. Returns nullptr on error. If -// |permanent| is true, the resulting key is permanent and is not exportable in -// plaintext form. -CRYPTO_EXPORT ScopedSECKEYPrivateKey -ImportNSSKeyFromPrivateKeyInfo(PK11SlotInfo* slot, - const std::vector& input, - bool permanent); - -#if defined(USE_NSS_CERTS) - -// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for -// the private key half in the key database. Returns the private key on success -// or nullptr on error. -CRYPTO_EXPORT ScopedSECKEYPrivateKey -FindNSSKeyFromPublicKeyInfo(const std::vector& input); - -// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for -// the private key half in the slot specified by |slot|. Returns the private key -// on success or nullptr on error. -CRYPTO_EXPORT ScopedSECKEYPrivateKey -FindNSSKeyFromPublicKeyInfoInSlot(const std::vector& input, - PK11SlotInfo* slot); - -#endif // defined(USE_NSS_CERTS) - -} // namespace crypto - -#endif // CRYPTO_NSS_KEY_UTIL_H_ diff --git a/crypto/nss_key_util_unittest.cc b/crypto/nss_key_util_unittest.cc deleted file mode 100644 index ff4d55a146094..0000000000000 --- a/crypto/nss_key_util_unittest.cc +++ /dev/null @@ -1,87 +0,0 @@ -// 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/nss_key_util.h" - -#include -#include - -#include - -#include "crypto/nss_util.h" -#include "crypto/scoped_nss_types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -class NSSKeyUtilTest : public testing::Test { - public: - void SetUp() override { - EnsureNSSInit(); - - internal_slot_.reset(PK11_GetInternalSlot()); - ASSERT_TRUE(internal_slot_); - } - - PK11SlotInfo* internal_slot() { return internal_slot_.get(); } - - private: - ScopedPK11Slot internal_slot_; -}; - -TEST_F(NSSKeyUtilTest, GenerateRSAKeyPairNSS) { - const int kKeySizeBits = 1024; - - ScopedSECKEYPublicKey public_key; - ScopedSECKEYPrivateKey private_key; - ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), kKeySizeBits, - false /* not permanent */, &public_key, - &private_key)); - - EXPECT_EQ(rsaKey, SECKEY_GetPublicKeyType(public_key.get())); - EXPECT_EQ(rsaKey, SECKEY_GetPrivateKeyType(private_key.get())); - EXPECT_EQ((kKeySizeBits + 7) / 8, - PK11_GetPrivateModulusLen(private_key.get())); -} - -#if defined(USE_NSS_CERTS) -TEST_F(NSSKeyUtilTest, FindNSSKeyFromPublicKeyInfo) { - // Create an NSS keypair, which will put the keys in the user's NSSDB. - ScopedSECKEYPublicKey public_key; - ScopedSECKEYPrivateKey private_key; - ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512, - false /* not permanent */, &public_key, - &private_key)); - - ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); - ASSERT_TRUE(item); - std::vector public_key_der(item->data, item->data + item->len); - - ScopedSECKEYPrivateKey private_key2 = - FindNSSKeyFromPublicKeyInfo(public_key_der); - ASSERT_TRUE(private_key2); - EXPECT_EQ(private_key->pkcs11ID, private_key2->pkcs11ID); -} - -TEST_F(NSSKeyUtilTest, FailedFindNSSKeyFromPublicKeyInfo) { - // Create an NSS keypair, which will put the keys in the user's NSSDB. - ScopedSECKEYPublicKey public_key; - ScopedSECKEYPrivateKey private_key; - ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512, - false /* not permanent */, &public_key, - &private_key)); - - ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); - ASSERT_TRUE(item); - std::vector public_key_der(item->data, item->data + item->len); - - // Remove the keys from the DB, and make sure we can't find them again. - PK11_DestroyTokenObject(private_key->pkcs11Slot, private_key->pkcs11ID); - PK11_DestroyTokenObject(public_key->pkcs11Slot, public_key->pkcs11ID); - - EXPECT_FALSE(FindNSSKeyFromPublicKeyInfo(public_key_der)); -} -#endif // defined(USE_NSS_CERTS) - -} // namespace crypto diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc deleted file mode 100644 index 125591c73f6b9..0000000000000 --- a/crypto/nss_util.cc +++ /dev/null @@ -1,1131 +0,0 @@ -// Copyright (c) 2012 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/nss_util.h" -#include "crypto/nss_util_internal.h" - -#include -#include -#include -#include -#include -#include -#include - -#if defined(OS_OPENBSD) -#include -#include -#endif - -#if defined(OS_CHROMEOS) -#include -#endif - -#include -#include - -#include "base/base_paths.h" -#include "base/bind.h" -#include "base/cpu.h" -#include "base/debug/alias.h" -#include "base/debug/stack_trace.h" -#include "base/environment.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/native_library.h" -#include "base/path_service.h" -#include "base/stl_util.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_checker.h" -#include "base/threading/thread_restrictions.h" -#include "base/threading/worker_pool.h" -#include "build/build_config.h" - -// USE_NSS_CERTS means NSS is used for certificates and platform integration. -// This requires additional support to manage the platform certificate and key -// stores. -#if defined(USE_NSS_CERTS) -#include "base/synchronization/lock.h" -#include "crypto/nss_crypto_module_delegate.h" -#endif // defined(USE_NSS_CERTS) - -namespace crypto { - -namespace { - -#if defined(OS_CHROMEOS) -const char kUserNSSDatabaseName[] = "UserNSSDB"; - -// Constants for loading the Chrome OS TPM-backed PKCS #11 library. -const char kChapsModuleName[] = "Chaps"; -const char kChapsPath[] = "libchaps.so"; - -// Fake certificate authority database used for testing. -static const base::FilePath::CharType kReadOnlyCertDB[] = - FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb"); -#endif // defined(OS_CHROMEOS) - -std::string GetNSSErrorMessage() { - std::string result; - if (PR_GetErrorTextLength()) { - scoped_ptr error_text(new char[PR_GetErrorTextLength() + 1]); - PRInt32 copied = PR_GetErrorText(error_text.get()); - result = std::string(error_text.get(), copied); - } else { - result = base::StringPrintf("NSS error code: %d", PR_GetError()); - } - return result; -} - -#if defined(USE_NSS_CERTS) -#if !defined(OS_CHROMEOS) -base::FilePath GetDefaultConfigDirectory() { - base::FilePath dir; - PathService::Get(base::DIR_HOME, &dir); - if (dir.empty()) { - LOG(ERROR) << "Failed to get home directory."; - return dir; - } - dir = dir.AppendASCII(".pki").AppendASCII("nssdb"); - if (!base::CreateDirectory(dir)) { - LOG(ERROR) << "Failed to create " << dir.value() << " directory."; - dir.clear(); - } - DVLOG(2) << "DefaultConfigDirectory: " << dir.value(); - return dir; -} -#endif // !defined(IS_CHROMEOS) - -// On non-Chrome OS platforms, return the default config directory. On Chrome OS -// test images, return a read-only directory with fake root CA certs (which are -// used by the local Google Accounts server mock we use when testing our login -// code). On Chrome OS non-test images (where the read-only directory doesn't -// exist), return an empty path. -base::FilePath GetInitialConfigDirectory() { -#if defined(OS_CHROMEOS) - base::FilePath database_dir = base::FilePath(kReadOnlyCertDB); - if (!base::PathExists(database_dir)) - database_dir.clear(); - return database_dir; -#else - return GetDefaultConfigDirectory(); -#endif // defined(OS_CHROMEOS) -} - -// This callback for NSS forwards all requests to a caller-specified -// CryptoModuleBlockingPasswordDelegate object. -char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) { - crypto::CryptoModuleBlockingPasswordDelegate* delegate = - reinterpret_cast(arg); - if (delegate) { - bool cancelled = false; - std::string password = delegate->RequestPassword(PK11_GetTokenName(slot), - retry != PR_FALSE, - &cancelled); - if (cancelled) - return NULL; - char* result = PORT_Strdup(password.c_str()); - password.replace(0, password.size(), password.size(), 0); - return result; - } - DLOG(ERROR) << "PK11 password requested with NULL arg"; - return NULL; -} - -// NSS creates a local cache of the sqlite database if it detects that the -// filesystem the database is on is much slower than the local disk. The -// detection doesn't work with the latest versions of sqlite, such as 3.6.22 -// (NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=578561). So we set -// the NSS environment variable NSS_SDB_USE_CACHE to "yes" to override NSS's -// detection when database_dir is on NFS. See http://crbug.com/48585. -// -// TODO(wtc): port this function to other USE_NSS_CERTS platforms. It is -// defined only for OS_LINUX and OS_OPENBSD simply because the statfs structure -// is OS-specific. -// -// Because this function sets an environment variable it must be run before we -// go multi-threaded. -void UseLocalCacheOfNSSDatabaseIfNFS(const base::FilePath& database_dir) { - bool db_on_nfs = false; -#if defined(OS_LINUX) - base::FileSystemType fs_type = base::FILE_SYSTEM_UNKNOWN; - if (base::GetFileSystemType(database_dir, &fs_type)) - db_on_nfs = (fs_type == base::FILE_SYSTEM_NFS); -#elif defined(OS_OPENBSD) - struct statfs buf; - if (statfs(database_dir.value().c_str(), &buf) == 0) - db_on_nfs = (strcmp(buf.f_fstypename, MOUNT_NFS) == 0); -#else - NOTIMPLEMENTED(); -#endif - - if (db_on_nfs) { - scoped_ptr env(base::Environment::Create()); - static const char kUseCacheEnvVar[] = "NSS_SDB_USE_CACHE"; - if (!env->HasVar(kUseCacheEnvVar)) - env->SetVar(kUseCacheEnvVar, "yes"); - } -} - -#endif // defined(USE_NSS_CERTS) - -// A singleton to initialize/deinitialize NSPR. -// Separate from the NSS singleton because we initialize NSPR on the UI thread. -// Now that we're leaking the singleton, we could merge back with the NSS -// singleton. -class NSPRInitSingleton { - private: - friend struct base::DefaultLazyInstanceTraits; - - NSPRInitSingleton() { - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); - } - - // NOTE(willchan): We don't actually execute this code since we leak NSS to - // prevent non-joinable threads from using NSS after it's already been shut - // down. - ~NSPRInitSingleton() { - PL_ArenaFinish(); - PRStatus prstatus = PR_Cleanup(); - if (prstatus != PR_SUCCESS) - LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?"; - } -}; - -base::LazyInstance::Leaky - g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; - -// Force a crash with error info on NSS_NoDB_Init failure. -void CrashOnNSSInitFailure() { - int nss_error = PR_GetError(); - int os_error = PR_GetOSError(); - base::debug::Alias(&nss_error); - base::debug::Alias(&os_error); - LOG(ERROR) << "Error initializing NSS without a persistent database: " - << GetNSSErrorMessage(); - LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error; -} - -#if defined(OS_CHROMEOS) -class ChromeOSUserData { - public: - explicit ChromeOSUserData(ScopedPK11Slot public_slot) - : public_slot_(public_slot.Pass()), - private_slot_initialization_started_(false) {} - ~ChromeOSUserData() { - if (public_slot_) { - SECStatus status = SECMOD_CloseUserDB(public_slot_.get()); - if (status != SECSuccess) - PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); - } - } - - ScopedPK11Slot GetPublicSlot() { - return ScopedPK11Slot( - public_slot_ ? PK11_ReferenceSlot(public_slot_.get()) : NULL); - } - - ScopedPK11Slot GetPrivateSlot( - const base::Callback& callback) { - if (private_slot_) - return ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get())); - if (!callback.is_null()) - tpm_ready_callback_list_.push_back(callback); - return ScopedPK11Slot(); - } - - void SetPrivateSlot(ScopedPK11Slot private_slot) { - DCHECK(!private_slot_); - private_slot_ = private_slot.Pass(); - - SlotReadyCallbackList callback_list; - callback_list.swap(tpm_ready_callback_list_); - for (SlotReadyCallbackList::iterator i = callback_list.begin(); - i != callback_list.end(); - ++i) { - (*i).Run(ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get()))); - } - } - - bool private_slot_initialization_started() const { - return private_slot_initialization_started_; - } - - void set_private_slot_initialization_started() { - private_slot_initialization_started_ = true; - } - - private: - ScopedPK11Slot public_slot_; - ScopedPK11Slot private_slot_; - - bool private_slot_initialization_started_; - - typedef std::vector > - SlotReadyCallbackList; - SlotReadyCallbackList tpm_ready_callback_list_; -}; - -class ScopedChapsLoadFixup { - public: - ScopedChapsLoadFixup(); - ~ScopedChapsLoadFixup(); - - private: -#if defined(COMPONENT_BUILD) - void *chaps_handle_; -#endif -}; - -#if defined(COMPONENT_BUILD) - -ScopedChapsLoadFixup::ScopedChapsLoadFixup() { - // HACK: libchaps links the system protobuf and there are symbol conflicts - // with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround. - chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND); -} - -ScopedChapsLoadFixup::~ScopedChapsLoadFixup() { - // LoadModule() will have taken a 2nd reference. - if (chaps_handle_) - dlclose(chaps_handle_); -} - -#else - -ScopedChapsLoadFixup::ScopedChapsLoadFixup() {} -ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {} - -#endif // defined(COMPONENT_BUILD) -#endif // defined(OS_CHROMEOS) - -class NSSInitSingleton { - public: -#if defined(OS_CHROMEOS) - // Used with PostTaskAndReply to pass handles to worker thread and back. - struct TPMModuleAndSlot { - explicit TPMModuleAndSlot(SECMODModule* init_chaps_module) - : chaps_module(init_chaps_module) {} - SECMODModule* chaps_module; - crypto::ScopedPK11Slot tpm_slot; - }; - - ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, - const base::FilePath& path) { - DCHECK(thread_checker_.CalledOnValidThread()); - // NSS is allowed to do IO on the current thread since dispatching - // to a dedicated thread would still have the affect of blocking - // the current thread, due to NSS's internal locking requirements - base::ThreadRestrictions::ScopedAllowIO allow_io; - - base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb"); - if (!base::CreateDirectory(nssdb_path)) { - LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; - return ScopedPK11Slot(); - } - return OpenSoftwareNSSDB(nssdb_path, db_name); - } - - void EnableTPMTokenForNSS() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // If this gets set, then we'll use the TPM for certs with - // private keys, otherwise we'll fall back to the software - // implementation. - tpm_token_enabled_for_nss_ = true; - } - - bool IsTPMTokenEnabledForNSS() { - DCHECK(thread_checker_.CalledOnValidThread()); - return tpm_token_enabled_for_nss_; - } - - void InitializeTPMTokenAndSystemSlot( - int system_slot_id, - const base::Callback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - // Should not be called while there is already an initialization in - // progress. - DCHECK(!initializing_tpm_token_); - // If EnableTPMTokenForNSS hasn't been called, return false. - if (!tpm_token_enabled_for_nss_) { - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(callback, false)); - return; - } - - // If everything is already initialized, then return true. - // Note that only |tpm_slot_| is checked, since |chaps_module_| could be - // NULL in tests while |tpm_slot_| has been set to the test DB. - if (tpm_slot_) { - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(callback, true)); - return; - } - - // Note that a reference is not taken to chaps_module_. This is safe since - // NSSInitSingleton is Leaky, so the reference it holds is never released. - scoped_ptr tpm_args(new TPMModuleAndSlot(chaps_module_)); - TPMModuleAndSlot* tpm_args_ptr = tpm_args.get(); - if (base::WorkerPool::PostTaskAndReply( - FROM_HERE, - base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread, - system_slot_id, - tpm_args_ptr), - base::Bind(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot, - base::Unretained(this), // NSSInitSingleton is leaky - callback, - base::Passed(&tpm_args)), - true /* task_is_slow */ - )) { - initializing_tpm_token_ = true; - } else { - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(callback, false)); - } - } - - static void InitializeTPMTokenOnWorkerThread(CK_SLOT_ID token_slot_id, - TPMModuleAndSlot* tpm_args) { - // This tries to load the Chaps module so NSS can talk to the hardware - // TPM. - if (!tpm_args->chaps_module) { - ScopedChapsLoadFixup chaps_loader; - - DVLOG(3) << "Loading chaps..."; - tpm_args->chaps_module = LoadModule( - kChapsModuleName, - kChapsPath, - // For more details on these parameters, see: - // https://developer.mozilla.org/en/PKCS11_Module_Specs - // slotFlags=[PublicCerts] -- Certificates and public keys can be - // read from this slot without requiring a call to C_Login. - // askpw=only -- Only authenticate to the token when necessary. - "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\""); - } - if (tpm_args->chaps_module) { - tpm_args->tpm_slot = - GetTPMSlotForIdOnWorkerThread(tpm_args->chaps_module, token_slot_id); - } - } - - void OnInitializedTPMTokenAndSystemSlot( - const base::Callback& callback, - scoped_ptr tpm_args) { - DCHECK(thread_checker_.CalledOnValidThread()); - DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module - << ", got tpm slot: " << !!tpm_args->tpm_slot; - - chaps_module_ = tpm_args->chaps_module; - tpm_slot_ = tpm_args->tpm_slot.Pass(); - if (!chaps_module_ && test_system_slot_) { - // chromeos_unittests try to test the TPM initialization process. If we - // have a test DB open, pretend that it is the TPM slot. - tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get())); - } - initializing_tpm_token_ = false; - - if (tpm_slot_) - RunAndClearTPMReadyCallbackList(); - - callback.Run(!!tpm_slot_); - } - - void RunAndClearTPMReadyCallbackList() { - TPMReadyCallbackList callback_list; - callback_list.swap(tpm_ready_callback_list_); - for (TPMReadyCallbackList::iterator i = callback_list.begin(); - i != callback_list.end(); - ++i) { - i->Run(); - } - } - - bool IsTPMTokenReady(const base::Closure& callback) { - if (!callback.is_null()) { - // Cannot DCHECK in the general case yet, but since the callback is - // a new addition to the API, DCHECK to make sure at least the new uses - // don't regress. - DCHECK(thread_checker_.CalledOnValidThread()); - } else if (!thread_checker_.CalledOnValidThread()) { - // TODO(mattm): Change to DCHECK when callers have been fixed. - DVLOG(1) << "Called on wrong thread.\n" - << base::debug::StackTrace().ToString(); - } - - if (tpm_slot_) - return true; - - if (!callback.is_null()) - tpm_ready_callback_list_.push_back(callback); - - return false; - } - - // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot - // id as an int. This should be safe since this is only used with chaps, which - // we also control. - static crypto::ScopedPK11Slot GetTPMSlotForIdOnWorkerThread( - SECMODModule* chaps_module, - CK_SLOT_ID slot_id) { - DCHECK(chaps_module); - - DVLOG(3) << "Poking chaps module."; - SECStatus rv = SECMOD_UpdateSlotList(chaps_module); - if (rv != SECSuccess) - PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError(); - - PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id); - if (!slot) - LOG(ERROR) << "TPM slot " << slot_id << " not found."; - return crypto::ScopedPK11Slot(slot); - } - - bool InitializeNSSForChromeOSUser(const std::string& username_hash, - const base::FilePath& path) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { - // This user already exists in our mapping. - DVLOG(2) << username_hash << " already initialized."; - return false; - } - - DVLOG(2) << "Opening NSS DB " << path.value(); - std::string db_name = base::StringPrintf( - "%s %s", kUserNSSDatabaseName, username_hash.c_str()); - ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path)); - chromeos_user_map_[username_hash] = - new ChromeOSUserData(public_slot.Pass()); - return true; - } - - bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); - - return !chromeos_user_map_[username_hash] - ->private_slot_initialization_started(); - } - - void WillInitializeTPMForChromeOSUser(const std::string& username_hash) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); - - chromeos_user_map_[username_hash] - ->set_private_slot_initialization_started(); - } - - void InitializeTPMForChromeOSUser(const std::string& username_hash, - CK_SLOT_ID slot_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); - DCHECK(chromeos_user_map_[username_hash]-> - private_slot_initialization_started()); - - if (!chaps_module_) - return; - - // Note that a reference is not taken to chaps_module_. This is safe since - // NSSInitSingleton is Leaky, so the reference it holds is never released. - scoped_ptr tpm_args(new TPMModuleAndSlot(chaps_module_)); - TPMModuleAndSlot* tpm_args_ptr = tpm_args.get(); - base::WorkerPool::PostTaskAndReply( - FROM_HERE, - base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread, - slot_id, - tpm_args_ptr), - base::Bind(&NSSInitSingleton::OnInitializedTPMForChromeOSUser, - base::Unretained(this), // NSSInitSingleton is leaky - username_hash, - base::Passed(&tpm_args)), - true /* task_is_slow */ - ); - } - - void OnInitializedTPMForChromeOSUser(const std::string& username_hash, - scoped_ptr tpm_args) { - DCHECK(thread_checker_.CalledOnValidThread()); - DVLOG(2) << "Got tpm slot for " << username_hash << " " - << !!tpm_args->tpm_slot; - chromeos_user_map_[username_hash]->SetPrivateSlot( - tpm_args->tpm_slot.Pass()); - } - - void InitializePrivateSoftwareSlotForChromeOSUser( - const std::string& username_hash) { - DCHECK(thread_checker_.CalledOnValidThread()); - VLOG(1) << "using software private slot for " << username_hash; - DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); - DCHECK(chromeos_user_map_[username_hash]-> - private_slot_initialization_started()); - - chromeos_user_map_[username_hash]->SetPrivateSlot( - chromeos_user_map_[username_hash]->GetPublicSlot()); - } - - ScopedPK11Slot GetPublicSlotForChromeOSUser( - const std::string& username_hash) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (username_hash.empty()) { - DVLOG(2) << "empty username_hash"; - return ScopedPK11Slot(); - } - - if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) { - LOG(ERROR) << username_hash << " not initialized."; - return ScopedPK11Slot(); - } - return chromeos_user_map_[username_hash]->GetPublicSlot(); - } - - ScopedPK11Slot GetPrivateSlotForChromeOSUser( - const std::string& username_hash, - const base::Callback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (username_hash.empty()) { - DVLOG(2) << "empty username_hash"; - if (!callback.is_null()) { - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(callback, base::Passed(ScopedPK11Slot()))); - } - return ScopedPK11Slot(); - } - - DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); - - return chromeos_user_map_[username_hash]->GetPrivateSlot(callback); - } - - void CloseChromeOSUserForTesting(const std::string& username_hash) { - DCHECK(thread_checker_.CalledOnValidThread()); - ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash); - DCHECK(i != chromeos_user_map_.end()); - delete i->second; - chromeos_user_map_.erase(i); - } - - void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { - // Ensure that a previous value of test_system_slot_ is not overwritten. - // Unsetting, i.e. setting a NULL, however is allowed. - DCHECK(!slot || !test_system_slot_); - test_system_slot_ = slot.Pass(); - if (test_system_slot_) { - tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get())); - RunAndClearTPMReadyCallbackList(); - } else { - tpm_slot_.reset(); - } - } -#endif // defined(OS_CHROMEOS) - -#if !defined(OS_CHROMEOS) - PK11SlotInfo* GetPersistentNSSKeySlot() { - // TODO(mattm): Change to DCHECK when callers have been fixed. - if (!thread_checker_.CalledOnValidThread()) { - DVLOG(1) << "Called on wrong thread.\n" - << base::debug::StackTrace().ToString(); - } - - return PK11_GetInternalKeySlot(); - } -#endif - -#if defined(OS_CHROMEOS) - void GetSystemNSSKeySlotCallback( - const base::Callback& callback) { - callback.Run(ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get()))); - } - - ScopedPK11Slot GetSystemNSSKeySlot( - const base::Callback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - // TODO(mattm): chromeos::TPMTokenloader always calls - // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is - // disabled, tpm_slot_ will be the first user's slot instead. Can that be - // detected and return NULL instead? - - base::Closure wrapped_callback; - if (!callback.is_null()) { - wrapped_callback = - base::Bind(&NSSInitSingleton::GetSystemNSSKeySlotCallback, - base::Unretained(this) /* singleton is leaky */, - callback); - } - if (IsTPMTokenReady(wrapped_callback)) - return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get())); - return ScopedPK11Slot(); - } -#endif - -#if defined(USE_NSS_CERTS) - base::Lock* write_lock() { - return &write_lock_; - } -#endif // defined(USE_NSS_CERTS) - - // This method is used to force NSS to be initialized without a DB. - // Call this method before NSSInitSingleton() is constructed. - static void ForceNoDBInit() { - force_nodb_init_ = true; - } - - private: - friend struct base::DefaultLazyInstanceTraits; - - NSSInitSingleton() - : tpm_token_enabled_for_nss_(false), - initializing_tpm_token_(false), - chaps_module_(NULL), - root_(NULL) { - // It's safe to construct on any thread, since LazyInstance will prevent any - // other threads from accessing until the constructor is done. - thread_checker_.DetachFromThread(); - - DisableAESNIIfNeeded(); - - EnsureNSPRInit(); - - // We *must* have NSS >= 3.14.3. - static_assert( - (NSS_VMAJOR == 3 && NSS_VMINOR == 14 && NSS_VPATCH >= 3) || - (NSS_VMAJOR == 3 && NSS_VMINOR > 14) || - (NSS_VMAJOR > 3), - "nss version check failed"); - // Also check the run-time NSS version. - // NSS_VersionCheck is a >= check, not strict equality. - if (!NSS_VersionCheck("3.14.3")) { - LOG(FATAL) << "NSS_VersionCheck(\"3.14.3\") failed. NSS >= 3.14.3 is " - "required. Please upgrade to the latest NSS, and if you " - "still get this error, contact your distribution " - "maintainer."; - } - - SECStatus status = SECFailure; - bool nodb_init = force_nodb_init_; - -#if !defined(USE_NSS_CERTS) - // Use the system certificate store, so initialize NSS without database. - nodb_init = true; -#endif - - if (nodb_init) { - status = NSS_NoDB_Init(NULL); - if (status != SECSuccess) { - CrashOnNSSInitFailure(); - return; - } -#if defined(OS_IOS) - root_ = InitDefaultRootCerts(); -#endif // defined(OS_IOS) - } else { -#if defined(USE_NSS_CERTS) - base::FilePath database_dir = GetInitialConfigDirectory(); - if (!database_dir.empty()) { - // This duplicates the work which should have been done in - // EarlySetupForNSSInit. However, this function is idempotent so - // there's no harm done. - UseLocalCacheOfNSSDatabaseIfNFS(database_dir); - - // Initialize with a persistent database (likely, ~/.pki/nssdb). - // Use "sql:" which can be shared by multiple processes safely. - std::string nss_config_dir = - base::StringPrintf("sql:%s", database_dir.value().c_str()); -#if defined(OS_CHROMEOS) - status = NSS_Init(nss_config_dir.c_str()); -#else - status = NSS_InitReadWrite(nss_config_dir.c_str()); -#endif - if (status != SECSuccess) { - LOG(ERROR) << "Error initializing NSS with a persistent " - "database (" << nss_config_dir - << "): " << GetNSSErrorMessage(); - } - } - if (status != SECSuccess) { - VLOG(1) << "Initializing NSS without a persistent database."; - status = NSS_NoDB_Init(NULL); - if (status != SECSuccess) { - CrashOnNSSInitFailure(); - return; - } - } - - PK11_SetPasswordFunc(PKCS11PasswordFunc); - - // If we haven't initialized the password for the NSS databases, - // initialize an empty-string password so that we don't need to - // log in. - PK11SlotInfo* slot = PK11_GetInternalKeySlot(); - if (slot) { - // PK11_InitPin may write to the keyDB, but no other thread can use NSS - // yet, so we don't need to lock. - if (PK11_NeedUserInit(slot)) - PK11_InitPin(slot, NULL, NULL); - PK11_FreeSlot(slot); - } - - root_ = InitDefaultRootCerts(); -#endif // defined(USE_NSS_CERTS) - } - - // Disable MD5 certificate signatures. (They are disabled by default in - // NSS 3.14.) - NSS_SetAlgorithmPolicy(SEC_OID_MD5, 0, NSS_USE_ALG_IN_CERT_SIGNATURE); - NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, - 0, NSS_USE_ALG_IN_CERT_SIGNATURE); - } - - // NOTE(willchan): We don't actually execute this code since we leak NSS to - // prevent non-joinable threads from using NSS after it's already been shut - // down. - ~NSSInitSingleton() { -#if defined(OS_CHROMEOS) - STLDeleteValues(&chromeos_user_map_); -#endif - tpm_slot_.reset(); - if (root_) { - SECMOD_UnloadUserModule(root_); - SECMOD_DestroyModule(root_); - root_ = NULL; - } - if (chaps_module_) { - SECMOD_UnloadUserModule(chaps_module_); - SECMOD_DestroyModule(chaps_module_); - chaps_module_ = NULL; - } - - SECStatus status = NSS_Shutdown(); - if (status != SECSuccess) { - // We VLOG(1) because this failure is relatively harmless (leaking, but - // we're shutting down anyway). - VLOG(1) << "NSS_Shutdown failed; see http://crbug.com/4609"; - } - } - -#if defined(USE_NSS_CERTS) || defined(OS_IOS) - // Load nss's built-in root certs. - SECMODModule* InitDefaultRootCerts() { - SECMODModule* root = LoadModule("Root Certs", "libnssckbi.so", NULL); - if (root) - return root; - - // Aw, snap. Can't find/load root cert shared library. - // This will make it hard to talk to anybody via https. - // TODO(mattm): Re-add the NOTREACHED here when crbug.com/310972 is fixed. - return NULL; - } - - // Load the given module for this NSS session. - static SECMODModule* LoadModule(const char* name, - const char* library_path, - const char* params) { - std::string modparams = base::StringPrintf( - "name=\"%s\" library=\"%s\" %s", - name, library_path, params ? params : ""); - - // Shouldn't need to const_cast here, but SECMOD doesn't properly - // declare input string arguments as const. Bug - // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed - // on NSS codebase to address this. - SECMODModule* module = SECMOD_LoadUserModule( - const_cast(modparams.c_str()), NULL, PR_FALSE); - if (!module) { - LOG(ERROR) << "Error loading " << name << " module into NSS: " - << GetNSSErrorMessage(); - return NULL; - } - if (!module->loaded) { - LOG(ERROR) << "After loading " << name << ", loaded==false: " - << GetNSSErrorMessage(); - SECMOD_DestroyModule(module); - return NULL; - } - return module; - } -#endif - - static void DisableAESNIIfNeeded() { - if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { - // Some versions of NSS have a bug that causes AVX instructions to be - // used without testing whether XSAVE is enabled by the operating system. - // In order to work around this, we disable AES-NI in NSS when we find - // that |has_avx()| is false (which includes the XSAVE test). See - // https://bugzilla.mozilla.org/show_bug.cgi?id=940794 - base::CPU cpu; - - if (cpu.has_avx_hardware() && !cpu.has_avx()) { - scoped_ptr env(base::Environment::Create()); - env->SetVar("NSS_DISABLE_HW_AES", "1"); - } - } - } - - // If this is set to true NSS is forced to be initialized without a DB. - static bool force_nodb_init_; - - bool tpm_token_enabled_for_nss_; - bool initializing_tpm_token_; - typedef std::vector TPMReadyCallbackList; - TPMReadyCallbackList tpm_ready_callback_list_; - SECMODModule* chaps_module_; - crypto::ScopedPK11Slot tpm_slot_; - SECMODModule* root_; -#if defined(OS_CHROMEOS) - typedef std::map ChromeOSUserMap; - ChromeOSUserMap chromeos_user_map_; - ScopedPK11Slot test_system_slot_; -#endif -#if defined(USE_NSS_CERTS) - // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 - // is fixed, we will no longer need the lock. - base::Lock write_lock_; -#endif // defined(USE_NSS_CERTS) - - base::ThreadChecker thread_checker_; -}; - -// static -bool NSSInitSingleton::force_nodb_init_ = false; - -base::LazyInstance::Leaky - g_nss_singleton = LAZY_INSTANCE_INITIALIZER; -} // namespace - -#if defined(USE_NSS_CERTS) -ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path, - const std::string& description) { - const std::string modspec = - base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", - path.value().c_str(), - description.c_str()); - PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); - if (db_slot) { - if (PK11_NeedUserInit(db_slot)) - PK11_InitPin(db_slot, NULL, NULL); - } else { - LOG(ERROR) << "Error opening persistent database (" << modspec - << "): " << GetNSSErrorMessage(); - } - return ScopedPK11Slot(db_slot); -} - -void EarlySetupForNSSInit() { - base::FilePath database_dir = GetInitialConfigDirectory(); - if (!database_dir.empty()) - UseLocalCacheOfNSSDatabaseIfNFS(database_dir); -} -#endif - -void EnsureNSPRInit() { - g_nspr_singleton.Get(); -} - -void InitNSSSafely() { - // We might fork, but we haven't loaded any security modules. - DisableNSSForkCheck(); - // If we're sandboxed, we shouldn't be able to open user security modules, - // but it's more correct to tell NSS to not even try. - // Loading user security modules would have security implications. - ForceNSSNoDBInit(); - // Initialize NSS. - EnsureNSSInit(); -} - -void EnsureNSSInit() { - // Initializing SSL causes us to do blocking IO. - // Temporarily allow it until we fix - // http://code.google.com/p/chromium/issues/detail?id=59847 - base::ThreadRestrictions::ScopedAllowIO allow_io; - g_nss_singleton.Get(); -} - -void ForceNSSNoDBInit() { - NSSInitSingleton::ForceNoDBInit(); -} - -void DisableNSSForkCheck() { - scoped_ptr env(base::Environment::Create()); - env->SetVar("NSS_STRICT_NOFORK", "DISABLED"); -} - -void LoadNSSLibraries() { - // Some NSS libraries are linked dynamically so load them here. -#if defined(USE_NSS_CERTS) - // Try to search for multiple directories to load the libraries. - std::vector paths; - - // Use relative path to Search PATH for the library files. - paths.push_back(base::FilePath()); - - // For Debian derivatives NSS libraries are located here. - paths.push_back(base::FilePath("/usr/lib/nss")); - - // Ubuntu 11.10 (Oneiric) and Debian Wheezy place the libraries here. -#if defined(ARCH_CPU_X86_64) - paths.push_back(base::FilePath("/usr/lib/x86_64-linux-gnu/nss")); -#elif defined(ARCH_CPU_X86) - paths.push_back(base::FilePath("/usr/lib/i386-linux-gnu/nss")); -#elif defined(ARCH_CPU_ARMEL) -#if defined(__ARM_PCS_VFP) - paths.push_back(base::FilePath("/usr/lib/arm-linux-gnueabihf/nss")); -#else - paths.push_back(base::FilePath("/usr/lib/arm-linux-gnueabi/nss")); -#endif // defined(__ARM_PCS_VFP) -#elif defined(ARCH_CPU_MIPSEL) - paths.push_back(base::FilePath("/usr/lib/mipsel-linux-gnu/nss")); -#endif // defined(ARCH_CPU_X86_64) - - // A list of library files to load. - std::vector libs; - libs.push_back("libsoftokn3.so"); - libs.push_back("libfreebl3.so"); - - // For each combination of library file and path, check for existence and - // then load. - size_t loaded = 0; - for (size_t i = 0; i < libs.size(); ++i) { - for (size_t j = 0; j < paths.size(); ++j) { - base::FilePath path = paths[j].Append(libs[i]); - base::NativeLibrary lib = base::LoadNativeLibrary(path, NULL); - if (lib) { - ++loaded; - break; - } - } - } - - if (loaded == libs.size()) { - VLOG(3) << "NSS libraries loaded."; - } else { - LOG(ERROR) << "Failed to load NSS libraries."; - } -#endif // defined(USE_NSS_CERTS) -} - -bool CheckNSSVersion(const char* version) { - return !!NSS_VersionCheck(version); -} - -#if defined(USE_NSS_CERTS) -base::Lock* GetNSSWriteLock() { - return g_nss_singleton.Get().write_lock(); -} - -AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) { - // May be NULL if the lock is not needed in our version of NSS. - if (lock_) - lock_->Acquire(); -} - -AutoNSSWriteLock::~AutoNSSWriteLock() { - if (lock_) { - lock_->AssertAcquired(); - lock_->Release(); - } -} - -AutoSECMODListReadLock::AutoSECMODListReadLock() - : lock_(SECMOD_GetDefaultModuleListLock()) { - SECMOD_GetReadLock(lock_); - } - -AutoSECMODListReadLock::~AutoSECMODListReadLock() { - SECMOD_ReleaseReadLock(lock_); -} -#endif // defined(USE_NSS_CERTS) - -#if defined(OS_CHROMEOS) -ScopedPK11Slot GetSystemNSSKeySlot( - const base::Callback& callback) { - return g_nss_singleton.Get().GetSystemNSSKeySlot(callback); -} - -void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { - g_nss_singleton.Get().SetSystemKeySlotForTesting(slot.Pass()); -} - -void EnableTPMTokenForNSS() { - g_nss_singleton.Get().EnableTPMTokenForNSS(); -} - -bool IsTPMTokenEnabledForNSS() { - return g_nss_singleton.Get().IsTPMTokenEnabledForNSS(); -} - -bool IsTPMTokenReady(const base::Closure& callback) { - return g_nss_singleton.Get().IsTPMTokenReady(callback); -} - -void InitializeTPMTokenAndSystemSlot( - int token_slot_id, - const base::Callback& callback) { - g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id, - callback); -} - -bool InitializeNSSForChromeOSUser(const std::string& username_hash, - const base::FilePath& path) { - return g_nss_singleton.Get().InitializeNSSForChromeOSUser(username_hash, - path); -} - -bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { - return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser( - username_hash); -} - -void WillInitializeTPMForChromeOSUser(const std::string& username_hash) { - g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash); -} - -void InitializeTPMForChromeOSUser( - const std::string& username_hash, - CK_SLOT_ID slot_id) { - g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id); -} - -void InitializePrivateSoftwareSlotForChromeOSUser( - const std::string& username_hash) { - g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser( - username_hash); -} - -ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) { - return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash); -} - -ScopedPK11Slot GetPrivateSlotForChromeOSUser( - const std::string& username_hash, - const base::Callback& callback) { - return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(username_hash, - callback); -} - -void CloseChromeOSUserForTesting(const std::string& username_hash) { - g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash); -} -#endif // defined(OS_CHROMEOS) - -base::Time PRTimeToBaseTime(PRTime prtime) { - return base::Time::FromInternalValue( - prtime + base::Time::UnixEpoch().ToInternalValue()); -} - -PRTime BaseTimeToPRTime(base::Time time) { - return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); -} - -#if !defined(OS_CHROMEOS) -PK11SlotInfo* GetPersistentNSSKeySlot() { - return g_nss_singleton.Get().GetPersistentNSSKeySlot(); -} -#endif - -} // namespace crypto diff --git a/crypto/nss_util.h b/crypto/nss_util.h deleted file mode 100644 index 1ca0de3e77759..0000000000000 --- a/crypto/nss_util.h +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2012 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_NSS_UTIL_H_ -#define CRYPTO_NSS_UTIL_H_ - -#include -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "crypto/crypto_export.h" - -namespace base { -class FilePath; -class Lock; -class Time; -} // namespace base - -// This file specifically doesn't depend on any NSS or NSPR headers because it -// is included by various (non-crypto) parts of chrome to call the -// initialization functions. -namespace crypto { - -#if defined(USE_NSS_CERTS) -// EarlySetupForNSSInit performs lightweight setup which must occur before the -// process goes multithreaded. This does not initialise NSS. For test, see -// EnsureNSSInit. -CRYPTO_EXPORT void EarlySetupForNSSInit(); -#endif - -// Initialize NRPR if it isn't already initialized. This function is -// thread-safe, and NSPR will only ever be initialized once. -CRYPTO_EXPORT void EnsureNSPRInit(); - -// Initialize NSS safely for strict sandboxing. This function tells NSS to not -// load user security modules, and makes sure NSS will have proper entropy in a -// restricted, sandboxed environment. -// -// As a defense in depth measure, this function should be called in a sandboxed -// environment. That way, in the event of a bug, NSS will still not be able to -// load security modules that could expose private data and keys. -// -// Make sure to get an LGTM from the Chrome Security Team if you use this. -CRYPTO_EXPORT void InitNSSSafely(); - -// Initialize NSS if it isn't already initialized. This must be called before -// any other NSS functions. This function is thread-safe, and NSS will only -// ever be initialized once. -CRYPTO_EXPORT void EnsureNSSInit(); - -// Call this before calling EnsureNSSInit() will force NSS to initialize -// without a persistent DB. This is used for the special case where access of -// persistent DB is prohibited. -// -// TODO(hclam): Isolate loading default root certs. -// -// NSS will be initialized without loading any user security modules, including -// the built-in root certificates module. User security modules need to be -// loaded manually after NSS initialization. -// -// If EnsureNSSInit() is called before then this function has no effect. -// -// Calling this method only has effect on Linux. -// -// WARNING: Use this with caution. -CRYPTO_EXPORT void ForceNSSNoDBInit(); - -// This method is used to disable checks in NSS when used in a forked process. -// NSS checks whether it is running a forked process to avoid problems when -// using user security modules in a forked process. However if we are sure -// there are no modules loaded before the process is forked then there is no -// harm disabling the check. -// -// This method must be called before EnsureNSSInit() to take effect. -// -// WARNING: Use this with caution. -CRYPTO_EXPORT void DisableNSSForkCheck(); - -// Load NSS library files. This function has no effect on Mac and Windows. -// This loads the necessary NSS library files so that NSS can be initialized -// after loading additional library files is disallowed, for example when the -// sandbox is active. -// -// Note that this does not load libnssckbi.so which contains the root -// certificates. -CRYPTO_EXPORT void LoadNSSLibraries(); - -// Check if the current NSS version is greater than or equals to |version|. -// A sample version string is "3.12.3". -bool CheckNSSVersion(const char* version); - -#if defined(OS_CHROMEOS) -// Indicates that NSS should use the Chaps library so that we -// can access the TPM through NSS. InitializeTPMTokenAndSystemSlot and -// InitializeTPMForChromeOSUser must still be called to load the slots. -CRYPTO_EXPORT void EnableTPMTokenForNSS(); - -// Returns true if EnableTPMTokenForNSS has been called. -CRYPTO_EXPORT bool IsTPMTokenEnabledForNSS(); - -// Returns true if the TPM is owned and PKCS#11 initialized with the -// user and security officer PINs, and has been enabled in NSS by -// calling EnableTPMForNSS, and Chaps has been successfully -// loaded into NSS. -// If |callback| is non-null and the function returns false, the |callback| will -// be run once the TPM is ready. |callback| will never be run if the function -// returns true. -CRYPTO_EXPORT bool IsTPMTokenReady(const base::Closure& callback) - WARN_UNUSED_RESULT; - -// Initialize the TPM token and system slot. The |callback| will run on the same -// thread with true if the token and slot were successfully loaded or were -// already initialized. |callback| will be passed false if loading failed. Once -// called, InitializeTPMTokenAndSystemSlot must not be called again until the -// |callback| has been run. -CRYPTO_EXPORT void InitializeTPMTokenAndSystemSlot( - int system_slot_id, - const base::Callback& callback); -#endif - -// Convert a NSS PRTime value into a base::Time object. -// We use a int64 instead of PRTime here to avoid depending on NSPR headers. -CRYPTO_EXPORT base::Time PRTimeToBaseTime(int64 prtime); - -// Convert a base::Time object into a PRTime value. -// We use a int64 instead of PRTime here to avoid depending on NSPR headers. -CRYPTO_EXPORT int64 BaseTimeToPRTime(base::Time time); - -#if defined(USE_NSS_CERTS) -// NSS has a bug which can cause a deadlock or stall in some cases when writing -// to the certDB and keyDB. It also has a bug which causes concurrent key pair -// generations to scribble over each other. To work around this, we synchronize -// writes to the NSS databases with a global lock. The lock is hidden beneath a -// function for easy disabling when the bug is fixed. Callers should allow for -// it to return NULL in the future. -// -// See https://bugzilla.mozilla.org/show_bug.cgi?id=564011 -base::Lock* GetNSSWriteLock(); - -// A helper class that acquires the NSS write Lock while the AutoNSSWriteLock -// is in scope. -class CRYPTO_EXPORT AutoNSSWriteLock { - public: - AutoNSSWriteLock(); - ~AutoNSSWriteLock(); - private: - base::Lock *lock_; - DISALLOW_COPY_AND_ASSIGN(AutoNSSWriteLock); -}; -#endif // defined(USE_NSS_CERTS) - -} // namespace crypto - -#endif // CRYPTO_NSS_UTIL_H_ diff --git a/crypto/nss_util_internal.h b/crypto/nss_util_internal.h deleted file mode 100644 index f321343d95649..0000000000000 --- a/crypto/nss_util_internal.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2012 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_NSS_UTIL_INTERNAL_H_ -#define CRYPTO_NSS_UTIL_INTERNAL_H_ - -#include - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "crypto/crypto_export.h" -#include "crypto/scoped_nss_types.h" - -namespace base { -class FilePath; -} - -// These functions return a type defined in an NSS header, and so cannot be -// declared in nss_util.h. Hence, they are declared here. - -namespace crypto { - -// Opens an NSS software database in folder |path|, with the (potentially) -// user-visible description |description|. Returns the slot for the opened -// database, or NULL if the database could not be opened. -CRYPTO_EXPORT_PRIVATE ScopedPK11Slot - OpenSoftwareNSSDB(const base::FilePath& path, - const std::string& description); - -#if !defined(OS_CHROMEOS) -// Returns a reference to the default NSS key slot for storing persistent data. -// Caller must release returned reference with PK11_FreeSlot. -CRYPTO_EXPORT PK11SlotInfo* GetPersistentNSSKeySlot() WARN_UNUSED_RESULT; -#endif - -// A helper class that acquires the SECMOD list read lock while the -// AutoSECMODListReadLock is in scope. -class CRYPTO_EXPORT AutoSECMODListReadLock { - public: - AutoSECMODListReadLock(); - ~AutoSECMODListReadLock(); - - private: - SECMODListLock* lock_; - DISALLOW_COPY_AND_ASSIGN(AutoSECMODListReadLock); -}; - -#if defined(OS_CHROMEOS) -// Returns a reference to the system-wide TPM slot if it is loaded. If it is not -// loaded and |callback| is non-null, the |callback| will be run once the slot -// is loaded. -CRYPTO_EXPORT ScopedPK11Slot GetSystemNSSKeySlot( - const base::Callback& callback) WARN_UNUSED_RESULT; - -// Sets the test system slot to |slot|, which means that |slot| will be exposed -// through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true. -// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization, -// does not have to be called if the test system slot is set. -// This must must not be called consecutively with a |slot| != NULL. If |slot| -// is NULL, the test system slot is unset. -CRYPTO_EXPORT_PRIVATE void SetSystemKeySlotForTesting(ScopedPK11Slot slot); - -// Prepare per-user NSS slot mapping. It is safe to call this function multiple -// times. Returns true if the user was added, or false if it already existed. -CRYPTO_EXPORT bool InitializeNSSForChromeOSUser( - const std::string& username_hash, - const base::FilePath& path); - -// Returns whether TPM for ChromeOS user still needs initialization. If -// true is returned, the caller can proceed to initialize TPM slot for the -// user, but should call |WillInitializeTPMForChromeOSUser| first. -// |InitializeNSSForChromeOSUser| must have been called first. -CRYPTO_EXPORT bool ShouldInitializeTPMForChromeOSUser( - const std::string& username_hash) WARN_UNUSED_RESULT; - -// Makes |ShouldInitializeTPMForChromeOSUser| start returning false. -// Should be called before starting TPM initialization for the user. -// Assumes |InitializeNSSForChromeOSUser| had already been called. -CRYPTO_EXPORT void WillInitializeTPMForChromeOSUser( - const std::string& username_hash); - -// Use TPM slot |slot_id| for user. InitializeNSSForChromeOSUser must have been -// called first. -CRYPTO_EXPORT void InitializeTPMForChromeOSUser( - const std::string& username_hash, - CK_SLOT_ID slot_id); - -// Use the software slot as the private slot for user. -// InitializeNSSForChromeOSUser must have been called first. -CRYPTO_EXPORT void InitializePrivateSoftwareSlotForChromeOSUser( - const std::string& username_hash); - -// Returns a reference to the public slot for user. -CRYPTO_EXPORT ScopedPK11Slot GetPublicSlotForChromeOSUser( - const std::string& username_hash) WARN_UNUSED_RESULT; - -// Returns the private slot for |username_hash| if it is loaded. If it is not -// loaded and |callback| is non-null, the |callback| will be run once the slot -// is loaded. -CRYPTO_EXPORT ScopedPK11Slot GetPrivateSlotForChromeOSUser( - const std::string& username_hash, - const base::Callback& callback) WARN_UNUSED_RESULT; - -// Closes the NSS DB for |username_hash| that was previously opened by the -// *Initialize*ForChromeOSUser functions. -CRYPTO_EXPORT_PRIVATE void CloseChromeOSUserForTesting( - const std::string& username_hash); -#endif // defined(OS_CHROMEOS) - -} // namespace crypto - -#endif // CRYPTO_NSS_UTIL_INTERNAL_H_ diff --git a/crypto/nss_util_unittest.cc b/crypto/nss_util_unittest.cc deleted file mode 100644 index 28591916d3f65..0000000000000 --- a/crypto/nss_util_unittest.cc +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2011 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/nss_util.h" - -#include - -#include "base/time/time.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -TEST(NSSUtilTest, PRTimeConversion) { - EXPECT_EQ(base::Time::UnixEpoch(), PRTimeToBaseTime(0)); - EXPECT_EQ(0, BaseTimeToPRTime(base::Time::UnixEpoch())); - - PRExplodedTime prxtime; - prxtime.tm_params.tp_gmt_offset = 0; - prxtime.tm_params.tp_dst_offset = 0; - base::Time::Exploded exploded; - exploded.year = prxtime.tm_year = 2011; - exploded.month = 12; - prxtime.tm_month = 11; - // PRExplodedTime::tm_wday is a smaller type than Exploded::day_of_week, so - // assigning the two in this order instead of the reverse avoids potential - // warnings about type downcasting. - exploded.day_of_week = prxtime.tm_wday = 0; // Should be unused. - exploded.day_of_month = prxtime.tm_mday = 10; - exploded.hour = prxtime.tm_hour = 2; - exploded.minute = prxtime.tm_min = 52; - exploded.second = prxtime.tm_sec = 19; - exploded.millisecond = 342; - prxtime.tm_usec = 342000; - - PRTime pr_time = PR_ImplodeTime(&prxtime); - base::Time base_time = base::Time::FromUTCExploded(exploded); - - EXPECT_EQ(base_time, PRTimeToBaseTime(pr_time)); - EXPECT_EQ(pr_time, BaseTimeToPRTime(base_time)); -} - -} // namespace crypto diff --git a/crypto/openssl_bio_string.cc b/crypto/openssl_bio_string.cc deleted file mode 100644 index 48805001ef664..0000000000000 --- a/crypto/openssl_bio_string.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2014 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/openssl_bio_string.h" - -#include -#include - -namespace crypto { - -namespace { - -int bio_string_write(BIO* bio, const char* data, int len) { - reinterpret_cast(bio->ptr)->append(data, len); - return len; -} - -int bio_string_puts(BIO* bio, const char* data) { - // Note: unlike puts(), BIO_puts does not add a newline. - return bio_string_write(bio, data, strlen(data)); -} - -long bio_string_ctrl(BIO* bio, int cmd, long num, void* ptr) { - std::string* str = reinterpret_cast(bio->ptr); - switch (cmd) { - case BIO_CTRL_RESET: - str->clear(); - return 1; - case BIO_C_FILE_SEEK: - return -1; - case BIO_C_FILE_TELL: - return str->size(); - case BIO_CTRL_FLUSH: - return 1; - default: - return 0; - } -} - -int bio_string_new(BIO* bio) { - bio->ptr = NULL; - bio->init = 0; - return 1; -} - -int bio_string_free(BIO* bio) { - // The string is owned by the caller, so there's nothing to do here. - return bio != NULL; -} - -BIO_METHOD bio_string_methods = { - // TODO(mattm): Should add some type number too? (bio.h uses 1-24) - BIO_TYPE_SOURCE_SINK, - "bio_string", - bio_string_write, - NULL, /* read */ - bio_string_puts, - NULL, /* gets */ - bio_string_ctrl, - bio_string_new, - bio_string_free, - NULL, /* callback_ctrl */ -}; - -} // namespace - -BIO* BIO_new_string(std::string* out) { - BIO* bio = BIO_new(&bio_string_methods); - if (!bio) - return bio; - bio->ptr = out; - bio->init = 1; - return bio; -} - -} // namespace crypto diff --git a/crypto/openssl_bio_string.h b/crypto/openssl_bio_string.h deleted file mode 100644 index ca46c12de8d8f..0000000000000 --- a/crypto/openssl_bio_string.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 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_OPENSSL_BIO_STRING_H_ -#define CRYPTO_OPENSSL_BIO_STRING_H_ - -#include - -#include "crypto/crypto_export.h" - -// From -typedef struct bio_st BIO; - -namespace crypto { - -// Creates a new BIO that can be used with OpenSSL's various output functions, -// and which will write all output directly into |out|. This is primarily -// intended as a utility to reduce the amount of copying and separate -// allocations when performing extensive string modifications or streaming -// within OpenSSL. -// -// Note: |out| must remain valid for the duration of the BIO. -CRYPTO_EXPORT BIO* BIO_new_string(std::string* out); - -} // namespace crypto - -#endif // CRYPTO_OPENSSL_BIO_STRING_H_ - diff --git a/crypto/openssl_bio_string_unittest.cc b/crypto/openssl_bio_string_unittest.cc deleted file mode 100644 index 9dfa0e70f7332..0000000000000 --- a/crypto/openssl_bio_string_unittest.cc +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 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/openssl_bio_string.h" - -#include - -#include "crypto/scoped_openssl_types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -TEST(OpenSSLBIOString, TestWrite) { - std::string s; - const std::string expected1("a one\nb 2\n"); - const std::string expected2("c d e f"); - const std::string expected3("g h i"); - { - ScopedBIO bio(BIO_new_string(&s)); - ASSERT_TRUE(bio.get()); - - EXPECT_EQ(static_cast(expected1.size()), - BIO_printf(bio.get(), "a %s\nb %i\n", "one", 2)); - EXPECT_EQ(expected1, s); - - EXPECT_EQ(1, BIO_flush(bio.get())); - EXPECT_EQ(expected1, s); - - EXPECT_EQ(static_cast(expected2.size()), - BIO_write(bio.get(), expected2.data(), expected2.size())); - EXPECT_EQ(expected1 + expected2, s); - - EXPECT_EQ(static_cast(expected3.size()), - BIO_puts(bio.get(), expected3.c_str())); - EXPECT_EQ(expected1 + expected2 + expected3, s); - } - EXPECT_EQ(expected1 + expected2 + expected3, s); -} - -TEST(OpenSSLBIOString, TestReset) { - std::string s; - const std::string expected1("a b c\n"); - const std::string expected2("d e f g\n"); - { - ScopedBIO bio(BIO_new_string(&s)); - ASSERT_TRUE(bio.get()); - - EXPECT_EQ(static_cast(expected1.size()), - BIO_write(bio.get(), expected1.data(), expected1.size())); - EXPECT_EQ(expected1, s); - - EXPECT_EQ(1, BIO_reset(bio.get())); - EXPECT_EQ(std::string(), s); - - EXPECT_EQ(static_cast(expected2.size()), - BIO_write(bio.get(), expected2.data(), expected2.size())); - EXPECT_EQ(expected2, s); - } - EXPECT_EQ(expected2, s); -} - -} // namespace crypto diff --git a/crypto/openssl_util.cc b/crypto/openssl_util.cc deleted file mode 100644 index d89857f3851d7..0000000000000 --- a/crypto/openssl_util.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2011 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/openssl_util.h" - -#include -#include -#include - -#include "base/logging.h" -#include "base/memory/singleton.h" -#include "base/strings/string_piece.h" -#include "build/build_config.h" - -#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) -#include -#include "base/cpu.h" -#endif - -namespace crypto { - -namespace { - -// Singleton for initializing and cleaning up the OpenSSL library. -class OpenSSLInitSingleton { - public: - static OpenSSLInitSingleton* GetInstance() { - // We allow the SSL environment to leak for multiple reasons: - // - it is used from a non-joinable worker thread that is not stopped on - // shutdown, hence may still be using OpenSSL library after the AtExit - // runner has completed. - // - There are other OpenSSL related singletons (e.g. the client socket - // context) who's cleanup depends on the global environment here, but - // we can't control the order the AtExit handlers will run in so - // allowing the global environment to leak at least ensures it is - // available for those other singletons to reliably cleanup. - return Singleton >::get(); - } - private: - friend struct DefaultSingletonTraits; - OpenSSLInitSingleton() { -#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) - const bool has_neon = - (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; - // CRYPTO_set_NEON_capable is called before |SSL_library_init| because this - // stops BoringSSL from probing for NEON support via SIGILL in the case - // that getauxval isn't present. - CRYPTO_set_NEON_capable(has_neon); - // See https://code.google.com/p/chromium/issues/detail?id=341598 - base::CPU cpu; - CRYPTO_set_NEON_functional(!cpu.has_broken_neon()); -#endif - - SSL_library_init(); - } - - ~OpenSSLInitSingleton() {} - - DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton); -}; - -// Callback routine for OpenSSL to print error messages. |str| is a -// NULL-terminated string of length |len| containing diagnostic information -// such as the library, function and reason for the error, the file and line -// where the error originated, plus potentially any context-specific -// information about the error. |context| contains a pointer to user-supplied -// data, which is currently unused. -// If this callback returns a value <= 0, OpenSSL will stop processing the -// error queue and return, otherwise it will continue calling this function -// until all errors have been removed from the queue. -int OpenSSLErrorCallback(const char* str, size_t len, void* context) { - DVLOG(1) << "\t" << base::StringPiece(str, len); - return 1; -} - -} // namespace - -void EnsureOpenSSLInit() { - (void)OpenSSLInitSingleton::GetInstance(); -} - -void ClearOpenSSLERRStack(const tracked_objects::Location& location) { - if (logging::DEBUG_MODE && VLOG_IS_ON(1)) { - uint32_t error_num = ERR_peek_error(); - if (error_num == 0) - return; - - std::string message; - location.Write(true, true, &message); - DVLOG(1) << "OpenSSL ERR_get_error stack from " << message; - ERR_print_errors_cb(&OpenSSLErrorCallback, NULL); - } else { - ERR_clear_error(); - } -} - -} // namespace crypto diff --git a/crypto/openssl_util.h b/crypto/openssl_util.h deleted file mode 100644 index 2743883dc17b4..0000000000000 --- a/crypto/openssl_util.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2012 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_OPENSSL_UTIL_H_ -#define CRYPTO_OPENSSL_UTIL_H_ - -#include "base/basictypes.h" -#include "base/location.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// Provides a buffer of at least MIN_SIZE bytes, for use when calling OpenSSL's -// SHA256, HMAC, etc functions, adapting the buffer sizing rules to meet those -// of the our base wrapper APIs. -// This allows the library to write directly to the caller's buffer if it is of -// sufficient size, but if not it will write to temporary |min_sized_buffer_| -// of required size and then its content is automatically copied out on -// destruction, with truncation as appropriate. -template -class ScopedOpenSSLSafeSizeBuffer { - public: - ScopedOpenSSLSafeSizeBuffer(unsigned char* output, size_t output_len) - : output_(output), - output_len_(output_len) { - } - - ~ScopedOpenSSLSafeSizeBuffer() { - if (output_len_ < MIN_SIZE) { - // Copy the temporary buffer out, truncating as needed. - memcpy(output_, min_sized_buffer_, output_len_); - } - // else... any writing already happened directly into |output_|. - } - - unsigned char* safe_buffer() { - return output_len_ < MIN_SIZE ? min_sized_buffer_ : output_; - } - - private: - // Pointer to the caller's data area and its associated size, where data - // written via safe_buffer() will [eventually] end up. - unsigned char* output_; - size_t output_len_; - - // Temporary buffer writen into in the case where the caller's - // buffer is not of sufficient size. - unsigned char min_sized_buffer_[MIN_SIZE]; - - DISALLOW_COPY_AND_ASSIGN(ScopedOpenSSLSafeSizeBuffer); -}; - -// Initialize OpenSSL if it isn't already initialized. This must be called -// before any other OpenSSL functions though it is safe and cheap to call this -// multiple times. -// This function is thread-safe, and OpenSSL will only ever be initialized once. -// OpenSSL will be properly shut down on program exit. -void CRYPTO_EXPORT EnsureOpenSSLInit(); - -// Drains the OpenSSL ERR_get_error stack. On a debug build the error codes -// are send to VLOG(1), on a release build they are disregarded. In most -// cases you should pass FROM_HERE as the |location|. -void CRYPTO_EXPORT ClearOpenSSLERRStack( - const tracked_objects::Location& location); - -// Place an instance of this class on the call stack to automatically clear -// the OpenSSL error stack on function exit. -class OpenSSLErrStackTracer { - public: - // Pass FROM_HERE as |location|, to help track the source of OpenSSL error - // messages. Note any diagnostic emitted will be tagged with the location of - // the constructor call as it's not possible to trace a destructor's callsite. - explicit OpenSSLErrStackTracer(const tracked_objects::Location& location) - : location_(location) { - EnsureOpenSSLInit(); - } - ~OpenSSLErrStackTracer() { - ClearOpenSSLERRStack(location_); - } - - private: - const tracked_objects::Location location_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(OpenSSLErrStackTracer); -}; - -} // namespace crypto - -#endif // CRYPTO_OPENSSL_UTIL_H_ diff --git a/crypto/p224.cc b/crypto/p224.cc deleted file mode 100644 index 11946a9413c5b..0000000000000 --- a/crypto/p224.cc +++ /dev/null @@ -1,758 +0,0 @@ -// Copyright (c) 2012 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. - -// This is an implementation of the P224 elliptic curve group. It's written to -// be short and simple rather than fast, although it's still constant-time. -// -// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. - -#include "crypto/p224.h" - -#include - -#include "base/sys_byteorder.h" - -namespace { - -using base::HostToNet32; -using base::NetToHost32; - -// Field element functions. -// -// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1. -// -// Field elements are represented by a FieldElement, which is a typedef to an -// array of 8 uint32's. The value of a FieldElement, a, is: -// a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7] -// -// Using 28-bit limbs means that there's only 4 bits of headroom, which is less -// than we would really like. But it has the useful feature that we hit 2**224 -// exactly, making the reflections during a reduce much nicer. - -using crypto::p224::FieldElement; - -// kP is the P224 prime. -const FieldElement kP = { - 1, 0, 0, 268431360, - 268435455, 268435455, 268435455, 268435455, -}; - -void Contract(FieldElement* inout); - -// IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise. -uint32 IsZero(const FieldElement& a) { - FieldElement minimal; - memcpy(&minimal, &a, sizeof(minimal)); - Contract(&minimal); - - uint32 is_zero = 0, is_p = 0; - for (unsigned i = 0; i < 8; i++) { - is_zero |= minimal[i]; - is_p |= minimal[i] - kP[i]; - } - - // If either is_zero or is_p is 0, then we should return 1. - is_zero |= is_zero >> 16; - is_zero |= is_zero >> 8; - is_zero |= is_zero >> 4; - is_zero |= is_zero >> 2; - is_zero |= is_zero >> 1; - - is_p |= is_p >> 16; - is_p |= is_p >> 8; - is_p |= is_p >> 4; - is_p |= is_p >> 2; - is_p |= is_p >> 1; - - // For is_zero and is_p, the LSB is 0 iff all the bits are zero. - is_zero &= is_p & 1; - is_zero = (~is_zero) << 31; - is_zero = static_cast(is_zero) >> 31; - return is_zero; -} - -// Add computes *out = a+b -// -// a[i] + b[i] < 2**32 -void Add(FieldElement* out, const FieldElement& a, const FieldElement& b) { - for (int i = 0; i < 8; i++) { - (*out)[i] = a[i] + b[i]; - } -} - -static const uint32 kTwo31p3 = (1u<<31) + (1u<<3); -static const uint32 kTwo31m3 = (1u<<31) - (1u<<3); -static const uint32 kTwo31m15m3 = (1u<<31) - (1u<<15) - (1u<<3); -// kZero31ModP is 0 mod p where bit 31 is set in all limbs so that we can -// subtract smaller amounts without underflow. See the section "Subtraction" in -// [1] for why. -static const FieldElement kZero31ModP = { - kTwo31p3, kTwo31m3, kTwo31m3, kTwo31m15m3, - kTwo31m3, kTwo31m3, kTwo31m3, kTwo31m3 -}; - -// Subtract computes *out = a-b -// -// a[i], b[i] < 2**30 -// out[i] < 2**32 -void Subtract(FieldElement* out, const FieldElement& a, const FieldElement& b) { - for (int i = 0; i < 8; i++) { - // See the section on "Subtraction" in [1] for details. - (*out)[i] = a[i] + kZero31ModP[i] - b[i]; - } -} - -static const uint64 kTwo63p35 = (1ull<<63) + (1ull<<35); -static const uint64 kTwo63m35 = (1ull<<63) - (1ull<<35); -static const uint64 kTwo63m35m19 = (1ull<<63) - (1ull<<35) - (1ull<<19); -// kZero63ModP is 0 mod p where bit 63 is set in all limbs. See the section -// "Subtraction" in [1] for why. -static const uint64 kZero63ModP[8] = { - kTwo63p35, kTwo63m35, kTwo63m35, kTwo63m35, - kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35, -}; - -static const uint32 kBottom28Bits = 0xfffffff; - -// LargeFieldElement also represents an element of the field. The limbs are -// still spaced 28-bits apart and in little-endian order. So the limbs are at -// 0, 28, 56, ..., 392 bits, each 64-bits wide. -typedef uint64 LargeFieldElement[15]; - -// ReduceLarge converts a LargeFieldElement to a FieldElement. -// -// in[i] < 2**62 - -// GCC 4.9 incorrectly vectorizes the first coefficient elimination loop, so -// disable that optimization via pragma. Don't use the pragma under Clang, since -// clang doesn't understand it. -// TODO(wez): Remove this when crbug.com/439566 is fixed. -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC optimize("no-tree-vectorize") -#endif - -void ReduceLarge(FieldElement* out, LargeFieldElement* inptr) { - LargeFieldElement& in(*inptr); - - for (int i = 0; i < 8; i++) { - in[i] += kZero63ModP[i]; - } - - // Eliminate the coefficients at 2**224 and greater while maintaining the - // same value mod p. - for (int i = 14; i >= 8; i--) { - in[i-8] -= in[i]; // reflection off the "+1" term of p. - in[i-5] += (in[i] & 0xffff) << 12; // part of the "-2**96" reflection. - in[i-4] += in[i] >> 16; // the rest of the "-2**96" reflection. - } - in[8] = 0; - // in[0..8] < 2**64 - - // As the values become small enough, we start to store them in |out| and use - // 32-bit operations. - for (int i = 1; i < 8; i++) { - in[i+1] += in[i] >> 28; - (*out)[i] = static_cast(in[i] & kBottom28Bits); - } - // Eliminate the term at 2*224 that we introduced while keeping the same - // value mod p. - in[0] -= in[8]; // reflection off the "+1" term of p. - (*out)[3] += static_cast(in[8] & 0xffff) << 12; // "-2**96" term - (*out)[4] += static_cast(in[8] >> 16); // rest of "-2**96" term - // in[0] < 2**64 - // out[3] < 2**29 - // out[4] < 2**29 - // out[1,2,5..7] < 2**28 - - (*out)[0] = static_cast(in[0] & kBottom28Bits); - (*out)[1] += static_cast((in[0] >> 28) & kBottom28Bits); - (*out)[2] += static_cast(in[0] >> 56); - // out[0] < 2**28 - // out[1..4] < 2**29 - // out[5..7] < 2**28 -} - -// TODO(wez): Remove this when crbug.com/439566 is fixed. -#if defined(__GNUC__) && !defined(__clang__) -// Reenable "tree-vectorize" optimization if it got disabled for ReduceLarge. -#pragma GCC reset_options -#endif - -// Mul computes *out = a*b -// -// a[i] < 2**29, b[i] < 2**30 (or vice versa) -// out[i] < 2**29 -void Mul(FieldElement* out, const FieldElement& a, const FieldElement& b) { - LargeFieldElement tmp; - memset(&tmp, 0, sizeof(tmp)); - - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 8; j++) { - tmp[i+j] += static_cast(a[i]) * static_cast(b[j]); - } - } - - ReduceLarge(out, &tmp); -} - -// Square computes *out = a*a -// -// a[i] < 2**29 -// out[i] < 2**29 -void Square(FieldElement* out, const FieldElement& a) { - LargeFieldElement tmp; - memset(&tmp, 0, sizeof(tmp)); - - for (int i = 0; i < 8; i++) { - for (int j = 0; j <= i; j++) { - uint64 r = static_cast(a[i]) * static_cast(a[j]); - if (i == j) { - tmp[i+j] += r; - } else { - tmp[i+j] += r << 1; - } - } - } - - ReduceLarge(out, &tmp); -} - -// Reduce reduces the coefficients of in_out to smaller bounds. -// -// On entry: a[i] < 2**31 + 2**30 -// On exit: a[i] < 2**29 -void Reduce(FieldElement* in_out) { - FieldElement& a = *in_out; - - for (int i = 0; i < 7; i++) { - a[i+1] += a[i] >> 28; - a[i] &= kBottom28Bits; - } - uint32 top = a[7] >> 28; - a[7] &= kBottom28Bits; - - // top < 2**4 - // Constant-time: mask = (top != 0) ? 0xffffffff : 0 - uint32 mask = top; - mask |= mask >> 2; - mask |= mask >> 1; - mask <<= 31; - mask = static_cast(static_cast(mask) >> 31); - - // Eliminate top while maintaining the same value mod p. - a[0] -= top; - a[3] += top << 12; - - // We may have just made a[0] negative but, if we did, then we must - // have added something to a[3], thus it's > 2**12. Therefore we can - // carry down to a[0]. - a[3] -= 1 & mask; - a[2] += mask & ((1<<28) - 1); - a[1] += mask & ((1<<28) - 1); - a[0] += mask & (1<<28); -} - -// Invert calcuates *out = in**-1 by computing in**(2**224 - 2**96 - 1), i.e. -// Fermat's little theorem. -void Invert(FieldElement* out, const FieldElement& in) { - FieldElement f1, f2, f3, f4; - - Square(&f1, in); // 2 - Mul(&f1, f1, in); // 2**2 - 1 - Square(&f1, f1); // 2**3 - 2 - Mul(&f1, f1, in); // 2**3 - 1 - Square(&f2, f1); // 2**4 - 2 - Square(&f2, f2); // 2**5 - 4 - Square(&f2, f2); // 2**6 - 8 - Mul(&f1, f1, f2); // 2**6 - 1 - Square(&f2, f1); // 2**7 - 2 - for (int i = 0; i < 5; i++) { // 2**12 - 2**6 - Square(&f2, f2); - } - Mul(&f2, f2, f1); // 2**12 - 1 - Square(&f3, f2); // 2**13 - 2 - for (int i = 0; i < 11; i++) { // 2**24 - 2**12 - Square(&f3, f3); - } - Mul(&f2, f3, f2); // 2**24 - 1 - Square(&f3, f2); // 2**25 - 2 - for (int i = 0; i < 23; i++) { // 2**48 - 2**24 - Square(&f3, f3); - } - Mul(&f3, f3, f2); // 2**48 - 1 - Square(&f4, f3); // 2**49 - 2 - for (int i = 0; i < 47; i++) { // 2**96 - 2**48 - Square(&f4, f4); - } - Mul(&f3, f3, f4); // 2**96 - 1 - Square(&f4, f3); // 2**97 - 2 - for (int i = 0; i < 23; i++) { // 2**120 - 2**24 - Square(&f4, f4); - } - Mul(&f2, f4, f2); // 2**120 - 1 - for (int i = 0; i < 6; i++) { // 2**126 - 2**6 - Square(&f2, f2); - } - Mul(&f1, f1, f2); // 2**126 - 1 - Square(&f1, f1); // 2**127 - 2 - Mul(&f1, f1, in); // 2**127 - 1 - for (int i = 0; i < 97; i++) { // 2**224 - 2**97 - Square(&f1, f1); - } - Mul(out, f1, f3); // 2**224 - 2**96 - 1 -} - -// Contract converts a FieldElement to its minimal, distinguished form. -// -// On entry, in[i] < 2**29 -// On exit, in[i] < 2**28 -void Contract(FieldElement* inout) { - FieldElement& out = *inout; - - // Reduce the coefficients to < 2**28. - for (int i = 0; i < 7; i++) { - out[i+1] += out[i] >> 28; - out[i] &= kBottom28Bits; - } - uint32 top = out[7] >> 28; - out[7] &= kBottom28Bits; - - // Eliminate top while maintaining the same value mod p. - out[0] -= top; - out[3] += top << 12; - - // We may just have made out[0] negative. So we carry down. If we made - // out[0] negative then we know that out[3] is sufficiently positive - // because we just added to it. - for (int i = 0; i < 3; i++) { - uint32 mask = static_cast(static_cast(out[i]) >> 31); - out[i] += (1 << 28) & mask; - out[i+1] -= 1 & mask; - } - - // We might have pushed out[3] over 2**28 so we perform another, partial - // carry chain. - for (int i = 3; i < 7; i++) { - out[i+1] += out[i] >> 28; - out[i] &= kBottom28Bits; - } - top = out[7] >> 28; - out[7] &= kBottom28Bits; - - // Eliminate top while maintaining the same value mod p. - out[0] -= top; - out[3] += top << 12; - - // There are two cases to consider for out[3]: - // 1) The first time that we eliminated top, we didn't push out[3] over - // 2**28. In this case, the partial carry chain didn't change any values - // and top is zero. - // 2) We did push out[3] over 2**28 the first time that we eliminated top. - // The first value of top was in [0..16), therefore, prior to eliminating - // the first top, 0xfff1000 <= out[3] <= 0xfffffff. Therefore, after - // overflowing and being reduced by the second carry chain, out[3] <= - // 0xf000. Thus it cannot have overflowed when we eliminated top for the - // second time. - - // Again, we may just have made out[0] negative, so do the same carry down. - // As before, if we made out[0] negative then we know that out[3] is - // sufficiently positive. - for (int i = 0; i < 3; i++) { - uint32 mask = static_cast(static_cast(out[i]) >> 31); - out[i] += (1 << 28) & mask; - out[i+1] -= 1 & mask; - } - - // The value is < 2**224, but maybe greater than p. In order to reduce to a - // unique, minimal value we see if the value is >= p and, if so, subtract p. - - // First we build a mask from the top four limbs, which must all be - // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones - // ends up with any zero bits in the bottom 28 bits, then this wasn't - // true. - uint32 top_4_all_ones = 0xffffffffu; - for (int i = 4; i < 8; i++) { - top_4_all_ones &= out[i]; - } - top_4_all_ones |= 0xf0000000; - // Now we replicate any zero bits to all the bits in top_4_all_ones. - top_4_all_ones &= top_4_all_ones >> 16; - top_4_all_ones &= top_4_all_ones >> 8; - top_4_all_ones &= top_4_all_ones >> 4; - top_4_all_ones &= top_4_all_ones >> 2; - top_4_all_ones &= top_4_all_ones >> 1; - top_4_all_ones = - static_cast(static_cast(top_4_all_ones << 31) >> 31); - - // Now we test whether the bottom three limbs are non-zero. - uint32 bottom_3_non_zero = out[0] | out[1] | out[2]; - bottom_3_non_zero |= bottom_3_non_zero >> 16; - bottom_3_non_zero |= bottom_3_non_zero >> 8; - bottom_3_non_zero |= bottom_3_non_zero >> 4; - bottom_3_non_zero |= bottom_3_non_zero >> 2; - bottom_3_non_zero |= bottom_3_non_zero >> 1; - bottom_3_non_zero = - static_cast(static_cast(bottom_3_non_zero) >> 31); - - // Everything depends on the value of out[3]. - // If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p - // If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0, - // then the whole value is >= p - // If it's < 0xffff000, then the whole value is < p - uint32 n = out[3] - 0xffff000; - uint32 out_3_equal = n; - out_3_equal |= out_3_equal >> 16; - out_3_equal |= out_3_equal >> 8; - out_3_equal |= out_3_equal >> 4; - out_3_equal |= out_3_equal >> 2; - out_3_equal |= out_3_equal >> 1; - out_3_equal = - ~static_cast(static_cast(out_3_equal << 31) >> 31); - - // If out[3] > 0xffff000 then n's MSB will be zero. - uint32 out_3_gt = ~static_cast(static_cast(n << 31) >> 31); - - uint32 mask = top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt); - out[0] -= 1 & mask; - out[3] -= 0xffff000 & mask; - out[4] -= 0xfffffff & mask; - out[5] -= 0xfffffff & mask; - out[6] -= 0xfffffff & mask; - out[7] -= 0xfffffff & mask; -} - - -// Group element functions. -// -// These functions deal with group elements. The group is an elliptic curve -// group with a = -3 defined in FIPS 186-3, section D.2.2. - -using crypto::p224::Point; - -// kB is parameter of the elliptic curve. -const FieldElement kB = { - 55967668, 11768882, 265861671, 185302395, - 39211076, 180311059, 84673715, 188764328, -}; - -void CopyConditional(Point* out, const Point& a, uint32 mask); -void DoubleJacobian(Point* out, const Point& a); - -// AddJacobian computes *out = a+b where a != b. -void AddJacobian(Point *out, - const Point& a, - const Point& b) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl - FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v; - - uint32 z1_is_zero = IsZero(a.z); - uint32 z2_is_zero = IsZero(b.z); - - // Z1Z1 = Z1² - Square(&z1z1, a.z); - - // Z2Z2 = Z2² - Square(&z2z2, b.z); - - // U1 = X1*Z2Z2 - Mul(&u1, a.x, z2z2); - - // U2 = X2*Z1Z1 - Mul(&u2, b.x, z1z1); - - // S1 = Y1*Z2*Z2Z2 - Mul(&s1, b.z, z2z2); - Mul(&s1, a.y, s1); - - // S2 = Y2*Z1*Z1Z1 - Mul(&s2, a.z, z1z1); - Mul(&s2, b.y, s2); - - // H = U2-U1 - Subtract(&h, u2, u1); - Reduce(&h); - uint32 x_equal = IsZero(h); - - // I = (2*H)² - for (int k = 0; k < 8; k++) { - i[k] = h[k] << 1; - } - Reduce(&i); - Square(&i, i); - - // J = H*I - Mul(&j, h, i); - // r = 2*(S2-S1) - Subtract(&r, s2, s1); - Reduce(&r); - uint32 y_equal = IsZero(r); - - if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { - // The two input points are the same therefore we must use the dedicated - // doubling function as the slope of the line is undefined. - DoubleJacobian(out, a); - return; - } - - for (int k = 0; k < 8; k++) { - r[k] <<= 1; - } - Reduce(&r); - - // V = U1*I - Mul(&v, u1, i); - - // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H - Add(&z1z1, z1z1, z2z2); - Add(&z2z2, a.z, b.z); - Reduce(&z2z2); - Square(&z2z2, z2z2); - Subtract(&out->z, z2z2, z1z1); - Reduce(&out->z); - Mul(&out->z, out->z, h); - - // X3 = r²-J-2*V - for (int k = 0; k < 8; k++) { - z1z1[k] = v[k] << 1; - } - Add(&z1z1, j, z1z1); - Reduce(&z1z1); - Square(&out->x, r); - Subtract(&out->x, out->x, z1z1); - Reduce(&out->x); - - // Y3 = r*(V-X3)-2*S1*J - for (int k = 0; k < 8; k++) { - s1[k] <<= 1; - } - Mul(&s1, s1, j); - Subtract(&z1z1, v, out->x); - Reduce(&z1z1); - Mul(&z1z1, z1z1, r); - Subtract(&out->y, z1z1, s1); - Reduce(&out->y); - - CopyConditional(out, a, z2_is_zero); - CopyConditional(out, b, z1_is_zero); -} - -// DoubleJacobian computes *out = a+a. -void DoubleJacobian(Point* out, const Point& a) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - FieldElement delta, gamma, beta, alpha, t; - - Square(&delta, a.z); - Square(&gamma, a.y); - Mul(&beta, a.x, gamma); - - // alpha = 3*(X1-delta)*(X1+delta) - Add(&t, a.x, delta); - for (int i = 0; i < 8; i++) { - t[i] += t[i] << 1; - } - Reduce(&t); - Subtract(&alpha, a.x, delta); - Reduce(&alpha); - Mul(&alpha, alpha, t); - - // Z3 = (Y1+Z1)²-gamma-delta - Add(&out->z, a.y, a.z); - Reduce(&out->z); - Square(&out->z, out->z); - Subtract(&out->z, out->z, gamma); - Reduce(&out->z); - Subtract(&out->z, out->z, delta); - Reduce(&out->z); - - // X3 = alpha²-8*beta - for (int i = 0; i < 8; i++) { - delta[i] = beta[i] << 3; - } - Reduce(&delta); - Square(&out->x, alpha); - Subtract(&out->x, out->x, delta); - Reduce(&out->x); - - // Y3 = alpha*(4*beta-X3)-8*gamma² - for (int i = 0; i < 8; i++) { - beta[i] <<= 2; - } - Reduce(&beta); - Subtract(&beta, beta, out->x); - Reduce(&beta); - Square(&gamma, gamma); - for (int i = 0; i < 8; i++) { - gamma[i] <<= 3; - } - Reduce(&gamma); - Mul(&out->y, alpha, beta); - Subtract(&out->y, out->y, gamma); - Reduce(&out->y); -} - -// CopyConditional sets *out=a if mask is 0xffffffff. mask must be either 0 of -// 0xffffffff. -void CopyConditional(Point* out, - const Point& a, - uint32 mask) { - for (int i = 0; i < 8; i++) { - out->x[i] ^= mask & (a.x[i] ^ out->x[i]); - out->y[i] ^= mask & (a.y[i] ^ out->y[i]); - out->z[i] ^= mask & (a.z[i] ^ out->z[i]); - } -} - -// ScalarMult calculates *out = a*scalar where scalar is a big-endian number of -// length scalar_len and != 0. -void ScalarMult(Point* out, const Point& a, - const uint8* scalar, size_t scalar_len) { - memset(out, 0, sizeof(*out)); - Point tmp; - - for (size_t i = 0; i < scalar_len; i++) { - for (unsigned int bit_num = 0; bit_num < 8; bit_num++) { - DoubleJacobian(out, *out); - uint32 bit = static_cast(static_cast( - (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31)); - AddJacobian(&tmp, a, *out); - CopyConditional(out, tmp, bit); - } - } -} - -// Get224Bits reads 7 words from in and scatters their contents in -// little-endian form into 8 words at out, 28 bits per output word. -void Get224Bits(uint32* out, const uint32* in) { - out[0] = NetToHost32(in[6]) & kBottom28Bits; - out[1] = ((NetToHost32(in[5]) << 4) | - (NetToHost32(in[6]) >> 28)) & kBottom28Bits; - out[2] = ((NetToHost32(in[4]) << 8) | - (NetToHost32(in[5]) >> 24)) & kBottom28Bits; - out[3] = ((NetToHost32(in[3]) << 12) | - (NetToHost32(in[4]) >> 20)) & kBottom28Bits; - out[4] = ((NetToHost32(in[2]) << 16) | - (NetToHost32(in[3]) >> 16)) & kBottom28Bits; - out[5] = ((NetToHost32(in[1]) << 20) | - (NetToHost32(in[2]) >> 12)) & kBottom28Bits; - out[6] = ((NetToHost32(in[0]) << 24) | - (NetToHost32(in[1]) >> 8)) & kBottom28Bits; - out[7] = (NetToHost32(in[0]) >> 4) & kBottom28Bits; -} - -// Put224Bits performs the inverse operation to Get224Bits: taking 28 bits from -// each of 8 input words and writing them in big-endian order to 7 words at -// out. -void Put224Bits(uint32* out, const uint32* in) { - out[6] = HostToNet32((in[0] >> 0) | (in[1] << 28)); - out[5] = HostToNet32((in[1] >> 4) | (in[2] << 24)); - out[4] = HostToNet32((in[2] >> 8) | (in[3] << 20)); - out[3] = HostToNet32((in[3] >> 12) | (in[4] << 16)); - out[2] = HostToNet32((in[4] >> 16) | (in[5] << 12)); - out[1] = HostToNet32((in[5] >> 20) | (in[6] << 8)); - out[0] = HostToNet32((in[6] >> 24) | (in[7] << 4)); -} - -} // anonymous namespace - -namespace crypto { - -namespace p224 { - -bool Point::SetFromString(const base::StringPiece& in) { - if (in.size() != 2*28) - return false; - const uint32* inwords = reinterpret_cast(in.data()); - Get224Bits(x, inwords); - Get224Bits(y, inwords + 7); - memset(&z, 0, sizeof(z)); - z[0] = 1; - - // Check that the point is on the curve, i.e. that y² = x³ - 3x + b. - FieldElement lhs; - Square(&lhs, y); - Contract(&lhs); - - FieldElement rhs; - Square(&rhs, x); - Mul(&rhs, x, rhs); - - FieldElement three_x; - for (int i = 0; i < 8; i++) { - three_x[i] = x[i] * 3; - } - Reduce(&three_x); - Subtract(&rhs, rhs, three_x); - Reduce(&rhs); - - ::Add(&rhs, rhs, kB); - Contract(&rhs); - return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; -} - -std::string Point::ToString() const { - FieldElement zinv, zinv_sq, xx, yy; - - // If this is the point at infinity we return a string of all zeros. - if (IsZero(this->z)) { - static const char zeros[56] = {0}; - return std::string(zeros, sizeof(zeros)); - } - - Invert(&zinv, this->z); - Square(&zinv_sq, zinv); - Mul(&xx, x, zinv_sq); - Mul(&zinv_sq, zinv_sq, zinv); - Mul(&yy, y, zinv_sq); - - Contract(&xx); - Contract(&yy); - - uint32 outwords[14]; - Put224Bits(outwords, xx); - Put224Bits(outwords + 7, yy); - return std::string(reinterpret_cast(outwords), sizeof(outwords)); -} - -void ScalarMult(const Point& in, const uint8* scalar, Point* out) { - ::ScalarMult(out, in, scalar, 28); -} - -// kBasePoint is the base point (generator) of the elliptic curve group. -static const Point kBasePoint = { - {22813985, 52956513, 34677300, 203240812, - 12143107, 133374265, 225162431, 191946955}, - {83918388, 223877528, 122119236, 123340192, - 266784067, 263504429, 146143011, 198407736}, - {1, 0, 0, 0, 0, 0, 0, 0}, -}; - -void ScalarBaseMult(const uint8* scalar, Point* out) { - ::ScalarMult(out, kBasePoint, scalar, 28); -} - -void Add(const Point& a, const Point& b, Point* out) { - AddJacobian(out, a, b); -} - -void Negate(const Point& in, Point* out) { - // Guide to elliptic curve cryptography, page 89 suggests that (X : X+Y : Z) - // is the negative in Jacobian coordinates, but it doesn't actually appear to - // be true in testing so this performs the negation in affine coordinates. - FieldElement zinv, zinv_sq, y; - Invert(&zinv, in.z); - Square(&zinv_sq, zinv); - Mul(&out->x, in.x, zinv_sq); - Mul(&zinv_sq, zinv_sq, zinv); - Mul(&y, in.y, zinv_sq); - - Subtract(&out->y, kP, y); - Reduce(&out->y); - - memset(&out->z, 0, sizeof(out->z)); - out->z[0] = 1; -} - -} // namespace p224 - -} // namespace crypto diff --git a/crypto/p224.h b/crypto/p224.h deleted file mode 100644 index 2efecfab559a0..0000000000000 --- a/crypto/p224.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 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_P224_H_ -#define CRYPTO_P224_H_ - -#include - -#include "base/basictypes.h" -#include "base/strings/string_piece.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// P224 implements an elliptic curve group, commonly known as P224 and defined -// in FIPS 186-3, section D.2.2. -namespace p224 { - -// An element of the field (ℤ/pℤ) is represented with 8, 28-bit limbs in -// little endian order. -typedef uint32 FieldElement[8]; - -struct CRYPTO_EXPORT Point { - // SetFromString the value of the point from the 56 byte, external - // representation. The external point representation is an (x, y) pair of a - // point on the curve. Each field element is represented as a big-endian - // number < p. - bool SetFromString(const base::StringPiece& in); - - // ToString returns an external representation of the Point. - std::string ToString() const; - - // An Point is represented in Jacobian form (x/z², y/z³). - FieldElement x, y, z; -}; - -// kScalarBytes is the number of bytes needed to represent an element of the -// P224 field. -static const size_t kScalarBytes = 28; - -// ScalarMult computes *out = in*scalar where scalar is a 28-byte, big-endian -// number. -void CRYPTO_EXPORT ScalarMult(const Point& in, const uint8* scalar, Point* out); - -// ScalarBaseMult computes *out = g*scalar where g is the base point of the -// curve and scalar is a 28-byte, big-endian number. -void CRYPTO_EXPORT ScalarBaseMult(const uint8* scalar, Point* out); - -// Add computes *out = a+b. -void CRYPTO_EXPORT Add(const Point& a, const Point& b, Point* out); - -// Negate calculates out = -a; -void CRYPTO_EXPORT Negate(const Point& a, Point* out); - -} // namespace p224 - -} // namespace crypto - -#endif // CRYPTO_P224_H_ diff --git a/crypto/p224_spake.cc b/crypto/p224_spake.cc deleted file mode 100644 index a6dec40568a6d..0000000000000 --- a/crypto/p224_spake.cc +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2012 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. - -// This code implements SPAKE2, a variant of EKE: -// http://www.di.ens.fr/~pointche/pub.php?reference=AbPo04 - -#include - -#include - -#include -#include -#include -#include - -namespace { - -// The following two points (M and N in the protocol) are verifiable random -// points on the curve and can be generated with the following code: - -// #include -// #include -// #include -// -// #include -// #include -// #include -// -// static const char kSeed1[] = "P224 point generation seed (M)"; -// static const char kSeed2[] = "P224 point generation seed (N)"; -// -// void find_seed(const char* seed) { -// SHA256_CTX sha256; -// uint8_t digest[SHA256_DIGEST_LENGTH]; -// -// SHA256_Init(&sha256); -// SHA256_Update(&sha256, seed, strlen(seed)); -// SHA256_Final(digest, &sha256); -// -// BIGNUM x, y; -// EC_GROUP* p224 = EC_GROUP_new_by_curve_name(NID_secp224r1); -// EC_POINT* p = EC_POINT_new(p224); -// -// for (unsigned i = 0;; i++) { -// BN_init(&x); -// BN_bin2bn(digest, 28, &x); -// -// if (EC_POINT_set_compressed_coordinates_GFp( -// p224, p, &x, digest[28] & 1, NULL)) { -// BN_init(&y); -// EC_POINT_get_affine_coordinates_GFp(p224, p, &x, &y, NULL); -// char* x_str = BN_bn2hex(&x); -// char* y_str = BN_bn2hex(&y); -// printf("Found after %u iterations:\n%s\n%s\n", i, x_str, y_str); -// OPENSSL_free(x_str); -// OPENSSL_free(y_str); -// BN_free(&x); -// BN_free(&y); -// break; -// } -// -// SHA256_Init(&sha256); -// SHA256_Update(&sha256, digest, sizeof(digest)); -// SHA256_Final(digest, &sha256); -// -// BN_free(&x); -// } -// -// EC_POINT_free(p); -// EC_GROUP_free(p224); -// } -// -// int main() { -// find_seed(kSeed1); -// find_seed(kSeed2); -// return 0; -// } - -const crypto::p224::Point kM = { - {174237515, 77186811, 235213682, 33849492, - 33188520, 48266885, 177021753, 81038478}, - {104523827, 245682244, 266509668, 236196369, - 28372046, 145351378, 198520366, 113345994}, - {1, 0, 0, 0, 0, 0, 0, 0}, -}; - -const crypto::p224::Point kN = { - {136176322, 263523628, 251628795, 229292285, - 5034302, 185981975, 171998428, 11653062}, - {197567436, 51226044, 60372156, 175772188, - 42075930, 8083165, 160827401, 65097570}, - {1, 0, 0, 0, 0, 0, 0, 0}, -}; - -} // anonymous namespace - -namespace crypto { - -P224EncryptedKeyExchange::P224EncryptedKeyExchange( - PeerType peer_type, const base::StringPiece& password) - : state_(kStateInitial), - is_server_(peer_type == kPeerTypeServer) { - memset(&x_, 0, sizeof(x_)); - memset(&expected_authenticator_, 0, sizeof(expected_authenticator_)); - - // x_ is a random scalar. - RandBytes(x_, sizeof(x_)); - - // Calculate |password| hash to get SPAKE password value. - SHA256HashString(std::string(password.data(), password.length()), - pw_, sizeof(pw_)); - - Init(); -} - -void P224EncryptedKeyExchange::Init() { - // X = g**x_ - p224::Point X; - p224::ScalarBaseMult(x_, &X); - - // The client masks the Diffie-Hellman value, X, by adding M**pw and the - // server uses N**pw. - p224::Point MNpw; - p224::ScalarMult(is_server_ ? kN : kM, pw_, &MNpw); - - // X* = X + (N|M)**pw - p224::Point Xstar; - p224::Add(X, MNpw, &Xstar); - - next_message_ = Xstar.ToString(); -} - -const std::string& P224EncryptedKeyExchange::GetNextMessage() { - if (state_ == kStateInitial) { - state_ = kStateRecvDH; - return next_message_; - } else if (state_ == kStateSendHash) { - state_ = kStateRecvHash; - return next_message_; - } - - LOG(FATAL) << "P224EncryptedKeyExchange::GetNextMessage called in" - " bad state " << state_; - next_message_ = ""; - return next_message_; -} - -P224EncryptedKeyExchange::Result P224EncryptedKeyExchange::ProcessMessage( - const base::StringPiece& message) { - if (state_ == kStateRecvHash) { - // This is the final state of the protocol: we are reading the peer's - // authentication hash and checking that it matches the one that we expect. - if (message.size() != sizeof(expected_authenticator_)) { - error_ = "peer's hash had an incorrect size"; - return kResultFailed; - } - if (!SecureMemEqual(message.data(), expected_authenticator_, - message.size())) { - error_ = "peer's hash had incorrect value"; - return kResultFailed; - } - state_ = kStateDone; - return kResultSuccess; - } - - if (state_ != kStateRecvDH) { - LOG(FATAL) << "P224EncryptedKeyExchange::ProcessMessage called in" - " bad state " << state_; - error_ = "internal error"; - return kResultFailed; - } - - // Y* is the other party's masked, Diffie-Hellman value. - p224::Point Ystar; - if (!Ystar.SetFromString(message)) { - error_ = "failed to parse peer's masked Diffie-Hellman value"; - return kResultFailed; - } - - // We calculate the mask value: (N|M)**pw - p224::Point MNpw, minus_MNpw, Y, k; - p224::ScalarMult(is_server_ ? kM : kN, pw_, &MNpw); - p224::Negate(MNpw, &minus_MNpw); - - // Y = Y* - (N|M)**pw - p224::Add(Ystar, minus_MNpw, &Y); - - // K = Y**x_ - p224::ScalarMult(Y, x_, &k); - - // If everything worked out, then K is the same for both parties. - key_ = k.ToString(); - - std::string client_masked_dh, server_masked_dh; - if (is_server_) { - client_masked_dh = message.as_string(); - server_masked_dh = next_message_; - } else { - client_masked_dh = next_message_; - server_masked_dh = message.as_string(); - } - - // Now we calculate the hashes that each side will use to prove to the other - // that they derived the correct value for K. - uint8 client_hash[kSHA256Length], server_hash[kSHA256Length]; - CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, key_, - client_hash); - CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, key_, - server_hash); - - const uint8* my_hash = is_server_ ? server_hash : client_hash; - const uint8* their_hash = is_server_ ? client_hash : server_hash; - - next_message_ = - std::string(reinterpret_cast(my_hash), kSHA256Length); - memcpy(expected_authenticator_, their_hash, kSHA256Length); - state_ = kStateSendHash; - return kResultPending; -} - -void P224EncryptedKeyExchange::CalculateHash( - PeerType peer_type, - const std::string& client_masked_dh, - const std::string& server_masked_dh, - const std::string& k, - uint8* out_digest) { - std::string hash_contents; - - if (peer_type == kPeerTypeServer) { - hash_contents = "server"; - } else { - hash_contents = "client"; - } - - hash_contents += client_masked_dh; - hash_contents += server_masked_dh; - hash_contents += - std::string(reinterpret_cast(pw_), sizeof(pw_)); - hash_contents += k; - - SHA256HashString(hash_contents, out_digest, kSHA256Length); -} - -const std::string& P224EncryptedKeyExchange::error() const { - return error_; -} - -const std::string& P224EncryptedKeyExchange::GetKey() const { - DCHECK_EQ(state_, kStateDone); - return GetUnverifiedKey(); -} - -const std::string& P224EncryptedKeyExchange::GetUnverifiedKey() const { - // Key is already final when state is kStateSendHash. Subsequent states are - // used only for verification of the key. Some users may combine verification - // with sending verifiable data instead of |expected_authenticator_|. - DCHECK_GE(state_, kStateSendHash); - return key_; -} - -void P224EncryptedKeyExchange::SetXForTesting(const std::string& x) { - memset(&x_, 0, sizeof(x_)); - memcpy(&x_, x.data(), std::min(x.size(), sizeof(x_))); - Init(); -} - -} // namespace crypto diff --git a/crypto/p224_spake.h b/crypto/p224_spake.h deleted file mode 100644 index 556b15cd09f7d..0000000000000 --- a/crypto/p224_spake.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2012 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_P224_SPAKE_H_ -#define CRYPTO_P224_SPAKE_H_ - -#include -#include -#include -#include - -namespace crypto { - -// P224EncryptedKeyExchange implements SPAKE2, a variant of Encrypted -// Key Exchange. It allows two parties that have a secret common -// password to establish a common secure key by exchanging messages -// over an insecure channel without disclosing the password. -// -// The password can be low entropy as authenticating with an attacker only -// gives the attacker a one-shot password oracle. No other information about -// the password is leaked. (However, you must be sure to limit the number of -// permitted authentication attempts otherwise they get many one-shot oracles.) -// -// The protocol requires several RTTs (actually two, but you shouldn't assume -// that.) To use the object, call GetNextMessage() and pass that message to the -// peer. Get a message from the peer and feed it into ProcessMessage. Then -// examine the return value of ProcessMessage: -// kResultPending: Another round is required. Call GetNextMessage and repeat. -// kResultFailed: The authentication has failed. You can get a human readable -// error message by calling error(). -// kResultSuccess: The authentication was successful. -// -// In each exchange, each peer always sends a message. -class CRYPTO_EXPORT P224EncryptedKeyExchange { - public: - enum Result { - kResultPending, - kResultFailed, - kResultSuccess, - }; - - // PeerType's values are named client and server due to convention. But - // they could be called "A" and "B" as far as the protocol is concerned so - // long as the two parties don't both get the same label. - enum PeerType { - kPeerTypeClient, - kPeerTypeServer, - }; - - // peer_type: the type of the local authentication party. - // password: secret session password. Both parties to the - // authentication must pass the same value. For the case of a - // TLS connection, see RFC 5705. - P224EncryptedKeyExchange(PeerType peer_type, - const base::StringPiece& password); - - // GetNextMessage returns a byte string which must be passed to the other - // party in the authentication. - const std::string& GetNextMessage(); - - // ProcessMessage processes a message which must have been generated by a - // call to GetNextMessage() by the other party. - Result ProcessMessage(const base::StringPiece& message); - - // In the event that ProcessMessage() returns kResultFailed, error will - // return a human readable error message. - const std::string& error() const; - - // The key established as result of the key exchange. Must be called - // at then end after ProcessMessage() returns kResultSuccess. - const std::string& GetKey() const; - - // The key established as result of the key exchange. Can be called after - // the first ProcessMessage() - const std::string& GetUnverifiedKey() const; - - private: - // The authentication state machine is very simple and each party proceeds - // through each of these states, in order. - enum State { - kStateInitial, - kStateRecvDH, - kStateSendHash, - kStateRecvHash, - kStateDone, - }; - - FRIEND_TEST_ALL_PREFIXES(MutualAuth, ExpectedValues); - - void Init(); - - // Sets internal random scalar. Should be used by tests only. - void SetXForTesting(const std::string& x); - - State state_; - const bool is_server_; - // next_message_ contains a value for GetNextMessage() to return. - std::string next_message_; - std::string error_; - - // CalculateHash computes the verification hash for the given peer and writes - // |kSHA256Length| bytes at |out_digest|. - void CalculateHash( - PeerType peer_type, - const std::string& client_masked_dh, - const std::string& server_masked_dh, - const std::string& k, - uint8* out_digest); - - // x_ is the secret Diffie-Hellman exponent (see paper referenced in .cc - // file). - uint8 x_[p224::kScalarBytes]; - // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32, - // big-endian length prefix (see paper referenced in .cc file). - uint8 pw_[p224::kScalarBytes]; - // expected_authenticator_ is used to store the hash value expected from the - // other party. - uint8 expected_authenticator_[kSHA256Length]; - - std::string key_; -}; - -} // namespace crypto - -#endif // CRYPTO_P224_SPAKE_H_ diff --git a/crypto/p224_spake_unittest.cc b/crypto/p224_spake_unittest.cc deleted file mode 100644 index 15b5be268413d..0000000000000 --- a/crypto/p224_spake_unittest.cc +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2011 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/p224_spake.h" - -#include - -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -namespace { - -std::string HexEncodeString(const std::string& binary_data) { - return base::HexEncode(binary_data.c_str(), binary_data.size()); -} - -bool RunExchange(P224EncryptedKeyExchange* client, - P224EncryptedKeyExchange* server, - bool is_password_same) { - for (;;) { - std::string client_message, server_message; - client_message = client->GetNextMessage(); - server_message = server->GetNextMessage(); - - P224EncryptedKeyExchange::Result client_result, server_result; - client_result = client->ProcessMessage(server_message); - server_result = server->ProcessMessage(client_message); - - // Check that we never hit the case where only one succeeds. - EXPECT_EQ(client_result == P224EncryptedKeyExchange::kResultSuccess, - server_result == P224EncryptedKeyExchange::kResultSuccess); - - if (client_result == P224EncryptedKeyExchange::kResultFailed || - server_result == P224EncryptedKeyExchange::kResultFailed) { - return false; - } - - EXPECT_EQ(is_password_same, - client->GetUnverifiedKey() == server->GetUnverifiedKey()); - - if (client_result == P224EncryptedKeyExchange::kResultSuccess && - server_result == P224EncryptedKeyExchange::kResultSuccess) { - return true; - } - - EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, client_result); - EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, server_result); - } -} - -const char kPassword[] = "foo"; - -} // namespace - -TEST(MutualAuth, CorrectAuth) { - P224EncryptedKeyExchange client( - P224EncryptedKeyExchange::kPeerTypeClient, kPassword); - P224EncryptedKeyExchange server( - P224EncryptedKeyExchange::kPeerTypeServer, kPassword); - - EXPECT_TRUE(RunExchange(&client, &server, true)); - EXPECT_EQ(client.GetKey(), server.GetKey()); -} - -TEST(MutualAuth, IncorrectPassword) { - P224EncryptedKeyExchange client( - P224EncryptedKeyExchange::kPeerTypeClient, - kPassword); - P224EncryptedKeyExchange server( - P224EncryptedKeyExchange::kPeerTypeServer, - "wrongpassword"); - - EXPECT_FALSE(RunExchange(&client, &server, false)); -} - -TEST(MutualAuth, ExpectedValues) { - P224EncryptedKeyExchange client(P224EncryptedKeyExchange::kPeerTypeClient, - kPassword); - client.SetXForTesting("Client x"); - P224EncryptedKeyExchange server(P224EncryptedKeyExchange::kPeerTypeServer, - kPassword); - server.SetXForTesting("Server x"); - - std::string client_message = client.GetNextMessage(); - EXPECT_EQ( - "3508EF7DECC8AB9F9C439FBB0154288BBECC0A82E8448F4CF29554EB" - "BE9D486686226255EAD1D077C635B1A41F46AC91D7F7F32CED9EC3E0", - HexEncodeString(client_message)); - - std::string server_message = server.GetNextMessage(); - EXPECT_EQ( - "A3088C18B75D2C2B107105661AEC85424777475EB29F1DDFB8C14AFB" - "F1603D0DF38413A00F420ACF2059E7997C935F5A957A193D09A2B584", - HexEncodeString(server_message)); - - EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, - client.ProcessMessage(server_message)); - EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, - server.ProcessMessage(client_message)); - - EXPECT_EQ(client.GetUnverifiedKey(), server.GetUnverifiedKey()); - // Must stay the same. External implementations should be able to pair with. - EXPECT_EQ( - "CE7CCFC435CDA4F01EC8826788B1F8B82EF7D550A34696B371096E64" - "C487D4FE193F7D1A6FF6820BC7F807796BA3889E8F999BBDEFC32FFA", - HexEncodeString(server.GetUnverifiedKey())); - - EXPECT_TRUE(RunExchange(&client, &server, true)); - EXPECT_EQ(client.GetKey(), server.GetKey()); -} - -TEST(MutualAuth, Fuzz) { - static const unsigned kIterations = 40; - - for (unsigned i = 0; i < kIterations; i++) { - P224EncryptedKeyExchange client( - P224EncryptedKeyExchange::kPeerTypeClient, kPassword); - P224EncryptedKeyExchange server( - P224EncryptedKeyExchange::kPeerTypeServer, kPassword); - - // We'll only be testing small values of i, but we don't want that to bias - // the test coverage. So we disperse the value of i by multiplying by the - // FNV, 32-bit prime, producing a poor-man's PRNG. - const uint32 rand = i * 16777619; - - for (unsigned round = 0;; round++) { - std::string client_message, server_message; - client_message = client.GetNextMessage(); - server_message = server.GetNextMessage(); - - if ((rand & 1) == round) { - const bool server_or_client = rand & 2; - std::string* m = server_or_client ? &server_message : &client_message; - if (rand & 4) { - // Truncate - *m = m->substr(0, (i >> 3) % m->size()); - } else { - // Corrupt - const size_t bits = m->size() * 8; - const size_t bit_to_corrupt = (rand >> 3) % bits; - const_cast(m->data())[bit_to_corrupt / 8] ^= - 1 << (bit_to_corrupt % 8); - } - } - - P224EncryptedKeyExchange::Result client_result, server_result; - client_result = client.ProcessMessage(server_message); - server_result = server.ProcessMessage(client_message); - - // If we have corrupted anything, we expect the authentication to fail, - // although one side can succeed if we happen to corrupt the second round - // message to the other. - ASSERT_FALSE( - client_result == P224EncryptedKeyExchange::kResultSuccess && - server_result == P224EncryptedKeyExchange::kResultSuccess); - - if (client_result == P224EncryptedKeyExchange::kResultFailed || - server_result == P224EncryptedKeyExchange::kResultFailed) { - break; - } - - ASSERT_EQ(P224EncryptedKeyExchange::kResultPending, - client_result); - ASSERT_EQ(P224EncryptedKeyExchange::kResultPending, - server_result); - } - } -} - -} // namespace crypto diff --git a/crypto/p224_unittest.cc b/crypto/p224_unittest.cc deleted file mode 100644 index aaf5f59f47e77..0000000000000 --- a/crypto/p224_unittest.cc +++ /dev/null @@ -1,824 +0,0 @@ -// Copyright (c) 2012 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 -#include - -#include "crypto/p224.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -using p224::Point; - -// kBasePointExternal is the P224 base point in external representation. -static const uint8 kBasePointExternal[56] = { - 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, - 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, - 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, - 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, - 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, - 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, - 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34, -}; - -// TestVector represents a test of scalar multiplication of the base point. -// |scalar| is a big-endian scalar and |affine| is the external representation -// of g*scalar. -struct TestVector { - uint8 scalar[28]; - uint8 affine[28*2]; -}; - -static const int kNumNISTTestVectors = 52; - -// kNISTTestVectors are the NIST test vectors for P224. -static const TestVector kNISTTestVectors[kNumNISTTestVectors] = { - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01}, - {0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, - 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, - 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, - 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, - 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, - 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, - 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34 - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, }, - - {0x70, 0x6a, 0x46, 0xdc, 0x76, 0xdc, 0xb7, 0x67, - 0x98, 0xe6, 0x0e, 0x6d, 0x89, 0x47, 0x47, 0x88, - 0xd1, 0x6d, 0xc1, 0x80, 0x32, 0xd2, 0x68, 0xfd, - 0x1a, 0x70, 0x4f, 0xa6, 0x1c, 0x2b, 0x76, 0xa7, - 0xbc, 0x25, 0xe7, 0x70, 0x2a, 0x70, 0x4f, 0xa9, - 0x86, 0x89, 0x28, 0x49, 0xfc, 0xa6, 0x29, 0x48, - 0x7a, 0xcf, 0x37, 0x09, 0xd2, 0xe4, 0xe8, 0xbb, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, }, - {0xdf, 0x1b, 0x1d, 0x66, 0xa5, 0x51, 0xd0, 0xd3, - 0x1e, 0xff, 0x82, 0x25, 0x58, 0xb9, 0xd2, 0xcc, - 0x75, 0xc2, 0x18, 0x02, 0x79, 0xfe, 0x0d, 0x08, - 0xfd, 0x89, 0x6d, 0x04, 0xa3, 0xf7, 0xf0, 0x3c, - 0xad, 0xd0, 0xbe, 0x44, 0x4c, 0x0a, 0xa5, 0x68, - 0x30, 0x13, 0x0d, 0xdf, 0x77, 0xd3, 0x17, 0x34, - 0x4e, 0x1a, 0xf3, 0x59, 0x19, 0x81, 0xa9, 0x25, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, }, - {0xae, 0x99, 0xfe, 0xeb, 0xb5, 0xd2, 0x69, 0x45, - 0xb5, 0x48, 0x92, 0x09, 0x2a, 0x8a, 0xee, 0x02, - 0x91, 0x29, 0x30, 0xfa, 0x41, 0xcd, 0x11, 0x4e, - 0x40, 0x44, 0x73, 0x01, 0x04, 0x82, 0x58, 0x0a, - 0x0e, 0xc5, 0xbc, 0x47, 0xe8, 0x8b, 0xc8, 0xc3, - 0x78, 0x63, 0x2c, 0xd1, 0x96, 0xcb, 0x3f, 0xa0, - 0x58, 0xa7, 0x11, 0x4e, 0xb0, 0x30, 0x54, 0xc9, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, }, - {0x31, 0xc4, 0x9a, 0xe7, 0x5b, 0xce, 0x78, 0x07, - 0xcd, 0xff, 0x22, 0x05, 0x5d, 0x94, 0xee, 0x90, - 0x21, 0xfe, 0xdb, 0xb5, 0xab, 0x51, 0xc5, 0x75, - 0x26, 0xf0, 0x11, 0xaa, 0x27, 0xe8, 0xbf, 0xf1, - 0x74, 0x56, 0x35, 0xec, 0x5b, 0xa0, 0xc9, 0xf1, - 0xc2, 0xed, 0xe1, 0x54, 0x14, 0xc6, 0x50, 0x7d, - 0x29, 0xff, 0xe3, 0x7e, 0x79, 0x0a, 0x07, 0x9b, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, }, - {0x1f, 0x24, 0x83, 0xf8, 0x25, 0x72, 0x25, 0x1f, - 0xca, 0x97, 0x5f, 0xea, 0x40, 0xdb, 0x82, 0x1d, - 0xf8, 0xad, 0x82, 0xa3, 0xc0, 0x02, 0xee, 0x6c, - 0x57, 0x11, 0x24, 0x08, 0x89, 0xfa, 0xf0, 0xcc, - 0xb7, 0x50, 0xd9, 0x9b, 0x55, 0x3c, 0x57, 0x4f, - 0xad, 0x7e, 0xcf, 0xb0, 0x43, 0x85, 0x86, 0xeb, - 0x39, 0x52, 0xaf, 0x5b, 0x4b, 0x15, 0x3c, 0x7e, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, }, - {0xdb, 0x2f, 0x6b, 0xe6, 0x30, 0xe2, 0x46, 0xa5, - 0xcf, 0x7d, 0x99, 0xb8, 0x51, 0x94, 0xb1, 0x23, - 0xd4, 0x87, 0xe2, 0xd4, 0x66, 0xb9, 0x4b, 0x24, - 0xa0, 0x3c, 0x3e, 0x28, 0x0f, 0x3a, 0x30, 0x08, - 0x54, 0x97, 0xf2, 0xf6, 0x11, 0xee, 0x25, 0x17, - 0xb1, 0x63, 0xef, 0x8c, 0x53, 0xb7, 0x15, 0xd1, - 0x8b, 0xb4, 0xe4, 0x80, 0x8d, 0x02, 0xb9, 0x63, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, }, - {0x85, 0x8e, 0x6f, 0x9c, 0xc6, 0xc1, 0x2c, 0x31, - 0xf5, 0xdf, 0x12, 0x4a, 0xa7, 0x77, 0x67, 0xb0, - 0x5c, 0x8b, 0xc0, 0x21, 0xbd, 0x68, 0x3d, 0x2b, - 0x55, 0x57, 0x15, 0x50, 0x04, 0x6d, 0xcd, 0x3e, - 0xa5, 0xc4, 0x38, 0x98, 0xc5, 0xc5, 0xfc, 0x4f, - 0xda, 0xc7, 0xdb, 0x39, 0xc2, 0xf0, 0x2e, 0xbe, - 0xe4, 0xe3, 0x54, 0x1d, 0x1e, 0x78, 0x04, 0x7a, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x09, }, - {0x2f, 0xdc, 0xcc, 0xfe, 0xe7, 0x20, 0xa7, 0x7e, - 0xf6, 0xcb, 0x3b, 0xfb, 0xb4, 0x47, 0xf9, 0x38, - 0x31, 0x17, 0xe3, 0xda, 0xa4, 0xa0, 0x7e, 0x36, - 0xed, 0x15, 0xf7, 0x8d, 0x37, 0x17, 0x32, 0xe4, - 0xf4, 0x1b, 0xf4, 0xf7, 0x88, 0x30, 0x35, 0xe6, - 0xa7, 0x9f, 0xce, 0xdc, 0x0e, 0x19, 0x6e, 0xb0, - 0x7b, 0x48, 0x17, 0x16, 0x97, 0x51, 0x74, 0x63, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, }, - {0xae, 0xa9, 0xe1, 0x7a, 0x30, 0x65, 0x17, 0xeb, - 0x89, 0x15, 0x2a, 0xa7, 0x09, 0x6d, 0x2c, 0x38, - 0x1e, 0xc8, 0x13, 0xc5, 0x1a, 0xa8, 0x80, 0xe7, - 0xbe, 0xe2, 0xc0, 0xfd, 0x39, 0xbb, 0x30, 0xea, - 0xb3, 0x37, 0xe0, 0xa5, 0x21, 0xb6, 0xcb, 0xa1, - 0xab, 0xe4, 0xb2, 0xb3, 0xa3, 0xe5, 0x24, 0xc1, - 0x4a, 0x3f, 0xe3, 0xeb, 0x11, 0x6b, 0x65, 0x5f, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, }, - {0xef, 0x53, 0xb6, 0x29, 0x4a, 0xca, 0x43, 0x1f, - 0x0f, 0x3c, 0x22, 0xdc, 0x82, 0xeb, 0x90, 0x50, - 0x32, 0x4f, 0x1d, 0x88, 0xd3, 0x77, 0xe7, 0x16, - 0x44, 0x8e, 0x50, 0x7c, 0x20, 0xb5, 0x10, 0x00, - 0x40, 0x92, 0xe9, 0x66, 0x36, 0xcf, 0xb7, 0xe3, - 0x2e, 0xfd, 0xed, 0x82, 0x65, 0xc2, 0x66, 0xdf, - 0xb7, 0x54, 0xfa, 0x6d, 0x64, 0x91, 0xa6, 0xda, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, }, - {0x6e, 0x31, 0xee, 0x1d, 0xc1, 0x37, 0xf8, 0x1b, - 0x05, 0x67, 0x52, 0xe4, 0xde, 0xab, 0x14, 0x43, - 0xa4, 0x81, 0x03, 0x3e, 0x9b, 0x4c, 0x93, 0xa3, - 0x04, 0x4f, 0x4f, 0x7a, 0x20, 0x7d, 0xdd, 0xf0, - 0x38, 0x5b, 0xfd, 0xea, 0xb6, 0xe9, 0xac, 0xda, - 0x8d, 0xa0, 0x6b, 0x3b, 0xbe, 0xf2, 0x24, 0xa9, - 0x3a, 0xb1, 0xe9, 0xe0, 0x36, 0x10, 0x9d, 0x13, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, }, - {0x34, 0xe8, 0xe1, 0x7a, 0x43, 0x0e, 0x43, 0x28, - 0x97, 0x93, 0xc3, 0x83, 0xfa, 0xc9, 0x77, 0x42, - 0x47, 0xb4, 0x0e, 0x9e, 0xbd, 0x33, 0x66, 0x98, - 0x1f, 0xcf, 0xae, 0xca, 0x25, 0x28, 0x19, 0xf7, - 0x1c, 0x7f, 0xb7, 0xfb, 0xcb, 0x15, 0x9b, 0xe3, - 0x37, 0xd3, 0x7d, 0x33, 0x36, 0xd7, 0xfe, 0xb9, - 0x63, 0x72, 0x4f, 0xdf, 0xb0, 0xec, 0xb7, 0x67, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0e, }, - {0xa5, 0x36, 0x40, 0xc8, 0x3d, 0xc2, 0x08, 0x60, - 0x3d, 0xed, 0x83, 0xe4, 0xec, 0xf7, 0x58, 0xf2, - 0x4c, 0x35, 0x7d, 0x7c, 0xf4, 0x80, 0x88, 0xb2, - 0xce, 0x01, 0xe9, 0xfa, 0xd5, 0x81, 0x4c, 0xd7, - 0x24, 0x19, 0x9c, 0x4a, 0x5b, 0x97, 0x4a, 0x43, - 0x68, 0x5f, 0xbf, 0x5b, 0x8b, 0xac, 0x69, 0x45, - 0x9c, 0x94, 0x69, 0xbc, 0x8f, 0x23, 0xcc, 0xaf, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0f, }, - {0xba, 0xa4, 0xd8, 0x63, 0x55, 0x11, 0xa7, 0xd2, - 0x88, 0xae, 0xbe, 0xed, 0xd1, 0x2c, 0xe5, 0x29, - 0xff, 0x10, 0x2c, 0x91, 0xf9, 0x7f, 0x86, 0x7e, - 0x21, 0x91, 0x6b, 0xf9, 0x97, 0x9a, 0x5f, 0x47, - 0x59, 0xf8, 0x0f, 0x4f, 0xb4, 0xec, 0x2e, 0x34, - 0xf5, 0x56, 0x6d, 0x59, 0x56, 0x80, 0xa1, 0x17, - 0x35, 0xe7, 0xb6, 0x10, 0x46, 0x12, 0x79, 0x89, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, }, - {0x0b, 0x6e, 0xc4, 0xfe, 0x17, 0x77, 0x38, 0x24, - 0x04, 0xef, 0x67, 0x99, 0x97, 0xba, 0x8d, 0x1c, - 0xc5, 0xcd, 0x8e, 0x85, 0x34, 0x92, 0x59, 0xf5, - 0x90, 0xc4, 0xc6, 0x6d, 0x33, 0x99, 0xd4, 0x64, - 0x34, 0x59, 0x06, 0xb1, 0x1b, 0x00, 0xe3, 0x63, - 0xef, 0x42, 0x92, 0x21, 0xf2, 0xec, 0x72, 0x0d, - 0x2f, 0x66, 0x5d, 0x7d, 0xea, 0xd5, 0xb4, 0x82, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x11, }, - {0xb8, 0x35, 0x7c, 0x3a, 0x6c, 0xee, 0xf2, 0x88, - 0x31, 0x0e, 0x17, 0xb8, 0xbf, 0xef, 0xf9, 0x20, - 0x08, 0x46, 0xca, 0x8c, 0x19, 0x42, 0x49, 0x7c, - 0x48, 0x44, 0x03, 0xbc, 0xff, 0x14, 0x9e, 0xfa, - 0x66, 0x06, 0xa6, 0xbd, 0x20, 0xef, 0x7d, 0x1b, - 0x06, 0xbd, 0x92, 0xf6, 0x90, 0x46, 0x39, 0xdc, - 0xe5, 0x17, 0x4d, 0xb6, 0xcc, 0x55, 0x4a, 0x26, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x12, }, - {0xc9, 0xff, 0x61, 0xb0, 0x40, 0x87, 0x4c, 0x05, - 0x68, 0x47, 0x92, 0x16, 0x82, 0x4a, 0x15, 0xea, - 0xb1, 0xa8, 0x38, 0xa7, 0x97, 0xd1, 0x89, 0x74, - 0x62, 0x26, 0xe4, 0xcc, 0xea, 0x98, 0xd6, 0x0e, - 0x5f, 0xfc, 0x9b, 0x8f, 0xcf, 0x99, 0x9f, 0xab, - 0x1d, 0xf7, 0xe7, 0xef, 0x70, 0x84, 0xf2, 0x0d, - 0xdb, 0x61, 0xbb, 0x04, 0x5a, 0x6c, 0xe0, 0x02, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x13, }, - {0xa1, 0xe8, 0x1c, 0x04, 0xf3, 0x0c, 0xe2, 0x01, - 0xc7, 0xc9, 0xac, 0xe7, 0x85, 0xed, 0x44, 0xcc, - 0x33, 0xb4, 0x55, 0xa0, 0x22, 0xf2, 0xac, 0xdb, - 0xc6, 0xca, 0xe8, 0x3c, 0xdc, 0xf1, 0xf6, 0xc3, - 0xdb, 0x09, 0xc7, 0x0a, 0xcc, 0x25, 0x39, 0x1d, - 0x49, 0x2f, 0xe2, 0x5b, 0x4a, 0x18, 0x0b, 0xab, - 0xd6, 0xce, 0xa3, 0x56, 0xc0, 0x47, 0x19, 0xcd, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x14, }, - {0xfc, 0xc7, 0xf2, 0xb4, 0x5d, 0xf1, 0xcd, 0x5a, - 0x3c, 0x0c, 0x07, 0x31, 0xca, 0x47, 0xa8, 0xaf, - 0x75, 0xcf, 0xb0, 0x34, 0x7e, 0x83, 0x54, 0xee, - 0xfe, 0x78, 0x24, 0x55, 0x0d, 0x5d, 0x71, 0x10, - 0x27, 0x4c, 0xba, 0x7c, 0xde, 0xe9, 0x0e, 0x1a, - 0x8b, 0x0d, 0x39, 0x4c, 0x37, 0x6a, 0x55, 0x73, - 0xdb, 0x6b, 0xe0, 0xbf, 0x27, 0x47, 0xf5, 0x30, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x8e, 0xbb, 0xb9, - 0x5e, 0xed, 0x0e, 0x13, }, - {0x61, 0xf0, 0x77, 0xc6, 0xf6, 0x2e, 0xd8, 0x02, - 0xda, 0xd7, 0xc2, 0xf3, 0x8f, 0x5c, 0x67, 0xf2, - 0xcc, 0x45, 0x36, 0x01, 0xe6, 0x1b, 0xd0, 0x76, - 0xbb, 0x46, 0x17, 0x9e, 0x22, 0x72, 0xf9, 0xe9, - 0xf5, 0x93, 0x3e, 0x70, 0x38, 0x8e, 0xe6, 0x52, - 0x51, 0x34, 0x43, 0xb5, 0xe2, 0x89, 0xdd, 0x13, - 0x5d, 0xcc, 0x0d, 0x02, 0x99, 0xb2, 0x25, 0xe4, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x9d, 0x89, - 0x3d, 0x4c, 0xdd, 0x74, 0x72, 0x46, 0xcd, 0xca, - 0x43, 0x59, 0x0e, 0x13, }, - {0x02, 0x98, 0x95, 0xf0, 0xaf, 0x49, 0x6b, 0xfc, - 0x62, 0xb6, 0xef, 0x8d, 0x8a, 0x65, 0xc8, 0x8c, - 0x61, 0x39, 0x49, 0xb0, 0x36, 0x68, 0xaa, 0xb4, - 0xf0, 0x42, 0x9e, 0x35, 0x3e, 0xa6, 0xe5, 0x3f, - 0x9a, 0x84, 0x1f, 0x20, 0x19, 0xec, 0x24, 0xbd, - 0xe1, 0xa7, 0x56, 0x77, 0xaa, 0x9b, 0x59, 0x02, - 0xe6, 0x10, 0x81, 0xc0, 0x10, 0x64, 0xde, 0x93, - }, - }, - { - {0x41, 0xff, 0xc1, 0xff, 0xff, 0xfe, 0x01, 0xff, - 0xfc, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x07, 0xc0, - 0x01, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xf0, 0x7f, - 0xfe, 0x00, 0x07, 0xc0, }, - {0xab, 0x68, 0x99, 0x30, 0xbc, 0xae, 0x4a, 0x4a, - 0xa5, 0xf5, 0xcb, 0x08, 0x5e, 0x82, 0x3e, 0x8a, - 0xe3, 0x0f, 0xd3, 0x65, 0xeb, 0x1d, 0xa4, 0xab, - 0xa9, 0xcf, 0x03, 0x79, 0x33, 0x45, 0xa1, 0x21, - 0xbb, 0xd2, 0x33, 0x54, 0x8a, 0xf0, 0xd2, 0x10, - 0x65, 0x4e, 0xb4, 0x0b, 0xab, 0x78, 0x8a, 0x03, - 0x66, 0x64, 0x19, 0xbe, 0x6f, 0xbd, 0x34, 0xe7, - }, - }, - { - {0x7f, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xc0, 0x03, - 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x0e, 0x00, 0xff, }, - {0xbd, 0xb6, 0xa8, 0x81, 0x7c, 0x1f, 0x89, 0xda, - 0x1c, 0x2f, 0x3d, 0xd8, 0xe9, 0x7f, 0xeb, 0x44, - 0x94, 0xf2, 0xed, 0x30, 0x2a, 0x4c, 0xe2, 0xbc, - 0x7f, 0x5f, 0x40, 0x25, 0x4c, 0x70, 0x20, 0xd5, - 0x7c, 0x00, 0x41, 0x18, 0x89, 0x46, 0x2d, 0x77, - 0xa5, 0x43, 0x8b, 0xb4, 0xe9, 0x7d, 0x17, 0x77, - 0x00, 0xbf, 0x72, 0x43, 0xa0, 0x7f, 0x16, 0x80, - }, - }, - { - {0x7f, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xf8, 0xff, 0xff, - 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, - 0x00, 0x0f, 0xff, 0xff, }, - {0xd5, 0x8b, 0x61, 0xaa, 0x41, 0xc3, 0x2d, 0xd5, - 0xeb, 0xa4, 0x62, 0x64, 0x7d, 0xba, 0x75, 0xc5, - 0xd6, 0x7c, 0x83, 0x60, 0x6c, 0x0a, 0xf2, 0xbd, - 0x92, 0x84, 0x46, 0xa9, 0xd2, 0x4b, 0xa6, 0xa8, - 0x37, 0xbe, 0x04, 0x60, 0xdd, 0x10, 0x7a, 0xe7, - 0x77, 0x25, 0x69, 0x6d, 0x21, 0x14, 0x46, 0xc5, - 0x60, 0x9b, 0x45, 0x95, 0x97, 0x6b, 0x16, 0xbd, - }, - }, - { - {0x7f, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xfe, 0x3f, - 0xff, 0xfc, 0x10, 0x00, 0x00, 0x20, 0x00, 0x3f, - 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, - 0x3f, 0xff, 0xff, 0xff, }, - {0xdc, 0x9f, 0xa7, 0x79, 0x78, 0xa0, 0x05, 0x51, - 0x09, 0x80, 0xe9, 0x29, 0xa1, 0x48, 0x5f, 0x63, - 0x71, 0x6d, 0xf6, 0x95, 0xd7, 0xa0, 0xc1, 0x8b, - 0xb5, 0x18, 0xdf, 0x03, 0xed, 0xe2, 0xb0, 0x16, - 0xf2, 0xdd, 0xff, 0xc2, 0xa8, 0xc0, 0x15, 0xb1, - 0x34, 0x92, 0x82, 0x75, 0xce, 0x09, 0xe5, 0x66, - 0x1b, 0x7a, 0xb1, 0x4c, 0xe0, 0xd1, 0xd4, 0x03, - }, - }, - { - {0x70, 0x01, 0xf0, 0x00, 0x1c, 0x00, 0x01, 0xc0, - 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xc0, 0x00, - 0x00, 0x01, 0xfc, 0x00, }, - {0x49, 0x9d, 0x8b, 0x28, 0x29, 0xcf, 0xb8, 0x79, - 0xc9, 0x01, 0xf7, 0xd8, 0x5d, 0x35, 0x70, 0x45, - 0xed, 0xab, 0x55, 0x02, 0x88, 0x24, 0xd0, 0xf0, - 0x5b, 0xa2, 0x79, 0xba, 0xbf, 0x92, 0x95, 0x37, - 0xb0, 0x6e, 0x40, 0x15, 0x91, 0x96, 0x39, 0xd9, - 0x4f, 0x57, 0x83, 0x8f, 0xa3, 0x3f, 0xc3, 0xd9, - 0x52, 0x59, 0x8d, 0xcd, 0xbb, 0x44, 0xd6, 0x38, - }, - }, - { - {0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, - 0x00, 0xff, 0xf0, 0x30, 0x00, 0x1f, 0x00, 0x00, - 0xff, 0xff, 0xf0, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, }, - {0x82, 0x46, 0xc9, 0x99, 0x13, 0x71, 0x86, 0x63, - 0x2c, 0x5f, 0x9e, 0xdd, 0xf3, 0xb1, 0xb0, 0xe1, - 0x76, 0x4c, 0x5e, 0x8b, 0xd0, 0xe0, 0xd8, 0xa5, - 0x54, 0xb9, 0xcb, 0x77, 0xe8, 0x0e, 0xd8, 0x66, - 0x0b, 0xc1, 0xcb, 0x17, 0xac, 0x7d, 0x84, 0x5b, - 0xe4, 0x0a, 0x7a, 0x02, 0x2d, 0x33, 0x06, 0xf1, - 0x16, 0xae, 0x9f, 0x81, 0xfe, 0xa6, 0x59, 0x47, - }, - }, - { - {0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xfe, 0x08, 0x00, 0x00, 0x1f, - 0xf0, 0x00, 0x1f, 0xff, }, - {0x66, 0x70, 0xc2, 0x0a, 0xfc, 0xce, 0xae, 0xa6, - 0x72, 0xc9, 0x7f, 0x75, 0xe2, 0xe9, 0xdd, 0x5c, - 0x84, 0x60, 0xe5, 0x4b, 0xb3, 0x85, 0x38, 0xeb, - 0xb4, 0xbd, 0x30, 0xeb, 0xf2, 0x80, 0xd8, 0x00, - 0x8d, 0x07, 0xa4, 0xca, 0xf5, 0x42, 0x71, 0xf9, - 0x93, 0x52, 0x7d, 0x46, 0xff, 0x3f, 0xf4, 0x6f, - 0xd1, 0x19, 0x0a, 0x3f, 0x1f, 0xaa, 0x4f, 0x74, - }, - }, - { - {0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xe0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, }, - {0x00, 0x0e, 0xca, 0x93, 0x42, 0x47, 0x42, 0x5c, - 0xfd, 0x94, 0x9b, 0x79, 0x5c, 0xb5, 0xce, 0x1e, - 0xff, 0x40, 0x15, 0x50, 0x38, 0x6e, 0x28, 0xd1, - 0xa4, 0xc5, 0xa8, 0xeb, 0xd4, 0xc0, 0x10, 0x40, - 0xdb, 0xa1, 0x96, 0x28, 0x93, 0x1b, 0xc8, 0x85, - 0x53, 0x70, 0x31, 0x7c, 0x72, 0x2c, 0xbd, 0x9c, - 0xa6, 0x15, 0x69, 0x85, 0xf1, 0xc2, 0xe9, 0xce, - }, - }, - { - {0x7f, 0xff, 0xfc, 0x03, 0xff, 0x80, 0x7f, 0xff, - 0xe0, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x0f, 0xff, - 0x80, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff, - 0xff, 0xfe, 0x00, 0x1f, }, - {0xef, 0x35, 0x3b, 0xf5, 0xc7, 0x3c, 0xd5, 0x51, - 0xb9, 0x6d, 0x59, 0x6f, 0xbc, 0x9a, 0x67, 0xf1, - 0x6d, 0x61, 0xdd, 0x9f, 0xe5, 0x6a, 0xf1, 0x9d, - 0xe1, 0xfb, 0xa9, 0xcd, 0x21, 0x77, 0x1b, 0x9c, - 0xdc, 0xe3, 0xe8, 0x43, 0x0c, 0x09, 0xb3, 0x83, - 0x8b, 0xe7, 0x0b, 0x48, 0xc2, 0x1e, 0x15, 0xbc, - 0x09, 0xee, 0x1f, 0x2d, 0x79, 0x45, 0xb9, 0x1f, - }, - }, - { - {0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x7f, 0xff, - 0xff, 0xff, 0x01, 0xff, 0xfe, 0x03, 0xff, 0xfe, - 0x40, 0x00, 0x38, 0x00, 0x07, 0xe0, 0x00, 0x3f, - 0xfe, 0x00, 0x00, 0x00, }, - {0x40, 0x36, 0x05, 0x2a, 0x30, 0x91, 0xeb, 0x48, - 0x10, 0x46, 0xad, 0x32, 0x89, 0xc9, 0x5d, 0x3a, - 0xc9, 0x05, 0xca, 0x00, 0x23, 0xde, 0x2c, 0x03, - 0xec, 0xd4, 0x51, 0xcf, 0xd7, 0x68, 0x16, 0x5a, - 0x38, 0xa2, 0xb9, 0x6f, 0x81, 0x25, 0x86, 0xa9, - 0xd5, 0x9d, 0x41, 0x36, 0x03, 0x5d, 0x9c, 0x85, - 0x3a, 0x5b, 0xf2, 0xe1, 0xc8, 0x6a, 0x49, 0x93, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x29, }, - {0xfc, 0xc7, 0xf2, 0xb4, 0x5d, 0xf1, 0xcd, 0x5a, - 0x3c, 0x0c, 0x07, 0x31, 0xca, 0x47, 0xa8, 0xaf, - 0x75, 0xcf, 0xb0, 0x34, 0x7e, 0x83, 0x54, 0xee, - 0xfe, 0x78, 0x24, 0x55, 0xf2, 0xa2, 0x8e, 0xef, - 0xd8, 0xb3, 0x45, 0x83, 0x21, 0x16, 0xf1, 0xe5, - 0x74, 0xf2, 0xc6, 0xb2, 0xc8, 0x95, 0xaa, 0x8c, - 0x24, 0x94, 0x1f, 0x40, 0xd8, 0xb8, 0x0a, 0xd1, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x2a, }, - {0xa1, 0xe8, 0x1c, 0x04, 0xf3, 0x0c, 0xe2, 0x01, - 0xc7, 0xc9, 0xac, 0xe7, 0x85, 0xed, 0x44, 0xcc, - 0x33, 0xb4, 0x55, 0xa0, 0x22, 0xf2, 0xac, 0xdb, - 0xc6, 0xca, 0xe8, 0x3c, 0x23, 0x0e, 0x09, 0x3c, - 0x24, 0xf6, 0x38, 0xf5, 0x33, 0xda, 0xc6, 0xe2, - 0xb6, 0xd0, 0x1d, 0xa3, 0xb5, 0xe7, 0xf4, 0x54, - 0x29, 0x31, 0x5c, 0xa9, 0x3f, 0xb8, 0xe6, 0x34, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x2b, }, - {0xc9, 0xff, 0x61, 0xb0, 0x40, 0x87, 0x4c, 0x05, - 0x68, 0x47, 0x92, 0x16, 0x82, 0x4a, 0x15, 0xea, - 0xb1, 0xa8, 0x38, 0xa7, 0x97, 0xd1, 0x89, 0x74, - 0x62, 0x26, 0xe4, 0xcc, 0x15, 0x67, 0x29, 0xf1, - 0xa0, 0x03, 0x64, 0x70, 0x30, 0x66, 0x60, 0x54, - 0xe2, 0x08, 0x18, 0x0f, 0x8f, 0x7b, 0x0d, 0xf2, - 0x24, 0x9e, 0x44, 0xfb, 0xa5, 0x93, 0x1f, 0xff, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x2c, }, - {0xb8, 0x35, 0x7c, 0x3a, 0x6c, 0xee, 0xf2, 0x88, - 0x31, 0x0e, 0x17, 0xb8, 0xbf, 0xef, 0xf9, 0x20, - 0x08, 0x46, 0xca, 0x8c, 0x19, 0x42, 0x49, 0x7c, - 0x48, 0x44, 0x03, 0xbc, 0x00, 0xeb, 0x61, 0x05, - 0x99, 0xf9, 0x59, 0x42, 0xdf, 0x10, 0x82, 0xe4, - 0xf9, 0x42, 0x6d, 0x08, 0x6f, 0xb9, 0xc6, 0x23, - 0x1a, 0xe8, 0xb2, 0x49, 0x33, 0xaa, 0xb5, 0xdb, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x2d, }, - {0x0b, 0x6e, 0xc4, 0xfe, 0x17, 0x77, 0x38, 0x24, - 0x04, 0xef, 0x67, 0x99, 0x97, 0xba, 0x8d, 0x1c, - 0xc5, 0xcd, 0x8e, 0x85, 0x34, 0x92, 0x59, 0xf5, - 0x90, 0xc4, 0xc6, 0x6d, 0xcc, 0x66, 0x2b, 0x9b, - 0xcb, 0xa6, 0xf9, 0x4e, 0xe4, 0xff, 0x1c, 0x9c, - 0x10, 0xbd, 0x6d, 0xdd, 0x0d, 0x13, 0x8d, 0xf2, - 0xd0, 0x99, 0xa2, 0x82, 0x15, 0x2a, 0x4b, 0x7f, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x2e, }, - {0xba, 0xa4, 0xd8, 0x63, 0x55, 0x11, 0xa7, 0xd2, - 0x88, 0xae, 0xbe, 0xed, 0xd1, 0x2c, 0xe5, 0x29, - 0xff, 0x10, 0x2c, 0x91, 0xf9, 0x7f, 0x86, 0x7e, - 0x21, 0x91, 0x6b, 0xf9, 0x68, 0x65, 0xa0, 0xb8, - 0xa6, 0x07, 0xf0, 0xb0, 0x4b, 0x13, 0xd1, 0xcb, - 0x0a, 0xa9, 0x92, 0xa5, 0xa9, 0x7f, 0x5e, 0xe8, - 0xca, 0x18, 0x49, 0xef, 0xb9, 0xed, 0x86, 0x78, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x2f, }, - {0xa5, 0x36, 0x40, 0xc8, 0x3d, 0xc2, 0x08, 0x60, - 0x3d, 0xed, 0x83, 0xe4, 0xec, 0xf7, 0x58, 0xf2, - 0x4c, 0x35, 0x7d, 0x7c, 0xf4, 0x80, 0x88, 0xb2, - 0xce, 0x01, 0xe9, 0xfa, 0x2a, 0x7e, 0xb3, 0x28, - 0xdb, 0xe6, 0x63, 0xb5, 0xa4, 0x68, 0xb5, 0xbc, - 0x97, 0xa0, 0x40, 0xa3, 0x74, 0x53, 0x96, 0xba, - 0x63, 0x6b, 0x96, 0x43, 0x70, 0xdc, 0x33, 0x52, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x30, }, - {0x34, 0xe8, 0xe1, 0x7a, 0x43, 0x0e, 0x43, 0x28, - 0x97, 0x93, 0xc3, 0x83, 0xfa, 0xc9, 0x77, 0x42, - 0x47, 0xb4, 0x0e, 0x9e, 0xbd, 0x33, 0x66, 0x98, - 0x1f, 0xcf, 0xae, 0xca, 0xda, 0xd7, 0xe6, 0x08, - 0xe3, 0x80, 0x48, 0x04, 0x34, 0xea, 0x64, 0x1c, - 0xc8, 0x2c, 0x82, 0xcb, 0xc9, 0x28, 0x01, 0x46, - 0x9c, 0x8d, 0xb0, 0x20, 0x4f, 0x13, 0x48, 0x9a, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x31, }, - {0x6e, 0x31, 0xee, 0x1d, 0xc1, 0x37, 0xf8, 0x1b, - 0x05, 0x67, 0x52, 0xe4, 0xde, 0xab, 0x14, 0x43, - 0xa4, 0x81, 0x03, 0x3e, 0x9b, 0x4c, 0x93, 0xa3, - 0x04, 0x4f, 0x4f, 0x7a, 0xdf, 0x82, 0x22, 0x0f, - 0xc7, 0xa4, 0x02, 0x15, 0x49, 0x16, 0x53, 0x25, - 0x72, 0x5f, 0x94, 0xc3, 0x41, 0x0d, 0xdb, 0x56, - 0xc5, 0x4e, 0x16, 0x1f, 0xc9, 0xef, 0x62, 0xee, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x32, }, - {0xef, 0x53, 0xb6, 0x29, 0x4a, 0xca, 0x43, 0x1f, - 0x0f, 0x3c, 0x22, 0xdc, 0x82, 0xeb, 0x90, 0x50, - 0x32, 0x4f, 0x1d, 0x88, 0xd3, 0x77, 0xe7, 0x16, - 0x44, 0x8e, 0x50, 0x7c, 0xdf, 0x4a, 0xef, 0xff, - 0xbf, 0x6d, 0x16, 0x99, 0xc9, 0x30, 0x48, 0x1c, - 0xd1, 0x02, 0x12, 0x7c, 0x9a, 0x3d, 0x99, 0x20, - 0x48, 0xab, 0x05, 0x92, 0x9b, 0x6e, 0x59, 0x27, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x33, }, - {0xae, 0xa9, 0xe1, 0x7a, 0x30, 0x65, 0x17, 0xeb, - 0x89, 0x15, 0x2a, 0xa7, 0x09, 0x6d, 0x2c, 0x38, - 0x1e, 0xc8, 0x13, 0xc5, 0x1a, 0xa8, 0x80, 0xe7, - 0xbe, 0xe2, 0xc0, 0xfd, 0xc6, 0x44, 0xcf, 0x15, - 0x4c, 0xc8, 0x1f, 0x5a, 0xde, 0x49, 0x34, 0x5e, - 0x54, 0x1b, 0x4d, 0x4b, 0x5c, 0x1a, 0xdb, 0x3e, - 0xb5, 0xc0, 0x1c, 0x14, 0xee, 0x94, 0x9a, 0xa2, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x34, }, - {0x2f, 0xdc, 0xcc, 0xfe, 0xe7, 0x20, 0xa7, 0x7e, - 0xf6, 0xcb, 0x3b, 0xfb, 0xb4, 0x47, 0xf9, 0x38, - 0x31, 0x17, 0xe3, 0xda, 0xa4, 0xa0, 0x7e, 0x36, - 0xed, 0x15, 0xf7, 0x8d, 0xc8, 0xe8, 0xcd, 0x1b, - 0x0b, 0xe4, 0x0b, 0x08, 0x77, 0xcf, 0xca, 0x19, - 0x58, 0x60, 0x31, 0x22, 0xf1, 0xe6, 0x91, 0x4f, - 0x84, 0xb7, 0xe8, 0xe9, 0x68, 0xae, 0x8b, 0x9e, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x35, }, - {0x85, 0x8e, 0x6f, 0x9c, 0xc6, 0xc1, 0x2c, 0x31, - 0xf5, 0xdf, 0x12, 0x4a, 0xa7, 0x77, 0x67, 0xb0, - 0x5c, 0x8b, 0xc0, 0x21, 0xbd, 0x68, 0x3d, 0x2b, - 0x55, 0x57, 0x15, 0x50, 0xfb, 0x92, 0x32, 0xc1, - 0x5a, 0x3b, 0xc7, 0x67, 0x3a, 0x3a, 0x03, 0xb0, - 0x25, 0x38, 0x24, 0xc5, 0x3d, 0x0f, 0xd1, 0x41, - 0x1b, 0x1c, 0xab, 0xe2, 0xe1, 0x87, 0xfb, 0x87, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x36, }, - {0xdb, 0x2f, 0x6b, 0xe6, 0x30, 0xe2, 0x46, 0xa5, - 0xcf, 0x7d, 0x99, 0xb8, 0x51, 0x94, 0xb1, 0x23, - 0xd4, 0x87, 0xe2, 0xd4, 0x66, 0xb9, 0x4b, 0x24, - 0xa0, 0x3c, 0x3e, 0x28, 0xf0, 0xc5, 0xcf, 0xf7, - 0xab, 0x68, 0x0d, 0x09, 0xee, 0x11, 0xda, 0xe8, - 0x4e, 0x9c, 0x10, 0x72, 0xac, 0x48, 0xea, 0x2e, - 0x74, 0x4b, 0x1b, 0x7f, 0x72, 0xfd, 0x46, 0x9e, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x37, }, - {0x1f, 0x24, 0x83, 0xf8, 0x25, 0x72, 0x25, 0x1f, - 0xca, 0x97, 0x5f, 0xea, 0x40, 0xdb, 0x82, 0x1d, - 0xf8, 0xad, 0x82, 0xa3, 0xc0, 0x02, 0xee, 0x6c, - 0x57, 0x11, 0x24, 0x08, 0x76, 0x05, 0x0f, 0x33, - 0x48, 0xaf, 0x26, 0x64, 0xaa, 0xc3, 0xa8, 0xb0, - 0x52, 0x81, 0x30, 0x4e, 0xbc, 0x7a, 0x79, 0x14, - 0xc6, 0xad, 0x50, 0xa4, 0xb4, 0xea, 0xc3, 0x83, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x38, }, - {0x31, 0xc4, 0x9a, 0xe7, 0x5b, 0xce, 0x78, 0x07, - 0xcd, 0xff, 0x22, 0x05, 0x5d, 0x94, 0xee, 0x90, - 0x21, 0xfe, 0xdb, 0xb5, 0xab, 0x51, 0xc5, 0x75, - 0x26, 0xf0, 0x11, 0xaa, 0xd8, 0x17, 0x40, 0x0e, - 0x8b, 0xa9, 0xca, 0x13, 0xa4, 0x5f, 0x36, 0x0e, - 0x3d, 0x12, 0x1e, 0xaa, 0xeb, 0x39, 0xaf, 0x82, - 0xd6, 0x00, 0x1c, 0x81, 0x86, 0xf5, 0xf8, 0x66, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x39, }, - {0xae, 0x99, 0xfe, 0xeb, 0xb5, 0xd2, 0x69, 0x45, - 0xb5, 0x48, 0x92, 0x09, 0x2a, 0x8a, 0xee, 0x02, - 0x91, 0x29, 0x30, 0xfa, 0x41, 0xcd, 0x11, 0x4e, - 0x40, 0x44, 0x73, 0x01, 0xfb, 0x7d, 0xa7, 0xf5, - 0xf1, 0x3a, 0x43, 0xb8, 0x17, 0x74, 0x37, 0x3c, - 0x87, 0x9c, 0xd3, 0x2d, 0x69, 0x34, 0xc0, 0x5f, - 0xa7, 0x58, 0xee, 0xb1, 0x4f, 0xcf, 0xab, 0x38, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x3a, }, - {0xdf, 0x1b, 0x1d, 0x66, 0xa5, 0x51, 0xd0, 0xd3, - 0x1e, 0xff, 0x82, 0x25, 0x58, 0xb9, 0xd2, 0xcc, - 0x75, 0xc2, 0x18, 0x02, 0x79, 0xfe, 0x0d, 0x08, - 0xfd, 0x89, 0x6d, 0x04, 0x5c, 0x08, 0x0f, 0xc3, - 0x52, 0x2f, 0x41, 0xbb, 0xb3, 0xf5, 0x5a, 0x97, - 0xcf, 0xec, 0xf2, 0x1f, 0x88, 0x2c, 0xe8, 0xcb, - 0xb1, 0xe5, 0x0c, 0xa6, 0xe6, 0x7e, 0x56, 0xdc, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x3b, }, - {0x70, 0x6a, 0x46, 0xdc, 0x76, 0xdc, 0xb7, 0x67, - 0x98, 0xe6, 0x0e, 0x6d, 0x89, 0x47, 0x47, 0x88, - 0xd1, 0x6d, 0xc1, 0x80, 0x32, 0xd2, 0x68, 0xfd, - 0x1a, 0x70, 0x4f, 0xa6, 0xe3, 0xd4, 0x89, 0x58, - 0x43, 0xda, 0x18, 0x8f, 0xd5, 0x8f, 0xb0, 0x56, - 0x79, 0x76, 0xd7, 0xb5, 0x03, 0x59, 0xd6, 0xb7, - 0x85, 0x30, 0xc8, 0xf6, 0x2d, 0x1b, 0x17, 0x46, - }, - }, - { - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x3c, }, - {0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, - 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, - 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, - 0x11, 0x5c, 0x1d, 0x21, 0x42, 0xc8, 0x9c, 0x77, - 0x4a, 0x08, 0xdc, 0x04, 0xb3, 0xdd, 0x20, 0x19, - 0x32, 0xbc, 0x8a, 0x5e, 0xa5, 0xf8, 0xb8, 0x9b, - 0xbb, 0x2a, 0x7e, 0x66, 0x7a, 0xff, 0x81, 0xcd, - }, - }, -}; - -TEST(P224, ExternalToInternalAndBack) { - Point point; - - EXPECT_TRUE(point.SetFromString(base::StringPiece( - reinterpret_cast(kBasePointExternal), - sizeof(kBasePointExternal)))); - - const std::string external = point.ToString(); - - ASSERT_EQ(external.size(), 56u); - EXPECT_TRUE(memcmp(external.data(), kBasePointExternal, - sizeof(kBasePointExternal)) == 0); -} - -TEST(P224, ScalarBaseMult) { - Point point; - - for (size_t i = 0; i < arraysize(kNISTTestVectors); i++) { - p224::ScalarBaseMult(kNISTTestVectors[i].scalar, &point); - const std::string external = point.ToString(); - ASSERT_EQ(external.size(), 56u); - EXPECT_TRUE(memcmp(external.data(), kNISTTestVectors[i].affine, - external.size()) == 0); - } -} - -TEST(P224, Addition) { - Point a, b, minus_b, sum, a_again; - - ASSERT_TRUE(a.SetFromString(base::StringPiece( - reinterpret_cast(kNISTTestVectors[10].affine), 56))); - ASSERT_TRUE(b.SetFromString(base::StringPiece( - reinterpret_cast(kNISTTestVectors[11].affine), 56))); - - p224::Negate(b, &minus_b); - p224::Add(a, b, &sum); - EXPECT_TRUE(memcmp(&sum, &a, sizeof(sum)) != 0); - p224::Add(minus_b, sum, &a_again); - EXPECT_TRUE(a_again.ToString() == a.ToString()); -} - -TEST(P224, Infinity) { - char zeros[56]; - memset(zeros, 0, sizeof(zeros)); - - // Test that x^0 = ∞. - Point a; - p224::ScalarBaseMult(reinterpret_cast(zeros), &a); - EXPECT_TRUE(memcmp(zeros, a.ToString().data(), sizeof(zeros)) == 0); - - // We shouldn't allow ∞ to be imported. - EXPECT_FALSE(a.SetFromString(std::string(zeros, sizeof(zeros)))); -} - -} // namespace crypto diff --git a/crypto/random.cc b/crypto/random.cc deleted file mode 100644 index a19bb1a11c78e..0000000000000 --- a/crypto/random.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2012 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/random.h" - -#include "base/rand_util.h" - -namespace crypto { - -void RandBytes(void *bytes, size_t length) { - // It's OK to call base::RandBytes(), because it's already strongly random. - // But _other_ code should go through this function to ensure that code which - // needs secure randomness is easily discoverable. - base::RandBytes(bytes, length); -} - -} // namespace crypto - diff --git a/crypto/random.h b/crypto/random.h deleted file mode 100644 index 002616bd30ef7..0000000000000 --- a/crypto/random.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2012 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_RANDOM_H_ -#define CRYPTO_RANDOM_H_ - -#include - -#include "crypto/crypto_export.h" - -namespace crypto { - -// Fills the given buffer with |length| random bytes of cryptographically -// secure random numbers. -// |length| must be positive. -CRYPTO_EXPORT void RandBytes(void *bytes, size_t length); - -} - -#endif diff --git a/crypto/random_unittest.cc b/crypto/random_unittest.cc deleted file mode 100644 index 00d4b2b5e861e..0000000000000 --- a/crypto/random_unittest.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2012 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/random.h" - -#include "base/strings/string_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -// Basic functionality tests. Does NOT test the security of the random data. - -// Ensures we don't have all trivial data, i.e. that the data is indeed random. -// Currently, that means the bytes cannot be all the same (e.g. all zeros). -bool IsTrivial(const std::string& bytes) { - for (size_t i = 0; i < bytes.size(); i++) { - if (bytes[i] != bytes[0]) { - return false; - } - } - return true; -} - -TEST(RandBytes, RandBytes) { - std::string bytes(16, '\0'); - crypto::RandBytes(base::WriteInto(&bytes, bytes.size()), bytes.size()); - EXPECT_TRUE(!IsTrivial(bytes)); -} diff --git a/crypto/rsa_private_key.cc b/crypto/rsa_private_key.cc deleted file mode 100644 index 812d9fa16e578..0000000000000 --- a/crypto/rsa_private_key.cc +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright (c) 2011 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/rsa_private_key.h" - -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_util.h" - -// This file manually encodes and decodes RSA private keys using PrivateKeyInfo -// from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are: -// -// PrivateKeyInfo ::= SEQUENCE { -// version Version, -// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, -// privateKey PrivateKey, -// attributes [0] IMPLICIT Attributes OPTIONAL -// } -// -// RSAPrivateKey ::= SEQUENCE { -// version Version, -// modulus INTEGER, -// publicExponent INTEGER, -// privateExponent INTEGER, -// prime1 INTEGER, -// prime2 INTEGER, -// exponent1 INTEGER, -// exponent2 INTEGER, -// coefficient INTEGER -// } - -namespace { -// Helper for error handling during key import. -#define READ_ASSERT(truth) \ - if (!(truth)) { \ - NOTREACHED(); \ - return false; \ - } -} // namespace - -namespace crypto { - -const uint8 PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00 -}; - -PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) - : big_endian_(big_endian) {} - -PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {} - -bool PrivateKeyInfoCodec::Export(std::vector* output) { - std::list content; - - // Version (always zero) - uint8 version = 0; - - PrependInteger(coefficient_, &content); - PrependInteger(exponent2_, &content); - PrependInteger(exponent1_, &content); - PrependInteger(prime2_, &content); - PrependInteger(prime1_, &content); - PrependInteger(private_exponent_, &content); - PrependInteger(public_exponent_, &content); - PrependInteger(modulus_, &content); - PrependInteger(&version, 1, &content); - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content); - - // RSA algorithm OID - for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) - content.push_front(kRsaAlgorithmIdentifier[i - 1]); - - PrependInteger(&version, 1, &content); - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - - // Copy everying into the output. - output->reserve(content.size()); - output->assign(content.begin(), content.end()); - - return true; -} - -bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector* output) { - // Create a sequence with the modulus (n) and public exponent (e). - std::vector bit_string; - if (!ExportPublicKey(&bit_string)) - return false; - - // Add the sequence as the contents of a bit string. - std::list content; - PrependBitString(&bit_string[0], static_cast(bit_string.size()), - &content); - - // Add the RSA algorithm OID. - for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) - content.push_front(kRsaAlgorithmIdentifier[i - 1]); - - // Finally, wrap everything in a sequence. - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - - // Copy everything into the output. - output->reserve(content.size()); - output->assign(content.begin(), content.end()); - - return true; -} - -bool PrivateKeyInfoCodec::ExportPublicKey(std::vector* output) { - // Create a sequence with the modulus (n) and public exponent (e). - std::list content; - PrependInteger(&public_exponent_[0], - static_cast(public_exponent_.size()), - &content); - PrependInteger(&modulus_[0], static_cast(modulus_.size()), &content); - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - - // Copy everything into the output. - output->reserve(content.size()); - output->assign(content.begin(), content.end()); - - return true; -} - -bool PrivateKeyInfoCodec::Import(const std::vector& input) { - if (input.empty()) { - return false; - } - - // Parse the private key info up to the public key values, ignoring - // the subsequent private key values. - uint8* src = const_cast(&input.front()); - uint8* end = src + input.size(); - if (!ReadSequence(&src, end) || - !ReadVersion(&src, end) || - !ReadAlgorithmIdentifier(&src, end) || - !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) || - !ReadSequence(&src, end) || - !ReadVersion(&src, end) || - !ReadInteger(&src, end, &modulus_)) - return false; - - int mod_size = modulus_.size(); - READ_ASSERT(mod_size % 2 == 0); - int primes_size = mod_size / 2; - - if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) || - !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) || - !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_)) - return false; - - READ_ASSERT(src == end); - - - return true; -} - -void PrivateKeyInfoCodec::PrependInteger(const std::vector& in, - std::list* out) { - uint8* ptr = const_cast(&in.front()); - PrependIntegerImpl(ptr, in.size(), out, big_endian_); -} - -// Helper to prepend an ASN.1 integer. -void PrivateKeyInfoCodec::PrependInteger(uint8* val, - int num_bytes, - std::list* data) { - PrependIntegerImpl(val, num_bytes, data, big_endian_); -} - -void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val, - int num_bytes, - std::list* data, - bool big_endian) { - // Reverse input if little-endian. - std::vector tmp; - if (!big_endian) { - tmp.assign(val, val + num_bytes); - std::reverse(tmp.begin(), tmp.end()); - val = &tmp.front(); - } - - // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes - // from the most-significant end of the integer. - int start = 0; - while (start < (num_bytes - 1) && val[start] == 0x00) { - start++; - num_bytes--; - } - PrependBytes(val, start, num_bytes, data); - - // ASN.1 integers are signed. To encode a positive integer whose sign bit - // (the most significant bit) would otherwise be set and make the number - // negative, ASN.1 requires a leading null byte to force the integer to be - // positive. - uint8 front = data->front(); - if ((front & 0x80) != 0) { - data->push_front(0x00); - num_bytes++; - } - - PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); -} - -bool PrivateKeyInfoCodec::ReadInteger(uint8** pos, - uint8* end, - std::vector* out) { - return ReadIntegerImpl(pos, end, out, big_endian_); -} - -bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, - uint8* end, - size_t expected_size, - std::vector* out) { - std::vector temp; - if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian - return false; - - int pad = expected_size - temp.size(); - int index = 0; - if (out->size() == expected_size + 1) { - READ_ASSERT(out->front() == 0x00); - pad++; - index++; - } else { - READ_ASSERT(out->size() <= expected_size); - } - - out->insert(out->end(), pad, 0x00); - out->insert(out->end(), temp.begin(), temp.end()); - - // Reverse output if little-endian. - if (!big_endian_) - std::reverse(out->begin(), out->end()); - return true; -} - -bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, - uint8* end, - std::vector* out, - bool big_endian) { - uint32 length = 0; - if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length) - return false; - - // The first byte can be zero to force positiveness. We can ignore this. - if (**pos == 0x00) { - ++(*pos); - --length; - } - - if (length) - out->insert(out->end(), *pos, (*pos) + length); - - (*pos) += length; - - // Reverse output if little-endian. - if (!big_endian) - std::reverse(out->begin(), out->end()); - return true; -} - -void PrivateKeyInfoCodec::PrependBytes(uint8* val, - int start, - int num_bytes, - std::list* data) { - while (num_bytes > 0) { - --num_bytes; - data->push_front(val[start + num_bytes]); - } -} - -void PrivateKeyInfoCodec::PrependLength(size_t size, std::list* data) { - // The high bit is used to indicate whether additional octets are needed to - // represent the length. - if (size < 0x80) { - data->push_front(static_cast(size)); - } else { - uint8 num_bytes = 0; - while (size > 0) { - data->push_front(static_cast(size & 0xFF)); - size >>= 8; - num_bytes++; - } - CHECK_LE(num_bytes, 4); - data->push_front(0x80 | num_bytes); - } -} - -void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type, - uint32 length, - std::list* output) { - PrependLength(length, output); - output->push_front(type); -} - -void PrivateKeyInfoCodec::PrependBitString(uint8* val, - int num_bytes, - std::list* output) { - // Start with the data. - PrependBytes(val, 0, num_bytes, output); - // Zero unused bits. - output->push_front(0); - // Add the length. - PrependLength(num_bytes + 1, output); - // Finally, add the bit string tag. - output->push_front((uint8) kBitStringTag); -} - -bool PrivateKeyInfoCodec::ReadLength(uint8** pos, uint8* end, uint32* result) { - READ_ASSERT(*pos < end); - int length = 0; - - // If the MSB is not set, the length is just the byte itself. - if (!(**pos & 0x80)) { - length = **pos; - (*pos)++; - } else { - // Otherwise, the lower 7 indicate the length of the length. - int length_of_length = **pos & 0x7F; - READ_ASSERT(length_of_length <= 4); - (*pos)++; - READ_ASSERT(*pos + length_of_length < end); - - length = 0; - for (int i = 0; i < length_of_length; ++i) { - length <<= 8; - length |= **pos; - (*pos)++; - } - } - - READ_ASSERT(*pos + length <= end); - if (result) *result = length; - return true; -} - -bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8** pos, - uint8* end, - uint8 expected_tag, - uint32* length) { - READ_ASSERT(*pos < end); - READ_ASSERT(**pos == expected_tag); - (*pos)++; - - return ReadLength(pos, end, length); -} - -bool PrivateKeyInfoCodec::ReadSequence(uint8** pos, uint8* end) { - return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); -} - -bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8** pos, uint8* end) { - READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); - READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, - sizeof(kRsaAlgorithmIdentifier)) == 0); - (*pos) += sizeof(kRsaAlgorithmIdentifier); - return true; -} - -bool PrivateKeyInfoCodec::ReadVersion(uint8** pos, uint8* end) { - uint32 length = 0; - if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length)) - return false; - - // The version should be zero. - for (uint32 i = 0; i < length; ++i) { - READ_ASSERT(**pos == 0x00); - (*pos)++; - } - - return true; -} - -} // namespace crypto diff --git a/crypto/rsa_private_key.h b/crypto/rsa_private_key.h deleted file mode 100644 index 637be38836f8d..0000000000000 --- a/crypto/rsa_private_key.h +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2012 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_RSA_PRIVATE_KEY_H_ -#define CRYPTO_RSA_PRIVATE_KEY_H_ - -#include "build/build_config.h" - -#include -#include - -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -#if defined(USE_NSS_CERTS) -#include "base/gtest_prod_util.h" -#endif - -#if defined(USE_OPENSSL) -// Forward declaration for openssl/*.h -typedef struct evp_pkey_st EVP_PKEY; -#else -// Forward declaration. -typedef struct PK11SlotInfoStr PK11SlotInfo; -typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey; -typedef struct SECKEYPublicKeyStr SECKEYPublicKey; -#endif - - -namespace crypto { - -// Used internally by RSAPrivateKey for serializing and deserializing -// PKCS #8 PrivateKeyInfo and PublicKeyInfo. -class PrivateKeyInfoCodec { - public: - - // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8. - static const uint8 kRsaAlgorithmIdentifier[]; - - // ASN.1 tags for some types we use. - static const uint8 kBitStringTag = 0x03; - static const uint8 kIntegerTag = 0x02; - static const uint8 kNullTag = 0x05; - static const uint8 kOctetStringTag = 0x04; - static const uint8 kSequenceTag = 0x30; - - // |big_endian| here specifies the byte-significance of the integer components - // that will be parsed & serialized (modulus(), etc...) during Import(), - // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the - // PrivateKeyInfo/PublicKeyInfo (which is always big-endian). - explicit PrivateKeyInfoCodec(bool big_endian); - - ~PrivateKeyInfoCodec(); - - // Exports the contents of the integer components to the ASN.1 DER encoding - // of the PrivateKeyInfo structure to |output|. - bool Export(std::vector* output); - - // Exports the contents of the integer components to the ASN.1 DER encoding - // of the PublicKeyInfo structure to |output|. - bool ExportPublicKeyInfo(std::vector* output); - - // Exports the contents of the integer components to the ASN.1 DER encoding - // of the RSAPublicKey structure to |output|. - bool ExportPublicKey(std::vector* output); - - // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input| - // and populates the integer components with |big_endian_| byte-significance. - // IMPORTANT NOTE: This is currently *not* security-approved for importing - // keys from unstrusted sources. - bool Import(const std::vector& input); - - // Accessors to the contents of the integer components of the PrivateKeyInfo - // structure. - std::vector* modulus() { return &modulus_; }; - std::vector* public_exponent() { return &public_exponent_; }; - std::vector* private_exponent() { return &private_exponent_; }; - std::vector* prime1() { return &prime1_; }; - std::vector* prime2() { return &prime2_; }; - std::vector* exponent1() { return &exponent1_; }; - std::vector* exponent2() { return &exponent2_; }; - std::vector* coefficient() { return &coefficient_; }; - - private: - // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_| - // value. - void PrependInteger(const std::vector& in, std::list* out); - void PrependInteger(uint8* val, int num_bytes, std::list* data); - - // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian| - // byte-significance into |data| as an ASN.1 integer. - void PrependIntegerImpl(uint8* val, - int num_bytes, - std::list* data, - bool big_endian); - - // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_| - // value. - bool ReadInteger(uint8** pos, uint8* end, std::vector* out); - bool ReadIntegerWithExpectedSize(uint8** pos, - uint8* end, - size_t expected_size, - std::vector* out); - - // Reads an ASN.1 integer from |pos|, and stores the result into |out| with - // |big_endian| byte-significance. - bool ReadIntegerImpl(uint8** pos, - uint8* end, - std::vector* out, - bool big_endian); - - // Prepends the integer stored in |val|, starting a index |start|, for - // |num_bytes| bytes onto |data|. - void PrependBytes(uint8* val, - int start, - int num_bytes, - std::list* data); - - // Helper to prepend an ASN.1 length field. - void PrependLength(size_t size, std::list* data); - - // Helper to prepend an ASN.1 type header. - void PrependTypeHeaderAndLength(uint8 type, - uint32 length, - std::list* output); - - // Helper to prepend an ASN.1 bit string - void PrependBitString(uint8* val, int num_bytes, std::list* output); - - // Read an ASN.1 length field. This also checks that the length does not - // extend beyond |end|. - bool ReadLength(uint8** pos, uint8* end, uint32* result); - - // Read an ASN.1 type header and its length. - bool ReadTypeHeaderAndLength(uint8** pos, - uint8* end, - uint8 expected_tag, - uint32* length); - - // Read an ASN.1 sequence declaration. This consumes the type header and - // length field, but not the contents of the sequence. - bool ReadSequence(uint8** pos, uint8* end); - - // Read the RSA AlgorithmIdentifier. - bool ReadAlgorithmIdentifier(uint8** pos, uint8* end); - - // Read one of the two version fields in PrivateKeyInfo. - bool ReadVersion(uint8** pos, uint8* end); - - // The byte-significance of the stored components (modulus, etc..). - bool big_endian_; - - // Component integers of the PrivateKeyInfo - std::vector modulus_; - std::vector public_exponent_; - std::vector private_exponent_; - std::vector prime1_; - std::vector prime2_; - std::vector exponent1_; - std::vector exponent2_; - std::vector coefficient_; - - DISALLOW_COPY_AND_ASSIGN(PrivateKeyInfoCodec); -}; - -// Encapsulates an RSA private key. Can be used to generate new keys, export -// keys to other formats, or to extract a public key. -// TODO(hclam): This class should be ref-counted so it can be reused easily. -class CRYPTO_EXPORT RSAPrivateKey { - public: - ~RSAPrivateKey(); - - // Create a new random instance. Can return NULL if initialization fails. - static RSAPrivateKey* Create(uint16 num_bits); - - // Create a new instance by importing an existing private key. The format is - // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if - // initialization fails. - static RSAPrivateKey* CreateFromPrivateKeyInfo( - const std::vector& input); - -#if defined(USE_OPENSSL) - // Create a new instance from an existing EVP_PKEY, taking a - // reference to it. |key| must be an RSA key. Returns NULL on - // failure. - static RSAPrivateKey* CreateFromKey(EVP_PKEY* key); -#else - // Create a new instance by referencing an existing private key - // structure. Does not import the key. - static RSAPrivateKey* CreateFromKey(SECKEYPrivateKey* key); -#endif - -#if defined(USE_OPENSSL) - EVP_PKEY* key() { return key_; } -#else - SECKEYPrivateKey* key() { return key_; } - SECKEYPublicKey* public_key() { return public_key_; } -#endif - - // Creates a copy of the object. - RSAPrivateKey* Copy() const; - - // Exports the private key to a PKCS #1 PrivateKey block. - bool ExportPrivateKey(std::vector* output) const; - - // Exports the public key to an X509 SubjectPublicKeyInfo block. - bool ExportPublicKey(std::vector* output) const; - - private: -#if defined(USE_NSS_CERTS) - FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FindFromPublicKey); - FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FailedFindFromPublicKey); -#endif - - // Constructor is private. Use one of the Create*() methods above instead. - RSAPrivateKey(); - -#if defined(USE_OPENSSL) - EVP_PKEY* key_; -#else - SECKEYPrivateKey* key_; - SECKEYPublicKey* public_key_; -#endif - - DISALLOW_COPY_AND_ASSIGN(RSAPrivateKey); -}; - -} // namespace crypto - -#endif // CRYPTO_RSA_PRIVATE_KEY_H_ diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc deleted file mode 100644 index 88e55fa576812..0000000000000 --- a/crypto/rsa_private_key_nss.cc +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2011 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/rsa_private_key.h" - -#include -#include -#include - -#include - -#include "base/debug/leak_annotations.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_util.h" -#include "crypto/nss_key_util.h" -#include "crypto/nss_util.h" -#include "crypto/scoped_nss_types.h" - -// TODO(rafaelw): Consider using NSS's ASN.1 encoder. -namespace { - -static bool ReadAttribute(SECKEYPrivateKey* key, - CK_ATTRIBUTE_TYPE type, - std::vector* output) { - SECItem item; - SECStatus rv; - rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - - output->assign(item.data, item.data + item.len); - SECITEM_FreeItem(&item, PR_FALSE); - return true; -} - -} // namespace - -namespace crypto { - -RSAPrivateKey::~RSAPrivateKey() { - if (key_) - SECKEY_DestroyPrivateKey(key_); - if (public_key_) - SECKEY_DestroyPublicKey(public_key_); -} - -// static -RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { - EnsureNSSInit(); - - ScopedPK11Slot slot(PK11_GetInternalSlot()); - if (!slot) { - NOTREACHED(); - return nullptr; - } - - ScopedSECKEYPublicKey public_key; - ScopedSECKEYPrivateKey private_key; - if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */, - &public_key, &private_key)) { - return nullptr; - } - - RSAPrivateKey* rsa_key = new RSAPrivateKey; - rsa_key->public_key_ = public_key.release(); - rsa_key->key_ = private_key.release(); - return rsa_key; -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( - const std::vector& input) { - EnsureNSSInit(); - - ScopedPK11Slot slot(PK11_GetInternalSlot()); - if (!slot) { - NOTREACHED(); - return nullptr; - } - ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo( - slot.get(), input, false /* not permanent */)); - if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey) - return nullptr; - return RSAPrivateKey::CreateFromKey(key.get()); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) { - DCHECK(key); - if (SECKEY_GetPrivateKeyType(key) != rsaKey) - return NULL; - RSAPrivateKey* copy = new RSAPrivateKey(); - copy->key_ = SECKEY_CopyPrivateKey(key); - copy->public_key_ = SECKEY_ConvertToPublicKey(key); - if (!copy->key_ || !copy->public_key_) { - NOTREACHED(); - delete copy; - return NULL; - } - return copy; -} - -RSAPrivateKey* RSAPrivateKey::Copy() const { - RSAPrivateKey* copy = new RSAPrivateKey(); - copy->key_ = SECKEY_CopyPrivateKey(key_); - copy->public_key_ = SECKEY_CopyPublicKey(public_key_); - return copy; -} - -bool RSAPrivateKey::ExportPrivateKey(std::vector* output) const { - PrivateKeyInfoCodec private_key_info(true); - - // Manually read the component attributes of the private key and build up - // the PrivateKeyInfo. - if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) || - !ReadAttribute(key_, CKA_PUBLIC_EXPONENT, - private_key_info.public_exponent()) || - !ReadAttribute(key_, CKA_PRIVATE_EXPONENT, - private_key_info.private_exponent()) || - !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) || - !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) || - !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) || - !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || - !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { - NOTREACHED(); - return false; - } - - return private_key_info.Export(output); -} - -bool RSAPrivateKey::ExportPublicKey(std::vector* output) const { - ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); - if (!der_pubkey.get()) { - NOTREACHED(); - return false; - } - - output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len); - return true; -} - -RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { - EnsureNSSInit(); -} - -} // namespace crypto diff --git a/crypto/rsa_private_key_openssl.cc b/crypto/rsa_private_key_openssl.cc deleted file mode 100644 index 52a0a7a1815e8..0000000000000 --- a/crypto/rsa_private_key_openssl.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2011 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/rsa_private_key.h" - -#include -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" - -namespace crypto { - -namespace { - -using ScopedPKCS8_PRIV_KEY_INFO = - ScopedOpenSSL; - -// Function pointer definition, for injecting the required key export function -// into ExportKey, below. The supplied function should export EVP_PKEY into -// the supplied BIO, returning 1 on success or 0 on failure. -using ExportFunction = int (*)(BIO*, EVP_PKEY*); - -// Helper to export |key| into |output| via the specified ExportFunction. -bool ExportKey(EVP_PKEY* key, - ExportFunction export_fn, - std::vector* output) { - if (!key) - return false; - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedBIO bio(BIO_new(BIO_s_mem())); - - int res = export_fn(bio.get(), key); - if (!res) - return false; - - char* data = NULL; - long len = BIO_get_mem_data(bio.get(), &data); - if (!data || len < 0) - return false; - - output->assign(data, data + len); - return true; -} - -} // namespace - -// static -RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - ScopedRSA rsa_key(RSA_new()); - ScopedBIGNUM bn(BN_new()); - if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L)) - return NULL; - - if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL)) - return NULL; - - scoped_ptr result(new RSAPrivateKey); - result->key_ = EVP_PKEY_new(); - if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get())) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( - const std::vector& input) { - if (input.empty()) - return NULL; - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - // Importing is a little more involved than exporting, as we must first - // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key - // Info structure returned. - const uint8_t* ptr = &input[0]; - ScopedPKCS8_PRIV_KEY_INFO p8inf( - d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, input.size())); - if (!p8inf.get() || ptr != &input[0] + input.size()) - return NULL; - - scoped_ptr result(new RSAPrivateKey); - result->key_ = EVP_PKCS82PKEY(p8inf.get()); - if (!result->key_ || EVP_PKEY_id(result->key_) != EVP_PKEY_RSA) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromKey(EVP_PKEY* key) { - DCHECK(key); - if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA) - return NULL; - RSAPrivateKey* copy = new RSAPrivateKey(); - copy->key_ = EVP_PKEY_up_ref(key); - return copy; -} - -RSAPrivateKey::RSAPrivateKey() - : key_(NULL) { -} - -RSAPrivateKey::~RSAPrivateKey() { - if (key_) - EVP_PKEY_free(key_); -} - -RSAPrivateKey* RSAPrivateKey::Copy() const { - scoped_ptr copy(new RSAPrivateKey()); - ScopedRSA rsa(EVP_PKEY_get1_RSA(key_)); - if (!rsa) - return NULL; - copy->key_ = EVP_PKEY_new(); - if (!EVP_PKEY_set1_RSA(copy->key_, rsa.get())) - return NULL; - return copy.release(); -} - -bool RSAPrivateKey::ExportPrivateKey(std::vector* output) const { - return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output); -} - -bool RSAPrivateKey::ExportPublicKey(std::vector* output) const { - return ExportKey(key_, i2d_PUBKEY_bio, output); -} - -} // namespace crypto diff --git a/crypto/rsa_private_key_unittest.cc b/crypto/rsa_private_key_unittest.cc deleted file mode 100644 index 9e7f6ff51fe04..0000000000000 --- a/crypto/rsa_private_key_unittest.cc +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright (c) 2011 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/rsa_private_key.h" - -#include "base/memory/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const uint8 kTestPrivateKeyInfo[] = { - 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, - 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, - 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, - 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, - 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, - 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, - 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, - 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, - 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, - 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, - 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, - 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, - 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, - 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, - 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, - 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, - 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, - 0x37, 0xcb, 0xf2, 0x98, 0xa0, 0xce, 0xb4, 0xcb, - 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7, - 0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, - 0xed, 0xb8, 0x48, 0x8b, 0x16, 0x93, 0x36, 0x95, - 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6, - 0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, - 0x43, 0x78, 0xf9, 0xfe, 0x1f, 0x33, 0x23, 0x1e, - 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b, - 0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, - 0x86, 0xb2, 0xcb, 0x3c, 0xfe, 0x4e, 0xa1, 0xfa, - 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38, - 0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, - 0xa3, 0xf6, 0x85, 0x6b, 0x84, 0x43, 0xc9, 0x1e, - 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e, - 0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, - 0x29, 0x5c, 0xc0, 0x4f, 0x01, 0x02, 0x41, 0x00, - 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c, - 0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, - 0xcc, 0x61, 0xcd, 0x38, 0x42, 0x20, 0xd3, 0x82, - 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89, - 0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, - 0xba, 0x16, 0x1a, 0xea, 0x15, 0xc6, 0xf0, 0xb8, - 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2, - 0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, - 0x02, 0x41, 0x00, 0xc0, 0x60, 0x62, 0x80, 0xe1, - 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72, - 0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, - 0x7d, 0xd6, 0xb8, 0x31, 0x2b, 0x84, 0x7f, 0x62, - 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c, - 0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, - 0x5c, 0x09, 0x3c, 0xcf, 0x2f, 0x44, 0x9d, 0xb6, - 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b, - 0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, - 0xe2, 0x0e, 0x56, 0xca, 0x03, 0x1a, 0xc0, 0xf9, - 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda, - 0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, - 0xda, 0x55, 0x98, 0x74, 0xfc, 0x28, 0x17, 0x93, - 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae, - 0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, - 0xb8, 0x06, 0x03, 0xba, 0x08, 0x59, 0x2b, 0x17, - 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41, - 0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, - 0xa0, 0x24, 0xf5, 0xdb, 0x2f, 0xf0, 0x2f, 0xf1, - 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0, - 0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, - 0xb4, 0x14, 0xd4, 0x09, 0x91, 0x33, 0x5a, 0xfd, - 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69, - 0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, - 0xff, 0x6e, 0xeb, 0xc6, 0x86, 0xf5, 0xb4, 0xc7, - 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f, - 0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, - 0x3e, 0x70, 0x8a, 0xbf, 0x27, 0x49, 0xb0, 0x99, - 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6, - 0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, - 0xc6, 0xa4, 0x92, 0xd1, 0xce, 0x6c, 0x72, 0xfb, - 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca, - 0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, - 0xb1, 0xc5, 0x15, 0xf3 -}; - -} // namespace - -// Generate random private keys with two different sizes. Reimport, then -// export them again. We should get back the same exact bytes. -TEST(RSAPrivateKeyUnitTest, InitRandomTest) { - scoped_ptr keypair1( - crypto::RSAPrivateKey::Create(1024)); - scoped_ptr keypair2( - crypto::RSAPrivateKey::Create(2048)); - ASSERT_TRUE(keypair1.get()); - ASSERT_TRUE(keypair2.get()); - - std::vector privkey1; - std::vector privkey2; - std::vector pubkey1; - std::vector pubkey2; - - ASSERT_TRUE(keypair1->ExportPrivateKey(&privkey1)); - ASSERT_TRUE(keypair2->ExportPrivateKey(&privkey2)); - ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1)); - ASSERT_TRUE(keypair2->ExportPublicKey(&pubkey2)); - - scoped_ptr keypair3( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey1)); - scoped_ptr keypair4( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey2)); - ASSERT_TRUE(keypair3.get()); - ASSERT_TRUE(keypair4.get()); - - std::vector privkey3; - std::vector privkey4; - ASSERT_TRUE(keypair3->ExportPrivateKey(&privkey3)); - ASSERT_TRUE(keypair4->ExportPrivateKey(&privkey4)); - - ASSERT_EQ(privkey1.size(), privkey3.size()); - ASSERT_EQ(privkey2.size(), privkey4.size()); - ASSERT_TRUE(0 == memcmp(&privkey1.front(), &privkey3.front(), - privkey1.size())); - ASSERT_TRUE(0 == memcmp(&privkey2.front(), &privkey4.front(), - privkey2.size())); -} - -// Test Copy() method. -TEST(RSAPrivateKeyUnitTest, CopyTest) { - std::vector input( - kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo)); - - scoped_ptr key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); - - scoped_ptr key_copy(key->Copy()); - ASSERT_TRUE(key_copy.get()); - - std::vector privkey_copy; - ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy)); - ASSERT_EQ(input, privkey_copy); -} - -// Test that CreateFromPrivateKeyInfo fails if there is extra data after the RSA -// key. -TEST(RSAPrivateKeyUnitTest, ExtraData) { - std::vector input( - kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo)); - input.push_back(0); - - scoped_ptr key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); - - // Import should fail. - EXPECT_FALSE(key); -} - -TEST(RSAPrivateKeyUnitTest, NotRsaKey) { - // Defines a valid P-256 private key. - const uint8 kTestEcPrivateKeyInfo[] = { - 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, - 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, - 0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20, - 0x1F, 0xE3, 0x39, 0x50, 0xC5, 0xF4, 0x61, 0x12, 0x4A, 0xE9, 0x92, 0xC2, - 0xBD, 0xFD, 0xF1, 0xC7, 0x3B, 0x16, 0x15, 0xF5, 0x71, 0xBD, 0x56, 0x7E, - 0x60, 0xD1, 0x9A, 0xA1, 0xF4, 0x8C, 0xDF, 0x42, 0xA1, 0x44, 0x03, 0x42, - 0x00, 0x04, 0x7C, 0x11, 0x0C, 0x66, 0xDC, 0xFD, 0xA8, 0x07, 0xF6, 0xE6, - 0x9E, 0x45, 0xDD, 0xB3, 0xC7, 0x4F, 0x69, 0xA1, 0x48, 0x4D, 0x20, 0x3E, - 0x8D, 0xC5, 0xAD, 0xA8, 0xE9, 0xA9, 0xDD, 0x7C, 0xB3, 0xC7, 0x0D, 0xF4, - 0x48, 0x98, 0x6E, 0x51, 0xBD, 0xE5, 0xD1, 0x57, 0x6F, 0x99, 0x90, 0x1F, - 0x9C, 0x2C, 0x6A, 0x80, 0x6A, 0x47, 0xFD, 0x90, 0x76, 0x43, 0xA7, 0x2B, - 0x83, 0x55, 0x97, 0xEF, 0xC8, 0xC6 - }; - - std::vector input( - kTestEcPrivateKeyInfo, - kTestEcPrivateKeyInfo + sizeof(kTestEcPrivateKeyInfo)); - - scoped_ptr key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); - - // Import should fail as the given PKCS8 bytes were for an EC key not RSA key. - EXPECT_FALSE(key); -} - -// Verify that generated public keys look good. This test data was generated -// with the openssl command line tool. -TEST(RSAPrivateKeyUnitTest, PublicKeyTest) { - const uint8 expected_public_key_info[] = { - 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, - 0x89, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, - 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, - 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, - 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, - 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, - 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, - 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, - 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, - 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, - 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, - 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, - 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, - 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, - 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, - 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, - 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, - 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, - 0x00, 0x01 - }; - - std::vector input( - kTestPrivateKeyInfo, kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo)); - - scoped_ptr key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); - ASSERT_TRUE(key.get()); - - std::vector output; - ASSERT_TRUE(key->ExportPublicKey(&output)); - - ASSERT_TRUE( - memcmp(expected_public_key_info, &output.front(), output.size()) == 0); -} - -// These two test keys each contain an integer that has 0x00 for its most -// significant byte. When encoded as ASN.1, this byte is dropped and there are -// two interesting sub-cases. When the sign bit of the integer is set, an extra -// null byte is added back to force the encoded value to be positive. When the -// sign bit is not set, the encoded integer is just left shorter than usual. -// See also: http://code.google.com/p/chromium/issues/detail?id=14877. -// -// Before we were handling this correctly, we would see one of two failures: -// * RSAPrivateKey::CreateFromPrivateKeyInfo would return null because the -// underlying windows API failed to import the key. -// * The import would succeed, but incorrectly interpret the data. On export, -// the key would contain different values. -// -// This test case verifies these two failures modes don't occur. -TEST(RSAPrivateKeyUnitTest, ShortIntegers) { - const uint8 short_integer_with_high_bit[] = { - 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0x92, 0x59, 0x32, - 0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67, - 0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, - 0xda, 0xe1, 0xa3, 0x1e, 0x40, 0x01, 0x14, 0x5c, - 0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4, - 0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, - 0xf4, 0x53, 0x9f, 0xb8, 0xe0, 0x83, 0x93, 0xd1, - 0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f, - 0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, - 0x1f, 0xc1, 0x20, 0xb0, 0x70, 0xb2, 0x3b, 0xea, - 0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39, - 0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, - 0x12, 0xa4, 0x42, 0x26, 0x6c, 0x6e, 0x79, 0x70, - 0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81, - 0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, - 0x04, 0x58, 0xf5, 0x6b, 0xc9, 0xf1, 0xb5, 0x65, - 0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, - 0xb6, 0x59, 0x1d, 0xdc, 0x36, 0xb6, 0x60, 0x36, - 0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16, - 0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, - 0x68, 0x8f, 0xc5, 0xf8, 0xe2, 0x5d, 0xb3, 0x19, - 0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a, - 0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, - 0x30, 0x98, 0xb1, 0xf7, 0xbd, 0x14, 0x9a, 0x57, - 0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef, - 0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, - 0x54, 0x17, 0x25, 0x5b, 0x37, 0xe3, 0x35, 0x63, - 0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43, - 0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, - 0xda, 0xd7, 0x6f, 0xd2, 0x18, 0xbd, 0x39, 0xf1, - 0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e, - 0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, - 0xc1, 0x91, 0xec, 0xb8, 0x01, 0x02, 0x41, 0x00, - 0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f, - 0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, - 0x96, 0x8d, 0x22, 0x7b, 0x78, 0x73, 0xea, 0xbb, - 0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50, - 0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, - 0xa8, 0xca, 0x54, 0x41, 0xe8, 0xce, 0xbe, 0x7d, - 0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69, - 0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, - 0x02, 0x41, 0x00, 0xbd, 0x1e, 0xfe, 0x51, 0x99, - 0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c, - 0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, - 0x4c, 0xae, 0xa6, 0x41, 0x1c, 0xf0, 0x10, 0x37, - 0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d, - 0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, - 0x05, 0x98, 0x6b, 0x3d, 0x55, 0xb7, 0x6f, 0x7c, - 0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31, - 0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, - 0xa5, 0x9e, 0x12, 0xa7, 0x68, 0xa0, 0x7e, 0xdf, - 0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f, - 0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, - 0x82, 0xfe, 0x7e, 0x33, 0xb1, 0x78, 0x7f, 0x70, - 0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48, - 0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, - 0x86, 0xe5, 0xc9, 0x15, 0x88, 0x14, 0x53, 0xd8, - 0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41, - 0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, - 0xd5, 0xce, 0x8f, 0xfe, 0xbb, 0xc8, 0x5c, 0x30, - 0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89, - 0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, - 0xfd, 0x03, 0xd2, 0xdd, 0xe4, 0xf0, 0xb4, 0x20, - 0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde, - 0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, - 0xcf, 0xec, 0x8a, 0x59, 0x4a, 0x73, 0xca, 0xc5, - 0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4, - 0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, - 0xdb, 0xe5, 0x52, 0x38, 0xf9, 0x59, 0x91, 0x2d, - 0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42, - 0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, - 0x71, 0x10, 0x3a, 0xbd, 0x92, 0x8f, 0x9b, 0xa2, - 0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c, - 0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, - 0x45, 0x84, 0xb0 - }; - - const uint8 short_integer_without_high_bit[] = { - 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x9e, 0x8d, - 0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03, - 0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, - 0x85, 0x27, 0x81, 0x52, 0xf2, 0x1b, 0x3e, 0x5b, - 0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5, - 0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, - 0x92, 0x7e, 0x34, 0xcf, 0x37, 0x82, 0x48, 0x2d, - 0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a, - 0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, - 0x01, 0x00, 0x1b, 0xfe, 0x06, 0x15, 0xc6, 0xe3, - 0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb, - 0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, - 0x53, 0x78, 0x06, 0x03, 0x0d, 0x59, 0xf5, 0x20, - 0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52, - 0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, - 0x02, 0x2d, 0x49, 0xd5, 0x15, 0x5b, 0xf1, 0xd9, - 0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, - 0x95, 0x17, 0x34, 0x88, 0xf6, 0x91, 0xc7, 0x3f, - 0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84, - 0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, - 0xc5, 0x21, 0x61, 0x10, 0xa8, 0x69, 0x09, 0x1e, - 0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b, - 0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, - 0x84, 0x3e, 0xb9, 0xe5, 0xe6, 0x31, 0x0a, 0x01, - 0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6, - 0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, - 0x7b, 0xd3, 0x97, 0x5a, 0x44, 0x3a, 0xee, 0xff, - 0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a, - 0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, - 0xb3, 0xa8, 0xb2, 0xc7, 0x73, 0x25, 0x0f, 0x58, - 0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe, - 0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, - 0xe0, 0x28, 0x15, 0x02, 0x41, 0x00, 0xeb, 0x15, - 0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22, - 0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, - 0xad, 0xf4, 0x57, 0x68, 0x90, 0xb7, 0x9f, 0xe2, - 0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b, - 0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, - 0x1d, 0xb8, 0x5c, 0x96, 0xeb, 0x04, 0x08, 0xe1, - 0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1, - 0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, - 0x00, 0xd5, 0x06, 0x45, 0xd7, 0x55, 0x63, 0x1a, - 0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39, - 0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, - 0xe2, 0x5b, 0xc6, 0xd2, 0x55, 0xdd, 0xab, 0x55, - 0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73, - 0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, - 0x1d, 0xce, 0x18, 0x7f, 0xb0, 0xc8, 0x47, 0x77, - 0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94, - 0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, - 0x17, 0x44, 0x75, 0x0a, 0xf1, 0x10, 0xee, 0x1b, - 0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15, - 0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, - 0xf7, 0x27, 0xe7, 0xe8, 0x2c, 0x47, 0xf1, 0x0f, - 0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19, - 0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, - 0x0b, 0x60, 0x7f, 0x94, 0x2a, 0x80, 0x8d, 0x22, - 0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2, - 0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, - 0x05, 0xc5, 0x3c, 0x9d, 0xcf, 0x8a, 0x60, 0xc7, - 0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3, - 0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, - 0x4a, 0xd2, 0x6a, 0xbc, 0x8b, 0x62, 0x22, 0x3c, - 0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e, - 0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, - 0xb7, 0x3e, 0x91, 0x9c, 0x09, 0xf6, 0xd7, 0x02, - 0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8, - 0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, - 0x91, 0x58, 0xff, 0xf9, 0x19, 0xac, 0x3a, 0x73, - 0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9, - 0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, - 0x43, 0x9b, 0x39, 0xc8, 0x04, 0x4d, 0x2b, 0x01, - 0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43, - 0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, - 0xea, 0xbe - }; - - std::vector input1; - std::vector input2; - - input1.resize(sizeof(short_integer_with_high_bit)); - input2.resize(sizeof(short_integer_without_high_bit)); - - memcpy(&input1.front(), short_integer_with_high_bit, - sizeof(short_integer_with_high_bit)); - memcpy(&input2.front(), short_integer_without_high_bit, - sizeof(short_integer_without_high_bit)); - - scoped_ptr keypair1( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input1)); - scoped_ptr keypair2( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input2)); - ASSERT_TRUE(keypair1.get()); - ASSERT_TRUE(keypair2.get()); - - std::vector output1; - std::vector output2; - ASSERT_TRUE(keypair1->ExportPrivateKey(&output1)); - ASSERT_TRUE(keypair2->ExportPrivateKey(&output2)); - - ASSERT_EQ(input1.size(), output1.size()); - ASSERT_EQ(input2.size(), output2.size()); - ASSERT_TRUE(0 == memcmp(&output1.front(), &input1.front(), - input1.size())); - ASSERT_TRUE(0 == memcmp(&output2.front(), &input2.front(), - input2.size())); -} - -TEST(RSAPrivateKeyUnitTest, CreateFromKeyTest) { - scoped_ptr key_pair( - crypto::RSAPrivateKey::Create(512)); - ASSERT_TRUE(key_pair.get()); - - scoped_ptr key_copy( - crypto::RSAPrivateKey::CreateFromKey(key_pair->key())); - ASSERT_TRUE(key_copy.get()); - - std::vector privkey; - std::vector pubkey; - ASSERT_TRUE(key_pair->ExportPrivateKey(&privkey)); - ASSERT_TRUE(key_pair->ExportPublicKey(&pubkey)); - - std::vector privkey_copy; - std::vector pubkey_copy; - ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy)); - ASSERT_TRUE(key_copy->ExportPublicKey(&pubkey_copy)); - - ASSERT_EQ(privkey, privkey_copy); - ASSERT_EQ(pubkey, pubkey_copy); -} - diff --git a/crypto/scoped_capi_types.h b/crypto/scoped_capi_types.h deleted file mode 100644 index ac92e394b9c5d..0000000000000 --- a/crypto/scoped_capi_types.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2012 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_SCOPED_CAPI_TYPES_H_ -#define CRYPTO_SCOPED_CAPI_TYPES_H_ - -#include - -#include - -#include "base/logging.h" -#include "crypto/wincrypt_shim.h" - -namespace crypto { - -// Simple destructor for the Free family of CryptoAPI functions, such as -// CryptDestroyHash, which take only a single argument to release. -template -struct CAPIDestroyer { - void operator()(CAPIHandle handle) const { - if (handle) { - BOOL ok = Destroyer(handle); - DCHECK(ok); - } - } -}; - -// Destructor for the Close/Release family of CryptoAPI functions, which take -// a second DWORD parameter indicating flags to use when closing or releasing. -// This includes functions like CertCloseStore or CryptReleaseContext. -template -struct CAPIDestroyerWithFlags { - void operator()(CAPIHandle handle) const { - if (handle) { - BOOL ok = Destroyer(handle, flags); - DCHECK(ok); - } - } -}; - -// scoped_ptr-like class for the CryptoAPI cryptography and certificate -// handles. Because these handles are defined as integer types, and not -// pointers, the existing scoped classes, such as scoped_ptr, are insufficient. -// The semantics are the same as scoped_ptr. -template -class ScopedCAPIHandle { - public: - explicit ScopedCAPIHandle(CAPIHandle handle = NULL) : handle_(handle) {} - - ~ScopedCAPIHandle() { - reset(); - } - - void reset(CAPIHandle handle = NULL) { - if (handle_ != handle) { - FreeProc free_proc; - free_proc(handle_); - handle_ = handle; - } - } - - operator CAPIHandle() const { return handle_; } - CAPIHandle get() const { return handle_; } - - CAPIHandle* receive() { - CHECK(handle_ == NULL); - return &handle_; - } - - bool operator==(CAPIHandle handle) const { - return handle_ == handle; - } - - bool operator!=(CAPIHandle handle) const { - return handle_ != handle; - } - - void swap(ScopedCAPIHandle& b) { - CAPIHandle tmp = b.handle_; - b.handle_ = handle_; - handle_ = tmp; - } - - CAPIHandle release() { - CAPIHandle tmp = handle_; - handle_ = NULL; - return tmp; - } - - private: - CAPIHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(ScopedCAPIHandle); -}; - -template inline -bool operator==(CH h, const ScopedCAPIHandle& b) { - return h == b.get(); -} - -template inline -bool operator!=(CH h, const ScopedCAPIHandle& b) { - return h != b.get(); -} - -typedef ScopedCAPIHandle< - HCRYPTPROV, - CAPIDestroyerWithFlags > ScopedHCRYPTPROV; - -typedef ScopedCAPIHandle< - HCRYPTKEY, CAPIDestroyer > ScopedHCRYPTKEY; - -typedef ScopedCAPIHandle< - HCRYPTHASH, CAPIDestroyer > ScopedHCRYPTHASH; - -} // namespace crypto - -#endif // CRYPTO_SCOPED_CAPI_TYPES_H_ diff --git a/crypto/scoped_nss_types.h b/crypto/scoped_nss_types.h deleted file mode 100644 index fdfb83c154f8c..0000000000000 --- a/crypto/scoped_nss_types.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2012 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_SCOPED_NSS_TYPES_H_ -#define CRYPTO_SCOPED_NSS_TYPES_H_ - -#include -#include -#include -#include - -#include "base/memory/scoped_ptr.h" - -namespace crypto { - -template -struct NSSDestroyer { - typedef void AllowSelfReset; - void operator()(Type* ptr) const { - Destroyer(ptr); - } -}; - -template -struct NSSDestroyer1 { - typedef void AllowSelfReset; - void operator()(Type* ptr) const { - Destroyer(ptr, freeit); - } -}; - -// Define some convenient scopers around NSS pointers. -typedef scoped_ptr > - ScopedPK11Context; -typedef scoped_ptr > - ScopedPK11Slot; -typedef scoped_ptr > - ScopedPK11SlotList; -typedef scoped_ptr > - ScopedPK11SymKey; -typedef scoped_ptr > - ScopedSECKEYPublicKey; -typedef scoped_ptr > - ScopedSECKEYPrivateKey; -typedef scoped_ptr > - ScopedSECAlgorithmID; -typedef scoped_ptr > - ScopedSECItem; -typedef scoped_ptr > - ScopedPLArenaPool; - -} // namespace crypto - -#endif // CRYPTO_SCOPED_NSS_TYPES_H_ diff --git a/crypto/scoped_openssl_types.h b/crypto/scoped_openssl_types.h deleted file mode 100644 index 73f763271bb7c..0000000000000 --- a/crypto/scoped_openssl_types.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 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_SCOPED_OPENSSL_TYPES_H_ -#define CRYPTO_SCOPED_OPENSSL_TYPES_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/memory/scoped_ptr.h" - -namespace crypto { - -// Simplistic helper that wraps a call to a deleter function. In a C++11 world, -// this would be std::function<>. An alternative would be to re-use -// base::internal::RunnableAdapter<>, but that's far too heavy weight. -template -struct OpenSSLDestroyer { - using AllowSelfReset = void; - void operator()(Type* ptr) const { Destroyer(ptr); } -}; - -template -using ScopedOpenSSL = - scoped_ptr>; - -struct OpenSSLFree { - void operator()(uint8_t* ptr) const { OPENSSL_free(ptr); } -}; - -// Several typedefs are provided for crypto-specific primitives, for -// short-hand and prevalence. Note that OpenSSL types related to X.509 are -// intentionally not included, as crypto/ does not generally deal with -// certificates or PKI. -using ScopedBIGNUM = ScopedOpenSSL; -using ScopedEC_Key = ScopedOpenSSL; -using ScopedBIO = ScopedOpenSSL; -using ScopedDSA = ScopedOpenSSL; -using ScopedECDSA_SIG = ScopedOpenSSL; -using ScopedEC_GROUP = ScopedOpenSSL; -using ScopedEC_KEY = ScopedOpenSSL; -using ScopedEC_POINT = ScopedOpenSSL; -using ScopedEVP_MD_CTX = ScopedOpenSSL; -using ScopedEVP_PKEY = ScopedOpenSSL; -using ScopedEVP_PKEY_CTX = ScopedOpenSSL; -using ScopedRSA = ScopedOpenSSL; - -// The bytes must have been allocated with OPENSSL_malloc. -using ScopedOpenSSLBytes = scoped_ptr; - -} // namespace crypto - -#endif // CRYPTO_SCOPED_OPENSSL_TYPES_H_ diff --git a/crypto/scoped_test_nss_chromeos_user.cc b/crypto/scoped_test_nss_chromeos_user.cc deleted file mode 100644 index aec25d8dff0c3..0000000000000 --- a/crypto/scoped_test_nss_chromeos_user.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 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/scoped_test_nss_chromeos_user.h" - -#include "base/logging.h" -#include "crypto/nss_util.h" -#include "crypto/nss_util_internal.h" - -namespace crypto { - -ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( - const std::string& username_hash) - : username_hash_(username_hash), constructed_successfully_(false) { - if (!temp_dir_.CreateUniqueTempDir()) - return; - // This opens a software DB in the given folder. In production code that is in - // the home folder, but for testing the temp folder is used. - constructed_successfully_ = - InitializeNSSForChromeOSUser(username_hash, temp_dir_.path()); -} - -ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() { - if (constructed_successfully_) - CloseChromeOSUserForTesting(username_hash_); -} - -void ScopedTestNSSChromeOSUser::FinishInit() { - DCHECK(constructed_successfully_); - if (!ShouldInitializeTPMForChromeOSUser(username_hash_)) - return; - WillInitializeTPMForChromeOSUser(username_hash_); - InitializePrivateSoftwareSlotForChromeOSUser(username_hash_); -} - -} // namespace crypto diff --git a/crypto/scoped_test_nss_chromeos_user.h b/crypto/scoped_test_nss_chromeos_user.h deleted file mode 100644 index 1638517704dee..0000000000000 --- a/crypto/scoped_test_nss_chromeos_user.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 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_SCOPED_TEST_NSS_CHROMEOS_USER_H_ -#define CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_ - -#include - -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// Opens a persistent NSS software database in a temporary directory for the -// user with |username_hash|. This database will be used for both the user's -// public and private slot. -class CRYPTO_EXPORT_PRIVATE ScopedTestNSSChromeOSUser { - public: - // Opens the software database and sets the public slot for the user. The - // private slot will not be initialized until FinishInit() is called. - explicit ScopedTestNSSChromeOSUser(const std::string& username_hash); - ~ScopedTestNSSChromeOSUser(); - - std::string username_hash() const { return username_hash_; } - bool constructed_successfully() const { return constructed_successfully_; } - - // Completes initialization of user. Causes any waiting private slot callbacks - // to run, see GetPrivateSlotForChromeOSUser(). - void FinishInit(); - - private: - const std::string username_hash_; - base::ScopedTempDir temp_dir_; - bool constructed_successfully_; - - DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser); -}; - -} // namespace crypto - -#endif // CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_ diff --git a/crypto/scoped_test_nss_db.cc b/crypto/scoped_test_nss_db.cc deleted file mode 100644 index 452c26d73e505..0000000000000 --- a/crypto/scoped_test_nss_db.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 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/scoped_test_nss_db.h" - -#include "base/logging.h" -#include "base/threading/thread_restrictions.h" -#include "crypto/nss_util.h" -#include "crypto/nss_util_internal.h" - -namespace crypto { - -ScopedTestNSSDB::ScopedTestNSSDB() { - EnsureNSSInit(); - // NSS is allowed to do IO on the current thread since dispatching - // to a dedicated thread would still have the affect of blocking - // the current thread, due to NSS's internal locking requirements - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (!temp_dir_.CreateUniqueTempDir()) - return; - - const char kTestDescription[] = "Test DB"; - slot_ = OpenSoftwareNSSDB(temp_dir_.path(), kTestDescription); -} - -ScopedTestNSSDB::~ScopedTestNSSDB() { - // Don't close when NSS is < 3.15.1, because it would require an additional - // sleep for 1 second after closing the database, due to - // http://bugzil.la/875601. - if (!NSS_VersionCheck("3.15.1")) { - LOG(ERROR) << "NSS version is < 3.15.1, test DB will not be closed."; - temp_dir_.Take(); - return; - } - - // NSS is allowed to do IO on the current thread since dispatching - // to a dedicated thread would still have the affect of blocking - // the current thread, due to NSS's internal locking requirements - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (slot_) { - SECStatus status = SECMOD_CloseUserDB(slot_.get()); - if (status != SECSuccess) - PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); - } - - if (!temp_dir_.Delete()) - LOG(ERROR) << "Could not delete temporary directory."; -} - -} // namespace crypto diff --git a/crypto/scoped_test_nss_db.h b/crypto/scoped_test_nss_db.h deleted file mode 100644 index 88c2d55dbe4ed..0000000000000 --- a/crypto/scoped_test_nss_db.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 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_SCOPED_TEST_NSS_DB_H_ -#define CRYPTO_SCOPED_TEST_NSS_DB_H_ - -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "crypto/crypto_export.h" -#include "crypto/scoped_nss_types.h" - -namespace crypto { - -// Opens a persistent NSS database in a temporary directory. -// Prior NSS version 3.15.1, because of http://bugzil.la/875601 , the opened DB -// will not be closed automatically. -class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB { - public: - ScopedTestNSSDB(); - ~ScopedTestNSSDB(); - - bool is_open() const { return slot_; } - PK11SlotInfo* slot() const { return slot_.get(); } - - private: - base::ScopedTempDir temp_dir_; - ScopedPK11Slot slot_; - - DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB); -}; - -} // namespace crypto - -#endif // CRYPTO_SCOPED_TEST_NSS_DB_H_ diff --git a/crypto/scoped_test_system_nss_key_slot.cc b/crypto/scoped_test_system_nss_key_slot.cc deleted file mode 100644 index 53fbbffc1a99f..0000000000000 --- a/crypto/scoped_test_system_nss_key_slot.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 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/scoped_test_system_nss_key_slot.h" - -#include "crypto/nss_util_internal.h" -#include "crypto/scoped_test_nss_db.h" - -namespace crypto { - -ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot() - : test_db_(new ScopedTestNSSDB) { - if (!test_db_->is_open()) - return; - SetSystemKeySlotForTesting( - ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot()))); -} - -ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() { - SetSystemKeySlotForTesting(ScopedPK11Slot()); -} - -bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const { - return test_db_->is_open(); -} - -PK11SlotInfo* ScopedTestSystemNSSKeySlot::slot() const { - return test_db_->slot(); -} - -} // namespace crypto diff --git a/crypto/scoped_test_system_nss_key_slot.h b/crypto/scoped_test_system_nss_key_slot.h deleted file mode 100644 index ac3b72c4ce0bd..0000000000000 --- a/crypto/scoped_test_system_nss_key_slot.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 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_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ -#define CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "crypto/crypto_export.h" - -// Forward declaration, from -typedef struct PK11SlotInfoStr PK11SlotInfo; - -namespace crypto { - -class ScopedTestNSSDB; - -// Opens a persistent NSS software database in a temporary directory and sets -// the test system slot to the opened database. This helper should be created in -// tests to fake the system token that is usually provided by the Chaps module. -// |slot| is exposed through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will -// return true. -// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization, -// does not have to be called if this helper is used. -// At most one instance of this helper must be used at a time. -class CRYPTO_EXPORT_PRIVATE ScopedTestSystemNSSKeySlot { - public: - explicit ScopedTestSystemNSSKeySlot(); - ~ScopedTestSystemNSSKeySlot(); - - bool ConstructedSuccessfully() const; - PK11SlotInfo* slot() const; - - private: - scoped_ptr test_db_; - - DISALLOW_COPY_AND_ASSIGN(ScopedTestSystemNSSKeySlot); -}; - -} // namespace crypto - -#endif // CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ diff --git a/crypto/secure_hash.h b/crypto/secure_hash.h deleted file mode 100644 index 23349b0be008f..0000000000000 --- a/crypto/secure_hash.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2012 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_SECURE_HASH_H_ -#define CRYPTO_SECURE_HASH_H_ - -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -namespace base { -class Pickle; -class PickleIterator; -} - -namespace crypto { - -// A wrapper to calculate secure hashes incrementally, allowing to -// be used when the full input is not known in advance. -class CRYPTO_EXPORT SecureHash { - public: - enum Algorithm { - SHA256, - }; - virtual ~SecureHash() {} - - static SecureHash* Create(Algorithm type); - - virtual void Update(const void* input, size_t len) = 0; - virtual void Finish(void* output, size_t len) = 0; - - // Serialize the context, so it can be restored at a later time. - // |pickle| will contain the serialized data. - // Returns whether or not |pickle| was filled. - virtual bool Serialize(base::Pickle* pickle) = 0; - - // Restore the context that was saved earlier. - // |data_iterator| allows this to be used as part of a larger pickle. - // |pickle| holds the saved data. - // Returns success or failure. - virtual bool Deserialize(base::PickleIterator* data_iterator) = 0; - - protected: - SecureHash() {} - - private: - DISALLOW_COPY_AND_ASSIGN(SecureHash); -}; - -} // namespace crypto - -#endif // CRYPTO_SECURE_HASH_H_ diff --git a/crypto/secure_hash_default.cc b/crypto/secure_hash_default.cc deleted file mode 100644 index 739b402b6c199..0000000000000 --- a/crypto/secure_hash_default.cc +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2012 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/secure_hash.h" - -#include "base/logging.h" -#include "base/pickle.h" -#include "crypto/third_party/nss/chromium-blapi.h" -#include "crypto/third_party/nss/chromium-sha256.h" - -namespace crypto { - -namespace { - -const char kSHA256Descriptor[] = "NSS"; - -class SecureHashSHA256NSS : public SecureHash { - public: - static const int kSecureHashVersion = 1; - - SecureHashSHA256NSS() { - SHA256_Begin(&ctx_); - } - - ~SecureHashSHA256NSS() override { memset(&ctx_, 0, sizeof(ctx_)); } - - // SecureHash implementation: - void Update(const void* input, size_t len) override { - SHA256_Update(&ctx_, static_cast(input), len); - } - - void Finish(void* output, size_t len) override { - SHA256_End(&ctx_, static_cast(output), NULL, - static_cast(len)); - } - - bool Serialize(base::Pickle* pickle) override; - bool Deserialize(base::PickleIterator* data_iterator) override; - - private: - SHA256Context ctx_; -}; - -bool SecureHashSHA256NSS::Serialize(base::Pickle* pickle) { - if (!pickle) - return false; - - if (!pickle->WriteInt(kSecureHashVersion) || - !pickle->WriteString(kSHA256Descriptor) || - !pickle->WriteBytes(&ctx_, sizeof(ctx_))) { - return false; - } - - return true; -} - -bool SecureHashSHA256NSS::Deserialize(base::PickleIterator* data_iterator) { - int version; - if (!data_iterator->ReadInt(&version)) - return false; - - if (version > kSecureHashVersion) - return false; // We don't know how to deal with this. - - std::string type; - if (!data_iterator->ReadString(&type)) - return false; - - if (type != kSHA256Descriptor) - return false; // It's the wrong kind. - - const char* data = NULL; - if (!data_iterator->ReadBytes(&data, sizeof(ctx_))) - return false; - - memcpy(&ctx_, data, sizeof(ctx_)); - - return true; -} - -} // namespace - -SecureHash* SecureHash::Create(Algorithm algorithm) { - switch (algorithm) { - case SHA256: - return new SecureHashSHA256NSS(); - default: - NOTIMPLEMENTED(); - return NULL; - } -} - -} // namespace crypto diff --git a/crypto/secure_hash_openssl.cc b/crypto/secure_hash_openssl.cc deleted file mode 100644 index 1033b8e25eb82..0000000000000 --- a/crypto/secure_hash_openssl.cc +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2012 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/secure_hash.h" - -#include -#include - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/pickle.h" -#include "crypto/openssl_util.h" - -namespace crypto { - -namespace { - -const char kSHA256Descriptor[] = "OpenSSL"; - -class SecureHashSHA256OpenSSL : public SecureHash { - public: - static const int kSecureHashVersion = 1; - - SecureHashSHA256OpenSSL() { - SHA256_Init(&ctx_); - } - - ~SecureHashSHA256OpenSSL() override { - OPENSSL_cleanse(&ctx_, sizeof(ctx_)); - } - - void Update(const void* input, size_t len) override { - SHA256_Update(&ctx_, static_cast(input), len); - } - - void Finish(void* output, size_t len) override { - ScopedOpenSSLSafeSizeBuffer result( - static_cast(output), len); - SHA256_Final(result.safe_buffer(), &ctx_); - } - - bool Serialize(base::Pickle* pickle) override; - bool Deserialize(base::PickleIterator* data_iterator) override; - - private: - SHA256_CTX ctx_; -}; - -bool SecureHashSHA256OpenSSL::Serialize(base::Pickle* pickle) { - if (!pickle) - return false; - - if (!pickle->WriteInt(kSecureHashVersion) || - !pickle->WriteString(kSHA256Descriptor) || - !pickle->WriteBytes(&ctx_, sizeof(ctx_))) { - return false; - } - - return true; -} - -bool SecureHashSHA256OpenSSL::Deserialize(base::PickleIterator* data_iterator) { - if (!data_iterator) - return false; - - int version; - if (!data_iterator->ReadInt(&version)) - return false; - - if (version > kSecureHashVersion) - return false; // We don't know how to deal with this. - - std::string type; - if (!data_iterator->ReadString(&type)) - return false; - - if (type != kSHA256Descriptor) - return false; // It's the wrong kind. - - const char* data = NULL; - if (!data_iterator->ReadBytes(&data, sizeof(ctx_))) - return false; - - memcpy(&ctx_, data, sizeof(ctx_)); - - return true; -} - -} // namespace - -SecureHash* SecureHash::Create(Algorithm algorithm) { - switch (algorithm) { - case SHA256: - return new SecureHashSHA256OpenSSL(); - default: - NOTIMPLEMENTED(); - return NULL; - } -} - -} // namespace crypto diff --git a/crypto/secure_hash_unittest.cc b/crypto/secure_hash_unittest.cc deleted file mode 100644 index facf476e0afa5..0000000000000 --- a/crypto/secure_hash_unittest.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2012 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/secure_hash.h" - -#include - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/pickle.h" -#include "crypto/sha2.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(SecureHashTest, TestUpdate) { - // Example B.3 from FIPS 180-2: long message. - std::string input3(500000, 'a'); // 'a' repeated half a million times - int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c, - 0x99, 0x14, 0xfb, 0x92, - 0x81, 0xa1, 0xc7, 0xe2, - 0x84, 0xd7, 0x3e, 0x67, - 0xf1, 0x80, 0x9a, 0x48, - 0xa4, 0x97, 0x20, 0x0e, - 0x04, 0x6d, 0x39, 0xcc, - 0xc7, 0x11, 0x2c, 0xd0 }; - - uint8 output3[crypto::kSHA256Length]; - - scoped_ptr ctx(crypto::SecureHash::Create( - crypto::SecureHash::SHA256)); - ctx->Update(input3.data(), input3.size()); - ctx->Update(input3.data(), input3.size()); - - ctx->Finish(output3, sizeof(output3)); - for (size_t i = 0; i < crypto::kSHA256Length; i++) - EXPECT_EQ(expected3[i], static_cast(output3[i])); -} - -// Save the crypto state mid-stream, and create another instance with the -// saved state. Then feed the same data afterwards to both. -// When done, both should have the same hash value. -TEST(SecureHashTest, TestSerialization) { - std::string input1(10001, 'a'); // 'a' repeated 10001 times - std::string input2(10001, 'b'); // 'b' repeated 10001 times - std::string input3(10001, 'c'); // 'c' repeated 10001 times - std::string input4(10001, 'd'); // 'd' repeated 10001 times - std::string input5(10001, 'e'); // 'e' repeated 10001 times - - uint8 output1[crypto::kSHA256Length]; - uint8 output2[crypto::kSHA256Length]; - - scoped_ptr ctx1(crypto::SecureHash::Create( - crypto::SecureHash::SHA256)); - scoped_ptr ctx2(crypto::SecureHash::Create( - crypto::SecureHash::SHA256)); - base::Pickle pickle; - ctx1->Update(input1.data(), input1.size()); - ctx1->Update(input2.data(), input2.size()); - ctx1->Update(input3.data(), input3.size()); - - EXPECT_TRUE(ctx1->Serialize(&pickle)); - ctx1->Update(input4.data(), input4.size()); - ctx1->Update(input5.data(), input5.size()); - - ctx1->Finish(output1, sizeof(output1)); - - base::PickleIterator data_iterator(pickle); - EXPECT_TRUE(ctx2->Deserialize(&data_iterator)); - ctx2->Update(input4.data(), input4.size()); - ctx2->Update(input5.data(), input5.size()); - - ctx2->Finish(output2, sizeof(output2)); - - EXPECT_EQ(0, memcmp(output1, output2, crypto::kSHA256Length)); -} diff --git a/crypto/secure_util.cc b/crypto/secure_util.cc deleted file mode 100644 index 3fe8aa961a027..0000000000000 --- a/crypto/secure_util.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2011 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/secure_util.h" - -namespace crypto { - -bool SecureMemEqual(const void* s1, const void* s2, size_t n) { - const unsigned char* s1_ptr = reinterpret_cast(s1); - const unsigned char* s2_ptr = reinterpret_cast(s2); - unsigned char tmp = 0; - for (size_t i = 0; i < n; ++i, ++s1_ptr, ++s2_ptr) - tmp |= *s1_ptr ^ *s2_ptr; - return (tmp == 0); -} - -} // namespace crypto - diff --git a/crypto/secure_util.h b/crypto/secure_util.h deleted file mode 100644 index cfe05ca15540b..0000000000000 --- a/crypto/secure_util.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012 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_SECURE_UTIL_H_ -#define CRYPTO_SECURE_UTIL_H_ - -#include - -#include "crypto/crypto_export.h" - -namespace crypto { - -// Performs a constant-time comparison of two strings, returning true if the -// strings are equal. -// -// For cryptographic operations, comparison functions such as memcmp() may -// expose side-channel information about input, allowing an attacker to -// perform timing analysis to determine what the expected bits should be. In -// order to avoid such attacks, the comparison must execute in constant time, -// so as to not to reveal to the attacker where the difference(s) are. -// For an example attack, see -// http://groups.google.com/group/keyczar-discuss/browse_thread/thread/5571eca0948b2a13 -CRYPTO_EXPORT bool SecureMemEqual(const void* s1, const void* s2, size_t n); - -} // namespace crypto - -#endif // CRYPTO_SECURE_UTIL_H_ - diff --git a/crypto/sha2.cc b/crypto/sha2.cc deleted file mode 100644 index 6f362379618f1..0000000000000 --- a/crypto/sha2.cc +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2012 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/sha2.h" - -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "crypto/secure_hash.h" - -namespace crypto { - -void SHA256HashString(const base::StringPiece& str, void* output, size_t len) { - scoped_ptr ctx(SecureHash::Create(SecureHash::SHA256)); - ctx->Update(str.data(), str.length()); - ctx->Finish(output, len); -} - -std::string SHA256HashString(const base::StringPiece& str) { - std::string output(kSHA256Length, 0); - SHA256HashString(str, string_as_array(&output), output.size()); - return output; -} - -} // namespace crypto diff --git a/crypto/sha2.h b/crypto/sha2.h deleted file mode 100644 index 7e279d3e94383..0000000000000 --- a/crypto/sha2.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2012 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_SHA2_H_ -#define CRYPTO_SHA2_H_ - -#include - -#include "base/strings/string_piece.h" -#include "crypto/crypto_export.h" - -namespace crypto { - -// These functions perform SHA-256 operations. -// -// Functions for SHA-384 and SHA-512 can be added when the need arises. - -static const size_t kSHA256Length = 32; // Length in bytes of a SHA-256 hash. - -// Computes the SHA-256 hash of the input string 'str' and stores the first -// 'len' bytes of the hash in the output buffer 'output'. If 'len' > 32, -// only 32 bytes (the full hash) are stored in the 'output' buffer. -CRYPTO_EXPORT void SHA256HashString(const base::StringPiece& str, - void* output, size_t len); - -// Convenience version of the above that returns the result in a 32-byte -// string. -CRYPTO_EXPORT std::string SHA256HashString(const base::StringPiece& str); - -} // namespace crypto - -#endif // CRYPTO_SHA2_H_ diff --git a/crypto/sha2_unittest.cc b/crypto/sha2_unittest.cc deleted file mode 100644 index 78da1360d4daa..0000000000000 --- a/crypto/sha2_unittest.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2011 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/sha2.h" - -#include "base/basictypes.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(Sha256Test, Test1) { - // Example B.1 from FIPS 180-2: one-block message. - std::string input1 = "abc"; - int expected1[] = { 0xba, 0x78, 0x16, 0xbf, - 0x8f, 0x01, 0xcf, 0xea, - 0x41, 0x41, 0x40, 0xde, - 0x5d, 0xae, 0x22, 0x23, - 0xb0, 0x03, 0x61, 0xa3, - 0x96, 0x17, 0x7a, 0x9c, - 0xb4, 0x10, 0xff, 0x61, - 0xf2, 0x00, 0x15, 0xad }; - - uint8 output1[crypto::kSHA256Length]; - crypto::SHA256HashString(input1, output1, sizeof(output1)); - for (size_t i = 0; i < crypto::kSHA256Length; i++) - EXPECT_EQ(expected1[i], static_cast(output1[i])); - - uint8 output_truncated1[4]; // 4 bytes == 32 bits - crypto::SHA256HashString(input1, - output_truncated1, sizeof(output_truncated1)); - for (size_t i = 0; i < sizeof(output_truncated1); i++) - EXPECT_EQ(expected1[i], static_cast(output_truncated1[i])); -} - -TEST(Sha256Test, Test1_String) { - // Same as the above, but using the wrapper that returns a std::string. - // Example B.1 from FIPS 180-2: one-block message. - std::string input1 = "abc"; - int expected1[] = { 0xba, 0x78, 0x16, 0xbf, - 0x8f, 0x01, 0xcf, 0xea, - 0x41, 0x41, 0x40, 0xde, - 0x5d, 0xae, 0x22, 0x23, - 0xb0, 0x03, 0x61, 0xa3, - 0x96, 0x17, 0x7a, 0x9c, - 0xb4, 0x10, 0xff, 0x61, - 0xf2, 0x00, 0x15, 0xad }; - - std::string output1 = crypto::SHA256HashString(input1); - ASSERT_EQ(crypto::kSHA256Length, output1.size()); - for (size_t i = 0; i < crypto::kSHA256Length; i++) - EXPECT_EQ(expected1[i], static_cast(output1[i])); -} - -TEST(Sha256Test, Test2) { - // Example B.2 from FIPS 180-2: multi-block message. - std::string input2 = - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - int expected2[] = { 0x24, 0x8d, 0x6a, 0x61, - 0xd2, 0x06, 0x38, 0xb8, - 0xe5, 0xc0, 0x26, 0x93, - 0x0c, 0x3e, 0x60, 0x39, - 0xa3, 0x3c, 0xe4, 0x59, - 0x64, 0xff, 0x21, 0x67, - 0xf6, 0xec, 0xed, 0xd4, - 0x19, 0xdb, 0x06, 0xc1 }; - - uint8 output2[crypto::kSHA256Length]; - crypto::SHA256HashString(input2, output2, sizeof(output2)); - for (size_t i = 0; i < crypto::kSHA256Length; i++) - EXPECT_EQ(expected2[i], static_cast(output2[i])); - - uint8 output_truncated2[6]; - crypto::SHA256HashString(input2, - output_truncated2, sizeof(output_truncated2)); - for (size_t i = 0; i < sizeof(output_truncated2); i++) - EXPECT_EQ(expected2[i], static_cast(output_truncated2[i])); -} - -TEST(Sha256Test, Test3) { - // Example B.3 from FIPS 180-2: long message. - std::string input3(1000000, 'a'); // 'a' repeated a million times - int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c, - 0x99, 0x14, 0xfb, 0x92, - 0x81, 0xa1, 0xc7, 0xe2, - 0x84, 0xd7, 0x3e, 0x67, - 0xf1, 0x80, 0x9a, 0x48, - 0xa4, 0x97, 0x20, 0x0e, - 0x04, 0x6d, 0x39, 0xcc, - 0xc7, 0x11, 0x2c, 0xd0 }; - - uint8 output3[crypto::kSHA256Length]; - crypto::SHA256HashString(input3, output3, sizeof(output3)); - for (size_t i = 0; i < crypto::kSHA256Length; i++) - EXPECT_EQ(expected3[i], static_cast(output3[i])); - - uint8 output_truncated3[12]; - crypto::SHA256HashString(input3, - output_truncated3, sizeof(output_truncated3)); - for (size_t i = 0; i < sizeof(output_truncated3); i++) - EXPECT_EQ(expected3[i], static_cast(output_truncated3[i])); -} diff --git a/crypto/signature_creator.h b/crypto/signature_creator.h deleted file mode 100644 index ab9d2c1a21b58..0000000000000 --- a/crypto/signature_creator.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2012 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_SIGNATURE_CREATOR_H_ -#define CRYPTO_SIGNATURE_CREATOR_H_ - -#include - -#include "build/build_config.h" -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -#if defined(USE_OPENSSL) -// Forward declaration for openssl/*.h -typedef struct env_md_ctx_st EVP_MD_CTX; -#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) -// Forward declaration. -struct SGNContextStr; -#endif - -namespace crypto { - -class RSAPrivateKey; - -// Signs data using a bare private key (as opposed to a full certificate). -// Currently can only sign data using SHA-1 or SHA-256 with RSA PKCS#1v1.5. -class CRYPTO_EXPORT SignatureCreator { - public: - // The set of supported hash functions. Extend as required. - enum HashAlgorithm { - SHA1, - SHA256, - }; - - ~SignatureCreator(); - - // Create an instance. The caller must ensure that the provided PrivateKey - // instance outlives the created SignatureCreator. Uses the HashAlgorithm - // specified. - static SignatureCreator* Create(RSAPrivateKey* key, HashAlgorithm hash_alg); - - - // Signs the precomputed |hash_alg| digest |data| using private |key| as - // specified in PKCS #1 v1.5. - static bool Sign(RSAPrivateKey* key, - HashAlgorithm hash_alg, - const uint8* data, - int data_len, - std::vector* signature); - - // Update the signature with more data. - bool Update(const uint8* data_part, int data_part_len); - - // Finalize the signature. - bool Final(std::vector* signature); - - private: - // Private constructor. Use the Create() method instead. - SignatureCreator(); - -#if defined(USE_OPENSSL) - EVP_MD_CTX* sign_context_; -#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) - SGNContextStr* sign_context_; -#endif - - DISALLOW_COPY_AND_ASSIGN(SignatureCreator); -}; - -} // namespace crypto - -#endif // CRYPTO_SIGNATURE_CREATOR_H_ diff --git a/crypto/signature_creator_nss.cc b/crypto/signature_creator_nss.cc deleted file mode 100644 index da03312881dbb..0000000000000 --- a/crypto/signature_creator_nss.cc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2012 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/signature_creator.h" - -#include -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "crypto/nss_util.h" -#include "crypto/rsa_private_key.h" - -namespace crypto { - -namespace { - -SECOidTag ToNSSSigOid(SignatureCreator::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureCreator::SHA1: - return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; - case SignatureCreator::SHA256: - return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; - } - return SEC_OID_UNKNOWN; -} - -SECOidTag ToNSSHashOid(SignatureCreator::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureCreator::SHA1: - return SEC_OID_SHA1; - case SignatureCreator::SHA256: - return SEC_OID_SHA256; - } - return SEC_OID_UNKNOWN; -} - -} // namespace - -SignatureCreator::~SignatureCreator() { - if (sign_context_) { - SGN_DestroyContext(sign_context_, PR_TRUE); - sign_context_ = NULL; - } -} - -// static -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, - HashAlgorithm hash_alg) { - scoped_ptr result(new SignatureCreator); - result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key()); - if (!result->sign_context_) { - NOTREACHED(); - return NULL; - } - - SECStatus rv = SGN_Begin(result->sign_context_); - if (rv != SECSuccess) { - NOTREACHED(); - return NULL; - } - - return result.release(); -} - -// static -bool SignatureCreator::Sign(RSAPrivateKey* key, - HashAlgorithm hash_alg, - const uint8* data, - int data_len, - std::vector* signature) { - SECItem data_item; - data_item.type = siBuffer; - data_item.data = const_cast(data); - data_item.len = data_len; - - SECItem signature_item; - SECStatus rv = SGN_Digest(key->key(), ToNSSHashOid(hash_alg), &signature_item, - &data_item); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - signature->assign(signature_item.data, - signature_item.data + signature_item.len); - SECITEM_FreeItem(&signature_item, PR_FALSE); - return true; -} - -bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { - SECStatus rv = SGN_Update(sign_context_, data_part, data_part_len); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - - return true; -} - -bool SignatureCreator::Final(std::vector* signature) { - SECItem signature_item; - SECStatus rv = SGN_End(sign_context_, &signature_item); - if (rv != SECSuccess) { - return false; - } - signature->assign(signature_item.data, - signature_item.data + signature_item.len); - SECITEM_FreeItem(&signature_item, PR_FALSE); - return true; -} - -SignatureCreator::SignatureCreator() : sign_context_(NULL) { - EnsureNSSInit(); -} - -} // namespace crypto diff --git a/crypto/signature_creator_openssl.cc b/crypto/signature_creator_openssl.cc deleted file mode 100644 index 0d90d50044da8..0000000000000 --- a/crypto/signature_creator_openssl.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2012 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/signature_creator.h" - -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "crypto/openssl_util.h" -#include "crypto/rsa_private_key.h" -#include "crypto/scoped_openssl_types.h" - -namespace crypto { - -namespace { - -const EVP_MD* ToOpenSSLDigest(SignatureCreator::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureCreator::SHA1: - return EVP_sha1(); - case SignatureCreator::SHA256: - return EVP_sha256(); - } - return NULL; -} - -int ToOpenSSLDigestType(SignatureCreator::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureCreator::SHA1: - return NID_sha1; - case SignatureCreator::SHA256: - return NID_sha256; - } - return NID_undef; -} - -} // namespace - -// static -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, - HashAlgorithm hash_alg) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - scoped_ptr result(new SignatureCreator); - const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); - DCHECK(digest); - if (!digest) { - return NULL; - } - if (!EVP_DigestSignInit(result->sign_context_, NULL, digest, NULL, - key->key())) { - return NULL; - } - return result.release(); -} - -// static -bool SignatureCreator::Sign(RSAPrivateKey* key, - HashAlgorithm hash_alg, - const uint8* data, - int data_len, - std::vector* signature) { - ScopedRSA rsa_key(EVP_PKEY_get1_RSA(key->key())); - if (!rsa_key) - return false; - signature->resize(RSA_size(rsa_key.get())); - - unsigned int len = 0; - if (!RSA_sign(ToOpenSSLDigestType(hash_alg), data, data_len, - vector_as_array(signature), &len, rsa_key.get())) { - signature->clear(); - return false; - } - signature->resize(len); - return true; -} - -SignatureCreator::SignatureCreator() - : sign_context_(EVP_MD_CTX_create()) { -} - -SignatureCreator::~SignatureCreator() { - EVP_MD_CTX_destroy(sign_context_); -} - -bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - return !!EVP_DigestSignUpdate(sign_context_, data_part, data_part_len); -} - -bool SignatureCreator::Final(std::vector* signature) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - - // Determine the maximum length of the signature. - size_t len = 0; - if (!EVP_DigestSignFinal(sign_context_, NULL, &len)) { - signature->clear(); - return false; - } - signature->resize(len); - - // Sign it. - if (!EVP_DigestSignFinal(sign_context_, vector_as_array(signature), &len)) { - signature->clear(); - return false; - } - signature->resize(len); - return true; -} - -} // namespace crypto diff --git a/crypto/signature_creator_unittest.cc b/crypto/signature_creator_unittest.cc deleted file mode 100644 index 694becdcb4475..0000000000000 --- a/crypto/signature_creator_unittest.cc +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2012 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 - -#include "base/memory/scoped_ptr.h" -#include "base/sha1.h" -#include "crypto/rsa_private_key.h" -#include "crypto/sha2.h" -#include "crypto/signature_creator.h" -#include "crypto/signature_verifier.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -// This is the algorithm ID for SHA-1 with RSA encryption. -const uint8 kSHA1WithRSAAlgorithmID[] = { - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00 -}; - -// This is the algorithm ID for SHA-1 with RSA encryption. -const uint8 kSHA256WithRSAAlgorithmID[] = { - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x0B, 0x05, 0x00 -}; - -} - -TEST(SignatureCreatorTest, BasicTest) { - // Do a verify round trip. - scoped_ptr key_original( - crypto::RSAPrivateKey::Create(1024)); - ASSERT_TRUE(key_original.get()); - - std::vector key_info; - key_original->ExportPrivateKey(&key_info); - scoped_ptr key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info)); - ASSERT_TRUE(key.get()); - - scoped_ptr signer( - crypto::SignatureCreator::Create(key.get(), - crypto::SignatureCreator::SHA1)); - ASSERT_TRUE(signer.get()); - - std::string data("Hello, World!"); - ASSERT_TRUE(signer->Update(reinterpret_cast(data.c_str()), - data.size())); - - std::vector signature; - ASSERT_TRUE(signer->Final(&signature)); - - std::vector public_key_info; - ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); - - crypto::SignatureVerifier verifier; - ASSERT_TRUE(verifier.VerifyInit( - kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID), - &signature.front(), signature.size(), - &public_key_info.front(), public_key_info.size())); - - verifier.VerifyUpdate(reinterpret_cast(data.c_str()), - data.size()); - ASSERT_TRUE(verifier.VerifyFinal()); -} - -TEST(SignatureCreatorTest, SignDigestTest) { - // Do a verify round trip. - scoped_ptr key_original( - crypto::RSAPrivateKey::Create(1024)); - ASSERT_TRUE(key_original.get()); - - std::vector key_info; - key_original->ExportPrivateKey(&key_info); - scoped_ptr key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info)); - ASSERT_TRUE(key.get()); - - std::string data("Hello, World!"); - std::string sha1 = base::SHA1HashString(data); - // Sign sha1 of the input data. - std::vector signature; - ASSERT_TRUE(crypto::SignatureCreator::Sign( - key.get(), - crypto::SignatureCreator::SHA1, - reinterpret_cast(sha1.c_str()), - sha1.size(), - &signature)); - - std::vector public_key_info; - ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); - - // Verify the input data. - crypto::SignatureVerifier verifier; - ASSERT_TRUE(verifier.VerifyInit( - kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID), - &signature.front(), signature.size(), - &public_key_info.front(), public_key_info.size())); - - verifier.VerifyUpdate(reinterpret_cast(data.c_str()), - data.size()); - ASSERT_TRUE(verifier.VerifyFinal()); -} - -TEST(SignatureCreatorTest, SignSHA256DigestTest) { - // Do a verify round trip. - scoped_ptr key_original( - crypto::RSAPrivateKey::Create(1024)); - ASSERT_TRUE(key_original.get()); - - std::vector key_info; - key_original->ExportPrivateKey(&key_info); - scoped_ptr key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info)); - ASSERT_TRUE(key.get()); - - std::string data("Hello, World!"); - std::string sha256 = crypto::SHA256HashString(data); - // Sign sha256 of the input data. - std::vector signature; - ASSERT_TRUE(crypto::SignatureCreator::Sign( - key.get(), - crypto::SignatureCreator::HashAlgorithm::SHA256, - reinterpret_cast(sha256.c_str()), - sha256.size(), - &signature)); - - std::vector public_key_info; - ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); - - // Verify the input data. - crypto::SignatureVerifier verifier; - ASSERT_TRUE(verifier.VerifyInit( - kSHA256WithRSAAlgorithmID, sizeof(kSHA256WithRSAAlgorithmID), - &signature.front(), signature.size(), - &public_key_info.front(), public_key_info.size())); - - verifier.VerifyUpdate(reinterpret_cast(data.c_str()), - data.size()); - ASSERT_TRUE(verifier.VerifyFinal()); -} diff --git a/crypto/signature_verifier.h b/crypto/signature_verifier.h deleted file mode 100644 index fbf87d4cc64d8..0000000000000 --- a/crypto/signature_verifier.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2012 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_SIGNATURE_VERIFIER_H_ -#define CRYPTO_SIGNATURE_VERIFIER_H_ - -#include - -#include "build/build_config.h" -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -#if defined(USE_OPENSSL) -typedef struct env_md_st EVP_MD; -typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; -#else -typedef struct HASHContextStr HASHContext; -typedef struct SECKEYPublicKeyStr SECKEYPublicKey; -typedef struct VFYContextStr VFYContext; -#endif - -namespace crypto { - -// The SignatureVerifier class verifies a signature using a bare public key -// (as opposed to a certificate). -class CRYPTO_EXPORT SignatureVerifier { - public: - // The set of supported hash functions. Extend as required. - enum HashAlgorithm { - SHA1, - SHA256, - }; - - SignatureVerifier(); - ~SignatureVerifier(); - - // Streaming interface: - - // Initiates a signature verification operation. This should be followed - // by one or more VerifyUpdate calls and a VerifyFinal call. - // NOTE: for RSA-PSS signatures, use VerifyInitRSAPSS instead. - // - // The signature algorithm is specified as a DER encoded ASN.1 - // AlgorithmIdentifier structure: - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - // - // The signature is encoded according to the signature algorithm, but it - // must not be further encoded in an ASN.1 BIT STRING. - // Note: An RSA signature is actually a big integer. It must be in - // big-endian byte order. - // - // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo - // structure, which contains not only the public key but also its type - // (algorithm): - // SubjectPublicKeyInfo ::= SEQUENCE { - // algorithm AlgorithmIdentifier, - // subjectPublicKey BIT STRING } - bool VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len); - - // Initiates a RSA-PSS signature verification operation. This should be - // followed by one or more VerifyUpdate calls and a VerifyFinal call. - // - // The RSA-PSS signature algorithm parameters are specified with the - // |hash_alg|, |mask_hash_alg|, and |salt_len| arguments. - // - // An RSA-PSS signature is a nonnegative integer encoded as a byte string - // (of the same length as the RSA modulus) in big-endian byte order. It - // must not be further encoded in an ASN.1 BIT STRING. - // - // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo - // structure, which contains not only the public key but also its type - // (algorithm): - // SubjectPublicKeyInfo ::= SEQUENCE { - // algorithm AlgorithmIdentifier, - // subjectPublicKey BIT STRING } - bool VerifyInitRSAPSS(HashAlgorithm hash_alg, - HashAlgorithm mask_hash_alg, - int salt_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len); - - // Feeds a piece of the data to the signature verifier. - void VerifyUpdate(const uint8* data_part, int data_part_len); - - // Concludes a signature verification operation. Returns true if the - // signature is valid. Returns false if the signature is invalid or an - // error occurred. - bool VerifyFinal(); - - // Note: we can provide a one-shot interface if there is interest: - // bool Verify(const uint8* data, - // int data_len, - // const uint8* signature_algorithm, - // int signature_algorithm_len, - // const uint8* signature, - // int signature_len, - // const uint8* public_key_info, - // int public_key_info_len); - - private: -#if defined(USE_OPENSSL) - bool CommonInit(const EVP_MD* digest, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len, - EVP_PKEY_CTX** pkey_ctx); -#else - static SECKEYPublicKey* DecodePublicKeyInfo(const uint8* public_key_info, - int public_key_info_len); -#endif - - void Reset(); - - std::vector signature_; - -#if defined(USE_OPENSSL) - struct VerifyContext; - VerifyContext* verify_context_; -#else - // Used for all signature types except RSA-PSS. - VFYContext* vfy_context_; - - // Used for RSA-PSS signatures. - HashAlgorithm hash_alg_; - HashAlgorithm mask_hash_alg_; - unsigned int salt_len_; - SECKEYPublicKey* public_key_; - HASHContext* hash_context_; -#endif -}; - -} // namespace crypto - -#endif // CRYPTO_SIGNATURE_VERIFIER_H_ diff --git a/crypto/signature_verifier_nss.cc b/crypto/signature_verifier_nss.cc deleted file mode 100644 index 5be620da6bd1f..0000000000000 --- a/crypto/signature_verifier_nss.cc +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright (c) 2011 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/signature_verifier.h" - -#include -#include -#include -#include -#include -#include - -#include "base/logging.h" -#include "crypto/nss_util.h" -#include "crypto/third_party/nss/chromium-nss.h" - -namespace crypto { - -namespace { - -HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureVerifier::SHA1: - return HASH_AlgSHA1; - case SignatureVerifier::SHA256: - return HASH_AlgSHA256; - } - return HASH_AlgNULL; -} - -SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key, - HASHContext* hash_context, - HASH_HashType mask_hash_alg, - unsigned int salt_len, - const unsigned char* signature, - unsigned int signature_len) { - unsigned int hash_len = HASH_ResultLenContext(hash_context); - std::vector hash(hash_len); - HASH_End(hash_context, &hash[0], &hash_len, hash.size()); - - unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key); - if (signature_len != modulus_len) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - return SECFailure; - } - std::vector enc(signature_len); - SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0], - const_cast(signature), - signature_len, NULL); - if (rv != SECSuccess) { - LOG(WARNING) << "PK11_PubEncryptRaw failed"; - return rv; - } - return emsa_pss_verify(&hash[0], &enc[0], enc.size(), - HASH_GetType(hash_context), mask_hash_alg, - salt_len); -} - -} // namespace - -SignatureVerifier::SignatureVerifier() - : vfy_context_(NULL), - hash_alg_(SHA1), - mask_hash_alg_(SHA1), - salt_len_(0), - public_key_(NULL), - hash_context_(NULL) { - EnsureNSSInit(); -} - -SignatureVerifier::~SignatureVerifier() { - Reset(); -} - -bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - if (vfy_context_ || hash_context_) - return false; - - signature_.assign(signature, signature + signature_len); - - SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, - public_key_info_len); - if (!public_key) - return false; - - PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - SECKEY_DestroyPublicKey(public_key); - return false; - } - - SECItem sig_alg_der; - sig_alg_der.type = siBuffer; - sig_alg_der.data = const_cast(signature_algorithm); - sig_alg_der.len = signature_algorithm_len; - SECAlgorithmID sig_alg_id; - SECStatus rv; - rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, - SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), - &sig_alg_der); - if (rv != SECSuccess) { - SECKEY_DestroyPublicKey(public_key); - PORT_FreeArena(arena, PR_TRUE); - return false; - } - - SECItem sig; - sig.type = siBuffer; - sig.data = const_cast(signature); - sig.len = signature_len; - SECOidTag hash_alg_tag; - vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig, - &sig_alg_id, &hash_alg_tag, - NULL); - SECKEY_DestroyPublicKey(public_key); // Done with public_key. - PORT_FreeArena(arena, PR_TRUE); // Done with sig_alg_id. - if (!vfy_context_) { - // A corrupted RSA signature could be detected without the data, so - // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE - // (-8182). - return false; - } - - rv = VFY_Begin(vfy_context_); - if (rv != SECSuccess) { - NOTREACHED(); - return false; - } - return true; -} - -bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, - HashAlgorithm mask_hash_alg, - int salt_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - if (vfy_context_ || hash_context_) - return false; - - signature_.assign(signature, signature + signature_len); - - SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, - public_key_info_len); - if (!public_key) - return false; - - public_key_ = public_key; - hash_alg_ = hash_alg; - mask_hash_alg_ = mask_hash_alg; - salt_len_ = salt_len; - hash_context_ = HASH_Create(ToNSSHashType(hash_alg_)); - if (!hash_context_) - return false; - HASH_Begin(hash_context_); - return true; -} - -void SignatureVerifier::VerifyUpdate(const uint8* data_part, - int data_part_len) { - if (vfy_context_) { - SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); - DCHECK_EQ(SECSuccess, rv); - } else { - HASH_Update(hash_context_, data_part, data_part_len); - } -} - -bool SignatureVerifier::VerifyFinal() { - SECStatus rv; - if (vfy_context_) { - rv = VFY_End(vfy_context_); - } else { - rv = VerifyRSAPSS_End(public_key_, hash_context_, - ToNSSHashType(mask_hash_alg_), salt_len_, - signature_.data(), - signature_.size()); - } - Reset(); - - // If signature verification fails, the error code is - // SEC_ERROR_BAD_SIGNATURE (-8182). - return (rv == SECSuccess); -} - -// static -SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo( - const uint8* public_key_info, - int public_key_info_len) { - CERTSubjectPublicKeyInfo* spki = NULL; - SECItem spki_der; - spki_der.type = siBuffer; - spki_der.data = const_cast(public_key_info); - spki_der.len = public_key_info_len; - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); - if (!spki) - return NULL; - SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); - SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. - return public_key; -} - -void SignatureVerifier::Reset() { - if (vfy_context_) { - VFY_DestroyContext(vfy_context_, PR_TRUE); - vfy_context_ = NULL; - } - if (hash_context_) { - HASH_Destroy(hash_context_); - hash_context_ = NULL; - } - if (public_key_) { - SECKEY_DestroyPublicKey(public_key_); - public_key_ = NULL; - } - signature_.clear(); -} - -} // namespace crypto diff --git a/crypto/signature_verifier_openssl.cc b/crypto/signature_verifier_openssl.cc deleted file mode 100644 index a33d665ec1320..0000000000000 --- a/crypto/signature_verifier_openssl.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2011 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/signature_verifier.h" - -#include -#include - -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" - -namespace crypto { - -namespace { - -const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) { - switch (hash_alg) { - case SignatureVerifier::SHA1: - return EVP_sha1(); - case SignatureVerifier::SHA256: - return EVP_sha256(); - } - return NULL; -} - -} // namespace - -struct SignatureVerifier::VerifyContext { - ScopedEVP_MD_CTX ctx; -}; - -SignatureVerifier::SignatureVerifier() - : verify_context_(NULL) { -} - -SignatureVerifier::~SignatureVerifier() { - Reset(); -} - -bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, - int signature_algorithm_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedOpenSSL algorithm( - d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len)); - if (!algorithm.get()) - return false; - int nid = OBJ_obj2nid(algorithm.get()->algorithm); - const EVP_MD* digest; - if (nid == NID_ecdsa_with_SHA1) { - digest = EVP_sha1(); - } else if (nid == NID_ecdsa_with_SHA256) { - digest = EVP_sha256(); - } else { - // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA - // signatures. - digest = EVP_get_digestbyobj(algorithm.get()->algorithm); - } - if (!digest) - return false; - - return CommonInit(digest, signature, signature_len, public_key_info, - public_key_info_len, NULL); -} - -bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, - HashAlgorithm mask_hash_alg, - int salt_len, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); - DCHECK(digest); - if (!digest) { - return false; - } - - EVP_PKEY_CTX* pkey_ctx; - if (!CommonInit(digest, signature, signature_len, public_key_info, - public_key_info_len, &pkey_ctx)) { - return false; - } - - int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); - if (rv != 1) - return false; - const EVP_MD* const mgf_digest = ToOpenSSLDigest(mask_hash_alg); - DCHECK(mgf_digest); - if (!mgf_digest) { - return false; - } - rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest); - if (rv != 1) - return false; - rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); - return rv == 1; -} - -void SignatureVerifier::VerifyUpdate(const uint8* data_part, - int data_part_len) { - DCHECK(verify_context_); - OpenSSLErrStackTracer err_tracer(FROM_HERE); - int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(), - data_part, data_part_len); - DCHECK_EQ(rv, 1); -} - -bool SignatureVerifier::VerifyFinal() { - DCHECK(verify_context_); - OpenSSLErrStackTracer err_tracer(FROM_HERE); - int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), - vector_as_array(&signature_), - signature_.size()); - DCHECK_EQ(static_cast(!!rv), rv); - Reset(); - return rv == 1; -} - -bool SignatureVerifier::CommonInit(const EVP_MD* digest, - const uint8* signature, - int signature_len, - const uint8* public_key_info, - int public_key_info_len, - EVP_PKEY_CTX** pkey_ctx) { - if (verify_context_) - return false; - - verify_context_ = new VerifyContext; - - signature_.assign(signature, signature + signature_len); - - const uint8_t* ptr = public_key_info; - ScopedEVP_PKEY public_key(d2i_PUBKEY(nullptr, &ptr, public_key_info_len)); - if (!public_key.get() || ptr != public_key_info + public_key_info_len) - return false; - - verify_context_->ctx.reset(EVP_MD_CTX_create()); - int rv = EVP_DigestVerifyInit(verify_context_->ctx.get(), pkey_ctx, - digest, nullptr, public_key.get()); - return rv == 1; -} - -void SignatureVerifier::Reset() { - delete verify_context_; - verify_context_ = NULL; - signature_.clear(); -} - -} // namespace crypto diff --git a/crypto/signature_verifier_unittest.cc b/crypto/signature_verifier_unittest.cc deleted file mode 100644 index a661ff7f8ab8c..0000000000000 --- a/crypto/signature_verifier_unittest.cc +++ /dev/null @@ -1,1167 +0,0 @@ -// Copyright (c) 2011 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/signature_verifier.h" - -#include "base/numerics/safe_conversions.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(SignatureVerifierTest, BasicTest) { - // The input data in this test comes from real certificates. - // - // tbs_certificate ("to-be-signed certificate", the part of a certificate - // that is signed), signature_algorithm, and algorithm come from the - // certificate of bugs.webkit.org. - // - // public_key_info comes from the certificate of the issuer, Go Daddy Secure - // Certification Authority. - // - // The bytes in the array initializers are formatted to expose the DER - // encoding of the ASN.1 structures. - - // The data that is signed is the following ASN.1 structure: - // TBSCertificate ::= SEQUENCE { - // ... -- omitted, not important - // } - const uint8 tbs_certificate[1017] = { - 0x30, 0x82, 0x03, 0xf5, // a SEQUENCE of length 1013 (0x3f5) - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x43, 0xdd, 0x63, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, - 0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, - 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, - 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, - 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, - 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, - 0x38, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, 0x31, 0x38, - 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x33, 0x31, 0x38, 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x30, 0x79, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, - 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, - 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0c, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x46, 0x6f, 0x72, - 0x67, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72, - 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa7, 0x62, 0x79, 0x41, 0xda, 0x28, - 0xf2, 0xc0, 0x4f, 0xe0, 0x25, 0xaa, 0xa1, 0x2e, 0x3b, 0x30, 0x94, 0xb5, - 0xc9, 0x26, 0x3a, 0x1b, 0xe2, 0xd0, 0xcc, 0xa2, 0x95, 0xe2, 0x91, 0xc0, - 0xf0, 0x40, 0x9e, 0x27, 0x6e, 0xbd, 0x6e, 0xde, 0x7c, 0xb6, 0x30, 0x5c, - 0xb8, 0x9b, 0x01, 0x2f, 0x92, 0x04, 0xa1, 0xef, 0x4a, 0xb1, 0x6c, 0xb1, - 0x7e, 0x8e, 0xcd, 0xa6, 0xf4, 0x40, 0x73, 0x1f, 0x2c, 0x96, 0xad, 0xff, - 0x2a, 0x6d, 0x0e, 0xba, 0x52, 0x84, 0x83, 0xb0, 0x39, 0xee, 0xc9, 0x39, - 0xdc, 0x1e, 0x34, 0xd0, 0xd8, 0x5d, 0x7a, 0x09, 0xac, 0xa9, 0xee, 0xca, - 0x65, 0xf6, 0x85, 0x3a, 0x6b, 0xee, 0xe4, 0x5c, 0x5e, 0xf8, 0xda, 0xd1, - 0xce, 0x88, 0x47, 0xcd, 0x06, 0x21, 0xe0, 0xb9, 0x4b, 0xe4, 0x07, 0xcb, - 0x57, 0xdc, 0xca, 0x99, 0x54, 0xf7, 0x0e, 0xd5, 0x17, 0x95, 0x05, 0x2e, - 0xe9, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xce, 0x30, - 0x82, 0x01, 0xca, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, - 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, - 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x57, - 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x50, 0x30, 0x4e, 0x30, 0x4c, 0xa0, - 0x4a, 0xa0, 0x48, 0x86, 0x46, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, - 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, - 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x64, 0x65, 0x64, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, 0x33, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x52, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4b, - 0x30, 0x49, 0x30, 0x47, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, - 0x6d, 0x01, 0x07, 0x17, 0x02, 0x30, 0x38, 0x30, 0x36, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x2a, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x30, 0x7f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x23, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64, - 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x4a, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, - 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72, 0x74, - 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48, - 0xdf, 0x60, 0x32, 0xcc, 0x89, 0x01, 0xb6, 0xdc, 0x2f, 0xe3, 0x73, 0xb5, - 0x9c, 0x16, 0x58, 0x32, 0x68, 0xa9, 0xc3, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, - 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee, 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, - 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x23, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, - 0x1c, 0x30, 0x1a, 0x82, 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, - 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x0a, 0x77, 0x65, 0x62, 0x6b, 0x69, - 0x74, 0x2e, 0x6f, 0x72, 0x67 - }; - - // The signature algorithm is specified as the following ASN.1 structure: - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - // - const uint8 signature_algorithm[15] = { - 0x30, 0x0d, // a SEQUENCE of length 13 (0xd) - 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 - // 1.2.840.113549.1.1.5 - sha1WithRSAEncryption - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, // a NULL of length 0 - }; - - // RSA signature, a big integer in the big-endian byte order. - const uint8 signature[256] = { - 0x1e, 0x6a, 0xe7, 0xe0, 0x4f, 0xe7, 0x4d, 0xd0, 0x69, 0x7c, 0xf8, 0x8f, - 0x99, 0xb4, 0x18, 0x95, 0x36, 0x24, 0x0f, 0x0e, 0xa3, 0xea, 0x34, 0x37, - 0xf4, 0x7d, 0xd5, 0x92, 0x35, 0x53, 0x72, 0x76, 0x3f, 0x69, 0xf0, 0x82, - 0x56, 0xe3, 0x94, 0x7a, 0x1d, 0x1a, 0x81, 0xaf, 0x9f, 0xc7, 0x43, 0x01, - 0x64, 0xd3, 0x7c, 0x0d, 0xc8, 0x11, 0x4e, 0x4a, 0xe6, 0x1a, 0xc3, 0x01, - 0x74, 0xe8, 0x35, 0x87, 0x5c, 0x61, 0xaa, 0x8a, 0x46, 0x06, 0xbe, 0x98, - 0x95, 0x24, 0x9e, 0x01, 0xe3, 0xe6, 0xa0, 0x98, 0xee, 0x36, 0x44, 0x56, - 0x8d, 0x23, 0x9c, 0x65, 0xea, 0x55, 0x6a, 0xdf, 0x66, 0xee, 0x45, 0xe8, - 0xa0, 0xe9, 0x7d, 0x9a, 0xba, 0x94, 0xc5, 0xc8, 0xc4, 0x4b, 0x98, 0xff, - 0x9a, 0x01, 0x31, 0x6d, 0xf9, 0x2b, 0x58, 0xe7, 0xe7, 0x2a, 0xc5, 0x4d, - 0xbb, 0xbb, 0xcd, 0x0d, 0x70, 0xe1, 0xad, 0x03, 0xf5, 0xfe, 0xf4, 0x84, - 0x71, 0x08, 0xd2, 0xbc, 0x04, 0x7b, 0x26, 0x1c, 0xa8, 0x0f, 0x9c, 0xd8, - 0x12, 0x6a, 0x6f, 0x2b, 0x67, 0xa1, 0x03, 0x80, 0x9a, 0x11, 0x0b, 0xe9, - 0xe0, 0xb5, 0xb3, 0xb8, 0x19, 0x4e, 0x0c, 0xa4, 0xd9, 0x2b, 0x3b, 0xc2, - 0xca, 0x20, 0xd3, 0x0c, 0xa4, 0xff, 0x93, 0x13, 0x1f, 0xfc, 0xba, 0x94, - 0x93, 0x8c, 0x64, 0x15, 0x2e, 0x28, 0xa9, 0x55, 0x8c, 0x2c, 0x48, 0xd3, - 0xd3, 0xc1, 0x50, 0x69, 0x19, 0xe8, 0x34, 0xd3, 0xf1, 0x04, 0x9f, 0x0a, - 0x7a, 0x21, 0x87, 0xbf, 0xb9, 0x59, 0x37, 0x2e, 0xf4, 0x71, 0xa5, 0x3e, - 0xbe, 0xcd, 0x70, 0x83, 0x18, 0xf8, 0x8a, 0x72, 0x85, 0x45, 0x1f, 0x08, - 0x01, 0x6f, 0x37, 0xf5, 0x2b, 0x7b, 0xea, 0xb9, 0x8b, 0xa3, 0xcc, 0xfd, - 0x35, 0x52, 0xdd, 0x66, 0xde, 0x4f, 0x30, 0xc5, 0x73, 0x81, 0xb6, 0xe8, - 0x3c, 0xd8, 0x48, 0x8a - }; - - // The public key is specified as the following ASN.1 structure: - // SubjectPublicKeyInfo ::= SEQUENCE { - // algorithm AlgorithmIdentifier, - // subjectPublicKey BIT STRING } - const uint8 public_key_info[294] = { - 0x30, 0x82, 0x01, 0x22, // a SEQUENCE of length 290 (0x122) - // algorithm - 0x30, 0x0d, // a SEQUENCE of length 13 - 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, // a NULL of length 0 - // subjectPublicKey - 0x03, 0x82, 0x01, 0x0f, // a BIT STRING of length 271 (0x10f) - 0x00, // number of unused bits - 0x30, 0x82, 0x01, 0x0a, // a SEQUENCE of length 266 (0x10a) - // modulus - 0x02, 0x82, 0x01, 0x01, // an INTEGER of length 257 (0x101) - 0x00, 0xc4, 0x2d, 0xd5, 0x15, 0x8c, 0x9c, 0x26, 0x4c, 0xec, - 0x32, 0x35, 0xeb, 0x5f, 0xb8, 0x59, 0x01, 0x5a, 0xa6, 0x61, - 0x81, 0x59, 0x3b, 0x70, 0x63, 0xab, 0xe3, 0xdc, 0x3d, 0xc7, - 0x2a, 0xb8, 0xc9, 0x33, 0xd3, 0x79, 0xe4, 0x3a, 0xed, 0x3c, - 0x30, 0x23, 0x84, 0x8e, 0xb3, 0x30, 0x14, 0xb6, 0xb2, 0x87, - 0xc3, 0x3d, 0x95, 0x54, 0x04, 0x9e, 0xdf, 0x99, 0xdd, 0x0b, - 0x25, 0x1e, 0x21, 0xde, 0x65, 0x29, 0x7e, 0x35, 0xa8, 0xa9, - 0x54, 0xeb, 0xf6, 0xf7, 0x32, 0x39, 0xd4, 0x26, 0x55, 0x95, - 0xad, 0xef, 0xfb, 0xfe, 0x58, 0x86, 0xd7, 0x9e, 0xf4, 0x00, - 0x8d, 0x8c, 0x2a, 0x0c, 0xbd, 0x42, 0x04, 0xce, 0xa7, 0x3f, - 0x04, 0xf6, 0xee, 0x80, 0xf2, 0xaa, 0xef, 0x52, 0xa1, 0x69, - 0x66, 0xda, 0xbe, 0x1a, 0xad, 0x5d, 0xda, 0x2c, 0x66, 0xea, - 0x1a, 0x6b, 0xbb, 0xe5, 0x1a, 0x51, 0x4a, 0x00, 0x2f, 0x48, - 0xc7, 0x98, 0x75, 0xd8, 0xb9, 0x29, 0xc8, 0xee, 0xf8, 0x66, - 0x6d, 0x0a, 0x9c, 0xb3, 0xf3, 0xfc, 0x78, 0x7c, 0xa2, 0xf8, - 0xa3, 0xf2, 0xb5, 0xc3, 0xf3, 0xb9, 0x7a, 0x91, 0xc1, 0xa7, - 0xe6, 0x25, 0x2e, 0x9c, 0xa8, 0xed, 0x12, 0x65, 0x6e, 0x6a, - 0xf6, 0x12, 0x44, 0x53, 0x70, 0x30, 0x95, 0xc3, 0x9c, 0x2b, - 0x58, 0x2b, 0x3d, 0x08, 0x74, 0x4a, 0xf2, 0xbe, 0x51, 0xb0, - 0xbf, 0x87, 0xd0, 0x4c, 0x27, 0x58, 0x6b, 0xb5, 0x35, 0xc5, - 0x9d, 0xaf, 0x17, 0x31, 0xf8, 0x0b, 0x8f, 0xee, 0xad, 0x81, - 0x36, 0x05, 0x89, 0x08, 0x98, 0xcf, 0x3a, 0xaf, 0x25, 0x87, - 0xc0, 0x49, 0xea, 0xa7, 0xfd, 0x67, 0xf7, 0x45, 0x8e, 0x97, - 0xcc, 0x14, 0x39, 0xe2, 0x36, 0x85, 0xb5, 0x7e, 0x1a, 0x37, - 0xfd, 0x16, 0xf6, 0x71, 0x11, 0x9a, 0x74, 0x30, 0x16, 0xfe, - 0x13, 0x94, 0xa3, 0x3f, 0x84, 0x0d, 0x4f, - // public exponent - 0x02, 0x03, // an INTEGER of length 3 - 0x01, 0x00, 0x01 - }; - - // We use the signature verifier to perform four signature verification - // tests. - crypto::SignatureVerifier verifier; - bool ok; - - // Test 1: feed all of the data to the verifier at once (a single - // VerifyUpdate call). - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); - EXPECT_TRUE(ok); - verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate)); - ok = verifier.VerifyFinal(); - EXPECT_TRUE(ok); - - // Test 2: feed the data to the verifier in three parts (three VerifyUpdate - // calls). - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); - EXPECT_TRUE(ok); - verifier.VerifyUpdate(tbs_certificate, 256); - verifier.VerifyUpdate(tbs_certificate + 256, 256); - verifier.VerifyUpdate(tbs_certificate + 512, sizeof(tbs_certificate) - 512); - ok = verifier.VerifyFinal(); - EXPECT_TRUE(ok); - - // Test 3: verify the signature with incorrect data. - uint8 bad_tbs_certificate[sizeof(tbs_certificate)]; - memcpy(bad_tbs_certificate, tbs_certificate, sizeof(tbs_certificate)); - bad_tbs_certificate[10] += 1; // Corrupt one byte of the data. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); - EXPECT_TRUE(ok); - verifier.VerifyUpdate(bad_tbs_certificate, sizeof(bad_tbs_certificate)); - ok = verifier.VerifyFinal(); - EXPECT_FALSE(ok); - - // Test 4: verify a bad signature. - uint8 bad_signature[sizeof(signature)]; - memcpy(bad_signature, signature, sizeof(signature)); - bad_signature[10] += 1; // Corrupt one byte of the signature. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - bad_signature, sizeof(bad_signature), - public_key_info, sizeof(public_key_info)); - - // A crypto library (e.g., NSS) may detect that the signature is corrupted - // and cause VerifyInit to return false, so it is fine for 'ok' to be false. - if (ok) { - verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate)); - ok = verifier.VerifyFinal(); - EXPECT_FALSE(ok); - } - - // Test 5: import an invalid key. - uint8_t bad_public_key_info[sizeof(public_key_info)]; - memcpy(bad_public_key_info, public_key_info, sizeof(public_key_info)); - bad_public_key_info[0] += 1; // Corrupt part of the SPKI syntax. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - bad_public_key_info, sizeof(bad_public_key_info)); - EXPECT_FALSE(ok); - - // Test 6: import a key with extra data. - uint8_t long_public_key_info[sizeof(public_key_info) + 5]; - memset(long_public_key_info, 0, sizeof(long_public_key_info)); - memcpy(long_public_key_info, public_key_info, sizeof(public_key_info)); - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - long_public_key_info, sizeof(long_public_key_info)); - EXPECT_FALSE(ok); -} - -////////////////////////////////////////////////////////////////////// -// -// RSA-PSS signature verification known answer test -// -////////////////////////////////////////////////////////////////////// - -// The following RSA-PSS signature test vectors come from the pss-vect.txt -// file downloaded from -// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip. -// -// For each key, 6 random messages of length between 1 and 256 octets have -// been RSASSA-PSS signed. -// -// Hash function: SHA-1 -// Mask generation function: MGF1 with SHA-1 -// Salt length: 20 octets - -// Example 1: A 1024-bit RSA Key Pair" - -// RSA modulus n: -static const char rsa_modulus_n_1[] = - "a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 " - "56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 " - "d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 " - "94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df " - "d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 " - "c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 " - "05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 " - "ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 "; -// RSA public exponent e: " -static const char rsa_public_exponent_e_1[] = - "01 00 01 "; - -// RSASSA-PSS Signature Example 1.1 -// Message to be signed: -static const char message_1_1[] = - "cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26 " - "d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6 " - "23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15 " - "6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76 " - "97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3 " - "d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0 " - "61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29 " - "cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61 " - "93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08 " - "a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c " - "29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca " - "b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16 " - "be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed " - "1b 73 31 8b 75 0a 01 67 d0 "; -// Salt: -static const char salt_1_1[] = - "de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f " - "3e 67 76 af "; -// Signature: -static const char signature_1_1[] = - "90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71 " - "fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87 " - "e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2 " - "26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15 " - "df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9 " - "c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65 " - "98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4 " - "c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c "; - -// RSASSA-PSS Signature Example 1.2 -// Message to be signed: -static const char message_1_2[] = - "85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c " - "f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f " - "71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13 " - "22 6b 9e "; -// Salt: -static const char salt_1_2[] = - "ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f " - "d5 6d f4 2d "; -// Signature: -static const char signature_1_2[] = - "3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce " - "fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e " - "f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db " - "0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45 " - "17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4 " - "cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35 " - "90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14 " - "18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43 "; - -// RSASSA-PSS Signature Example 1.3 -// Message to be signed: -static const char message_1_3[] = - "a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5 " - "aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef " - "8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d " - "fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55 " - "fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db " - "43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7 " - "45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29 " - "c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4 " - "56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17 " - "be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c " - "03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b " - "79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa " - "29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61 " - "8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13 " - "38 e7 d4 70 "; -// Salt: -static const char salt_1_3[] = - "71 0b 9c 47 47 d8 00 d4 de 87 f1 2a fd ce 6d f1 " - "81 07 cc 77 "; -// Signature: -static const char signature_1_3[] = - "66 60 26 fb a7 1b d3 e7 cf 13 15 7c c2 c5 1a 8e " - "4a a6 84 af 97 78 f9 18 49 f3 43 35 d1 41 c0 01 " - "54 c4 19 76 21 f9 62 4a 67 5b 5a bc 22 ee 7d 5b " - "aa ff aa e1 c9 ba ca 2c c3 73 b3 f3 3e 78 e6 14 " - "3c 39 5a 91 aa 7f ac a6 64 eb 73 3a fd 14 d8 82 " - "72 59 d9 9a 75 50 fa ca 50 1e f2 b0 4e 33 c2 3a " - "a5 1f 4b 9e 82 82 ef db 72 8c c0 ab 09 40 5a 91 " - "60 7c 63 69 96 1b c8 27 0d 2d 4f 39 fc e6 12 b1 "; - -// RSASSA-PSS Signature Example 1.4 -// Message to be signed: -static const char message_1_4[] = - "bc 65 67 47 fa 9e af b3 f0 "; -// Salt: -static const char salt_1_4[] = - "05 6f 00 98 5d e1 4d 8e f5 ce a9 e8 2f 8c 27 be " - "f7 20 33 5e "; -// Signature: -static const char signature_1_4[] = - "46 09 79 3b 23 e9 d0 93 62 dc 21 bb 47 da 0b 4f " - "3a 76 22 64 9a 47 d4 64 01 9b 9a ea fe 53 35 9c " - "17 8c 91 cd 58 ba 6b cb 78 be 03 46 a7 bc 63 7f " - "4b 87 3d 4b ab 38 ee 66 1f 19 96 34 c5 47 a1 ad " - "84 42 e0 3d a0 15 b1 36 e5 43 f7 ab 07 c0 c1 3e " - "42 25 b8 de 8c ce 25 d4 f6 eb 84 00 f8 1f 7e 18 " - "33 b7 ee 6e 33 4d 37 09 64 ca 79 fd b8 72 b4 d7 " - "52 23 b5 ee b0 81 01 59 1f b5 32 d1 55 a6 de 87 "; - -// RSASSA-PSS Signature Example 1.5 -// Message to be signed: -static const char message_1_5[] = - "b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64 " - "e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76 " - "c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e " - "f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75 " - "48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4 " - "b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f " - "32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7 " - "82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc " - "5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f " - "45 5a 69 09 b4 "; -// Salt: -static const char salt_1_5[] = - "80 e7 0f f8 6a 08 de 3e c6 09 72 b3 9b 4f bf dc " - "ea 67 ae 8e "; -// Signature: -static const char signature_1_5[] = - "1d 2a ad 22 1c a4 d3 1d df 13 50 92 39 01 93 98 " - "e3 d1 4b 32 dc 34 dc 5a f4 ae ae a3 c0 95 af 73 " - "47 9c f0 a4 5e 56 29 63 5a 53 a0 18 37 76 15 b1 " - "6c b9 b1 3b 3e 09 d6 71 eb 71 e3 87 b8 54 5c 59 " - "60 da 5a 64 77 6e 76 8e 82 b2 c9 35 83 bf 10 4c " - "3f db 23 51 2b 7b 4e 89 f6 33 dd 00 63 a5 30 db " - "45 24 b0 1c 3f 38 4c 09 31 0e 31 5a 79 dc d3 d6 " - "84 02 2a 7f 31 c8 65 a6 64 e3 16 97 8b 75 9f ad "; - -// RSASSA-PSS Signature Example 1.6 -// Message to be signed: -static const char message_1_6[] = - "10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7 " - "5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec " - "74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4 " - "3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4 " - "35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90 " - "9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7 " - "05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad " - "b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87 " - "94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00 " - "44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73 " - "d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29 " - "51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb " - "3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf " - "e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6 " - "13 8d 14 4f 8c e4 e2 da 73 "; -// Salt: -static const char salt_1_6[] = - "a8 ab 69 dd 80 1f 00 74 c2 a1 fc 60 64 98 36 c6 " - "16 d9 96 81 "; -// Signature: -static const char signature_1_6[] = - "2a 34 f6 12 5e 1f 6b 0b f9 71 e8 4f bd 41 c6 32 " - "be 8f 2c 2a ce 7d e8 b6 92 6e 31 ff 93 e9 af 98 " - "7f bc 06 e5 1e 9b e1 4f 51 98 f9 1f 3f 95 3b d6 " - "7d a6 0a 9d f5 97 64 c3 dc 0f e0 8e 1c be f0 b7 " - "5f 86 8d 10 ad 3f ba 74 9f ef 59 fb 6d ac 46 a0 " - "d6 e5 04 36 93 31 58 6f 58 e4 62 8f 39 aa 27 89 " - "82 54 3b c0 ee b5 37 dc 61 95 80 19 b3 94 fb 27 " - "3f 21 58 58 a0 a0 1a c4 d6 50 b9 55 c6 7f 4c 58 "; - -// Example 9: A 1536-bit RSA Key Pair - -// RSA modulus n: -static const char rsa_modulus_n_9[] = - "e6 bd 69 2a c9 66 45 79 04 03 fd d0 f5 be b8 b9 " - "bf 92 ed 10 00 7f c3 65 04 64 19 dd 06 c0 5c 5b " - "5b 2f 48 ec f9 89 e4 ce 26 91 09 97 9c bb 40 b4 " - "a0 ad 24 d2 24 83 d1 ee 31 5a d4 cc b1 53 42 68 " - "35 26 91 c5 24 f6 dd 8e 6c 29 d2 24 cf 24 69 73 " - "ae c8 6c 5b f6 b1 40 1a 85 0d 1b 9a d1 bb 8c bc " - "ec 47 b0 6f 0f 8c 7f 45 d3 fc 8f 31 92 99 c5 43 " - "3d db c2 b3 05 3b 47 de d2 ec d4 a4 ca ef d6 14 " - "83 3d c8 bb 62 2f 31 7e d0 76 b8 05 7f e8 de 3f " - "84 48 0a d5 e8 3e 4a 61 90 4a 4f 24 8f b3 97 02 " - "73 57 e1 d3 0e 46 31 39 81 5c 6f d4 fd 5a c5 b8 " - "17 2a 45 23 0e cb 63 18 a0 4f 14 55 d8 4e 5a 8b "; -// RSA public exponent e: -static const char rsa_public_exponent_e_9[] = - "01 00 01 "; - -// RSASSA-PSS Signature Example 9.1 -// Message to be signed: -static const char message_9_1[] = - "a8 8e 26 58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59 " - "1c d6 58 7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59 " - "22 02 8b c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa " - "70 ba 36 72 cd de 4c fe 49 70 cc 79 04 60 1b 27 " - "88 72 bf 51 32 1c 4a 97 2f 3c 95 57 0f 34 45 d4 " - "f5 79 80 e0 f2 0d f5 48 46 e6 a5 2c 66 8f 12 88 " - "c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe b3 2f " - "0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c f9 79 " - "f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 dd 76 " - "2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 ca 70 " - "9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 85 66 " - "ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 15 94 " - "20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 11 a2 " - "c7 50 f5 "; -// Salt: -static const char salt_9_1[] = - "c0 a4 25 31 3d f8 d7 56 4b d2 43 4d 31 15 23 d5 " - "25 7e ed 80 "; -// Signature: -static const char signature_9_1[] = - "58 61 07 22 6c 3c e0 13 a7 c8 f0 4d 1a 6a 29 59 " - "bb 4b 8e 20 5b a4 3a 27 b5 0f 12 41 11 bc 35 ef " - "58 9b 03 9f 59 32 18 7c b6 96 d7 d9 a3 2c 0c 38 " - "30 0a 5c dd a4 83 4b 62 d2 eb 24 0a f3 3f 79 d1 " - "3d fb f0 95 bf 59 9e 0d 96 86 94 8c 19 64 74 7b " - "67 e8 9c 9a ba 5c d8 50 16 23 6f 56 6c c5 80 2c " - "b1 3e ad 51 bc 7c a6 be f3 b9 4d cb db b1 d5 70 " - "46 97 71 df 0e 00 b1 a8 a0 67 77 47 2d 23 16 27 " - "9e da e8 64 74 66 8d 4e 1e ff f9 5f 1d e6 1c 60 " - "20 da 32 ae 92 bb f1 65 20 fe f3 cf 4d 88 f6 11 " - "21 f2 4b bd 9f e9 1b 59 ca f1 23 5b 2a 93 ff 81 " - "fc 40 3a dd f4 eb de a8 49 34 a9 cd af 8e 1a 9e "; - -// RSASSA-PSS Signature Example 9.2 -// Message to be signed: -static const char message_9_2[] = - "c8 c9 c6 af 04 ac da 41 4d 22 7e f2 3e 08 20 c3 " - "73 2c 50 0d c8 72 75 e9 5b 0d 09 54 13 99 3c 26 " - "58 bc 1d 98 85 81 ba 87 9c 2d 20 1f 14 cb 88 ce " - "d1 53 a0 19 69 a7 bf 0a 7b e7 9c 84 c1 48 6b c1 " - "2b 3f a6 c5 98 71 b6 82 7c 8c e2 53 ca 5f ef a8 " - "a8 c6 90 bf 32 6e 8e 37 cd b9 6d 90 a8 2e ba b6 " - "9f 86 35 0e 18 22 e8 bd 53 6a 2e "; -// Salt: -static const char salt_9_2[] = - "b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 ef " - "8c 5c 0e 91 "; -// Signature: -static const char signature_9_2[] = - "80 b6 d6 43 25 52 09 f0 a4 56 76 38 97 ac 9e d2 " - "59 d4 59 b4 9c 28 87 e5 88 2e cb 44 34 cf d6 6d " - "d7 e1 69 93 75 38 1e 51 cd 7f 55 4f 2c 27 17 04 " - "b3 99 d4 2b 4b e2 54 0a 0e ca 61 95 1f 55 26 7f " - "7c 28 78 c1 22 84 2d ad b2 8b 01 bd 5f 8c 02 5f " - "7e 22 84 18 a6 73 c0 3d 6b c0 c7 36 d0 a2 95 46 " - "bd 67 f7 86 d9 d6 92 cc ea 77 8d 71 d9 8c 20 63 " - "b7 a7 10 92 18 7a 4d 35 af 10 81 11 d8 3e 83 ea " - "e4 6c 46 aa 34 27 7e 06 04 45 89 90 37 88 f1 d5 " - "e7 ce e2 5f b4 85 e9 29 49 11 88 14 d6 f2 c3 ee " - "36 14 89 01 6f 32 7f b5 bc 51 7e b5 04 70 bf fa " - "1a fa 5f 4c e9 aa 0c e5 b8 ee 19 bf 55 01 b9 58 "; - -// RSASSA-PSS Signature Example 9.3 -// Message to be signed: -static const char message_9_3[] = - "0a fa d4 2c cd 4f c6 06 54 a5 50 02 d2 28 f5 2a " - "4a 5f e0 3b 8b bb 08 ca 82 da ca 55 8b 44 db e1 " - "26 6e 50 c0 e7 45 a3 6d 9d 29 04 e3 40 8a bc d1 " - "fd 56 99 94 06 3f 4a 75 cc 72 f2 fe e2 a0 cd 89 " - "3a 43 af 1c 5b 8b 48 7d f0 a7 16 10 02 4e 4f 6d " - "df 9f 28 ad 08 13 c1 aa b9 1b cb 3c 90 64 d5 ff " - "74 2d ef fe a6 57 09 41 39 36 9e 5e a6 f4 a9 63 " - "19 a5 cc 82 24 14 5b 54 50 62 75 8f ef d1 fe 34 " - "09 ae 16 92 59 c6 cd fd 6b 5f 29 58 e3 14 fa ec " - "be 69 d2 ca ce 58 ee 55 17 9a b9 b3 e6 d1 ec c1 " - "4a 55 7c 5f eb e9 88 59 52 64 fc 5d a1 c5 71 46 " - "2e ca 79 8a 18 a1 a4 94 0c da b4 a3 e9 20 09 cc " - "d4 2e 1e 94 7b 13 14 e3 22 38 a2 de ce 7d 23 a8 " - "9b 5b 30 c7 51 fd 0a 4a 43 0d 2c 54 85 94 "; -// Salt: -static const char salt_9_3[] = - "9a 2b 00 7e 80 97 8b bb 19 2c 35 4e b7 da 9a ed " - "fc 74 db f5 "; -// Signature: -static const char signature_9_3[] = - "48 44 08 f3 89 8c d5 f5 34 83 f8 08 19 ef bf 27 " - "08 c3 4d 27 a8 b2 a6 fa e8 b3 22 f9 24 02 37 f9 " - "81 81 7a ca 18 46 f1 08 4d aa 6d 7c 07 95 f6 e5 " - "bf 1a f5 9c 38 e1 85 84 37 ce 1f 7e c4 19 b9 8c " - "87 36 ad f6 dd 9a 00 b1 80 6d 2b d3 ad 0a 73 77 " - "5e 05 f5 2d fe f3 a5 9a b4 b0 81 43 f0 df 05 cd " - "1a d9 d0 4b ec ec a6 da a4 a2 12 98 03 e2 00 cb " - "c7 77 87 ca f4 c1 d0 66 3a 6c 59 87 b6 05 95 20 " - "19 78 2c af 2e c1 42 6d 68 fb 94 ed 1d 4b e8 16 " - "a7 ed 08 1b 77 e6 ab 33 0b 3f fc 07 38 20 fe cd " - "e3 72 7f cb e2 95 ee 61 a0 50 a3 43 65 86 37 c3 " - "fd 65 9c fb 63 73 6d e3 2d 9f 90 d3 c2 f6 3e ca "; - -// RSASSA-PSS Signature Example 9.4 -// Message to be signed: -static const char message_9_4[] = - "1d fd 43 b4 6c 93 db 82 62 9b da e2 bd 0a 12 b8 " - "82 ea 04 c3 b4 65 f5 cf 93 02 3f 01 05 96 26 db " - "be 99 f2 6b b1 be 94 9d dd d1 6d c7 f3 de bb 19 " - "a1 94 62 7f 0b 22 44 34 df 7d 87 00 e9 e9 8b 06 " - "e3 60 c1 2f db e3 d1 9f 51 c9 68 4e b9 08 9e cb " - "b0 a2 f0 45 03 99 d3 f5 9e ac 72 94 08 5d 04 4f " - "53 93 c6 ce 73 74 23 d8 b8 6c 41 53 70 d3 89 e3 " - "0b 9f 0a 3c 02 d2 5d 00 82 e8 ad 6f 3f 1e f2 4a " - "45 c3 cf 82 b3 83 36 70 63 a4 d4 61 3e 42 64 f0 " - "1b 2d ac 2e 5a a4 20 43 f8 fb 5f 69 fa 87 1d 14 " - "fb 27 3e 76 7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0 " - "c7 e0 f6 be 25 61 92 3a 77 21 1d 66 a6 e2 db b4 " - "3c 36 63 50 be ae 22 da 3a c2 c1 f5 07 70 96 fc " - "b5 c4 bf 25 5f 75 74 35 1a e0 b1 e1 f0 36 32 81 " - "7c 08 56 d4 a8 ba 97 af bd c8 b8 58 55 40 2b c5 " - "69 26 fc ec 20 9f 9e a8 "; -// Salt: -static const char salt_9_4[] = - "70 f3 82 bd df 4d 5d 2d d8 8b 3b c7 b7 30 8b e6 " - "32 b8 40 45 "; -// Signature: -static const char signature_9_4[] = - "84 eb eb 48 1b e5 98 45 b4 64 68 ba fb 47 1c 01 " - "12 e0 2b 23 5d 84 b5 d9 11 cb d1 92 6e e5 07 4a " - "e0 42 44 95 cb 20 e8 23 08 b8 eb b6 5f 41 9a 03 " - "fb 40 e7 2b 78 98 1d 88 aa d1 43 05 36 85 17 2c " - "97 b2 9c 8b 7b f0 ae 73 b5 b2 26 3c 40 3d a0 ed " - "2f 80 ff 74 50 af 78 28 eb 8b 86 f0 02 8b d2 a8 " - "b1 76 a4 d2 28 cc ce a1 83 94 f2 38 b0 9f f7 58 " - "cc 00 bc 04 30 11 52 35 57 42 f2 82 b5 4e 66 3a " - "91 9e 70 9d 8d a2 4a de 55 00 a7 b9 aa 50 22 6e " - "0c a5 29 23 e6 c2 d8 60 ec 50 ff 48 0f a5 74 77 " - "e8 2b 05 65 f4 37 9f 79 c7 72 d5 c2 da 80 af 9f " - "bf 32 5e ce 6f c2 0b 00 96 16 14 be e8 9a 18 3e "; - -// RSASSA-PSS Signature Example 9.5 -// Message to be signed: -static const char message_9_5[] = - "1b dc 6e 7c 98 fb 8c f5 4e 9b 09 7b 66 a8 31 e9 " - "cf e5 2d 9d 48 88 44 8e e4 b0 97 80 93 ba 1d 7d " - "73 ae 78 b3 a6 2b a4 ad 95 cd 28 9c cb 9e 00 52 " - "26 bb 3d 17 8b cc aa 82 1f b0 44 a4 e2 1e e9 76 " - "96 c1 4d 06 78 c9 4c 2d ae 93 b0 ad 73 92 22 18 " - "55 3d aa 7e 44 eb e5 77 25 a7 a4 5c c7 2b 9b 21 " - "38 a6 b1 7c 8d b4 11 ce 82 79 ee 12 41 af f0 a8 " - "be c6 f7 7f 87 ed b0 c6 9c b2 72 36 e3 43 5a 80 " - "0b 19 2e 4f 11 e5 19 e3 fe 30 fc 30 ea cc ca 4f " - "bb 41 76 90 29 bf 70 8e 81 7a 9e 68 38 05 be 67 " - "fa 10 09 84 68 3b 74 83 8e 3b cf fa 79 36 6e ed " - "1d 48 1c 76 72 91 18 83 8f 31 ba 8a 04 8a 93 c1 " - "be 44 24 59 8e 8d f6 32 8b 7a 77 88 0a 3f 9c 7e " - "2e 8d fc a8 eb 5a 26 fb 86 bd c5 56 d4 2b be 01 " - "d9 fa 6e d8 06 46 49 1c 93 41 "; -// Salt: -static const char salt_9_5[] = - "d6 89 25 7a 86 ef fa 68 21 2c 5e 0c 61 9e ca 29 " - "5f b9 1b 67 "; -// Signature: -static const char signature_9_5[] = - "82 10 2d f8 cb 91 e7 17 99 19 a0 4d 26 d3 35 d6 " - "4f bc 2f 87 2c 44 83 39 43 24 1d e8 45 48 10 27 " - "4c df 3d b5 f4 2d 42 3d b1 52 af 71 35 f7 01 42 " - "0e 39 b4 94 a6 7c bf d1 9f 91 19 da 23 3a 23 da " - "5c 64 39 b5 ba 0d 2b c3 73 ee e3 50 70 01 37 8d " - "4a 40 73 85 6b 7f e2 ab a0 b5 ee 93 b2 7f 4a fe " - "c7 d4 d1 20 92 1c 83 f6 06 76 5b 02 c1 9e 4d 6a " - "1a 3b 95 fa 4c 42 29 51 be 4f 52 13 10 77 ef 17 " - "17 97 29 cd df bd b5 69 50 db ac ee fe 78 cb 16 " - "64 0a 09 9e a5 6d 24 38 9e ef 10 f8 fe cb 31 ba " - "3e a3 b2 27 c0 a8 66 98 bb 89 e3 e9 36 39 05 bf " - "22 77 7b 2a 3a a5 21 b6 5b 4c ef 76 d8 3b de 4c "; - -// RSASSA-PSS Signature Example 9.6 -// Message to be signed: -static const char message_9_6[] = - "88 c7 a9 f1 36 04 01 d9 0e 53 b1 01 b6 1c 53 25 " - "c3 c7 5d b1 b4 11 fb eb 8e 83 0b 75 e9 6b 56 67 " - "0a d2 45 40 4e 16 79 35 44 ee 35 4b c6 13 a9 0c " - "c9 84 87 15 a7 3d b5 89 3e 7f 6d 27 98 15 c0 c1 " - "de 83 ef 8e 29 56 e3 a5 6e d2 6a 88 8d 7a 9c dc " - "d0 42 f4 b1 6b 7f a5 1e f1 a0 57 36 62 d1 6a 30 " - "2d 0e c5 b2 85 d2 e0 3a d9 65 29 c8 7b 3d 37 4d " - "b3 72 d9 5b 24 43 d0 61 b6 b1 a3 50 ba 87 80 7e " - "d0 83 af d1 eb 05 c3 f5 2f 4e ba 5e d2 22 77 14 " - "fd b5 0b 9d 9d 9d d6 81 4f 62 f6 27 2f cd 5c db " - "ce 7a 9e f7 97 "; -// Salt: -static const char salt_9_6[] = - "c2 5f 13 bf 67 d0 81 67 1a 04 81 a1 f1 82 0d 61 " - "3b ba 22 76 "; -// Signature: -static const char signature_9_6[] = - "a7 fd b0 d2 59 16 5c a2 c8 8d 00 bb f1 02 8a 86 " - "7d 33 76 99 d0 61 19 3b 17 a9 64 8e 14 cc bb aa " - "de ac aa cd ec 81 5e 75 71 29 4e bb 8a 11 7a f2 " - "05 fa 07 8b 47 b0 71 2c 19 9e 3a d0 51 35 c5 04 " - "c2 4b 81 70 51 15 74 08 02 48 79 92 ff d5 11 d4 " - "af c6 b8 54 49 1e b3 f0 dd 52 31 39 54 2f f1 5c " - "31 01 ee 85 54 35 17 c6 a3 c7 94 17 c6 7e 2d d9 " - "aa 74 1e 9a 29 b0 6d cb 59 3c 23 36 b3 67 0a e3 " - "af ba c7 c3 e7 6e 21 54 73 e8 66 e3 38 ca 24 4d " - "e0 0b 62 62 4d 6b 94 26 82 2c ea e9 f8 cc 46 08 " - "95 f4 12 50 07 3f d4 5c 5a 1e 7b 42 5c 20 4a 42 " - "3a 69 91 59 f6 90 3e 71 0b 37 a7 bb 2b c8 04 9f "; - -// Example 10: A 2048-bit RSA Key Pair - -// RSA modulus n: -static const char rsa_modulus_n_10[] = - "a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70 " - "ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5 " - "7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18 " - "75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad " - "cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12 " - "cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae " - "4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e " - "90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a " - "21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37 " - "39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea " - "45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73 " - "3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07 " - "0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17 " - "b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00 " - "1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82 " - "ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 "; -// RSA public exponent e: -static const char rsa_public_exponent_e_10[] = - "01 00 01 "; - -// RSASSA-PSS Signature Example 10.1 -// Message to be signed: -static const char message_10_1[] = - "88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c " - "6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 "; -// Salt: -static const char salt_10_1[] = - "04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab " - "fc ec de 89 "; -// Signature: -static const char signature_10_1[] = - "82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54 " - "06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5 " - "af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14 " - "8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2 " - "1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7 " - "9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74 " - "1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a " - "77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f " - "d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16 " - "59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e " - "57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb " - "3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00 " - "0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8 " - "e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04 " - "38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1 " - "b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 "; - -// RSASSA-PSS Signature Example 10.2 -// Message to be signed: -static const char message_10_2[] = - "dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c " - "52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13 " - "97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b " - "34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db " - "d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3 " - "c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75 " - "ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e " - "80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac "; -// Salt: -static const char salt_10_2[] = - "8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb " - "57 f9 b7 1b "; -// Signature: -static const char signature_10_2[] = - "14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c " - "d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30 " - "53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10 " - "11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28 " - "92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a " - "5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca " - "ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec " - "d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63 " - "7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22 " - "21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15 " - "99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68 " - "25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42 " - "31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab " - "c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd " - "26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26 " - "d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 "; - -// RSASSA-PSS Signature Example 10.3 -// Message to be signed: -static const char message_10_3[] = - "48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b " - "08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01 " - "93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6 " - "26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71 " - "ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d " - "e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1 " - "3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db "; -// Salt: -static const char salt_10_3[] = - "4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6 " - "e2 0c 2d 73 "; -// Signature: -static const char signature_10_3[] = - "6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb " - "39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5 " - "4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d " - "3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01 " - "02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a " - "a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5 " - "d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa " - "91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66 " - "f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78 " - "34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b " - "44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de " - "03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53 " - "1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19 " - "6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24 " - "71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5 " - "0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb "; - -// RSASSA-PSS Signature Example 10.4 -// Message to be signed: -static const char message_10_4[] = - "0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75 " - "5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4 " - "e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82 " - "db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a " - "62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45 " - "1a "; -// Salt: -static const char salt_10_4[] = - "c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0 " - "1c b5 41 ec "; -// Signature: -static const char signature_10_4[] = - "34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61 " - "a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd " - "ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93 " - "2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc " - "f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0 " - "2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34 " - "b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6 " - "6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce " - "c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45 " - "0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d " - "02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec " - "b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f " - "01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9 " - "2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d " - "de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6 " - "c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb "; - -// RSASSA-PSS Signature Example 10.5 -// Message to be signed: -static const char message_10_5[] = - "f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f " - "06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97 " - "6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98 " - "01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b " - "b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9 " - "16 "; -// Salt: -static const char salt_10_5[] = - "ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52 " - "65 5f 5d fb "; -// Signature: -static const char signature_10_5[] = - "7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c " - "55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3 " - "46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de " - "42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1 " - "f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38 " - "77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b " - "3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b " - "b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72 " - "1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05 " - "e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed " - "b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5 " - "a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9 " - "21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11 " - "26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24 " - "86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a " - "cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc "; - -// RSASSA-PSS Signature Example 10.6 -// Message to be signed: -static const char message_10_6[] = - "25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1 " - "f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5 " - "55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91 " - "dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52 " - "c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03 " - "23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0 " - "74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7 " - "d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37 " - "8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e " - "aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef " - "b8 af d7 "; -// Salt: -static const char salt_10_6[] = - "ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c " - "a2 d1 df 28 "; -// Signature: -static const char signature_10_6[] = - "6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21 " - "80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9 " - "b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12 " - "5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7 " - "b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91 " - "55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c " - "43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46 " - "bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81 " - "8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96 " - "d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e " - "f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18 " - "e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08 " - "8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed " - "94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59 " - "e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73 " - "2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f "; - -struct SignatureExample { - const char* message; - const char* salt; - const char* signature; -}; - -struct PSSTestVector { - const char* modulus_n; - const char* public_exponent_e; - SignatureExample example[6]; -}; - -static const PSSTestVector pss_test[] = { - { - rsa_modulus_n_1, - rsa_public_exponent_e_1, - { - { message_1_1, salt_1_1, signature_1_1 }, - { message_1_2, salt_1_2, signature_1_2 }, - { message_1_3, salt_1_3, signature_1_3 }, - { message_1_4, salt_1_4, signature_1_4 }, - { message_1_5, salt_1_5, signature_1_5 }, - { message_1_6, salt_1_6, signature_1_6 }, - } - }, - { - rsa_modulus_n_9, - rsa_public_exponent_e_9, - { - { message_9_1, salt_9_1, signature_9_1 }, - { message_9_2, salt_9_2, signature_9_2 }, - { message_9_3, salt_9_3, signature_9_3 }, - { message_9_4, salt_9_4, signature_9_4 }, - { message_9_5, salt_9_5, signature_9_5 }, - { message_9_6, salt_9_6, signature_9_6 }, - } - }, - { - rsa_modulus_n_10, - rsa_public_exponent_e_10, - { - { message_10_1, salt_10_1, signature_10_1 }, - { message_10_2, salt_10_2, signature_10_2 }, - { message_10_3, salt_10_3, signature_10_3 }, - { message_10_4, salt_10_4, signature_10_4 }, - { message_10_5, salt_10_5, signature_10_5 }, - { message_10_6, salt_10_6, signature_10_6 }, - } - }, -}; - -static uint8 HexDigitValue(char digit) { - if ('0' <= digit && digit <= '9') - return digit - '0'; - if ('a' <= digit && digit <= 'f') - return digit - 'a' + 10; - return digit - 'A' + 10; -} - -static bool DecodeTestInput(const char* in, std::vector* out) { - out->clear(); - while (in[0] != '\0') { - if (!isxdigit(in[0]) || !isxdigit(in[1]) || in[2] != ' ') - return false; - uint8 octet = HexDigitValue(in[0]) * 16 + HexDigitValue(in[1]); - out->push_back(octet); - in += 3; - } - return true; -} - -// PrependASN1Length prepends an ASN.1 serialized length to the beginning of -// |out|. -static void PrependASN1Length(std::vector* out, size_t len) { - if (len < 128) { - out->insert(out->begin(), static_cast(len)); - } else if (len < 256) { - out->insert(out->begin(), static_cast(len)); - out->insert(out->begin(), 0x81); - } else if (len < 0x10000) { - out->insert(out->begin(), static_cast(len)); - out->insert(out->begin(), static_cast(len >> 8)); - out->insert(out->begin(), 0x82); - } else { - CHECK(false) << "ASN.1 length not handled: " << len; - } -} - -static bool EncodeRSAPublicKey(const std::vector& modulus_n, - const std::vector& public_exponent_e, - std::vector* public_key_info) { - // The public key is specified as the following ASN.1 structure: - // SubjectPublicKeyInfo ::= SEQUENCE { - // algorithm AlgorithmIdentifier, - // subjectPublicKey BIT STRING } - // - // The signature algorithm is specified as the following ASN.1 structure: - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - // - // An RSA public key is specified as the following ASN.1 structure: - // RSAPublicKey ::= SEQUENCE { - // modulus INTEGER, -- n - // publicExponent INTEGER -- e - // } - static const uint8 kIntegerTag = 0x02; - static const uint8 kBitStringTag = 0x03; - static const uint8 kSequenceTag = 0x30; - public_key_info->clear(); - - // Encode the public exponent e as an INTEGER. - public_key_info->insert(public_key_info->begin(), - public_exponent_e.begin(), - public_exponent_e.end()); - PrependASN1Length(public_key_info, public_exponent_e.size()); - public_key_info->insert(public_key_info->begin(), kIntegerTag); - - // Encode the modulus n as an INTEGER. - public_key_info->insert(public_key_info->begin(), - modulus_n.begin(), modulus_n.end()); - size_t modulus_size = modulus_n.size(); - if (modulus_n[0] & 0x80) { - public_key_info->insert(public_key_info->begin(), 0x00); - modulus_size++; - } - PrependASN1Length(public_key_info, modulus_size); - public_key_info->insert(public_key_info->begin(), kIntegerTag); - - // Encode the RSAPublicKey SEQUENCE. - PrependASN1Length(public_key_info, public_key_info->size()); - public_key_info->insert(public_key_info->begin(), kSequenceTag); - - // Encode the BIT STRING. - // Number of unused bits. - public_key_info->insert(public_key_info->begin(), 0x00); - PrependASN1Length(public_key_info, public_key_info->size()); - public_key_info->insert(public_key_info->begin(), kBitStringTag); - - // Encode the AlgorithmIdentifier. - static const uint8 algorithm[] = { - 0x30, 0x0d, // a SEQUENCE of length 13 - 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, - }; - public_key_info->insert(public_key_info->begin(), - algorithm, algorithm + sizeof(algorithm)); - - // Encode the outermost SEQUENCE. - PrependASN1Length(public_key_info, public_key_info->size()); - public_key_info->insert(public_key_info->begin(), kSequenceTag); - - return true; -} - -TEST(SignatureVerifierTest, VerifyRSAPSS) { - for (unsigned int i = 0; i < arraysize(pss_test); i++) { - SCOPED_TRACE(i); - std::vector modulus_n; - std::vector public_exponent_e; - ASSERT_TRUE(DecodeTestInput(pss_test[i].modulus_n, &modulus_n)); - ASSERT_TRUE(DecodeTestInput(pss_test[i].public_exponent_e, - &public_exponent_e)); - std::vector public_key_info; - ASSERT_TRUE(EncodeRSAPublicKey(modulus_n, public_exponent_e, - &public_key_info)); - - for (unsigned int j = 0; j < arraysize(pss_test[i].example); j++) { - SCOPED_TRACE(j); - std::vector message; - std::vector salt; - std::vector signature; - ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].message, &message)); - ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].salt, &salt)); - ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].signature, - &signature)); - - crypto::SignatureVerifier verifier; - bool ok; - - // Positive test. - ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, - crypto::SignatureVerifier::SHA1, - salt.size(), - &signature[0], signature.size(), - &public_key_info[0], - public_key_info.size()); - ASSERT_TRUE(ok); - verifier.VerifyUpdate(&message[0], message.size()); - ok = verifier.VerifyFinal(); - EXPECT_TRUE(ok); - - // Modify the first byte of the message. - ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, - crypto::SignatureVerifier::SHA1, - salt.size(), - &signature[0], signature.size(), - &public_key_info[0], - public_key_info.size()); - ASSERT_TRUE(ok); - message[0] += 1; - verifier.VerifyUpdate(&message[0], message.size()); - message[0] -= 1; - ok = verifier.VerifyFinal(); - EXPECT_FALSE(ok); - - // Truncate the message. - ASSERT_FALSE(message.empty()); - ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, - crypto::SignatureVerifier::SHA1, - salt.size(), - &signature[0], signature.size(), - &public_key_info[0], - public_key_info.size()); - ASSERT_TRUE(ok); - verifier.VerifyUpdate(&message[0], message.size() - 1); - ok = verifier.VerifyFinal(); - EXPECT_FALSE(ok); - - // Corrupt the signature. - signature[0] += 1; - ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, - crypto::SignatureVerifier::SHA1, - salt.size(), - &signature[0], signature.size(), - &public_key_info[0], - public_key_info.size()); - signature[0] -= 1; - ASSERT_TRUE(ok); - verifier.VerifyUpdate(&message[0], message.size()); - ok = verifier.VerifyFinal(); - EXPECT_FALSE(ok); - } - } -} diff --git a/crypto/symmetric_key.h b/crypto/symmetric_key.h deleted file mode 100644 index 996c5923b1898..0000000000000 --- a/crypto/symmetric_key.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2012 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_SYMMETRIC_KEY_H_ -#define CRYPTO_SYMMETRIC_KEY_H_ - -#include - -#include "base/basictypes.h" -#include "crypto/crypto_export.h" - -#if defined(NACL_WIN64) -// See comments for crypto_nacl_win64 in crypto.gyp. -// Must test for NACL_WIN64 before OS_WIN since former is a subset of latter. -#include "crypto/scoped_capi_types.h" -#elif defined(USE_NSS_CERTS) || \ - (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX))) -#include "crypto/scoped_nss_types.h" -#endif - -namespace crypto { - -// Wraps a platform-specific symmetric key and allows it to be held in a -// scoped_ptr. -class CRYPTO_EXPORT SymmetricKey { - public: - // Defines the algorithm that a key will be used with. See also - // classs Encrptor. - enum Algorithm { - AES, - HMAC_SHA1, - }; - - virtual ~SymmetricKey(); - - // Generates a random key suitable to be used with |algorithm| and of - // |key_size_in_bits| bits. |key_size_in_bits| must be a multiple of 8. - // The caller is responsible for deleting the returned SymmetricKey. - static SymmetricKey* GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits); - - // Derives a key from the supplied password and salt using PBKDF2, suitable - // for use with specified |algorithm|. Note |algorithm| is not the algorithm - // used to derive the key from the password. |key_size_in_bits| must be a - // multiple of 8. The caller is responsible for deleting the returned - // SymmetricKey. - static SymmetricKey* DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits); - - // Imports an array of key bytes in |raw_key|. This key may have been - // generated by GenerateRandomKey or DeriveKeyFromPassword and exported with - // GetRawKey, or via another compatible method. The key must be of suitable - // size for use with |algorithm|. The caller owns the returned SymmetricKey. - static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key); - -#if defined(NACL_WIN64) - HCRYPTKEY key() const { return key_.get(); } -#elif defined(USE_OPENSSL) - const std::string& key() { return key_; } -#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) - PK11SymKey* key() const { return key_.get(); } -#endif - - // Extracts the raw key from the platform specific data. - // Warning: |raw_key| holds the raw key as bytes and thus must be handled - // carefully. - bool GetRawKey(std::string* raw_key); - - private: -#if defined(NACL_WIN64) - SymmetricKey(HCRYPTPROV provider, HCRYPTKEY key, - const void* key_data, size_t key_size_in_bytes); - - ScopedHCRYPTPROV provider_; - ScopedHCRYPTKEY key_; - - // Contains the raw key, if it is known during initialization and when it - // is likely that the associated |provider_| will be unable to export the - // |key_|. This is the case of HMAC keys when the key size exceeds 16 bytes - // when using the default RSA provider. - // TODO(rsleevi): See if KP_EFFECTIVE_KEYLEN is the reason why CryptExportKey - // fails with NTE_BAD_KEY/NTE_BAD_LEN - std::string raw_key_; -#elif defined(USE_OPENSSL) - SymmetricKey() {} - std::string key_; -#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX) - explicit SymmetricKey(PK11SymKey* key); - ScopedPK11SymKey key_; -#endif - - DISALLOW_COPY_AND_ASSIGN(SymmetricKey); -}; - -} // namespace crypto - -#endif // CRYPTO_SYMMETRIC_KEY_H_ diff --git a/crypto/symmetric_key_nss.cc b/crypto/symmetric_key_nss.cc deleted file mode 100644 index 95ca9bd073ed8..0000000000000 --- a/crypto/symmetric_key_nss.cc +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2012 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/symmetric_key.h" - -#include -#include - -#include "base/logging.h" -#include "crypto/nss_util.h" - -namespace crypto { - -SymmetricKey::~SymmetricKey() {} - -// static -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits) { - DCHECK_EQ(AES, algorithm); - - EnsureNSSInit(); - - // Whitelist supported key sizes to avoid accidentaly relying on - // algorithms available in NSS but not BoringSSL and vice - // versa. Note that BoringSSL does not support AES-192. - if (key_size_in_bits != 128 && key_size_in_bits != 256) - return NULL; - - ScopedPK11Slot slot(PK11_GetInternalSlot()); - if (!slot.get()) - return NULL; - - PK11SymKey* sym_key = PK11_KeyGen(slot.get(), CKM_AES_KEY_GEN, NULL, - key_size_in_bits / 8, NULL); - if (!sym_key) - return NULL; - - return new SymmetricKey(sym_key); -} - -// static -SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits) { - EnsureNSSInit(); - if (salt.empty() || iterations == 0 || key_size_in_bits == 0) - return NULL; - - if (algorithm == AES) { - // Whitelist supported key sizes to avoid accidentaly relying on - // algorithms available in NSS but not BoringSSL and vice - // versa. Note that BoringSSL does not support AES-192. - if (key_size_in_bits != 128 && key_size_in_bits != 256) - return NULL; - } - - SECItem password_item; - password_item.type = siBuffer; - password_item.data = reinterpret_cast( - const_cast(password.data())); - password_item.len = password.size(); - - SECItem salt_item; - salt_item.type = siBuffer; - salt_item.data = reinterpret_cast( - const_cast(salt.data())); - salt_item.len = salt.size(); - - SECOidTag cipher_algorithm = - algorithm == AES ? SEC_OID_AES_256_CBC : SEC_OID_HMAC_SHA1; - ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, - cipher_algorithm, - SEC_OID_HMAC_SHA1, - key_size_in_bits / 8, - iterations, - &salt_item)); - if (!alg_id.get()) - return NULL; - - ScopedPK11Slot slot(PK11_GetInternalSlot()); - if (!slot.get()) - return NULL; - - PK11SymKey* sym_key = PK11_PBEKeyGen(slot.get(), alg_id.get(), &password_item, - PR_FALSE, NULL); - if (!sym_key) - return NULL; - - return new SymmetricKey(sym_key); -} - -// static -SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const std::string& raw_key) { - EnsureNSSInit(); - - if (algorithm == AES) { - // Whitelist supported key sizes to avoid accidentaly relying on - // algorithms available in NSS but not BoringSSL and vice - // versa. Note that BoringSSL does not support AES-192. - if (raw_key.size() != 128/8 && raw_key.size() != 256/8) - return NULL; - } - - CK_MECHANISM_TYPE cipher = - algorithm == AES ? CKM_AES_CBC : CKM_SHA_1_HMAC; - - SECItem key_item; - key_item.type = siBuffer; - key_item.data = reinterpret_cast( - const_cast(raw_key.data())); - key_item.len = raw_key.size(); - - ScopedPK11Slot slot(PK11_GetInternalSlot()); - if (!slot.get()) - return NULL; - - // The exact value of the |origin| argument doesn't matter to NSS as long as - // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a - // placeholder. - PK11SymKey* sym_key = PK11_ImportSymKey(slot.get(), cipher, PK11_OriginUnwrap, - CKA_ENCRYPT, &key_item, NULL); - if (!sym_key) - return NULL; - - return new SymmetricKey(sym_key); -} - -bool SymmetricKey::GetRawKey(std::string* raw_key) { - SECStatus rv = PK11_ExtractKeyValue(key_.get()); - if (SECSuccess != rv) - return false; - - SECItem* key_item = PK11_GetKeyData(key_.get()); - if (!key_item) - return false; - - raw_key->assign(reinterpret_cast(key_item->data), key_item->len); - return true; -} - -SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) { - DCHECK(key); -} - -} // namespace crypto diff --git a/crypto/symmetric_key_openssl.cc b/crypto/symmetric_key_openssl.cc deleted file mode 100644 index 912c9b4db2d74..0000000000000 --- a/crypto/symmetric_key_openssl.cc +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2011 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/symmetric_key.h" - -#include -#include - -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_util.h" -#include "crypto/openssl_util.h" - -namespace crypto { - -SymmetricKey::~SymmetricKey() { - std::fill(key_.begin(), key_.end(), '\0'); // Zero out the confidential key. -} - -// static -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits) { - DCHECK_EQ(AES, algorithm); - - // Whitelist supported key sizes to avoid accidentaly relying on - // algorithms available in NSS but not BoringSSL and vice - // versa. Note that BoringSSL does not support AES-192. - if (key_size_in_bits != 128 && key_size_in_bits != 256) - return NULL; - - size_t key_size_in_bytes = key_size_in_bits / 8; - DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8); - - if (key_size_in_bytes == 0) - return NULL; - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - scoped_ptr key(new SymmetricKey); - uint8* key_data = reinterpret_cast( - base::WriteInto(&key->key_, key_size_in_bytes + 1)); - - int rv = RAND_bytes(key_data, static_cast(key_size_in_bytes)); - return rv == 1 ? key.release() : NULL; -} - -// static -SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits) { - DCHECK(algorithm == AES || algorithm == HMAC_SHA1); - - if (algorithm == AES) { - // Whitelist supported key sizes to avoid accidentaly relying on - // algorithms available in NSS but not BoringSSL and vice - // versa. Note that BoringSSL does not support AES-192. - if (key_size_in_bits != 128 && key_size_in_bits != 256) - return NULL; - } - - size_t key_size_in_bytes = key_size_in_bits / 8; - DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8); - - if (key_size_in_bytes == 0) - return NULL; - - OpenSSLErrStackTracer err_tracer(FROM_HERE); - scoped_ptr key(new SymmetricKey); - uint8* key_data = reinterpret_cast( - base::WriteInto(&key->key_, key_size_in_bytes + 1)); - int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(), - reinterpret_cast(salt.data()), - salt.length(), iterations, - static_cast(key_size_in_bytes), - key_data); - return rv == 1 ? key.release() : NULL; -} - -// static -SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const std::string& raw_key) { - if (algorithm == AES) { - // Whitelist supported key sizes to avoid accidentaly relying on - // algorithms available in NSS but not BoringSSL and vice - // versa. Note that BoringSSL does not support AES-192. - if (raw_key.size() != 128/8 && raw_key.size() != 256/8) - return NULL; - } - - scoped_ptr key(new SymmetricKey); - key->key_ = raw_key; - return key.release(); -} - -bool SymmetricKey::GetRawKey(std::string* raw_key) { - *raw_key = key_; - return true; -} - -} // namespace crypto diff --git a/crypto/symmetric_key_unittest.cc b/crypto/symmetric_key_unittest.cc deleted file mode 100644 index 28e44d27da7ac..0000000000000 --- a/crypto/symmetric_key_unittest.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2011 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/symmetric_key.h" - -#include - -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(SymmetricKeyTest, GenerateRandomKey) { - scoped_ptr key( - crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); - ASSERT_TRUE(NULL != key.get()); - std::string raw_key; - EXPECT_TRUE(key->GetRawKey(&raw_key)); - EXPECT_EQ(32U, raw_key.size()); - - // Do it again and check that the keys are different. - // (Note: this has a one-in-10^77 chance of failure!) - scoped_ptr key2( - crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); - ASSERT_TRUE(NULL != key2.get()); - std::string raw_key2; - EXPECT_TRUE(key2->GetRawKey(&raw_key2)); - EXPECT_EQ(32U, raw_key2.size()); - EXPECT_NE(raw_key, raw_key2); -} - -TEST(SymmetricKeyTest, ImportGeneratedKey) { - scoped_ptr key1( - crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); - ASSERT_TRUE(NULL != key1.get()); - std::string raw_key1; - EXPECT_TRUE(key1->GetRawKey(&raw_key1)); - - scoped_ptr key2( - crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key1)); - ASSERT_TRUE(NULL != key2.get()); - - std::string raw_key2; - EXPECT_TRUE(key2->GetRawKey(&raw_key2)); - - EXPECT_EQ(raw_key1, raw_key2); -} - -TEST(SymmetricKeyTest, ImportDerivedKey) { - scoped_ptr key1( - crypto::SymmetricKey::DeriveKeyFromPassword( - crypto::SymmetricKey::HMAC_SHA1, "password", "somesalt", 1024, 160)); - ASSERT_TRUE(NULL != key1.get()); - std::string raw_key1; - EXPECT_TRUE(key1->GetRawKey(&raw_key1)); - - scoped_ptr key2( - crypto::SymmetricKey::Import(crypto::SymmetricKey::HMAC_SHA1, raw_key1)); - ASSERT_TRUE(NULL != key2.get()); - - std::string raw_key2; - EXPECT_TRUE(key2->GetRawKey(&raw_key2)); - - EXPECT_EQ(raw_key1, raw_key2); -} - -struct PBKDF2TestVector { - crypto::SymmetricKey::Algorithm algorithm; - const char* password; - const char* salt; - unsigned int rounds; - unsigned int key_size_in_bits; - const char* expected; // ASCII encoded hex bytes -}; - -class SymmetricKeyDeriveKeyFromPasswordTest - : public testing::TestWithParam { -}; - -TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) { - PBKDF2TestVector test_data(GetParam()); -#if defined(OS_MACOSX) && !defined(OS_IOS) - // The OS X crypto libraries have minimum salt and iteration requirements - // so some of the tests below will cause them to barf. Skip these. - if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) { - VLOG(1) << "Skipped test vector for " << test_data.expected; - return; - } -#endif // OS_MACOSX - - scoped_ptr key( - crypto::SymmetricKey::DeriveKeyFromPassword( - test_data.algorithm, - test_data.password, test_data.salt, - test_data.rounds, test_data.key_size_in_bits)); - ASSERT_TRUE(NULL != key.get()); - - std::string raw_key; - key->GetRawKey(&raw_key); - EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size()); - EXPECT_EQ(test_data.expected, - base::StringToLowerASCII(base::HexEncode(raw_key.data(), - raw_key.size()))); -} - -static const PBKDF2TestVector kTestVectors[] = { - // These tests come from - // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 1, - 160, - "0c60c80f961f0e71f3a9b524af6012062fe037a6", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 2, - 160, - "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 4096, - 160, - "4b007901b765489abead49d926f721d065a429c1", - }, - // This test takes over 30s to run on the trybots. -#if 0 - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "salt", - 16777216, - 160, - "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984", - }, -#endif - - // These tests come from RFC 3962, via BSD source code at - // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "ATHENA.MIT.EDUraeburn", - 1, - 160, - "cdedb5281bb2f801565a1122b25635150ad1f7a0", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "ATHENA.MIT.EDUraeburn", - 2, - 160, - "01dbee7f4a9e243e988b62c73cda935da05378b9", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "ATHENA.MIT.EDUraeburn", - 1200, - 160, - "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "password", - "\022" "4VxxV4\022", /* 0x1234567878563412 */ - 5, - 160, - "d1daa78615f287e6a1c8b120d7062a493f98d203", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "pass phrase equals block size", - 1200, - 160, - "139c30c0966bc32ba55fdbf212530ac9c5ec59f1", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "pass phrase exceeds block size", - 1200, - 160, - "9ccad6d468770cd51b10e6a68721be611a8b4d28", - }, - { - crypto::SymmetricKey::HMAC_SHA1, - "\360\235\204\236", /* g-clef (0xf09d849e) */ - "EXAMPLE.COMpianist", - 50, - 160, - "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0", - }, - - // Regression tests for AES keys, derived from the Linux NSS implementation. - { - crypto::SymmetricKey::AES, - "A test password", - "saltsalt", - 1, - 256, - "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de", - }, - { - crypto::SymmetricKey::AES, - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "pass phrase exceeds block size", - 20, - 256, - "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c", - }, -}; - -INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest, - testing::ValuesIn(kTestVectors)); diff --git a/crypto/symmetric_key_win.cc b/crypto/symmetric_key_win.cc deleted file mode 100644 index b3d65f6613760..0000000000000 --- a/crypto/symmetric_key_win.cc +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright (c) 2012 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/symmetric_key.h" - -#include - -// TODO(wtc): replace scoped_array by std::vector. -#include "base/memory/scoped_ptr.h" -#include "base/sys_byteorder.h" - -namespace crypto { - -namespace { - -// The following is a non-public Microsoft header documented in MSDN under -// CryptImportKey / CryptExportKey. Following the header is the byte array of -// the actual plaintext key. -struct PlaintextBlobHeader { - BLOBHEADER hdr; - DWORD cbKeySize; -}; - -// CryptoAPI makes use of three distinct ALG_IDs for AES, rather than just -// CALG_AES (which exists, but depending on the functions you are calling, may -// result in function failure, whereas the subtype would succeed). -ALG_ID GetAESAlgIDForKeySize(size_t key_size_in_bits) { - // Only AES-128/-192/-256 is supported in CryptoAPI. - switch (key_size_in_bits) { - case 128: - return CALG_AES_128; - case 192: - return CALG_AES_192; - case 256: - return CALG_AES_256; - default: - NOTREACHED(); - return 0; - } -}; - -// Imports a raw/plaintext key of |key_size| stored in |*key_data| into a new -// key created for the specified |provider|. |alg| contains the algorithm of -// the key being imported. -// If |key_data| is intended to be used as an HMAC key, then |alg| should be -// CALG_HMAC. -// If successful, returns true and stores the imported key in |*key|. -// TODO(wtc): use this function in hmac_win.cc. -bool ImportRawKey(HCRYPTPROV provider, - ALG_ID alg, - const void* key_data, size_t key_size, - ScopedHCRYPTKEY* key) { - DCHECK_GT(key_size, 0); - - DWORD actual_size = - static_cast(sizeof(PlaintextBlobHeader) + key_size); - std::vector tmp_data(actual_size); - BYTE* actual_key = &tmp_data[0]; - memcpy(actual_key + sizeof(PlaintextBlobHeader), key_data, key_size); - PlaintextBlobHeader* key_header = - reinterpret_cast(actual_key); - memset(key_header, 0, sizeof(PlaintextBlobHeader)); - - key_header->hdr.bType = PLAINTEXTKEYBLOB; - key_header->hdr.bVersion = CUR_BLOB_VERSION; - key_header->hdr.aiKeyAlg = alg; - - key_header->cbKeySize = static_cast(key_size); - - HCRYPTKEY unsafe_key = NULL; - DWORD flags = CRYPT_EXPORTABLE; - if (alg == CALG_HMAC) { - // Though it may appear odd that IPSEC and RC2 are being used, this is - // done in accordance with Microsoft's FIPS 140-2 Security Policy for the - // RSA Enhanced Provider, as the approved means of using arbitrary HMAC - // key material. - key_header->hdr.aiKeyAlg = CALG_RC2; - flags |= CRYPT_IPSEC_HMAC_KEY; - } - - BOOL ok = - CryptImportKey(provider, actual_key, actual_size, 0, flags, &unsafe_key); - - // Clean up the temporary copy of key, regardless of whether it was imported - // sucessfully or not. - SecureZeroMemory(actual_key, actual_size); - - if (!ok) - return false; - - key->reset(unsafe_key); - return true; -} - -// Attempts to generate a random AES key of |key_size_in_bits|. Returns true -// if generation is successful, storing the generated key in |*key| and the -// key provider (CSP) in |*provider|. -bool GenerateAESKey(size_t key_size_in_bits, - ScopedHCRYPTPROV* provider, - ScopedHCRYPTKEY* key) { - DCHECK(provider); - DCHECK(key); - - ALG_ID alg = GetAESAlgIDForKeySize(key_size_in_bits); - if (alg == 0) - return false; - - ScopedHCRYPTPROV safe_provider; - // Note: The only time NULL is safe to be passed as pszContainer is when - // dwFlags contains CRYPT_VERIFYCONTEXT, as all keys generated and/or used - // will be treated as ephemeral keys and not persisted. - BOOL ok = CryptAcquireContext(safe_provider.receive(), NULL, NULL, - PROV_RSA_AES, CRYPT_VERIFYCONTEXT); - if (!ok) - return false; - - ScopedHCRYPTKEY safe_key; - // In the FIPS 140-2 Security Policy for CAPI on XP/Vista+, Microsoft notes - // that CryptGenKey makes use of the same functionality exposed via - // CryptGenRandom. The reason this is being used, as opposed to - // CryptGenRandom and CryptImportKey is for compliance with the security - // policy - ok = CryptGenKey(safe_provider.get(), alg, CRYPT_EXPORTABLE, - safe_key.receive()); - if (!ok) - return false; - - key->swap(safe_key); - provider->swap(safe_provider); - - return true; -} - -// Returns true if the HMAC key size meets the requirement of FIPS 198 -// Section 3. |alg| is the hash function used in the HMAC. -bool CheckHMACKeySize(size_t key_size_in_bits, ALG_ID alg) { - DWORD hash_size = 0; - switch (alg) { - case CALG_SHA1: - hash_size = 20; - break; - case CALG_SHA_256: - hash_size = 32; - break; - case CALG_SHA_384: - hash_size = 48; - break; - case CALG_SHA_512: - hash_size = 64; - break; - } - if (hash_size == 0) - return false; - - // An HMAC key must be >= L/2, where L is the output size of the hash - // function being used. - return (key_size_in_bits >= (hash_size / 2 * 8) && - (key_size_in_bits % 8) == 0); -} - -// Attempts to generate a random, |key_size_in_bits|-long HMAC key, for use -// with the hash function |alg|. -// |key_size_in_bits| must be >= 1/2 the hash size of |alg| for security. -// Returns true if generation is successful, storing the generated key in -// |*key| and the key provider (CSP) in |*provider|. -bool GenerateHMACKey(size_t key_size_in_bits, - ALG_ID alg, - ScopedHCRYPTPROV* provider, - ScopedHCRYPTKEY* key, - scoped_ptr* raw_key) { - DCHECK(provider); - DCHECK(key); - DCHECK(raw_key); - - if (!CheckHMACKeySize(key_size_in_bits, alg)) - return false; - - ScopedHCRYPTPROV safe_provider; - // See comment in GenerateAESKey as to why NULL is acceptable for the - // container name. - BOOL ok = CryptAcquireContext(safe_provider.receive(), NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - if (!ok) - return false; - - DWORD key_size_in_bytes = static_cast(key_size_in_bits / 8); - scoped_ptr random(new BYTE[key_size_in_bytes]); - ok = CryptGenRandom(safe_provider, key_size_in_bytes, random.get()); - if (!ok) - return false; - - ScopedHCRYPTKEY safe_key; - bool rv = ImportRawKey(safe_provider, CALG_HMAC, random.get(), - key_size_in_bytes, &safe_key); - if (rv) { - key->swap(safe_key); - provider->swap(safe_provider); - raw_key->swap(random); - } - - SecureZeroMemory(random.get(), key_size_in_bytes); - return rv; -} - -// Attempts to create an HMAC hash instance using the specified |provider| -// and |key|. The inner hash function will be |hash_alg|. If successful, -// returns true and stores the hash in |*hash|. -// TODO(wtc): use this function in hmac_win.cc. -bool CreateHMACHash(HCRYPTPROV provider, - HCRYPTKEY key, - ALG_ID hash_alg, - ScopedHCRYPTHASH* hash) { - ScopedHCRYPTHASH safe_hash; - BOOL ok = CryptCreateHash(provider, CALG_HMAC, key, 0, safe_hash.receive()); - if (!ok) - return false; - - HMAC_INFO hmac_info; - memset(&hmac_info, 0, sizeof(hmac_info)); - hmac_info.HashAlgid = hash_alg; - - ok = CryptSetHashParam(safe_hash, HP_HMAC_INFO, - reinterpret_cast(&hmac_info), 0); - if (!ok) - return false; - - hash->swap(safe_hash); - return true; -} - -// Computes a block of the derived key using the PBKDF2 function F for the -// specified |block_index| using the PRF |hash|, writing the output to -// |output_buf|. -// |output_buf| must have enough space to accomodate the output of the PRF -// specified by |hash|. -// Returns true if the block was successfully computed. -bool ComputePBKDF2Block(HCRYPTHASH hash, - DWORD hash_size, - const std::string& salt, - size_t iterations, - uint32 block_index, - BYTE* output_buf) { - // From RFC 2898: - // 3. The function F is defined as the exclusive-or sum of the first - // c iterates of the underlying pseudorandom function PRF applied to the - // password P and the concatenation of the salt S and the block index i: - // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c - // where - // U_1 = PRF(P, S || INT (i)) - // U_2 = PRF(P, U_1) - // ... - // U_c = PRF(P, U_{c-1}) - ScopedHCRYPTHASH safe_hash; - BOOL ok = CryptDuplicateHash(hash, NULL, 0, safe_hash.receive()); - if (!ok) - return false; - - // Iteration U_1: Compute PRF for S. - ok = CryptHashData(safe_hash, reinterpret_cast(salt.data()), - static_cast(salt.size()), 0); - if (!ok) - return false; - - // Iteration U_1: and append (big-endian) INT (i). - uint32 big_endian_block_index = base::HostToNet32(block_index); - ok = CryptHashData(safe_hash, - reinterpret_cast(&big_endian_block_index), - sizeof(big_endian_block_index), 0); - - std::vector hash_value(hash_size); - - DWORD size = hash_size; - ok = CryptGetHashParam(safe_hash, HP_HASHVAL, &hash_value[0], &size, 0); - if (!ok || size != hash_size) - return false; - - memcpy(output_buf, &hash_value[0], hash_size); - - // Iteration 2 - c: Compute U_{iteration} by applying the PRF to - // U_{iteration - 1}, then xor the resultant hash with |output|, which - // contains U_1 ^ U_2 ^ ... ^ U_{iteration - 1}. - for (size_t iteration = 2; iteration <= iterations; ++iteration) { - safe_hash.reset(); - ok = CryptDuplicateHash(hash, NULL, 0, safe_hash.receive()); - if (!ok) - return false; - - ok = CryptHashData(safe_hash, &hash_value[0], hash_size, 0); - if (!ok) - return false; - - size = hash_size; - ok = CryptGetHashParam(safe_hash, HP_HASHVAL, &hash_value[0], &size, 0); - if (!ok || size != hash_size) - return false; - - for (int i = 0; i < hash_size; ++i) - output_buf[i] ^= hash_value[i]; - } - - return true; -} - -} // namespace - -SymmetricKey::~SymmetricKey() { - // TODO(wtc): create a "secure" string type that zeroes itself in the - // destructor. - if (!raw_key_.empty()) - SecureZeroMemory(const_cast(raw_key_.data()), raw_key_.size()); -} - -// static -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, - size_t key_size_in_bits) { - DCHECK_GE(key_size_in_bits, 8); - - ScopedHCRYPTPROV provider; - ScopedHCRYPTKEY key; - - bool ok = false; - scoped_ptr raw_key; - - switch (algorithm) { - case AES: - ok = GenerateAESKey(key_size_in_bits, &provider, &key); - break; - case HMAC_SHA1: - ok = GenerateHMACKey(key_size_in_bits, CALG_SHA1, &provider, - &key, &raw_key); - break; - } - - if (!ok) { - NOTREACHED(); - return NULL; - } - - size_t key_size_in_bytes = key_size_in_bits / 8; - if (raw_key == NULL) - key_size_in_bytes = 0; - - SymmetricKey* result = new SymmetricKey(provider.release(), - key.release(), - raw_key.get(), - key_size_in_bytes); - if (raw_key != NULL) - SecureZeroMemory(raw_key.get(), key_size_in_bytes); - - return result; -} - -// static -SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, - const std::string& password, - const std::string& salt, - size_t iterations, - size_t key_size_in_bits) { - // CryptoAPI lacks routines to perform PBKDF2 derivation as specified - // in RFC 2898, so it must be manually implemented. Only HMAC-SHA1 is - // supported as the PRF. - - // While not used until the end, sanity-check the input before proceeding - // with the expensive computation. - DWORD provider_type = 0; - ALG_ID alg = 0; - switch (algorithm) { - case AES: - provider_type = PROV_RSA_AES; - alg = GetAESAlgIDForKeySize(key_size_in_bits); - break; - case HMAC_SHA1: - provider_type = PROV_RSA_FULL; - alg = CALG_HMAC; - break; - default: - NOTREACHED(); - break; - } - if (provider_type == 0 || alg == 0) - return NULL; - - ScopedHCRYPTPROV provider; - BOOL ok = CryptAcquireContext(provider.receive(), NULL, NULL, provider_type, - CRYPT_VERIFYCONTEXT); - if (!ok) - return NULL; - - // Convert the user password into a key suitable to be fed into the PRF - // function. - ScopedHCRYPTKEY password_as_key; - BYTE* password_as_bytes = - const_cast(reinterpret_cast(password.data())); - if (!ImportRawKey(provider, CALG_HMAC, password_as_bytes, - password.size(), &password_as_key)) - return NULL; - - // Configure the PRF function. Only HMAC variants are supported, with the - // only hash function supported being SHA1. - // TODO(rsleevi): Support SHA-256 on XP SP3+. - ScopedHCRYPTHASH prf; - if (!CreateHMACHash(provider, password_as_key, CALG_SHA1, &prf)) - return NULL; - - DWORD hLen = 0; - DWORD param_size = sizeof(hLen); - ok = CryptGetHashParam(prf, HP_HASHSIZE, - reinterpret_cast(&hLen), ¶m_size, 0); - if (!ok || hLen == 0) - return NULL; - - // 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop. - size_t dkLen = key_size_in_bits / 8; - DCHECK_GT(dkLen, 0); - - if ((dkLen / hLen) > 0xFFFFFFFF) { - DLOG(ERROR) << "Derived key too long."; - return NULL; - } - - // 2. Let l be the number of hLen-octet blocks in the derived key, - // rounding up, and let r be the number of octets in the last - // block: - size_t L = (dkLen + hLen - 1) / hLen; - DCHECK_GT(L, 0); - - size_t total_generated_size = L * hLen; - std::vector generated_key(total_generated_size); - BYTE* block_offset = &generated_key[0]; - - // 3. For each block of the derived key apply the function F defined below - // to the password P, the salt S, the iteration count c, and the block - // index to compute the block: - // T_1 = F (P, S, c, 1) - // T_2 = F (P, S, c, 2) - // ... - // T_l = F (P, S, c, l) - // - // 4. Concatenate the blocks and extract the first dkLen octets to produce - // a derived key DK: - // DK = T_1 || T_2 || ... || T_l<0..r-1> - for (uint32 block_index = 1; block_index <= L; ++block_index) { - if (!ComputePBKDF2Block(prf, hLen, salt, iterations, block_index, - block_offset)) - return NULL; - block_offset += hLen; - } - - // Convert the derived key bytes into a key handle for the desired algorithm. - ScopedHCRYPTKEY key; - if (!ImportRawKey(provider, alg, &generated_key[0], dkLen, &key)) - return NULL; - - SymmetricKey* result = new SymmetricKey(provider.release(), key.release(), - &generated_key[0], dkLen); - - SecureZeroMemory(&generated_key[0], total_generated_size); - - return result; -} - -// static -SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const std::string& raw_key) { - DWORD provider_type = 0; - ALG_ID alg = 0; - switch (algorithm) { - case AES: - provider_type = PROV_RSA_AES; - alg = GetAESAlgIDForKeySize(raw_key.size() * 8); - break; - case HMAC_SHA1: - provider_type = PROV_RSA_FULL; - alg = CALG_HMAC; - break; - default: - NOTREACHED(); - break; - } - if (provider_type == 0 || alg == 0) - return NULL; - - ScopedHCRYPTPROV provider; - BOOL ok = CryptAcquireContext(provider.receive(), NULL, NULL, provider_type, - CRYPT_VERIFYCONTEXT); - if (!ok) - return NULL; - - ScopedHCRYPTKEY key; - if (!ImportRawKey(provider, alg, raw_key.data(), raw_key.size(), &key)) - return NULL; - - return new SymmetricKey(provider.release(), key.release(), - raw_key.data(), raw_key.size()); -} - -bool SymmetricKey::GetRawKey(std::string* raw_key) { - // Short circuit for when the key was supplied to the constructor. - if (!raw_key_.empty()) { - *raw_key = raw_key_; - return true; - } - - DWORD size = 0; - BOOL ok = CryptExportKey(key_, 0, PLAINTEXTKEYBLOB, 0, NULL, &size); - if (!ok) - return false; - - std::vector result(size); - - ok = CryptExportKey(key_, 0, PLAINTEXTKEYBLOB, 0, &result[0], &size); - if (!ok) - return false; - - PlaintextBlobHeader* header = - reinterpret_cast(&result[0]); - raw_key->assign(reinterpret_cast(&result[sizeof(*header)]), - header->cbKeySize); - - SecureZeroMemory(&result[0], size); - - return true; -} - -SymmetricKey::SymmetricKey(HCRYPTPROV provider, - HCRYPTKEY key, - const void* key_data, size_t key_size_in_bytes) - : provider_(provider), key_(key) { - if (key_data) { - raw_key_.assign(reinterpret_cast(key_data), - key_size_in_bytes); - } -} - -} // namespace crypto diff --git a/crypto/third_party/nss/LICENSE b/crypto/third_party/nss/LICENSE deleted file mode 100644 index 03671648c17a3..0000000000000 --- a/crypto/third_party/nss/LICENSE +++ /dev/null @@ -1,35 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ diff --git a/crypto/third_party/nss/README.chromium b/crypto/third_party/nss/README.chromium deleted file mode 100644 index 1a63665e6fa17..0000000000000 --- a/crypto/third_party/nss/README.chromium +++ /dev/null @@ -1,18 +0,0 @@ -Name: Network Security Services (NSS) -URL: http://www.mozilla.org/projects/security/pki/nss/ -License: MPL 1.1/GPL 2.0/LGPL 2.1 - -We extracted the SHA-256 source files, eliminated unneeded dependencies, -deleted or commented out unused code, and tweaked them for Chrome's source -tree. sha512.c is renamed sha512.cc so that it can include Chrome's C++ -header "base/basictypes.h". We define NOUNROLL256 to reduce the object code -size. - -In blapi.h and sha512.cc, replaced uint32 by unsigned int so that they can -be compiled with -DNO_NSPR_10_SUPPORT. NO_NSPR_10_SUPPORT turns off the -definition of the NSPR 1.0 types int8 - int64 and uint8 - uint64 to avoid -conflict with the same-named types defined in "base/basictypes.h". - -rsawrapr.c is copied from nss/lib/softoken/rsawrapr.c, with -HASH_GetRawHashObject changed to HASH_GetHashObject. It contains the -emsa_pss_verify function for verifying RSA-PSS signatures. diff --git a/crypto/third_party/nss/chromium-blapi.h b/crypto/third_party/nss/chromium-blapi.h deleted file mode 100644 index 2ca772e4d3294..0000000000000 --- a/crypto/third_party/nss/chromium-blapi.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * crypto.h - public data structures and prototypes for the crypto library - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dr Vipul Gupta , Sun Microsystems Laboratories - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* $Id: blapi.h,v 1.27 2007/11/09 18:49:32 wtc%google.com Exp $ */ - -#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ -#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ - -#include "crypto/third_party/nss/chromium-blapit.h" - -/******************************************/ - -extern SHA256Context *SHA256_NewContext(void); -extern void SHA256_DestroyContext(SHA256Context *cx, PRBool freeit); -extern void SHA256_Begin(SHA256Context *cx); -extern void SHA256_Update(SHA256Context *cx, const unsigned char *input, - unsigned int inputLen); -extern void SHA256_End(SHA256Context *cx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen); -extern SECStatus SHA256_HashBuf(unsigned char *dest, const unsigned char *src, - unsigned int src_length); -extern SECStatus SHA256_Hash(unsigned char *dest, const char *src); -extern void SHA256_TraceState(SHA256Context *cx); -extern unsigned int SHA256_FlattenSize(SHA256Context *cx); -extern SECStatus SHA256_Flatten(SHA256Context *cx,unsigned char *space); -extern SHA256Context * SHA256_Resurrect(unsigned char *space, void *arg); -extern void SHA256_Clone(SHA256Context *dest, SHA256Context *src); - -/******************************************/ - -extern SHA512Context *SHA512_NewContext(void); -extern void SHA512_DestroyContext(SHA512Context *cx, PRBool freeit); -extern void SHA512_Begin(SHA512Context *cx); -extern void SHA512_Update(SHA512Context *cx, const unsigned char *input, - unsigned int inputLen); -extern void SHA512_End(SHA512Context *cx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen); -extern SECStatus SHA512_HashBuf(unsigned char *dest, const unsigned char *src, - unsigned int src_length); -extern SECStatus SHA512_Hash(unsigned char *dest, const char *src); -extern void SHA512_TraceState(SHA512Context *cx); -extern unsigned int SHA512_FlattenSize(SHA512Context *cx); -extern SECStatus SHA512_Flatten(SHA512Context *cx,unsigned char *space); -extern SHA512Context * SHA512_Resurrect(unsigned char *space, void *arg); -extern void SHA512_Clone(SHA512Context *dest, SHA512Context *src); - -/******************************************/ - -extern SHA384Context *SHA384_NewContext(void); -extern void SHA384_DestroyContext(SHA384Context *cx, PRBool freeit); -extern void SHA384_Begin(SHA384Context *cx); -extern void SHA384_Update(SHA384Context *cx, const unsigned char *input, - unsigned int inputLen); -extern void SHA384_End(SHA384Context *cx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen); -extern SECStatus SHA384_HashBuf(unsigned char *dest, const unsigned char *src, - unsigned int src_length); -extern SECStatus SHA384_Hash(unsigned char *dest, const char *src); -extern void SHA384_TraceState(SHA384Context *cx); -extern unsigned int SHA384_FlattenSize(SHA384Context *cx); -extern SECStatus SHA384_Flatten(SHA384Context *cx,unsigned char *space); -extern SHA384Context * SHA384_Resurrect(unsigned char *space, void *arg); -extern void SHA384_Clone(SHA384Context *dest, SHA384Context *src); - -#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ */ diff --git a/crypto/third_party/nss/chromium-blapit.h b/crypto/third_party/nss/chromium-blapit.h deleted file mode 100644 index 938547a2c0666..0000000000000 --- a/crypto/third_party/nss/chromium-blapit.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * blapit.h - public data structures for the crypto library - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dr Vipul Gupta and - * Douglas Stebila , Sun Microsystems Laboratories - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* $Id: blapit.h,v 1.20 2007/02/28 19:47:37 rrelyea%redhat.com Exp $ */ - -#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ -#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ - -#include "crypto/third_party/nss/chromium-prtypes.h" - -/* -** A status code. Status's are used by procedures that return status -** values. Again the motivation is so that a compiler can generate -** warnings when return values are wrong. Correct testing of status codes: -** -** SECStatus rv; -** rv = some_function (some_argument); -** if (rv != SECSuccess) -** do_an_error_thing(); -** -*/ -typedef enum _SECStatus { - SECWouldBlock = -2, - SECFailure = -1, - SECSuccess = 0 -} SECStatus; - -#define SHA256_LENGTH 32 /* bytes */ -#define SHA384_LENGTH 48 /* bytes */ -#define SHA512_LENGTH 64 /* bytes */ -#define HASH_LENGTH_MAX SHA512_LENGTH - -/* - * Input block size for each hash algorithm. - */ - -#define SHA256_BLOCK_LENGTH 64 /* bytes */ -#define SHA384_BLOCK_LENGTH 128 /* bytes */ -#define SHA512_BLOCK_LENGTH 128 /* bytes */ -#define HASH_BLOCK_LENGTH_MAX SHA512_BLOCK_LENGTH - -/*************************************************************************** -** Opaque objects -*/ - -struct SHA256ContextStr ; -struct SHA512ContextStr ; - -typedef struct SHA256ContextStr SHA256Context; -typedef struct SHA512ContextStr SHA512Context; -/* SHA384Context is really a SHA512ContextStr. This is not a mistake. */ -typedef struct SHA512ContextStr SHA384Context; - -#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ */ diff --git a/crypto/third_party/nss/chromium-nss.h b/crypto/third_party/nss/chromium-nss.h deleted file mode 100644 index 437e6bd5cdb61..0000000000000 --- a/crypto/third_party/nss/chromium-nss.h +++ /dev/null @@ -1,79 +0,0 @@ - /* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_ -#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_ - -// This file contains some functions we borrowed from NSS. - -#include -#include -#include -#include - -#include "crypto/crypto_export.h" - -extern "C" SECStatus emsa_pss_verify(const unsigned char *mHash, - const unsigned char *em, - unsigned int emLen, - HASH_HashType hashAlg, - HASH_HashType maskHashAlg, - unsigned int sLen); - -// Like PK11_ImportEncryptedPrivateKeyInfo, but hardcoded for EC, and returns -// the SECKEYPrivateKey. -// See https://bugzilla.mozilla.org/show_bug.cgi?id=211546 -// When we use NSS 3.13.2 or later, -// PK11_ImportEncryptedPrivateKeyInfoAndReturnKey can be used instead. -SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey( - PK11SlotInfo* slot, - SECKEYEncryptedPrivateKeyInfo* epki, - SECItem* password, - SECItem* nickname, - SECItem* public_value, - PRBool permanent, - PRBool sensitive, - SECKEYPrivateKey** private_key, - void* wincx); - -// Like SEC_DerSignData. -CRYPTO_EXPORT SECStatus DerSignData(PLArenaPool *arena, - SECItem *result, - SECItem *input, - SECKEYPrivateKey *key, - SECOidTag algo_id); - -#endif // CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_ diff --git a/crypto/third_party/nss/chromium-prtypes.h b/crypto/third_party/nss/chromium-prtypes.h deleted file mode 100644 index d5ea8a9d20bf3..0000000000000 --- a/crypto/third_party/nss/chromium-prtypes.h +++ /dev/null @@ -1,77 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* Emulates the real prtypes.h. Defines the types and macros that sha512.cc - * needs. */ - -#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ -#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ - -#include -#include - -#include "build/build_config.h" - -#if defined(ARCH_CPU_LITTLE_ENDIAN) -#define IS_LITTLE_ENDIAN 1 -#else -#define IS_BIG_ENDIAN 1 -#endif - -/* - * The C language requires that 'long' be at least 32 bits. 2147483647 is the - * largest signed 32-bit integer. - */ -#if LONG_MAX > 2147483647L -#define PR_BYTES_PER_LONG 8 -#else -#define PR_BYTES_PER_LONG 4 -#endif - -#define HAVE_LONG_LONG - -#if defined(__linux__) -#define LINUX -#endif - -typedef uint8_t PRUint8; -typedef uint32_t PRUint32; - -typedef int PRBool; - -#define PR_MIN(x,y) ((x)<(y)?(x):(y)) - -#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ */ diff --git a/crypto/third_party/nss/chromium-sha256.h b/crypto/third_party/nss/chromium-sha256.h deleted file mode 100644 index 52815ca7f10d0..0000000000000 --- a/crypto/third_party/nss/chromium-sha256.h +++ /dev/null @@ -1,51 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ -#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ - -#include "crypto/third_party/nss/chromium-prtypes.h" - -struct SHA256ContextStr { - union { - PRUint32 w[64]; /* message schedule, input buffer, plus 48 words */ - PRUint8 b[256]; - } u; - PRUint32 h[8]; /* 8 state variables */ - PRUint32 sizeHi,sizeLo; /* 64-bit count of hashed bytes. */ -}; - -#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ */ diff --git a/crypto/third_party/nss/pk11akey.cc b/crypto/third_party/nss/pk11akey.cc deleted file mode 100644 index 4db582fc6c4b9..0000000000000 --- a/crypto/third_party/nss/pk11akey.cc +++ /dev/null @@ -1,98 +0,0 @@ - /* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dr Stephen Henson - * Dr Vipul Gupta , and - * Douglas Stebila , Sun Microsystems Laboratories - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "crypto/third_party/nss/chromium-nss.h" - -#include - -#include "base/logging.h" - -// Based on PK11_ImportEncryptedPrivateKeyInfo function in -// mozilla/security/nss/lib/pk11wrap/pk11akey.c. -SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey( - PK11SlotInfo* slot, - SECKEYEncryptedPrivateKeyInfo* epki, - SECItem* password, - SECItem* nickname, - SECItem* public_value, - PRBool permanent, - PRBool sensitive, - SECKEYPrivateKey** private_key, - void* wincx) { - SECItem* crypto_param = NULL; - - CK_ATTRIBUTE_TYPE usage = CKA_SIGN; - - PK11SymKey* key = PK11_PBEKeyGen(slot, - &epki->algorithm, - password, - PR_FALSE, // faulty3DES - wincx); - if (key == NULL) { - DLOG(ERROR) << "PK11_PBEKeyGen: " << PORT_GetError(); - return SECFailure; - } - - CK_MECHANISM_TYPE crypto_mech_type = PK11_GetPBECryptoMechanism( - &epki->algorithm, &crypto_param, password); - if (crypto_mech_type == CKM_INVALID_MECHANISM) { - DLOG(ERROR) << "PK11_GetPBECryptoMechanism: " << PORT_GetError(); - PK11_FreeSymKey(key); - return SECFailure; - } - - crypto_mech_type = PK11_GetPadMechanism(crypto_mech_type); - - *private_key = PK11_UnwrapPrivKey(slot, key, crypto_mech_type, crypto_param, - &epki->encryptedData, nickname, - public_value, permanent, sensitive, CKK_EC, - &usage, 1, wincx); - - if (crypto_param != NULL) - SECITEM_ZfreeItem(crypto_param, PR_TRUE); - - PK11_FreeSymKey(key); - - if (!*private_key) { - DLOG(ERROR) << "PK11_UnwrapPrivKey: " << PORT_GetError(); - return SECFailure; - } - - return SECSuccess; -} diff --git a/crypto/third_party/nss/rsawrapr.c b/crypto/third_party/nss/rsawrapr.c deleted file mode 100644 index 73e498f937d1f..0000000000000 --- a/crypto/third_party/nss/rsawrapr.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * PKCS#1 encoding and decoding functions. - * This file is believed to contain no code licensed from other parties. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "seccomon.h" -#include "secerr.h" -#include "sechash.h" - -/* Needed for RSA-PSS functions */ -static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* - * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447. - */ -static SECStatus -MGF1(HASH_HashType hashAlg, unsigned char *mask, unsigned int maskLen, - const unsigned char *mgfSeed, unsigned int mgfSeedLen) -{ - unsigned int digestLen; - PRUint32 counter, rounds; - unsigned char *tempHash, *temp; - const SECHashObject *hash; - void *hashContext; - unsigned char C[4]; - - hash = HASH_GetHashObject(hashAlg); - if (hash == NULL) - return SECFailure; - - hashContext = (*hash->create)(); - rounds = (maskLen + hash->length - 1) / hash->length; - for (counter = 0; counter < rounds; counter++) { - C[0] = (unsigned char)((counter >> 24) & 0xff); - C[1] = (unsigned char)((counter >> 16) & 0xff); - C[2] = (unsigned char)((counter >> 8) & 0xff); - C[3] = (unsigned char)(counter & 0xff); - - /* This could be optimized when the clone functions in - * rawhash.c are implemented. */ - (*hash->begin)(hashContext); - (*hash->update)(hashContext, mgfSeed, mgfSeedLen); - (*hash->update)(hashContext, C, sizeof C); - - tempHash = mask + counter * hash->length; - if (counter != (rounds-1)) { - (*hash->end)(hashContext, tempHash, &digestLen, hash->length); - } else { /* we're in the last round and need to cut the hash */ - temp = (unsigned char *)PORT_Alloc(hash->length); - (*hash->end)(hashContext, temp, &digestLen, hash->length); - PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length); - PORT_Free(temp); - } - } - (*hash->destroy)(hashContext, PR_TRUE); - - return SECSuccess; -} - -/* - * Verify a RSA-PSS signature. - * Described in RFC 3447, section 9.1.2. - * We use mHash instead of M as input. - * emBits from the RFC is just modBits - 1, see section 8.1.2. - * We only support MGF1 as the MGF. - * - * NOTE: this code assumes modBits is a multiple of 8. - */ -SECStatus -emsa_pss_verify(const unsigned char *mHash, - const unsigned char *em, unsigned int emLen, - HASH_HashType hashAlg, HASH_HashType maskHashAlg, - unsigned int sLen) -{ - const SECHashObject *hash; - void *hash_context; - unsigned char *db; - unsigned char *H_; /* H' from the RFC */ - unsigned int i, dbMaskLen; - SECStatus rv; - - hash = HASH_GetHashObject(hashAlg); - dbMaskLen = emLen - hash->length - 1; - - /* Step 3 + 4 + 6 */ - if ((emLen < (hash->length + sLen + 2)) || - (em[emLen - 1] != 0xbc) || - ((em[0] & 0x80) != 0)) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - return SECFailure; - } - - /* Step 7 */ - db = (unsigned char *)PORT_Alloc(dbMaskLen); - if (db == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - /* &em[dbMaskLen] points to H, used as mgfSeed */ - MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length); - - /* Step 8 */ - for (i = 0; i < dbMaskLen; i++) { - db[i] ^= em[i]; - } - - /* Step 9 */ - db[0] &= 0x7f; - - /* Step 10 */ - for (i = 0; i < (dbMaskLen - sLen - 1); i++) { - if (db[i] != 0) { - PORT_Free(db); - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - return SECFailure; - } - } - if (db[dbMaskLen - sLen - 1] != 0x01) { - PORT_Free(db); - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - return SECFailure; - } - - /* Step 12 + 13 */ - H_ = (unsigned char *)PORT_Alloc(hash->length); - if (H_ == NULL) { - PORT_Free(db); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - hash_context = (*hash->create)(); - if (hash_context == NULL) { - PORT_Free(db); - PORT_Free(H_); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - (*hash->begin)(hash_context); - (*hash->update)(hash_context, eightZeros, 8); - (*hash->update)(hash_context, mHash, hash->length); - (*hash->update)(hash_context, &db[dbMaskLen - sLen], sLen); - (*hash->end)(hash_context, H_, &i, hash->length); - (*hash->destroy)(hash_context, PR_TRUE); - - PORT_Free(db); - - /* Step 14 */ - if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - rv = SECFailure; - } else { - rv = SECSuccess; - } - - PORT_Free(H_); - return rv; -} diff --git a/crypto/third_party/nss/secsign.cc b/crypto/third_party/nss/secsign.cc deleted file mode 100644 index a788defc70410..0000000000000 --- a/crypto/third_party/nss/secsign.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Signature stuff. - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dr Vipul Gupta , Sun Microsystems Laboratories - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "crypto/third_party/nss/chromium-nss.h" - -#include - -#include -#include -#include -#include - -#include "base/basictypes.h" -#include "base/logging.h" -#include "build/build_config.h" - -SECStatus DerSignData(PLArenaPool *arena, - SECItem *result, - SECItem *input, - SECKEYPrivateKey *key, - SECOidTag algo_id) { - if (key->keyType != ecKey) { - return SEC_DerSignData(arena, result, input->data, input->len, key, - algo_id); - } - - // NSS has a private function sec_DecodeSigAlg it uses to figure out the - // correct hash from the algorithm id. - HASH_HashType hash_type; - switch (algo_id) { - case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: - hash_type = HASH_AlgSHA1; - break; -#ifdef SHA224_LENGTH - case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: - hash_type = HASH_AlgSHA224; - break; -#endif - case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: - hash_type = HASH_AlgSHA256; - break; - case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: - hash_type = HASH_AlgSHA384; - break; - case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: - hash_type = HASH_AlgSHA512; - break; - default: - PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); - return SECFailure; - } - - // Hash the input. - std::vector hash_data(HASH_ResultLen(hash_type)); - SECStatus rv = HASH_HashBuf( - hash_type, &hash_data[0], input->data, input->len); - if (rv != SECSuccess) - return rv; - SECItem hash = {siBuffer, &hash_data[0], - static_cast(hash_data.size())}; - - // Compute signature of hash. - int signature_len = PK11_SignatureLen(key); - std::vector signature_data(signature_len); - SECItem sig = {siBuffer, &signature_data[0], - static_cast(signature_len)}; - rv = PK11_Sign(key, &sig, &hash); - if (rv != SECSuccess) - return rv; - - CERTSignedData sd; - PORT_Memset(&sd, 0, sizeof(sd)); - // Fill in tbsCertificate. - sd.data.data = (unsigned char*) input->data; - sd.data.len = input->len; - - // Fill in signatureAlgorithm. - rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algo_id, 0); - if (rv != SECSuccess) - return rv; - - // Fill in signatureValue. - rv = DSAU_EncodeDerSigWithLen(&sd.signature, &sig, sig.len); - if (rv != SECSuccess) - return rv; - sd.signature.len <<= 3; // Convert to bit string. - - // DER encode the signed data object. - void* encode_result = SEC_ASN1EncodeItem( - arena, result, &sd, SEC_ASN1_GET(CERT_SignedDataTemplate)); - - PORT_Free(sd.signature.data); - - return encode_result ? SECSuccess : SECFailure; -} diff --git a/crypto/third_party/nss/sha512.cc b/crypto/third_party/nss/sha512.cc deleted file mode 100644 index 5ef4e5062dcb1..0000000000000 --- a/crypto/third_party/nss/sha512.cc +++ /dev/null @@ -1,1391 +0,0 @@ -/* - * sha512.c - implementation of SHA256, SHA384 and SHA512 - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* $Id: sha512.c,v 1.9 2006/10/13 16:54:04 wtchang%redhat.com Exp $ */ - -// Prevent manual unrolling in the sha256 code, which reduces the binary code -// size from ~10k to ~1k. The performance should be reasonable for our use. -#define NOUNROLL256 1 - -#include "crypto/third_party/nss/chromium-prtypes.h" /* for PRUintXX */ -#if defined(_X86_) || defined(SHA_NO_LONG_LONG) -#define NOUNROLL512 1 -#undef HAVE_LONG_LONG -#endif -#include "crypto/third_party/nss/chromium-blapi.h" -#include "crypto/third_party/nss/chromium-sha256.h" /* for struct SHA256ContextStr */ - -#include -#include -#define PORT_New(type) static_cast(malloc(sizeof(type))) -#define PORT_ZFree(ptr, len) do { memset(ptr, 0, len); free(ptr); } while (0) -#define PORT_Strlen(s) static_cast(strlen(s)) -#define PORT_Memcpy memcpy - -/* ============= Common constants and defines ======================= */ - -#define W ctx->u.w -#define B ctx->u.b -#define H ctx->h - -#define SHR(x,n) (x >> n) -#define SHL(x,n) (x << n) -#define Ch(x,y,z) ((x & y) ^ (~x & z)) -#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) - -/* Padding used with all flavors of SHA */ -static const PRUint8 pad[240] = { -0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - /* compiler will fill the rest in with zeros */ -}; - -/* ============= SHA256 implemenmtation ================================== */ - -/* SHA-256 constants, K256. */ -static const PRUint32 K256[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -/* SHA-256 initial hash values */ -static const PRUint32 H256[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 -}; - -#if defined(_MSC_VER) && defined(_X86_) -#ifndef FORCEINLINE -#if (_MSC_VER >= 1200) -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE __inline -#endif -#endif -#define FASTCALL __fastcall - -static FORCEINLINE PRUint32 FASTCALL -swap4b(PRUint32 dwd) -{ - __asm { - mov eax,dwd - bswap eax - } -} - -#define SHA_HTONL(x) swap4b(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) - -#elif defined(LINUX) && defined(_X86_) -#undef __OPTIMIZE__ -#define __OPTIMIZE__ 1 -#undef __pentium__ -#define __pentium__ 1 -#include -#define SHA_HTONL(x) bswap_32(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) - -#else /* neither windows nor Linux PC */ -#define SWAP4MASK 0x00FF00FF -#define SHA_HTONL(x) (t1 = (x), t1 = (t1 << 16) | (t1 >> 16), \ - ((t1 & SWAP4MASK) << 8) | ((t1 >> 8) & SWAP4MASK)) -#define BYTESWAP4(x) x = SHA_HTONL(x) -#endif - -#if defined(_MSC_VER) && defined(_X86_) -#pragma intrinsic (_lrotr, _lrotl) -#define ROTR32(x,n) _lrotr(x,n) -#define ROTL32(x,n) _lrotl(x,n) -#else -#define ROTR32(x,n) ((x >> n) | (x << ((8 * sizeof x) - n))) -#define ROTL32(x,n) ((x << n) | (x >> ((8 * sizeof x) - n))) -#endif - -/* Capitol Sigma and lower case sigma functions */ -#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x,22)) -#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x,25)) -#define s0(x) (t1 = x, ROTR32(t1, 7) ^ ROTR32(t1,18) ^ SHR(t1, 3)) -#define s1(x) (t2 = x, ROTR32(t2,17) ^ ROTR32(t2,19) ^ SHR(t2,10)) - -SHA256Context * -SHA256_NewContext(void) -{ - SHA256Context *ctx = PORT_New(SHA256Context); - return ctx; -} - -void -SHA256_DestroyContext(SHA256Context *ctx, PRBool freeit) -{ - if (freeit) { - PORT_ZFree(ctx, sizeof *ctx); - } -} - -void -SHA256_Begin(SHA256Context *ctx) -{ - memset(ctx, 0, sizeof *ctx); - memcpy(H, H256, sizeof H256); -} - -static void -SHA256_Compress(SHA256Context *ctx) -{ - { - register PRUint32 t1, t2; - -#if defined(IS_LITTLE_ENDIAN) - BYTESWAP4(W[0]); - BYTESWAP4(W[1]); - BYTESWAP4(W[2]); - BYTESWAP4(W[3]); - BYTESWAP4(W[4]); - BYTESWAP4(W[5]); - BYTESWAP4(W[6]); - BYTESWAP4(W[7]); - BYTESWAP4(W[8]); - BYTESWAP4(W[9]); - BYTESWAP4(W[10]); - BYTESWAP4(W[11]); - BYTESWAP4(W[12]); - BYTESWAP4(W[13]); - BYTESWAP4(W[14]); - BYTESWAP4(W[15]); -#endif - -#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16]) - - /* prepare the "message schedule" */ -#ifdef NOUNROLL256 - { - int t; - for (t = 16; t < 64; ++t) { - INITW(t); - } - } -#else - INITW(16); - INITW(17); - INITW(18); - INITW(19); - - INITW(20); - INITW(21); - INITW(22); - INITW(23); - INITW(24); - INITW(25); - INITW(26); - INITW(27); - INITW(28); - INITW(29); - - INITW(30); - INITW(31); - INITW(32); - INITW(33); - INITW(34); - INITW(35); - INITW(36); - INITW(37); - INITW(38); - INITW(39); - - INITW(40); - INITW(41); - INITW(42); - INITW(43); - INITW(44); - INITW(45); - INITW(46); - INITW(47); - INITW(48); - INITW(49); - - INITW(50); - INITW(51); - INITW(52); - INITW(53); - INITW(54); - INITW(55); - INITW(56); - INITW(57); - INITW(58); - INITW(59); - - INITW(60); - INITW(61); - INITW(62); - INITW(63); - -#endif -#undef INITW - } - { - PRUint32 a, b, c, d, e, f, g, h; - - a = H[0]; - b = H[1]; - c = H[2]; - d = H[3]; - e = H[4]; - f = H[5]; - g = H[6]; - h = H[7]; - -#define ROUND(n,a,b,c,d,e,f,g,h) \ - h += S1(e) + Ch(e,f,g) + K256[n] + W[n]; \ - d += h; \ - h += S0(a) + Maj(a,b,c); - -#ifdef NOUNROLL256 - { - int t; - for (t = 0; t < 64; t+= 8) { - ROUND(t+0,a,b,c,d,e,f,g,h) - ROUND(t+1,h,a,b,c,d,e,f,g) - ROUND(t+2,g,h,a,b,c,d,e,f) - ROUND(t+3,f,g,h,a,b,c,d,e) - ROUND(t+4,e,f,g,h,a,b,c,d) - ROUND(t+5,d,e,f,g,h,a,b,c) - ROUND(t+6,c,d,e,f,g,h,a,b) - ROUND(t+7,b,c,d,e,f,g,h,a) - } - } -#else - ROUND( 0,a,b,c,d,e,f,g,h) - ROUND( 1,h,a,b,c,d,e,f,g) - ROUND( 2,g,h,a,b,c,d,e,f) - ROUND( 3,f,g,h,a,b,c,d,e) - ROUND( 4,e,f,g,h,a,b,c,d) - ROUND( 5,d,e,f,g,h,a,b,c) - ROUND( 6,c,d,e,f,g,h,a,b) - ROUND( 7,b,c,d,e,f,g,h,a) - - ROUND( 8,a,b,c,d,e,f,g,h) - ROUND( 9,h,a,b,c,d,e,f,g) - ROUND(10,g,h,a,b,c,d,e,f) - ROUND(11,f,g,h,a,b,c,d,e) - ROUND(12,e,f,g,h,a,b,c,d) - ROUND(13,d,e,f,g,h,a,b,c) - ROUND(14,c,d,e,f,g,h,a,b) - ROUND(15,b,c,d,e,f,g,h,a) - - ROUND(16,a,b,c,d,e,f,g,h) - ROUND(17,h,a,b,c,d,e,f,g) - ROUND(18,g,h,a,b,c,d,e,f) - ROUND(19,f,g,h,a,b,c,d,e) - ROUND(20,e,f,g,h,a,b,c,d) - ROUND(21,d,e,f,g,h,a,b,c) - ROUND(22,c,d,e,f,g,h,a,b) - ROUND(23,b,c,d,e,f,g,h,a) - - ROUND(24,a,b,c,d,e,f,g,h) - ROUND(25,h,a,b,c,d,e,f,g) - ROUND(26,g,h,a,b,c,d,e,f) - ROUND(27,f,g,h,a,b,c,d,e) - ROUND(28,e,f,g,h,a,b,c,d) - ROUND(29,d,e,f,g,h,a,b,c) - ROUND(30,c,d,e,f,g,h,a,b) - ROUND(31,b,c,d,e,f,g,h,a) - - ROUND(32,a,b,c,d,e,f,g,h) - ROUND(33,h,a,b,c,d,e,f,g) - ROUND(34,g,h,a,b,c,d,e,f) - ROUND(35,f,g,h,a,b,c,d,e) - ROUND(36,e,f,g,h,a,b,c,d) - ROUND(37,d,e,f,g,h,a,b,c) - ROUND(38,c,d,e,f,g,h,a,b) - ROUND(39,b,c,d,e,f,g,h,a) - - ROUND(40,a,b,c,d,e,f,g,h) - ROUND(41,h,a,b,c,d,e,f,g) - ROUND(42,g,h,a,b,c,d,e,f) - ROUND(43,f,g,h,a,b,c,d,e) - ROUND(44,e,f,g,h,a,b,c,d) - ROUND(45,d,e,f,g,h,a,b,c) - ROUND(46,c,d,e,f,g,h,a,b) - ROUND(47,b,c,d,e,f,g,h,a) - - ROUND(48,a,b,c,d,e,f,g,h) - ROUND(49,h,a,b,c,d,e,f,g) - ROUND(50,g,h,a,b,c,d,e,f) - ROUND(51,f,g,h,a,b,c,d,e) - ROUND(52,e,f,g,h,a,b,c,d) - ROUND(53,d,e,f,g,h,a,b,c) - ROUND(54,c,d,e,f,g,h,a,b) - ROUND(55,b,c,d,e,f,g,h,a) - - ROUND(56,a,b,c,d,e,f,g,h) - ROUND(57,h,a,b,c,d,e,f,g) - ROUND(58,g,h,a,b,c,d,e,f) - ROUND(59,f,g,h,a,b,c,d,e) - ROUND(60,e,f,g,h,a,b,c,d) - ROUND(61,d,e,f,g,h,a,b,c) - ROUND(62,c,d,e,f,g,h,a,b) - ROUND(63,b,c,d,e,f,g,h,a) -#endif - - H[0] += a; - H[1] += b; - H[2] += c; - H[3] += d; - H[4] += e; - H[5] += f; - H[6] += g; - H[7] += h; - } -#undef ROUND -} - -#undef s0 -#undef s1 -#undef S0 -#undef S1 - -void -SHA256_Update(SHA256Context *ctx, const unsigned char *input, - unsigned int inputLen) -{ - unsigned int inBuf = ctx->sizeLo & 0x3f; - if (!inputLen) - return; - - /* Add inputLen into the count of bytes processed, before processing */ - if ((ctx->sizeLo += inputLen) < inputLen) - ctx->sizeHi++; - - /* if data already in buffer, attemp to fill rest of buffer */ - if (inBuf) { - unsigned int todo = SHA256_BLOCK_LENGTH - inBuf; - if (inputLen < todo) - todo = inputLen; - memcpy(B + inBuf, input, todo); - input += todo; - inputLen -= todo; - if (inBuf + todo == SHA256_BLOCK_LENGTH) - SHA256_Compress(ctx); - } - - /* if enough data to fill one or more whole buffers, process them. */ - while (inputLen >= SHA256_BLOCK_LENGTH) { - memcpy(B, input, SHA256_BLOCK_LENGTH); - input += SHA256_BLOCK_LENGTH; - inputLen -= SHA256_BLOCK_LENGTH; - SHA256_Compress(ctx); - } - /* if data left over, fill it into buffer */ - if (inputLen) - memcpy(B, input, inputLen); -} - -void -SHA256_End(SHA256Context *ctx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen) -{ - unsigned int inBuf = ctx->sizeLo & 0x3f; - unsigned int padLen = (inBuf < 56) ? (56 - inBuf) : (56 + 64 - inBuf); - PRUint32 hi, lo; -#ifdef SWAP4MASK - PRUint32 t1; -#endif - - hi = (ctx->sizeHi << 3) | (ctx->sizeLo >> 29); - lo = (ctx->sizeLo << 3); - - SHA256_Update(ctx, pad, padLen); - -#if defined(IS_LITTLE_ENDIAN) - W[14] = SHA_HTONL(hi); - W[15] = SHA_HTONL(lo); -#else - W[14] = hi; - W[15] = lo; -#endif - SHA256_Compress(ctx); - - /* now output the answer */ -#if defined(IS_LITTLE_ENDIAN) - BYTESWAP4(H[0]); - BYTESWAP4(H[1]); - BYTESWAP4(H[2]); - BYTESWAP4(H[3]); - BYTESWAP4(H[4]); - BYTESWAP4(H[5]); - BYTESWAP4(H[6]); - BYTESWAP4(H[7]); -#endif - padLen = PR_MIN(SHA256_LENGTH, maxDigestLen); - memcpy(digest, H, padLen); - if (digestLen) - *digestLen = padLen; -} - -/* Comment out unused code, mostly the SHA384 and SHA512 implementations. */ -#if 0 -SECStatus -SHA256_HashBuf(unsigned char *dest, const unsigned char *src, - unsigned int src_length) -{ - SHA256Context ctx; - unsigned int outLen; - - SHA256_Begin(&ctx); - SHA256_Update(&ctx, src, src_length); - SHA256_End(&ctx, dest, &outLen, SHA256_LENGTH); - - return SECSuccess; -} - - -SECStatus -SHA256_Hash(unsigned char *dest, const char *src) -{ - return SHA256_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); -} - - -void SHA256_TraceState(SHA256Context *ctx) { } - -unsigned int -SHA256_FlattenSize(SHA256Context *ctx) -{ - return sizeof *ctx; -} - -SECStatus -SHA256_Flatten(SHA256Context *ctx,unsigned char *space) -{ - PORT_Memcpy(space, ctx, sizeof *ctx); - return SECSuccess; -} - -SHA256Context * -SHA256_Resurrect(unsigned char *space, void *arg) -{ - SHA256Context *ctx = SHA256_NewContext(); - if (ctx) - PORT_Memcpy(ctx, space, sizeof *ctx); - return ctx; -} - -void SHA256_Clone(SHA256Context *dest, SHA256Context *src) -{ - memcpy(dest, src, sizeof *dest); -} - - -/* ======= SHA512 and SHA384 common constants and defines ================= */ - -/* common #defines for SHA512 and SHA384 */ -#if defined(HAVE_LONG_LONG) -#define ROTR64(x,n) ((x >> n) | (x << (64 - n))) -#define ROTL64(x,n) ((x << n) | (x >> (64 - n))) - -#define S0(x) (ROTR64(x,28) ^ ROTR64(x,34) ^ ROTR64(x,39)) -#define S1(x) (ROTR64(x,14) ^ ROTR64(x,18) ^ ROTR64(x,41)) -#define s0(x) (t1 = x, ROTR64(t1, 1) ^ ROTR64(t1, 8) ^ SHR(t1,7)) -#define s1(x) (t2 = x, ROTR64(t2,19) ^ ROTR64(t2,61) ^ SHR(t2,6)) - -#if PR_BYTES_PER_LONG == 8 -#define ULLC(hi,lo) 0x ## hi ## lo ## UL -#elif defined(_MSC_VER) -#define ULLC(hi,lo) 0x ## hi ## lo ## ui64 -#else -#define ULLC(hi,lo) 0x ## hi ## lo ## ULL -#endif - -#define SHA_MASK16 ULLC(0000FFFF,0000FFFF) -#define SHA_MASK8 ULLC(00FF00FF,00FF00FF) -#define SHA_HTONLL(x) (t1 = x, \ - t1 = ((t1 & SHA_MASK8 ) << 8) | ((t1 >> 8) & SHA_MASK8 ), \ - t1 = ((t1 & SHA_MASK16) << 16) | ((t1 >> 16) & SHA_MASK16), \ - (t1 >> 32) | (t1 << 32)) -#define BYTESWAP8(x) x = SHA_HTONLL(x) - -#else /* no long long */ - -#if defined(IS_LITTLE_ENDIAN) -#define ULLC(hi,lo) { 0x ## lo ## U, 0x ## hi ## U } -#else -#define ULLC(hi,lo) { 0x ## hi ## U, 0x ## lo ## U } -#endif - -#define SHA_HTONLL(x) ( BYTESWAP4(x.lo), BYTESWAP4(x.hi), \ - x.hi ^= x.lo ^= x.hi ^= x.lo, x) -#define BYTESWAP8(x) do { PRUint32 tmp; BYTESWAP4(x.lo); BYTESWAP4(x.hi); \ - tmp = x.lo; x.lo = x.hi; x.hi = tmp; } while (0) -#endif - -/* SHA-384 and SHA-512 constants, K512. */ -static const PRUint64 K512[80] = { -#if PR_BYTES_PER_LONG == 8 - 0x428a2f98d728ae22UL , 0x7137449123ef65cdUL , - 0xb5c0fbcfec4d3b2fUL , 0xe9b5dba58189dbbcUL , - 0x3956c25bf348b538UL , 0x59f111f1b605d019UL , - 0x923f82a4af194f9bUL , 0xab1c5ed5da6d8118UL , - 0xd807aa98a3030242UL , 0x12835b0145706fbeUL , - 0x243185be4ee4b28cUL , 0x550c7dc3d5ffb4e2UL , - 0x72be5d74f27b896fUL , 0x80deb1fe3b1696b1UL , - 0x9bdc06a725c71235UL , 0xc19bf174cf692694UL , - 0xe49b69c19ef14ad2UL , 0xefbe4786384f25e3UL , - 0x0fc19dc68b8cd5b5UL , 0x240ca1cc77ac9c65UL , - 0x2de92c6f592b0275UL , 0x4a7484aa6ea6e483UL , - 0x5cb0a9dcbd41fbd4UL , 0x76f988da831153b5UL , - 0x983e5152ee66dfabUL , 0xa831c66d2db43210UL , - 0xb00327c898fb213fUL , 0xbf597fc7beef0ee4UL , - 0xc6e00bf33da88fc2UL , 0xd5a79147930aa725UL , - 0x06ca6351e003826fUL , 0x142929670a0e6e70UL , - 0x27b70a8546d22ffcUL , 0x2e1b21385c26c926UL , - 0x4d2c6dfc5ac42aedUL , 0x53380d139d95b3dfUL , - 0x650a73548baf63deUL , 0x766a0abb3c77b2a8UL , - 0x81c2c92e47edaee6UL , 0x92722c851482353bUL , - 0xa2bfe8a14cf10364UL , 0xa81a664bbc423001UL , - 0xc24b8b70d0f89791UL , 0xc76c51a30654be30UL , - 0xd192e819d6ef5218UL , 0xd69906245565a910UL , - 0xf40e35855771202aUL , 0x106aa07032bbd1b8UL , - 0x19a4c116b8d2d0c8UL , 0x1e376c085141ab53UL , - 0x2748774cdf8eeb99UL , 0x34b0bcb5e19b48a8UL , - 0x391c0cb3c5c95a63UL , 0x4ed8aa4ae3418acbUL , - 0x5b9cca4f7763e373UL , 0x682e6ff3d6b2b8a3UL , - 0x748f82ee5defb2fcUL , 0x78a5636f43172f60UL , - 0x84c87814a1f0ab72UL , 0x8cc702081a6439ecUL , - 0x90befffa23631e28UL , 0xa4506cebde82bde9UL , - 0xbef9a3f7b2c67915UL , 0xc67178f2e372532bUL , - 0xca273eceea26619cUL , 0xd186b8c721c0c207UL , - 0xeada7dd6cde0eb1eUL , 0xf57d4f7fee6ed178UL , - 0x06f067aa72176fbaUL , 0x0a637dc5a2c898a6UL , - 0x113f9804bef90daeUL , 0x1b710b35131c471bUL , - 0x28db77f523047d84UL , 0x32caab7b40c72493UL , - 0x3c9ebe0a15c9bebcUL , 0x431d67c49c100d4cUL , - 0x4cc5d4becb3e42b6UL , 0x597f299cfc657e2aUL , - 0x5fcb6fab3ad6faecUL , 0x6c44198c4a475817UL -#else - ULLC(428a2f98,d728ae22), ULLC(71374491,23ef65cd), - ULLC(b5c0fbcf,ec4d3b2f), ULLC(e9b5dba5,8189dbbc), - ULLC(3956c25b,f348b538), ULLC(59f111f1,b605d019), - ULLC(923f82a4,af194f9b), ULLC(ab1c5ed5,da6d8118), - ULLC(d807aa98,a3030242), ULLC(12835b01,45706fbe), - ULLC(243185be,4ee4b28c), ULLC(550c7dc3,d5ffb4e2), - ULLC(72be5d74,f27b896f), ULLC(80deb1fe,3b1696b1), - ULLC(9bdc06a7,25c71235), ULLC(c19bf174,cf692694), - ULLC(e49b69c1,9ef14ad2), ULLC(efbe4786,384f25e3), - ULLC(0fc19dc6,8b8cd5b5), ULLC(240ca1cc,77ac9c65), - ULLC(2de92c6f,592b0275), ULLC(4a7484aa,6ea6e483), - ULLC(5cb0a9dc,bd41fbd4), ULLC(76f988da,831153b5), - ULLC(983e5152,ee66dfab), ULLC(a831c66d,2db43210), - ULLC(b00327c8,98fb213f), ULLC(bf597fc7,beef0ee4), - ULLC(c6e00bf3,3da88fc2), ULLC(d5a79147,930aa725), - ULLC(06ca6351,e003826f), ULLC(14292967,0a0e6e70), - ULLC(27b70a85,46d22ffc), ULLC(2e1b2138,5c26c926), - ULLC(4d2c6dfc,5ac42aed), ULLC(53380d13,9d95b3df), - ULLC(650a7354,8baf63de), ULLC(766a0abb,3c77b2a8), - ULLC(81c2c92e,47edaee6), ULLC(92722c85,1482353b), - ULLC(a2bfe8a1,4cf10364), ULLC(a81a664b,bc423001), - ULLC(c24b8b70,d0f89791), ULLC(c76c51a3,0654be30), - ULLC(d192e819,d6ef5218), ULLC(d6990624,5565a910), - ULLC(f40e3585,5771202a), ULLC(106aa070,32bbd1b8), - ULLC(19a4c116,b8d2d0c8), ULLC(1e376c08,5141ab53), - ULLC(2748774c,df8eeb99), ULLC(34b0bcb5,e19b48a8), - ULLC(391c0cb3,c5c95a63), ULLC(4ed8aa4a,e3418acb), - ULLC(5b9cca4f,7763e373), ULLC(682e6ff3,d6b2b8a3), - ULLC(748f82ee,5defb2fc), ULLC(78a5636f,43172f60), - ULLC(84c87814,a1f0ab72), ULLC(8cc70208,1a6439ec), - ULLC(90befffa,23631e28), ULLC(a4506ceb,de82bde9), - ULLC(bef9a3f7,b2c67915), ULLC(c67178f2,e372532b), - ULLC(ca273ece,ea26619c), ULLC(d186b8c7,21c0c207), - ULLC(eada7dd6,cde0eb1e), ULLC(f57d4f7f,ee6ed178), - ULLC(06f067aa,72176fba), ULLC(0a637dc5,a2c898a6), - ULLC(113f9804,bef90dae), ULLC(1b710b35,131c471b), - ULLC(28db77f5,23047d84), ULLC(32caab7b,40c72493), - ULLC(3c9ebe0a,15c9bebc), ULLC(431d67c4,9c100d4c), - ULLC(4cc5d4be,cb3e42b6), ULLC(597f299c,fc657e2a), - ULLC(5fcb6fab,3ad6faec), ULLC(6c44198c,4a475817) -#endif -}; - -struct SHA512ContextStr { - union { - PRUint64 w[80]; /* message schedule, input buffer, plus 64 words */ - PRUint32 l[160]; - PRUint8 b[640]; - } u; - PRUint64 h[8]; /* 8 state variables */ - PRUint64 sizeLo; /* 64-bit count of hashed bytes. */ -}; - -/* =========== SHA512 implementation ===================================== */ - -/* SHA-512 initial hash values */ -static const PRUint64 H512[8] = { -#if PR_BYTES_PER_LONG == 8 - 0x6a09e667f3bcc908UL , 0xbb67ae8584caa73bUL , - 0x3c6ef372fe94f82bUL , 0xa54ff53a5f1d36f1UL , - 0x510e527fade682d1UL , 0x9b05688c2b3e6c1fUL , - 0x1f83d9abfb41bd6bUL , 0x5be0cd19137e2179UL -#else - ULLC(6a09e667,f3bcc908), ULLC(bb67ae85,84caa73b), - ULLC(3c6ef372,fe94f82b), ULLC(a54ff53a,5f1d36f1), - ULLC(510e527f,ade682d1), ULLC(9b05688c,2b3e6c1f), - ULLC(1f83d9ab,fb41bd6b), ULLC(5be0cd19,137e2179) -#endif -}; - - -SHA512Context * -SHA512_NewContext(void) -{ - SHA512Context *ctx = PORT_New(SHA512Context); - return ctx; -} - -void -SHA512_DestroyContext(SHA512Context *ctx, PRBool freeit) -{ - if (freeit) { - PORT_ZFree(ctx, sizeof *ctx); - } -} - -void -SHA512_Begin(SHA512Context *ctx) -{ - memset(ctx, 0, sizeof *ctx); - memcpy(H, H512, sizeof H512); -} - -#if defined(SHA512_TRACE) -#if defined(HAVE_LONG_LONG) -#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %016lx, %s = %016lx\n", \ - n, #e, d, #a, h); -#else -#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %08x%08x, %s = %08x%08x\n", \ - n, #e, d.hi, d.lo, #a, h.hi, h.lo); -#endif -#else -#define DUMP(n,a,d,e,h) -#endif - -#if defined(HAVE_LONG_LONG) - -#define ADDTO(x,y) y += x - -#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16]) - -#define ROUND(n,a,b,c,d,e,f,g,h) \ - h += S1(e) + Ch(e,f,g) + K512[n] + W[n]; \ - d += h; \ - h += S0(a) + Maj(a,b,c); \ - DUMP(n,a,d,e,h) - -#else /* use only 32-bit variables, and don't unroll loops */ - -#undef NOUNROLL512 -#define NOUNROLL512 1 - -#define ADDTO(x,y) y.lo += x.lo; y.hi += x.hi + (x.lo > y.lo) - -#define ROTR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n)) -#define ROTR64A(x,n,lo,hi) (x.lo << (64-n) | x.hi >> (n-32)) -#define SHR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n)) - -/* Capitol Sigma and lower case sigma functions */ -#define s0lo(x) (ROTR64a(x,1,lo,hi) ^ ROTR64a(x,8,lo,hi) ^ SHR64a(x,7,lo,hi)) -#define s0hi(x) (ROTR64a(x,1,hi,lo) ^ ROTR64a(x,8,hi,lo) ^ (x.hi >> 7)) - -#define s1lo(x) (ROTR64a(x,19,lo,hi) ^ ROTR64A(x,61,lo,hi) ^ SHR64a(x,6,lo,hi)) -#define s1hi(x) (ROTR64a(x,19,hi,lo) ^ ROTR64A(x,61,hi,lo) ^ (x.hi >> 6)) - -#define S0lo(x)(ROTR64a(x,28,lo,hi) ^ ROTR64A(x,34,lo,hi) ^ ROTR64A(x,39,lo,hi)) -#define S0hi(x)(ROTR64a(x,28,hi,lo) ^ ROTR64A(x,34,hi,lo) ^ ROTR64A(x,39,hi,lo)) - -#define S1lo(x)(ROTR64a(x,14,lo,hi) ^ ROTR64a(x,18,lo,hi) ^ ROTR64A(x,41,lo,hi)) -#define S1hi(x)(ROTR64a(x,14,hi,lo) ^ ROTR64a(x,18,hi,lo) ^ ROTR64A(x,41,hi,lo)) - -/* 32-bit versions of Ch and Maj */ -#define Chxx(x,y,z,lo) ((x.lo & y.lo) ^ (~x.lo & z.lo)) -#define Majx(x,y,z,lo) ((x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo)) - -#define INITW(t) \ - do { \ - PRUint32 lo, tm; \ - PRUint32 cy = 0; \ - lo = s1lo(W[t-2]); \ - lo += (tm = W[t-7].lo); if (lo < tm) cy++; \ - lo += (tm = s0lo(W[t-15])); if (lo < tm) cy++; \ - lo += (tm = W[t-16].lo); if (lo < tm) cy++; \ - W[t].lo = lo; \ - W[t].hi = cy + s1hi(W[t-2]) + W[t-7].hi + s0hi(W[t-15]) + W[t-16].hi; \ - } while (0) - -#define ROUND(n,a,b,c,d,e,f,g,h) \ - { \ - PRUint32 lo, tm, cy; \ - lo = S1lo(e); \ - lo += (tm = Chxx(e,f,g,lo)); cy = (lo < tm); \ - lo += (tm = K512[n].lo); if (lo < tm) cy++; \ - lo += (tm = W[n].lo); if (lo < tm) cy++; \ - h.lo += lo; if (h.lo < lo) cy++; \ - h.hi += cy + S1hi(e) + Chxx(e,f,g,hi) + K512[n].hi + W[n].hi; \ - d.lo += h.lo; \ - d.hi += h.hi + (d.lo < h.lo); \ - lo = S0lo(a); \ - lo += (tm = Majx(a,b,c,lo)); cy = (lo < tm); \ - h.lo += lo; if (h.lo < lo) cy++; \ - h.hi += cy + S0hi(a) + Majx(a,b,c,hi); \ - DUMP(n,a,d,e,h) \ - } -#endif - -static void -SHA512_Compress(SHA512Context *ctx) -{ -#if defined(IS_LITTLE_ENDIAN) - { -#if defined(HAVE_LONG_LONG) - PRUint64 t1; -#else - PRUint32 t1; -#endif - BYTESWAP8(W[0]); - BYTESWAP8(W[1]); - BYTESWAP8(W[2]); - BYTESWAP8(W[3]); - BYTESWAP8(W[4]); - BYTESWAP8(W[5]); - BYTESWAP8(W[6]); - BYTESWAP8(W[7]); - BYTESWAP8(W[8]); - BYTESWAP8(W[9]); - BYTESWAP8(W[10]); - BYTESWAP8(W[11]); - BYTESWAP8(W[12]); - BYTESWAP8(W[13]); - BYTESWAP8(W[14]); - BYTESWAP8(W[15]); - } -#endif - - { - PRUint64 t1, t2; -#ifdef NOUNROLL512 - { - /* prepare the "message schedule" */ - int t; - for (t = 16; t < 80; ++t) { - INITW(t); - } - } -#else - INITW(16); - INITW(17); - INITW(18); - INITW(19); - - INITW(20); - INITW(21); - INITW(22); - INITW(23); - INITW(24); - INITW(25); - INITW(26); - INITW(27); - INITW(28); - INITW(29); - - INITW(30); - INITW(31); - INITW(32); - INITW(33); - INITW(34); - INITW(35); - INITW(36); - INITW(37); - INITW(38); - INITW(39); - - INITW(40); - INITW(41); - INITW(42); - INITW(43); - INITW(44); - INITW(45); - INITW(46); - INITW(47); - INITW(48); - INITW(49); - - INITW(50); - INITW(51); - INITW(52); - INITW(53); - INITW(54); - INITW(55); - INITW(56); - INITW(57); - INITW(58); - INITW(59); - - INITW(60); - INITW(61); - INITW(62); - INITW(63); - INITW(64); - INITW(65); - INITW(66); - INITW(67); - INITW(68); - INITW(69); - - INITW(70); - INITW(71); - INITW(72); - INITW(73); - INITW(74); - INITW(75); - INITW(76); - INITW(77); - INITW(78); - INITW(79); -#endif - } -#ifdef SHA512_TRACE - { - int i; - for (i = 0; i < 80; ++i) { -#ifdef HAVE_LONG_LONG - printf("W[%2d] = %016lx\n", i, W[i]); -#else - printf("W[%2d] = %08x%08x\n", i, W[i].hi, W[i].lo); -#endif - } - } -#endif - { - PRUint64 a, b, c, d, e, f, g, h; - - a = H[0]; - b = H[1]; - c = H[2]; - d = H[3]; - e = H[4]; - f = H[5]; - g = H[6]; - h = H[7]; - -#ifdef NOUNROLL512 - { - int t; - for (t = 0; t < 80; t+= 8) { - ROUND(t+0,a,b,c,d,e,f,g,h) - ROUND(t+1,h,a,b,c,d,e,f,g) - ROUND(t+2,g,h,a,b,c,d,e,f) - ROUND(t+3,f,g,h,a,b,c,d,e) - ROUND(t+4,e,f,g,h,a,b,c,d) - ROUND(t+5,d,e,f,g,h,a,b,c) - ROUND(t+6,c,d,e,f,g,h,a,b) - ROUND(t+7,b,c,d,e,f,g,h,a) - } - } -#else - ROUND( 0,a,b,c,d,e,f,g,h) - ROUND( 1,h,a,b,c,d,e,f,g) - ROUND( 2,g,h,a,b,c,d,e,f) - ROUND( 3,f,g,h,a,b,c,d,e) - ROUND( 4,e,f,g,h,a,b,c,d) - ROUND( 5,d,e,f,g,h,a,b,c) - ROUND( 6,c,d,e,f,g,h,a,b) - ROUND( 7,b,c,d,e,f,g,h,a) - - ROUND( 8,a,b,c,d,e,f,g,h) - ROUND( 9,h,a,b,c,d,e,f,g) - ROUND(10,g,h,a,b,c,d,e,f) - ROUND(11,f,g,h,a,b,c,d,e) - ROUND(12,e,f,g,h,a,b,c,d) - ROUND(13,d,e,f,g,h,a,b,c) - ROUND(14,c,d,e,f,g,h,a,b) - ROUND(15,b,c,d,e,f,g,h,a) - - ROUND(16,a,b,c,d,e,f,g,h) - ROUND(17,h,a,b,c,d,e,f,g) - ROUND(18,g,h,a,b,c,d,e,f) - ROUND(19,f,g,h,a,b,c,d,e) - ROUND(20,e,f,g,h,a,b,c,d) - ROUND(21,d,e,f,g,h,a,b,c) - ROUND(22,c,d,e,f,g,h,a,b) - ROUND(23,b,c,d,e,f,g,h,a) - - ROUND(24,a,b,c,d,e,f,g,h) - ROUND(25,h,a,b,c,d,e,f,g) - ROUND(26,g,h,a,b,c,d,e,f) - ROUND(27,f,g,h,a,b,c,d,e) - ROUND(28,e,f,g,h,a,b,c,d) - ROUND(29,d,e,f,g,h,a,b,c) - ROUND(30,c,d,e,f,g,h,a,b) - ROUND(31,b,c,d,e,f,g,h,a) - - ROUND(32,a,b,c,d,e,f,g,h) - ROUND(33,h,a,b,c,d,e,f,g) - ROUND(34,g,h,a,b,c,d,e,f) - ROUND(35,f,g,h,a,b,c,d,e) - ROUND(36,e,f,g,h,a,b,c,d) - ROUND(37,d,e,f,g,h,a,b,c) - ROUND(38,c,d,e,f,g,h,a,b) - ROUND(39,b,c,d,e,f,g,h,a) - - ROUND(40,a,b,c,d,e,f,g,h) - ROUND(41,h,a,b,c,d,e,f,g) - ROUND(42,g,h,a,b,c,d,e,f) - ROUND(43,f,g,h,a,b,c,d,e) - ROUND(44,e,f,g,h,a,b,c,d) - ROUND(45,d,e,f,g,h,a,b,c) - ROUND(46,c,d,e,f,g,h,a,b) - ROUND(47,b,c,d,e,f,g,h,a) - - ROUND(48,a,b,c,d,e,f,g,h) - ROUND(49,h,a,b,c,d,e,f,g) - ROUND(50,g,h,a,b,c,d,e,f) - ROUND(51,f,g,h,a,b,c,d,e) - ROUND(52,e,f,g,h,a,b,c,d) - ROUND(53,d,e,f,g,h,a,b,c) - ROUND(54,c,d,e,f,g,h,a,b) - ROUND(55,b,c,d,e,f,g,h,a) - - ROUND(56,a,b,c,d,e,f,g,h) - ROUND(57,h,a,b,c,d,e,f,g) - ROUND(58,g,h,a,b,c,d,e,f) - ROUND(59,f,g,h,a,b,c,d,e) - ROUND(60,e,f,g,h,a,b,c,d) - ROUND(61,d,e,f,g,h,a,b,c) - ROUND(62,c,d,e,f,g,h,a,b) - ROUND(63,b,c,d,e,f,g,h,a) - - ROUND(64,a,b,c,d,e,f,g,h) - ROUND(65,h,a,b,c,d,e,f,g) - ROUND(66,g,h,a,b,c,d,e,f) - ROUND(67,f,g,h,a,b,c,d,e) - ROUND(68,e,f,g,h,a,b,c,d) - ROUND(69,d,e,f,g,h,a,b,c) - ROUND(70,c,d,e,f,g,h,a,b) - ROUND(71,b,c,d,e,f,g,h,a) - - ROUND(72,a,b,c,d,e,f,g,h) - ROUND(73,h,a,b,c,d,e,f,g) - ROUND(74,g,h,a,b,c,d,e,f) - ROUND(75,f,g,h,a,b,c,d,e) - ROUND(76,e,f,g,h,a,b,c,d) - ROUND(77,d,e,f,g,h,a,b,c) - ROUND(78,c,d,e,f,g,h,a,b) - ROUND(79,b,c,d,e,f,g,h,a) -#endif - - ADDTO(a,H[0]); - ADDTO(b,H[1]); - ADDTO(c,H[2]); - ADDTO(d,H[3]); - ADDTO(e,H[4]); - ADDTO(f,H[5]); - ADDTO(g,H[6]); - ADDTO(h,H[7]); - } -} - -void -SHA512_Update(SHA512Context *ctx, const unsigned char *input, - unsigned int inputLen) -{ - unsigned int inBuf; - if (!inputLen) - return; - -#if defined(HAVE_LONG_LONG) - inBuf = (unsigned int)ctx->sizeLo & 0x7f; - /* Add inputLen into the count of bytes processed, before processing */ - ctx->sizeLo += inputLen; -#else - inBuf = (unsigned int)ctx->sizeLo.lo & 0x7f; - ctx->sizeLo.lo += inputLen; - if (ctx->sizeLo.lo < inputLen) ctx->sizeLo.hi++; -#endif - - /* if data already in buffer, attemp to fill rest of buffer */ - if (inBuf) { - unsigned int todo = SHA512_BLOCK_LENGTH - inBuf; - if (inputLen < todo) - todo = inputLen; - memcpy(B + inBuf, input, todo); - input += todo; - inputLen -= todo; - if (inBuf + todo == SHA512_BLOCK_LENGTH) - SHA512_Compress(ctx); - } - - /* if enough data to fill one or more whole buffers, process them. */ - while (inputLen >= SHA512_BLOCK_LENGTH) { - memcpy(B, input, SHA512_BLOCK_LENGTH); - input += SHA512_BLOCK_LENGTH; - inputLen -= SHA512_BLOCK_LENGTH; - SHA512_Compress(ctx); - } - /* if data left over, fill it into buffer */ - if (inputLen) - memcpy(B, input, inputLen); -} - -void -SHA512_End(SHA512Context *ctx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen) -{ -#if defined(HAVE_LONG_LONG) - unsigned int inBuf = (unsigned int)ctx->sizeLo & 0x7f; - unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf); - PRUint64 lo, t1; - lo = (ctx->sizeLo << 3); -#else - unsigned int inBuf = (unsigned int)ctx->sizeLo.lo & 0x7f; - unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf); - PRUint64 lo = ctx->sizeLo; - PRUint32 t1; - lo.lo <<= 3; -#endif - - SHA512_Update(ctx, pad, padLen); - -#if defined(HAVE_LONG_LONG) - W[14] = 0; -#else - W[14].lo = 0; - W[14].hi = 0; -#endif - - W[15] = lo; -#if defined(IS_LITTLE_ENDIAN) - BYTESWAP8(W[15]); -#endif - SHA512_Compress(ctx); - - /* now output the answer */ -#if defined(IS_LITTLE_ENDIAN) - BYTESWAP8(H[0]); - BYTESWAP8(H[1]); - BYTESWAP8(H[2]); - BYTESWAP8(H[3]); - BYTESWAP8(H[4]); - BYTESWAP8(H[5]); - BYTESWAP8(H[6]); - BYTESWAP8(H[7]); -#endif - padLen = PR_MIN(SHA512_LENGTH, maxDigestLen); - memcpy(digest, H, padLen); - if (digestLen) - *digestLen = padLen; -} - -SECStatus -SHA512_HashBuf(unsigned char *dest, const unsigned char *src, - unsigned int src_length) -{ - SHA512Context ctx; - unsigned int outLen; - - SHA512_Begin(&ctx); - SHA512_Update(&ctx, src, src_length); - SHA512_End(&ctx, dest, &outLen, SHA512_LENGTH); - - return SECSuccess; -} - - -SECStatus -SHA512_Hash(unsigned char *dest, const char *src) -{ - return SHA512_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); -} - - -void SHA512_TraceState(SHA512Context *ctx) { } - -unsigned int -SHA512_FlattenSize(SHA512Context *ctx) -{ - return sizeof *ctx; -} - -SECStatus -SHA512_Flatten(SHA512Context *ctx,unsigned char *space) -{ - PORT_Memcpy(space, ctx, sizeof *ctx); - return SECSuccess; -} - -SHA512Context * -SHA512_Resurrect(unsigned char *space, void *arg) -{ - SHA512Context *ctx = SHA512_NewContext(); - if (ctx) - PORT_Memcpy(ctx, space, sizeof *ctx); - return ctx; -} - -void SHA512_Clone(SHA512Context *dest, SHA512Context *src) -{ - memcpy(dest, src, sizeof *dest); -} - -/* ======================================================================= */ -/* SHA384 uses a SHA512Context as the real context. -** The only differences between SHA384 an SHA512 are: -** a) the intialization values for the context, and -** b) the number of bytes of data produced as output. -*/ - -/* SHA-384 initial hash values */ -static const PRUint64 H384[8] = { -#if PR_BYTES_PER_LONG == 8 - 0xcbbb9d5dc1059ed8UL , 0x629a292a367cd507UL , - 0x9159015a3070dd17UL , 0x152fecd8f70e5939UL , - 0x67332667ffc00b31UL , 0x8eb44a8768581511UL , - 0xdb0c2e0d64f98fa7UL , 0x47b5481dbefa4fa4UL -#else - ULLC(cbbb9d5d,c1059ed8), ULLC(629a292a,367cd507), - ULLC(9159015a,3070dd17), ULLC(152fecd8,f70e5939), - ULLC(67332667,ffc00b31), ULLC(8eb44a87,68581511), - ULLC(db0c2e0d,64f98fa7), ULLC(47b5481d,befa4fa4) -#endif -}; - -SHA384Context * -SHA384_NewContext(void) -{ - return SHA512_NewContext(); -} - -void -SHA384_DestroyContext(SHA384Context *ctx, PRBool freeit) -{ - SHA512_DestroyContext(ctx, freeit); -} - -void -SHA384_Begin(SHA384Context *ctx) -{ - memset(ctx, 0, sizeof *ctx); - memcpy(H, H384, sizeof H384); -} - -void -SHA384_Update(SHA384Context *ctx, const unsigned char *input, - unsigned int inputLen) -{ - SHA512_Update(ctx, input, inputLen); -} - -void -SHA384_End(SHA384Context *ctx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen) -{ -#define SHA_MIN(a,b) (a < b ? a : b) - unsigned int maxLen = SHA_MIN(maxDigestLen, SHA384_LENGTH); - SHA512_End(ctx, digest, digestLen, maxLen); -} - -SECStatus -SHA384_HashBuf(unsigned char *dest, const unsigned char *src, - unsigned int src_length) -{ - SHA512Context ctx; - unsigned int outLen; - - SHA384_Begin(&ctx); - SHA512_Update(&ctx, src, src_length); - SHA512_End(&ctx, dest, &outLen, SHA384_LENGTH); - - return SECSuccess; -} - -SECStatus -SHA384_Hash(unsigned char *dest, const char *src) -{ - return SHA384_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); -} - -void SHA384_TraceState(SHA384Context *ctx) { } - -unsigned int -SHA384_FlattenSize(SHA384Context *ctx) -{ - return sizeof(SHA384Context); -} - -SECStatus -SHA384_Flatten(SHA384Context *ctx,unsigned char *space) -{ - return SHA512_Flatten(ctx, space); -} - -SHA384Context * -SHA384_Resurrect(unsigned char *space, void *arg) -{ - return SHA512_Resurrect(space, arg); -} - -void SHA384_Clone(SHA384Context *dest, SHA384Context *src) -{ - memcpy(dest, src, sizeof *dest); -} -#endif /* Comment out unused code. */ - -/* ======================================================================= */ -#ifdef SELFTEST -#include - -static const char abc[] = { "abc" }; -static const char abcdbc[] = { - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" -}; -static const char abcdef[] = { - "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" -}; - -void -dumpHash32(const unsigned char *buf, unsigned int bufLen) -{ - unsigned int i; - for (i = 0; i < bufLen; i += 4) { - printf(" %02x%02x%02x%02x", buf[i], buf[i+1], buf[i+2], buf[i+3]); - } - printf("\n"); -} - -void test256(void) -{ - unsigned char outBuf[SHA256_LENGTH]; - - printf("SHA256, input = %s\n", abc); - SHA256_Hash(outBuf, abc); - dumpHash32(outBuf, sizeof outBuf); - - printf("SHA256, input = %s\n", abcdbc); - SHA256_Hash(outBuf, abcdbc); - dumpHash32(outBuf, sizeof outBuf); -} - -void -dumpHash64(const unsigned char *buf, unsigned int bufLen) -{ - unsigned int i; - for (i = 0; i < bufLen; i += 8) { - if (i % 32 == 0) - printf("\n"); - printf(" %02x%02x%02x%02x%02x%02x%02x%02x", - buf[i ], buf[i+1], buf[i+2], buf[i+3], - buf[i+4], buf[i+5], buf[i+6], buf[i+7]); - } - printf("\n"); -} - -void test512(void) -{ - unsigned char outBuf[SHA512_LENGTH]; - - printf("SHA512, input = %s\n", abc); - SHA512_Hash(outBuf, abc); - dumpHash64(outBuf, sizeof outBuf); - - printf("SHA512, input = %s\n", abcdef); - SHA512_Hash(outBuf, abcdef); - dumpHash64(outBuf, sizeof outBuf); -} - -void time512(void) -{ - unsigned char outBuf[SHA512_LENGTH]; - - SHA512_Hash(outBuf, abc); - SHA512_Hash(outBuf, abcdef); -} - -void test384(void) -{ - unsigned char outBuf[SHA384_LENGTH]; - - printf("SHA384, input = %s\n", abc); - SHA384_Hash(outBuf, abc); - dumpHash64(outBuf, sizeof outBuf); - - printf("SHA384, input = %s\n", abcdef); - SHA384_Hash(outBuf, abcdef); - dumpHash64(outBuf, sizeof outBuf); -} - -int main (int argc, char *argv[], char *envp[]) -{ - int i = 1; - if (argc > 1) { - i = atoi(argv[1]); - } - if (i < 2) { - test256(); - test512(); - test384(); - } else { - while (i-- > 0) { - time512(); - } - printf("done\n"); - } - return 0; -} - -#endif diff --git a/crypto/wincrypt_shim.h b/crypto/wincrypt_shim.h deleted file mode 100644 index 799ac49feeb55..0000000000000 --- a/crypto/wincrypt_shim.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 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 NET_CRYPTO_WINCRYPT_SHIM_H_ -#define NET_CRYPTO_WINCRYPT_SHIM_H_ - -// wincrypt.h defines macros which conflict with OpenSSL's types. This header -// includes wincrypt and undefines the OpenSSL macros which conflict. Any -// Chromium headers which include wincrypt should instead include this header. - -#include -#include - -// Undefine the macros which conflict with OpenSSL and define replacements. See -// http://msdn.microsoft.com/en-us/library/windows/desktop/aa378145(v=vs.85).aspx -#undef X509_CERT_PAIR -#undef X509_EXTENSIONS -#undef X509_NAME - -#define WINCRYPT_X509_CERT_PAIR ((LPCSTR) 53) -#define WINCRYPT_X509_EXTENSIONS ((LPCSTR) 5) -#define WINCRYPT_X509_NAME ((LPCSTR) 7) - -#endif // NET_CRYPTO_WINCRYPT_SHIM_H_ \ No newline at end of file diff --git a/gpu/gles2_conform_support/BUILD.gn b/gpu/gles2_conform_support/BUILD.gn new file mode 100644 index 0000000000000..853beea4bfd38 --- /dev/null +++ b/gpu/gles2_conform_support/BUILD.gn @@ -0,0 +1,38 @@ +# 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. + +import("//build/config/allocator.gni") + +# GYP version: gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support +executable("gles2_conform_support") { + sources = [ + "gles2_conform_support.c", + "native/egl_native.cc", + "native/egl_native_win.cc", + "native/main.cc", + ] + defines = [ + "GLES2_CONFORM_SUPPORT_ONLY", + "GTF_GLES20", + "EGLAPI=", + "EGLAPIENTRY=", + ] + deps = [ + "//base", + "//gpu/gles2_conform_support/egl", + "//base/third_party/dynamic_annotations", + "//ui/gl", + "//gpu/command_buffer/client:gles2_c_lib_nocheck", + ] + if (is_linux) { + sources += [ + "native/egl_native_aura.cc", + "native/egl_native_x11.cc", + ] + } + if (use_allocator != "none") { + # See http://crbug.com/162998#c4 for why this is needed. + deps += [ "//base/allocator" ] + } +} diff --git a/gpu/gles2_conform_support/README b/gpu/gles2_conform_support/README new file mode 100644 index 0000000000000..04305616a5ef0 --- /dev/null +++ b/gpu/gles2_conform_support/README @@ -0,0 +1,15 @@ +To run OpenGL ES 2.0 conformance tests, do the following: +(These require access to Google-internal sources.) +1. Generate build files: + "python build/gyp_chromium gpu/gles2_conform_support/gles2_conform_test.gyp" + or set "GYP_DEFINES=internal_gles2_conform_tests=1" and rebuild your + projects using your standard method. Example: + "GYP_DEFINES=internal_gles2_conform_tests=1 gclient runhooks" +2. Build any of the two targets: + - gles2_conform_test_angle which tests ANGLE + - gles2_conform_test_native which tests command-buffer service + - gles2_conform_test_windowless which tests command-buffer service on most platforms + - gles2_conform_test_pepper will be added later +3. Run the targets as: "gles2_conform_test_native -noimagefileio + -run=third_party\gles2_conform\GTF_ES\glsl\GTF\mustpass.run" + diff --git a/gpu/gles2_conform_support/dummy.cc b/gpu/gles2_conform_support/dummy.cc new file mode 100644 index 0000000000000..0ebcbbc5f5302 --- /dev/null +++ b/gpu/gles2_conform_support/dummy.cc @@ -0,0 +1,7 @@ +// Copyright (c) 2013 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. + +// gles2_conform_test_windowless target contains only .c files, and it no +// longer links against libstdc++. We have to create this empty dummy.cc +// file and add it to the target. diff --git a/gpu/gles2_conform_support/egl/BUILD.gn b/gpu/gles2_conform_support/egl/BUILD.gn new file mode 100644 index 0000000000000..32fb8706ef421 --- /dev/null +++ b/gpu/gles2_conform_support/egl/BUILD.gn @@ -0,0 +1,35 @@ +# 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. + +# GYP version: gpu/gles2_conform_support/gles_conform_support.gyp:egl_native +source_set("egl") { + output_name = "egl_native" + sources = [ + "config.cc", + "config.h", + "display.cc", + "display.h", + "egl.cc", + "surface.cc", + "surface.h", + ] + + configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + + defines = [ + "EGLAPI=", + "EGLAPIENTRY=", + ] + + deps = [ + "//base", + "//gpu/command_buffer/client:gles2_implementation_no_check", + "//gpu/command_buffer/service", + "//gpu", + "//ui/base", + "//ui/gfx", + "//ui/gfx/geometry", + "//ui/gl", + ] +} diff --git a/gpu/gles2_conform_support/egl/config.cc b/gpu/gles2_conform_support/egl/config.cc new file mode 100644 index 0000000000000..d6ce3072c982e --- /dev/null +++ b/gpu/gles2_conform_support/egl/config.cc @@ -0,0 +1,152 @@ +// Copyright (c) 2011 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 "gpu/gles2_conform_support/egl/config.h" + +namespace egl { + +Config::Config() + : buffer_size_(0), + red_size_(0), + green_size_(0), + blue_size_(0), + luminance_size_(0), + alpha_size_(0), + alpha_mask_size_(0), + bind_to_texture_rgb_(EGL_FALSE), + bind_to_texture_rgba_(EGL_FALSE), + color_buffer_type_(EGL_RGB_BUFFER), + config_caveat_(EGL_NONE), + config_id_(EGL_DONT_CARE), + conformant_(EGL_OPENGL_ES2_BIT), + depth_size_(0), + level_(0), + max_pbuffer_width_(0), + max_pbuffer_height_(0), + max_pbuffer_pixels_(0), + min_swap_interval_(EGL_DONT_CARE), + max_swap_interval_(EGL_DONT_CARE), + native_renderable_(EGL_TRUE), + native_visual_id_(0), + native_visual_type_(EGL_DONT_CARE), + renderable_type_(EGL_OPENGL_ES2_BIT), + sample_buffers_(0), + samples_(0), + stencil_size_(0), + surface_type_(EGL_WINDOW_BIT), + transparent_type_(EGL_NONE), + transparent_red_value_(EGL_DONT_CARE), + transparent_green_value_(EGL_DONT_CARE), + transparent_blue_value_(EGL_DONT_CARE) { +} + +Config::~Config() { +} + +bool Config::GetAttrib(EGLint attribute, EGLint* value) const { + // TODO(alokp): Find out how to get correct values. + switch (attribute) { + case EGL_BUFFER_SIZE: + *value = buffer_size_; + break; + case EGL_RED_SIZE: + *value = red_size_; + break; + case EGL_GREEN_SIZE: + *value = green_size_; + break; + case EGL_BLUE_SIZE: + *value = blue_size_; + break; + case EGL_LUMINANCE_SIZE: + *value = luminance_size_; + break; + case EGL_ALPHA_SIZE: + *value = alpha_size_; + break; + case EGL_ALPHA_MASK_SIZE: + *value = alpha_mask_size_; + break; + case EGL_BIND_TO_TEXTURE_RGB: + *value = bind_to_texture_rgb_; + break; + case EGL_BIND_TO_TEXTURE_RGBA: + *value = bind_to_texture_rgba_; + break; + case EGL_COLOR_BUFFER_TYPE: + *value = color_buffer_type_; + break; + case EGL_CONFIG_CAVEAT: + *value = config_caveat_; + break; + case EGL_CONFIG_ID: + *value = config_id_; + break; + case EGL_CONFORMANT: + *value = conformant_; + break; + case EGL_DEPTH_SIZE: + *value = depth_size_; + break; + case EGL_LEVEL: + *value = level_; + break; + case EGL_MAX_PBUFFER_WIDTH: + *value = max_pbuffer_width_; + break; + case EGL_MAX_PBUFFER_HEIGHT: + *value = max_pbuffer_height_; + break; + case EGL_MAX_PBUFFER_PIXELS: + *value = max_pbuffer_pixels_; + break; + case EGL_MIN_SWAP_INTERVAL: + *value = min_swap_interval_; + break; + case EGL_MAX_SWAP_INTERVAL: + *value = max_swap_interval_; + break; + case EGL_NATIVE_RENDERABLE: + *value = native_renderable_; + break; + case EGL_NATIVE_VISUAL_ID: + *value = native_visual_id_; + break; + case EGL_NATIVE_VISUAL_TYPE: + *value = native_visual_type_; + break; + case EGL_RENDERABLE_TYPE: + *value = renderable_type_; + break; + case EGL_SAMPLE_BUFFERS: + *value = sample_buffers_; + break; + case EGL_SAMPLES: + *value = samples_; + break; + case EGL_STENCIL_SIZE: + *value = stencil_size_; + break; + case EGL_SURFACE_TYPE: + *value = surface_type_; + break; + case EGL_TRANSPARENT_TYPE: + *value = transparent_type_; + break; + case EGL_TRANSPARENT_RED_VALUE: + *value = transparent_red_value_; + break; + case EGL_TRANSPARENT_GREEN_VALUE: + *value = transparent_green_value_; + break; + case EGL_TRANSPARENT_BLUE_VALUE: + *value = transparent_blue_value_; + break; + default: + return false; + } + return true; +} + +} // namespace egl diff --git a/gpu/gles2_conform_support/egl/config.h b/gpu/gles2_conform_support/egl/config.h new file mode 100644 index 0000000000000..ef2ae1dcb9e11 --- /dev/null +++ b/gpu/gles2_conform_support/egl/config.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 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 GPU_GLES2_CONFORM_TEST_CONFIG_H_ +#define GPU_GLES2_CONFORM_TEST_CONFIG_H_ + +#include + +#include "base/basictypes.h" + +namespace egl { + +class Config { + public: + Config(); + ~Config(); + + bool GetAttrib(EGLint attribute, EGLint* value) const; + + private: + // Total color component bits in the color buffer. + EGLint buffer_size_; + // Bits of Red in the color buffer. + EGLint red_size_; + // Bits of Green in the color buffer. + EGLint green_size_; + // Bits of Blue in the color buffer. + EGLint blue_size_; + // Bits of Luminance in the color buffer. + EGLint luminance_size_; + // Bits of Alpha in the color buffer. + EGLint alpha_size_; + // Bits of Alpha Mask in the mask buffer. + EGLint alpha_mask_size_; + // True if bindable to RGB textures. + EGLBoolean bind_to_texture_rgb_; + // True if bindable to RGBA textures. + EGLBoolean bind_to_texture_rgba_; + // Color buffer type. + EGLenum color_buffer_type_; + // Any caveats for the configuration. + EGLenum config_caveat_; + // Unique EGLConfig identifier. + EGLint config_id_; + // Whether contexts created with this config are conformant. + EGLint conformant_; + // Bits of Z in the depth buffer. + EGLint depth_size_; + // Frame buffer level. + EGLint level_; + // Maximum width of pbuffer. + EGLint max_pbuffer_width_; + // Maximum height of pbuffer. + EGLint max_pbuffer_height_; + // Maximum size of pbuffer. + EGLint max_pbuffer_pixels_; + // Minimum swap interval. + EGLint min_swap_interval_; + // Maximum swap interval. + EGLint max_swap_interval_; + // True if native rendering APIs can render to surface. + EGLBoolean native_renderable_; + // Handle of corresponding native visual. + EGLint native_visual_id_; + // Native visual type of the associated visual. + EGLint native_visual_type_; + // Which client rendering APIs are supported. + EGLint renderable_type_; + // Number of multisample buffers. + EGLint sample_buffers_; + // Number of samples per pixel. + EGLint samples_; + // Bits of Stencil in the stencil buffer. + EGLint stencil_size_; + // Which types of EGL surfaces are supported. + EGLint surface_type_; + // Type of transparency supported + EGLenum transparent_type_; + // Transparent red value + EGLint transparent_red_value_; + // Transparent green value + EGLint transparent_green_value_; + // Transparent blue value + EGLint transparent_blue_value_; + + DISALLOW_COPY_AND_ASSIGN(Config); +}; + +} // namespace egl + +#endif // GPU_GLES2_CONFORM_TEST_CONFIG_H_ diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc new file mode 100644 index 0000000000000..bd17250e16ef8 --- /dev/null +++ b/gpu/gles2_conform_support/egl/display.cc @@ -0,0 +1,342 @@ +// Copyright (c) 2012 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 "gpu/gles2_conform_support/egl/display.h" + +#include +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/client/transfer_buffer.h" +#include "gpu/command_buffer/common/value_state.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/memory_tracking.h" +#include "gpu/command_buffer/service/transfer_buffer_manager.h" +#include "gpu/command_buffer/service/valuebuffer_manager.h" +#include "gpu/gles2_conform_support/egl/config.h" +#include "gpu/gles2_conform_support/egl/surface.h" + +namespace { +const int32 kCommandBufferSize = 1024 * 1024; +const int32 kTransferBufferSize = 512 * 1024; +} + +namespace egl { + +Display::Display(EGLNativeDisplayType display_id) + : display_id_(display_id), + is_initialized_(false), + create_offscreen_(false), + create_offscreen_width_(0), + create_offscreen_height_(0) { +} + +Display::~Display() { + gles2::Terminate(); +} + +bool Display::Initialize() { + gles2::Initialize(); + is_initialized_ = true; + return true; +} + +bool Display::IsValidConfig(EGLConfig config) { + return (config != NULL) && (config == config_.get()); +} + +bool Display::ChooseConfigs(EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + // TODO(alokp): Find out a way to find all configs. CommandBuffer currently + // does not support finding or choosing configs. + *num_config = 1; + if (configs != NULL) { + if (config_ == NULL) { + config_.reset(new Config); + } + configs[0] = config_.get(); + } + return true; +} + +bool Display::GetConfigs(EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + // TODO(alokp): Find out a way to find all configs. CommandBuffer currently + // does not support finding or choosing configs. + *num_config = 1; + if (configs != NULL) { + if (config_ == NULL) { + config_.reset(new Config); + } + configs[0] = config_.get(); + } + return true; +} + +bool Display::GetConfigAttrib(EGLConfig config, + EGLint attribute, + EGLint* value) { + const egl::Config* cfg = static_cast(config); + return cfg->GetAttrib(attribute, value); +} + +bool Display::IsValidNativeWindow(EGLNativeWindowType win) { +#if defined OS_WIN + return ::IsWindow(win) != FALSE; +#else + // TODO(alokp): Validate window handle. + return true; +#endif // OS_WIN +} + +bool Display::IsValidSurface(EGLSurface surface) { + return (surface != NULL) && (surface == surface_.get()); +} + +EGLSurface Display::CreateWindowSurface(EGLConfig config, + EGLNativeWindowType win, + const EGLint* attrib_list) { + if (surface_ != NULL) { + // We do not support more than one window surface. + return EGL_NO_SURFACE; + } + + { + gpu::TransferBufferManager* manager = new gpu::TransferBufferManager(); + transfer_buffer_manager_.reset(manager); + manager->Initialize(); + } + scoped_ptr command_buffer( + new gpu::CommandBufferService(transfer_buffer_manager_.get())); + if (!command_buffer->Initialize()) + return NULL; + + scoped_refptr group( + new gpu::gles2::ContextGroup(NULL, + NULL, + new gpu::gles2::ShaderTranslatorCache, + NULL, + NULL, + NULL, + true)); + + decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); + if (!decoder_.get()) + return EGL_NO_SURFACE; + + gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), + decoder_.get(), + NULL)); + + decoder_->set_engine(gpu_scheduler_.get()); + gfx::Size size(create_offscreen_width_, create_offscreen_height_); + if (create_offscreen_) { + gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); + create_offscreen_ = false; + create_offscreen_width_ = 0; + create_offscreen_height_ = 0; + } else { + gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win); + } + if (!gl_surface_.get()) + return EGL_NO_SURFACE; + + gl_context_ = gfx::GLContext::CreateGLContext(NULL, + gl_surface_.get(), + gfx::PreferDiscreteGpu); + if (!gl_context_.get()) + return EGL_NO_SURFACE; + + gl_context_->MakeCurrent(gl_surface_.get()); + + EGLint depth_size = 0; + EGLint alpha_size = 0; + EGLint stencil_size = 0; + GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); + GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); + GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); + std::vector attribs; + attribs.push_back(EGL_DEPTH_SIZE); + attribs.push_back(depth_size); + attribs.push_back(EGL_ALPHA_SIZE); + attribs.push_back(alpha_size); + attribs.push_back(EGL_STENCIL_SIZE); + attribs.push_back(stencil_size); + // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null + attribs.push_back(EGL_NONE); + + if (!decoder_->Initialize(gl_surface_.get(), + gl_context_.get(), + gl_surface_->IsOffscreen(), + size, + gpu::gles2::DisallowedFeatures(), + attribs)) { + return EGL_NO_SURFACE; + } + + command_buffer->SetPutOffsetChangeCallback( + base::Bind(&gpu::GpuScheduler::PutChanged, + base::Unretained(gpu_scheduler_.get()))); + command_buffer->SetGetBufferChangeCallback( + base::Bind(&gpu::GpuScheduler::SetGetBuffer, + base::Unretained(gpu_scheduler_.get()))); + + scoped_ptr cmd_helper( + new gpu::gles2::GLES2CmdHelper(command_buffer.get())); + if (!cmd_helper->Initialize(kCommandBufferSize)) + return NULL; + + scoped_ptr transfer_buffer(new gpu::TransferBuffer( + cmd_helper.get())); + + command_buffer_.reset(command_buffer.release()); + transfer_buffer_.reset(transfer_buffer.release()); + gles2_cmd_helper_.reset(cmd_helper.release()); + surface_.reset(new Surface(win)); + + return surface_.get(); +} + +void Display::DestroySurface(EGLSurface surface) { + DCHECK(IsValidSurface(surface)); + gpu_scheduler_.reset(); + if (decoder_.get()) { + decoder_->Destroy(true); + } + decoder_.reset(); + gl_surface_ = NULL; + gl_context_ = NULL; + surface_.reset(); +} + +void Display::SwapBuffers(EGLSurface surface) { + DCHECK(IsValidSurface(surface)); + context_->SwapBuffers(); +} + +bool Display::IsValidContext(EGLContext ctx) { + return (ctx != NULL) && (ctx == context_.get()); +} + +EGLContext Display::CreateContext(EGLConfig config, + EGLContext share_ctx, + const EGLint* attrib_list) { + DCHECK(IsValidConfig(config)); + // TODO(alokp): Add support for shared contexts. + if (share_ctx != NULL) + return EGL_NO_CONTEXT; + + DCHECK(command_buffer_ != NULL); + DCHECK(transfer_buffer_.get()); + + bool bind_generates_resources = true; + bool lose_context_when_out_of_memory = false; + bool support_client_side_arrays = true; + + context_.reset( + new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), + NULL, + transfer_buffer_.get(), + bind_generates_resources, + lose_context_when_out_of_memory, + support_client_side_arrays, + this)); + + if (!context_->Initialize( + kTransferBufferSize, + kTransferBufferSize / 2, + kTransferBufferSize * 2, + gpu::gles2::GLES2Implementation::kNoLimit)) { + return EGL_NO_CONTEXT; + } + + context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); + context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); + + return context_.get(); +} + +void Display::DestroyContext(EGLContext ctx) { + DCHECK(IsValidContext(ctx)); + context_.reset(); + transfer_buffer_.reset(); +} + +bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) { + if (ctx == EGL_NO_CONTEXT) { + gles2::SetGLContext(NULL); + } else { + DCHECK(IsValidSurface(draw)); + DCHECK(IsValidSurface(read)); + DCHECK(IsValidContext(ctx)); + gles2::SetGLContext(context_.get()); + } + return true; +} + +gpu::Capabilities Display::GetCapabilities() { + return decoder_->GetCapabilities(); +} + +int32_t Display::CreateImage(ClientBuffer buffer, + size_t width, + size_t height, + unsigned internalformat) { + NOTIMPLEMENTED(); + return -1; +} + +void Display::DestroyImage(int32 id) { + NOTIMPLEMENTED(); +} + +int32_t Display::CreateGpuMemoryBufferImage(size_t width, + size_t height, + unsigned internalformat, + unsigned usage) { + NOTIMPLEMENTED(); + return -1; +} + +uint32 Display::InsertSyncPoint() { + NOTIMPLEMENTED(); + return 0u; +} + +uint32 Display::InsertFutureSyncPoint() { + NOTIMPLEMENTED(); + return 0u; +} + +void Display::RetireSyncPoint(uint32 sync_point) { + NOTIMPLEMENTED(); +} + +void Display::SignalSyncPoint(uint32 sync_point, + const base::Closure& callback) { + NOTIMPLEMENTED(); +} + +void Display::SignalQuery(uint32 query, const base::Closure& callback) { + NOTIMPLEMENTED(); +} + +void Display::SetSurfaceVisible(bool visible) { + NOTIMPLEMENTED(); +} + +uint32 Display::CreateStreamTexture(uint32 texture_id) { + NOTIMPLEMENTED(); + return 0; +} + +void Display::SetLock(base::Lock*) { + NOTIMPLEMENTED(); +} + +} // namespace egl diff --git a/gpu/gles2_conform_support/egl/display.h b/gpu/gles2_conform_support/egl/display.h new file mode 100644 index 0000000000000..9b349bd3b6f3a --- /dev/null +++ b/gpu/gles2_conform_support/egl/display.h @@ -0,0 +1,124 @@ +// Copyright (c) 2012 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 GPU_GLES2_CONFORM_SUPPORT_EGL_DISPLAY_H_ +#define GPU_GLES2_CONFORM_SUPPORT_EGL_DISPLAY_H_ + +#include + +#include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" +#include "gpu/command_buffer/client/gpu_control.h" +#include "gpu/command_buffer/service/command_buffer_service.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gpu_scheduler.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" + +namespace gpu { +class CommandBufferService; +class GpuControl; +class GpuScheduler; +class TransferBuffer; +class TransferBufferManagerInterface; + +namespace gles2 { +class GLES2CmdHelper; +class GLES2Implementation; +} // namespace gles2 +} // namespace gpu + +namespace egl { + +class Config; +class Surface; + +class Display : private gpu::GpuControl { + public: + explicit Display(EGLNativeDisplayType display_id); + ~Display() override; + + void SetCreateOffscreen(int width, int height) { + create_offscreen_ = true; + create_offscreen_width_ = width; + create_offscreen_height_ = height; + } + + bool is_initialized() const { return is_initialized_; } + bool Initialize(); + + // Config routines. + bool IsValidConfig(EGLConfig config); + bool ChooseConfigs( + EGLConfig* configs, EGLint config_size, EGLint* num_config); + bool GetConfigs(EGLConfig* configs, EGLint config_size, EGLint* num_config); + bool GetConfigAttrib(EGLConfig config, EGLint attribute, EGLint* value); + + // Surface routines. + bool IsValidNativeWindow(EGLNativeWindowType win); + bool IsValidSurface(EGLSurface surface); + EGLSurface CreateWindowSurface(EGLConfig config, + EGLNativeWindowType win, + const EGLint* attrib_list); + void DestroySurface(EGLSurface surface); + void SwapBuffers(EGLSurface surface); + + // Context routines. + bool IsValidContext(EGLContext ctx); + EGLContext CreateContext(EGLConfig config, + EGLContext share_ctx, + const EGLint* attrib_list); + void DestroyContext(EGLContext ctx); + bool MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx); + + // GpuControl implementation. + gpu::Capabilities GetCapabilities() override; + int32_t CreateImage(ClientBuffer buffer, + size_t width, + size_t height, + unsigned internalformat) override; + void DestroyImage(int32_t id) override; + int32_t CreateGpuMemoryBufferImage(size_t width, + size_t height, + unsigned internalformat, + unsigned usage) override; + uint32 InsertSyncPoint() override; + uint32 InsertFutureSyncPoint() override; + void RetireSyncPoint(uint32 sync_point) override; + void SignalSyncPoint(uint32 sync_point, + const base::Closure& callback) override; + void SignalQuery(uint32 query, const base::Closure& callback) override; + void SetSurfaceVisible(bool visible) override; + uint32 CreateStreamTexture(uint32 texture_id) override; + void SetLock(base::Lock*) override; + + private: + EGLNativeDisplayType display_id_; + + bool is_initialized_; + bool create_offscreen_; + int create_offscreen_width_; + int create_offscreen_height_; + + scoped_ptr transfer_buffer_manager_; + scoped_ptr command_buffer_; + scoped_ptr gpu_scheduler_; + scoped_ptr decoder_; + scoped_refptr gl_context_; + scoped_refptr gl_surface_; + scoped_ptr gles2_cmd_helper_; + scoped_ptr transfer_buffer_; + + // TODO(alokp): Support more than one config, surface, and context. + scoped_ptr config_; + scoped_ptr surface_; + scoped_ptr context_; + + DISALLOW_COPY_AND_ASSIGN(Display); +}; + +} // namespace egl + +#endif // GPU_GLES2_CONFORM_SUPPORT_EGL_DISPLAY_H_ diff --git a/gpu/gles2_conform_support/egl/egl.cc b/gpu/gles2_conform_support/egl/egl.cc new file mode 100644 index 0000000000000..f23cf76e994b7 --- /dev/null +++ b/gpu/gles2_conform_support/egl/egl.cc @@ -0,0 +1,404 @@ +// Copyright (c) 2012 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 + +#include "base/command_line.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/gles2_conform_support/egl/display.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" + +#if REGAL_STATIC_EGL +extern "C" { + +typedef EGLContext RegalSystemContext; +#define REGAL_DECL +REGAL_DECL void RegalMakeCurrent( RegalSystemContext ctx ); + +} // extern "C" +#endif + +namespace { +void SetCurrentError(EGLint error_code) { +} + +template +T EglError(EGLint error_code, T return_value) { + SetCurrentError(error_code); + return return_value; +} + +template +T EglSuccess(T return_value) { + SetCurrentError(EGL_SUCCESS); + return return_value; +} + +EGLint ValidateDisplay(EGLDisplay dpy) { + if (dpy == EGL_NO_DISPLAY) + return EGL_BAD_DISPLAY; + + egl::Display* display = static_cast(dpy); + if (!display->is_initialized()) + return EGL_NOT_INITIALIZED; + + return EGL_SUCCESS; +} + +EGLint ValidateDisplayConfig(EGLDisplay dpy, EGLConfig config) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return error_code; + + egl::Display* display = static_cast(dpy); + if (!display->IsValidConfig(config)) + return EGL_BAD_CONFIG; + + return EGL_SUCCESS; +} + +EGLint ValidateDisplaySurface(EGLDisplay dpy, EGLSurface surface) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return error_code; + + egl::Display* display = static_cast(dpy); + if (!display->IsValidSurface(surface)) + return EGL_BAD_SURFACE; + + return EGL_SUCCESS; +} + +EGLint ValidateDisplayContext(EGLDisplay dpy, EGLContext context) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return error_code; + + egl::Display* display = static_cast(dpy); + if (!display->IsValidContext(context)) + return EGL_BAD_CONTEXT; + + return EGL_SUCCESS; +} +} // namespace + +extern "C" { +EGLint eglGetError() { + // TODO(alokp): Fix me. + return EGL_SUCCESS; +} + +EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) { + return new egl::Display(display_id); +} + +EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { + if (dpy == EGL_NO_DISPLAY) + return EglError(EGL_BAD_DISPLAY, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + if (!display->Initialize()) + return EglError(EGL_NOT_INITIALIZED, EGL_FALSE); + + int argc = 1; + const char* const argv[] = { + "dummy" + }; + base::CommandLine::Init(argc, argv); + gfx::GLSurface::InitializeOneOff(); + + *major = 1; + *minor = 4; + return EglSuccess(EGL_TRUE); +} + +EGLBoolean eglTerminate(EGLDisplay dpy) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + delete display; + + return EglSuccess(EGL_TRUE); +} + +const char* eglQueryString(EGLDisplay dpy, EGLint name) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, static_cast(NULL)); + + switch (name) { + case EGL_CLIENT_APIS: + return EglSuccess("OpenGL_ES"); + case EGL_EXTENSIONS: + return EglSuccess(""); + case EGL_VENDOR: + return EglSuccess("Google Inc."); + case EGL_VERSION: + return EglSuccess("1.4"); + default: + return EglError(EGL_BAD_PARAMETER, static_cast(NULL)); + } +} + +EGLBoolean eglChooseConfig(EGLDisplay dpy, + const EGLint* attrib_list, + EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + if (num_config == NULL) + return EglError(EGL_BAD_PARAMETER, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + if (!display->ChooseConfigs(configs, config_size, num_config)) + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + + return EglSuccess(EGL_TRUE); +} + +EGLBoolean eglGetConfigs(EGLDisplay dpy, + EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + if (num_config == NULL) + return EglError(EGL_BAD_PARAMETER, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + if (!display->GetConfigs(configs, config_size, num_config)) + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + + return EglSuccess(EGL_TRUE); +} + +EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, + EGLConfig config, + EGLint attribute, + EGLint* value) { + EGLint error_code = ValidateDisplayConfig(dpy, config); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + if (!display->GetConfigAttrib(config, attribute, value)) + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + + return EglSuccess(EGL_TRUE); +} + +EGLSurface eglCreateWindowSurface(EGLDisplay dpy, + EGLConfig config, + EGLNativeWindowType win, + const EGLint* attrib_list) { + EGLint error_code = ValidateDisplayConfig(dpy, config); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_NO_SURFACE); + + egl::Display* display = static_cast(dpy); + if (!display->IsValidNativeWindow(win)) + return EglError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + + EGLSurface surface = display->CreateWindowSurface(config, win, attrib_list); + if (surface == EGL_NO_SURFACE) + return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + + return EglSuccess(surface); +} + +EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, + EGLConfig config, + const EGLint* attrib_list) { + return EGL_NO_SURFACE; +} + +EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, + EGLConfig config, + EGLNativePixmapType pixmap, + const EGLint* attrib_list) { + return EGL_NO_SURFACE; +} + +EGLBoolean eglDestroySurface(EGLDisplay dpy, + EGLSurface surface) { + EGLint error_code = ValidateDisplaySurface(dpy, surface); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + display->DestroySurface(surface); + return EglSuccess(EGL_TRUE); +} + +EGLBoolean eglQuerySurface(EGLDisplay dpy, + EGLSurface surface, + EGLint attribute, + EGLint* value) { + return EGL_FALSE; +} + +EGLBoolean eglBindAPI(EGLenum api) { + return EGL_FALSE; +} + +EGLenum eglQueryAPI() { + return EGL_OPENGL_ES_API; +} + +EGLBoolean eglWaitClient(void) { + return EGL_FALSE; +} + +EGLBoolean eglReleaseThread(void) { + return EGL_FALSE; +} + +EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, + EGLenum buftype, + EGLClientBuffer buffer, + EGLConfig config, + const EGLint* attrib_list) { + return EGL_NO_SURFACE; +} + +EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, + EGLSurface surface, + EGLint attribute, + EGLint value) { + return EGL_FALSE; +} + +EGLBoolean eglBindTexImage(EGLDisplay dpy, + EGLSurface surface, + EGLint buffer) { + return EGL_FALSE; +} + +EGLBoolean eglReleaseTexImage(EGLDisplay dpy, + EGLSurface surface, + EGLint buffer) { + return EGL_FALSE; +} + +EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) { + return EGL_FALSE; +} + +EGLContext eglCreateContext(EGLDisplay dpy, + EGLConfig config, + EGLContext share_context, + const EGLint* attrib_list) { + EGLint error_code = ValidateDisplayConfig(dpy, config); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_NO_CONTEXT); + + if (share_context != EGL_NO_CONTEXT) { + error_code = ValidateDisplayContext(dpy, share_context); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_NO_CONTEXT); + } + + egl::Display* display = static_cast(dpy); + EGLContext context = display->CreateContext( + config, share_context, attrib_list); + if (context == EGL_NO_CONTEXT) + return EglError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + + return EglSuccess(context); +} + +EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { + EGLint error_code = ValidateDisplayContext(dpy, ctx); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + display->DestroyContext(ctx); + return EGL_TRUE; +} + +EGLBoolean eglMakeCurrent(EGLDisplay dpy, + EGLSurface draw, + EGLSurface read, + EGLContext ctx) { + if (ctx != EGL_NO_CONTEXT) { + EGLint error_code = ValidateDisplaySurface(dpy, draw); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + error_code = ValidateDisplaySurface(dpy, read); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + error_code = ValidateDisplayContext(dpy, ctx); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + } + + egl::Display* display = static_cast(dpy); + if (!display->MakeCurrent(draw, read, ctx)) + return EglError(EGL_CONTEXT_LOST, EGL_FALSE); + +#if REGAL_STATIC_EGL + RegalMakeCurrent(ctx); +#endif + + return EGL_TRUE; +} + +EGLContext eglGetCurrentContext() { + return EGL_NO_CONTEXT; +} + +EGLSurface eglGetCurrentSurface(EGLint readdraw) { + return EGL_NO_SURFACE; +} + +EGLDisplay eglGetCurrentDisplay() { + return EGL_NO_DISPLAY; +} + +EGLBoolean eglQueryContext(EGLDisplay dpy, + EGLContext ctx, + EGLint attribute, + EGLint* value) { + return EGL_FALSE; +} + +EGLBoolean eglWaitGL() { + return EGL_FALSE; +} + +EGLBoolean eglWaitNative(EGLint engine) { + return EGL_FALSE; +} + +EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { + EGLint error_code = ValidateDisplaySurface(dpy, surface); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast(dpy); + display->SwapBuffers(surface); + return EglSuccess(EGL_TRUE); +} + +EGLBoolean eglCopyBuffers(EGLDisplay dpy, + EGLSurface surface, + EGLNativePixmapType target) { + return EGL_FALSE; +} + +/* Now, define eglGetProcAddress using the generic function ptr. type */ +__eglMustCastToProperFunctionPointerType +eglGetProcAddress(const char* procname) { + return gles2::GetGLFunctionPointer(procname); +} +} // extern "C" diff --git a/gpu/gles2_conform_support/egl/surface.cc b/gpu/gles2_conform_support/egl/surface.cc new file mode 100644 index 0000000000000..423fe2756f65c --- /dev/null +++ b/gpu/gles2_conform_support/egl/surface.cc @@ -0,0 +1,15 @@ +// Copyright (c) 2011 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 "gpu/gles2_conform_support/egl/surface.h" + +namespace egl { + +Surface::Surface(EGLNativeWindowType win) : window_(win) { +} + +Surface::~Surface() { +} + +} // namespace egl diff --git a/gpu/gles2_conform_support/egl/surface.h b/gpu/gles2_conform_support/egl/surface.h new file mode 100644 index 0000000000000..3b66de082c7cd --- /dev/null +++ b/gpu/gles2_conform_support/egl/surface.h @@ -0,0 +1,29 @@ +// Copyright (c) 2011 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 GPU_GLES2_CONFORM_TEST_SURFACE_H_ +#define GPU_GLES2_CONFORM_TEST_SURFACE_H_ + +#include + +#include "base/basictypes.h" + +namespace egl { + +class Surface { + public: + explicit Surface(EGLNativeWindowType win); + ~Surface(); + + EGLNativeWindowType window() { return window_; } + + private: + EGLNativeWindowType window_; + + DISALLOW_COPY_AND_ASSIGN(Surface); +}; + +} // namespace egl + +#endif // GPU_GLES2_CONFORM_TEST_SURFACE_H_ diff --git a/gpu/gles2_conform_support/generate_gles2_conform_tests.py b/gpu/gles2_conform_support/generate_gles2_conform_tests.py new file mode 100755 index 0000000000000..df2980a11a430 --- /dev/null +++ b/gpu/gles2_conform_support/generate_gles2_conform_tests.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# Copyright (c) 2013 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. + +"""code generator for OpenGL ES 2.0 conformance tests.""" + +import os +import re +import sys + +def ReadFileAsLines(filename): + """Reads a file, removing blank lines and lines that start with #""" + file = open(filename, "r") + raw_lines = file.readlines() + file.close() + lines = [] + for line in raw_lines: + line = line.strip() + if len(line) > 0 and not line.startswith("#"): + lines.append(line) + return lines + + +def GenerateTests(file): + """Generates gles2_conform_test_autogen.cc""" + + tests = ReadFileAsLines( + "../../third_party/gles2_conform/GTF_ES/glsl/GTF/mustpass_es20.run") + + file.write(""" +#include "gpu/gles2_conform_support/gles2_conform_test.h" +#include "testing/gtest/include/gtest/gtest.h" +""") + + for test in tests: + file.write(""" +TEST(GLES2ConformTest, %(name)s) { + EXPECT_TRUE(RunGLES2ConformTest("%(path)s")); +} +""" % { + "name": re.sub(r'[^A-Za-z0-9]', '_', test), + "path": test, + }) + + +def main(argv): + """This is the main function.""" + + if len(argv) >= 1: + dir = argv[0] + else: + dir = '.' + + file = open(os.path.join(dir, 'gles2_conform_test_autogen.cc'), 'wb') + GenerateTests(file) + file.close() + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/gpu/gles2_conform_support/generate_gles2_embedded_data.py b/gpu/gles2_conform_support/generate_gles2_embedded_data.py new file mode 100755 index 0000000000000..8d7330f551d1c --- /dev/null +++ b/gpu/gles2_conform_support/generate_gles2_embedded_data.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# Copyright (c) 2013 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. + +"""generates files to embed the gles2 conformance test data in executable.""" + +import os +import sys + +class GenerateEmbeddedFiles(object): + """generates files to embed the gles2 conform test data in executable""" + + paths_to_ignore = set([ + ".", + "..", + ".svn", + ".git", + ".hg", + ]) + + extensions_to_include = set([ + ".vert", + ".frag", + ".test", + ".run", + ]) + + def __init__(self, scan_dir, base_dir): + self.scan_dir = scan_dir + self.base_dir = base_dir + self.count = 0; + if self.base_dir != None: + self.files_data_h = open(os.path.join(base_dir, "FilesDATA.h"), "wb") + self.files_data_c = open(os.path.join(base_dir, "FilesDATA.c"), "wb") + self.files_toc_c = open(os.path.join(base_dir, "FilesTOC.c"), "wb") + + self.files_data_h.write("#ifndef FilesDATA_h\n\n") + self.files_data_h.write("#define FilesDATA_h\n\n"); + + self.files_data_c.write("#include \"FilesDATA.h\"\n\n") + + self.files_toc_c.write("#include \"FilesTOC.h\"\n\n"); + self.files_toc_c.write("struct GTFVectorFileEntry tempFiles;\n\n"); + self.files_toc_c.write("struct FileEntry files[] = {\n"); + + self.AddFiles(scan_dir) + + if self.base_dir != None: + self.files_toc_c.write("\n};\n\n"); + self.files_toc_c.write( + "int numFileEntrys = sizeof(files) / sizeof(struct FileEntry);\n"); + + self.files_data_h.write("\n\n#endif // FilesDATA_h\n"); + + self.files_data_c.close() + self.files_data_h.close() + self.files_toc_c.close() + + def AddFiles(self, scan_dir): + """Scan a folder and embed the contents of files.""" + files = os.listdir(scan_dir) + sub_dirs = [] + for file in files: + full_path = os.path.join(scan_dir, file) + ext = os.path.splitext(file)[1] + base_path = full_path[len(self.scan_dir) + 1:] + if os.path.isdir(full_path): + if not file in GenerateEmbeddedFiles.paths_to_ignore: + sub_dirs.append(full_path) + elif ext in GenerateEmbeddedFiles.extensions_to_include: + if self.base_dir == None: + print full_path.replace("\\", "/") + else: + self.count += 1 + name = "_FILE_%s_%d" % (ext.upper(), self.count) + name = name.replace(".", "_") + + self.files_data_h.write("extern const char %s[];\n" % name) + self.files_data_c.write("const char %s[] = \n" % name) + + data = open(full_path, "r") + lines = data.readlines(); + data.close() + + for line in lines: + line = line.replace("\n", "") + line = line.replace("\r", "") + line = line.replace("\\", "\\\\") + line = line.replace("\"", "\\\"") + + self.files_data_c.write('"%s\\n"\n' % line) + + self.files_data_c.write(";\n") + self.files_toc_c.write("\t{ \"%s\", %s, 0 },\n" % ( + base_path.replace("\\", "/"), name)) + + for sub_dir in sub_dirs: + self.AddFiles(sub_dir) + + +def main(argv): + """This is the main function.""" + + if len(argv) >= 1: + scan_dir = argv[0] + else: + scan_dir = '.' + + if len(argv) >= 2: + base_dir = argv[1] + else: + base_dir = None + + GenerateEmbeddedFiles(scan_dir, base_dir) + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/gpu/gles2_conform_support/gles2_conform_support.c b/gpu/gles2_conform_support/gles2_conform_support.c new file mode 100644 index 0000000000000..db0e8c0bc2ca6 --- /dev/null +++ b/gpu/gles2_conform_support/gles2_conform_support.c @@ -0,0 +1,23 @@ +// Copyright (c) 2011 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. + +// A small sample just to make sure we can actually compile and link +// our OpenGL ES 2.0 conformance test support code. + +#include +#include "gpu/gles2_conform_support/gtf/gtf_stubs.h" + +// Note: This code is not intended to run, only compile and link. +int GTFMain(int argc, char** argv) { + EGLint major, minor; + EGLDisplay eglDisplay; + EGLNativeDisplayType nativeDisplay = EGL_DEFAULT_DISPLAY; + + eglDisplay = eglGetDisplay(nativeDisplay); + eglInitialize(eglDisplay, &major, &minor); + + return 0; +} + + diff --git a/gpu/gles2_conform_support/gles2_conform_test.cc b/gpu/gles2_conform_support/gles2_conform_test.cc new file mode 100644 index 0000000000000..906e1af2754a2 --- /dev/null +++ b/gpu/gles2_conform_support/gles2_conform_test.cc @@ -0,0 +1,97 @@ +// Copyright (c) 2013 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 "gpu/gles2_conform_support/gles2_conform_test.h" + +#include + +#include "base/at_exit.h" +#include "base/base_paths.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#if defined(OS_MACOSX) +#include "base/mac/scoped_nsautorelease_pool.h" +#endif +#include "base/path_service.h" +#include "base/process/launch.h" +#include "base/strings/string_util.h" +#include "gpu/config/gpu_test_config.h" +#include "gpu/config/gpu_test_expectations_parser.h" +#include "testing/gtest/include/gtest/gtest.h" + +bool RunGLES2ConformTest(const char* path) { + // Load test expectations, and return early if a test is marked as FAIL. + base::FilePath src_path; + PathService::Get(base::DIR_SOURCE_ROOT, &src_path); + base::FilePath test_expectations_path = + src_path.Append(FILE_PATH_LITERAL("gpu")). + Append(FILE_PATH_LITERAL("gles2_conform_support")). + Append(FILE_PATH_LITERAL("gles2_conform_test_expectations.txt")); + if (!base::PathExists(test_expectations_path)) { + LOG(ERROR) << "Fail to locate gles2_conform_test_expectations.txt"; + return false; + } + gpu::GPUTestExpectationsParser test_expectations; + if (!test_expectations.LoadTestExpectations(test_expectations_path)) { + LOG(ERROR) << "Fail to load gles2_conform_test_expectations.txt"; + return false; + } + gpu::GPUTestBotConfig bot_config; + if (!bot_config.LoadCurrentConfig(NULL)) { + LOG(ERROR) << "Fail to load bot configuration"; + return false; + } + if (!bot_config.IsValid()) { + LOG(ERROR) << "Invalid bot configuration"; + return false; + } + std::string path_string(path); + std::string test_name; + base::ReplaceChars(path_string, "\\/.", "_", &test_name); + int32 expectation = + test_expectations.GetTestExpectation(test_name, bot_config); + if (expectation != gpu::GPUTestExpectationsParser::kGpuTestPass) { + LOG(WARNING) << "Test " << test_name << " is bypassed"; + return true; + } + + base::FilePath test_path; + PathService::Get(base::DIR_EXE, &test_path); + base::FilePath program(test_path.Append(FILE_PATH_LITERAL( + "gles2_conform_test_windowless"))); + + base::CommandLine* currentCmdLine = base::CommandLine::ForCurrentProcess(); + base::CommandLine cmdline(program); + cmdline.AppendArguments(*currentCmdLine, false); + cmdline.AppendSwitch(std::string("--")); + cmdline.AppendArg(std::string("-run=") + path); + + std::string output; + bool success = base::GetAppOutput(cmdline, &output); + if (success) { + size_t success_index = output.find("Conformance PASSED all"); + size_t failed_index = output.find("FAILED"); + success = (success_index != std::string::npos) && + (failed_index == std::string::npos); + } + if (!success) { + LOG(ERROR) << output; + } + return success; +} + +int main(int argc, char** argv) { + base::AtExitManager exit_manager; + base::CommandLine::Init(argc, argv); +#if defined(OS_MACOSX) + base::mac::ScopedNSAutoreleasePool pool; +#endif + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + + + diff --git a/gpu/gles2_conform_support/gles2_conform_test.h b/gpu/gles2_conform_support/gles2_conform_test.h new file mode 100644 index 0000000000000..565774f4d689b --- /dev/null +++ b/gpu/gles2_conform_support/gles2_conform_test.h @@ -0,0 +1,11 @@ +// Copyright (c) 2013 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 GPU_GLES2_CONFORM_SUPPORT_GLES2_CONFORM_TEST_H +#define GPU_GLES2_CONFORM_SUPPORT_GLES2_CONFORM_TEST_H + +bool RunGLES2ConformTest(const char* path); + +#endif // GPU_GLES2_CONFORM_SUPPORT_GLES2_CONFORM_TEST_H + diff --git a/gpu/gles2_conform_support/gles2_conform_test_expectations.txt b/gpu/gles2_conform_support/gles2_conform_test_expectations.txt new file mode 100644 index 0000000000000..532ce749b66b1 --- /dev/null +++ b/gpu/gles2_conform_support/gles2_conform_test_expectations.txt @@ -0,0 +1,100 @@ +// Copyright (c) 2013 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. + +// This file contains a list of defective GLES2 conformance tests. The expected +// format is: +// {BUG#} {MODIFIERS} : {TEST_NAME} = {PASS,FAIL,FLAKY,TIMEOUT,SKIP} +// +// MODIFIERS can be a combination of the below list: +// WIN XP VISTA WIN7 MAC LEOPARD SNOWLEOPARD LION LINUX CHROMEOS MOUNTAINLION +// MAVERICKS +// NVIDIA AMD INTEL +// 0xabcd - GPU PCI device ID. Specifying a PCI id requires a vendor. +// DEBUG RELEASE +// +// TEST_NAME can be a specific test name, or have a '*' in the end, which +// indicates a prefix matching. +// +// Any tests whose expectations are not PASS will be skipped on the bots. +// +// Examples: +// 91530 MAC WIN LINUX : context_lost_restored = TIMEOUT +// 91533 WIN : gl_min_uniforms = FAIL +// 91531 MAC WIN LINUX : conformance_more_* = SKIP +// 91532 MAC NVIDIA 0x0640 : tex_image_and_sub_image_2d_with_video = PASS FAIL + +253674 LION INTEL : GL2ExtensionTests_dFdy_input_run = FAIL +253674 LION INTEL : GL2FixedTests_point_sprites_input_run = FAIL +253674 LION INTEL : GL_control_flow_input_run = FAIL +253674 LION INTEL : GL_dot_input_run = FAIL +253674 LION INTEL : GL_faceforward_input_run = FAIL +253674 LION INTEL : GL_length_input_run = FAIL +253674 LION INTEL : GL_normalize_input_run = FAIL +253674 LION INTEL : GL_reflect_input_run = FAIL +253674 LION INTEL : GL_refract_input_run = FAIL +253674 LION INTEL : GL_tan_input_run = FAIL + +253674 LION AMD : GL2FixedTests_point_sprites_input_run = FAIL +253674 LION AMD : GL_dot_input_run = FAIL +253674 LION AMD : GL_length_input_run = FAIL + +// See also crbug.com/306485 for non-Lion instances. +253674 MAC AMD : GL_distance_input_run = FAIL + +253674 MOUNTAINLION AMD : GL2ExtensionTests_dFdy_input_run = FAIL +253674 MOUNTAINLION AMD : GL2FixedTests_point_sprites_input_run = FAIL +253674 MOUNTAINLION AMD : GL_control_flow_input_run = FAIL +253674 MOUNTAINLION AMD : GL_operators_input_run = FAIL + +253674 MOUNTAINLION INTEL : GL2ExtensionTests_dFdy_input_run = FAIL +253674 MOUNTAINLION INTEL : GL2FixedTests_point_sprites_input_run = FAIL +253674 MOUNTAINLION INTEL : GL_control_flow_input_run = FAIL +253674 MOUNTAINLION INTEL : GL_operators_input_run = FAIL + +339911 MOUNTAINLION INTEL : GL2FixedTests_blend_input_run = FAIL + +253674 MAC : GL2Tests_glUniform_input_run = FAIL +253674 MAC : GL2Tests_three_uniforms_input_run = FAIL + +393677 CHROMEOS INTEL 0xa011 : GL_acos_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_asin_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_atan_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_control_flow_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_cos_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_discard_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_functions_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_gl_FrontFacing_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_log_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_log2_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_normalize_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL_sin_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL2ExtensionTests_dFdx_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL2ExtensionTests_dFdy_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL2ExtensionTests_fwidth_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL2FixedTests_blend_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL2FixedTests_point_rasterization_input_run = FAIL +393677 CHROMEOS INTEL 0xa011 : GL2FixedTests_scissor_input_run = FAIL + +408251 WIN : GL2ExtensionTests_vertex_array_object_input_run = FAIL +408251 WIN : GL2FixedTests_blend_input_run = FAIL +408251 WIN : GL2FixedTests_buffer_clear_input_run = FAIL +408251 WIN : GL2FixedTests_buffer_color_input_run = FAIL +408251 WIN : GL2FixedTests_copy_texture_input_run = FAIL +408251 WIN : GL2FixedTests_depth_buffer_clear_input_run = FAIL +408251 WIN : GL2FixedTests_mipmaps_interpolation_input_run = FAIL +408251 WIN : GL2FixedTests_stencil_plane_clear_input_run = FAIL +408251 WIN : GL2FixedTests_triangle_tiling_input_run = FAIL +408251 WIN : GL2FixedTests_user_clip_planes_input_run = FAIL +408251 WIN : GL2Tests_fixed_data_type_input_run = FAIL +408251 WIN : GL_biConstants_input_run = FAIL +408251 WIN : GL_biuDepthRange_input_run = FAIL +408251 WIN : GL_mat_input_run = FAIL +408251 WIN : GL_struct_input_run = FAIL + +//////////////////////////////////////////////////////////////////////////////// +// +// Temprory entries: they should be removed once the bugs are fixed. +// +//////////////////////////////////////////////////////////////////////////////// + diff --git a/gpu/gles2_conform_support/gtf/gtf_stubs.h b/gpu/gles2_conform_support/gtf/gtf_stubs.h new file mode 100644 index 0000000000000..23bb362bbe0c9 --- /dev/null +++ b/gpu/gles2_conform_support/gtf/gtf_stubs.h @@ -0,0 +1,23 @@ +// Copyright (c) 2011 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. + +// A few stubs so we don't need the actual OpenGL ES 2.0 conformance tests +// to compile the support for them. + +#ifndef GPU_GLES2_CONFORM_SUPPORT_GTF_GTF_STUBS_H_ +#define GPU_GLES2_CONFORM_SUPPORT_GTF_GTF_STUBS_H_ + +#include +#include +#include + +typedef unsigned char GTFbool; +#define GTFfalse 0 +#define GTFtrue 1 + +int GTFMain(int argc, char** argv); + +#endif // GPU_GLES2_CONFORM_SUPPORT_GTF_GTF_STUBS_H_ + + diff --git a/gpu/gles2_conform_support/native/BUILD.gn b/gpu/gles2_conform_support/native/BUILD.gn new file mode 100644 index 0000000000000..0d1c0ee04d7bd --- /dev/null +++ b/gpu/gles2_conform_support/native/BUILD.gn @@ -0,0 +1,58 @@ +# 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. + +# GYP version: gpu/gles2_conform_support/gles2_conform_support.gyp:egl_main_native +source_set("native") { + output_name = "egl_main_native" + sources = [ + "egl_native.cc", + "egl_native_win.cc", + "main.cc", + ] + defines = [ + "GLES2_CONFORM_SUPPORT_ONLY", + "GTF_GLES20", + "EGLAPI=", + "EGLAPIENTRY=", + ] + deps = [ + "//base", + "//gpu/gles2_conform_support/egl", + "//ui/gl", + ] + if (is_linux) { + sources += [ + "egl_native_aura.cc", + "egl_native_x11.cc", + ] + } +} + +# GYP version: gpu/gles2_conform_support/gles2_conform_support.gyp:egl_main_windowless +source_set("windowless") { + output_name = "egl_main_windowless" + sources = [ + "egl_native.cc", + "egl_native_win.cc", + "egl_native_windowless.cc", + "main.cc", + ] + defines = [ + "GLES2_CONFORM_SUPPORT_ONLY", + "GTF_GLES20", + "EGLAPI=", + "EGLAPIENTRY=", + ] + deps = [ + "//base", + "//gpu/gles2_conform_support/egl", + "//ui/gl", + ] + if (is_linux) { + sources += [ + "egl_native_aura.cc", + "egl_native_x11.cc", + ] + } +} diff --git a/gpu/gles2_conform_support/native/egl_native.cc b/gpu/gles2_conform_support/native/egl_native.cc new file mode 100644 index 0000000000000..bf8c7719b9615 --- /dev/null +++ b/gpu/gles2_conform_support/native/egl_native.cc @@ -0,0 +1,42 @@ +// Copyright (c) 2012 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. + +extern "C" { +#if defined(GLES2_CONFORM_SUPPORT_ONLY) +#include "gpu/gles2_conform_support/gtf/gtf_stubs.h" +#else +#include "third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.h" +#endif + +GTFbool GTFNativeCreatePixmap(EGLNativeDisplayType nativeDisplay, + EGLDisplay eglDisplay, EGLConfig eglConfig, + const char *title, int width, int height, + EGLNativePixmapType *pNativePixmap) { + return GTFtrue; +} + +void GTFNativeDestroyPixmap(EGLNativeDisplayType nativeDisplay, + EGLNativePixmapType nativePixmap) { +} + +EGLImageKHR GTFCreateEGLImageExternal( + int width, int height, int format, + float r, float g, float b, float a, void** resource) { + return (EGLImageKHR)0; +} + +void GTFDestroyEGLImageExternal(EGLImageKHR image, void* resource) { +} + +const int* GTFQueryFormatsEGLImageExternal(void) { + return 0; +} + +GTFbool GTFIsAlphaFormatEGLImageExternal(int format) { + return GTFfalse; +} + +} // extern "C" + + diff --git a/gpu/gles2_conform_support/native/egl_native_aura.cc b/gpu/gles2_conform_support/native/egl_native_aura.cc new file mode 100644 index 0000000000000..f3eea4726c368 --- /dev/null +++ b/gpu/gles2_conform_support/native/egl_native_aura.cc @@ -0,0 +1,42 @@ +// Copyright 2013 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. + +// This is just a compile fix. If this is really needed when using aura, the +// methods below should be filled out. + +#include +#include + +#include "base/logging.h" + +extern "C" { +#if defined(GLES2_CONFORM_SUPPORT_ONLY) +#include "gpu/gles2_conform_support/gtf/gtf_stubs.h" +#else +#include "third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.h" +#endif + +GTFbool GTFNativeCreateDisplay(EGLNativeDisplayType *pNativeDisplay) { + NOTIMPLEMENTED(); + return GTFfalse; +} + +void GTFNativeDestroyDisplay(EGLNativeDisplayType nativeDisplay) { + NOTIMPLEMENTED(); +} + +void GTFNativeDestroyWindow(EGLNativeDisplayType nativeDisplay, + EGLNativeWindowType nativeWindow) { + NOTIMPLEMENTED(); +} + +GTFbool GTFNativeCreateWindow(EGLNativeDisplayType nativeDisplay, + EGLDisplay eglDisplay, EGLConfig eglConfig, + const char* title, int width, int height, + EGLNativeWindowType *pNativeWindow) { + NOTIMPLEMENTED(); + return GTFfalse; +} + +} // extern "C" diff --git a/gpu/gles2_conform_support/native/egl_native_win.cc b/gpu/gles2_conform_support/native/egl_native_win.cc new file mode 100644 index 0000000000000..acb286db61d0a --- /dev/null +++ b/gpu/gles2_conform_support/native/egl_native_win.cc @@ -0,0 +1,117 @@ +// Copyright (c) 2012 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. + +extern "C" { +#if defined(GLES2_CONFORM_SUPPORT_ONLY) +#include "gpu/gles2_conform_support/gtf/gtf_stubs.h" +#else +#include "third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.h" +#endif +} + +#include + +namespace { +LPCTSTR kWindowClassName = TEXT("ES2CONFORM"); + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, + WPARAM w_param, LPARAM l_param) { + LRESULT result = 0; + switch (msg) { + case WM_CLOSE: + ::DestroyWindow(hwnd); + break; + case WM_DESTROY: + ::PostQuitMessage(0); + break; + case WM_ERASEBKGND: + // Return a non-zero value to indicate that the background has been + // erased. + result = 1; + break; + default: + result = ::DefWindowProc(hwnd, msg, w_param, l_param); + break; + } + return result; +} +} // namespace. + +extern "C" { + +GTFbool GTFNativeCreateDisplay(EGLNativeDisplayType *pNativeDisplay) { + *pNativeDisplay = EGL_DEFAULT_DISPLAY; + return GTFtrue; +} + +void GTFNativeDestroyDisplay(EGLNativeDisplayType nativeDisplay) { + // Nothing to destroy since we are using EGL_DEFAULT_DISPLAY +} + +GTFbool GTFNativeCreateWindow(EGLNativeDisplayType nativeDisplay, + EGLDisplay eglDisplay, EGLConfig eglConfig, + const char* title, int width, int height, + EGLNativeWindowType *pNativeWindow) { + WNDCLASS wnd_class = {0}; + HINSTANCE instance = GetModuleHandle(NULL); + wnd_class.style = CS_OWNDC; + wnd_class.lpfnWndProc = WindowProc; + wnd_class.hInstance = instance; + wnd_class.hbrBackground = + reinterpret_cast(GetStockObject(BLACK_BRUSH)); + wnd_class.lpszClassName = kWindowClassName; + if (!RegisterClass(&wnd_class)) + return GTFfalse; + + DWORD wnd_style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + RECT wnd_rect; + wnd_rect.left = 0; + wnd_rect.top = 0; + wnd_rect.right = width; + wnd_rect.bottom = height; + if (!AdjustWindowRect(&wnd_rect, wnd_style, FALSE)) + return GTFfalse; + +#ifdef UNICODE + // Convert ascii string to wide string. + const std::wstring wnd_title(title, title + strlen(title)); +#else + const std::string wnd_title = title; +#endif // UNICODE + + HWND hwnd = CreateWindow( + wnd_class.lpszClassName, + wnd_title.c_str(), + wnd_style, + 0, + 0, + wnd_rect.right - wnd_rect.left, + wnd_rect.bottom - wnd_rect.top, + NULL, + NULL, + instance, + NULL); + if (hwnd == NULL) + return GTFfalse; + + ShowWindow(hwnd, SW_SHOWNORMAL); + *pNativeWindow = hwnd; + return GTFtrue; +} + +void GTFNativeDestroyWindow(EGLNativeDisplayType nativeDisplay, + EGLNativeWindowType nativeWindow) { + DestroyWindow(nativeWindow); + UnregisterClass(kWindowClassName, GetModuleHandle(NULL)); +} + +EGLImageKHR GTFCreateEGLImage(int width, int height, + GLenum format, GLenum type) { + return (EGLImageKHR)NULL; +} + +void GTFDestroyEGLImage(EGLImageKHR image) { +} + +} // extern "C" diff --git a/gpu/gles2_conform_support/native/egl_native_windowless.cc b/gpu/gles2_conform_support/native/egl_native_windowless.cc new file mode 100644 index 0000000000000..14172cfea1e2f --- /dev/null +++ b/gpu/gles2_conform_support/native/egl_native_windowless.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2012 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 "gpu/gles2_conform_support/egl/display.h" + +extern "C" { +#if defined(GLES2_CONFORM_SUPPORT_ONLY) +#include "gpu/gles2_conform_support/gtf/gtf_stubs.h" +#else +#include "third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.h" +#endif + +GTFbool GTFNativeCreateDisplay(EGLNativeDisplayType *pNativeDisplay) { + *pNativeDisplay = EGL_DEFAULT_DISPLAY; + return GTFtrue; +} + +void GTFNativeDestroyDisplay(EGLNativeDisplayType nativeDisplay) { + // Nothing to destroy since we are using EGL_DEFAULT_DISPLAY +} + +GTFbool GTFNativeCreateWindow(EGLNativeDisplayType nativeDisplay, + EGLDisplay eglDisplay, EGLConfig eglConfig, + const char* title, int width, int height, + EGLNativeWindowType *pNativeWindow) { + egl::Display* display = static_cast(eglDisplay); + display->SetCreateOffscreen(width, height); + return GTFtrue; +} + +void GTFNativeDestroyWindow(EGLNativeDisplayType nativeDisplay, + EGLNativeWindowType nativeWindow) { +} + +EGLImageKHR GTFCreateEGLImage(int width, int height, + GLenum format, GLenum type) { + return (EGLImageKHR)NULL; +} + +void GTFDestroyEGLImage(EGLImageKHR image) { +} + +} // extern "C" + diff --git a/gpu/gles2_conform_support/native/egl_native_x11.cc b/gpu/gles2_conform_support/native/egl_native_x11.cc new file mode 100644 index 0000000000000..3cb6895c88041 --- /dev/null +++ b/gpu/gles2_conform_support/native/egl_native_x11.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2012 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 +#include + +extern "C" { +#if defined(GLES2_CONFORM_SUPPORT_ONLY) +#include "gpu/gles2_conform_support/gtf/gtf_stubs.h" +#else +#include "third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.h" +#endif + +EGLImageKHR GTFCreateEGLImage(int width, int height, + GLenum format, GLenum type) { + PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr_; + egl_create_image_khr_ = reinterpret_cast + (eglGetProcAddress("eglCreateImageKHR")); + + static const EGLint attrib[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_GL_TEXTURE_LEVEL_KHR, 0, + EGL_NONE + }; + + if (format != GL_RGBA && format != GL_RGB) + return static_cast(NULL); + + if (type != GL_UNSIGNED_BYTE) + return static_cast(NULL); + + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, + 0, + format, + width, + height, + 0, + format, + type, + NULL); + + // Disable mip-maps because we do not require it. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + if(glGetError() != GL_NO_ERROR) + return static_cast(NULL); + + EGLImageKHR egl_image = + egl_create_image_khr_(eglGetCurrentDisplay(), + eglGetCurrentContext(), + EGL_GL_TEXTURE_2D_KHR, + reinterpret_cast(texture), + attrib); + + if (eglGetError() == EGL_SUCCESS) + return egl_image; + else + return static_cast(NULL); +} + +void GTFDestroyEGLImage(EGLImageKHR image) { + PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr_; + egl_destroy_image_khr_ = reinterpret_cast + (eglGetProcAddress("eglDestroyImageKHR")); + + egl_destroy_image_khr_(eglGetCurrentDisplay(), image); +} + +} // extern "C" diff --git a/gpu/gles2_conform_support/native/main.cc b/gpu/gles2_conform_support/native/main.cc new file mode 100644 index 0000000000000..1dc377b099eaa --- /dev/null +++ b/gpu/gles2_conform_support/native/main.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2012 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 "base/at_exit.h" +#include "base/command_line.h" +#include "base/message_loop/message_loop.h" +#if defined(OS_MACOSX) +#include "base/mac/scoped_nsautorelease_pool.h" +#endif +#if defined(OS_WIN) +#include "base/strings/utf_string_conversions.h" +#endif +#include "ui/gl/gl_surface.h" + +extern "C" { +#if defined(GLES2_CONFORM_SUPPORT_ONLY) +#include "gpu/gles2_conform_support/gtf/gtf_stubs.h" +#else +#include "third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFMain.h" +#endif +} + +int main(int argc, char *argv[]) { + base::AtExitManager at_exit; + base::CommandLine::Init(argc, argv); + base::MessageLoopForUI message_loop; + + base::CommandLine::StringVector args = + base::CommandLine::ForCurrentProcess()->GetArgs(); + +#if defined(OS_MACOSX) + base::mac::ScopedNSAutoreleasePool pool; +#endif + + scoped_ptr argsArray(new const char*[args.size()+1]); + argsArray[0] = argv[0]; + +#if defined(OS_WIN) + std::vector argsNonWide(args.size()); + for (size_t index = 0; index < args.size(); ++index) { + argsNonWide[index] = base::UTF16ToASCII(args[index]); + argsArray[index+1] = argsNonWide[index].c_str(); + } +#else + for (size_t index = 0; index < args.size(); ++index) { + argsArray[index+1] = args[index].c_str(); + } +#endif + + GTFMain(static_cast(args.size()+1), + const_cast(argsArray.get())); + + return 0; +} + diff --git a/services/android/add_manifest_entry.py b/mojo/android/add_manifest_entry.py similarity index 100% rename from services/android/add_manifest_entry.py rename to mojo/android/add_manifest_entry.py diff --git a/services/android/rules.gni b/mojo/android/rules.gni similarity index 95% rename from services/android/rules.gni rename to mojo/android/rules.gni index facf5057fed0d..c1c0886eb2237 100644 --- a/services/android/rules.gni +++ b/mojo/android/rules.gni @@ -5,7 +5,7 @@ import("//build/config/android/rules.gni") import("//mojo/public/mojo_application.gni") -servicess_android_path = get_path_info(".", "abspath") +mojo_android_path = get_path_info(".", "abspath") template("mojo_android_java_application") { assert(defined(invoker.mojo_main)) @@ -42,7 +42,7 @@ template("mojo_android_java_application") { } action(android_with_manifest_name) { - script = "${servicess_android_path}/add_manifest_entry.py" + script = "${mojo_android_path}/add_manifest_entry.py" deps = [ ":$android_standalone_name", diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn index f86ded928c4c8..25756548c4d53 100644 --- a/mojo/common/BUILD.gn +++ b/mojo/common/BUILD.gn @@ -19,6 +19,7 @@ component("common") { "data_pipe_utils_internal.h", "handle_watcher.cc", "handle_watcher.h", + "interface_ptr_set.h", "message_pump_mojo.cc", "message_pump_mojo.h", "message_pump_mojo_handler.h", @@ -48,9 +49,10 @@ test("mojo_common_unittests") { "common_type_converters_unittest.cc", "data_pipe_utils_unittest.cc", "handle_watcher_unittest.cc", + "interface_ptr_set_unittest.cc", "message_pump_mojo_unittest.cc", "task_tracker_unittest.cc", - "weak_interface_ptr_set_unittest.cc", + "weak_binding_set_unittest.cc", ] deps = [ diff --git a/mojo/common/interface_ptr_set.h b/mojo/common/interface_ptr_set.h new file mode 100644 index 0000000000000..a08a7289696c4 --- /dev/null +++ b/mojo/common/interface_ptr_set.h @@ -0,0 +1,72 @@ +// Copyright 2014 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 MOJO_COMMON_INTERFACE_PTR_SET_H_ +#define MOJO_COMMON_INTERFACE_PTR_SET_H_ + +#include + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" + +namespace mojo { + +// An InterfacePtrSet contains a collection of InterfacePtrs +// that are automatically removed from the collection and destroyed +// when their associated MessagePipe experiences a connection error. +// When the set is destroyed all of the MessagePipes will be closed. +template +class InterfacePtrSet { + public: + InterfacePtrSet() {} + ~InterfacePtrSet() { CloseAll(); } + + // |ptr| must be bound to a message pipe. + void AddInterfacePtr(InterfacePtr ptr) { + DCHECK(ptr.is_bound()); + ptrs_.emplace_back(ptr.Pass()); + InterfacePtr& intrfc_ptr = ptrs_.back(); + Interface* pointer = intrfc_ptr.get(); + // Set the connection error handler for the newly added InterfacePtr to be a + // function that will erase it from the vector. + intrfc_ptr.set_connection_error_handler([pointer, this]() { + // Since InterfacePtr itself is a movable type, the thing that uniquely + // identifies the InterfacePtr we wish to erase is its Interface*. + auto it = std::find_if(ptrs_.begin(), ptrs_.end(), + [pointer](const InterfacePtr& p) { + return (p.get() == pointer); + }); + DCHECK(it != ptrs_.end()); + ptrs_.erase(it); + }); + } + + // Applies |function| to each of the InterfacePtrs in the set. + template + void ForAllPtrs(FunctionType function) { + for (const auto& it : ptrs_) { + if (it) + function(it.get()); + } + } + + // Closes the MessagePipe associated with each of the InterfacePtrs in + // this set and clears the set. + void CloseAll() { + for (auto& it : ptrs_) { + if (it) + it.reset(); + } + ptrs_.clear(); + } + + size_t size() const { return ptrs_.size(); } + + private: + std::vector> ptrs_; +}; + +} // namespace mojo + +#endif // MOJO_COMMON_INTERFACE_PTR_SET_H_ diff --git a/mojo/common/weak_interface_ptr_set_unittest.cc b/mojo/common/interface_ptr_set_unittest.cc similarity index 82% rename from mojo/common/weak_interface_ptr_set_unittest.cc rename to mojo/common/interface_ptr_set_unittest.cc index 833606b82e7a5..8edd4caaf7621 100644 --- a/mojo/common/weak_interface_ptr_set_unittest.cc +++ b/mojo/common/interface_ptr_set_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "mojo/common/weak_interface_ptr_set.h" +#include "mojo/common/interface_ptr_set.h" #include "base/message_loop/message_loop.h" #include "mojo/common/message_pump_mojo.h" @@ -32,8 +32,8 @@ class DummyImpl : public tests::Dummy { DISALLOW_COPY_AND_ASSIGN(DummyImpl); }; -// Tests all of the functionality of WeakInterfacePtrSet. -TEST(WeakInterfacePtr, FullLifeCycleTest) { +// Tests all of the functionality of InterfacePtrSet. +TEST(InterfacePtrSetTest, FullLifeCycle) { base::MessageLoop loop(MessagePumpMojo::Create()); // Create 10 InterfacePtrs. @@ -47,7 +47,7 @@ TEST(WeakInterfacePtr, FullLifeCycleTest) { } // Move all 10 InterfacePtrs into the set. - WeakInterfacePtrSet intrfc_ptr_set; + InterfacePtrSet intrfc_ptr_set; EXPECT_EQ(0u, intrfc_ptr_set.size()); for (InterfacePtr& ptr : intrfc_ptrs) { intrfc_ptr_set.AddInterfacePtr(ptr.Pass()); @@ -73,22 +73,20 @@ TEST(WeakInterfacePtr, FullLifeCycleTest) { EXPECT_EQ(1, impl->call_count()); } - // Close the first 5 message pipes. + // Close the first 5 message pipes. This will (after RunUntilIdle) cause + // connection errors on the closed pipes which will cause the first five + // objects to be removed. for (size_t i = 0; i < kNumObjects / 2; i++) { impls[i]->CloseMessagePipe(); } - - // Invoke ForAllPtrs() again. This will cause connection errors on the - // closed pipes which will cause the first five objects to be removed. EXPECT_EQ(kNumObjects, intrfc_ptr_set.size()); - // TODO(rudominer) It should not be necessary to invoke ForAllPtrs in order - // to see the effect of the error handlers. The error handlers are invoked - // just after PumpMessages() is invoked. Fix this test after we fix the - // implementation of WeakInterfacePtrSet. - intrfc_ptr_set.ForAllPtrs([](tests::Dummy* dummy) { dummy->Foo(); }); loop.RunUntilIdle(); EXPECT_EQ(kNumObjects / 2, intrfc_ptr_set.size()); + // Invoke ForAllPtrs again on the remaining five pointers + intrfc_ptr_set.ForAllPtrs([](tests::Dummy* dummy) { dummy->Foo(); }); + loop.RunUntilIdle(); + // Check that now the first five counts are still 1 but the second five // counts are two. for (size_t i = 0; i < kNumObjects; i++) { diff --git a/mojo/common/weak_binding_set.h b/mojo/common/weak_binding_set.h index 90cd7e4af00c5..203e8c3242ec2 100644 --- a/mojo/common/weak_binding_set.h +++ b/mojo/common/weak_binding_set.h @@ -13,47 +13,8 @@ namespace mojo { -namespace internal { - -// TODO(vtl): https://github.com/domokit/mojo/issues/311 applies here as well. -template -class WeakBinding { - public: - WeakBinding(Interface* impl, InterfaceRequest request) - : binding_(impl, request.Pass()), weak_ptr_factory_(this) { - binding_.set_connection_error_handler([this]() { OnConnectionError(); }); - } - - ~WeakBinding() {} - - void set_connection_error_handler(const Closure& error_handler) { - error_handler_ = error_handler; - } - - base::WeakPtr GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - void Close() { binding_.Close(); } - - private: - void OnConnectionError() { - Closure error_handler = error_handler_; - delete this; - error_handler.Run(); - } - - mojo::Binding binding_; - Closure error_handler_; - base::WeakPtrFactory weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(WeakBinding); -}; - -} // namespace internal - -// Use this class to manage a set of weak pointers to bindings each of which is -// owned by the pipe they are bound to. +// Use this class to manage a set of bindings each of which is +// owned by the pipe it is bound to. template class WeakBindingSet { public: @@ -61,32 +22,29 @@ class WeakBindingSet { ~WeakBindingSet() { CloseAllBindings(); } void AddBinding(Interface* impl, InterfaceRequest request) { - auto binding = new internal::WeakBinding(impl, request.Pass()); - binding->set_connection_error_handler([this]() { OnConnectionError(); }); - bindings_.push_back(binding->GetWeakPtr()); + bindings_.emplace_back(new Binding(impl, request.Pass())); + auto* binding = bindings_.back().get(); + // Set the connection error handler for the newly added Binding to be a + // function that will erase it from the vector. + binding->set_connection_error_handler([this, binding]() { + auto it = + std::find_if(bindings_.begin(), bindings_.end(), + [binding](const std::unique_ptr>& b) { + return (b.get() == binding); + }); + DCHECK(it != bindings_.end()); + bindings_.erase(it); + }); } void CloseAllBindings() { - for (const auto& it : bindings_) { - if (it) - it->Close(); - } bindings_.clear(); } - private: - void OnConnectionError() { - // Clear any deleted bindings. - bindings_.erase( - std::remove_if( - bindings_.begin(), bindings_.end(), - [](const base::WeakPtr>& p) { - return p.get() == nullptr; - }), - bindings_.end()); - } + size_t size() const { return bindings_.size(); } - std::vector>> bindings_; + private: + std::vector>> bindings_; DISALLOW_COPY_AND_ASSIGN(WeakBindingSet); }; diff --git a/mojo/common/weak_binding_set_unittest.cc b/mojo/common/weak_binding_set_unittest.cc new file mode 100644 index 0000000000000..2a957b1f9782b --- /dev/null +++ b/mojo/common/weak_binding_set_unittest.cc @@ -0,0 +1,108 @@ +// 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 "mojo/common/weak_binding_set.h" + +#include "base/message_loop/message_loop.h" +#include "mojo/common/message_pump_mojo.h" +#include "mojo/common/test_interfaces.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace common { +namespace { + +class DummyImpl : public tests::Dummy { + public: + DummyImpl() {} + + void Foo() override { call_count_++; } + + int call_count() const { return call_count_; } + + private: + int call_count_ = 0; + + DISALLOW_COPY_AND_ASSIGN(DummyImpl); +}; + +// Tests all of the functionality of WeakBindingSet. +TEST(WeakBindingSet, FullLifeCycleTest) { + base::MessageLoop loop(MessagePumpMojo::Create()); + + // Create 10 InterfacePtrs and DummyImpls. + const size_t kNumObjects = 10; + InterfacePtr intrfc_ptrs[kNumObjects]; + DummyImpl impls[kNumObjects]; + + // Create 10 message pipes, bind everything together, and add the + // bindings to binding_set. + WeakBindingSet binding_set; + EXPECT_EQ(0u, binding_set.size()); + for (size_t i = 0; i < kNumObjects; i++) { + binding_set.AddBinding(&impls[i], GetProxy(&intrfc_ptrs[i])); + } + EXPECT_EQ(kNumObjects, binding_set.size()); + + // Check that initially all call counts are zero. + for (const auto& impl : impls) { + EXPECT_EQ(0, impl.call_count()); + } + + // Invoke method foo() on all 10 InterfacePointers. + for (InterfacePtr& ptr : intrfc_ptrs) { + ptr->Foo(); + } + + // Check that now all call counts are one. + loop.RunUntilIdle(); + for (const auto& impl : impls) { + EXPECT_EQ(1, impl.call_count()); + } + + // Close the first 5 message pipes and destroy the first five + // InterfacePtrs. + for (size_t i = 0; i < kNumObjects / 2; i++) { + intrfc_ptrs[i].reset(); + } + + // Check that the set contains only five elements now. + loop.RunUntilIdle(); + EXPECT_EQ(kNumObjects / 2, binding_set.size()); + + // Invoke method foo() on the second five InterfacePointers. + for (size_t i = kNumObjects / 2; i < kNumObjects; i++) { + intrfc_ptrs[i]->Foo(); + } + loop.RunUntilIdle(); + + // Check that now the first five counts are still 1 but the second five + // counts are two. + for (size_t i = 0; i < kNumObjects; i++) { + int expected = (i < kNumObjects / 2 ? 1 : 2); + EXPECT_EQ(expected, impls[i].call_count()); + } + + // Invoke CloseAllBindings + binding_set.CloseAllBindings(); + EXPECT_EQ(0u, binding_set.size()); + + // Invoke method foo() on the second five InterfacePointers. + for (size_t i = kNumObjects / 2; i < kNumObjects; i++) { + intrfc_ptrs[i]->Foo(); + } + loop.RunUntilIdle(); + + // Check that the call counts are the same as before. + for (size_t i = 0; i < kNumObjects; i++) { + int expected = (i < kNumObjects / 2 ? 1 : 2); + EXPECT_EQ(expected, impls[i].call_count()); + } +} + +} // namespace +} // namespace common +} // namespace mojo diff --git a/mojo/common/weak_interface_ptr_set.h b/mojo/common/weak_interface_ptr_set.h deleted file mode 100644 index f93c0259574a7..0000000000000 --- a/mojo/common/weak_interface_ptr_set.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 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 MOJO_COMMON_WEAK_INTERFACE_PTR_SET_H_ -#define MOJO_COMMON_WEAK_INTERFACE_PTR_SET_H_ - -#include - -#include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" - -namespace mojo { - -namespace internal { - -// TODO(vtl): This name of this class is a little odd -- it's not a "weak -// pointer", but a wrapper around InterfacePtr that owns itself and can vend -// weak pointers to itself. Probably, with connection error callbacks instead of -// ErrorHandlers, this class is unneeded, and WeakInterfacePtrSet can simply -// own/remove interface pointers as connection errors occur. -// https://github.com/domokit/mojo/issues/311 -template -class WeakInterfacePtr { - public: - explicit WeakInterfacePtr(InterfacePtr ptr) - : ptr_(ptr.Pass()), weak_ptr_factory_(this) { - ptr_.set_connection_error_handler([this]() { delete this; }); - } - ~WeakInterfacePtr() {} - - void Close() { ptr_.reset(); } - - Interface* get() { return ptr_.get(); } - - base::WeakPtr GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - private: - InterfacePtr ptr_; - base::WeakPtrFactory weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(WeakInterfacePtr); -}; - -} // namespace internal - -// A WeakInterfacePtrSet contains a collection of InterfacePtrs -// that are automatically removed from the collection and destroyed -// when their associated MessagePipe experiences a connection error. -// When the set is destroyed all of the MessagePipes will be closed. -// TODO(rudominer) Rename this class since the ownership of the elements -// is not "weak" from the point of view of the client. -template -class WeakInterfacePtrSet { - public: - WeakInterfacePtrSet() {} - ~WeakInterfacePtrSet() { CloseAll(); } - - // |ptr| must be bound to a message pipe. - void AddInterfacePtr(InterfacePtr ptr) { - DCHECK(ptr.is_bound()); - auto weak_interface_ptr = - new internal::WeakInterfacePtr(ptr.Pass()); - ptrs_.push_back(weak_interface_ptr->GetWeakPtr()); - ClearNullInterfacePtrs(); - } - - // Applies |function| to each of the InterfacePtrs in the set. - template - void ForAllPtrs(FunctionType function) { - for (const auto& it : ptrs_) { - if (it) - function(it->get()); - } - ClearNullInterfacePtrs(); - } - - // Closes the MessagePipe associated with each of the InterfacePtrs in - // this set and clears the set. - void CloseAll() { - for (const auto& it : ptrs_) { - if (it) - it->Close(); - } - ptrs_.clear(); - } - - // TODO(rudominer) After reworking this class and eliminating the method - // ClearNullInterfacePtrs, this method should become const. - size_t size() { - ClearNullInterfacePtrs(); - return ptrs_.size(); - } - - private: - using WPWIPI = base::WeakPtr>; - - void ClearNullInterfacePtrs() { - ptrs_.erase(std::remove_if(ptrs_.begin(), ptrs_.end(), [](const WPWIPI& p) { - return p.get() == nullptr; - }), ptrs_.end()); - } - - std::vector ptrs_; -}; - -} // namespace mojo - -#endif // MOJO_COMMON_WEAK_INTERFACE_PTR_SET_H_ diff --git a/mojo/dart/embedder/BUILD.gn b/mojo/dart/embedder/BUILD.gn index 708fc6678f9ad..f15e4aa0163f5 100644 --- a/mojo/dart/embedder/BUILD.gn +++ b/mojo/dart/embedder/BUILD.gn @@ -43,7 +43,6 @@ source_set("dart_controller_no_snapshot") { ":generate_dart_embedder_service_isolate_resources_cc", "//base", "//base:i18n", - "//crypto", "//dart/runtime:libdart", "//dart/runtime/bin:libdart_embedder_noio", "//third_party/dart-pkg", diff --git a/mojo/dart/embedder/builtin_natives.cc b/mojo/dart/embedder/builtin_natives.cc index 4a8ce6efd1a78..e7a55854f2fc2 100644 --- a/mojo/dart/embedder/builtin_natives.cc +++ b/mojo/dart/embedder/builtin_natives.cc @@ -12,7 +12,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "crypto/random.h" +#include "base/rand_util.h" #include "dart/runtime/include/dart_api.h" #include "mojo/dart/embedder/builtin.h" #include "mojo/dart/embedder/mojo_natives.h" @@ -324,7 +324,7 @@ void Crypto_GetRandomBytes(Dart_NativeArguments args) { intptr_t count = static_cast(count64); scoped_ptr buffer(new uint8_t[count]); - crypto::RandBytes(reinterpret_cast(buffer.get()), count); + base::RandBytes(reinterpret_cast(buffer.get()), count); Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, count); if (Dart_IsError(result)) { diff --git a/mojo/dart/embedder/dart_controller.cc b/mojo/dart/embedder/dart_controller.cc index 256494e98a6b5..6819c69286d90 100644 --- a/mojo/dart/embedder/dart_controller.cc +++ b/mojo/dart/embedder/dart_controller.cc @@ -6,8 +6,8 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/path_service.h" +#include "base/rand_util.h" #include "base/sys_info.h" -#include "crypto/random.h" #include "dart/runtime/include/dart_api.h" #include "dart/runtime/include/dart_native_api.h" #include "mojo/dart/embedder/builtin.h" @@ -658,7 +658,7 @@ bool DartController::RunSingleDartScript(const DartControllerConfig& config) { } static bool generateEntropy(uint8_t* buffer, intptr_t length) { - crypto::RandBytes(reinterpret_cast(buffer), length); + base::RandBytes(reinterpret_cast(buffer), length); return true; } diff --git a/mojo/dart/embedder/test/BUILD.gn b/mojo/dart/embedder/test/BUILD.gn index 4a1c11bf78b6e..87395a3e30935 100644 --- a/mojo/dart/embedder/test/BUILD.gn +++ b/mojo/dart/embedder/test/BUILD.gn @@ -27,7 +27,6 @@ test("dart_unittests") { ":dart_controller_for_test", ":dart_to_cpp_unittests", "//base", - "//crypto:crypto", "//mojo/dart/embedder:dart_controller_no_snapshot", "//mojo/edk/test:run_all_unittests", "//mojo/edk/test:test_support", @@ -48,7 +47,6 @@ source_set("dart_to_cpp_unittests") { ":dart_controller_for_test", ":dart_to_cpp_bindings", "//base", - "//crypto", "//mojo/dart/embedder:dart_controller_no_snapshot", "//mojo/edk/test:test_support", "//mojo/public/cpp/bindings", diff --git a/mojo/dart/embedder/test/dart_to_cpp_tests.cc b/mojo/dart/embedder/test/dart_to_cpp_tests.cc index 9148e283dd298..9abc7a349dff0 100644 --- a/mojo/dart/embedder/test/dart_to_cpp_tests.cc +++ b/mojo/dart/embedder/test/dart_to_cpp_tests.cc @@ -9,10 +9,10 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/path_service.h" +#include "base/rand_util.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread.h" -#include "crypto/random.h" #include "mojo/dart/embedder/dart_controller.h" #include "mojo/dart/embedder/test/dart_to_cpp.mojom.h" #include "mojo/edk/test/test_utils.h" @@ -277,7 +277,7 @@ class DartToCppTest : public testing::Test { } static bool GenerateEntropy(uint8_t* buffer, intptr_t length) { - crypto::RandBytes(reinterpret_cast(buffer), length); + base::RandBytes(reinterpret_cast(buffer), length); return true; } diff --git a/mojo/dart/embedder/test/run_dart_tests.cc b/mojo/dart/embedder/test/run_dart_tests.cc index 06bb77bee9a51..3b026000aa7ae 100644 --- a/mojo/dart/embedder/test/run_dart_tests.cc +++ b/mojo/dart/embedder/test/run_dart_tests.cc @@ -7,7 +7,7 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/path_service.h" -#include "crypto/random.h" +#include "base/rand_util.h" #include "mojo/dart/embedder/dart_controller.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/environment/environment.h" @@ -20,7 +20,7 @@ namespace dart { namespace { static bool generateEntropy(uint8_t* buffer, intptr_t length) { - crypto::RandBytes(reinterpret_cast(buffer), length); + base::RandBytes(reinterpret_cast(buffer), length); return true; } diff --git a/mojo/dart/embedder/test/validation_unittest.cc b/mojo/dart/embedder/test/validation_unittest.cc index bf5b87c929a6c..15132583bf1e5 100644 --- a/mojo/dart/embedder/test/validation_unittest.cc +++ b/mojo/dart/embedder/test/validation_unittest.cc @@ -13,7 +13,7 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/path_service.h" -#include "crypto/random.h" +#include "base/rand_util.h" #include "mojo/dart/embedder/dart_controller.h" #include "testing/gtest/include/gtest/gtest.h" @@ -36,7 +36,7 @@ std::string GetPath() { } static bool generateEntropy(uint8_t* buffer, intptr_t length) { - crypto::RandBytes(reinterpret_cast(buffer), length); + base::RandBytes(reinterpret_cast(buffer), length); return true; } diff --git a/mojo/devtools/common/android_gdb/session.py b/mojo/devtools/common/android_gdb/session.py index 7a6c335073315..e6b9b994f3cee 100644 --- a/mojo/devtools/common/android_gdb/session.py +++ b/mojo/devtools/common/android_gdb/session.py @@ -25,6 +25,7 @@ import sys import tempfile import traceback +import urllib2 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import android_gdb.config as config @@ -128,13 +129,29 @@ def _associate_symbols(self, mapping, local_file): text_address = mapping[0].start + s['sh_offset'] _gdb_execute("add-symbol-file %s 0x%x" % (local_file, text_address)) - def _download_file(self, remote): - """Downloads a remote file through GDB connection. + def _download_file(self, signature, remote): + """Downloads a remote file either from the cloud or through GDB connection. Returns: The filename of the downloaded file """ temp_file = tempfile.NamedTemporaryFile() + logging.info("Trying to download symbols from the cloud.") + symbols_url = "http://storage.googleapis.com/mojo/symbols/%s" % signature + try: + symbol_file = urllib2.urlopen(symbols_url) + try: + with open(temp_file.name, "w") as dst: + shutil.copyfileobj(symbol_file, dst) + logging.info("Getting symbols for %s at %s." % (remote, symbols_url)) + # This allows the deletion of temporary files on disk when the + # debugging session terminates. + self._downloaded_files.append(temp_file) + return temp_file.name + finally: + symbol_file.close() + except urllib2.HTTPError: + pass logging.info("Downloading file %s" % remote) _gdb_execute("remote get %s %s" % (remote, temp_file.name)) # This allows the deletion of temporary files on disk when the debugging @@ -142,9 +159,6 @@ def _download_file(self, remote): self._downloaded_files.append(temp_file) return temp_file.name - def _download_and_associate_symbol(self, mapping): - self._associate_symbols(mapping, self._download_file(mapping[0].filename)) - def _find_mapping_for_address(self, mappings, address): """Returns the list of all mappings of the file occupying the |address| memory address. @@ -166,11 +180,11 @@ def _try_to_map(self, mapping): if signature in self._libraries: self._associate_symbols(mapping, self._libraries[signature]) else: - # This library file is not known locally. Download it from the device - # and put it in cache so, if it got symbols, we can see them. + # This library file is not known locally. Download it from the device or + # the cloud and put it in cache so, if it got symbols, we can see them. local_file = os.path.join(self._remote_file_cache, signature) if not os.path.exists(local_file): - tmp_output = self._download_file(remote_file) + tmp_output = self._download_file(signature, remote_file) shutil.move(tmp_output, local_file) self._associate_symbols(mapping, local_file) return True diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn index c3e0d538be9bc..b3144f099b019 100644 --- a/mojo/edk/embedder/BUILD.gn +++ b/mojo/edk/embedder/BUILD.gn @@ -87,7 +87,6 @@ mojo_edk_source_set("platform") { deps = [ "//base", - "//crypto", ] if (is_android) { diff --git a/mojo/edk/embedder/simple_platform_support.cc b/mojo/edk/embedder/simple_platform_support.cc index 5024087075956..4207120fc7b91 100644 --- a/mojo/edk/embedder/simple_platform_support.cc +++ b/mojo/edk/embedder/simple_platform_support.cc @@ -4,7 +4,7 @@ #include "mojo/edk/embedder/simple_platform_support.h" -#include "crypto/random.h" +#include "base/rand_util.h" #include "mojo/edk/embedder/simple_platform_shared_buffer.h" namespace mojo { @@ -12,7 +12,7 @@ namespace embedder { void SimplePlatformSupport::GetCryptoRandomBytes(void* bytes, size_t num_bytes) { - crypto::RandBytes(bytes, num_bytes); + base::RandBytes(bytes, num_bytes); } PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBuffer( diff --git a/mojo/tools/upload_binaries.py b/mojo/tools/upload_binaries.py index c5ecf922fdf0f..7ae73f12b3a5f 100755 --- a/mojo/tools/upload_binaries.py +++ b/mojo/tools/upload_binaries.py @@ -133,50 +133,6 @@ def upload_shell(config, dry_run, verbose): write_file_to_gs(version, latest_file, config, dry_run) -def upload_sky_shell_linux(config, dry_run, verbose, dest_prefix): - paths = Paths(config) - dest = '%(prefix)s/sky_shell.zip' % { 'prefix': dest_prefix } - with tempfile.NamedTemporaryFile() as zip_file: - with zipfile.ZipFile(zip_file, 'w') as z: - shell_path = paths.target_sky_shell_path - shell_filename = os.path.basename(shell_path) - if verbose: - print 'zipping %s' % shell_path - z.write(shell_path, shell_filename, zipfile.ZIP_DEFLATED) - icu_filename = 'icudtl.dat' - icu_path = os.path.join(os.path.dirname(shell_path), icu_filename) - if verbose: - print 'zipping %s' % icu_path - z.write(icu_path, icu_filename, zipfile.ZIP_DEFLATED) - upload(config, zip_file.name, dest, dry_run) - - -def upload_sky_shell_android(config, dry_run, _, dest_prefix): - paths = Paths(config) - shell_path = paths.target_sky_shell_path - shell_filename = os.path.basename(shell_path) - dest = '%(prefix)s/%(filename)s' % { - 'prefix': dest_prefix, - 'filename': shell_filename, - } - upload(config, shell_path, dest, dry_run) - - -def upload_sky_shell(config, dry_run, verbose): - target_name = target(config) - version = Version().version - template_data = { 'target': target_name, 'version': version } - dest_prefix = 'gs://mojo/sky/shell/%(target)s/%(version)s' % template_data - latest_file = 'gs://mojo/sky/shell/%(target)s/LATEST' % template_data - if config.target_os == Config.OS_LINUX: - upload_sky_shell_linux(config, dry_run, verbose, dest_prefix) - elif config.target_os == Config.OS_ANDROID: - upload_sky_shell_android(config, dry_run, verbose, dest_prefix) - else: - return - write_file_to_gs(version, latest_file, config, dry_run) - - def upload_app(app_binary_path, config, dry_run): app_binary_name = os.path.basename(app_binary_path) version = Version().version @@ -231,7 +187,6 @@ def main(): is_official_build=is_official_build) upload_shell(config, args.dry_run, args.verbose) - upload_sky_shell(config, args.dry_run, args.verbose) if is_official_build: print "Skipping uploading apps (official apk build)." diff --git a/services/android/BUILD.gn b/services/android/BUILD.gn deleted file mode 100644 index 6753600b854a6..0000000000000 --- a/services/android/BUILD.gn +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2014 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. - -import("//build/config/android/rules.gni") -import("//mojo/public/mojo_application.gni") - -mojo_android_application("java_handler") { - sources = [ - "java_handler.cc", - ] - - deps = [ - "//base", - "//mojo/android:libsystem_java", - "//mojo/android:system_java_jni_headers", - "//mojo/application", - "//mojo/application:content_handler", - "//mojo/common:tracing_impl", - "//mojo/environment:chromium", - "//mojo/public/c/system:for_shared_library", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/services/content_handler/public/interfaces", - "//mojo/services/url_response_disk_cache/public/interfaces", - ] - - java_sources = [ "java/src/org/chromium/services/android/JavaHandler.java" ] - - java_deps = [ - "//base:base_java", - "//mojo/android:system_java", - "//mojo/public/java:system", - ] - - jni_package = "mojo" -} diff --git a/services/android/java/src/org/chromium/services/android/JavaHandler.java b/services/android/java/src/org/chromium/services/android/JavaHandler.java deleted file mode 100644 index 401762a750f94..0000000000000 --- a/services/android/java/src/org/chromium/services/android/JavaHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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. - -package org.chromium.services.android; - -import android.content.Context; -import android.util.Log; - -import dalvik.system.DexClassLoader; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.jar.JarFile; -import java.util.jar.Manifest; - -/** - * Content handler for Android Java code. - */ -@JNINamespace("services::android") -public class JavaHandler { - private static final String TAG = "JavaHandler"; - - /** - * Extracts and runs the application libraries contained by the indicated archive. - * - * @param context the application context - * @param archivePath the path of the archive containing the application to be run - * @param cachePath the path to a directory that can be used to save cached data. - * @param applicationRequestHandle handle to the shell to be passed to the native application. - * On the Java side this is opaque payload. - */ - @CalledByNative - private static boolean bootstrap(Context context, String archivePath, - String cachePath, int applicationRequestHandle) { - File application_java_library = new File(archivePath); - - String dexPath = application_java_library.getAbsolutePath(); - DexClassLoader bootstrapLoader = new DexClassLoader(dexPath, - cachePath, null, JavaHandler.class.getClassLoader()); - - // The starting Mojo class is a class implementing a static MojoMain method. Its name is - // defined in the .jar manifest file, like a .jar defines a Main-Class attribute for the - // starting point of a standalone java application. - String mojoClass; - try (JarFile jar = new JarFile(application_java_library)) { - Manifest manifest = jar.getManifest(); - mojoClass = manifest.getMainAttributes().getValue("Mojo-Class"); - } catch (IOException e) { - Log.e(TAG, "Unable to extract Manifest attributes", e); - return false; - } - - if (mojoClass == null) { - Log.e(TAG, "Mojo-Class class not found"); - return false; - } - - Core core = CoreImpl.getInstance(); - try (MessagePipeHandle handle = core.acquireNativeHandle( - applicationRequestHandle).toMessagePipeHandle()) { - Class loadedClass = bootstrapLoader.loadClass(mojoClass); - Method mojoMain = - loadedClass.getMethod("mojoMain", Context.class, Core.class, - MessagePipeHandle.class); - nativePreInvokeEvent(); - mojoMain.invoke(null, context, core, handle); - } catch (Throwable t) { - Log.e(TAG, "Running MojoMain failed.", t); - return false; - } - return true; - } - - /** - * Notify the native side before starting the handled application for tracing. - */ - private static native void nativePreInvokeEvent(); -} diff --git a/services/android/java_handler.cc b/services/android/java_handler.cc deleted file mode 100644 index 257a0b9475b08..0000000000000 --- a/services/android/java_handler.cc +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2014 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 "services/android/java_handler.h" - -#include "base/android/base_jni_onload.h" -#include "base/android/base_jni_registrar.h" -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/library_loader/library_loader_hooks.h" -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/run_loop.h" -#include "base/scoped_native_library.h" -#include "base/trace_event/trace_event.h" -#include "jni/JavaHandler_jni.h" -#include "mojo/android/system/base_run_loop.h" -#include "mojo/android/system/core_impl.h" -#include "mojo/application/application_runner_chromium.h" -#include "mojo/application/content_handler_factory.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_impl.h" - -using base::android::AttachCurrentThread; -using base::android::ScopedJavaLocalRef; -using base::android::ConvertJavaStringToUTF8; -using base::android::ConvertUTF8ToJavaString; -using base::android::GetApplicationContext; - -namespace { - -bool RegisterJNI(JNIEnv* env) { - if (!base::android::RegisterJni(env)) - return false; - - if (!services::android::RegisterNativesImpl(env)) - return false; - - if (!mojo::android::RegisterCoreImpl(env)) - return false; - - if (!mojo::android::RegisterBaseRunLoop(env)) - return false; - - return true; -} - -} // namespace - -namespace services { -namespace android { - -JavaHandler::JavaHandler() : content_handler_factory_(this) { -} - -JavaHandler::~JavaHandler() { -} - -void JavaHandler::RunApplication( - mojo::InterfaceRequest application_request, - mojo::URLResponsePtr response) { - TRACE_EVENT_BEGIN1("java_handler", "JavaHandler::RunApplication", "url", - std::string(response->url)); - JNIEnv* env = base::android::AttachCurrentThread(); - base::FilePath archive_path; - base::FilePath cache_dir; - { - base::MessageLoop loop; - handler_task_runner_->PostTask( - FROM_HERE, - base::Bind(&JavaHandler::GetApplication, base::Unretained(this), - base::Unretained(&archive_path), - base::Unretained(&cache_dir), base::Passed(response.Pass()), - base::Bind(base::IgnoreResult( - &base::SingleThreadTaskRunner::PostTask), - loop.task_runner(), FROM_HERE, - base::MessageLoop::QuitWhenIdleClosure()))); - base::RunLoop().Run(); - } - - - jobject context = base::android::GetApplicationContext(); - ScopedJavaLocalRef j_archive_path = - ConvertUTF8ToJavaString(env, archive_path.value()); - ScopedJavaLocalRef j_cache_dir = - ConvertUTF8ToJavaString(env, cache_dir.value()); - Java_JavaHandler_bootstrap( - env, context, j_archive_path.obj(), j_cache_dir.obj(), - application_request.PassMessagePipe().release().value()); -} - -void JavaHandler::Initialize(mojo::ApplicationImpl* app) { - tracing_.Initialize(app); - handler_task_runner_ = base::MessageLoop::current()->task_runner(); - app->ConnectToService("mojo:url_response_disk_cache", - &url_response_disk_cache_); -} - -void JavaHandler::GetApplication(base::FilePath* archive_path, - base::FilePath* cache_dir, - mojo::URLResponsePtr response, - const base::Closure& callback) { - url_response_disk_cache_->GetFile( - response.Pass(), - [archive_path, cache_dir, callback](mojo::Array extracted_path, - mojo::Array cache_path) { - if (extracted_path.is_null()) { - *archive_path = base::FilePath(); - *cache_dir = base::FilePath(); - } else { - *archive_path = base::FilePath( - std::string(reinterpret_cast(&extracted_path.front()), - extracted_path.size())); - *cache_dir = base::FilePath(std::string( - reinterpret_cast(&cache_path.front()), cache_path.size())); - } - callback.Run(); - }); -} - -bool JavaHandler::ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) { - connection->AddService(&content_handler_factory_); - return true; -} - -void PreInvokeEvent(JNIEnv* env, jclass jcaller) { - TRACE_EVENT_END0("java_handler", "JavaHandler::RunApplication"); -} - -} // namespace android -} // namespace services - -MojoResult MojoMain(MojoHandle application_request) { - mojo::ApplicationRunnerChromium runner(new services::android::JavaHandler()); - return runner.Run(application_request); -} - -JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - std::vector register_callbacks; - register_callbacks.push_back(base::Bind(&RegisterJNI)); - if (!base::android::OnJNIOnLoadRegisterJNI(vm, register_callbacks) || - !base::android::OnJNIOnLoadInit( - std::vector())) { - return -1; - } - - // There cannot be two AtExit objects triggering at the same time. Remove the - // one from LibraryLoader as ApplicationRunnerChromium also uses one. - base::android::LibraryLoaderExitHook(); - - return JNI_VERSION_1_4; -} - -// This is needed because the application needs to access the application -// context. -extern "C" JNI_EXPORT void InitApplicationContext( - const base::android::JavaRef& context) { - JNIEnv* env = base::android::AttachCurrentThread(); - base::android::InitApplicationContext(env, context); -} - diff --git a/services/android/java_handler.h b/services/android/java_handler.h deleted file mode 100644 index efaa4a2274cbe..0000000000000 --- a/services/android/java_handler.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2014 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 SERVICES_ANDROID_JAVA_HANDLER_H_ -#define SERVICES_ANDROID_JAVA_HANDLER_H_ - -#include - -#include "base/files/file_path.h" -#include "base/single_thread_task_runner.h" -#include "mojo/application/content_handler_factory.h" -#include "mojo/common/tracing_impl.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/interface_factory_impl.h" -#include "mojo/services/content_handler/public/interfaces/content_handler.mojom.h" -#include "mojo/services/url_response_disk_cache/public/interfaces/url_response_disk_cache.mojom.h" - -namespace services { -namespace android { - -class JavaHandler : public mojo::ApplicationDelegate, - public mojo::ContentHandlerFactory::Delegate { - public: - JavaHandler(); - ~JavaHandler(); - - private: - // ApplicationDelegate: - void Initialize(mojo::ApplicationImpl* app) override; - bool ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) override; - - // ContentHandlerFactory::Delegate: - void RunApplication( - mojo::InterfaceRequest application_request, - mojo::URLResponsePtr response) override; - - void GetApplication(base::FilePath* archive_path, - base::FilePath* cache_dir, - mojo::URLResponsePtr response, - const base::Closure& callback); - - mojo::TracingImpl tracing_; - mojo::ContentHandlerFactory content_handler_factory_; - mojo::URLResponseDiskCachePtr url_response_disk_cache_; - scoped_refptr handler_task_runner_; - MOJO_DISALLOW_COPY_AND_ASSIGN(JavaHandler); -}; - -} // namespace android -} // namespace services - -#endif // SERVICES_ANDROID_JAVA_HANDLER_H_ diff --git a/services/sensors/BUILD.gn b/services/sensors/BUILD.gn index bb48911749343..dd38556de83b5 100644 --- a/services/sensors/BUILD.gn +++ b/services/sensors/BUILD.gn @@ -3,8 +3,8 @@ # found in the LICENSE file. if (is_android) { - import("//services/android/rules.gni") import("//build/config/android/config.gni") + import("//mojo/android/rules.gni") mojo_android_java_application("sensors") { sources = [ diff --git a/sky/tools/roll/roll.py b/sky/tools/roll/roll.py index 5389d638b71d8..d72b026fb917f 100755 --- a/sky/tools/roll/roll.py +++ b/sky/tools/roll/roll.py @@ -39,7 +39,6 @@ ] _chromium_libs = [ - 'crypto', 'url', ] @@ -74,8 +73,6 @@ dirs_from_mojo = [ 'gpu', 'mojo', - 'mojom', - 'services/android', 'services/asset_bundle', 'services/keyboard', 'services/sensors', @@ -84,11 +81,9 @@ # The contents of these files before the roll will be preserved after the roll, # even though they live in directories rolled in from Chromium. files_not_to_roll = [ - 'build/config/crypto.gni', 'build/config/ui.gni', 'build/ls.py', 'build/module_args/mojo.gni', - 'crypto/BUILD.gn', 'gpu/BUILD.gn', 'tools/android/download_android_tools.py', 'tools/android/VERSION_LINUX_NDK', diff --git a/sky/tools/roll/roll.py.orig b/sky/tools/roll/roll.py.orig new file mode 100755 index 0000000000000..5389d638b71d8 --- /dev/null +++ b/sky/tools/roll/roll.py.orig @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# 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. + +import argparse +import json +import os +import subprocess +import sys +import urllib2 +from utils import commit +from utils import system +import patch + +# //base and its dependencies +_base_deps = [ + 'base', + 'testing', + 'third_party/ashmem', + 'third_party/libevent', + 'third_party/libxml', # via //base/test + 'third_party/modp_b64', + 'third_party/tcmalloc', +] + +# //build and its dependencies +_build_deps = [ + 'build', + 'third_party/android_testrunner', + 'third_party/binutils', + 'third_party/instrumented_libraries', + 'third_party/pymock', + 'tools/android', + 'tools/clang', + 'tools/generate_library_loader', + 'tools/gritsettings', + 'tools/valgrind', +] + +_chromium_libs = [ + 'crypto', + 'url', +] + +_third_party_deps = [ + 'third_party/android_platform', + 'third_party/apple_apsl', + 'third_party/brotli', + 'third_party/expat', + 'third_party/freetype-android', + 'third_party/harfbuzz-ng', + 'third_party/iccjpeg', + 'third_party/jinja2', + 'third_party/jsr-305', + 'third_party/junit', + 'third_party/khronos', + 'third_party/libjpeg', + 'third_party/libpng', + 'third_party/libXNVCtrl', + 'third_party/markupsafe', + 'third_party/mesa', + 'third_party/mockito', + 'third_party/ots', + 'third_party/ply', + 'third_party/qcms', + 'third_party/re2', + 'third_party/robolectric', + 'third_party/zlib', +] + +dirs_from_chromium = _base_deps + _build_deps + _chromium_libs + _third_party_deps + +dirs_from_mojo = [ + 'gpu', + 'mojo', + 'mojom', + 'services/android', + 'services/asset_bundle', + 'services/keyboard', + 'services/sensors', +] + +# The contents of these files before the roll will be preserved after the roll, +# even though they live in directories rolled in from Chromium. +files_not_to_roll = [ + 'build/config/crypto.gni', + 'build/config/ui.gni', + 'build/ls.py', + 'build/module_args/mojo.gni', + 'crypto/BUILD.gn', + 'gpu/BUILD.gn', + 'tools/android/download_android_tools.py', + 'tools/android/VERSION_LINUX_NDK', + 'tools/android/VERSION_LINUX_SDK', + 'tools/android/VERSION_MACOSX_NDK', + 'tools/android/VERSION_MACOSX_SDK', +] + + +def rev(source_dir, dest_dir, dirs_to_rev, name): + for d in dirs_to_rev: + print "removing directory %s" % d + try: + system(["git", "rm", "-r", d], cwd=dest_dir) + except subprocess.CalledProcessError: + print "Could not remove %s" % d + print "cloning directory %s" % d + files = system(["git", "ls-files", d], cwd=source_dir) + for f in files.splitlines(): + source_path = os.path.join(source_dir, f) + if not os.path.isfile(source_path): + continue + dest_path = os.path.join(dest_dir, f) + system(["mkdir", "-p", os.path.dirname(dest_path)], cwd=source_dir) + system(["cp", source_path, dest_path], cwd=source_dir) + system(["git", "add", d], cwd=dest_dir) + + for f in files_not_to_roll: + system(["git", "checkout", "HEAD", f], cwd=dest_dir) + + system(["git", "add", "."], cwd=dest_dir) + src_commit = system(["git", "rev-parse", "HEAD"], cwd=source_dir).strip() + commit("Update to %s %s" % (name, src_commit), cwd=dest_dir) + + +def main(): + parser = argparse.ArgumentParser(description="Update the mojo repo's " + + "snapshot of things imported from chromium.") + parser.add_argument("--mojo-dir", type=str) + parser.add_argument("--chromium-dir", type=str) + parser.add_argument("--dest-dir", type=str) + + args = parser.parse_args() + + if args.mojo_dir: + rev(args.mojo_dir, args.dest_dir, dirs_from_mojo, 'mojo') + + if args.chromium_dir: + rev(args.chromium_dir, args.dest_dir, dirs_from_chromium, 'chromium') + + try: + patch.patch_and_filter(args.dest_dir) + except subprocess.CalledProcessError: + print "ERROR: Roll failed due to a patch not applying" + print "Fix the patch to apply, commit the result, and re-run this script" + return 1 + + return 0 + + +if __name__ == "__main__": + sys.exit(main())