diff options
Diffstat (limited to 'src/nss/app.c')
-rw-r--r-- | src/nss/app.c | 1598 |
1 files changed, 1598 insertions, 0 deletions
diff --git a/src/nss/app.c b/src/nss/app.c new file mode 100644 index 00000000..dabe36d1 --- /dev/null +++ b/src/nss/app.c @@ -0,0 +1,1598 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> + * Copyright (c) 2003 America Online, Inc. All rights reserved. + */ +#include "globals.h" + +#include <string.h> + +#include <nspr.h> +#include <nss.h> +#include <pk11func.h> +#include <cert.h> +#include <keyhi.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/nss/app.h> +#include <xmlsec/nss/crypto.h> +#include <xmlsec/nss/x509.h> +#include <xmlsec/nss/pkikeys.h> +#include <xmlsec/nss/keysstore.h> + +/* workaround - NSS exports this but doesn't declare it */ +extern CERTCertificate * __CERT_NewTempCertificate (CERTCertDBHandle *handle, + SECItem *derCert, + char *nickname, + PRBool isperm, + PRBool copyDER); +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 SECItem *xmlSecNssAppNicknameCollisionCallback (SECItem *old_nick, + PRBool *cancel, + void *wincx); +static xmlSecKeyPtr xmlSecNssAppDerKeyLoadSECItem (SECItem* secItem); + +/** + * xmlSecNssAppInit: + * @config: the path to NSS database files. + * + * General crypto engine initialization. This function is used + * by XMLSec command line utility and called before + * @xmlSecInit function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecNssAppInit(const char* config) { + SECStatus rv; + + if(config) { + rv = NSS_InitReadWrite(config); + if(rv != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "NSS_InitReadWrite", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "config=%s", + xmlSecErrorsSafeString(config)); + return(-1); + } + } else { + rv = NSS_NoDB_Init(NULL); + if(rv != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "NSS_NoDB_Init", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + 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); +} + +/** + * xmlSecNssAppShutdown: + * + * General crypto engine shutdown. This function is used + * by XMLSec command line utility and called after + * @xmlSecShutdown function. + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecNssAppShutdown(void) { + SECStatus rv; +/* + SSL_ClearSessionCache(); +*/ + PK11_LogoutAll(); + rv = NSS_Shutdown(); + if(rv != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "NSS_Shutdown", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); +} + + +static int +xmlSecNssAppCreateSECItem(SECItem *contents, const xmlSecByte* data, xmlSecSize dataSize) { + xmlSecAssert2(contents != NULL, -1); + xmlSecAssert2(data != NULL, -1); + + contents->data = 0; + if (!SECITEM_AllocItem(NULL, contents, dataSize)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SECITEM_AllocItem", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + if(dataSize > 0) { + xmlSecAssert2(contents->data != NULL, -1); + memcpy(contents->data, data, dataSize); + } + + return (0); +} + +static int +xmlSecNssAppReadSECItem(SECItem *contents, const char *fn) { + PRFileInfo info; + PRFileDesc *file = NULL; + PRInt32 numBytes; + PRStatus prStatus; + int ret = -1; + + xmlSecAssert2(contents != NULL, -1); + xmlSecAssert2(fn != NULL, -1); + + file = PR_Open(fn, PR_RDONLY, 00660); + if (file == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PR_Open", + XMLSEC_ERRORS_R_IO_FAILED, + "filename=%s", + xmlSecErrorsSafeString(fn)); + goto done; + } + + prStatus = PR_GetOpenFileInfo(file, &info); + if (prStatus != PR_SUCCESS) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PR_GetOpenFileInfo", + XMLSEC_ERRORS_R_IO_FAILED, + "filename=%s", + xmlSecErrorsSafeString(fn)); + goto done; + } + + contents->data = 0; + if (!SECITEM_AllocItem(NULL, contents, info.size)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SECITEM_AllocItem", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + 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 ATTRIBUTE_UNUSED) +{ + SECItem it; + + 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)); +} + +static SECItem * +xmlSecNssAppNicknameCollisionCallback(SECItem *old_nick ATTRIBUTE_UNUSED, + PRBool *cancel, + void *wincx ATTRIBUTE_UNUSED) +{ + if (cancel == NULL) { + return (NULL); + } + + /* XXX not handled yet */ + *cancel = PR_TRUE; + return (NULL); +} + +/** + * xmlSecNssAppKeyLoad: + * @filename: the key filename. + * @format: the key file format. + * @pwd: the key file password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from a file + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecNssAppKeyLoad(const char *filename, xmlSecKeyDataFormat format, + const char *pwd, void* pwdCallback, void* pwdCallbackCtx) { + SECItem secItem; + xmlSecKeyPtr res; + int ret; + + xmlSecAssert2(filename != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + /* read the file contents */ + memset(&secItem, 0, sizeof(secItem)); + ret = xmlSecNssAppReadSECItem(&secItem, filename); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppReadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeyLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(NULL); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(res); +} + +/** + * xmlSecNssAppKeyLoadMemory: + * @data: the key binary data. + * @dataSize: the key binary data size. + * @format: the key data format. + * @pwd: the key data2 password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from a binary @data. + * + * Returns: 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; + 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppCreateSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + res = xmlSecNssAppKeyLoadSECItem(&secItem, format, pwd, pwdCallback, pwdCallbackCtx); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeyLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(NULL); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(res); +} + +/** + * xmlSecNssAppKeyLoadSECItem: + * @secItem: the pointer to sec item. + * @format: the key format. + * @pwd: the key password. + * @pwdCallback: the key password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key from a file + * + * Returns: 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppPkcs12LoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; + case xmlSecKeyDataFormatCertDer: + key = xmlSecNssAppKeyFromCertLoadSECItem(secItem, format); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeyFromCertLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; +#endif /* XMLSEC_NO_X509 */ + case xmlSecKeyDataFormatDer: + key = xmlSecNssAppDerKeyLoadSECItem(secItem); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppDerKeyLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + break; + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeyLoad", + XMLSEC_ERRORS_R_INVALID_FORMAT, + "format=%d", 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; + 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssGetInternalKeySlot", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + 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 openssl 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SECKEY_DecodeDERSubjectPublicKeyInfo", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + } + + pubkey = SECKEY_ExtractPublicKey(spki); + if (pubkey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SECKEY_ExtractPublicKey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + } + + data = xmlSecNssPKIAdoptKey(privkey, pubkey); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssPKIAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + privkey = NULL; + pubkey = NULL; + + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(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); +} + +#ifndef XMLSEC_NO_X509 +/** + * xmlSecNssAppKeyCertLoad: + * @key: the pointer to key. + * @filename: the certificate filename. + * @format: the certificate file format. + * + * Reads the certificate from $@filename and adds it to key + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecNssAppKeyCertLoad(xmlSecKeyPtr key, const char* filename, xmlSecKeyDataFormat format) { + SECItem secItem; + 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppReadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeyCertLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(-1); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(0); +} + +/** + * xmlSecNssAppKeyCertLoadMemory: + * @key: the pointer to key. + * @data: the key binary data. + * @dataSize: the key binary data size. + * @format: the certificate format. + * + * Reads the certificate from @data and adds it to key + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecNssAppKeyCertLoadMemory(xmlSecKeyPtr key, const xmlSecByte* data, xmlSecSize dataSize, xmlSecKeyDataFormat format) { + SECItem secItem; + 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppCreateSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecNssAppKeyCertLoadSECItem(key, &secItem, format); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeyCertLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(-1); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(0); +} + +/** + * xmlSecNssAppKeyCertLoadSECItem: + * @key: the pointer to key. + * @secItem: the pointer to SECItem. + * @format: the certificate format. + * + * Reads the certificate from @secItem and adds it to key + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecNssAppKeyCertLoadSECItem(xmlSecKeyPtr key, SECItem* secItem, xmlSecKeyDataFormat format) { + CERTCertificate *cert=NULL; + xmlSecKeyDataPtr data; + int ret; + + xmlSecAssert2(key != NULL, -1); + xmlSecAssert2(secItem != NULL, -1); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1); + + data = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyEnsureData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "transform=%s", + xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id))); + return(-1); + } + + switch(format) { + case xmlSecKeyDataFormatPkcs8Der: + case xmlSecKeyDataFormatDer: + cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + secItem, NULL, PR_FALSE, PR_TRUE); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "__CERT_NewTempCertificate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "format=%d", format); + return(-1); + } + break; + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_FORMAT, + "format=%d", format); + return(-1); + } + + xmlSecAssert2(cert != NULL, -1); + ret = xmlSecNssKeyDataX509AdoptCert(data, cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(data))); + CERT_DestroyCertificate(cert); + return(-1); + } + + return(0); +} + +/** + * xmlSecNssAppPkcs12Load: + * @filename: the PKCS12 key filename. + * @pwd: the PKCS12 file password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 file. + * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecNssAppPkcs12Load(const char *filename, const char *pwd, + void *pwdCallback ATTRIBUTE_UNUSED, + void* pwdCallbackCtx ATTRIBUTE_UNUSED) { + SECItem secItem; + xmlSecKeyPtr res; + int ret; + + xmlSecAssert2(filename != NULL, NULL); + + /* read the file contents */ + memset(&secItem, 0, sizeof(secItem)); + ret = xmlSecNssAppReadSECItem(&secItem, filename); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppReadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppPkcs12LoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(NULL); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(res); +} + +/** + * xmlSecNssAppPkcs12LoadMemory: + * @data: the key binary data. + * @dataSize: the key binary data size. + * @pwd: the PKCS12 password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 binary data. + * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecNssAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize, const char *pwd, + void *pwdCallback ATTRIBUTE_UNUSED, + void* pwdCallbackCtx ATTRIBUTE_UNUSED) { + SECItem secItem; + xmlSecKeyPtr res; + int ret; + + xmlSecAssert2(data != NULL, NULL); + + memset(&secItem, 0, sizeof(secItem)); + ret = xmlSecNssAppCreateSECItem(&secItem, data, dataSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppCreateSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + res = xmlSecNssAppPkcs12LoadSECItem(&secItem, pwd, pwdCallback, pwdCallbackCtx); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppPkcs12LoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(NULL); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(res); +} + + +/** + * xmlSecNssAppPkcs12LoadSECItem: + * @secItem: the @SECItem object. + * @pwd: the PKCS12 file password. + * @pwdCallback: the password callback. + * @pwdCallbackCtx: the user context for password callback. + * + * Reads key and all associated certificates from the PKCS12 SECItem. + * For uniformity, call xmlSecNssAppKeyLoad instead of this function. Pass + * in format=xmlSecKeyDataFormatPkcs12. + * + * Returns: pointer to the key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecNssAppPkcs12LoadSECItem(SECItem* secItem, const char *pwd, + void *pwdCallback ATTRIBUTE_UNUSED, + void* pwdCallbackCtx ATTRIBUTE_UNUSED) { + xmlSecKeyPtr key = NULL; + xmlSecKeyDataPtr data = NULL; + xmlSecKeyDataPtr x509Data = NULL; + int ret; + PK11SlotInfo *slot = NULL; + SECItem pwditem; + SECItem uc2_pwditem; + SECStatus rv; + SECKEYPrivateKey *privkey = NULL; + SECKEYPublicKey *pubkey = NULL; + CERTCertList *certlist = NULL; + CERTCertListNode *head = NULL; + CERTCertificate *cert = NULL; + CERTCertificate *tmpcert = NULL; + SEC_PKCS12DecoderContext *p12ctx = 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssGetInternalKeySlot", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + pwditem.data = (unsigned char *)pwd; + pwditem.len = strlen(pwd)+1; + if (!SECITEM_AllocItem(NULL, &uc2_pwditem, 2*pwditem.len)) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SECITEM_AllocItem", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + if (PORT_UCS2_ASCIIConversion(PR_TRUE, pwditem.data, pwditem.len, + uc2_pwditem.data, 2*pwditem.len, + &(uc2_pwditem.len), 0) == PR_FALSE) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "PORT_UCS2_ASCIIConversion", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + p12ctx = SEC_PKCS12DecoderStart(&uc2_pwditem, slot, NULL, + NULL, NULL, NULL, NULL, NULL); + if (p12ctx == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SEC_PKCS12DecoderStart", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + rv = SEC_PKCS12DecoderUpdate(p12ctx, secItem->data, secItem->len); + if (rv != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SEC_PKCS12DecoderUpdate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + rv = SEC_PKCS12DecoderVerify(p12ctx); + if (rv != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SEC_PKCS12DecoderVerify", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + rv = SEC_PKCS12DecoderValidateBags(p12ctx, xmlSecNssAppNicknameCollisionCallback); + if (rv != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SEC_PKCS12DecoderValidateBags", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + rv = SEC_PKCS12DecoderImportBags(p12ctx); + if (rv != SECSuccess) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SEC_PKCS12DecoderImportBags", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + certlist = SEC_PKCS12DecoderGetCerts(p12ctx); + if (certlist == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "SEC_PKCS12DecoderGetCerts", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id); + if(x509Data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyDataCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "transform=%s", + xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id))); + 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 (data != NULL) { + /* we already found a private key. + * assume the first private key we find is THE ONE + */ + SECKEY_DestroyPrivateKey(privkey); + privkey = NULL; + } else { + pubkey = CERT_ExtractPublicKey(cert); + if (pubkey == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CERT_ExtractPublicKey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + data = xmlSecNssPKIAdoptKey(privkey, pubkey); + if(data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssPKIAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + pubkey = NULL; + privkey = NULL; + + tmpcert = CERT_DupCertificate(cert); + if(tmpcert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CERT_DupCertificate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + goto done; + } + + ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, tmpcert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeyDataX509AdoptKeyCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + CERT_DestroyCertificate(tmpcert); + goto done; + } + + } + } + + tmpcert = CERT_DupCertificate(cert); + if(tmpcert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CERT_DupCertificate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + goto done; + } + ret = xmlSecNssKeyDataX509AdoptCert(x509Data, tmpcert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + CERT_DestroyCertificate(tmpcert); + goto done; + } + + } /* end for loop */ + + if (data == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppPkcs12Load", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "private key not found in PKCS12 file"); + goto done; + } + + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + goto done; + } + + ret = xmlSecKeySetValue(key, data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + xmlSecKeyDestroy(key); + key = NULL; + goto done; + } + data = NULL; + + ret = xmlSecKeyAdoptData(key, x509Data); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyAdoptData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "data=%s", + xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); + xmlSecKeyDestroy(key); + key = NULL; + goto done; + } + x509Data = NULL; + +done: + 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(data != NULL) { + xmlSecKeyDataDestroy(data); + } + if (privkey) { + SECKEY_DestroyPrivateKey(privkey); + } + if (pubkey) { + SECKEY_DestroyPublicKey(pubkey); + } + + return(key); +} + +/** + * xmlSecNssAppKeyFromCertLoadSECItem: + * @secItem: the @SECItem object. + * @format: the cert format. + * + * Loads public key from cert. + * + * Returns: pointer to key or NULL if an error occurs. + */ +xmlSecKeyPtr +xmlSecNssAppKeyFromCertLoadSECItem(SECItem* secItem, xmlSecKeyDataFormat format) { + xmlSecKeyPtr key; + xmlSecKeyDataPtr keyData; + xmlSecKeyDataPtr certData; + CERTCertificate *cert=NULL; + int ret; + + xmlSecAssert2(secItem != NULL, NULL); + xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL); + + /* load cert */ + switch(format) { + case xmlSecKeyDataFormatCertDer: + cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + secItem, NULL, PR_FALSE, PR_TRUE); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "__CERT_NewTempCertificate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "format=%d", format); + return(NULL); + } + break; + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_FORMAT, + "format=%d", format); + return(NULL); + } + + /* get key value */ + keyData = xmlSecNssX509CertGetKey(cert); + if(keyData == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssX509CertGetKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + CERT_DestroyCertificate(cert); + return(NULL); + } + + /* create key */ + key = xmlSecKeyCreate(); + if(key == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDataDestroy(keyData); + CERT_DestroyCertificate(cert); + return(NULL); + } + + /* set key value */ + ret = xmlSecKeySetValue(key, keyData); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeySetValue", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + xmlSecKeyDataDestroy(keyData); + CERT_DestroyCertificate(cert); + return(NULL); + } + + /* create cert data */ + certData = xmlSecKeyEnsureData(key, xmlSecNssKeyDataX509Id); + if(certData == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyEnsureData", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + CERT_DestroyCertificate(cert); + return(NULL); + } + + /* put cert in the cert data */ + ret = xmlSecNssKeyDataX509AdoptCert(certData, cert); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeyDataX509AdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyDestroy(key); + CERT_DestroyCertificate(cert); + return(NULL); + } + + return(key); +} + + +/** + * xmlSecNssAppKeysMngrCertLoad: + * @mngr: the pointer to keys manager. + * @filename: the certificate file. + * @format: the certificate file format (PEM or DER). + * @type: the certificate type (trusted/untrusted). + * + * Reads cert from @filename and adds to the list of trusted or known + * untrusted certs in @store + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecNssAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, const char *filename, + xmlSecKeyDataFormat format, + xmlSecKeyDataType type) { + SECItem secItem; + 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppReadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeysMngrCertLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(-1); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(0); +} + +/** + * xmlSecNssAppKeysMngrCertLoadMemory: + * @mngr: the pointer to keys manager. + * @data: the key binary data. + * @dataSize: the key binary data size. + * @format: the certificate format (PEM or DER). + * @type: the certificate type (trusted/untrusted). + * + * Reads cert from @data and adds to the list of trusted or known + * untrusted certs in @store + * + * Returns: 0 on success or a negative value otherwise. + */ +int +xmlSecNssAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr, const xmlSecByte* data, + xmlSecSize dataSize, xmlSecKeyDataFormat format, + xmlSecKeyDataType type) { + SECItem secItem; + 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppCreateSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecNssAppKeysMngrCertLoadSECItem(mngr, &secItem, format, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssAppKeysMngrCertLoadSECItem", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + SECITEM_FreeItem(&secItem, PR_FALSE); + return(-1); + } + + SECITEM_FreeItem(&secItem, PR_FALSE); + return(0); +} + +/** + * xmlSecNssAppKeysMngrCertLoadSECItem: + * @mngr: the pointer to keys manager. + * @secItem: the pointer to SECItem. + * @format: the certificate format (PEM or DER). + * @type: the certificate type (trusted/untrusted). + * + * Reads cert from @secItem and adds to the list of trusted or known + * untrusted certs in @store + * + * Returns: 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(format != xmlSecKeyDataFormatUnknown, -1); + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecNssX509StoreId); + if(x509Store == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecNssX509StoreId"); + return(-1); + } + + switch(format) { + case xmlSecKeyDataFormatDer: + cert = __CERT_NewTempCertificate(CERT_GetDefaultCertDB(), + secItem, NULL, PR_FALSE, PR_TRUE); + if(cert == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "__CERT_NewTempCertificate", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "format=%d", format); + return(-1); + } + break; + default: + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_INVALID_FORMAT, + "format=%d", format); + return(-1); + } + + ret = xmlSecNssX509StoreAdoptCert(x509Store, cert, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssX509StoreAdoptCert", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + CERT_DestroyCertificate(cert); + return(-1); + } + + return(0); +} + +#endif /* XMLSEC_NO_X509 */ + +/** + * xmlSecNssAppDefaultKeysMngrInit: + * @mngr: the pointer to keys manager. + * + * Initializes @mngr with NSS keys store #xmlSecNssKeysStoreId + * and a default NSS crypto key data stores. + * + * Returns: 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeyStoreCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "xmlSecNssKeysStoreId"); + return(-1); + } + + ret = xmlSecKeysMngrAdoptKeysStore(mngr, keysStore); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrAdoptKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecKeyStoreDestroy(keysStore); + return(-1); + } + } + + ret = xmlSecNssKeysMngrInit(mngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeysMngrInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + mngr->getKey = xmlSecKeysMngrGetKey; + return(0); +} + +/** + * xmlSecNssAppDefaultKeysMngrAdoptKey: + * @mngr: the pointer to keys manager. + * @key: the pointer to key. + * + * Adds @key to the keys manager @mngr created with #xmlSecNssAppDefaultKeysMngrInit + * function. + * + * Returns: 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecNssKeysStoreAdoptKey(store, key); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeysStoreAdoptKey", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + return(0); +} + +/** + * xmlSecNssAppDefaultKeysMngrLoad: + * @mngr: the pointer to keys manager. + * @uri: the uri. + * + * Loads XML keys file from @uri to the keys manager @mngr created + * with #xmlSecNssAppDefaultKeysMngrInit function. + * + * Returns: 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecNssKeysStoreLoad(store, uri, mngr); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeysStoreLoad", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "uri=%s", xmlSecErrorsSafeString(uri)); + return(-1); + } + + return(0); +} + +/** + * xmlSecNssAppDefaultKeysMngrSave: + * @mngr: the pointer to keys manager. + * @filename: the destination filename. + * @type: the type of keys to save (public/private/symmetric). + * + * Saves keys from @mngr to XML keys file. + * + * Returns: 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecKeysMngrGetKeysStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + ret = xmlSecNssKeysStoreSave(store, filename, type); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecNssKeysStoreSave", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "filename%s", xmlSecErrorsSafeString(filename)); + return(-1); + } + + return(0); +} + +/** + * xmlSecNssAppGetDefaultPwdCallback: + * + * Gets default password callback. + * + * Returns: default password callback. + */ +void* +xmlSecNssAppGetDefaultPwdCallback(void) { + return(NULL); +} + |