/
githubmirror
/
xmlsec
Обзор
Документация
Войти
/
githubmirror
/
xmlsec
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/nss/app.c
1 720 строк
53 KB
lsh123
Update file headers for doxygen, use common copyright header, bump copyright to 2026 (#1122)
07 апр 2026, 04:13
Не верифицирован
07 апр 2026, 04:13
2e557ee
Код
Авторство
О чём код?
/** * 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_app * @brief Application support functions for NSS. * @details Common functions for the xmlsec1 command-line utility for NSS. */ #include "globals.h" #include <string.h> #include <nspr.h> #include <nss.h> #include <cert.h> #include <certdb.h> #include <keyhi.h> #include <pk11pub.h> #include <pkcs12.h> #include <p12plcy.h> /* #include <ssl.h> */ #include <xmlsec/xmlsec.h> #include <xmlsec/keys.h> #include <xmlsec/transforms.h> #include <xmlsec/errors.h> #include <xmlsec/private.h> #include <xmlsec/nss/app.h> #include <xmlsec/nss/crypto.h> #include <xmlsec/nss/x509.h> #include <xmlsec/nss/pkikeys.h> #include <xmlsec/nss/keysstore.h> #include "../cast_helpers.h" #include "private.h" static int xmlSecNssAppCreateSECItem (SECItem *contents, const xmlSecByte* data, xmlSecSize dataSize); static int xmlSecNssAppReadSECItem (SECItem *contents, const char *fn); static PRBool xmlSecNssAppAscii2UCS2Conv (PRBool toUnicode, unsigned char *inBuf, unsigned int inBufLen, unsigned char *outBuf, unsigned int maxOutBufLen, unsigned int *outBufLen, PRBool swapBytes); static xmlSecKeyPtr xmlSecNssAppDerKeyLoadSECItem (SECItem* secItem); #ifndef XMLSEC_NO_X509 static SECItem *xmlSecNssAppNicknameCollisionCallback (SECItem *old_nick, PRBool *cancel, void *wincx); #endif /* XMLSEC_NO_X509 */ /** * @brief Initializes the NSS crypto engine. * @details General crypto engine initialization. This function is used * by the XMLSec command-line utility and is called before the * #xmlSecInit function. * * @param config the path to NSS database files. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppInit(const char* config) { SECStatus rv; if(config) { rv = NSS_InitReadWrite(config); if(rv != SECSuccess) { xmlSecNssError2("NSS_InitReadWrite", NULL, "config=%s", xmlSecErrorsSafeString(config)); return(-1); } } else { rv = NSS_NoDB_Init(NULL); if(rv != SECSuccess) { xmlSecNssError("NSS_NoDB_Init", NULL); return(-1); } } /* configure PKCS11 */ PK11_ConfigurePKCS11("manufacturesID", "libraryDescription", "tokenDescription", "privateTokenDescription", "slotDescription", "privateSlotDescription", "fipsSlotDescription", "fipsPrivateSlotDescription", 0, 0); /* setup for PKCS12 */ PORT_SetUCS2_ASCIIConversionFunction(xmlSecNssAppAscii2UCS2Conv); SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); return(0); } /** * @brief Shuts down the NSS crypto engine. * @details General crypto engine shutdown. This function is used * by the XMLSec command-line utility and is called after the * #xmlSecShutdown function. * * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppShutdown(void) { SECStatus rv; /* SSL_ClearSessionCache(); */ PK11_LogoutAll(); rv = NSS_Shutdown(); if(rv != SECSuccess) { xmlSecNssError("NSS_Shutdown", NULL); return(-1); } return(0); } static int xmlSecNssAppCreateSECItem(SECItem *contents, const xmlSecByte* data, xmlSecSize dataSize) { unsigned int dataLen; xmlSecAssert2(contents != NULL, -1); xmlSecAssert2(data != NULL, -1); contents->data = 0; XMLSEC_SAFE_CAST_SIZE_TO_UINT(dataSize, dataLen, return(-1), NULL); if (!SECITEM_AllocItem(NULL, contents, dataLen)) { xmlSecNssError("SECITEM_AllocItem", NULL); return(-1); } if(dataLen > 0) { xmlSecAssert2(contents->data != NULL, -1); memcpy(contents->data, data, dataLen); } return (0); } static int xmlSecNssAppReadSECItem(SECItem *contents, const char *fn) { PRFileInfo info; PRFileDesc *file = NULL; PRInt32 numBytes; PRStatus prStatus; unsigned int ulen; int ret = -1; xmlSecAssert2(contents != NULL, -1); xmlSecAssert2(fn != NULL, -1); file = PR_Open(fn, PR_RDONLY, 00660); if (file == NULL) { xmlSecNssError2("PR_Open", NULL, "filename=%s", xmlSecErrorsSafeString(fn)); goto done; } prStatus = PR_GetOpenFileInfo(file, &info); if (prStatus != PR_SUCCESS) { xmlSecNssError2("PR_GetOpenFileInfo", NULL, "filename=%s", xmlSecErrorsSafeString(fn)); goto done; } XMLSEC_SAFE_CAST_INT_TO_UINT(info.size, ulen, goto done, NULL); contents->data = 0; if (!SECITEM_AllocItem(NULL, contents, ulen)) { xmlSecNssError("SECITEM_AllocItem", NULL); goto done; } numBytes = PR_Read(file, contents->data, info.size); if (numBytes != info.size) { SECITEM_FreeItem(contents, PR_FALSE); goto done; } ret = 0; done: if (file) { PR_Close(file); } return (ret); } static PRBool xmlSecNssAppAscii2UCS2Conv(PRBool toUnicode, unsigned char *inBuf, unsigned int inBufLen, unsigned char *outBuf, unsigned int maxOutBufLen, unsigned int *outBufLen, PRBool swapBytes XMLSEC_ATTRIBUTE_UNUSED) { SECItem it = { siBuffer, NULL, 0 }; if (toUnicode == PR_FALSE) { return (PR_FALSE); } memset(&it, 0, sizeof(it)); it.data = inBuf; it.len = inBufLen; return(PORT_UCS2_UTF8Conversion(toUnicode, it.data, it.len, outBuf, maxOutBufLen, outBufLen)); } #ifndef XMLSEC_NO_X509 /* rename certificate if needed */ static SECItem * xmlSecNssAppNicknameCollisionCallback(SECItem *old_nick XMLSEC_ATTRIBUTE_UNUSED, PRBool *cancel, void *wincx ) { CERTCertificate *cert = (CERTCertificate *)wincx; char *nick = NULL; SECItem *ret_nick = NULL; if((cancel == NULL) || (cert == NULL)) { xmlSecNssError("cert is missing", NULL); return(NULL); } nick = CERT_MakeCANickname(cert); if (!nick) { xmlSecNssError("CERT_MakeCANickname", NULL); return(NULL); } ret_nick = PORT_ZNew(SECItem); if (ret_nick == NULL) { xmlSecNssError("PORT_ZNew", NULL); PORT_Free(nick); return NULL; } /* done */ ret_nick->data = (unsigned char *)nick; ret_nick->len = (unsigned int)PORT_Strlen(nick); return ret_nick; } #endif /* XMLSEC_NO_X509 */ /** * @brief Reads a key from a file. * @param filename the key filename. * @param type the key type (public / private). * @param format the key file format. * @param pwd the key file password. * @param pwdCallback the key password callback. * @param pwdCallbackCtx the user context for password callback. * @return pointer to the key or NULL if an error occurs. */ xmlSecKeyPtr xmlSecNssAppKeyLoadEx(const char *filename, xmlSecKeyDataType type XMLSEC_ATTRIBUTE_UNUSED, xmlSecKeyDataFormat format, const char *pwd, void* pwdCallback, void* pwdCallbackCtx ) { SECItem secItem = { siBuffer, NULL, 0 }; xmlSecKeyPtr res; int ret; xmlSecAssert2(filename != NULL, NULL); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); UNREFERENCED_PARAMETER(type); /* read the file contents */ memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppReadSECItem(&secItem, filename); if(ret < 0) { xmlSecInternalError("xmlSecNssAppReadSECItem", NULL); return(NULL); } res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx); if(res == NULL) { xmlSecInternalError("xmlSecNssAppKeyLoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(NULL); } SECITEM_FreeItem(&secItem, PR_FALSE); return(res); } /** * @brief Reads a key from the binary @p data. * @param data the key binary data. * @param dataSize the key binary data size. * @param format the key data format. * @param pwd the key data password. * @param pwdCallback the key password callback. * @param pwdCallbackCtx the user context for password callback. * @return pointer to the key or NULL if an error occurs. */ xmlSecKeyPtr xmlSecNssAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format, const char *pwd, void* pwdCallback, void* pwdCallbackCtx) { SECItem secItem = { siBuffer, NULL, 0 }; xmlSecKeyPtr res; int ret; xmlSecAssert2(data != NULL, NULL); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize); if(ret < 0) { xmlSecInternalError("xmlSecNssAppCreateSECItem", NULL); return(NULL); } res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx); if(res == NULL) { xmlSecInternalError("xmlSecNssAppKeyLoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(NULL); } SECITEM_FreeItem(&secItem, PR_FALSE); return(res); } /** * @brief Reads a key from a SECItem. * @param secItem the pointer to sec item. * @param format the key format. * @param pwd the key password. * @param pwdCallback the key password callback. * @param pwdCallbackCtx the user context for password callback. * @return pointer to the key or NULL if an error occurs. */ xmlSecKeyPtr xmlSecNssAppKeyLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format, const char *pwd, void* pwdCallback, void* pwdCallbackCtx ) { xmlSecKeyPtr key = NULL; xmlSecAssert2(secItem != NULL, NULL); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); switch(format) { #ifndef XMLSEC_NO_X509 case xmlSecKeyDataFormatPkcs12: key = xmlSecNssAppPkcs12LoadSECItem(secItem, pwd, pwdCallback, pwdCallbackCtx); if(key == NULL) { xmlSecInternalError("xmlSecNssAppPkcs12LoadSECItem", NULL); return(NULL); } break; case xmlSecKeyDataFormatCertDer: case xmlSecKeyDataFormatCertPem: key = xmlSecNssAppKeyFromCertLoadSECItem(secItem, format); if(key == NULL) { xmlSecInternalError("xmlSecNssAppKeyFromCertLoadSECItem", NULL); return(NULL); } break; #endif /* XMLSEC_NO_X509 */ case xmlSecKeyDataFormatDer: key = xmlSecNssAppDerKeyLoadSECItem(secItem); if(key == NULL) { xmlSecInternalError("xmlSecNssAppDerKeyLoadSECItem", NULL); return(NULL); } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); return(NULL); } return(key); } static xmlSecKeyPtr xmlSecNssAppDerKeyLoadSECItem(SECItem* secItem) { xmlSecKeyPtr key = NULL; xmlSecKeyPtr retval = NULL; xmlSecKeyDataPtr data = NULL; int ret; SECKEYPublicKey *pubkey = NULL; SECKEYPrivateKey *privkey = NULL; CERTSubjectPublicKeyInfo *spki = NULL; SECItem nickname = { siBuffer, NULL, 0 }; PK11SlotInfo *slot = NULL; SECStatus status; xmlSecAssert2(secItem != NULL, NULL); /* we're importing a key about which we know nothing yet, just use the * internal slot */ slot = xmlSecNssGetInternalKeySlot(); if (slot == NULL) { xmlSecInternalError("xmlSecNssGetInternalKeySlot", NULL); goto done; } nickname.len = 0; nickname.data = NULL; /* TRY PRIVATE KEY FIRST * Note: This expects the key to be in PrivateKeyInfo format. The * DER files created from PEM via nss utilities aren't in that * format */ status = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, secItem, &nickname, NULL, PR_FALSE, PR_TRUE, KU_ALL, &privkey, NULL); if (status != SECSuccess) { /* TRY PUBLIC KEY */ spki = SECKEY_DecodeDERSubjectPublicKeyInfo(secItem); if (spki == NULL) { xmlSecNssError("SECKEY_DecodeDERSubjectPublicKeyInfo", NULL); goto done; } pubkey = SECKEY_ExtractPublicKey(spki); if (pubkey == NULL) { xmlSecNssError("SECKEY_ExtractPublicKey", NULL); goto done; } } data = xmlSecNssPKIAdoptKey(privkey, pubkey); if(data == NULL) { xmlSecInternalError("xmlSecNssPKIAdoptKey", NULL); goto done; } privkey = NULL; pubkey = NULL; key = xmlSecKeyCreate(); if(key == NULL) { xmlSecInternalError("xmlSecKeyCreate", NULL); goto done; } ret = xmlSecKeySetValue(key, data); if(ret < 0) { xmlSecInternalError("xmlSecKeySetValue", xmlSecKeyDataGetName(data)); goto done; } retval = key; key = NULL; data = NULL; done: if(slot != NULL) { PK11_FreeSlot(slot); } if(privkey != NULL) { SECKEY_DestroyPrivateKey(privkey); } if(pubkey != NULL) { SECKEY_DestroyPublicKey(pubkey); } if(key != NULL) { xmlSecKeyDestroy(key); } if(data != NULL) { xmlSecKeyDataDestroy(data); } if(spki != NULL) { SECKEY_DestroySubjectPublicKeyInfo(spki); } return (retval); } /* returns 1 if matches, 0 if not, or a negative value on error */ static int xmlSecNssAppCheckCertMatchesKey(xmlSecKeyPtr key, CERTCertificate * cert) { xmlSecKeyDataPtr keyData = NULL; SECKEYPublicKey* pubkey = NULL; SECKEYPublicKey* cert_pubkey = NULL; SECItem * der_pubkey = NULL; SECItem * der_cert_pubkey = NULL; int res = -1; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(cert != NULL, -1); /* get key's pubkey and its der encoding */ keyData = xmlSecKeyGetValue(key); if(keyData == NULL) { res = 0; /* no key -> no match */ goto done; } pubkey = xmlSecNssPKIKeyDataGetPubKey(keyData); if(pubkey == NULL) { xmlSecInternalError("xmlSecNssPKIKeyDataGetPubKey", NULL); goto done; } der_pubkey = SECKEY_EncodeDERSubjectPublicKeyInfo(pubkey); if (der_pubkey == NULL) { xmlSecNssError("SECKEY_EncodeDERSubjectPublicKeyInfo", NULL); goto done; } /* get certs's pubkey and its der encoding */ cert_pubkey = CERT_ExtractPublicKey(cert); if (cert_pubkey == NULL) { xmlSecNssError("CERT_ExtractPublicKey", NULL); goto done; } der_cert_pubkey = SECKEY_EncodeDERSubjectPublicKeyInfo(cert_pubkey); if (der_cert_pubkey == NULL) { xmlSecNssError("SECKEY_EncodeDERSubjectPublicKeyInfo", NULL); goto done; } /* compare */ if(SECEqual == SECITEM_CompareItem(der_pubkey, der_cert_pubkey)) { /* match */ res = 1; } else { /* no match */ res = 0; } done: if(pubkey != NULL) { SECKEY_DestroyPublicKey(pubkey); } if (cert_pubkey) { SECKEY_DestroyPublicKey(cert_pubkey); } if(der_pubkey != NULL) { SECITEM_FreeItem(der_pubkey, PR_TRUE); } if(der_cert_pubkey != NULL) { SECITEM_FreeItem(der_cert_pubkey, PR_TRUE); } return(res); } #ifndef XMLSEC_NO_X509 /** * @brief Reads the certificate from a file and adds to key. * @details Reads the certificate from @p filename and adds it to key. * * @param key the pointer to key. * @param filename the certificate filename. * @param format the certificate file format. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, xmlSecKeyDataFormat format) { SECItem secItem = { siBuffer, NULL, 0 }; int ret; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(filename != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); /* read the file contents */ memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppReadSECItem(&secItem, filename); if(ret < 0) { xmlSecInternalError("xmlSecNssAppReadSECItem", NULL); return(-1); } ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format); if(ret < 0) { xmlSecInternalError("xmlSecNssAppKeyCertLoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } SECITEM_FreeItem(&secItem, PR_FALSE); return(0); } /** * @brief Reads the certificate from memory and adds to key. * @details Reads the certificate from @p data and adds it to key. * * @param key the pointer to key. * @param data the key binary data. * @param dataSize the key binary data size. * @param format the certificate format. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format) { SECItem secItem = { siBuffer, NULL, 0 }; int ret; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); /* read the file contents */ memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize); if(ret < 0) { xmlSecInternalError("xmlSecNssAppCreateSECItem", NULL); return(-1); } ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format); if(ret < 0) { xmlSecInternalError("xmlSecNssAppKeyCertLoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } SECITEM_FreeItem(&secItem, PR_FALSE); return(0); } /** * @brief Reads a certificate from SECItem and adds to key. * @details Reads the certificate from @p secItem and adds it to key. * * @param key the pointer to key. * @param secItem the pointer to SECItem. * @param format the certificate format. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeyCertLoadSECItem(xmlSecKeyPtr key, SECItem* secItem, xmlSecKeyDataFormat format) { CERTCertificate *cert = NULL; xmlSecKeyDataPtr x509Data; int isKeyCert = 0; int ret; int res = -1; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(secItem != NULL, -1); xmlSecAssert2(secItem->type == siBuffer, -1); xmlSecAssert2(secItem->data != NULL, -1); xmlSecAssert2(secItem->len > 0, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); /* read cert */ switch(format) { case xmlSecKeyDataFormatPkcs8Der: case xmlSecKeyDataFormatDer: cert = xmlSecNssX509CertDerRead(CERT_GetDefaultCertDB(), secItem->data, secItem->len); if(cert == NULL) { xmlSecInternalError2("xmlSecNssX509CertDerRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); goto done; } break; case xmlSecKeyDataFormatCertPem: cert = xmlSecNssX509CertPemRead(CERT_GetDefaultCertDB(), secItem->data, secItem->len); if(cert == NULL) { xmlSecInternalError2("xmlSecNssX509CertPemRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); goto done; } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); goto done; } xmlSecAssert2(cert != NULL, -1); /* add cert to the key */ x509Data = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id); if(x509Data == NULL) { xmlSecInternalError("xmlSecKeyEnsureData(xmlSecNssKeyDataX509Id)", NULL); goto done; } /* do we want to add this cert as a key cert? */ if(xmlSecNssKeyDataX509GetKeyCert(x509Data) == NULL) { ret = xmlSecNssAppCheckCertMatchesKey(key, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssAppCheckCertMatchesKey", NULL); goto done; } if(ret == 1) { isKeyCert = 1; } } if(isKeyCert != 0) { ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptKeyCert", NULL); goto done; } } else { ret = xmlSecNssKeyDataX509AdoptCert(x509Data, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCert", NULL); goto done; } } cert = NULL; /* owned by x509Data now */ /* success */ res = 0; done: if(cert != NULL) { CERT_DestroyCertificate(cert); } return(res); } /** * @brief Reads key and certificates from PKCS12 file. * @details Reads a key and all associated certificates from the PKCS12 file. * For uniformity, call #xmlSecNssAppKeyLoadEx instead of this function. Pass * in format=xmlSecKeyDataFormatPkcs12. * * @param filename the PKCS12 key filename. * @param pwd the PKCS12 file password. * @param pwdCallback the password callback. * @param pwdCallbackCtx the user context for password callback. * @return pointer to the key or NULL if an error occurs. */ xmlSecKeyPtr xmlSecNssAppPkcs12Load(const char *filename, const char *pwd, void *pwdCallback XMLSEC_ATTRIBUTE_UNUSED, void* pwdCallbackCtx XMLSEC_ATTRIBUTE_UNUSED) { SECItem secItem = { siBuffer, NULL, 0 }; xmlSecKeyPtr res; int ret; xmlSecAssert2(filename != NULL, NULL); /* read the file contents */ memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppReadSECItem(&secItem, filename); if(ret < 0) { xmlSecInternalError("xmlSecNssAppReadSECItem", NULL); return(NULL); } res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx); if(res == NULL) { xmlSecInternalError("xmlSecNssAppPkcs12LoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(NULL); } SECITEM_FreeItem(&secItem, PR_FALSE); return(res); } /** * @brief Reads key and certs from PKCS12 binary data. * @details Reads a key and all associated certificates from the PKCS12 binary data. * For uniformity, call #xmlSecNssAppKeyLoadEx instead of this function. Pass * in format=xmlSecKeyDataFormatPkcs12. * * @param data the key binary data. * @param dataSize the key binary data size. * @param pwd the PKCS12 password. * @param pwdCallback the password callback. * @param pwdCallbackCtx the user context for password callback. * @return pointer to the key or NULL if an error occurs. */ xmlSecKeyPtr xmlSecNssAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize, const char *pwd, void *pwdCallback XMLSEC_ATTRIBUTE_UNUSED, void* pwdCallbackCtx XMLSEC_ATTRIBUTE_UNUSED) { SECItem secItem = { siBuffer, NULL, 0 }; xmlSecKeyPtr res; int ret; xmlSecAssert2(data != NULL, NULL); memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize); if(ret < 0) { xmlSecInternalError("xmlSecNssAppCreateSECItem", NULL); return(NULL); } res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx); if(res == NULL) { xmlSecInternalError("xmlSecNssAppPkcs12LoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(NULL); } SECITEM_FreeItem(&secItem, PR_FALSE); return(res); } /** * @brief Reads key and certs from PKCS12 SECItem. * @details Reads a key and all associated certificates from the PKCS12 SECItem. * For uniformity, call #xmlSecNssAppKeyLoadEx instead of this function. Pass * in format=xmlSecKeyDataFormatPkcs12. * * @param secItem the SECItem object. * @param pwd the PKCS12 file password. * @param pwdCallback the password callback. * @param pwdCallbackCtx the user context for password callback. * @return pointer to the key or NULL if an error occurs. */ xmlSecKeyPtr xmlSecNssAppPkcs12LoadSECItem(SECItem* secItem, const char *pwd, void *pwdCallback XMLSEC_ATTRIBUTE_UNUSED, void* pwdCallbackCtx XMLSEC_ATTRIBUTE_UNUSED) { xmlSecKeyPtr key = NULL; xmlSecKeyDataPtr keyValueData = NULL; xmlSecKeyDataPtr x509Data = NULL; int ret; PK11SlotInfo *slot = NULL; SECItem pwditem = { siBuffer, NULL, 0 }; SECItem uc2_pwditem = { siBuffer, NULL, 0 }; SECStatus rv; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; CERTCertList *certlist = NULL; CERTCertListNode *head = NULL; CERTCertificate *cert = NULL; CERTCertificate *tmpcert = NULL; SEC_PKCS12DecoderContext *p12ctx = NULL; const SEC_PKCS12DecoderItem *dip; size_t pwdSize; xmlSecKeyPtr res = NULL; xmlSecAssert2((secItem != NULL), NULL); if (pwd == NULL) { pwd = ""; } memset(&uc2_pwditem, 0, sizeof(uc2_pwditem)); /* we're importing a key about which we know nothing yet, just use the * internal slot. We have no criteria to choose a slot. */ slot = xmlSecNssGetInternalKeySlot(); if (slot == NULL) { xmlSecInternalError("xmlSecNssGetInternalKeySlot", NULL); goto done; } pwditem.data = (unsigned char *)pwd; pwdSize = strlen(pwd) + 1; XMLSEC_SAFE_CAST_SIZE_T_TO_UINT(pwdSize, pwditem.len, goto done, NULL); if (!SECITEM_AllocItem(NULL, &uc2_pwditem, 2*pwditem.len)) { xmlSecNssError("SECITEM_AllocItem", NULL); goto done; } if (PORT_UCS2_ASCIIConversion(PR_TRUE, pwditem.data, pwditem.len, uc2_pwditem.data, 2*pwditem.len, &(uc2_pwditem.len), 0) == PR_FALSE) { xmlSecNssError("PORT_UCS2_ASCIIConversion", NULL); goto done; } p12ctx = SEC_PKCS12DecoderStart(&uc2_pwditem, slot, NULL, NULL, NULL, NULL, NULL, NULL); if (p12ctx == NULL) { xmlSecNssError("SEC_PKCS12DecoderStart", NULL); goto done; } rv = SEC_PKCS12DecoderUpdate(p12ctx, secItem->data, secItem->len); if (rv != SECSuccess) { xmlSecNssError("SEC_PKCS12DecoderUpdate", NULL); goto done; } rv = SEC_PKCS12DecoderVerify(p12ctx); if (rv != SECSuccess) { xmlSecNssError("SEC_PKCS12DecoderVerify", NULL); goto done; } rv = SEC_PKCS12DecoderValidateBags(p12ctx, xmlSecNssAppNicknameCollisionCallback); if (rv != SECSuccess) { xmlSecNssError("SEC_PKCS12DecoderValidateBags", NULL); goto done; } rv = SEC_PKCS12DecoderImportBags(p12ctx); if (rv != SECSuccess) { xmlSecNssError("SEC_PKCS12DecoderImportBags", NULL); goto done; } certlist = SEC_PKCS12DecoderGetCerts(p12ctx); if (certlist == NULL) { xmlSecNssError("SEC_PKCS12DecoderGetCerts", NULL); goto done; } x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id); if(x509Data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id)", NULL); goto done; } for (head = CERT_LIST_HEAD(certlist); !CERT_LIST_END(head, certlist); head = CERT_LIST_NEXT(head)) { cert = head->cert; privkey = PK11_FindKeyByAnyCert(cert, NULL); if (privkey != NULL) { if (keyValueData != NULL) { /* we already found a private key. * assume the first private key we find is THE ONE */ SECKEY_DestroyPrivateKey(privkey); privkey = NULL; continue; } pubkey = CERT_ExtractPublicKey(cert); if (pubkey == NULL) { xmlSecNssError("CERT_ExtractPublicKey", NULL); goto done; } keyValueData = xmlSecNssPKIAdoptKey(privkey, pubkey); if(keyValueData == NULL) { xmlSecInternalError("xmlSecNssPKIAdoptKey", NULL); goto done; } pubkey = NULL; privkey = NULL; tmpcert = CERT_DupCertificate(cert); if(tmpcert == NULL) { xmlSecNssError("CERT_DupCertificate", NULL); goto done; } ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, tmpcert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptKeyCert", NULL); goto done; } tmpcert = NULL; /* owned by x509Data now */ } else { tmpcert = CERT_DupCertificate(cert); if(tmpcert == NULL) { xmlSecNssError("CERT_DupCertificate", NULL); goto done; } ret = xmlSecNssKeyDataX509AdoptCert(x509Data, tmpcert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptCert", NULL); goto done; } tmpcert = NULL; /* owned by x509Data now */ } } /* end for loop */ if (keyValueData == NULL) { /* private key not found in PKCS12 file */ xmlSecInternalError("xmlSecNssAppPkcs12Load(private key)", NULL); goto done; } /* create key and set key value and x509 data into it */ key = xmlSecKeyCreate(); if(key == NULL) { xmlSecInternalError("xmlSecKeyCreate", NULL); goto done; } ret = xmlSecKeySetValue(key, keyValueData); if(ret < 0) { xmlSecInternalError("xmlSecKeySetValue", NULL); goto done; } keyValueData = NULL; /* owned by key now */ ret = xmlSecKeyAdoptData(key, x509Data); if(ret < 0) { xmlSecInternalError("xmlSecKeyAdoptData", NULL); goto done; } x509Data = NULL; /* owned by key now */ /* try to find key name */ rv = SEC_PKCS12DecoderIterateInit(p12ctx); if (rv != SECSuccess) { xmlSecNssError("SEC_PKCS12DecoderIterateInit", NULL); goto done; } /* read pkcs12 bags */ while (SEC_PKCS12DecoderIterateNext(p12ctx, &dip) == SECSuccess) { if((dip->friendlyName != NULL) && (dip->friendlyName->data != NULL) && (dip->friendlyName->len > 0) ) { ret = xmlSecKeySetNameEx(key, dip->friendlyName->data, dip->friendlyName->len); if(ret < 0) { xmlSecInternalError("xmlSecKeySetNameEx", NULL); goto done; } /* use the first one */ break; } } /* success */ res = key; key = NULL; done: if(tmpcert != NULL) { CERT_DestroyCertificate(tmpcert); } if(key != NULL) { xmlSecKeyDestroy(key); } if (p12ctx) { SEC_PKCS12DecoderFinish(p12ctx); } SECITEM_FreeItem(&uc2_pwditem, PR_FALSE); if (slot) { PK11_FreeSlot(slot); } if (certlist) { CERT_DestroyCertList(certlist); } if(x509Data != NULL) { xmlSecKeyDataDestroy(x509Data); } if(keyValueData != NULL) { xmlSecKeyDataDestroy(keyValueData); } if (privkey) { SECKEY_DestroyPrivateKey(privkey); } if (pubkey) { SECKEY_DestroyPublicKey(pubkey); } return(res); } /** * @brief Loads public key from cert. * @param secItem the SECItem object. * @param format the cert format. * @return pointer to key or NULL if an error occurs. */ xmlSecKeyPtr xmlSecNssAppKeyFromCertLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format) { xmlSecKeyPtr key = NULL; xmlSecKeyDataPtr keyData = NULL; xmlSecKeyDataPtr certData; CERTCertificate *cert = NULL; int ret; xmlSecKeyPtr res = NULL; xmlSecAssert2(secItem != NULL, NULL); xmlSecAssert2(secItem->type == siBuffer, NULL); xmlSecAssert2(secItem->data != NULL, NULL); xmlSecAssert2(secItem->len > 0, NULL); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); /* load cert */ switch(format) { case xmlSecKeyDataFormatCertDer: cert = xmlSecNssX509CertDerRead(CERT_GetDefaultCertDB(), secItem->data, secItem->len); if(cert == NULL) { xmlSecInternalError2("xmlSecNssX509CertDerRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); goto done; } break; case xmlSecKeyDataFormatCertPem: cert = xmlSecNssX509CertPemRead(CERT_GetDefaultCertDB(), secItem->data, secItem->len); if(cert == NULL) { xmlSecInternalError2("xmlSecNssX509CertPemRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); goto done; } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); goto done; } /* get key value */ keyData = xmlSecNssX509CertGetKey(cert); if(keyData == NULL) { xmlSecInternalError("xmlSecNssX509CertGetKey", NULL); goto done; } /* create key set key value */ key = xmlSecKeyCreate(); if(key == NULL) { xmlSecInternalError("xmlSecKeyCreate", NULL); goto done; } ret = xmlSecKeySetValue(key, keyData); if(ret < 0) { xmlSecInternalError("xmlSecKeySetValue", NULL); goto done; } keyData = NULL; /* owned by key now */ /* create cert data put key's cert into it */ certData = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id); if(certData == NULL) { xmlSecInternalError("xmlSecKeyEnsureData", NULL); goto done; } ret = xmlSecNssKeyDataX509AdoptKeyCert(certData, cert); if(ret < 0) { xmlSecInternalError("xmlSecNssKeyDataX509AdoptKeyCert", NULL); goto done; } cert = 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(res); } /** * @brief Reads a cert from a file and adds to the key store. * @details Reads cert from @p filename and adds to the list of trusted or known * untrusted certs in @p store. * * @param mngr the pointer to keys manager. * @param filename the certificate file. * @param format the certificate file format (PEM or DER). * @param type the certificate type (trusted/untrusted). * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename, xmlSecKeyDataFormat format, xmlSecKeyDataType type) { SECItem secItem = { siBuffer, NULL, 0 }; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(filename != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); /* read the file contents */ memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppReadSECItem(&secItem, filename); if(ret < 0) { xmlSecInternalError("xmlSecNssAppReadSECItem", NULL); return(-1); } ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type); if(ret < 0) { xmlSecInternalError("xmlSecNssAppKeysMngrCertLoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } SECITEM_FreeItem(&secItem, PR_FALSE); return(0); } /** * @brief Reads cert from buffer and adds to the key store. * @details Reads cert from @p data and adds to the list of trusted or known * untrusted certs in @p store. * * @param mngr the pointer to keys manager. * @param data the certificatedata. * @param dataSize the certificate data size. * @param format the certificate format (PEM or DER). * @param type the certificate type (trusted/untrusted). * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format, xmlSecKeyDataType type) { SECItem secItem = { siBuffer, NULL, 0 }; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize); if(ret < 0) { xmlSecInternalError("xmlSecNssAppCreateSECItem", NULL); return(-1); } ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type); if(ret < 0) { xmlSecInternalError("xmlSecNssAppKeysMngrCertLoadSECItem", NULL); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } SECITEM_FreeItem(&secItem, PR_FALSE); return(0); } /** * @brief Reads cert from SECItem and adds to the key store. * @details Reads cert from @p secItem and adds to the list of trusted or known * untrusted certs in @p store. * * @param mngr the pointer to keys manager. * @param secItem the pointer to SECItem. * @param format the certificate format (PEM or DER). * @param type the certificate type (trusted/untrusted). * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeysMngrCertLoadSECItem(xmlSecKeysMngrPtr mngr, SECItem* secItem, xmlSecKeyDataFormat format, xmlSecKeyDataType type) { xmlSecKeyDataStorePtr x509Store; CERTCertificate* cert; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(secItem != NULL, -1); xmlSecAssert2(secItem->type == siBuffer, -1); xmlSecAssert2(secItem->data != NULL, -1); xmlSecAssert2(secItem->len > 0, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId); if(x509Store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetDataStore(xmlSecNssX509StoreId)", NULL); return(-1); } switch(format) { case xmlSecKeyDataFormatDer: cert = xmlSecNssX509CertDerRead(CERT_GetDefaultCertDB(), secItem->data, secItem->len); if(cert == NULL) { xmlSecInternalError2("xmlSecNssX509CertDerRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); return(-1); } break; case xmlSecKeyDataFormatCertPem: cert = xmlSecNssX509CertPemRead(CERT_GetDefaultCertDB(), secItem->data, secItem->len); if(cert == NULL) { xmlSecInternalError2("xmlSecNssX509CertPemRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); return(-1); } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); return(-1); } ret = xmlSecNssX509StoreAdoptCert(x509Store, cert, type); if(ret < 0) { xmlSecInternalError("xmlSecNssX509StoreAdoptCert", NULL); CERT_DestroyCertificate(cert); return(-1); } return(0); } /** * @brief Reads CRLs from a file and adds to the store. * @details Reads crl from @p filename and adds to the list of crls in @p store. * * @param mngr the pointer to keys manager. * @param filename the CRL file. * @param format the CRL file format (PEM or DER). * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeysMngrCrlLoad(xmlSecKeysMngrPtr mngr, const char *filename, xmlSecKeyDataFormat format) { xmlSecKeyDataStorePtr x509Store; CERTSignedCrl* crl; SECItem secItem = { siBuffer, NULL, 0 }; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(filename != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId); if(x509Store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetDataStore(xmlSecNssX509StoreId)", NULL); return(-1); } /* read the file contents */ memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppReadSECItem(&secItem, filename); if((ret < 0) || (secItem.type != siBuffer) ||(secItem.data == NULL) || (secItem.len <= 0)) { xmlSecInternalError("xmlSecNssAppReadSECItem", NULL); return(-1); } /* read CRL */ switch(format) { case xmlSecKeyDataFormatDer: crl = xmlSecNssX509CrlDerRead(secItem.data, secItem.len, XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS); if(crl == NULL) { xmlSecInternalError2("xmlSecNssX509CrlDerRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } SECITEM_FreeItem(&secItem, PR_FALSE); /* Add CRL to the store */ ret = xmlSecNssX509StoreAdoptCrl(x509Store, crl); if(ret < 0) { xmlSecInternalError("xmlSecNssX509StoreAdoptCrl", NULL); SEC_DestroyCrl(crl); return(-1); } crl = NULL; /* owned by x509data now */ /* done */ return(0); } /** * @brief Loads and verifies a CRL from a file. * @details Atomically loads and verifies a CRL from @p filename. * * @param mngr the keys manager. * @param filename the CRL filename. * @param format the CRL format (PEM or DER). * @param keyInfoCtx the key info context for verification parameters. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeysMngrCrlLoadAndVerify(xmlSecKeysMngrPtr mngr, const char *filename, xmlSecKeyDataFormat format, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataStorePtr x509Store; CERTSignedCrl* crl = NULL; SECItem secItem = { siBuffer, NULL, 0 }; int ret; int res = -1; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(filename != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); /* Get X509 store from keys manager */ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId); if(x509Store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetDataStore(xmlSecNssX509StoreId)", NULL); return(-1); } /* Load CRL from file ONCE */ memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppReadSECItem(&secItem, filename); if((ret < 0) || (secItem.type != siBuffer) ||(secItem.data == NULL) || (secItem.len <= 0)) { xmlSecInternalError2("xmlSecNssAppReadSECItem", NULL, "filename=%s", xmlSecErrorsSafeString(filename)); goto done; } /* Read CRL from memory - do NOT skip verification checks */ switch(format) { case xmlSecKeyDataFormatDer: crl = xmlSecNssX509CrlDerRead(secItem.data, secItem.len, XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS); if(crl == NULL) { xmlSecInternalError2("xmlSecNssX509CrlDerRead", NULL, "filename=%s", xmlSecErrorsSafeString(filename)); goto done; } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); goto done; } /* Verify the in-memory CRL */ ret = xmlSecNssX509StoreVerifyCrl(x509Store, crl, keyInfoCtx); if(ret < 0) { xmlSecInternalError2("xmlSecNssX509StoreVerifyCrl", NULL, "filename=%s", xmlSecErrorsSafeString(filename)); goto done; } else if(ret != 1) { /* Verification failed - treat as error */ xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_DATA, NULL, "filename=%s", xmlSecErrorsSafeString(filename)); goto done; } /* Adopt the verified in-memory CRL */ ret = xmlSecNssX509StoreAdoptCrl(x509Store, crl); if(ret < 0) { xmlSecInternalError2("xmlSecNssX509StoreAdoptCrl", NULL, "filename=%s", xmlSecErrorsSafeString(filename)); goto done; } /* Success - CRL is now owned by store, don't free it */ crl = NULL; res = 0; done: SECITEM_FreeItem(&secItem, PR_FALSE); if(crl != NULL) { SEC_DestroyCrl(crl); } return(res); } /** * @brief Reads CRLs from memory and adds to the store. * @details Reads crl from @p data and adds to the list of crls in @p store. * * @param mngr the pointer to keys manager. * @param data the CRL data. * @param dataSize the CRL data size. * @param format the CRL format (PEM or DER). * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppKeysMngrCrlLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format) { xmlSecKeyDataStorePtr x509Store; CERTSignedCrl* crl; SECItem secItem = { siBuffer, NULL, 0 }; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId); if(x509Store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetDataStore(xmlSecNssX509StoreId)", NULL); return(-1); } memset(&secItem, 0, sizeof(secItem)); ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize); if(ret < 0) { xmlSecInternalError("xmlSecNssAppCreateSECItem", NULL); return(-1); } /* read CRL */ switch(format) { case xmlSecKeyDataFormatDer: crl = xmlSecNssX509CrlDerRead(secItem.data, secItem.len, XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS); if(crl == NULL) { xmlSecInternalError2("xmlSecNssX509CrlDerRead", NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } break; default: xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL, "format=" XMLSEC_ENUM_FMT, XMLSEC_ENUM_CAST(format)); SECITEM_FreeItem(&secItem, PR_FALSE); return(-1); } SECITEM_FreeItem(&secItem, PR_FALSE); /* Add CRL to the store */ ret = xmlSecNssX509StoreAdoptCrl(x509Store, crl); if(ret < 0) { xmlSecInternalError("xmlSecNssX509StoreAdoptCrl", NULL); SEC_DestroyCrl(crl); return(-1); } crl = NULL; /* owned by x509data now */ /* done */ return(0); } #endif /* XMLSEC_NO_X509 */ /** * @brief Initializes the default key manager for NSS. * @details Initializes @p mngr with NSS keys store #xmlSecNssKeysStoreId * and a default NSS crypto key data stores. * * @param mngr the pointer to keys manager. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppDefaultKeysMngrInit(xmlSecKeysMngrPtr mngr) { int ret; xmlSecAssert2(mngr != NULL, -1); /* create NSS keys store if needed */ if(xmlSecKeysMngrGetKeysStore(mngr) == NULL) { xmlSecKeyStorePtr keysStore; keysStore = xmlSecKeyStoreCreate(xmlSecNssKeysStoreId); if(keysStore == NULL) { xmlSecInternalError("xmlSecKeyStoreCreate(xmlSecNssX509StoreId)", NULL); return(-1); } ret = xmlSecKeysMngrAdoptKeysStore(mngr, keysStore); if(ret < 0) { xmlSecInternalError("xmlSecKeysMngrAdoptKeysStore", NULL); xmlSecKeyStoreDestroy(keysStore); return(-1); } } ret = xmlSecNssKeysMngrInit(mngr); if(ret < 0) { xmlSecInternalError("xmlSecNssKeysMngrInit", NULL); return(-1); } mngr->getKey = xmlSecKeysMngrGetKey; return(0); } /** * @brief Adds @p key to the keys manager. * @details Adds @p key to the keys manager @p mngr created with #xmlSecNssAppDefaultKeysMngrInit * function. * * @param mngr the pointer to keys manager. * @param key the pointer to key. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppDefaultKeysMngrAdoptKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key) { xmlSecKeyStorePtr store; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(key != NULL, -1); store = xmlSecKeysMngrGetKeysStore(mngr); if(store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetKeysStore", NULL); return(-1); } ret = xmlSecNssKeysStoreAdoptKey(store, key); if(ret < 0) { xmlSecInternalError("xmlSecNssKeysStoreAdoptKey", NULL); return(-1); } return(0); } /** * @brief Verifies @p key using the keys manager. * @details Verifies @p key with the keys manager @p mngr created with #xmlSecCryptoAppDefaultKeysMngrInit * function: * - Checks that key certificate is present * - Checks that key certificate is valid * * Adds @p key to the keys manager @p mngr created with #xmlSecCryptoAppDefaultKeysMngrInit * function. * * @param mngr the pointer to keys manager. * @param key the pointer to key. * @param keyInfoCtx the key info context for verification. * @return 1 if key is verified, 0 otherwise, or a negative value if an error occurs. */ int xmlSecNssAppDefaultKeysMngrVerifyKey(xmlSecKeysMngrPtr mngr, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) { #ifndef XMLSEC_NO_X509 xmlSecKeyDataStorePtr x509Store; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId); if(x509Store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetDataStore(xmlSecNssX509StoreId)", NULL); return(-1); } return(xmlSecNssX509StoreVerifyKey(x509Store, key, keyInfoCtx)); #else /* XMLSEC_NO_X509 */ xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); xmlSecNotImplementedError("X509 support is disabled during compilation"); return(-1); #endif /* XMLSEC_NO_X509 */ } /** * @brief Loads the XML keys file into the keys manager. * @details Loads XML keys file from @p uri to the keys manager @p mngr created * with #xmlSecNssAppDefaultKeysMngrInit function. * * @param mngr the pointer to keys manager. * @param uri the uri. * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppDefaultKeysMngrLoad(xmlSecKeysMngrPtr mngr, const char* uri) { xmlSecKeyStorePtr store; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(uri != NULL, -1); store = xmlSecKeysMngrGetKeysStore(mngr); if(store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetKeysStore", NULL); return(-1); } ret = xmlSecNssKeysStoreLoad(store, uri, mngr); if(ret < 0) { xmlSecInternalError2("xmlSecNssKeysStoreLoad", NULL, "uri=%s", xmlSecErrorsSafeString(uri)); return(-1); } return(0); } /** * @brief Saves keys from @p mngr to XML keys file. * @param mngr the pointer to keys manager. * @param filename the destination filename. * @param type the type of keys to save (public/private/symmetric). * @return 0 on success or a negative value otherwise. */ int xmlSecNssAppDefaultKeysMngrSave(xmlSecKeysMngrPtr mngr, const char* filename, xmlSecKeyDataType type) { xmlSecKeyStorePtr store; int ret; xmlSecAssert2(mngr != NULL, -1); xmlSecAssert2(filename != NULL, -1); store = xmlSecKeysMngrGetKeysStore(mngr); if(store == NULL) { xmlSecInternalError("xmlSecKeysMngrGetKeysStore", NULL); return(-1); } ret = xmlSecNssKeysStoreSave(store, filename, type); if(ret < 0) { xmlSecInternalError2("xmlSecNssKeysStoreSave", NULL, "filename=%s", xmlSecErrorsSafeString(filename)); return(-1); } return(0); } /** * @brief Gets default password callback. * * @return default password callback. */ void* xmlSecNssAppGetDefaultPwdCallback(void) { /* TODO: NSS doesn't support password callback */ return(NULL); }