mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
bug 853682 - rm ipc/chromium/src/base/crypto/ which wasn't being built r=bsmedberg
This commit is contained in:
parent
c9251e6420
commit
1bee6a8a3c
@ -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
|
@ -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_
|
@ -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_
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user