mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-16 04:07:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
213
modules/libmar/verify/MacVerifyCrypto.cpp
Normal file
213
modules/libmar/verify/MacVerifyCrypto.cpp
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/* 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 <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "cryptox.h"
|
||||
|
||||
// We declare the necessary parts of the Security Transforms API here since
|
||||
// we're building with the 10.6 SDK, which doesn't know about Security
|
||||
// Transforms.
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT");
|
||||
typedef CFTypeRef SecTransformRef;
|
||||
typedef struct OpaqueSecKeyRef* SecKeyRef;
|
||||
|
||||
typedef SecTransformRef (*SecTransformCreateReadTransformWithReadStreamFunc)
|
||||
(CFReadStreamRef inputStream);
|
||||
SecTransformCreateReadTransformWithReadStreamFunc
|
||||
SecTransformCreateReadTransformWithReadStreamPtr = NULL;
|
||||
typedef CFTypeRef (*SecTransformExecuteFunc)(SecTransformRef transform,
|
||||
CFErrorRef* error);
|
||||
SecTransformExecuteFunc SecTransformExecutePtr = NULL;
|
||||
typedef SecTransformRef (*SecVerifyTransformCreateFunc)(SecKeyRef key,
|
||||
CFDataRef signature,
|
||||
CFErrorRef* error);
|
||||
SecVerifyTransformCreateFunc SecVerifyTransformCreatePtr = NULL;
|
||||
typedef Boolean (*SecTransformSetAttributeFunc)(SecTransformRef transform,
|
||||
CFStringRef key,
|
||||
CFTypeRef value,
|
||||
CFErrorRef* error);
|
||||
SecTransformSetAttributeFunc SecTransformSetAttributePtr = NULL;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_InitCryptoProvider()
|
||||
{
|
||||
if (!SecTransformCreateReadTransformWithReadStreamPtr) {
|
||||
SecTransformCreateReadTransformWithReadStreamPtr =
|
||||
(SecTransformCreateReadTransformWithReadStreamFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecTransformCreateReadTransformWithReadStream");
|
||||
}
|
||||
if (!SecTransformExecutePtr) {
|
||||
SecTransformExecutePtr = (SecTransformExecuteFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecTransformExecute");
|
||||
}
|
||||
if (!SecVerifyTransformCreatePtr) {
|
||||
SecVerifyTransformCreatePtr = (SecVerifyTransformCreateFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecVerifyTransformCreate");
|
||||
}
|
||||
if (!SecTransformSetAttributePtr) {
|
||||
SecTransformSetAttributePtr = (SecTransformSetAttributeFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecTransformSetAttribute");
|
||||
}
|
||||
if (!SecTransformCreateReadTransformWithReadStreamPtr ||
|
||||
!SecTransformExecutePtr ||
|
||||
!SecVerifyTransformCreatePtr ||
|
||||
!SecTransformSetAttributePtr) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData)
|
||||
{
|
||||
if (!aInputData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
void* inputData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
if (!inputData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
*aInputData = inputData;
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData, void* aBuf,
|
||||
unsigned int aLen)
|
||||
{
|
||||
if (aLen == 0) {
|
||||
return CryptoX_Success;
|
||||
}
|
||||
if (!aInputData || !*aInputData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
CFMutableDataRef inputData = (CFMutableDataRef)*aInputData;
|
||||
|
||||
CFDataAppendBytes(inputData, (const uint8*)aBuf, aLen);
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_LoadPublicKey(const unsigned char* aCertData,
|
||||
unsigned int aDataSize,
|
||||
CryptoX_PublicKey* aPublicKey)
|
||||
{
|
||||
if (!aCertData || aDataSize == 0 || !aPublicKey) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
*aPublicKey = NULL;
|
||||
CFDataRef certData = CFDataCreate(kCFAllocatorDefault,
|
||||
aCertData,
|
||||
aDataSize);
|
||||
if (!certData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
|
||||
certData);
|
||||
CFRelease(certData);
|
||||
if (!cert) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
OSStatus status = SecCertificateCopyPublicKey(cert,
|
||||
(SecKeyRef*)aPublicKey);
|
||||
CFRelease(cert);
|
||||
if (status != 0) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
CryptoX_PublicKey* aPublicKey,
|
||||
const unsigned char* aSignature,
|
||||
unsigned int aSignatureLen)
|
||||
{
|
||||
if (!aInputData || !*aInputData || !aPublicKey || !*aPublicKey ||
|
||||
!aSignature || aSignatureLen == 0) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
CFDataRef signatureData = CFDataCreate(kCFAllocatorDefault,
|
||||
aSignature, aSignatureLen);
|
||||
if (!signatureData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
CFErrorRef error;
|
||||
SecTransformRef verifier =
|
||||
SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey,
|
||||
signatureData,
|
||||
&error);
|
||||
if (!verifier || error) {
|
||||
CFRelease(signatureData);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
SecTransformSetAttributePtr(verifier,
|
||||
kSecTransformInputAttributeName,
|
||||
(CFDataRef)*aInputData,
|
||||
&error);
|
||||
if (error) {
|
||||
CFRelease(signatureData);
|
||||
CFRelease(verifier);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
CryptoX_Result result = CryptoX_Error;
|
||||
CFTypeRef rv = SecTransformExecutePtr(verifier, &error);
|
||||
if (error) {
|
||||
CFRelease(signatureData);
|
||||
CFRelease(verifier);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
if (CFGetTypeID(rv) == CFBooleanGetTypeID() &&
|
||||
CFBooleanGetValue((CFBooleanRef)rv) == true) {
|
||||
result = CryptoX_Success;
|
||||
}
|
||||
|
||||
CFRelease(signatureData);
|
||||
CFRelease(verifier);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData)
|
||||
{
|
||||
if (!aInputData || !*aInputData) {
|
||||
return;
|
||||
}
|
||||
|
||||
CFMutableDataRef inputData = NULL;
|
||||
inputData = (CFMutableDataRef)*aInputData;
|
||||
|
||||
CFRelease(inputData);
|
||||
}
|
||||
|
||||
void
|
||||
CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey)
|
||||
{
|
||||
if (!aPublicKey || !*aPublicKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
CFRelease((SecKeyRef)*aPublicKey);
|
||||
}
|
||||
273
modules/libmar/verify/cryptox.c
Normal file
273
modules/libmar/verify/cryptox.c
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "cryptox.h"
|
||||
|
||||
#if defined(MAR_NSS)
|
||||
|
||||
/**
|
||||
* Loads the public key for the specified cert name from the NSS store.
|
||||
*
|
||||
* @param certData The DER-encoded X509 certificate to extract the key from.
|
||||
* @param certDataSize The size of certData.
|
||||
* @param publicKey Out parameter for the public key to use.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
NSS_LoadPublicKey(const unsigned char *certData, unsigned int certDataSize,
|
||||
SECKEYPublicKey **publicKey)
|
||||
{
|
||||
CERTCertificate * cert;
|
||||
SECItem certDataItem = { siBuffer, (unsigned char*) certData, certDataSize };
|
||||
|
||||
if (!certData || !publicKey) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &certDataItem, NULL,
|
||||
PR_FALSE, PR_TRUE);
|
||||
/* Get the cert and embedded public key out of the database */
|
||||
if (!cert) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
*publicKey = CERT_ExtractPublicKey(cert);
|
||||
CERT_DestroyCertificate(cert);
|
||||
|
||||
if (!*publicKey) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
NSS_VerifyBegin(VFYContext **ctx,
|
||||
SECKEYPublicKey * const *publicKey)
|
||||
{
|
||||
SECStatus status;
|
||||
if (!ctx || !publicKey || !*publicKey) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* Check that the key length is large enough for our requirements */
|
||||
if ((SECKEY_PublicKeyStrength(*publicKey) * 8) <
|
||||
XP_MIN_SIGNATURE_LEN_IN_BYTES) {
|
||||
fprintf(stderr, "ERROR: Key length must be >= %d bytes\n",
|
||||
XP_MIN_SIGNATURE_LEN_IN_BYTES);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
*ctx = VFY_CreateContext(*publicKey, NULL,
|
||||
SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL);
|
||||
if (*ctx == NULL) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
status = VFY_Begin(*ctx);
|
||||
return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if a verify context matches the passed in signature.
|
||||
*
|
||||
* @param ctx The verify context that the signature should match.
|
||||
* @param signature The signature to match.
|
||||
* @param signatureLen The length of the signature.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
NSS_VerifySignature(VFYContext * const *ctx,
|
||||
const unsigned char *signature,
|
||||
unsigned int signatureLen)
|
||||
{
|
||||
SECItem signedItem;
|
||||
SECStatus status;
|
||||
if (!ctx || !signature || !*ctx) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
signedItem.len = signatureLen;
|
||||
signedItem.data = (unsigned char*)signature;
|
||||
status = VFY_EndWithSignature(*ctx, &signedItem);
|
||||
return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
/**
|
||||
* Verifies if a signature + public key matches a hash context.
|
||||
*
|
||||
* @param hash The hash context that the signature should match.
|
||||
* @param pubKey The public key to use on the signature.
|
||||
* @param signature The signature to check.
|
||||
* @param signatureLen The length of the signature.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CyprtoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
HCRYPTKEY *pubKey,
|
||||
const BYTE *signature,
|
||||
DWORD signatureLen)
|
||||
{
|
||||
DWORD i;
|
||||
BOOL result;
|
||||
/* Windows APIs expect the bytes in the signature to be in little-endian
|
||||
* order, but we write the signature in big-endian order. Other APIs like
|
||||
* NSS and OpenSSL expect big-endian order.
|
||||
*/
|
||||
BYTE *signatureReversed;
|
||||
if (!hash || !pubKey || !signature || signatureLen < 1) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
signatureReversed = malloc(signatureLen);
|
||||
if (!signatureReversed) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
for (i = 0; i < signatureLen; i++) {
|
||||
signatureReversed[i] = signature[signatureLen - 1 - i];
|
||||
}
|
||||
result = CryptVerifySignature(*hash, signatureReversed,
|
||||
signatureLen, *pubKey, NULL, 0);
|
||||
free(signatureReversed);
|
||||
return result ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the public key for the passed in cert data
|
||||
*
|
||||
* @param provider The cyrto provider
|
||||
* @param certData Data of the certificate to extract the public key from
|
||||
* @param sizeOfCertData The size of the certData buffer
|
||||
* @param certStore Pointer to the handle of the certificate store to use
|
||||
* @param CryptoX_Success on success
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_LoadPublicKey(HCRYPTPROV provider,
|
||||
BYTE *certData,
|
||||
DWORD sizeOfCertData,
|
||||
HCRYPTKEY *publicKey)
|
||||
{
|
||||
CRYPT_DATA_BLOB blob;
|
||||
CERT_CONTEXT *context;
|
||||
if (!provider || !certData || !publicKey) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
blob.cbData = sizeOfCertData;
|
||||
blob.pbData = certData;
|
||||
if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_CERT,
|
||||
CERT_QUERY_FORMAT_FLAG_BINARY,
|
||||
0, NULL, NULL, NULL,
|
||||
NULL, NULL, (const void **)&context)) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
if (!CryptImportPublicKeyInfo(provider,
|
||||
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||||
&context->pCertInfo->SubjectPublicKeyInfo,
|
||||
publicKey)) {
|
||||
CertFreeCertificateContext(context);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
CertFreeCertificateContext(context);
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
/* Try to acquire context in this way:
|
||||
* 1. Enhanced provider without creating a new key set
|
||||
* 2. Enhanced provider with creating a new key set
|
||||
* 3. Default provider without creating a new key set
|
||||
* 4. Default provider without creating a new key set
|
||||
* #2 and #4 should not be needed because of the CRYPT_VERIFYCONTEXT,
|
||||
* but we add it just in case.
|
||||
*
|
||||
* @param provider Out parameter containing the provider handle.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_InitCryptoContext(HCRYPTPROV *provider)
|
||||
{
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
MS_ENHANCED_PROV,
|
||||
PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
MS_ENHANCED_PROV,
|
||||
PROV_RSA_FULL,
|
||||
CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
NULL,
|
||||
PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
NULL,
|
||||
PROV_RSA_FULL,
|
||||
CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
|
||||
*provider = CryptoX_InvalidHandleValue;
|
||||
return CryptoX_Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a signature verification hash context
|
||||
*
|
||||
* @param provider The crypt provider to use
|
||||
* @param hash Out parameter for a handle to the hash context
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash)
|
||||
{
|
||||
BOOL result;
|
||||
if (!provider || !hash) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
*hash = (HCRYPTHASH)NULL;
|
||||
result = CryptCreateHash(provider, CALG_SHA1,
|
||||
0, 0, hash);
|
||||
return result ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a signature verification hash context
|
||||
*
|
||||
* @param hash The hash context to udpate
|
||||
* @param buf The buffer to update the hash context with
|
||||
* @param len The size of the passed in buffer
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_VerifyUpdate(HCRYPTHASH* hash, BYTE *buf, DWORD len)
|
||||
{
|
||||
BOOL result;
|
||||
if (!hash || !buf) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
result = CryptHashData(*hash, buf, len, 0);
|
||||
return result ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
172
modules/libmar/verify/cryptox.h
Normal file
172
modules/libmar/verify/cryptox.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifndef CRYPTOX_H
|
||||
#define CRYPTOX_H
|
||||
|
||||
#define XP_MIN_SIGNATURE_LEN_IN_BYTES 256
|
||||
|
||||
#define CryptoX_Result int
|
||||
#define CryptoX_Success 0
|
||||
#define CryptoX_Error (-1)
|
||||
#define CryptoX_Succeeded(X) ((X) == CryptoX_Success)
|
||||
#define CryptoX_Failed(X) ((X) != CryptoX_Success)
|
||||
|
||||
#if defined(MAR_NSS)
|
||||
|
||||
#include "cert.h"
|
||||
#include "keyhi.h"
|
||||
#include "cryptohi.h"
|
||||
|
||||
#define CryptoX_InvalidHandleValue NULL
|
||||
#define CryptoX_ProviderHandle void*
|
||||
#define CryptoX_SignatureHandle VFYContext *
|
||||
#define CryptoX_PublicKey SECKEYPublicKey *
|
||||
#define CryptoX_Certificate CERTCertificate *
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
CryptoX_Result NSS_LoadPublicKey(const unsigned char* certData,
|
||||
unsigned int certDataSize,
|
||||
SECKEYPublicKey** publicKey);
|
||||
CryptoX_Result NSS_VerifyBegin(VFYContext **ctx,
|
||||
SECKEYPublicKey * const *publicKey);
|
||||
CryptoX_Result NSS_VerifySignature(VFYContext * const *ctx ,
|
||||
const unsigned char *signature,
|
||||
unsigned int signatureLen);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#define CryptoX_InitCryptoProvider(CryptoHandle) \
|
||||
CryptoX_Success
|
||||
#define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
|
||||
NSS_VerifyBegin(SignatureHandle, PublicKey)
|
||||
#define CryptoX_FreeSignatureHandle(SignatureHandle) \
|
||||
VFY_DestroyContext(*SignatureHandle, PR_TRUE)
|
||||
#define CryptoX_VerifyUpdate(SignatureHandle, buf, len) \
|
||||
VFY_Update(*SignatureHandle, (const unsigned char*)(buf), len)
|
||||
#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey) \
|
||||
NSS_LoadPublicKey(certData, dataSize, publicKey)
|
||||
#define CryptoX_VerifySignature(hash, publicKey, signedData, len) \
|
||||
NSS_VerifySignature(hash, (const unsigned char *)(signedData), len)
|
||||
#define CryptoX_FreePublicKey(key) \
|
||||
SECKEY_DestroyPublicKey(*key)
|
||||
#define CryptoX_FreeCertificate(cert) \
|
||||
CERT_DestroyCertificate(*cert)
|
||||
|
||||
#elif XP_MACOSX
|
||||
|
||||
#define CryptoX_InvalidHandleValue NULL
|
||||
#define CryptoX_ProviderHandle void*
|
||||
#define CryptoX_SignatureHandle void*
|
||||
#define CryptoX_PublicKey void*
|
||||
#define CryptoX_Certificate void*
|
||||
|
||||
// Forward-declare Objective-C functions implemented in MacVerifyCrypto.mm.
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
CryptoX_Result CryptoMac_InitCryptoProvider();
|
||||
CryptoX_Result CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData);
|
||||
CryptoX_Result CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData,
|
||||
void* aBuf, unsigned int aLen);
|
||||
CryptoX_Result CryptoMac_LoadPublicKey(const unsigned char* aCertData,
|
||||
unsigned int aDataSize,
|
||||
CryptoX_PublicKey* aPublicKey);
|
||||
CryptoX_Result CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
CryptoX_PublicKey* aPublicKey,
|
||||
const unsigned char* aSignature,
|
||||
unsigned int aSignatureLen);
|
||||
void CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData);
|
||||
void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#define CryptoX_InitCryptoProvider(aProviderHandle) \
|
||||
CryptoMac_InitCryptoProvider()
|
||||
#define CryptoX_VerifyBegin(aCryptoHandle, aInputData, aPublicKey) \
|
||||
CryptoMac_VerifyBegin(aInputData)
|
||||
#define CryptoX_VerifyUpdate(aInputData, aBuf, aLen) \
|
||||
CryptoMac_VerifyUpdate(aInputData, aBuf, aLen)
|
||||
#define CryptoX_LoadPublicKey(aProviderHandle, aCertData, aDataSize, \
|
||||
aPublicKey) \
|
||||
CryptoMac_LoadPublicKey(aCertData, aDataSize, aPublicKey)
|
||||
#define CryptoX_VerifySignature(aInputData, aPublicKey, aSignature, \
|
||||
aSignatureLen) \
|
||||
CryptoMac_VerifySignature(aInputData, aPublicKey, aSignature, aSignatureLen)
|
||||
#define CryptoX_FreeSignatureHandle(aInputData) \
|
||||
CryptoMac_FreeSignatureHandle(aInputData)
|
||||
#define CryptoX_FreePublicKey(aPublicKey) \
|
||||
CryptoMac_FreePublicKey(aPublicKey)
|
||||
#define CryptoX_FreeCertificate(aCertificate)
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
CryptoX_Result CryptoAPI_InitCryptoContext(HCRYPTPROV *provider);
|
||||
CryptoX_Result CryptoAPI_LoadPublicKey(HCRYPTPROV hProv,
|
||||
BYTE *certData,
|
||||
DWORD sizeOfCertData,
|
||||
HCRYPTKEY *publicKey);
|
||||
CryptoX_Result CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash);
|
||||
CryptoX_Result CryptoAPI_VerifyUpdate(HCRYPTHASH* hash,
|
||||
BYTE *buf, DWORD len);
|
||||
CryptoX_Result CyprtoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
HCRYPTKEY *pubKey,
|
||||
const BYTE *signature,
|
||||
DWORD signatureLen);
|
||||
|
||||
#define CryptoX_InvalidHandleValue ((ULONG_PTR)NULL)
|
||||
#define CryptoX_ProviderHandle HCRYPTPROV
|
||||
#define CryptoX_SignatureHandle HCRYPTHASH
|
||||
#define CryptoX_PublicKey HCRYPTKEY
|
||||
#define CryptoX_Certificate HCERTSTORE
|
||||
#define CryptoX_InitCryptoProvider(CryptoHandle) \
|
||||
CryptoAPI_InitCryptoContext(CryptoHandle)
|
||||
#define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
|
||||
CryptoAPI_VerifyBegin(CryptoHandle, SignatureHandle)
|
||||
#define CryptoX_FreeSignatureHandle(SignatureHandle)
|
||||
#define CryptoX_VerifyUpdate(SignatureHandle, buf, len) \
|
||||
CryptoAPI_VerifyUpdate(SignatureHandle, (BYTE *)(buf), len)
|
||||
#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey) \
|
||||
CryptoAPI_LoadPublicKey(CryptoHandle, (BYTE*)(certData), dataSize, publicKey)
|
||||
#define CryptoX_VerifySignature(hash, publicKey, signedData, len) \
|
||||
CyprtoAPI_VerifySignature(hash, publicKey, signedData, len)
|
||||
#define CryptoX_FreePublicKey(key) \
|
||||
CryptDestroyKey(*(key))
|
||||
#define CryptoX_FreeCertificate(cert) \
|
||||
CertCloseStore(*(cert), CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
|
||||
#else
|
||||
|
||||
/* This default implementation is necessary because we don't want to
|
||||
* link to NSS from updater code on non Windows platforms. On Windows
|
||||
* we use CyrptoAPI instead of NSS. We don't call any function as they
|
||||
* would just fail, but this simplifies linking.
|
||||
*/
|
||||
|
||||
#define CryptoX_InvalidHandleValue NULL
|
||||
#define CryptoX_ProviderHandle void*
|
||||
#define CryptoX_SignatureHandle void*
|
||||
#define CryptoX_PublicKey void*
|
||||
#define CryptoX_Certificate void*
|
||||
#define CryptoX_InitCryptoProvider(CryptoHandle) \
|
||||
CryptoX_Error
|
||||
#define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
|
||||
CryptoX_Error
|
||||
#define CryptoX_FreeSignatureHandle(SignatureHandle)
|
||||
#define CryptoX_VerifyUpdate(SignatureHandle, buf, len) CryptoX_Error
|
||||
#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey) \
|
||||
CryptoX_Error
|
||||
#define CryptoX_VerifySignature(hash, publicKey, signedData, len) CryptoX_Error
|
||||
#define CryptoX_FreePublicKey(key) CryptoX_Error
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
466
modules/libmar/verify/mar_verify.c
Normal file
466
modules/libmar/verify/mar_verify.c
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mar_private.h"
|
||||
#include "mar.h"
|
||||
#include "cryptox.h"
|
||||
|
||||
int
|
||||
mar_read_entire_file(const char * filePath, uint32_t maxSize,
|
||||
/*out*/ const uint8_t * *data,
|
||||
/*out*/ uint32_t *size)
|
||||
{
|
||||
int result;
|
||||
FILE * f;
|
||||
|
||||
if (!filePath || !data || !size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = fopen(filePath, "rb");
|
||||
if (!f) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = -1;
|
||||
if (!fseeko(f, 0, SEEK_END)) {
|
||||
int64_t fileSize = ftello(f);
|
||||
if (fileSize > 0 && fileSize <= maxSize && !fseeko(f, 0, SEEK_SET)) {
|
||||
unsigned char * fileData;
|
||||
|
||||
*size = (unsigned int) fileSize;
|
||||
fileData = malloc(*size);
|
||||
if (fileData) {
|
||||
if (fread(fileData, *size, 1, f) == 1) {
|
||||
*data = fileData;
|
||||
result = 0;
|
||||
} else {
|
||||
free(fileData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int mar_extract_and_verify_signatures_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
uint32_t keyCount);
|
||||
int mar_verify_signatures_for_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
const uint8_t * const *extractedSignatures,
|
||||
uint32_t keyCount,
|
||||
uint32_t *numVerified);
|
||||
|
||||
/**
|
||||
* Reads the specified number of bytes from the file pointer and
|
||||
* stores them in the passed buffer.
|
||||
*
|
||||
* @param fp The file pointer to read from.
|
||||
* @param buffer The buffer to store the read results.
|
||||
* @param size The number of bytes to read, buffer must be
|
||||
* at least of this size.
|
||||
* @param ctxs Pointer to the first element in an array of verify context.
|
||||
* @param count The number of elements in ctxs
|
||||
* @param err The name of what is being written to in case of error.
|
||||
* @return 0 on success
|
||||
* -1 on read error
|
||||
* -2 on verify update error
|
||||
*/
|
||||
int
|
||||
ReadAndUpdateVerifyContext(FILE *fp,
|
||||
void *buffer,
|
||||
uint32_t size,
|
||||
CryptoX_SignatureHandle *ctxs,
|
||||
uint32_t count,
|
||||
const char *err)
|
||||
{
|
||||
uint32_t k;
|
||||
if (!fp || !buffer || !ctxs || count == 0 || !err) {
|
||||
fprintf(stderr, "ERROR: Invalid parameter specified.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
if (fread(buffer, size, 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read %s\n", err);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
for (k = 0; k < count; k++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifyUpdate(&ctxs[k], buffer, size))) {
|
||||
fprintf(stderr, "ERROR: Could not update verify context for %s\n", err);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a MAR file by verifying each signature with the corresponding
|
||||
* certificate. That is, the first signature will be verified using the first
|
||||
* certificate given, the second signature will be verified using the second
|
||||
* certificate given, etc. The signature count must exactly match the number of
|
||||
* certificates given, and all signature verifications must succeed.
|
||||
*
|
||||
* @param mar The file who's signature should be calculated
|
||||
* @param certData Pointer to the first element in an array of
|
||||
* certificate data
|
||||
* @param certDataSizes Pointer to the first element in an array for size of
|
||||
* the data stored
|
||||
* @param certCount The number of elements in certData and certDataSizes
|
||||
* @return 0 on success
|
||||
*/
|
||||
int
|
||||
mar_verify_signatures(MarFile *mar,
|
||||
const uint8_t * const *certData,
|
||||
const uint32_t *certDataSizes,
|
||||
uint32_t certCount) {
|
||||
int rv = -1;
|
||||
CryptoX_ProviderHandle provider = CryptoX_InvalidHandleValue;
|
||||
CryptoX_PublicKey keys[MAX_SIGNATURES];
|
||||
uint32_t k;
|
||||
|
||||
memset(keys, 0, sizeof(keys));
|
||||
|
||||
if (!mar || !certData || !certDataSizes || certCount == 0) {
|
||||
fprintf(stderr, "ERROR: Invalid parameter specified.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (!mar->fp) {
|
||||
fprintf(stderr, "ERROR: MAR file is not open.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (CryptoX_Failed(CryptoX_InitCryptoProvider(&provider))) {
|
||||
fprintf(stderr, "ERROR: Could not init crytpo library.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
for (k = 0; k < certCount; ++k) {
|
||||
if (CryptoX_Failed(CryptoX_LoadPublicKey(provider, certData[k], certDataSizes[k],
|
||||
&keys[k]))) {
|
||||
fprintf(stderr, "ERROR: Could not load public key.\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
rv = mar_extract_and_verify_signatures_fp(mar->fp, provider, keys, certCount);
|
||||
|
||||
failure:
|
||||
|
||||
for (k = 0; k < certCount; ++k) {
|
||||
if (keys[k]) {
|
||||
CryptoX_FreePublicKey(&keys[k]);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts each signature from the specified MAR file,
|
||||
* then calls mar_verify_signatures_for_fp to verify each signature.
|
||||
*
|
||||
* @param fp An opened MAR file handle
|
||||
* @param provider A library provider
|
||||
* @param keys The public keys to use to verify the MAR
|
||||
* @param keyCount The number of keys pointed to by keys
|
||||
* @return 0 on success
|
||||
*/
|
||||
int
|
||||
mar_extract_and_verify_signatures_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
uint32_t keyCount) {
|
||||
uint32_t signatureCount, signatureLen, numVerified = 0;
|
||||
uint32_t signatureAlgorithmIDs[MAX_SIGNATURES];
|
||||
uint8_t *extractedSignatures[MAX_SIGNATURES];
|
||||
uint32_t i;
|
||||
|
||||
memset(signatureAlgorithmIDs, 0, sizeof(signatureAlgorithmIDs));
|
||||
memset(extractedSignatures, 0, sizeof(extractedSignatures));
|
||||
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: Invalid file pointer passed.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* To protect against invalid MAR files, we assumes that the MAR file
|
||||
size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
|
||||
if (fseeko(fp, 0, SEEK_END)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to the end of the MAR file.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
if (ftello(fp) > MAX_SIZE_OF_MAR_FILE) {
|
||||
fprintf(stderr, "ERROR: MAR file is too large to be verified.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* Skip to the start of the signature block */
|
||||
if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to the signature block.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* Get the number of signatures */
|
||||
if (fread(&signatureCount, sizeof(signatureCount), 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read number of signatures.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
signatureCount = ntohl(signatureCount);
|
||||
|
||||
/* Check that we have less than the max amount of signatures so we don't
|
||||
waste too much of either updater's or signmar's time. */
|
||||
if (signatureCount > MAX_SIGNATURES) {
|
||||
fprintf(stderr, "ERROR: At most %d signatures can be specified.\n",
|
||||
MAX_SIGNATURES);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
/* Get the signature algorithm ID */
|
||||
if (fread(&signatureAlgorithmIDs[i], sizeof(uint32_t), 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read signatures algorithm ID.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
signatureAlgorithmIDs[i] = ntohl(signatureAlgorithmIDs[i]);
|
||||
|
||||
if (fread(&signatureLen, sizeof(uint32_t), 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read signatures length.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
signatureLen = ntohl(signatureLen);
|
||||
|
||||
/* To protected against invalid input make sure the signature length
|
||||
isn't too big. */
|
||||
if (signatureLen > MAX_SIGNATURE_LENGTH) {
|
||||
fprintf(stderr, "ERROR: Signature length is too large to verify.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
extractedSignatures[i] = malloc(signatureLen);
|
||||
if (!extractedSignatures[i]) {
|
||||
fprintf(stderr, "ERROR: Could allocate buffer for signature.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
if (fread(extractedSignatures[i], signatureLen, 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read extracted signature.\n");
|
||||
for (i = 0; i < signatureCount; ++i) {
|
||||
free(extractedSignatures[i]);
|
||||
}
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* We don't try to verify signatures we don't know about */
|
||||
if (signatureAlgorithmIDs[i] != 1) {
|
||||
fprintf(stderr, "ERROR: Unknown signature algorithm ID.\n");
|
||||
for (i = 0; i < signatureCount; ++i) {
|
||||
free(extractedSignatures[i]);
|
||||
}
|
||||
return CryptoX_Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (ftello(fp) == -1) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
if (mar_verify_signatures_for_fp(fp,
|
||||
provider,
|
||||
keys,
|
||||
(const uint8_t * const *)extractedSignatures,
|
||||
signatureCount,
|
||||
&numVerified) == CryptoX_Error) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
for (i = 0; i < signatureCount; ++i) {
|
||||
free(extractedSignatures[i]);
|
||||
}
|
||||
|
||||
/* If we reached here and we verified every
|
||||
signature, return success. */
|
||||
if (numVerified == signatureCount && keyCount == numVerified) {
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
if (numVerified == 0) {
|
||||
fprintf(stderr, "ERROR: Not all signatures were verified.\n");
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Only %d of %d signatures were verified.\n",
|
||||
numVerified, signatureCount);
|
||||
}
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a MAR file by verifying each signature with the corresponding
|
||||
* certificate. That is, the first signature will be verified using the first
|
||||
* certificate given, the second signature will be verified using the second
|
||||
* certificate given, etc. The signature count must exactly match the number of
|
||||
* certificates given, and all signature verifications must succeed.
|
||||
*
|
||||
* @param fp An opened MAR file handle
|
||||
* @param provider A library provider
|
||||
* @param keys A pointer to the first element in an
|
||||
* array of keys.
|
||||
* @param extractedSignatures Pointer to the first element in an array
|
||||
* of extracted signatures.
|
||||
* @param signatureCount The number of signatures in the MAR file
|
||||
* @param numVerified Out parameter which will be filled with
|
||||
* the number of verified signatures.
|
||||
* This information can be useful for printing
|
||||
* error messages.
|
||||
* @return 0 on success, *numVerified == signatureCount.
|
||||
*/
|
||||
int
|
||||
mar_verify_signatures_for_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
const uint8_t * const *extractedSignatures,
|
||||
uint32_t signatureCount,
|
||||
uint32_t *numVerified)
|
||||
{
|
||||
CryptoX_SignatureHandle signatureHandles[MAX_SIGNATURES];
|
||||
char buf[BLOCKSIZE];
|
||||
uint32_t signatureLengths[MAX_SIGNATURES];
|
||||
uint32_t i;
|
||||
int rv = CryptoX_Error;
|
||||
|
||||
memset(signatureHandles, 0, sizeof(signatureHandles));
|
||||
memset(signatureLengths, 0, sizeof(signatureLengths));
|
||||
|
||||
if (!extractedSignatures || !numVerified) {
|
||||
fprintf(stderr, "ERROR: Invalid parameter specified.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
*numVerified = 0;
|
||||
|
||||
/* This function is only called when we have at least one signature,
|
||||
but to protected against future people who call this function we
|
||||
make sure a non zero value is passed in.
|
||||
*/
|
||||
if (!signatureCount) {
|
||||
fprintf(stderr, "ERROR: There must be at least one signature.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifyBegin(provider,
|
||||
&signatureHandles[i], &keys[i]))) {
|
||||
fprintf(stderr, "ERROR: Could not initialize signature handle.\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip to the start of the file */
|
||||
if (fseeko(fp, 0, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to start of the file\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Bytes 0-3: MAR1
|
||||
Bytes 4-7: index offset
|
||||
Bytes 8-15: size of entire MAR
|
||||
*/
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp, buf,
|
||||
SIGNATURE_BLOCK_OFFSET +
|
||||
sizeof(uint32_t),
|
||||
signatureHandles,
|
||||
signatureCount,
|
||||
"signature block"))) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Read the signature block */
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
/* Get the signature algorithm ID */
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp,
|
||||
&buf,
|
||||
sizeof(uint32_t),
|
||||
signatureHandles,
|
||||
signatureCount,
|
||||
"signature algorithm ID"))) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp,
|
||||
&signatureLengths[i],
|
||||
sizeof(uint32_t),
|
||||
signatureHandles,
|
||||
signatureCount,
|
||||
"signature length"))) {
|
||||
goto failure;
|
||||
}
|
||||
signatureLengths[i] = ntohl(signatureLengths[i]);
|
||||
if (signatureLengths[i] > MAX_SIGNATURE_LENGTH) {
|
||||
fprintf(stderr, "ERROR: Embedded signature length is too large.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Skip past the signature itself as those are not included */
|
||||
if (fseeko(fp, signatureLengths[i], SEEK_CUR)) {
|
||||
fprintf(stderr, "ERROR: Could not seek past signature.\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the rest of the file after the signature block */
|
||||
while (!feof(fp)) {
|
||||
int numRead = fread(buf, 1, BLOCKSIZE , fp);
|
||||
if (ferror(fp)) {
|
||||
fprintf(stderr, "ERROR: Error reading data block.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifyUpdate(&signatureHandles[i],
|
||||
buf, numRead))) {
|
||||
fprintf(stderr, "ERROR: Error updating verify context with"
|
||||
" data block.\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify the signatures */
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifySignature(&signatureHandles[i],
|
||||
&keys[i],
|
||||
extractedSignatures[i],
|
||||
signatureLengths[i]))) {
|
||||
fprintf(stderr, "ERROR: Error verifying signature.\n");
|
||||
goto failure;
|
||||
}
|
||||
++*numVerified;
|
||||
}
|
||||
|
||||
rv = CryptoX_Success;
|
||||
failure:
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
CryptoX_FreeSignatureHandle(&signatureHandles[i]);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
31
modules/libmar/verify/moz.build
Normal file
31
modules/libmar/verify/moz.build
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
Library('verifymar')
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'cryptox.c',
|
||||
'mar_verify.c',
|
||||
]
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
USE_STATIC_LIBS = True
|
||||
elif CONFIG['OS_ARCH'] == 'Darwin':
|
||||
UNIFIED_SOURCES += [
|
||||
'MacVerifyCrypto.cpp',
|
||||
]
|
||||
OS_LIBS += [
|
||||
'-framework Security',
|
||||
]
|
||||
else:
|
||||
DEFINES['MAR_NSS'] = True
|
||||
LOCAL_INCLUDES += ['../sign']
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../src',
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue