bug 853682 - rm ipc/chromium/src/base/crypto/ which wasn't being built r=bsmedberg

This commit is contained in:
Trevor Saunders 2013-03-19 17:57:22 -04:00
parent e86dade785
commit f8e3dfe70b
7 changed files with 0 additions and 867 deletions

View File

@ -1,72 +0,0 @@
// Copyright (c) 2009 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/crypto/cssm_init.h"
#include <Security/cssm.h>
#include "base/logging.h"
#include "base/singleton.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 {
class CSSMInitSingleton {
public:
CSSMInitSingleton() : inited_(false), loaded_(false) {
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;
}
loaded_ = true;
}
~CSSMInitSingleton() {
CSSM_RETURN crtn;
if (loaded_) {
crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL);
DCHECK(crtn == CSSM_OK);
}
if (inited_) {
crtn = CSSM_Terminate();
DCHECK(crtn == CSSM_OK);
}
}
private:
bool inited_; // True if CSSM_Init has been called successfully.
bool loaded_; // True if CSSM_ModuleLoad has been called successfully.
};
} // namespace
namespace base {
void EnsureCSSMInit() {
Singleton<CSSMInitSingleton>::get();
}
} // namespace base

View File

@ -1,17 +0,0 @@
// Copyright (c) 2009 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 BASE_CRYPTO_CSSM_INIT_H_
#define BASE_CRYPTO_CSSM_INIT_H_
namespace base {
// 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.
void EnsureCSSMInit();
} // namespace base
#endif // BASE_CRYPTO_CSSM_INIT_H_

View File

@ -1,105 +0,0 @@
// Copyright (c) 2009 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 BASE_CRYPTO_SIGNATURE_VERIFIER_H_
#define BASE_CRYPTO_SIGNATURE_VERIFIER_H_
#include "build/build_config.h"
#if defined(OS_LINUX)
#include <cryptoht.h>
#elif defined(OS_MACOSX)
#include <Security/cssm.h>
#elif defined(OS_WIN)
#include <windows.h>
#include <wincrypt.h>
#endif
#include <vector>
#include "base/basictypes.h"
namespace base {
// The SignatureVerifier class verifies a signature using a bare public key
// (as opposed to a certificate).
class SignatureVerifier {
public:
SignatureVerifier();
~SignatureVerifier();
// Streaming interface:
// Initiates a signature verification operation. This should be followed
// by one or more VerifyUpdate calls and a VerifyFinal call.
//
// 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 signatures is actually a big integer. It must be in the
// 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_t* signature_algorithm,
int signature_algorithm_len,
const uint8_t* signature,
int signature_len,
const uint8_t* public_key_info,
int public_key_info_len);
// Feeds a piece of the data to the signature verifier.
void VerifyUpdate(const uint8_t* 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_t* data,
// int data_len,
// const uint8_t* signature_algorithm,
// int signature_algorithm_len,
// const uint8_t* signature,
// int signature_len,
// const uint8_t* public_key_info,
// int public_key_info_len);
private:
void Reset();
std::vector<uint8_t> signature_;
#if defined(OS_LINUX)
VFYContext* vfy_context_;
#elif defined(OS_MACOSX)
std::vector<uint8_t> public_key_info_;
CSSM_CSP_HANDLE csp_handle_;
CSSM_CC_HANDLE sig_handle_;
CSSM_KEY public_key_;
#elif defined(OS_WIN)
HCRYPTPROV provider_;
HCRYPTHASH hash_object_;
HCRYPTKEY public_key_;
#endif
};
} // namespace base
#endif // BASE_CRYPTO_SIGNATURE_VERIFIER_H_

View File

