📄 x509inputcertificate.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: x509InputCertificate.c,v 1.17 2002/08/06 20:11:06 dallen Exp $
____________________________________________________________________________*/
/*
* Author: michael_elkins@nai.com
* Last Edit: January 11, 2000
*/
#include "x509CMS.h"
#include "pgpX509Priv.h"
#include "pgpKeyPriv.h"
#include "pkcsreq_asn.h"
#include "pkcsreq_oid.h"
/* convert hex value into integer */
#define hexval(c) (((c)>='0'&&(c)<='9')?(c)-'0':10+(c)-'A')
static PGPKeyDBObjRef
x509FindPrivateKey (
PGPContextRef context,
PGPKeyDBRef db,
PKICONTEXT *asncontext,
PKISignerInfos *si)
{
int i, asnerr = 0;
PGPByte *hashval = 0;
PGPSize hashlen = 0;
PGPKeyDBObjRef key = kInvalidPGPKeyDBObjRef;
/* we should only have one signer */
pgpAssert (si->n <= 1);
if (si->n==0 || !si->elt[0])
return NULL;
/* find the at-pki-transaction-id authenticated attribute */
pgpAssert (si->elt[0]->authenticatedAttributes != 0);
if (!si->elt[0]->authenticatedAttributes)
return NULL;
pgpAssert (si->elt[0]->authenticatedAttributes->n > 0);
for (i = 0; i < si->elt[0]->authenticatedAttributes->n; i++)
{
if (memcmp (si->elt[0]->authenticatedAttributes->elt[i]->type.val,
PKIat_pki_transactionid_OID,
PKIat_pki_transactionid_OID_LEN) == 0)
{
/* depending on the CA, this will either be an INTEGER or
PrintableString */
if (*si->elt[0]->authenticatedAttributes->elt[i]->values.elt[0]->val == PKIID_PrintableString)
{
PKIPrintableString *ps = 0;
PKIUnpackPrintableString (asncontext,
&ps,
si->elt[0]->authenticatedAttributes->elt[i]->values.elt[0]->val,
si->elt[0]->authenticatedAttributes->elt[i]->values.elt[0]->len,
&asnerr);
if (asnerr == 0)
{
PGPSize j;
/* convert the hex string into binary */
hashlen = ps->len / 2;
hashval = PGPNewData (PGPPeekContextMemoryMgr (context),
ps->len / 2, 0);
for (j = 0; j < hashlen; j++)
{
hashval[j] = (hexval(ps->val[2 * j]) << 4) | hexval(ps->val[2 * j + 1]);
}
PKIFreePrintableString (asncontext, ps);
}
}
else
{
PKIINTEGER *asn;
PKIUnpackINTEGER (asncontext, &asn,
si->elt[0]->authenticatedAttributes->elt[i]->values.elt[0]->val,
si->elt[0]->authenticatedAttributes->elt[i]->values.elt[0]->len,
&asnerr);
if (asnerr == 0)
{
hashval = asn->val;
hashlen = asn->len;
PGPFreeData (asn);
}
}
break;
}
}
if (hashval)
{
PGPFilterRef filter = 0;
PGPKeySetRef keyset = 0;
PGPKeyIterRef iter = 0;
PGPError err;
err = PGPNewKeyDBObjDataFilter (context, kPGPKeyProperty_X509MD5Hash,
hashval, hashlen, kPGPMatchCriterion_Equal, &filter);
if (IsPGPError (err))
goto error;
err = PGPFilterKeyDB (db, filter, &keyset);
if (IsPGPError (err))
goto error;
err = PGPNewKeyIterFromKeySet (keyset, &iter);
if (IsPGPError (err))
goto error;
err = PGPKeyIterNextKeyDBObj (iter, kPGPKeyDBObjType_Key, &key);
error:
if (iter)
PGPFreeKeyIter (iter);
if (filter)
PGPFreeFilter (filter);
if (keyset)
PGPFreeKeySet (keyset);
PGPFreeData (hashval);
}
if( key == kInvalidPGPKeyDBObjRef)
{
/* If no luck, just use first key. Caller can give us just
* the key that is needed when we are retrieving a cert. */
PGPKeyIterRef iter;
PGPNewKeyIterFromKeyDB (db, &iter);
PGPKeyIterNextKeyDBObj (iter, kPGPKeyDBObjType_Key, &key);
PGPFreeKeyIter (iter);
}
return key;
}
static void
x509VerifyPKCS7Signatures (
PGPContextRef context,
PGPKeyDBRef keydb, /* [IN] where to find keys */
PKICONTEXT *asnContext, /* [IN] */
PKISignedData *sigData, /* [IN] */
PGPBoolean *sigPresent, /* [OUT] */
PGPBoolean *sigChecked, /* [OUT] */
PGPBoolean *sigVerified, /* [OUT] */
PGPKeyDBObjRef *signKey /* [OUT] */
)
{
X509CMSCallbackData pgpData;
int p7err;
int asnError = 0;
PGPError err;
PGPFilterRef filter = NULL;
PGPKeySetRef targetKeySet = NULL;
PGPKeyIterRef keyIter = NULL;
PGPKeyDBObjRef keyRef = NULL;
PGPByte *isnData = NULL;
PGPSize isnDataLen;
PKICertificate *cert = NULL;
PGPMemoryMgrRef mem = PGPPeekContextMemoryMgr (context);
if (!sigData || sigData->signerInfos.n < 1 || !sigData->signerInfos.elt[0])
return; /* nothing to check */
*sigPresent = 1;
if (!keydb)
return; /* Can't check without keys to check with */
/* find certificate for this user */
/* use the Issuer And Serial Number as a filter */
isnDataLen = PKISizeofIssuerAndSerialNumber (asnContext,
&sigData->signerInfos.elt[0]->issuerAndSerialNumber,
1);
isnData = PGPNewData (mem, isnDataLen, 0);
PKIPackIssuerAndSerialNumber (asnContext,
isnData,
isnDataLen,
&sigData->signerInfos.elt[0]->issuerAndSerialNumber,
&asnError);
if (asnError)
goto error_exit;
err = PGPNewKeyDBObjDataFilter( context, kPGPSigProperty_X509IASN,
isnData, isnDataLen, kPGPMatchCriterion_Equal, &filter );
if (IsPGPError (err))
goto error_exit;
err = PGPFilterKeySet (pgpKeyDBPeekRootSet(keydb), filter, &targetKeySet);
if (IsPGPError (err))
goto error_exit;
err = PGPNewKeyIterFromKeySet (targetKeySet, &keyIter);
if (IsPGPError (err))
goto error_exit;
err = PGPKeyIterNextKeyDBObj (keyIter, kPGPKeyDBObjType_Key, &keyRef);
if (IsPGPError (err))
goto error_exit;
*signKey = keyRef;
err = x509ExtractCertificate (context,
keyRef,
asnContext,
&cert);
if (IsPGPError (err))
goto error_exit;
*sigChecked = 1;
/* set up callback data */
memset (&pgpData, 0, sizeof (pgpData));
pgpData.context = context;
pgpData.key = keyRef;
/* verify signature */
p7err = sm_VerifyMessage (NULL, /* dont return the inner data */
0,
sigData,
cert,
pkcs7HashCallback,
(void *) &pgpData,
pkcs7VerifyCallback,
(void *) &pgpData,
asnContext);
if (p7err == PKCS7_OK)
*sigVerified = 1;
error_exit:
if (keyIter)
PGPFreeKeyIter (keyIter);
if (targetKeySet)
PGPFreeKeySet (targetKeySet);
if (filter)
PGPFreeFilter (filter);
if (cert)
PKIFreeCertificate (asnContext, cert);
if (isnData)
PGPFreeData (isnData);
}
static void
x509ExtractCertificatesFromSignedData (
PKICONTEXT *asnContext,
PKISignedData *sigData,
PKIExtendedCertificatesAndCertificates *certSet)
{
int i;
if (sigData->certificates)
{
for (i = 0; i < sigData->certificates->n; i++)
{
PKIAddOfElement(asnContext,sigData->certificates->elt[i],certSet);
sigData->certificates->elt[i] = NULL;
}
/* don't free this data when free'ing sigData */
if (sigData->certificates->n)
PGPFreeData( sigData->certificates->elt );
PGPFreeData (sigData->certificates);
sigData->certificates = NULL;
}
}
static void
x509ExtractCRLsFromSignedData (
PKICONTEXT *asnContext,
PKISignedData *sig,
PKICertificateRevocationLists *crls)
{
int i;
if (sig->crls)
{
for (i = 0; i < sig->crls->n; i++)
{
PKIAddOfElement (asnContext, sig->crls->elt[i], crls);
sig->crls->elt[i] = NULL;
}
if (sig->crls->n)
PGPFreeData (sig->crls->elt);
PGPFreeData (sig->crls);
sig->crls = NULL;
}
}
static PGPError
x509ParseAsCertificate(
PKICONTEXT *asnContext,
/*const*/ PGPByte *input,
PGPSize inputSize,
PKIExtendedCertificatesAndCertificates *certSet)
{
/* first check to see if this is a vanilla X.509 certificate */
int asnError = 0;
PKICertificate *cert;
PKIExtendedCertificateOrCertificate *extended;
PKIUnpackCertificate (asnContext, &cert, input, inputSize, &asnError);
if(asnError)
return kPGPError_LazyProgrammer;
extended = PKINewExtendedCertificateOrCertificate (asnContext);
extended->CHOICE_field_type = PKIID_Certificate;
extended->data = (void *) cert; /* NOTE: don't free `cert' */
PKIAddOfElement (asnContext, extended, certSet);
return kPGPError_NoErr;
}
static PGPError
x509ParseAsCRL(
PKICONTEXT *asnContext,
/*const*/ PGPByte *input,
PGPSize inputSize,
PKICertificateRevocationLists *crls)
{
/* check for x.509 crl */
int asnError=0;
PKICertificateList *crl;
PKIUnpackCertificateList(asnContext,&crl,input,inputSize,&asnError);
if(asnError)
return kPGPError_LazyProgrammer;
PKIAddOfElement (asnContext, crl, crls); /* don't free crl */
return kPGPError_NoErr;
}
PGPError
X509InputCertificate (
PGPContextRef context,
PGPByte *input, /* input buffer */
PGPSize inputSize,
PGPKeyDBRef keydb, /* where to find keys */
PGPInputFormat format, /* Import format (CA) */
PGPOptionListRef passphrase,/* Passphrase for decrypting */
PGPKeyDBObjRef *decryptKey, /* Output decryption key */
PGPKeyDBObjRef *signKey, /* Output signing key */
PGPBoolean *sigPresent, /* output flag for signed message */
PGPBoolean *sigChecked, /* output that we have sig key */
PGPBoolean *sigVerified, /* output flag for sig ok */
PGPAttributeValue **extraData,
PGPUInt32 *extraDataCount,
PGPByte **certOut,
PGPSize *certOutSize,
PGPByte **crlOut,
PGPSize *crlOutSize
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -