/
githubmirror
/
xmlsec
Обзор
Документация
Войти
/
githubmirror
/
xmlsec
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/nss/x509.c
1 518 строк
50 KB
lsh123
(xmlsec-nss) Enable SHA3 digest in NSS by default (#1147)
25 апр 2026, 02:13
Не верифицирован
25 апр 2026, 02:13
bf3bb6d
Код
Авторство
О чём код?
/** * XML Security Library (http://www.aleksey.com/xmlsec). * * This is free software; see the Copyright file in the source distribution for precise wording. * * Copyright (C) 2002-2026 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. * Copyright (c) 2003 America Online, Inc. All rights reserved. */ /** * @addtogroup xmlsec_nss_x509 * @brief X509 certificates implementation for NSS. * X509 certificates implementation for NSS. */ #include "globals.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <time.h> #include <prmem.h> #include <pratom.h> #include <keyhi.h> #include <cert.h> #include <certdb.h> #include <pk11pub.h> #include <sechash.h> #include <xmlsec/xmlsec.h> #include <xmlsec/base64.h> #include <xmlsec/keys.h> #include <xmlsec/keyinfo.h> #include <xmlsec/keysmngr.h> #include <xmlsec/x509.h> #include <xmlsec/errors.h> #include <xmlsec/private.h> #include <xmlsec/xmltree.h> #include <xmlsec/nss/crypto.h> #include <xmlsec/nss/x509.h> #include <xmlsec/nss/pkikeys.h> #include "../cast_helpers.h" #include "../x509_helpers.h" #include "private.h" #ifndef XMLSEC_NO_X509 /****************************************************************************** * * X509 utility functions * *****************************************************************************/ static int xmlSecNssVerifyAndAdoptX509KeyData (xmlSecKeyPtr key, xmlSecKeyDataPtr data, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecNssX509SECItemWrite (SECItem * secItem, xmlSecBufferPtr buf); static xmlChar* xmlSecNssX509NameWrite (CERTName* nm); static int xmlSecNssX509DigestWrite (CERTCertificate* cert, const xmlChar* algorithm, xmlSecBufferPtr buf); static void xmlSecNssX509CertDebugDump (CERTCertificate* cert, FILE* output); static void xmlSecNssX509CertDebugXmlDump (CERTCertificate* cert, FILE* output); /****************************************************************************** * * Internal NSS X509 data CTX * *****************************************************************************/ typedef struct _xmlSecNssX509DataCtx { CERTCertificate* keyCert; /* OWNED BY certsList */ CERTCertList* certsList; unsigned int numCerts; xmlSecNssX509CrlNodePtr crlsList; unsigned int numCrls; } xmlSecNssX509DataCtx, *xmlSecNssX509DataCtxPtr; /****************************************************************************** * * <dsig:X509Data/> processing (http://www.w3.org/TR/xmldsig-core/#sec-X509Data) * *****************************************************************************/ XMLSEC_KEY_DATA_DECLARE(NssX509Data, xmlSecNssX509DataCtx) #define xmlSecNssX509DataSize XMLSEC_KEY_DATA_SIZE(NssX509Data) static int xmlSecNssKeyDataX509Initialize (xmlSecKeyDataPtr data); static int xmlSecNssKeyDataX509Duplicate (xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src); static void xmlSecNssKeyDataX509Finalize (xmlSecKeyDataPtr data); static int xmlSecNssKeyDataX509XmlRead (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecNssKeyDataX509XmlWrite (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static void xmlSecNssKeyDataX509DebugDump (xmlSecKeyDataPtr data, FILE* output); static void xmlSecNssKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output); typedef struct _xmlSecNssKeyDataX509Context { xmlSecSize crtPos; xmlSecSize crtSize; xmlSecSize crlPos; xmlSecSize crlSize; } xmlSecNssDataX509Context; static int xmlSecNssKeyDataX509Read (xmlSecKeyDataPtr data, xmlSecKeyX509DataValuePtr x509Value, xmlSecKeysMngrPtr keysMngr, unsigned int flags); static int xmlSecNssKeyDataX509Write (xmlSecKeyDataPtr data, xmlSecKeyX509DataValuePtr x509Value, int content, void* context); static xmlSecKeyDataKlass xmlSecNssKeyDataX509Klass = { sizeof(xmlSecKeyDataKlass), xmlSecNssX509DataSize, /* data */ xmlSecNameX509Data, xmlSecKeyDataUsageReadFromFile | xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, /* xmlSecKeyDataUsage usage; */ xmlSecHrefX509Data, /* const xmlChar* href; */ xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ /* constructors/destructor */ xmlSecNssKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */ xmlSecNssKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ xmlSecNssKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */ NULL, /* xmlSecKeyDataGenerateMethod generate; */ /* get info */ NULL, /* xmlSecKeyDataGetTypeMethod getType; */ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */ NULL, /* DEPRECATED xmlSecKeyDataGetIdentifier getIdentifier; */ /* read/write */ xmlSecNssKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ xmlSecNssKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ /* debug */ xmlSecNssKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ xmlSecNssKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ /* reserved for the future */ NULL, /* void* reserved0; */ NULL, /* void* reserved1; */ }; /** * @brief The NSS X509 key data klass. * @details The NSS X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data). * @return the X509 data klass. */ xmlSecKeyDataId xmlSecNssKeyDataX509GetKlass(void) { return(&xmlSecNssKeyDataX509Klass); } /** * @brief Gets the certificate from which the key was extracted. * @param data the pointer to X509 key data. * * * @return the key's certificate or NULL if key data was not used for key * extraction or an error occurs. */ CERTCertificate* xmlSecNssKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); return(ctx->keyCert); } CERTCertList* xmlSecNssKeyDataX509GetCerts(xmlSecKeyDataPtr data) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); return(ctx->certsList); } xmlSecNssX509CrlNodePtr xmlSecNssKeyDataX509GetCrls(xmlSecKeyDataPtr data) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); return(ctx->crlsList); } static CERTCertListNode* xmlSecNssKeyDataX509FindCertInternal(xmlSecNssX509DataCtxPtr ctx, CERTCertificate* cert) { CERTCertListNode* cur; xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(cert != NULL, NULL); if(ctx->certsList == NULL) { return(NULL); } for(cur = CERT_LIST_HEAD(ctx->certsList); !CERT_LIST_END(cur, ctx->certsList); cur = CERT_LIST_NEXT(cur)) { if((cur->cert == cert) || (CERT_CompareCerts(cert, cur->cert) == PR_TRUE)) { return(cur); } } return(NULL); } static int xmlSecNssKeyDataX509AddCertInternal(xmlSecNssX509DataCtxPtr ctx, CERTCertificate* cert, int isKeyCert) { CERTCertListNode* existingCertNode; SECStatus rv; xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(cert != NULL, -1); if(ctx->certsList == NULL) { ctx->certsList = CERT_NewCertList(); if(ctx->certsList == NULL) { xmlSecNssError("CERT_NewCertList", NULL); return(-1); } } /* we don't want duplicates */ existingCertNode = xmlSecNssKeyDataX509FindCertInternal(ctx, cert); if(existingCertNode != NULL) { CERT_RemoveCertListNode(existingCertNode); --ctx->numCerts; } /* ensure that key cert is the first one */ if(isKeyCert != 0) { rv = CERT_AddCertToListHead(ctx->certsList, cert); if(rv != SECSuccess) { xmlSecNssError("CERT_AddCertToListHead", NULL); return(-1); } } else { rv = CERT_AddCertToListTail(ctx->certsList, cert); if(rv != SECSuccess) { xmlSecNssError("CERT_AddCertToListTail", NULL); return(-1); } } ++ctx->numCerts; /* done */ return(0); } /** * @brief Adds certificate to the X509 key data and sets the it as the key's * @param data the pointer to X509 key data. * @param cert the pointer to NSS X509 certificate. * * certificate in @p data. On success, the @p data owns the cert. * * @return 0 on success or a negative value if an error occurs. */ int xmlSecNssKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, CERTCertificate* cert) { xmlSecNssX509DataCtxPtr ctx; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1); xmlSecAssert2(cert != NULL, -1); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); /* check if for some reasons same cert is used */ if((ctx->keyCert != NULL) && ((ctx->keyCert == cert) || (CERT_CompareCerts(cert, ctx->keyCert) == PR_TRUE))) { CERT_DestroyCertificate(cert); /* caller expects data to own the cert on success. */ return(0); } xmlSecAssert2(ctx->keyCert == NULL, -1); ret = xmlSecNssKeyDataX509AddCertInternal(ctx, cert, 1); /* key cert */ if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AddCertInternal", NULL); return(-1); } /* cert is now owned by data, we can't fail or there will be a double free */ ctx->keyCert = cert; return(0); } /** * @brief Adds certificate to the X509 key data. * @param data the pointer to X509 key data. * @param cert the pointer to NSS X509 certificate. * @return 0 on success or a negative value if an error occurs. */ int xmlSecNssKeyDataX509AdoptCert(xmlSecKeyDataPtr data, CERTCertificate* cert) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1); xmlSecAssert2(cert != NULL, -1); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); /* pkcs12 files sometime have key cert twice: as the key cert and as the cert in the chain */ if((ctx->keyCert != NULL) && ((ctx->keyCert == cert) || (CERT_CompareCerts(cert, ctx->keyCert) == PR_TRUE))) { CERT_DestroyCertificate(cert); /* caller expects data to own the cert on success. */ return(0); } return(xmlSecNssKeyDataX509AddCertInternal(ctx, cert, 0)); /* not a key cert */ } /** * @brief Gets a certificate from X509 key data. * @param data the pointer to X509 key data. * @param pos the desired certificate position. * * * @return the pointer to certificate or NULL if @p pos is larger than the * number of certificates in @p data or an error occurs. */ CERTCertificate* xmlSecNssKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) { xmlSecNssX509DataCtxPtr ctx; CERTCertListNode* cur; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->certsList != NULL, NULL); xmlSecAssert2(pos < ctx->numCerts, NULL); /* to ensure that key cert is always first we put it at the top of the list * in xmlSecNssKeyDataX509AddCertInternal */ for(cur = CERT_LIST_HEAD(ctx->certsList); !CERT_LIST_END(cur, ctx->certsList); cur = CERT_LIST_NEXT(cur)) { if(pos <= 0) { return(cur->cert); } --pos; } /* not found: should not be here */ return (NULL); } /** * @brief Gets the number of certificates in @p data. * @param data the pointer to X509 key data. * @return te number of certificates in @p data. */ xmlSecSize xmlSecNssKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), 0); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(ctx->numCerts); } /** * @brief Adds CRL to the X509 key data. * @param data the pointer to X509 key data. * @param crl the pointer to NSS X509 CRL. * @return 0 on success or a negative value if an error occurs. */ int xmlSecNssKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, CERTSignedCrl* crl) { xmlSecNssX509DataCtxPtr ctx; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1); xmlSecAssert2(crl != NULL, -1); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); ret = xmlSecNssX509CrlListAdoptCrl(&(ctx->crlsList), crl); if(ret < 0) { xmlSecInternalError("xmlSecNssX509CrlListAdoptCrl", xmlSecKeyDataGetName(data)); return(-1); } /* keep the counter updated */ ctx->numCrls++; return(0); } /** * @brief Gets a CRL from X509 key data. * @param data the pointer to X509 key data. * @param pos the desired CRL position. * * * @return the pointer to CRL or NULL if @p pos is larger than the * number of CRLs in @p data or an error occurs. */ CERTSignedCrl * xmlSecNssKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) { xmlSecNssX509DataCtxPtr ctx; xmlSecNssX509CrlNodePtr head; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), NULL); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->crlsList != NULL, NULL); xmlSecAssert2(pos < ctx->numCrls, NULL); head = ctx->crlsList; while (pos > 0) { head = head->next; pos--; } return (head->crl); } /** * @brief Gets the number of CRLs in @p data. * @param data the pointer to X509 key data. * @return te number of CRLs in @p data. */ xmlSecSize xmlSecNssKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), 0); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(ctx->numCrls); } static int xmlSecNssKeyDataX509Initialize(xmlSecKeyDataPtr data) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); memset(ctx, 0, sizeof(xmlSecNssX509DataCtx)); return(0); } static void xmlSecNssKeyDataX509Finalize(xmlSecKeyDataPtr data) { xmlSecNssX509DataCtxPtr ctx; xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id)); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert(ctx != NULL); if(ctx->certsList != NULL) { CERT_DestroyCertList(ctx->certsList); ctx->certsList = NULL; } if(ctx->crlsList != NULL) { xmlSecNssX509CrlListDestroy(ctx->crlsList); ctx->crlsList = NULL; } memset(ctx, 0, sizeof(xmlSecNssX509DataCtx)); } static int xmlSecNssKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { xmlSecNssX509DataCtxPtr ctxSrc, ctxDst; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataX509Id), -1); xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataX509Id), -1); ctxSrc = xmlSecNssX509DataGetCtx(src); xmlSecAssert2(ctxSrc != NULL, -1); /* dst should not have any data */ ctxDst = xmlSecNssX509DataGetCtx(dst); xmlSecAssert2(ctxDst != NULL, -1); xmlSecAssert2(ctxDst->keyCert == NULL, -1); xmlSecAssert2(ctxDst->certsList == NULL, -1); xmlSecAssert2(ctxDst->crlsList == NULL, -1); /* crts */ if(ctxSrc->certsList != NULL) { CERTCertListNode* cur; CERTCertificate* cert; for(cur = CERT_LIST_HEAD(ctxSrc->certsList); !CERT_LIST_END(cur, ctxSrc->certsList); cur = CERT_LIST_NEXT(cur)) { xmlSecAssert2(cur->cert != NULL, -1); cert = CERT_DupCertificate(cur->cert); if(cert == NULL) { xmlSecNssError("CERT_DupCertificate", NULL); return(-1); } /* handle key cert */ if(cur->cert == ctxSrc->keyCert) { ret = xmlSecNssKeyDataX509AdoptKeyCert(dst, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptKeyCert", NULL); CERT_DestroyCertificate(cert); return(-1); } } else { ret = xmlSecNssKeyDataX509AdoptCert(dst, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCert", NULL); CERT_DestroyCertificate(cert); return(-1); } } /* cert is owned by dst now */ } } /* crls */ if(ctxSrc->crlsList != NULL) { ctxDst->crlsList = xmlSecNssX509CrlListDuplicate(ctxSrc->crlsList); if(ctxDst->crlsList == NULL) { xmlSecInternalError("xmlSecNssX509CrlListDuplicate", NULL); return(-1); } ctxDst->numCrls = ctxSrc->numCrls; } /* done */ return(0); } static int xmlSecNssKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataPtr data; int ret; xmlSecAssert2(id == xmlSecNssKeyDataX509Id, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id)", xmlSecKeyDataKlassGetName(id)); return(-1); } ret = xmlSecKeyDataX509XmlRead(key, data, node, keyInfoCtx, xmlSecNssKeyDataX509Read); if(ret < 0) { xmlSecInternalError("xmlSecKeyDataX509XmlRead", xmlSecKeyDataKlassGetName(id)); xmlSecKeyDataDestroy(data); return(-1); } /* did we find the key already? */ if(xmlSecKeyGetValue(key) != NULL) { xmlSecKeyDataDestroy(data); return(0); } ret = xmlSecNssVerifyAndAdoptX509KeyData(key, data, keyInfoCtx); if(ret < 0) { xmlSecInternalError("xmlSecNssVerifyAndAdoptX509KeyData", xmlSecKeyDataKlassGetName(id)); xmlSecKeyDataDestroy(data); return(-1); } else if(ret != 1) { /* no errors but key was not found and data was not adopted */ xmlSecKeyDataDestroy(data); return(0); } data = NULL; /* owned by data now */ /* success */ return(0); } static int xmlSecNssKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataPtr data; xmlSecNssDataX509Context context; int ret; xmlSecAssert2(id == xmlSecNssKeyDataX509Id, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); /* get x509 data */ data = xmlSecKeyGetData(key, id); if(data == NULL) { /* no x509 data in the key */ return(0); } /* setup context */ context.crtPos = context.crlPos = 0; context.crtSize = xmlSecNssKeyDataX509GetCertsSize(data); context.crlSize = xmlSecNssKeyDataX509GetCrlsSize(data); ret = xmlSecKeyDataX509XmlWrite(data, node, keyInfoCtx, xmlSecBase64GetDefaultLineSize(), 1, /* add line breaks */ xmlSecNssKeyDataX509Write, &context); if(ret < 0) { xmlSecInternalError3("xmlSecKeyDataX509XmlWrite", xmlSecKeyDataKlassGetName(id), "crtSize=" XMLSEC_SIZE_FMT "; crlSize=" XMLSEC_SIZE_FMT, context.crtSize, context.crlSize); return(-1); } /* success */ return(0); } static void xmlSecNssKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) { CERTCertificate* cert; xmlSecSize size, pos; xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id)); xmlSecAssert(output != NULL); fprintf(output, "=== X509 Data:\n"); cert = xmlSecNssKeyDataX509GetKeyCert(data); if(cert != NULL) { fprintf(output, "==== Key Certificate:\n"); xmlSecNssX509CertDebugDump(cert, output); } size = xmlSecNssKeyDataX509GetCertsSize(data); for(pos = 0; pos < size; ++pos) { cert = xmlSecNssKeyDataX509GetCert(data, pos); if(cert == NULL) { xmlSecInternalError2("xmlSecNssKeyDataX509GetCert", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, pos); return; } fprintf(output, "==== Certificate:\n"); xmlSecNssX509CertDebugDump(cert, output); } /* we don't print out crls */ } static void xmlSecNssKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { CERTCertificate* cert; xmlSecSize size, pos; xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id)); xmlSecAssert(output != NULL); fprintf(output, "<X509Data>\n"); cert = xmlSecNssKeyDataX509GetKeyCert(data); if(cert != NULL) { fprintf(output, "<KeyCertificate>\n"); xmlSecNssX509CertDebugXmlDump(cert, output); fprintf(output, "</KeyCertificate>\n"); } size = xmlSecNssKeyDataX509GetCertsSize(data); for(pos = 0; pos < size; ++pos) { cert = xmlSecNssKeyDataX509GetCert(data, pos); if(cert == NULL) { xmlSecInternalError2("xmlSecNssKeyDataX509GetCert", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, pos); return; } fprintf(output, "<Certificate>\n"); xmlSecNssX509CertDebugXmlDump(cert, output); fprintf(output, "</Certificate>\n"); } /* we don't print out crls */ fprintf(output, "</X509Data>\n"); } /* xmlSecKeyDataX509Read: 0 on success and a negative value otherwise */ static int xmlSecNssKeyDataX509Read(xmlSecKeyDataPtr data, xmlSecKeyX509DataValuePtr x509Value, xmlSecKeysMngrPtr keysMngr, unsigned int flags) { CERTCertificate* cert = NULL; CERTSignedCrl* crl = NULL; int ret; int res = -1; xmlSecAssert2(data != NULL, -1); xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1); xmlSecAssert2(x509Value != NULL, -1); xmlSecAssert2(keysMngr != NULL, -1); /* read CRT or CRL */ if(xmlSecBufferGetSize(&(x509Value->cert)) > 0) { cert = xmlSecNssX509CertDerRead(CERT_GetDefaultCertDB(), xmlSecBufferGetData(&(x509Value->cert)), xmlSecBufferGetSize(&(x509Value->cert)) ); if(cert == NULL) { xmlSecInternalError("xmlSecNssX509CertDerRead", xmlSecKeyDataGetName(data)); goto done; } } if(xmlSecBufferGetSize(&(x509Value->crl)) > 0) { crl = xmlSecNssX509CrlDerRead(xmlSecBufferGetData(&(x509Value->crl)), xmlSecBufferGetSize(&(x509Value->crl)), flags); if(crl == NULL) { xmlSecInternalError("xmlSecNssX509CrlDerRead", xmlSecKeyDataGetName(data)); goto done; } } /* if there is no cert in the X509Data node then try to find one */ if(cert == NULL) { xmlSecKeyDataStorePtr x509Store; int stopOnUnknownCert = 0; x509Store = xmlSecKeysMngrGetDataStore(keysMngr, xmlSecNssX509StoreId); if(x509Store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetDataStore", xmlSecKeyDataGetName(data)); goto done; } /* determine what to do */ if((flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) { stopOnUnknownCert = 1; } cert = xmlSecNssX509StoreFindCertByValue(x509Store, x509Value); if((cert == NULL) && (stopOnUnknownCert != 0)) { xmlSecOtherError(XMLSEC_ERRORS_R_CERT_NOT_FOUND, xmlSecKeyDataGetName(data), "cert lookup"); goto done; } } /* if we found a cert or a crl, then add it to the data */ if(cert != NULL) { ret = xmlSecNssKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCert", xmlSecKeyDataGetName(data)); goto done; } cert = NULL; /* owned by data now */ } if(crl != NULL) { ret = xmlSecNssKeyDataX509AdoptCrl(data, crl); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCrl", xmlSecKeyDataGetName(data)); goto done; } crl = NULL; /* owned by data now */ } /* success */ res = 0; done: /* cleanup */ if(cert != NULL) { CERT_DestroyCertificate(cert); } if(crl != NULL) { SEC_DestroyCrl(crl); } return(res); } /* xmlSecKeyDataX509Write: returns 1 on success, 0 if no more certs/crls are available, * or a negative value if an error occurs. */ static int xmlSecNssKeyDataX509Write(xmlSecKeyDataPtr data, xmlSecKeyX509DataValuePtr x509Value, int content, void* context) { xmlSecNssDataX509Context* ctx; int ret; xmlSecAssert2(data != NULL, -1); xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1); xmlSecAssert2(x509Value != NULL, -1); xmlSecAssert2(context != NULL, -1); ctx = (xmlSecNssDataX509Context*)context; if(ctx->crtPos < ctx->crtSize) { /* write cert */ CERTCertificate* cert = xmlSecNssKeyDataX509GetCert(data, ctx->crtPos); if(cert == NULL) { xmlSecInternalError2("xmlSecNssKeyDataX509GetCert", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crtPos); return(-1); } if (XMLSEC_X509DATA_HAS_EMPTY_NODE(content, XMLSEC_X509DATA_CERTIFICATE_NODE)) { ret = xmlSecNssX509SECItemWrite(&(cert->derCert), &(x509Value->cert)); if(ret < 0) { xmlSecInternalError2("xmlSecNssX509SECItemWrite(cert)", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crtPos); return(-1); } } if (XMLSEC_X509DATA_HAS_EMPTY_NODE(content, XMLSEC_X509DATA_SKI_NODE)) { SECItem ski = { siBuffer, NULL, 0 }; SECStatus rv; rv = CERT_FindSubjectKeyIDExtension(cert, &ski); if (rv != SECSuccess) { xmlSecNssError("CERT_FindSubjectKeyIDExtension", NULL); return(-1); } ret = xmlSecNssX509SECItemWrite(&ski, &(x509Value->ski)); if(ret < 0) { xmlSecInternalError2("xmlSecNssX509SECItemWrite(ski)", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crtPos); SECITEM_FreeItem(&ski, PR_FALSE); return(-1); } SECITEM_FreeItem(&ski, PR_FALSE); } if (XMLSEC_X509DATA_HAS_EMPTY_NODE(content, XMLSEC_X509DATA_SUBJECTNAME_NODE)) { xmlSecAssert2(x509Value->subject == NULL, -1); x509Value->subject = xmlSecNssX509NameWrite(&(cert->subject)); if(x509Value->subject == NULL) { xmlSecInternalError2("xmlSecNssX509NameWrite(subject)", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crtPos); return(-1); } } if (XMLSEC_X509DATA_HAS_EMPTY_NODE(content, XMLSEC_X509DATA_ISSUERSERIAL_NODE)) { xmlSecAssert2(x509Value->issuerName == NULL, -1); xmlSecAssert2(x509Value->issuerSerial == NULL, -1); x509Value->issuerName = xmlSecNssX509NameWrite(&(cert->issuer)); if(x509Value->issuerName == NULL) { xmlSecInternalError2("xmlSecNssX509NameWrite(ssuer)", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crtPos); return(-1); } x509Value->issuerSerial = xmlSecX509SerialNumberWrite(cert->serialNumber.data, (xmlSecSize)cert->serialNumber.len); if(x509Value->issuerSerial == NULL) { xmlSecInternalError2("xmlSecX509SerialNumberWrite(serialNumber))", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crtPos); return(-1); } } if((XMLSEC_X509DATA_HAS_EMPTY_NODE(content, XMLSEC_X509DATA_DIGEST_NODE)) && (x509Value->digestAlgorithm != NULL)) { ret = xmlSecNssX509DigestWrite(cert, x509Value->digestAlgorithm, &(x509Value->digest)); if(ret < 0) { xmlSecInternalError2("xmlSecNssX509DigestWrite", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crtPos); return(-1); } } ++ctx->crtPos; } else if(ctx->crlPos < ctx->crlSize) { /* write crl */ CERTSignedCrl* crl = xmlSecNssKeyDataX509GetCrl(data, ctx->crlPos); if(crl == NULL) { xmlSecInternalError2("xmlSecNssKeyDataX509GetCrl", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crlPos); return(-1); } if((content & XMLSEC_X509DATA_CRL_NODE) != 0) { ret = xmlSecNssX509SECItemWrite(crl->derCrl, &(x509Value->crl)); if(ret < 0) { xmlSecInternalError2("xmlSecNssX509SECItemWrite(crl)", xmlSecKeyDataGetName(data), "pos=" XMLSEC_SIZE_FMT, ctx->crlPos); return(-1); } } ++ctx->crlPos; } else { /* no more certs or crls */ return(0); } /* success */ return(1); } /* returns 1 if cert was found and verified and also data was adopted, 0 if not, or negative value if an error occurs */ static int xmlSecNssVerifyAndAdoptX509KeyData(xmlSecKeyPtr key, xmlSecKeyDataPtr data, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecNssX509DataCtxPtr ctx; xmlSecKeyDataStorePtr x509Store; xmlSecKeyDataPtr keyValue; CERTCertificate* cert; CERTCertificate* keyCert; int ret; SECStatus status; PRTime notBefore, notAfter; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataX509Id), -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); ctx = xmlSecNssX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->keyCert == NULL, -1); if((ctx->certsList == NULL) || (xmlSecKeyGetValue(key) != NULL)) { /* no certs or key was already found -> nothing to do (this shouldn't really happen) */ return(0); } /* lets find a cert we can verify */ x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecNssX509StoreId); if(x509Store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetDataStore", xmlSecKeyDataGetName(data)); return(-1); } cert = xmlSecNssX509StoreVerify(x509Store, ctx->certsList, keyInfoCtx); if(cert == NULL) { /* check if we want to fail if cert is not found */ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_INVALID_CERT) != 0) { xmlSecOtherError(XMLSEC_ERRORS_R_CERT_NOT_FOUND, xmlSecKeyDataGetName(data), NULL); return(-1); } return(0); } /* set cert into the x509 data, we don't know if the cert is already in KeyData or not * so assume we need to add it again. */ keyCert = CERT_DupCertificate(cert); if(keyCert == NULL) { xmlSecNssError("CERT_DupCertificate", xmlSecKeyDataGetName(data)); return(-1); } ret = xmlSecNssKeyDataX509AdoptKeyCert(data, keyCert); if(ret < 0) { xmlSecInternalError("xmlSecNssX509CertGetKey", xmlSecKeyDataGetName(data)); CERT_DestroyCertificate(keyCert); return(-1); } cert = keyCert = NULL; /* we should be using ctx->keyCert for everything */ /* extract key from cert and verify that the key matches our expectations */ keyValue = xmlSecNssX509CertGetKey(ctx->keyCert); if(keyValue == NULL) { xmlSecInternalError("xmlSecNssX509CertGetKey", xmlSecKeyDataGetName(data)); return(-1); } if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), keyValue) != 1) { xmlSecInternalError("xmlSecKeyReqMatchKeyValue", xmlSecKeyDataGetName(data)); xmlSecKeyDataDestroy(keyValue); return(-1); } ret = xmlSecKeySetValue(key, keyValue); if(ret < 0) { xmlSecInternalError("xmlSecKeySetValue", xmlSecKeyDataGetName(data)); xmlSecKeyDataDestroy(keyValue); return(-1); } keyValue = NULL; /* owned by key now */ /* copy cert not before / not after times from the cert */ status = CERT_GetCertTimes(ctx->keyCert, ¬Before, ¬After); if (status == SECSuccess) { ret = xmlSecNssX509CertGetTime(¬Before, &(key->notValidBefore)); if(ret < 0) { xmlSecInternalError("xmlSecNssX509CertGetTime(notValidBefore)", xmlSecKeyDataGetName(data)); return(-1); } ret = xmlSecNssX509CertGetTime(¬After, &(key->notValidAfter)); if(ret < 0) { xmlSecInternalError("xmlSecNssX509CertGetTime(notValidAfter)", xmlSecKeyDataGetName(data)); return(-1); } } else { key->notValidBefore = key->notValidAfter = 0; } /* THIS MUST BE THE LAST THING WE DO: add data to the key * if we do it sooner and fail later then both the caller and the key will free data * which would lead to double free */ ret = xmlSecKeyAdoptData(key, data); if(ret < 0) { xmlSecInternalError("xmlSecKeyAdoptData", xmlSecKeyDataGetName(data)); return(-1); } /* success: cert found and data was adopted */ return(1); } int xmlSecNssX509CertGetTime(PRTime* t, time_t* res) { xmlSecAssert2(t != NULL, -1); xmlSecAssert2(res != NULL, -1); /* PRTime is the number of microseconds since the epoch, convert to seconds */ (*res) = (time_t)(*t / PR_USEC_PER_SEC); return(0); } /** * @brief Extracts public key from the @p cert. * @param cert the certificate. * @return public key value or NULL if an error occurs. */ xmlSecKeyDataPtr xmlSecNssX509CertGetKey(CERTCertificate* cert) { xmlSecKeyDataPtr data; SECKEYPublicKey *pubkey = NULL; SECKEYPrivateKey *privkey = NULL; xmlSecAssert2(cert != NULL, NULL); pubkey = CERT_ExtractPublicKey(cert); if(pubkey == NULL) { xmlSecNssError("CERT_ExtractPublicKey", NULL); return(NULL); } /* see if we can find private key too for this cert */ privkey = PK11_FindKeyByAnyCert(cert, NULL); data = xmlSecNssPKIAdoptKey(privkey, pubkey); if(data == NULL) { xmlSecInternalError("xmlSecNssPKIAdoptKey", NULL); SECKEY_DestroyPublicKey(pubkey); if(privkey != NULL) { SECKEY_DestroyPrivateKey(privkey); } return(NULL); } return(data); } static int xmlSecNssX509SECItemWrite(SECItem* secItem, xmlSecBufferPtr buf) { xmlSecAssert2(secItem != NULL, -1); xmlSecAssert2(buf != NULL, -1); if((secItem->data != NULL) && (secItem->len > 0)) { int ret; ret = xmlSecBufferSetData(buf, secItem->data, secItem->len); if(ret < 0) { xmlSecInternalError2("xmlSecBufferSetData", NULL, "size=%u", secItem->len); return(-1); } } else { xmlSecBufferEmpty(buf); } return(0); } CERTCertificate* xmlSecNssX509CertDerRead(CERTCertDBHandle *handle, xmlSecByte* buf, xmlSecSize size) { CERTCertificate *cert; SECItem derCert = { siBuffer, NULL, 0 }; xmlSecAssert2(handle != NULL, NULL); xmlSecAssert2(buf != NULL, NULL); xmlSecAssert2(size > 0, NULL); derCert.data = buf; XMLSEC_SAFE_CAST_SIZE_TO_UINT(size, derCert.len, return(NULL), NULL); /* decode cert and import to temporary cert db */ cert = CERT_NewTempCertificate(handle, &derCert, NULL, PR_FALSE, PR_TRUE); if(cert == NULL) { xmlSecNssError("CERT_NewTempCertificate", NULL); return(NULL); } return(cert); } CERTSignedCrl* xmlSecNssX509CrlDerRead(xmlSecByte* buf, xmlSecSize size, unsigned int flags) { CERTSignedCrl *crl = NULL; SECItem derCrl = { siBuffer, NULL, 0 }; PK11SlotInfo *slot = NULL; PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS; xmlSecAssert2(buf != NULL, NULL); xmlSecAssert2(size > 0, NULL); derCrl.data = buf; XMLSEC_SAFE_CAST_SIZE_TO_UINT(size, derCrl.len, return(NULL), NULL); /* we're importing a CRL, it is ok to use the internal slot. * crlutil does it :) */ slot = xmlSecNssGetInternalKeySlot(); if (slot == NULL) { xmlSecInternalError("xmlSecNssGetInternalKeySlot", NULL); return NULL; } if((flags & XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS) != 0) { importOptions |= CRL_IMPORT_BYPASS_CHECKS; } crl = PK11_ImportCRL(slot, &derCrl, NULL, SEC_CRL_TYPE, NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS); if(crl == NULL) { xmlSecNssError("PK11_ImportCRL", NULL); PK11_FreeSlot(slot); return(NULL); } PK11_FreeSlot(slot); return(crl); } typedef struct _xmlSecNssX509CertReadResult { PLArenaPool* arena; SECItem cert; } xmlSecNssX509CertReadResult; static SECStatus xmlSecNssX509CertReadCallback(void *arg, SECItem **certs, int numcerts) { xmlSecNssX509CertReadResult* result = (xmlSecNssX509CertReadResult *)arg; xmlSecAssert2(result != NULL, SECFailure); xmlSecAssert2(result->arena != NULL, SECFailure); xmlSecAssert2(numcerts > 0, SECFailure); xmlSecAssert2(certs != NULL, SECFailure); xmlSecAssert2((*certs) != NULL, SECFailure); return SECITEM_CopyItem(result->arena, &(result->cert), *certs); } CERTCertificate* xmlSecNssX509CertPemRead(CERTCertDBHandle *handle, xmlSecByte* buf, xmlSecSize size) { xmlSecNssX509CertReadResult result; CERTCertificate *cert = NULL; int len; SECStatus rv; xmlSecAssert2(handle != NULL, NULL); xmlSecAssert2(buf != NULL, NULL); xmlSecAssert2(size > 0, NULL); XMLSEC_SAFE_CAST_SIZE_TO_INT(size, len, return(NULL), NULL); result.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if(result.arena == NULL) { xmlSecNssError("PORT_NewArena", NULL); return(NULL); } rv = CERT_DecodeCertPackage((char*)buf, len, xmlSecNssX509CertReadCallback, (void *)(&result)); if(rv != SECSuccess) { xmlSecNssError("CERT_DecodeCertPackage", NULL); PORT_FreeArena(result.arena, PR_FALSE); return(NULL); } cert = CERT_NewTempCertificate(handle, &(result.cert), NULL, PR_FALSE, PR_TRUE); if(cert == NULL) { xmlSecNssError("CERT_NewTempCertificate", NULL); PORT_FreeArena(result.arena, PR_FALSE); return(NULL); } /* done */ PORT_FreeArena(result.arena, PR_FALSE); return (cert); } static xmlChar* xmlSecNssX509NameWrite(CERTName* nm) { xmlChar *res = NULL; char *str; xmlSecAssert2(nm != NULL, NULL); str = CERT_NameToAscii(nm); if (str == NULL) { xmlSecNssError("CERT_NameToAscii", NULL); return(NULL); } res = xmlStrdup(BAD_CAST str); if(res == NULL) { xmlSecStrdupError(BAD_CAST str, NULL); PORT_Free(str); return(NULL); } PORT_Free(str); return(res); } static int xmlSecNssX509DigestWrite(CERTCertificate* cert, const xmlChar* algorithm, xmlSecBufferPtr buf) { SECOidTag digestAlg; xmlSecByte digest[XMLSEC_NSS_MAX_DIGEST_SIZE]; unsigned int digestLen; SECStatus status; int ret; xmlSecAssert2(cert != NULL, -1); xmlSecAssert2(buf != NULL, -1); if((cert->derCert.type != siBuffer) || (cert->derCert.data == NULL) || (cert->derCert.len <= 0)) { xmlSecInternalError("cert->derCert is invalid", NULL); return(-1); } digestAlg = xmlSecNssGetDigestFromHref(algorithm); if(digestAlg == SEC_OID_UNKNOWN) { xmlSecInternalError("xmlSecNssGetDigestFromHref", NULL); return(-1); } digestLen = HASH_ResultLenByOidTag(digestAlg); if((digestLen == 0) || (digestLen > sizeof(digest))) { xmlSecNssError3("HASH_ResultLenByOidTag", NULL, "digestAlgOid=%d; len=%u", (int)digestAlg, digestLen); return(-1); } status = PK11_HashBuf(digestAlg, digest, cert->derCert.data, (PRInt32)cert->derCert.len); if (status != SECSuccess) { xmlSecNssError2("PK11_HashBuf(cert->derCert)", NULL, "digestAlgOid=%d", (int)digestAlg); return(-1); } ret = xmlSecBufferSetData(buf, digest, digestLen); if(ret < 0) { xmlSecInternalError("xmlSecBufferSetData", NULL); return(-1); } /* success */ return(0); } static void xmlSecNssX509CertDebugDump(CERTCertificate* cert, FILE* output) { SECItem *sn; unsigned int i; xmlSecAssert(cert != NULL); xmlSecAssert(output != NULL); fprintf(output, "==== Subject Name: %s\n", cert->subjectName); fprintf(output, "==== Issuer Name: %s\n", cert->issuerName); sn = &(cert->serialNumber); for (i = 0; i < sn->len; i++) { if (i != sn->len - 1) { fprintf(output, "%02x:", sn->data[i]); } else { fprintf(output, "%02x", sn->data[i]); } } fprintf(output, "\n"); } static void xmlSecNssX509CertDebugXmlDump(CERTCertificate* cert, FILE* output) { SECItem *sn; unsigned int i; xmlSecAssert(cert != NULL); xmlSecAssert(output != NULL); fprintf(output, "<SubjectName>"); xmlSecPrintXmlString(output, BAD_CAST cert->subjectName); fprintf(output, "</SubjectName>\n"); fprintf(output, "<IssuerName>"); xmlSecPrintXmlString(output, BAD_CAST cert->issuerName); fprintf(output, "</IssuerName>\n"); fprintf(output, "<SerialNumber>"); sn = &(cert->serialNumber); for (i = 0; i < sn->len; i++) { if (i != sn->len - 1) { fprintf(output, "%02x:", sn->data[i]); } else { fprintf(output, "%02x", sn->data[i]); } } fprintf(output, "</SerialNumber>\n"); } xmlSecNssX509CrlNodePtr xmlSecNssX509CrlListDuplicate(xmlSecNssX509CrlNodePtr head) { xmlSecNssX509CrlNodePtr newHead = NULL; xmlSecNssX509CrlNodePtr cur; CERTSignedCrl* crl; int ret; xmlSecAssert2(head != NULL, NULL); for(cur = head; cur != NULL; cur = cur->next) { xmlSecAssert2(cur->crl != NULL, NULL); crl = SEC_DupCrl(cur->crl); if(crl == NULL) { xmlSecNssError("SEC_DupCrl", NULL); xmlSecNssX509CrlListDestroy(newHead); return(NULL); } ret = xmlSecNssX509CrlListAdoptCrl(&newHead, crl); if(ret < 0) { xmlSecInternalError("xmlSecNssX509CrlListAdoptCrl", NULL); SEC_DestroyCrl(crl); xmlSecNssX509CrlListDestroy(newHead); return(NULL); } /* crl is owned by newHead now */ } /* done */ return(newHead); } void xmlSecNssX509CrlListDestroy(xmlSecNssX509CrlNodePtr head) { xmlSecNssX509CrlNodePtr tmp; while(head != NULL) { tmp = head->next; SEC_DestroyCrl(head->crl); PR_Free(head); head = tmp; } } int xmlSecNssX509CrlListAdoptCrl(xmlSecNssX509CrlNodePtr * head, CERTSignedCrl* crl) { xmlSecNssX509CrlNodePtr crlnode; xmlSecAssert2(head != NULL, -1); xmlSecAssert2(crl != NULL, -1); crlnode = (xmlSecNssX509CrlNodePtr)PR_Malloc(sizeof(xmlSecNssX509CrlNode)); if(crlnode == NULL) { xmlSecNssError("PR_Malloc", NULL); return(-1); } memset(crlnode, 0, sizeof(xmlSecNssX509CrlNode)); crlnode->next = (*head); crlnode->crl = crl; (*head) = crlnode; return(0); } /****************************************************************************** * * Raw X509 Certificate processing * * *****************************************************************************/ static int xmlSecNssKeyDataRawX509CertBinRead (xmlSecKeyDataId id, xmlSecKeyPtr key, const xmlSecByte* buf, xmlSecSize bufSize, xmlSecKeyInfoCtxPtr keyInfoCtx); static xmlSecKeyDataKlass xmlSecNssKeyDataRawX509CertKlass = { sizeof(xmlSecKeyDataKlass), sizeof(xmlSecKeyData), /* data */ xmlSecNameRawX509Cert, xmlSecKeyDataUsageReadFromFile | xmlSecKeyDataUsageRetrievalMethodNodeBin, /* xmlSecKeyDataUsage usage; */ xmlSecHrefRawX509Cert, /* const xmlChar* href; */ NULL, /* const xmlChar* dataNodeName; */ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ /* constructors/destructor */ NULL, /* xmlSecKeyDataInitializeMethod initialize; */ NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */ NULL, /* xmlSecKeyDataFinalizeMethod finalize; */ NULL, /* xmlSecKeyDataGenerateMethod generate; */ /* get info */ NULL, /* xmlSecKeyDataGetTypeMethod getType; */ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */ NULL, /* DEPRECATED xmlSecKeyDataGetIdentifier getIdentifier; */ /* read/write */ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ xmlSecNssKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ /* debug */ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ /* reserved for the future */ NULL, /* void* reserved0; */ NULL, /* void* reserved1; */ }; /** * @brief The raw X509 certificates key data klass. * @return raw X509 certificates key data klass. */ xmlSecKeyDataId xmlSecNssKeyDataRawX509CertGetKlass(void) { return(&xmlSecNssKeyDataRawX509CertKlass); } static int xmlSecNssKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key, const xmlSecByte* buf, xmlSecSize bufSize, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataPtr data; CERTCertificate* cert; int ret; xmlSecAssert2(id == xmlSecNssKeyDataRawX509CertId, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(buf != NULL, -1); xmlSecAssert2(bufSize > 0, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); cert = xmlSecNssX509CertDerRead(CERT_GetDefaultCertDB(), (xmlSecByte*)buf, bufSize); if(cert == NULL) { xmlSecInternalError("xmlSecNssX509CertDerRead", NULL); return(-1); } data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id)", xmlSecKeyDataKlassGetName(id)); CERT_DestroyCertificate(cert); return(-1); } ret = xmlSecNssKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCert", xmlSecKeyDataKlassGetName(id)); CERT_DestroyCertificate(cert); xmlSecKeyDataDestroy(data); return(-1); } cert = NULL; /* owned by data now */ ret = xmlSecNssVerifyAndAdoptX509KeyData(key, data, keyInfoCtx); if(ret < 0) { xmlSecInternalError("xmlSecNssVerifyAndAdoptX509KeyData", xmlSecKeyDataKlassGetName(id)); xmlSecKeyDataDestroy(data); return(-1); } else if(ret != 1) { /* no errors but key was not found and data was not adopted */ xmlSecKeyDataDestroy(data); return(0); } data = NULL; /* owned by data now */ /* success */ return(0); } #endif /* XMLSEC_NO_X509 */