@ -1,143 +0,0 @@
// Copyright (c) 2009 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/crypto/signature_verifier.h"
#include <stdlib.h>
#include "base/crypto/cssm_init.h"
#include "base/logging.h"
namespace {
void* AppMalloc(CSSM_SIZE size, void *alloc_ref) {
return malloc(size);
}
void AppFree(void* mem_ptr, void* alloc_ref) {
free(mem_ptr);
}
void* AppRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) {
return realloc(ptr, size);
}
void* AppCalloc(uint32_t num, CSSM_SIZE size, void* alloc_ref) {
return calloc(num, size);
}
const CSSM_API_MEMORY_FUNCS mem_funcs = {
AppMalloc,
AppFree,
AppRealloc,
AppCalloc,
NULL
};
} // namespace
namespace base {
SignatureVerifier::SignatureVerifier() : csp_handle_(0), sig_handle_(0) {
EnsureCSSMInit();
static CSSM_VERSION version = {2, 0};
CSSM_RETURN crtn;
crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &mem_funcs, 0,
CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &csp_handle_);
DCHECK(crtn == CSSM_OK);
}
SignatureVerifier::~SignatureVerifier() {
Reset();
if (csp_handle_) {
CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_);
DCHECK(crtn == CSSM_OK);
}
}
bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm,
int signature_algorithm_len,
const uint8_t* signature,
int signature_len,
const uint8_t* public_key_info,
int public_key_info_len) {
signature_.assign(signature, signature + signature_len);
public_key_info_.assign(public_key_info,
public_key_info + public_key_info_len);
CSSM_ALGORITHMS key_alg = CSSM_ALGID_RSA; // TODO(wtc): hardcoded.
memset(&public_key_, 0, sizeof(public_key_));
public_key_.KeyData.Data = const_cast<uint8_t*>(&public_key_info_[0]);
public_key_.KeyData.Length = public_key_info_.size();
public_key_.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
public_key_.KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
public_key_.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_X509;
public_key_.KeyHeader.AlgorithmId = key_alg;
public_key_.KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
public_key_.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
public_key_.KeyHeader.KeyUsage = CSSM_KEYUSE_VERIFY;
CSSM_KEY_SIZE key_size;
CSSM_RETURN crtn;
crtn = CSSM_QueryKeySizeInBits(csp_handle_, NULL, &public_key_, &key_size);
if (crtn) {
NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn;
return false;
}
public_key_.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
// TODO(wtc): decode signature_algorithm...
CSSM_ALGORITHMS sig_alg = CSSM_ALGID_SHA1WithRSA;
crtn = CSSM_CSP_CreateSignatureContext(csp_handle_, sig_alg, NULL,
&public_key_, &sig_handle_);
if (crtn) {
NOTREACHED();
return false;
}
crtn = CSSM_VerifyDataInit(sig_handle_);
if (crtn) {
NOTREACHED();
return false;
}
return true;
}
void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
int data_part_len) {
CSSM_DATA data;
data.Data = const_cast<uint8_t*>(data_part);
data.Length = data_part_len;
CSSM_RETURN crtn = CSSM_VerifyDataUpdate(sig_handle_, &data, 1);
DCHECK(crtn == CSSM_OK);
}
bool SignatureVerifier::VerifyFinal() {
CSSM_DATA sig;
sig.Data = const_cast<uint8_t*>(&signature_[0]);
sig.Length = signature_.size();
CSSM_RETURN crtn = CSSM_VerifyDataFinal(sig_handle_, &sig);
Reset();
// crtn is CSSMERR_CSP_VERIFY_FAILED if signature verification fails.
return (crtn == CSSM_OK);
}
void SignatureVerifier::Reset() {
CSSM_RETURN crtn;
if (sig_handle_) {
crtn = CSSM_DeleteContext(sig_handle_);
DCHECK(crtn == CSSM_OK);
sig_handle_ = 0;
}
signature_.clear();
// Can't call CSSM_FreeKey on public_key_ because we constructed
// public_key_ manually.
}
} // namespace base

View File

@ -1,114 +0,0 @@
// Copyright (c) 2009 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/crypto/signature_verifier.h"
#include <cryptohi.h>
#include <keyhi.h>
#include <stdlib.h>
#include "base/logging.h"
#include "base/nss_init.h"
namespace base {
SignatureVerifier::SignatureVerifier() : vfy_context_(NULL) {
EnsureNSSInit();
}
SignatureVerifier::~SignatureVerifier() {
Reset();
}
bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm,
int signature_algorithm_len,
const uint8_t* signature,
int signature_len,
const uint8_t* public_key_info,
int public_key_info_len) {
signature_.assign(signature, signature + signature_len);
CERTSubjectPublicKeyInfo* spki = NULL;
SECItem spki_der;
spki_der.type = siBuffer;
spki_der.data = const_cast<uint8_t*>(public_key_info);
spki_der.len = public_key_info_len;
spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
if (!spki)
return false;
SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki.
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<uint8_t*>(signature_algorithm);
sig_alg_der.len = signature_algorithm_len;
SECAlgorithmID sig_alg_id;
SECStatus rv;
rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, 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<uint8_t*>(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;
}
void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
int data_part_len) {
SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
DCHECK(rv == SECSuccess);
}
bool SignatureVerifier::VerifyFinal() {
SECStatus rv = VFY_End(vfy_context_);
Reset();
// If signature verification fails, the error code is
// SEC_ERROR_BAD_SIGNATURE (-8182).
return (rv == SECSuccess);
}
void SignatureVerifier::Reset() {
if (vfy_context_) {
VFY_DestroyContext(vfy_context_, PR_TRUE);
vfy_context_ = NULL;
}
signature_.clear();
}
} // namespace base

View File

