[xmlsec] Dos the XMLSec library support multithreading?
StackWood
stackwood at 263.net
Wed May 12 23:26:50 PDT 2004
dear,
I have to paste my program below, and I appreciate your check for me.
I compile with gcc in LINUX9 and use openssl to encrypt.
When I begin to encryption, I just use only one thread but program fail in function xmlSecEncCtxXmlEncrypt(), the error message is "Segmentation fault". Now I expect to run in multithreading enviroment, so I wish to get some help. I appreciate you.
************************************************encrypt.c**************************************************************
#define XMLSEC_CRYPTO_OPENSSL //use openssl to encrypt
#include <pthread.h> //the multithreading is needed
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#ifndef XMLSEC_NO_XSLT
#include <libxslt/xslt.h>
#endif /* XMLSEC_NO_XSLT */
#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
#include <xmlsec/xmlenc.h>
#include <xmlsec/templates.h>
#include <xmlsec/crypto.h>
struct fileInfo
{
char *xmlFile;
char *nodeName;
// char *keyFile;
xmlSecKeysMngrPtr mngr;
};
xmlSecKeysMngrPtr load_rsa_keys(xmlSecKeysMngrPtr mngr, char* key_file);
int encrypt_file(struct fileInfo *xmlInfo);
int main(int argc, char **argv)
{
xmlSecKeysMngrPtr mngr;
pthread_t id;
struct fileInfo *xmlInfo;
int num,i,ret;
if (argc<2||((argc-1)%3)!=0)
{
fprintf(stderr, "Error: wrong number of arguments.\n");
fprintf(stderr, "Usage: %s <xml-file> <node-name> <key-file> [<xml-file> ...] ...\n", argv[0]);
fprintf(stderr, "Usage: %s <XML file name> <node name want to encrypt in XML file> <encrypt key file name>...\n", argv[0]);
return(1);
}
num=(argc-1)/3;
xmlInfo=(struct fileInfo *)malloc(sizeof(struct fileInfo));
/* Init libxml and libxslt libraries */
xmlInitParser();
LIBXML_TEST_VERSION
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
xmlSubstituteEntitiesDefault(1);
#ifndef XMLSEC_NO_XSLT
xmlIndentTreeOutput = 1;
#endif /* XMLSEC_NO_XSLT */
/* Init xmlsec library */
if(xmlSecInit() < 0) {
fprintf(stderr, "Error: xmlsec initialization failed.\n");
return(-1);
}
/* Check loaded library version */
if(xmlSecCheckVersion() != 1) {
fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
return(-1);
}
/* Load default crypto engine if we are supporting dynamic
* loading for xmlsec-crypto libraries. Use the crypto library
* name ("openssl", "nss", etc.) to load corresponding
* xmlsec-crypto library.
*/
#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
"that you have it installed and check shared libraries path\n"
"(LD_LIBRARY_PATH) envornment variable.\n");
return(-1);
}
#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
/* Init crypto library */
if(xmlSecCryptoAppInit(NULL) < 0) {
fprintf(stderr, "Error: crypto initialization failed.\n");
return(-1);
}
/* Init xmlsec-crypto library */
if(xmlSecCryptoInit() < 0) {
fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
return(-1);
}
/* init xmlSecKeysMngrPtr in the main */
mngr = xmlSecKeysMngrCreate();
if(mngr == NULL) {
fprintf(stderr, "Error: failed to create keys manager.\n");
return(-1);
}
if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
fprintf(stderr, "Error: failed to initialize keys manager.\n");
xmlSecKeysMngrDestroy(mngr);
return(-1);
}
fprintf(stderr, "Begine to process in thread.\n");
/* begin to enter thread to process */
for (i=0;i<num;i++)
{
xmlInfo->xmlFile=argv[3*i+1];
xmlInfo->nodeName=argv[3*i+2];
/* load keys into key manager*/
mngr = load_rsa_keys(mngr, argv[3*i+3]);
if(mngr == NULL) {
goto end;
}
xmlInfo->mngr=mngr;
ret=pthread_create(&id,NULL,(void *) encrypt_file,(void *) xmlInfo);
if(ret!=0)
{
fprintf(stderr, "ERROR: Create pthread error!\n");
return(-1);
}
}
end:
/* destroy keys manager */
xmlSecKeysMngrDestroy(mngr);
/* Shutdown xmlsec-crypto library */
xmlSecCryptoShutdown();
/* Shutdown crypto library */
xmlSecCryptoAppShutdown();
/* Shutdown xmlsec library */
xmlSecShutdown();
/* Shutdown libxslt/libxml */
#ifndef XMLSEC_NO_XSLT
xsltCleanupGlobals();
#endif /* XMLSEC_NO_XSLT */
xmlCleanupParser();
free(xmlInfo);
return(0);
}
/**
* load_rsa_keys:
* @key_file: the key filename.
*
* Creates simple keys manager and load RSA key from #key_file in it.
* The caller is responsible for destroing returned keys manager using
* @xmlSecKeysMngrDestroy.
*
* Returns the pointer to newly created keys manager or NULL if an error
* occurs.
*/
xmlSecKeysMngrPtr load_rsa_keys(xmlSecKeysMngrPtr mngr, char* key_file) {
xmlSecKeyPtr key;
BIO *keyIO;
assert(key_file);
/* get public key from input certificate */
if ((keyIO = BIO_new(BIO_s_file())) == NULL)
{
fprintf(stderr,"Error: failed to create BIO file \n");
return;
}
if (BIO_read_filename(keyIO,key_file) <= 0)
{
fprintf(stderr,"Error: failed to read certificate from file \"%s\"\n", key_file);
BIO_free(keyIO);
return;
}
key=xmlSecOpenSSLAppKeyFromCertLoadBIO(keyIO,xmlSecKeyDataFormatPem);
if(key == NULL) {
fprintf(stderr,"Error: failed to load rsa key from file \"%s\"\n", key_file);
xmlSecKeysMngrDestroy(mngr);
return(NULL);
}
/* set key name to the file name, this is just an example! */
if(xmlSecKeySetName(key, BAD_CAST "prvkey.pem") < 0) {
fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
xmlSecKeyDestroy(key);
xmlSecKeysMngrDestroy(mngr);
return(NULL);
}
/* add key to keys manager, from now on keys manager is responsible
* for destroying key
*/
if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", key_file);
xmlSecKeyDestroy(key);
xmlSecKeysMngrDestroy(mngr);
return(NULL);
}
fprintf(stderr, "End to complete mngr.\n");
return(mngr);
}
/**
* encrypt_file:
* @mngr: the pointer to keys manager.
* @xml_file: the encryption template file name.
* @key_name: the RSA key name.
*
* Encrypts #xml_file using a dynamicaly created template, a session DES key
* and an RSA key from keys manager.
*
* Returns 0 on success or a negative value if an error occurs.
*/
int encrypt_file(struct fileInfo *xmlInfo)
{
xmlDocPtr doc = NULL;
xmlNodePtr encDataNode = NULL;
xmlNodePtr keyInfoNode = NULL;
xmlNodePtr encKeyNode = NULL;
xmlNodePtr keyInfoNode2 = NULL;
xmlSecEncCtxPtr encCtx = NULL;
xmlNodePtr encNode = NULL;
xmlSecKeysMngrPtr mngr;
int id;
int res = -1;
FILE *fp;
char* xml_node;
char* xml_file;
// char* xml_key;
char saveName[20];
xml_file=xmlInfo->xmlFile;
xml_node=xmlInfo->nodeName;
// xml_key=xmlInfo->keyFile;
mngr=xmlInfo->mngr;
#if 0
/* load keys into key manager*/
mngr = load_rsa_keys(mngr, xml_key);
if(mngr == NULL) {
goto done;
}
#endif
/* load temilate */
doc = xmlParseFile(xml_file);
if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
goto done;
}
/* this is a sample that find Signature node to be encrypted */
encNode = xmlSecFindNode(xmlDocGetRootElement(doc), xml_node, NULL);
if(encNode == NULL) {
fprintf(stderr, "Error: not found %s Node \n", xml_node);
goto done;
}
encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformAes128CbcId,
NULL, xmlSecTypeEncElement, NULL, NULL);
if(encDataNode == NULL) {
fprintf(stderr, "Error: failed to create encryption template\n");
goto done;
}
/* we want to put encrypted data in the <enc:CipherValue/> node */
if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) {
fprintf(stderr, "Error: failed to add CipherValue node\n");
goto done;
}
/* add <dsig:KeyInfo/> */
keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
if(keyInfoNode == NULL) {
fprintf(stderr, "Error: failed to add key info\n");
goto done;
}
/* add <enc:EncryptedKey/> to store the encrypted session key */
encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode,
xmlSecTransformRsaPkcs1Id,
NULL, NULL, NULL);
if(encKeyNode == NULL) {
fprintf(stderr, "Error: failed to add key info\n");
goto done;
}
/* we want to put encrypted key in the <enc:CipherValue/> node */
if(xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) {
fprintf(stderr, "Error: failed to add CipherValue node\n");
goto done;
}
/* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/> */
keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL);
if(keyInfoNode2 == NULL) {
fprintf(stderr, "Error: failed to add key info\n");
goto done;
}
/* set key name so we can lookup key when needed */
if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode2, "Private Key") == NULL) {
fprintf(stderr, "Error: failed to add key name\n");
goto done;
}
/* create encryption context */
encCtx = xmlSecEncCtxCreate(mngr);
if(encCtx == NULL) {
fprintf(stderr,"Error: failed to create encryption context\n");
goto done;
}
/* generate a AES128 key */
encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataAesId, 128, xmlSecKeyDataTypeSession);
if(encCtx->encKey == NULL) {
fprintf(stderr,"Error: failed to generate session des key\n");
goto done;
}
fprintf(stderr,"Begine to encrypt the Node...\n");
/* encrypt the data */
if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, encNode) < 0) {
fprintf(stderr,"Error: encryption failed\n");
goto done;
}
fprintf(stderr,"End to encrypt the Node...\n");
/* we template is inserted in the doc */
encDataNode = NULL;
/* print encrypted data with document to stdout */
xmlDocDump(stdout, doc);
/* save to file by the threadID name */
id=pthread_self();
id=abs(id);
sprintf(saveName, "%d.xml", id);
if((fp=fopen(saveName, "w"))==NULL)
{
fprintf(stderr,"ERROR: cannot open file %s.",saveName);
goto done;
}
/* print encrypted data with document to file */
xmlDocDump(fp, doc);
/* success */
res = 0;
done:
/* cleanup */
if(encCtx != NULL) {
xmlSecEncCtxDestroy(encCtx);
}
if(encDataNode != NULL) {
xmlFreeNode(encDataNode);
}
if(doc != NULL) {
xmlFreeDoc(doc);
}
return(res);
}
**************************************************************************************************************
>Yes, the library does support multithreading. xmlSecSigCtx
>and xmlSecEncCtx are supposed to be used to do one signature
>at a time and from one thread at a time. xmlSecKeysMngr can
>be shared by many threads *for reading*. There are no
>sychronizaton inside the library itself. If you want to read
>and write to xmlSecKeysMngr in the same time then you have
>to implement your own keys manager.
>
>You did not provide information about OS/crypto library you use
>or the stack of your crash. It might happen that there is an issue
>with particular crypto library that might require additional "per
>thread" initialization.
>
>Aleksey
>
Best,
StackWood
stackwood at 263.net
2004-05-12
More information about the xmlsec
mailing list