/** * XMLSec library * * X509 support * * * This is free software; see Copyright file in the source * distribution for preciese wording. * * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved. * Copyright (C) 2003 Aleksey Sanin */ #include "globals.h" #ifndef XMLSEC_NO_X509 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__MINGW32__) # include "xmlsec-mingw.h" #endif /************************************************************************* * * X509 utility functions * ************************************************************************/ static int xmlSecMSCryptoX509DataNodeRead (xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509CertificateNodeRead (xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509CertificateNodeWrite (PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509SubjectNameNodeRead (xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509SubjectNameNodeWrite (PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509IssuerSerialNodeRead (xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509IssuerSerialNodeWrite (PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509SKINodeRead (xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509SKINodeWrite (PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509CRLNodeRead (xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoX509CRLNodeWrite (PCCRL_CONTEXT crl, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx); static PCCERT_CONTEXT xmlSecMSCryptoX509CertDerRead (const xmlSecByte* buf, xmlSecSize size); static PCCERT_CONTEXT xmlSecMSCryptoX509CertBase64DerRead (xmlChar* buf); static xmlChar* xmlSecMSCryptoX509CertBase64DerWrite (PCCERT_CONTEXT cert, int base64LineWrap); static PCCRL_CONTEXT xmlSecMSCryptoX509CrlDerRead (xmlSecByte* buf, xmlSecSize size, xmlSecKeyInfoCtxPtr keyInfoCtx); static PCCRL_CONTEXT xmlSecMSCryptoX509CrlBase64DerRead (xmlChar* buf, xmlSecKeyInfoCtxPtr keyInfoCtx); static xmlChar* xmlSecMSCryptoX509CrlBase64DerWrite (PCCRL_CONTEXT crl, int base64LineWrap); static xmlChar* xmlSecMSCryptoX509NameWrite(PCERT_NAME_BLOB nm); static int xmlSecMSCryptoASN1IntegerWrite (xmlNodePtr node, PCRYPT_INTEGER_BLOB num); static xmlChar* xmlSecMSCryptoX509SKIWrite (PCCERT_CONTEXT cert); static void xmlSecMSCryptoX509CertDebugDump (PCCERT_CONTEXT cert, FILE* output); static void xmlSecMSCryptoX509CertDebugXmlDump (PCCERT_CONTEXT cert, FILE* output); static int xmlSecMSCryptoX509CertGetTime (FILETIME t, time_t* res); /************************************************************************* * * Internal MSCrypto X509 data CTX * ************************************************************************/ typedef struct _xmlSecMSCryptoX509DataCtx xmlSecMSCryptoX509DataCtx, *xmlSecMSCryptoX509DataCtxPtr; struct _xmlSecMSCryptoX509DataCtx { PCCERT_CONTEXT keyCert; HCERTSTORE hMemStore; unsigned int numCerts; unsigned int numCrls; }; /************************************************************************** * * processing * * * The X509Data Element (http://www.w3.org/TR/xmldsig-core/#sec-X509Data) * * An X509Data element within KeyInfo contains one or more identifiers of keys * or X509 certificates (or certificates' identifiers or a revocation list). * The content of X509Data is: * * 1. At least one element, from the following set of element types; any of these may appear together or more than once iff (if and only if) each instance describes or is related to the same certificate: * 2. * * The X509IssuerSerial element, which contains an X.509 issuer * distinguished name/serial number pair that SHOULD be compliant * with RFC2253 [LDAP-DN], * * The X509SubjectName element, which contains an X.509 subject * distinguished name that SHOULD be compliant with RFC2253 [LDAP-DN], * * The X509SKI element, which contains the base64 encoded plain (i.e. * non-DER-encoded) value of a X509 V.3 SubjectKeyIdentifier extension. * * The X509Certificate element, which contains a base64-encoded [X509v3] * certificate, and * * Elements from an external namespace which accompanies/complements any * of the elements above. * * The X509CRL element, which contains a base64-encoded certificate * revocation list (CRL) [X509v3]. * * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that appear * MUST refer to the certificate or certificates containing the validation key. * All such elements that refer to a particular individual certificate MUST be * grouped inside a single X509Data element and if the certificate to which * they refer appears, it MUST also be in that X509Data element. * * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that relate to * the same key but different certificates MUST be grouped within a single * KeyInfo but MAY occur in multiple X509Data elements. * * All certificates appearing in an X509Data element MUST relate to the * validation key by either containing it or being part of a certification * chain that terminates in a certificate containing the validation key. * * No ordering is implied by the above constraints. * * Note, there is no direct provision for a PKCS#7 encoded "bag" of * certificates or CRLs. However, a set of certificates and CRLs can occur * within an X509Data element and multiple X509Data elements can occur in a * KeyInfo. Whenever multiple certificates occur in an X509Data element, at * least one such certificate must contain the public key which verifies the * signature. * * Schema Definition * * * * * * * * * * * * * * * * * * * * * * DTD * * * * * * * * * * * ----------------------------------------------------------------------- * * xmlSecMSCryptoX509DataCtx is located after xmlSecTransform * *************************************************************************/ #define xmlSecMSCryptoX509DataSize \ (sizeof(xmlSecKeyData) + sizeof(xmlSecMSCryptoX509DataCtx)) #define xmlSecMSCryptoX509DataGetCtx(data) \ ((xmlSecMSCryptoX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData))) static int xmlSecMSCryptoKeyDataX509Initialize (xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataX509Duplicate (xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src); static void xmlSecMSCryptoKeyDataX509Finalize (xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataX509XmlRead (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataX509XmlWrite (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static xmlSecKeyDataType xmlSecMSCryptoKeyDataX509GetType (xmlSecKeyDataPtr data); static const xmlChar* xmlSecMSCryptoKeyDataX509GetIdentifier (xmlSecKeyDataPtr data); static void xmlSecMSCryptoKeyDataX509DebugDump (xmlSecKeyDataPtr data, FILE* output); static void xmlSecMSCryptoKeyDataX509DebugXmlDump (xmlSecKeyDataPtr data, FILE* output); static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataX509Klass = { sizeof(xmlSecKeyDataKlass), xmlSecMSCryptoX509DataSize, /* data */ xmlSecNameX509Data, xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, /* xmlSecKeyDataUsage usage; */ xmlSecHrefX509Data, /* const xmlChar* href; */ xmlSecNodeX509Data, /* const xmlChar* dataNodeName; */ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ /* constructors/destructor */ xmlSecMSCryptoKeyDataX509Initialize, /* xmlSecKeyDataInitializeMethod initialize; */ xmlSecMSCryptoKeyDataX509Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ xmlSecMSCryptoKeyDataX509Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */ NULL, /* xmlSecKeyDataGenerateMethod generate; */ /* get info */ xmlSecMSCryptoKeyDataX509GetType, /* xmlSecKeyDataGetTypeMethod getType; */ NULL, /* xmlSecKeyDataGetSizeMethod getSize; */ xmlSecMSCryptoKeyDataX509GetIdentifier, /* xmlSecKeyDataGetIdentifier getIdentifier; */ /* read/write */ xmlSecMSCryptoKeyDataX509XmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ xmlSecMSCryptoKeyDataX509XmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ /* debug */ xmlSecMSCryptoKeyDataX509DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ xmlSecMSCryptoKeyDataX509DebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ /* reserved for the future */ NULL, /* void* reserved0; */ NULL, /* void* reserved1; */ }; /** * xmlSecMSCryptoKeyDataX509GetKlass: * * The MSCrypto X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data). * * Returns: the X509 data klass. */ xmlSecKeyDataId xmlSecMSCryptoKeyDataX509GetKlass(void) { return(&xmlSecMSCryptoKeyDataX509Klass); } /** * xmlSecMSCryptoKeyDataX509GetKeyCert: * @data: the pointer to X509 key data. * * Gets the certificate from which the key was extracted. * * Returns: the key's certificate or NULL if key data was not used for key * extraction or an error occurs. */ PCCERT_CONTEXT xmlSecMSCryptoKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); return(ctx->keyCert); } /** * xmlSecMSCryptoKeyDataX509AdoptKeyCert: * @data: the pointer to X509 key data. * @cert: the pointer to MSCRYPTO X509 certificate. * * Sets the key's certificate in @data. * * Returns: 0 on success or a negative value if an error occurs. */ int xmlSecMSCryptoKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT cert) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(cert != NULL, -1); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); if(ctx->keyCert != NULL) { CertFreeCertificateContext(ctx->keyCert); ctx->keyCert = 0; } ctx->keyCert = cert; return(0); } /** * xmlSecMSCryptoKeyDataX509AdoptCert: * @data: the pointer to X509 key data. * @cert: the pointer to MSCRYPTO X509 certificate. * * Adds certificate to the X509 key data. * * Returns: 0 on success or a negative value if an error occurs. */ int xmlSecMSCryptoKeyDataX509AdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT cert) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(cert != NULL, -1); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->hMemStore != 0, -1); if (!CertAddCertificateContextToStore(ctx->hMemStore, cert, CERT_STORE_ADD_ALWAYS, NULL)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CertAddCertificateContextToStore", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } CertFreeCertificateContext(cert); ctx->numCerts++; return(0); } /** * xmlSecMSCryptoKeyDataX509GetCert: * @data: the pointer to X509 key data. * @pos: the desired certificate position. * * Gets a certificate from X509 key data. * * Returns: the pointer to certificate or NULL if @pos is larger than the * number of certificates in @data or an error occurs. */ PCCERT_CONTEXT xmlSecMSCryptoKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) { xmlSecMSCryptoX509DataCtxPtr ctx; PCCERT_CONTEXT pCert = NULL; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->hMemStore != 0, NULL); xmlSecAssert2(ctx->numCerts > pos, NULL); while ((pCert = CertEnumCertificatesInStore(ctx->hMemStore, pCert)) && (pos > 0)) { pos--; } return(pCert); } /** * xmlSecMSCryptoKeyDataX509GetCertsSize: * @data: the pointer to X509 key data. * * Gets the number of certificates in @data. * * Returns: te number of certificates in @data. */ xmlSecSize xmlSecMSCryptoKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), 0); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(ctx->numCerts); } /** * xmlSecMSCryptoKeyDataX509AdoptCrl: * @data: the pointer to X509 key data. * @crl: the pointer to MSCrypto X509 CRL. * * Adds CRL to the X509 key data. * * Returns: 0 on success or a negative value if an error occurs. */ int xmlSecMSCryptoKeyDataX509AdoptCrl(xmlSecKeyDataPtr data, PCCRL_CONTEXT crl) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(crl != 0, -1); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->hMemStore != 0, -1); if (!CertAddCRLContextToStore(ctx->hMemStore, crl, CERT_STORE_ADD_ALWAYS, NULL)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CertAddCRLContextToStore", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ctx->numCrls++; return(0); } /** * xmlSecMSCryptoKeyDataX509GetCrl: * @data: the pointer to X509 key data. * @pos: the desired CRL position. * * Gets a CRL from X509 key data. * * Returns: the pointer to CRL or NULL if @pos is larger than the * number of CRLs in @data or an error occurs. */ PCCRL_CONTEXT xmlSecMSCryptoKeyDataX509GetCrl(xmlSecKeyDataPtr data, xmlSecSize pos) { xmlSecMSCryptoX509DataCtxPtr ctx; PCCRL_CONTEXT pCRL = NULL; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->hMemStore != 0, NULL); xmlSecAssert2(ctx->numCrls > pos, NULL); while ((pCRL = CertEnumCRLsInStore(ctx->hMemStore, pCRL)) && (pos > 0)) { pos--; } return(pCRL); } /** * xmlSecMSCryptoKeyDataX509GetCrlsSize: * @data: the pointer to X509 key data. * * Gets the number of CRLs in @data. * * Returns: te number of CRLs in @data. */ xmlSecSize xmlSecMSCryptoKeyDataX509GetCrlsSize(xmlSecKeyDataPtr data) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), 0); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(ctx->numCrls); } static int xmlSecMSCryptoKeyDataX509Initialize(xmlSecKeyDataPtr data) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); memset(ctx, 0, sizeof(xmlSecMSCryptoX509DataCtx)); ctx->hMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); if (ctx->hMemStore == 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CertOpenStore", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } return(0); } static int xmlSecMSCryptoKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { PCCERT_CONTEXT certSrc, certDst; PCCRL_CONTEXT crlSrc, crlDst; xmlSecSize size, pos; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataX509Id), -1); /* copy certsList */ size = xmlSecMSCryptoKeyDataX509GetCertsSize(src); for(pos = 0; pos < size; ++pos) { /* TBD: function below does linear scan, eliminate loop within * loop */ certSrc = xmlSecMSCryptoKeyDataX509GetCert(src, pos); if(certSrc == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)), "xmlSecMSCryptoKeyDataX509GetCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } certDst = CertDuplicateCertificateContext(certSrc); if(certDst == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "CertDuplicateCertificateContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ret = xmlSecMSCryptoKeyDataX509AdoptCert(dst, certDst); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "xmlSecMSCryptoKeyDataX509AdoptCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(certDst); return(-1); } } /* copy crls */ size = xmlSecMSCryptoKeyDataX509GetCrlsSize(src); for(pos = 0; pos < size; ++pos) { crlSrc = xmlSecMSCryptoKeyDataX509GetCrl(src, pos); if(crlSrc == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)), "xmlSecMSCryptoKeyDataX509GetCrl", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } crlDst = CertDuplicateCRLContext(crlSrc); if(crlDst == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "CertDuplicateCRLContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ret = xmlSecMSCryptoKeyDataX509AdoptCrl(dst, crlDst); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "xmlSecMSCryptoKeyDataX509AdoptCrl", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCRLContext(crlDst); return(-1); } } /* copy key cert if exist */ certSrc = xmlSecMSCryptoKeyDataX509GetKeyCert(src); if(certSrc != NULL) { certDst = CertDuplicateCertificateContext(certSrc); if(certDst == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "CertDuplicateCertificateContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ret = xmlSecMSCryptoKeyDataX509AdoptKeyCert(dst, certDst); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "xmlSecMSCryptoKeyDataX509AdoptKeyCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(certDst); return(-1); } } return(0); } static void xmlSecMSCryptoKeyDataX509Finalize(xmlSecKeyDataPtr data) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id)); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert(ctx != NULL); if(ctx->keyCert != NULL) { CertFreeCertificateContext(ctx->keyCert); ctx->keyCert = NULL; } if (ctx->hMemStore != 0) { if (!CertCloseStore(ctx->hMemStore, CERT_CLOSE_STORE_FORCE_FLAG)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertCloseStore", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return; } } memset(ctx, 0, sizeof(xmlSecMSCryptoX509DataCtx)); } static int xmlSecMSCryptoKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataPtr data; int ret; xmlSecAssert2(id == xmlSecMSCryptoKeyDataX509Id, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); data = xmlSecKeyEnsureData(key, id); if(data == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecKeyEnsureData", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ret = xmlSecMSCryptoX509DataNodeRead(data, node, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoX509DataNodeRead", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) { ret = xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoKeyDataX509VerifyAndExtractKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } return(0); } static int xmlSecMSCryptoKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataPtr data; PCCERT_CONTEXT cert; PCCRL_CONTEXT crl; xmlSecSize size, pos; int content = 0; int ret; xmlSecAssert2(id == xmlSecMSCryptoKeyDataX509Id, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); content = xmlSecX509DataGetNodeContent (node, 1, keyInfoCtx); if (content < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecX509DataGetNodeContent", XMLSEC_ERRORS_R_XMLSEC_FAILED, "content=%d", content); return(-1); } else if(content == 0) { /* by default we are writing certificates and crls */ content = XMLSEC_X509DATA_DEFAULT; } /* get x509 data */ data = xmlSecKeyGetData(key, id); if(data == NULL) { /* no x509 data in the key */ return(0); } /* write certs */ size = xmlSecMSCryptoKeyDataX509GetCertsSize(data); for(pos = 0; pos < size; ++pos) { cert = xmlSecMSCryptoKeyDataX509GetCert(data, pos); if(cert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoKeyDataX509GetCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) { ret = xmlSecMSCryptoX509CertificateNodeWrite(cert, node, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoX509CertificateNodeWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } } if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) { ret = xmlSecMSCryptoX509SubjectNameNodeWrite(cert, node, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoX509SubjectNameNodeWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } } if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) { ret = xmlSecMSCryptoX509IssuerSerialNodeWrite(cert, node, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoX509IssuerSerialNodeWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } } if((content & XMLSEC_X509DATA_SKI_NODE) != 0) { ret = xmlSecMSCryptoX509SKINodeWrite(cert, node, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoX509SKINodeWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } } } /* write crls if needed */ if((content & XMLSEC_X509DATA_CRL_NODE) != 0) { size = xmlSecMSCryptoKeyDataX509GetCrlsSize(data); for(pos = 0; pos < size; ++pos) { crl = xmlSecMSCryptoKeyDataX509GetCrl(data, pos); if(crl == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoKeyDataX509GetCrl", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } ret = xmlSecMSCryptoX509CRLNodeWrite(crl, node, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoX509CRLNodeWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return(-1); } } } return(0); } static xmlSecKeyDataType xmlSecMSCryptoKeyDataX509GetType(xmlSecKeyDataPtr data) { xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), xmlSecKeyDataTypeUnknown); /* TODO: return verified/not verified status */ return(xmlSecKeyDataTypeUnknown); } static const xmlChar* xmlSecMSCryptoKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) { xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), NULL); /* TODO */ return(NULL); } static void xmlSecMSCryptoKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) { PCCERT_CONTEXT cert; xmlSecSize size, pos; xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id)); xmlSecAssert(output != NULL); fprintf(output, "=== X509 Data:\n"); cert = xmlSecMSCryptoKeyDataX509GetKeyCert(data); if(cert != NULL) { fprintf(output, "==== Key Certificate:\n"); xmlSecMSCryptoX509CertDebugDump(cert, output); } size = xmlSecMSCryptoKeyDataX509GetCertsSize(data); for(pos = 0; pos < size; ++pos) { cert = xmlSecMSCryptoKeyDataX509GetCert(data, pos); if(cert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataX509GetCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return; } fprintf(output, "==== Certificate:\n"); xmlSecMSCryptoX509CertDebugDump(cert, output); } /* we don't print out crls */ } static void xmlSecMSCryptoKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { PCCERT_CONTEXT cert; xmlSecSize size, pos; xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id)); xmlSecAssert(output != NULL); fprintf(output, "\n"); cert = xmlSecMSCryptoKeyDataX509GetKeyCert(data); if(cert != NULL) { fprintf(output, "\n"); xmlSecMSCryptoX509CertDebugXmlDump(cert, output); fprintf(output, "\n"); } size = xmlSecMSCryptoKeyDataX509GetCertsSize(data); for(pos = 0; pos < size; ++pos) { cert = xmlSecMSCryptoKeyDataX509GetCert(data, pos); if(cert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataX509GetCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, "pos=%d", pos); return; } fprintf(output, "\n"); xmlSecMSCryptoX509CertDebugXmlDump(cert, output); fprintf(output, "\n"); } /* we don't print out crls */ fprintf(output, "\n"); } static int xmlSecMSCryptoX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlNodePtr cur; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); for(cur = xmlSecGetNextElementNode(node->children); cur != NULL; cur = xmlSecGetNextElementNode(cur->next)) { ret = 0; if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) { ret = xmlSecMSCryptoX509CertificateNodeRead(data, cur, keyInfoCtx); } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) { ret = xmlSecMSCryptoX509SubjectNameNodeRead(data, cur, keyInfoCtx); } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) { ret = xmlSecMSCryptoX509IssuerSerialNodeRead(data, cur, keyInfoCtx); } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) { ret = xmlSecMSCryptoX509SKINodeRead(data, cur, keyInfoCtx); } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) { ret = xmlSecMSCryptoX509CRLNodeRead(data, cur, keyInfoCtx); } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CHILD) != 0) { /* laxi schema validation: ignore unknown nodes */ xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_UNEXPECTED_NODE, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_XMLSEC_FAILED, "read node failed"); return(-1); } } return(0); } static int xmlSecMSCryptoX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlChar *content; PCCERT_CONTEXT cert; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); content = xmlNodeGetContent(node); if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) { if(content != NULL) { xmlFree(content); } if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(node)), XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } return(0); } cert = xmlSecMSCryptoX509CertBase64DerRead(content); if(cert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoX509CertBase64DerRead", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(content); return(-1); } ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataX509AdoptCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(cert); xmlFree(content); return(-1); } xmlFree(content); return(0); } static int xmlSecMSCryptoX509CertificateNodeWrite(PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlChar* buf; xmlNodePtr cur; xmlSecAssert2(cert != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); /* set base64 lines size from context */ buf = xmlSecMSCryptoX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize); if(buf == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoX509CertBase64DerWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } cur = xmlSecAddChild(node, xmlSecNodeX509Certificate, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509Certificate)); xmlFree(buf); return(-1); } /* todo: add \n around base64 data - from context */ /* todo: add errors check */ xmlNodeSetContent(cur, xmlSecStringCR); xmlNodeSetContent(cur, buf); xmlFree(buf); return(0); } static int xmlSecMSCryptoX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataStorePtr x509Store; xmlChar* subject; PCCERT_CONTEXT cert; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId); if(x509Store == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecKeysMngrGetDataStore", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } subject = xmlNodeGetContent(node); if((subject == NULL) || (xmlSecIsEmptyString(subject) == 1)) { if(subject != NULL) { xmlFree(subject); } if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(node)), XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } return(0); } cert = xmlSecMSCryptoX509StoreFindCert(x509Store, subject, NULL, NULL, NULL, keyInfoCtx); if(cert == NULL){ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), NULL, XMLSEC_ERRORS_R_CERT_NOT_FOUND, "subject=%s", xmlSecErrorsSafeString(subject)); xmlFree(subject); return(-1); } xmlFree(subject); return(0); } ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataX509AdoptCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(cert); xmlFree(subject); return(-1); } xmlFree(subject); return(0); } static int xmlSecMSCryptoX509SubjectNameNodeWrite(PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) { xmlChar* buf = NULL; xmlNodePtr cur = NULL; xmlSecAssert2(cert != NULL, -1); xmlSecAssert2(node != NULL, -1); buf = xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Subject)); if(buf == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Subject))", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } cur = xmlSecAddChild(node, xmlSecNodeX509SubjectName, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509SubjectName)); xmlFree(buf); return(-1); } xmlSecNodeEncodeAndSetContent(cur, buf); xmlFree(buf); return(0); } static int xmlSecMSCryptoX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataStorePtr x509Store; xmlNodePtr cur; xmlChar *issuerName; xmlChar *issuerSerial; PCCERT_CONTEXT cert; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId); if(x509Store == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecKeysMngrGetDataStore", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } cur = xmlSecGetNextElementNode(node->children); if(cur == NULL) { if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeX509IssuerName), XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node=%s", xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); return(-1); } return(0); } /* the first is required node X509IssuerName */ if(!xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeX509IssuerName), XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node=%s", xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); return(-1); } issuerName = xmlNodeGetContent(cur); if(issuerName == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509IssuerName)); return(-1); } cur = xmlSecGetNextElementNode(cur->next); /* next is required node X509SerialNumber */ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber)); xmlFree(issuerName); return(-1); } issuerSerial = xmlNodeGetContent(cur); if(issuerSerial == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber), XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "node=%s", xmlSecErrorsSafeString(xmlSecNodeGetName(cur))); xmlFree(issuerName); return(-1); } cur = xmlSecGetNextElementNode(cur->next); if(cur != NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_UNEXPECTED_NODE, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(issuerSerial); xmlFree(issuerName); return(-1); } cert = xmlSecMSCryptoX509StoreFindCert(x509Store, NULL, issuerName, issuerSerial, NULL, keyInfoCtx); if(cert == NULL){ if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), NULL, XMLSEC_ERRORS_R_CERT_NOT_FOUND, "issuerName=%s;issuerSerial=%s", xmlSecErrorsSafeString(issuerName), xmlSecErrorsSafeString(issuerSerial)); xmlFree(issuerSerial); xmlFree(issuerName); return(-1); } xmlFree(issuerSerial); xmlFree(issuerName); return(0); } ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataX509AdoptCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(cert); xmlFree(issuerSerial); xmlFree(issuerName); return(-1); } xmlFree(issuerSerial); xmlFree(issuerName); return(0); } static int xmlSecMSCryptoX509IssuerSerialNodeWrite(PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) { xmlNodePtr cur; xmlNodePtr issuerNameNode; xmlNodePtr issuerNumberNode; xmlChar* buf; int ret; xmlSecAssert2(cert != NULL, -1); xmlSecAssert2(node != NULL, -1); /* create xml nodes */ cur = xmlSecAddChild(node, xmlSecNodeX509IssuerSerial, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial)); return(-1); } issuerNameNode = xmlSecAddChild(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs); if(issuerNameNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509IssuerName)); return(-1); } issuerNumberNode = xmlSecAddChild(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs); if(issuerNumberNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber)); return(-1); } /* write data */ buf = xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Issuer)); if(buf == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoX509NameWrite(&(cert->pCertInfo->Issuer))", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } xmlSecNodeEncodeAndSetContent(issuerNameNode, buf); xmlFree(buf); ret = xmlSecMSCryptoASN1IntegerWrite(issuerNumberNode, &(cert->pCertInfo->SerialNumber)); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoASN1IntegerWrite(&(cert->serialNumber))", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } return(0); } static int xmlSecMSCryptoX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataStorePtr x509Store; xmlChar* ski; PCCERT_CONTEXT cert; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId); if(x509Store == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecKeysMngrGetDataStore", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ski = xmlNodeGetContent(node); if((ski == NULL) || (xmlSecIsEmptyString(ski) == 1)) { if(ski != NULL) { xmlFree(ski); } if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(node)), XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "node=%s", xmlSecErrorsSafeString(xmlSecNodeX509SKI)); return(-1); } return(0); } cert = xmlSecMSCryptoX509StoreFindCert(x509Store, NULL, NULL, NULL, ski, keyInfoCtx); if(cert == NULL){ xmlFree(ski); if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), NULL, XMLSEC_ERRORS_R_CERT_NOT_FOUND, "ski=%s", xmlSecErrorsSafeString(ski)); return(-1); } return(0); } ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataX509AdoptCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(cert); xmlFree(ski); return(-1); } xmlFree(ski); return(0); } static int xmlSecMSCryptoX509SKINodeWrite(PCCERT_CONTEXT cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) { xmlChar *buf = NULL; xmlNodePtr cur = NULL; xmlSecAssert2(cert != NULL, -1); xmlSecAssert2(node != NULL, -1); buf = xmlSecMSCryptoX509SKIWrite(cert); if(buf == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoX509SKIWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } cur = xmlSecAddChild(node, xmlSecNodeX509SKI, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "new_node=%s", xmlSecErrorsSafeString(xmlSecNodeX509SKI)); xmlFree(buf); return(-1); } xmlSecNodeEncodeAndSetContent(cur, buf); xmlFree(buf); return(0); } static int xmlSecMSCryptoX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlChar *content; PCCRL_CONTEXT crl; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); content = xmlNodeGetContent(node); if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) { if(content != NULL) { xmlFree(content); } if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), xmlSecErrorsSafeString(xmlSecNodeGetName(node)), XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } return(0); } crl = xmlSecMSCryptoX509CrlBase64DerRead(content, keyInfoCtx); if(crl == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoX509CrlBase64DerRead", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(content); return(-1); } if (0 != xmlSecMSCryptoKeyDataX509AdoptCrl(data, crl)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataX509AdoptCrl", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(content); CertFreeCRLContext(crl); return(-1); } xmlFree(content); return(0); } static int xmlSecMSCryptoX509CRLNodeWrite(PCCRL_CONTEXT crl, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlChar* buf = NULL; xmlNodePtr cur = NULL; xmlSecAssert2(crl != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); /* set base64 lines size from context */ buf = xmlSecMSCryptoX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize); if(buf == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoX509CrlBase64DerWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } cur = xmlSecAddChild(node, xmlSecNodeX509CRL, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "new_node=%s", xmlSecErrorsSafeString(xmlSecNodeX509CRL)); xmlFree(buf); return(-1); } /* todo: add \n around base64 data - from context */ /* todo: add errors check */ xmlNodeSetContent(cur, xmlSecStringCR); xmlNodeSetContent(cur, buf); xmlFree(buf); return(0); } static int xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecMSCryptoX509DataCtxPtr ctx; xmlSecKeyDataStorePtr x509Store; int ret; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataX509Id), -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1); ctx = xmlSecMSCryptoX509DataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->hMemStore != 0, -1); x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecMSCryptoX509StoreId); if(x509Store == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecKeysMngrGetDataStore", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } if((ctx->keyCert == NULL) && (xmlSecKeyGetValue(key) == NULL)) { PCCERT_CONTEXT cert; cert = xmlSecMSCryptoX509StoreVerify(x509Store, ctx->hMemStore, keyInfoCtx); if(cert != NULL) { xmlSecKeyDataPtr keyValue = NULL; PCCERT_CONTEXT pCert = NULL; ctx->keyCert = CertDuplicateCertificateContext(cert); if(ctx->keyCert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CertDuplicateCertificateContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } /* search key according to KeyReq */ pCert = CertDuplicateCertificateContext( ctx->keyCert ) ; if( pCert == NULL ) { xmlSecError( XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CertDuplicateCertificateContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } if( ( keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate ) == xmlSecKeyDataTypePrivate ) { keyValue = xmlSecMSCryptoCertAdopt( pCert, xmlSecKeyDataTypePrivate ) ; if(keyValue == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoCertAdopt", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext( pCert ) ; return(-1); } pCert = NULL ; } else if( ( keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePublic ) == xmlSecKeyDataTypePublic ) { keyValue = xmlSecMSCryptoCertAdopt( pCert, xmlSecKeyDataTypePublic ) ; if(keyValue == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoCertAdopt", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext( pCert ) ; return(-1); } pCert = NULL ; } /* verify that the key matches our expectations */ if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), keyValue) != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecKeyReqMatchKeyValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecKeyDataDestroy(keyValue); return(-1); } ret = xmlSecKeySetValue(key, keyValue); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecKeySetValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecKeyDataDestroy(keyValue); return(-1); } ret = xmlSecMSCryptoX509CertGetTime(ctx->keyCert->pCertInfo->NotBefore, &(key->notValidBefore)); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoX509CertGetTime", XMLSEC_ERRORS_R_XMLSEC_FAILED, "notValidBefore"); return(-1); } ret = xmlSecMSCryptoX509CertGetTime(ctx->keyCert->pCertInfo->NotAfter, &(key->notValidAfter)); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoX509CertGetTime", XMLSEC_ERRORS_R_XMLSEC_FAILED, "notValidAfter"); return(-1); } } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_INVALID_CERT) != 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), NULL, XMLSEC_ERRORS_R_CERT_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } return(0); } static int xmlSecMSCryptoX509CertGetTime(FILETIME t, time_t* res) { LONGLONG result; xmlSecAssert2(res != NULL, -1); result = t.dwHighDateTime; result = (result) << 32; result |= t.dwLowDateTime; result /= 10000; /* Convert from 100 nano-sec periods to seconds. */ #if defined(__MINGW32__) result -= 11644473600000ULL; /* Convert from Windows epoch to Unix epoch */ #else result -= 11644473600000; /* Convert from Windows epoch to Unix epoch */ #endif (*res) = (time_t)result; return(0); } static PCCERT_CONTEXT xmlSecMSCryptoX509CertBase64DerRead(xmlChar* buf) { int ret; xmlSecAssert2(buf != NULL, NULL); /* usual trick with base64 decoding "in-place" */ ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf)); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBase64Decode", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(xmlSecMSCryptoX509CertDerRead((xmlSecByte*)buf, ret)); } static PCCERT_CONTEXT xmlSecMSCryptoX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) { PCCERT_CONTEXT cert; xmlSecAssert2(buf != NULL, NULL); xmlSecAssert2(size > 0, NULL); cert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, buf, size); if(cert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertCreateCertificateContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(cert); } static xmlChar* xmlSecMSCryptoX509CertBase64DerWrite(PCCERT_CONTEXT cert, int base64LineWrap) { xmlChar *res = NULL; xmlSecByte *p = NULL; long size; xmlSecAssert2(cert != NULL, NULL); p = cert->pbCertEncoded; size = cert->cbCertEncoded; if((size <= 0) || (p == NULL)){ xmlSecError(XMLSEC_ERRORS_HERE, NULL, "cert->pbCertEncoded", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } res = xmlSecBase64Encode(p, size, base64LineWrap); if(res == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBase64Encode", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(res); } static PCCRL_CONTEXT xmlSecMSCryptoX509CrlBase64DerRead(xmlChar* buf, xmlSecKeyInfoCtxPtr keyInfoCtx) { int ret; xmlSecAssert2(buf != NULL, NULL); /* usual trick with base64 decoding "in-place" */ ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf)); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBase64Decode", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(xmlSecMSCryptoX509CrlDerRead((xmlSecByte*)buf, ret, keyInfoCtx)); } static PCCRL_CONTEXT xmlSecMSCryptoX509CrlDerRead(xmlSecByte* buf, xmlSecSize size, xmlSecKeyInfoCtxPtr keyInfoCtx) { PCCRL_CONTEXT crl = NULL; xmlSecAssert2(buf != NULL, NULL); xmlSecAssert2(keyInfoCtx != NULL, NULL); xmlSecAssert2(size > 0, NULL); crl = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, buf, size); if(crl == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertCreateCRLContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(crl); } static xmlChar* xmlSecMSCryptoX509CrlBase64DerWrite(PCCRL_CONTEXT crl, int base64LineWrap) { xmlChar *res = NULL; xmlSecByte *p = NULL; long size; xmlSecAssert2(crl != NULL, NULL); p = crl->pbCrlEncoded; size = crl->cbCrlEncoded; if((size <= 0) || (p == NULL)){ xmlSecError(XMLSEC_ERRORS_HERE, NULL, "crl->pbCrlEncoded", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } res = xmlSecBase64Encode(p, size, base64LineWrap); if(res == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBase64Encode", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(res); } static xmlChar* xmlSecMSCryptoX509NameWrite(PCERT_NAME_BLOB nm) { xmlChar *res = NULL; char *str; DWORD csz; xmlSecAssert2(nm->pbData != NULL, NULL); xmlSecAssert2(nm->cbData > 0, NULL); csz = CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, nm, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, NULL, 0); str = (char *)xmlMalloc(csz); if (NULL == str) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlMalloc", XMLSEC_ERRORS_R_MALLOC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return (NULL); } csz = CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, nm, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, str, csz); if (csz < 1) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertNameToStr", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(str); return(NULL); } /* aleksey: this is a hack, but mscrypto can not read E= flag and wants Email= instead. * don't ask me how is it possible not to read something you wrote yourself but also * see comment in the xmlSecMSCryptoX509FindCert function. */ if(strncmp(str, "E=", 2) == 0) { res = xmlMalloc(strlen(str) + 13 + 1); if(res == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlMalloc", XMLSEC_ERRORS_R_MALLOC_FAILED, "size=%d", strlen(str) + 13 + 1); xmlFree(str); return(NULL); } memcpy(res, "emailAddress=", 13); strcpy(res + 13, BAD_CAST (str + 2)); } else { res = xmlStrdup(BAD_CAST str); if(res == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlStrdup", XMLSEC_ERRORS_R_MALLOC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(str); return(NULL); } } xmlFree(str); return(res); } static int xmlSecMSCryptoASN1IntegerWrite(xmlNodePtr node, PCRYPT_INTEGER_BLOB num) { xmlSecBn bn; int ret; xmlSecAssert2(node != NULL, -1); xmlSecAssert2(num != NULL, -1); ret = xmlSecBnInitialize(&bn, num->cbData + 1); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBnInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%ld", num->cbData + 1); return(-1); } ret = xmlSecBnSetData(&bn, num->pbData, num->cbData); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBnSetData", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecBnFinalize(&bn); return(-1); } /* I have no clue why at a sudden a swap is needed to * convert from lsb... This code is purely based upon * trial and error :( WK */ ret = xmlSecBnSetNodeValue(&bn, node, xmlSecBnDec, 1, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBnSetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecBnFinalize(&bn); return(-1); } xmlSecBnFinalize(&bn); return(0); } static xmlChar* xmlSecMSCryptoX509SKIWrite(PCCERT_CONTEXT cert) { xmlChar *res = NULL; DWORD dwSize; BYTE *bSKI = NULL; PCERT_EXTENSION pCertExt; xmlSecAssert2(cert != NULL, NULL); /* First check if the SKI extension actually exists, otherwise we get a SHA1 hash o fthe key/cert */ pCertExt = CertFindExtension(szOID_SUBJECT_KEY_IDENTIFIER, cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension); if (pCertExt == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertFindExtension", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return (NULL); } if (!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &dwSize) || dwSize < 1) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertGetCertificateContextProperty", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return (NULL); } bSKI = xmlMalloc(dwSize); if (NULL == bSKI) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlMalloc", XMLSEC_ERRORS_R_MALLOC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return (NULL); } if (!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, bSKI, &dwSize)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertGetCertificateContextProperty", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(bSKI); return (NULL); } if (NULL == bSKI) { return(NULL); } res = xmlSecBase64Encode(bSKI, dwSize, 0); if(res == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBase64Encode", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlFree(bSKI); return(NULL); } xmlFree(bSKI); return(res); } static void xmlSecMSCryptoX509CertDebugDump(PCCERT_CONTEXT cert, FILE* output) { PCRYPT_INTEGER_BLOB sn; unsigned int i; LPSTR subject, issuer; DWORD dwSize; xmlSecAssert(cert != NULL); xmlSecAssert(output != NULL); /* todo: add error checks */ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, NULL, 0); subject = (LPSTR)xmlMalloc(dwSize); dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, subject, dwSize); dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0); issuer = (LPSTR)xmlMalloc(dwSize); dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer, dwSize); fprintf(output, "=== X509 Certificate\n"); fprintf(output, "==== Subject Name: %s\n", subject); fprintf(output, "==== Issuer Name: %s\n", issuer); if (subject) xmlFree(subject); if (issuer) xmlFree(issuer); sn = &(cert->pCertInfo->SerialNumber); for (i = 0; i < sn->cbData; i++) { if (i != sn->cbData - 1) { fprintf(output, "%02x:", sn->pbData[i]); } else { fprintf(output, "%02x", sn->pbData[i]); } } fprintf(output, "\n"); } static void xmlSecMSCryptoX509CertDebugXmlDump(PCCERT_CONTEXT cert, FILE* output) { PCRYPT_INTEGER_BLOB sn; unsigned int i; LPSTR subject, issuer; DWORD dwSize; xmlSecAssert(cert != NULL); xmlSecAssert(output != NULL); /* todo: add error checks */ /* subject */ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, NULL, 0); subject = (LPSTR)xmlMalloc(dwSize); dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL, subject, dwSize); fprintf(output, ""); xmlSecPrintXmlString(output, BAD_CAST subject); fprintf(output, "\n"); xmlFree(subject); /* issuer */ dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0); issuer = (LPSTR)xmlMalloc(dwSize); dwSize = CertGetNameString(cert, CERT_NAME_RDN_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer, dwSize); fprintf(output, ""); xmlSecPrintXmlString(output, BAD_CAST issuer); fprintf(output, "\n"); xmlFree(issuer); /* serial */ fprintf(output, ""); sn = &(cert->pCertInfo->SerialNumber); for (i = 0; i < sn->cbData; i++) { if (i != sn->cbData - 1) { fprintf(output, "%02x:", sn->pbData[i]); } else { fprintf(output, "%02x", sn->pbData[i]); } } fprintf(output, "\n"); } /************************************************************************** * * Raw X509 Certificate processing * * *************************************************************************/ static int xmlSecMSCryptoKeyDataRawX509CertBinRead (xmlSecKeyDataId id, xmlSecKeyPtr key, const xmlSecByte* buf, xmlSecSize bufSize, xmlSecKeyInfoCtxPtr keyInfoCtx); static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRawX509CertKlass = { sizeof(xmlSecKeyDataKlass), sizeof(xmlSecKeyData), /* data */ xmlSecNameRawX509Cert, 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, /* xmlSecKeyDataGetIdentifier getIdentifier; */ /* read/write */ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ xmlSecMSCryptoKeyDataRawX509CertBinRead, /* xmlSecKeyDataBinReadMethod binRead; */ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ /* debug */ NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */ NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ /* reserved for the future */ NULL, /* void* reserved0; */ NULL, /* void* reserved1; */ }; /** * xmlSecMSCryptoKeyDataRawX509CertGetKlass: * * The raw X509 certificates key data klass. * * Returns: raw X509 certificates key data klass. */ xmlSecKeyDataId xmlSecMSCryptoKeyDataRawX509CertGetKlass(void) { return(&xmlSecMSCryptoKeyDataRawX509CertKlass); } static int xmlSecMSCryptoKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key, const xmlSecByte* buf, xmlSecSize bufSize, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataPtr data; PCCERT_CONTEXT cert; int ret; xmlSecAssert2(id == xmlSecMSCryptoKeyDataRawX509CertId, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(buf != NULL, -1); xmlSecAssert2(bufSize > 0, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); cert = xmlSecMSCryptoX509CertDerRead(buf, bufSize); if(cert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoX509CertDerRead", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } data = xmlSecKeyEnsureData(key, xmlSecMSCryptoKeyDataX509Id); if(data == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecKeyEnsureData", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(cert); return(-1); } ret = xmlSecMSCryptoKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoKeyDataX509AdoptCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CertFreeCertificateContext(cert); return(-1); } ret = xmlSecMSCryptoKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoKeyDataX509VerifyAndExtractKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } return(0); } #endif /* XMLSEC_NO_X509 */