@ -1,268 +0,0 @@
// Copyright (c) 2009 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/crypto/signature_verifier.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_t 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_t 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_t 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_t 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.
base::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_t 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();
// Purify disables digital signature verification, causing the Windows
// CryptoAPI function CryptVerifySignature to always succeed. So we can't
// check the signature verification results of the negative tests when
// running inside Purify. See http://crbug.com/10031.
#ifndef PURIFY
EXPECT_FALSE(ok);
#endif
// Test 4: verify a bad signature.
uint8_t 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();
#ifndef PURIFY
EXPECT_FALSE(ok);
#endif
}
}

View File

@ -1,148 +0,0 @@
// Copyright (c) 2009 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/crypto/signature_verifier.h"
#include "base/logging.h"
#pragma comment(lib, "crypt32.lib")
namespace {
// Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the
// WINAPI calling convention.
void* WINAPI MyCryptAlloc(size_t size) {
return malloc(size);
}
void WINAPI MyCryptFree(void* p) {
free(p);
}
} // namespace
namespace base {
SignatureVerifier::SignatureVerifier() : hash_object_(0), public_key_(0) {
if (!CryptAcquireContext(&provider_, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
provider_ = 0;
}
SignatureVerifier::~SignatureVerifier() {
Reset();
if (provider_) {
BOOL ok = CryptReleaseContext(provider_, 0);
DCHECK(ok);
}
}
bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm,
int signature_algorithm_len,
const uint8_t* signature,
int signature_len,
const uint8_t* public_key_info,
int public_key_info_len) {
signature_.reserve(signature_len);
// CryptoAPI uses big integers in the little-endian byte order, so we need
// to first swap the order of signature bytes.
for (int i = signature_len - 1; i >= 0; --i)
signature_.push_back(signature[i]);
CRYPT_DECODE_PARA decode_para;
decode_para.cbSize = sizeof(decode_para);
decode_para.pfnAlloc = MyCryptAlloc;
decode_para.pfnFree = MyCryptFree;
CERT_PUBLIC_KEY_INFO* cert_public_key_info = NULL;
DWORD struct_len = 0;
BOOL ok;
ok = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
public_key_info,
public_key_info_len,
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
&decode_para,
&cert_public_key_info,
&struct_len);
if (!ok)
return false;
ok = CryptImportPublicKeyInfo(provider_,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
cert_public_key_info, &public_key_);
free(cert_public_key_info);
if (!ok)
return false;
CRYPT_ALGORITHM_IDENTIFIER* signature_algorithm_id;
struct_len = 0;
ok = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_ALGORITHM_IDENTIFIER,
signature_algorithm,
signature_algorithm_len,
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
&decode_para,
&signature_algorithm_id,
&struct_len);
DCHECK(ok || GetLastError() == ERROR_FILE_NOT_FOUND);
ALG_ID hash_alg_id;
if (ok) {
hash_alg_id = CALG_MD4; // Initialize to a weak hash algorithm that we
// don't support.
if (!strcmp(signature_algorithm_id->pszObjId, szOID_RSA_SHA1RSA))
hash_alg_id = CALG_SHA1;
else if (!strcmp(signature_algorithm_id->pszObjId, szOID_RSA_MD5RSA))
hash_alg_id = CALG_MD5;
free(signature_algorithm_id);
DCHECK(hash_alg_id != CALG_MD4);
if (hash_alg_id == CALG_MD4)
return false; // Unsupported hash algorithm.
} else if (GetLastError() == ERROR_FILE_NOT_FOUND) {
// TODO(wtc): X509_ALGORITHM_IDENTIFIER isn't supported on XP SP2. We
// may be able to encapsulate signature_algorithm in a dummy SignedContent
// and decode it with X509_CERT into a CERT_SIGNED_CONTENT_INFO. For now,
// just hardcode the hash algorithm to be SHA-1.
hash_alg_id = CALG_SHA1;
} else {
return false;
}
ok = CryptCreateHash(provider_, hash_alg_id, 0, 0, &hash_object_);
if (!ok)
return false;
return true;
}
void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
int data_part_len) {
BOOL ok = CryptHashData(hash_object_, data_part, data_part_len, 0);
DCHECK(ok) << "CryptHashData failed: " << GetLastError();
}
bool SignatureVerifier::VerifyFinal() {
BOOL ok = CryptVerifySignature(hash_object_, &signature_[0],
signature_.size(), public_key_, NULL, 0);
Reset();
if (!ok)
return false;
return true;
}
void SignatureVerifier::Reset() {
BOOL ok;
if (hash_object_) {
ok = CryptDestroyHash(hash_object_);
DCHECK(ok);
hash_object_ = 0;
}
if (public_key_) {
ok = CryptDestroyKey(public_key_);
DCHECK(ok);
public_key_ = 0;
}
signature_.clear();
}
} // namespace base