From 85b39a2b757daee3ef2e6b8878433f6353334b11 Mon Sep 17 00:00:00 2001 From: lsh123 Date: Thu, 23 Feb 2023 17:43:01 -0500 Subject: [PATCH] Fix x509data->keyCert when loading a key from a cert (#546) --- src/gnutls/app.c | 73 +++++++++++++++++++++----- src/mscng/app.c | 70 +++++++++++++++---------- src/mscrypto/app.c | 22 +++++++- src/nss/app.c | 113 +++++++++++++++++++++++++++++----------- src/openssl/app.c | 126 +++++++++++++++++++++++++++++++-------------- 5 files changed, 293 insertions(+), 111 deletions(-) diff --git a/src/gnutls/app.c b/src/gnutls/app.c index 317b8626d..2c2c354cd 100644 --- a/src/gnutls/app.c +++ b/src/gnutls/app.c @@ -226,38 +226,64 @@ xmlSecGnuTLSAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, */ int xmlSecGnuTLSAppKeyCertLoadMemory(xmlSecKeyPtr key, - const xmlSecByte* data, - xmlSecSize dataSize, - xmlSecKeyDataFormat format) { - gnutls_x509_crt_t cert; + const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format) +{ + gnutls_x509_crt_t cert = NULL; + gnutls_x509_crt_t keyCert = NULL; xmlSecKeyDataPtr keyData; int ret; + int res = -1; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(dataSize > 0, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + /* read cert and make a copy for the keyCert */ + cert = xmlSecGnuTLSX509CertRead(data, dataSize, format); + if(cert == NULL) { + xmlSecInternalError("xmlSecGnuTLSX509CertRead", NULL); + goto done; + } + + keyCert = xmlSecGnuTLSX509CertDup(cert); + if(keyCert == NULL) { + xmlSecInternalError("xmlSecGnuTLSX509CertDup", NULL); + goto done; + } + + /* add both cert and keyCert to the keyData */ keyData = xmlSecKeyEnsureData(key, xmlSecGnuTLSKeyDataX509Id); if(keyData == NULL) { xmlSecInternalError("xmlSecKeyEnsureData", NULL); - return(-1); + goto done; } - cert = xmlSecGnuTLSX509CertRead(data, dataSize, format); - if(cert == NULL) { - xmlSecInternalError("xmlSecGnuTLSX509CertRead", NULL); - return(-1); + ret = xmlSecGnuTLSKeyDataX509AdoptKeyCert(keyData, keyCert); + if(ret < 0) { + xmlSecInternalError("xmlSecGnuTLSKeyDataX509AdoptKeyCert", NULL); + goto done; } + keyCert = NULL; /* owned by keyData now */ ret = xmlSecGnuTLSKeyDataX509AdoptCert(keyData, cert); if(ret < 0) { xmlSecInternalError("xmlSecGnuTLSKeyDataX509AdoptCert", NULL); - gnutls_x509_crt_deinit(cert); - return(-1); + goto done; } + cert = NULL; /* owned by key data now */ - return(0); + /* success */ + res = 0; + +done: + if(cert != NULL) { + gnutls_x509_crt_deinit(cert); + } + if(keyCert != NULL) { + gnutls_x509_crt_deinit(keyCert); + } + return(res); } /** @@ -503,6 +529,7 @@ xmlSecGnuTLSAppKeyFromCertLoadMemory(const xmlSecByte* data, xmlSecKeyDataPtr keyData = NULL; xmlSecKeyDataPtr x509Data = NULL; gnutls_x509_crt_t cert = NULL; + gnutls_x509_crt_t keyCert = NULL; xmlSecKeyPtr res = NULL; int ret; @@ -510,13 +537,19 @@ xmlSecGnuTLSAppKeyFromCertLoadMemory(const xmlSecByte* data, xmlSecAssert2(dataSize > 0, NULL); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); - /* read cert */ + /* read cert and make a copy for keyCert */ cert = xmlSecGnuTLSX509CertRead(data, dataSize, format); if(cert == NULL) { xmlSecInternalError("xmlSecGnuTLSX509CertRead", NULL); goto done; } + keyCert = xmlSecGnuTLSX509CertDup(cert); + if(keyCert == NULL) { + xmlSecInternalError("xmlSecGnuTLSX509CertDup", NULL); + goto done; + } + /* create key */ key = xmlSecKeyCreate(); if(key == NULL) { @@ -545,11 +578,20 @@ xmlSecGnuTLSAppKeyFromCertLoadMemory(const xmlSecByte* data, xmlSecInternalError("xmlSecKeyEnsureData", NULL); goto done; } - ret = xmlSecGnuTLSKeyDataX509AdoptKeyCert(x509Data, cert); + + /* add cert and key cert */ + ret = xmlSecGnuTLSKeyDataX509AdoptKeyCert(x509Data, keyCert); if(ret < 0) { xmlSecInternalError("xmlSecGnuTLSKeyDataX509AdoptKeyCert", NULL); goto done; } + keyCert = NULL; /* owned by x509Data now */ + + ret = xmlSecGnuTLSKeyDataX509AdoptCert(x509Data, cert); + if(ret < 0) { + xmlSecInternalError("xmlSecGnuTLSKeyDataX509AdoptCert", NULL); + goto done; + } cert = NULL; /* owned by x509Data now */ /* success */ @@ -560,6 +602,9 @@ xmlSecGnuTLSAppKeyFromCertLoadMemory(const xmlSecByte* data, if(cert != NULL) { gnutls_x509_crt_deinit(cert); } + if(keyCert != NULL) { + gnutls_x509_crt_deinit(keyCert); + } if(keyData != NULL) { xmlSecKeyDataDestroy(keyData); } diff --git a/src/mscng/app.c b/src/mscng/app.c index 778ca5b27..f23fa649d 100644 --- a/src/mscng/app.c +++ b/src/mscng/app.c @@ -190,7 +190,8 @@ xmlSecKeyPtr xmlSecMSCngAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format, const char *pwd, void* pwdCallback, void* pwdCallbackCtx) { PCCERT_CONTEXT pCert = NULL; - PCCERT_CONTEXT tmpcert = NULL; + PCCERT_CONTEXT pCertChain = NULL; + PCCERT_CONTEXT pKeyCert = NULL; xmlSecKeyDataPtr x509Data = NULL; xmlSecKeyDataPtr keyData = NULL; xmlSecKeyPtr key = NULL; @@ -205,6 +206,7 @@ xmlSecMSCngAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecK UNREFERENCED_PARAMETER(pwdCallback); UNREFERENCED_PARAMETER(pwdCallbackCtx); + /* read cert and make a copy for cert chain and keyCert */ XMLSEC_SAFE_CAST_SIZE_TO_ULONG(dataSize, dwDataSize, goto done, NULL); pCert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, data, dwDataSize); if(pCert == NULL) { @@ -212,54 +214,64 @@ xmlSecMSCngAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecK goto done; } - x509Data = xmlSecKeyDataCreate(xmlSecMSCngKeyDataX509Id); - if(x509Data == NULL) { - xmlSecInternalError("xmlSecKeyDataCreate", NULL); + pCertChain = CertDuplicateCertificateContext(pCert); + if(pCertChain == NULL) { + xmlSecMSCngLastError("CertDuplicateCertificateContext", NULL); goto done; } - tmpcert = CertDuplicateCertificateContext(pCert); - if(tmpcert == NULL) { - xmlSecMSCngLastError("CertDuplicateCertificateContext", - xmlSecKeyDataGetName(x509Data)); + pKeyCert = CertDuplicateCertificateContext(pCert); + if(pKeyCert == NULL) { + xmlSecMSCngLastError("CertDuplicateCertificateContext", NULL); goto done; } - ret = xmlSecMSCngKeyDataX509AdoptKeyCert(x509Data, tmpcert); - if(ret < 0) { - xmlSecInternalError("xmlSecMSCngKeyDataX509AdoptKeyCert", + /* create key */ + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecInternalError("xmlSecKeyCreate", xmlSecKeyDataGetName(x509Data)); goto done; } - tmpcert = NULL; keyData = xmlSecMSCngCertAdopt(pCert, xmlSecKeyDataTypePublic); if(keyData == NULL) { - xmlSecInternalError("xmlSecMSCngCertAdopt", - xmlSecKeyDataGetName(x509Data)); + xmlSecInternalError("xmlSecMSCngCertAdopt", NULL); goto done; } - pCert = NULL; + pCert = NULL; /* owned by keyData now */ - key = xmlSecKeyCreate(); - if(key == NULL) { - xmlSecInternalError("xmlSecKeyCreate", - xmlSecKeyDataGetName(x509Data)); + ret = xmlSecKeySetValue(key, keyData); + if(ret < 0) { + xmlSecInternalError("xmlSecKeySetValue", NULL); + goto done; + } + keyData = NULL; + + /* add cert and keyCert to x509 data and add it to the key */ + x509Data = xmlSecKeyDataCreate(xmlSecMSCngKeyDataX509Id); + if(x509Data == NULL) { + xmlSecInternalError("xmlSecKeyDataCreate", NULL); goto done; } - ret = xmlSecKeySetValue(key, keyData); + ret = xmlSecMSCngKeyDataX509AdoptKeyCert(x509Data, pKeyCert); if(ret < 0) { - xmlSecInternalError("xmlSecKeySetValue", - xmlSecKeyDataGetName(x509Data)); + xmlSecInternalError("xmlSecMSCngKeyDataX509AdoptKeyCert", NULL); goto done; } - keyData = NULL; + pKeyCert = NULL; /* owned by x509Data data now */ + + ret = xmlSecMSCngKeyDataX509AdoptCert(x509Data, pCertChain); + if(ret < 0) { + xmlSecInternalError("xmlSecMSCngKeyDataX509AdoptCert", NULL); + goto done; + } + pCertChain = NULL; /* owned by x509Data data now */ ret = xmlSecKeyAdoptData(key, x509Data); if(ret < 0) { - xmlSecInternalError("xmlSecKeyAdoptData", - xmlSecKeyDataGetName(x509Data)); + xmlSecInternalError("xmlSecKeyAdoptData", NULL); goto done; } x509Data = NULL; @@ -267,12 +279,16 @@ xmlSecMSCngAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecK /* success */ res = key; key = NULL; + done: if(pCert != NULL) { CertFreeCertificateContext(pCert); } - if(tmpcert != NULL) { - CertFreeCertificateContext(tmpcert); + if(pCertChain != NULL) { + CertFreeCertificateContext(pCertChain); + } + if(pKeyCert != NULL) { + CertFreeCertificateContext(pKeyCert); } if(x509Data != NULL) { xmlSecKeyDataDestroy(x509Data); diff --git a/src/mscrypto/app.c b/src/mscrypto/app.c index e669fc83d..ae654a104 100644 --- a/src/mscrypto/app.c +++ b/src/mscrypto/app.c @@ -367,7 +367,7 @@ xmlSecMSCryptoAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, int xmlSecMSCryptoAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format) { - PCCERT_CONTEXT pCert; + PCCERT_CONTEXT pCert, pKeyCert; xmlSecKeyDataPtr kdata; DWORD dwDataSize; int ret; @@ -388,19 +388,39 @@ xmlSecMSCryptoAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xml case xmlSecKeyDataFormatDer: case xmlSecKeyDataFormatCertDer: XMLSEC_SAFE_CAST_SIZE_TO_ULONG(dataSize, dwDataSize, return(-1), NULL); + + /* read cert and make a copy for key cert */ pCert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, data, dwDataSize); if (NULL == pCert) { xmlSecInternalError2("CertCreateCertificateContext", xmlSecKeyDataGetName(kdata), "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); return(-1); } + pKeyCert = CertDuplicateCertificateContext(pCert); + if(pKeyCert == NULL) { + xmlSecMSCryptoError("CertDuplicateCertificateContext", xmlSecKeyDataGetName(kdata)); + CertFreeCertificateContext(pCert); + return(-1); + } + /* add cert and key cert */ ret = xmlSecMSCryptoKeyDataX509AdoptCert(kdata, pCert); if(ret < 0) { xmlSecInternalError("xmlSecMSCryptoKeyDataX509AdoptCert", xmlSecKeyDataGetName(kdata)); CertFreeCertificateContext(pCert); + CertFreeCertificateContext(pKeyCert); return(-1); } + pCert = NULL; /* owned by kdata */ + + ret = xmlSecMSCryptoKeyDataX509AdoptKeyCert(kdata, pKeyCert); + if(ret < 0) { + xmlSecInternalError("xmlSecMSCryptoKeyDataX509AdoptKeyCert", xmlSecKeyDataGetName(kdata)); + CertFreeCertificateContext(pKeyCert); + return(-1); + } + pKeyCert = NULL; /* owned by kdata */ + break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, xmlSecKeyDataGetName(kdata), diff --git a/src/nss/app.c b/src/nss/app.c index 5be6ae562..87874ca9e 100644 --- a/src/nss/app.c +++ b/src/nss/app.c @@ -572,9 +572,11 @@ xmlSecNssAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSi */ int xmlSecNssAppKeyCertLoadSECItem(xmlSecKeyPtr key, SECItem* secItem, xmlSecKeyDataFormat format) { - CERTCertificate *cert=NULL; + CERTCertificate *cert = NULL; + CERTCertificate *keyCert = NULL; xmlSecKeyDataPtr data; int ret; + int res = -1; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(secItem != NULL, -1); @@ -583,9 +585,10 @@ xmlSecNssAppKeyCertLoadSECItem(xmlSecKeyPtr key, SECItem* secItem, xmlSecKeyData data = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id); if(data == NULL) { xmlSecInternalError("xmlSecKeyEnsureData(xmlSecNssKeyDataX509Id)", NULL); - return(-1); + goto done; } + /* read cert */ switch(format) { case xmlSecKeyDataFormatPkcs8Der: case xmlSecKeyDataFormatDer: @@ -594,24 +597,49 @@ xmlSecNssAppKeyCertLoadSECItem(xmlSecKeyPtr key, SECItem* secItem, xmlSecKeyData if(cert == NULL) { xmlSecNssError2("__CERT_NewTempCertificate", xmlSecKeyDataGetName(data), "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); - return(-1); + goto done; } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, xmlSecKeyDataGetName(data), "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); - return(-1); + goto done; } - xmlSecAssert2(cert != NULL, -1); + + /* make a copy for key cert */ + keyCert = CERT_DupCertificate(cert); + if(keyCert == NULL) { + xmlSecNssError("CERT_DupCertificate", xmlSecKeyDataGetName(data)); + goto done; + } + + /* add both cert and key cert in the data */ ret = xmlSecNssKeyDataX509AdoptCert(data, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCert", xmlSecKeyDataGetName(data)); - CERT_DestroyCertificate(cert); - return(-1); + goto done; } + cert = NULL; /* owned by data now */ - return(0); + ret = xmlSecNssKeyDataX509AdoptKeyCert(data, keyCert); + if(ret < 0) { + xmlSecInternalError("xmlSecNssKeyDataX509AdoptKeyCert", xmlSecKeyDataGetName(data)); + goto done; + } + keyCert = NULL; /* owned by data now */ + + /* success */ + res = 0; + +done: + if(cert != NULL) { + CERT_DestroyCertificate(cert); + } + if(keyCert != NULL) { + CERT_DestroyCertificate(keyCert); + } + return(res); } /** @@ -941,11 +969,13 @@ xmlSecNssAppPkcs12LoadSECItem(SECItem* secItem, const char *pwd, */ xmlSecKeyPtr xmlSecNssAppKeyFromCertLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format) { - xmlSecKeyPtr key; - xmlSecKeyDataPtr keyData; + xmlSecKeyPtr key = NULL; + xmlSecKeyDataPtr keyData = NULL; xmlSecKeyDataPtr certData; - CERTCertificate *cert=NULL; + CERTCertificate *cert = NULL; + CERTCertificate *keyCert = NULL; int ret; + xmlSecKeyPtr res = NULL; xmlSecAssert2(secItem != NULL, NULL); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); @@ -954,65 +984,90 @@ xmlSecNssAppKeyFromCertLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format) switch(format) { case xmlSecKeyDataFormatCertDer: cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - secItem, NULL, PR_FALSE, PR_TRUE); + secItem, NULL, PR_FALSE, PR_TRUE); if(cert == NULL) { xmlSecNssError2("__CERT_NewTempCertificate", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); - return(NULL); + goto done; } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); - return(NULL); + goto done; } /* get key value */ keyData = xmlSecNssX509CertGetKey(cert); if(keyData == NULL) { xmlSecInternalError("xmlSecNssX509CertGetKey", NULL); - CERT_DestroyCertificate(cert); - return(NULL); + goto done; } /* create key */ key = xmlSecKeyCreate(); if(key == NULL) { xmlSecInternalError("xmlSecKeyCreate", NULL); - xmlSecKeyDataDestroy(keyData); - CERT_DestroyCertificate(cert); - return(NULL); + goto done; + } + + /* make a copy for key cert */ + keyCert = CERT_DupCertificate(cert); + if(keyCert == NULL) { + xmlSecNssError("CERT_DupCertificate", NULL); + goto done; } /* set key value */ ret = xmlSecKeySetValue(key, keyData); if(ret < 0) { xmlSecInternalError("xmlSecKeySetValue", NULL); - xmlSecKeyDestroy(key); - xmlSecKeyDataDestroy(keyData); - CERT_DestroyCertificate(cert); - return(NULL); + goto done; } + keyData = NULL; /* owned by key now */ /* create cert data */ certData = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id); if(certData == NULL) { xmlSecInternalError("xmlSecKeyEnsureData", NULL); - xmlSecKeyDestroy(key); - CERT_DestroyCertificate(cert); - return(NULL); + goto done; } - /* put cert in the cert data */ + /* put cert and key cert in the cert data */ ret = xmlSecNssKeyDataX509AdoptCert(certData, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCert", NULL); + goto done; + } + cert = NULL; /* owned by data now */ + + ret = xmlSecNssKeyDataX509AdoptKeyCert(certData, keyCert); + if(ret < 0) { + xmlSecInternalError("xmlSecNssKeyDataX509AdoptKeyCert", NULL); + goto done; + } + keyCert = NULL; /* owned by data now */ + + /* success */ + res = key; + key = NULL; + + +done: + if(key != NULL) { xmlSecKeyDestroy(key); + } + if(keyData != NULL) { + xmlSecKeyDataDestroy(keyData); + } + if(cert != NULL) { CERT_DestroyCertificate(cert); - return(NULL); + } + if(keyCert != NULL) { + CERT_DestroyCertificate(keyCert); } - return(key); + return(res); } diff --git a/src/openssl/app.c b/src/openssl/app.c index f3bd3e26d..269b32c66 100644 --- a/src/openssl/app.c +++ b/src/openssl/app.c @@ -658,22 +658,17 @@ int xmlSecOpenSSLAppKeyCertLoadBIO(xmlSecKeyPtr key, BIO* bio, xmlSecKeyDataFormat format) { xmlSecKeyDataFormat certFormat; - xmlSecKeyDataPtr data; - X509 *cert; + xmlSecKeyDataPtr data = NULL; + X509 *cert = NULL; + X509 *keyCert = NULL; int ret; + int res = -1; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(bio != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); - data = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id); - if(data == NULL) { - xmlSecInternalError("xmlSecKeyEnsureData", - xmlSecTransformKlassGetName(xmlSecOpenSSLKeyDataX509Id)); - return(-1); - } - - /* adjust cert format */ + /* adjust cert format if needed */ switch(format) { case xmlSecKeyDataFormatPkcs8Pem: certFormat = xmlSecKeyDataFormatPem; @@ -685,22 +680,50 @@ xmlSecOpenSSLAppKeyCertLoadBIO(xmlSecKeyPtr key, BIO* bio, xmlSecKeyDataFormat f certFormat = format; } + /* read cert and make a copy for key cert */ cert = xmlSecOpenSSLAppCertLoadBIO(bio, certFormat); if(cert == NULL) { - xmlSecInternalError("xmlSecOpenSSLAppCertLoad", - xmlSecKeyDataGetName(data)); - return(-1); + xmlSecInternalError("xmlSecOpenSSLAppCertLoad", NULL); + goto done; + } + keyCert = X509_dup(cert); + if(keyCert == NULL) { + xmlSecOpenSSLError("X509_dup", NULL); + goto done; + } + + /* add both cert and key cert to the key */ + data = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id); + if(data == NULL) { + xmlSecInternalError("xmlSecKeyEnsureData", NULL); + goto done; } ret = xmlSecOpenSSLKeyDataX509AdoptCert(data, cert); if(ret < 0) { - xmlSecInternalError("xmlSecOpenSSLKeyDataX509AdoptCert", - xmlSecKeyDataGetName(data)); - X509_free(cert); - return(-1); + xmlSecInternalError("xmlSecOpenSSLKeyDataX509AdoptCert", NULL); + goto done; } + cert = NULL; /* owned by data now */ - return(0); + ret = xmlSecOpenSSLKeyDataX509AdoptKeyCert(data, keyCert); + if(ret < 0) { + xmlSecInternalError("xmlSecOpenSSLKeyDataX509AdoptKeyCert", NULL); + goto done; + } + keyCert = NULL; /* owned by data now */ + + /* success */ + res = 0; + +done: + if(cert != NULL) { + X509_free(cert); + } + if(keyCert != NULL) { + X509_free(keyCert); + } + return(res); } /** @@ -999,68 +1022,91 @@ xmlSecOpenSSLAppPkcs12LoadBIO(BIO* bio, const char *pwd, */ xmlSecKeyPtr xmlSecOpenSSLAppKeyFromCertLoadBIO(BIO* bio, xmlSecKeyDataFormat format) { - xmlSecKeyPtr key; - xmlSecKeyDataPtr keyData; + xmlSecKeyPtr key = NULL; + xmlSecKeyDataPtr keyData = NULL; xmlSecKeyDataPtr certData; - X509 *cert; + X509 * cert = NULL; + X509 * keyCert = NULL; int ret; + xmlSecKeyPtr res = NULL; xmlSecAssert2(bio != NULL, NULL); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); - /* load cert */ + /* load cert and make a copy for keyCert */ cert = xmlSecOpenSSLAppCertLoadBIO(bio, format); if(cert == NULL) { xmlSecInternalError("xmlSecOpenSSLAppCertLoadBIO", NULL); - return(NULL); + goto done; + } + keyCert = X509_dup(cert); + if(keyCert == NULL) { + xmlSecOpenSSLError("X509_dup", NULL); + goto done; } /* get key value */ keyData = xmlSecOpenSSLX509CertGetKey(cert); if(keyData == NULL) { xmlSecInternalError("xmlSecOpenSSLX509CertGetKey", NULL); - X509_free(cert); - return(NULL); + goto done; } /* create key */ key = xmlSecKeyCreate(); if(key == NULL) { xmlSecInternalError("xmlSecKeyCreate", NULL); - xmlSecKeyDataDestroy(keyData); - X509_free(cert); - return(NULL); + goto done; } /* set key value */ ret = xmlSecKeySetValue(key, keyData); if(ret < 0) { xmlSecInternalError("xmlSecKeySetValue", NULL); - xmlSecKeyDestroy(key); - xmlSecKeyDataDestroy(keyData); - X509_free(cert); - return(NULL); + goto done; } + keyData = NULL; /* owned by key now */ /* create cert data */ certData = xmlSecKeyEnsureData(key, xmlSecOpenSSLKeyDataX509Id); if(certData == NULL) { xmlSecInternalError("xmlSecKeyEnsureData", NULL); - xmlSecKeyDestroy(key); - X509_free(cert); - return(NULL); + goto done; } - /* put cert in the cert data */ + /* put cert and key cert in the cert data */ ret = xmlSecOpenSSLKeyDataX509AdoptCert(certData, cert); if(ret < 0) { xmlSecInternalError("xmlSecOpenSSLKeyDataX509AdoptCert", NULL); - xmlSecKeyDestroy(key); - X509_free(cert); - return(NULL); + goto done; } + cert = NULL; /* owned by certData now */ - return(key); + ret = xmlSecOpenSSLKeyDataX509AdoptKeyCert(certData, keyCert); + if(ret < 0) { + xmlSecInternalError("xmlSecOpenSSLKeyDataX509AdoptKeyCert", NULL); + goto done; + } + keyCert = NULL; /* owned by certData now */ + + /* success */ + res = key; + key = NULL; + +done: + if(key != NULL) { + xmlSecKeyDestroy(key); + } + if(keyData != NULL) { + xmlSecKeyDataDestroy(keyData); + } + if(cert != NULL) { + X509_free(cert); + } + if(keyCert != NULL) { + X509_free(keyCert); + } + return(res); }