xmlsecurityengine/xmlsec/src/xmlsec_keyinfo.c
changeset 0 e35f40988205
child 16 d10d750052f0
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /** 
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * <dsig:KeyInfo/> element processing 
       
     5  * (http://www.w3.org/TR/xmlSec-core/#sec-KeyInfo:
       
     6  *
       
     7  * The KeyInfo Element
       
     8  *
       
     9  * KeyInfo is an optional element that enables the recipient(s) to obtain 
       
    10  * the key needed to validate the signature.  KeyInfo may contain keys, 
       
    11  * names, certificates and other public key management information, such as 
       
    12  * in-band key distribution or key agreement data. 
       
    13  * 
       
    14  *  Schema Definition:
       
    15  *
       
    16  *  <element name="KeyInfo" type="ds:KeyInfoType"/> 
       
    17  *  <complexType name="KeyInfoType" mixed="true">
       
    18  *    <choice maxOccurs="unbounded"> 
       
    19  *       <element ref="ds:KeyName"/> 
       
    20  *       <element ref="ds:KeyValue"/> 
       
    21  *       <element ref="ds:RetrievalMethod"/> 
       
    22  *       <element ref="ds:X509Data"/> 
       
    23  *       <element ref="ds:PGPData"/> 
       
    24  *       <element ref="ds:SPKIData"/>
       
    25  *       <element ref="ds:MgmtData"/>
       
    26  *       <any processContents="lax" namespace="##other"/>
       
    27  *       <!-- (1,1) elements from (0,unbounded) namespaces -->
       
    28  *    </choice>
       
    29  *    <attribute name="Id" type="ID" use="optional"/>
       
    30  *  </complexType>
       
    31  *    
       
    32  * DTD:
       
    33  *    
       
    34  * <!ELEMENT KeyInfo (#PCDATA|KeyName|KeyValue|RetrievalMethod|
       
    35  *                    X509Data|PGPData|SPKIData|MgmtData %KeyInfo.ANY;)* >      
       
    36  * <!ATTLIST KeyInfo  Id  ID   #IMPLIED >
       
    37  *  
       
    38  *
       
    39  * This is free software; see Copyright file in the source
       
    40  * distribution for preciese wording.
       
    41  * 
       
    42  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
       
    43  */
       
    44 #include "xmlsec_globals.h"
       
    45 
       
    46 #include <stdlib.h>
       
    47 #include <string.h>
       
    48  
       
    49 #include <libxml2_tree.h>
       
    50 #include <libxml2_globals.h>
       
    51 
       
    52 #include "xmlsec_xmlsec.h"
       
    53 #include "xmlsec_xmltree.h"
       
    54 #include "xmlsec_base64.h"
       
    55 #include "xmlsec_keys.h"
       
    56 #include "xmlsec_keysmngr.h"
       
    57 #include "xmlsec_transforms.h"
       
    58 #include "xmlsec_xmlenc.h"
       
    59 #include "xmlsec_keyinfo.h"
       
    60 #include "xmlsec_errors.h"
       
    61 
       
    62 
       
    63 /**************************************************************************
       
    64  *
       
    65  * Hi level functions
       
    66  *
       
    67  *************************************************************************/
       
    68 /**
       
    69  * xmlSecKeyInfoNodeRead:
       
    70  * @keyInfoNode: 	the pointer to <dsig:KeyInfo/> node.
       
    71  * @key:		the pointer to result key object.
       
    72  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
    73  *
       
    74  * Parses the <dsig:KeyInfo/> element @keyInfoNode, extracts the key data
       
    75  * and stores into @key.
       
    76  *
       
    77  * Returns 0 on success or -1 if an error occurs.
       
    78  */
       
    79 EXPORT_C
       
    80 int
       
    81 xmlSecKeyInfoNodeRead(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
    82     const xmlChar* nodeName;
       
    83     const xmlChar* nodeNs;
       
    84     xmlSecKeyDataId dataId;
       
    85     xmlNodePtr cur;
       
    86     int ret;
       
    87     
       
    88     xmlSecAssert2(keyInfoNode != NULL, -1);
       
    89     xmlSecAssert2(key != NULL, -1);
       
    90     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
    91     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
       
    92 
       
    93     for(cur = xmlSecGetNextElementNode(keyInfoNode->children); 
       
    94 	(cur != NULL) && 
       
    95 	(((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND) != 0) || 
       
    96 	 (xmlSecKeyIsValid(key) == 0) || 
       
    97 	 (xmlSecKeyMatch(key, NULL, &(keyInfoCtx->keyReq)) == 0));
       
    98 	cur = xmlSecGetNextElementNode(cur->next)) {
       
    99     
       
   100 	/* find data id */
       
   101 	nodeName = cur->name;
       
   102 	nodeNs = xmlSecGetNodeNsHref(cur);
       
   103 	
       
   104 	/* use global list only if we don't have a local one */
       
   105 	if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
       
   106 	    dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
       
   107 			    nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
       
   108 	} else {	
       
   109     	    dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
       
   110 			    nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
       
   111 	}
       
   112 	if(dataId != xmlSecKeyDataIdUnknown) {
       
   113 	    /* read data node */
       
   114 	    ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
       
   115 	    if(ret < 0) {
       
   116 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   117 			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
       
   118 			    "xmlSecKeyDataXmlRead",
       
   119 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   120 			    "node=%s", 
       
   121 			    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   122 		return(-1);
       
   123 	    }
       
   124 	} else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
       
   125 	    /* there is a laxi schema validation but application may
       
   126 	     * desire to disable unknown nodes*/
       
   127 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   128 			NULL,
       
   129 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   130 			XMLSEC_ERRORS_R_INVALID_NODE,
       
   131 			XMLSEC_ERRORS_NO_MESSAGE);
       
   132 	    return(-1);
       
   133 	}
       
   134     }
       
   135     
       
   136     return(0);    
       
   137 }
       
   138 
       
   139 /**
       
   140  * xmlSecKeyInfoNodeWrite:
       
   141  * @keyInfoNode: 	the pointer to <dsig:KeyInfo/> node.
       
   142  * @key:		the pointer to key object.
       
   143  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   144  *
       
   145  * Writes the @key into the <dsig:KeyInfo/> element template @keyInfoNode.
       
   146  *
       
   147  * Returns 0 on success or -1 if an error occurs.
       
   148  */
       
   149 EXPORT_C
       
   150 int 
       
   151 xmlSecKeyInfoNodeWrite(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   152     const xmlChar* nodeName;
       
   153     const xmlChar* nodeNs;
       
   154     xmlSecKeyDataId dataId;
       
   155     xmlNodePtr cur;
       
   156     int ret;
       
   157     
       
   158     xmlSecAssert2(keyInfoNode != NULL, -1);
       
   159     xmlSecAssert2(key != NULL, -1);
       
   160     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
   161     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
       
   162 
       
   163     for(cur = xmlSecGetNextElementNode(keyInfoNode->children); 
       
   164 	cur != NULL;
       
   165 	cur = xmlSecGetNextElementNode(cur->next)) {
       
   166     
       
   167 	/* find data id */
       
   168 	nodeName = cur->name;
       
   169 	nodeNs = xmlSecGetNodeNsHref(cur);
       
   170 
       
   171 	/* use global list only if we don't have a local one */
       
   172 	if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
       
   173         	dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
       
   174 			    nodeName, nodeNs, 
       
   175 			    xmlSecKeyDataUsageKeyInfoNodeWrite);
       
   176 	} else {
       
   177         	dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
       
   178 			    nodeName, nodeNs, 
       
   179 			    xmlSecKeyDataUsageKeyInfoNodeWrite);
       
   180 	}
       
   181 	if(dataId != xmlSecKeyDataIdUnknown) {
       
   182 	    ret = xmlSecKeyDataXmlWrite(dataId, key, cur, keyInfoCtx);
       
   183 	    if(ret < 0) {
       
   184 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   185 			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
       
   186 			    "xmlSecKeyDataXmlWrite",
       
   187 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   188 			    "node=%s", 
       
   189 			    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   190 		return(-1);
       
   191 	    }
       
   192 	} else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
       
   193 	    /* laxi schema validation but application can disable it*/
       
   194 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   195 			NULL,
       
   196 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   197 			XMLSEC_ERRORS_R_INVALID_NODE,
       
   198 			XMLSEC_ERRORS_NO_MESSAGE);
       
   199 	    return(-1);
       
   200 	}
       
   201     }
       
   202     
       
   203     return(0);
       
   204 } 
       
   205 
       
   206 /**************************************************************************
       
   207  *
       
   208  * KeyInfo context
       
   209  *
       
   210  *************************************************************************/
       
   211 /**
       
   212  * xmlSecKeyInfoCtxCreate:
       
   213  * @keysMngr: 		the pointer to keys manager (may be NULL).
       
   214  *
       
   215  * Allocates and initializes <dsig:KeyInfo/> element processing context.
       
   216  * Caller is responsible for freeing it by calling #xmlSecKeyInfoCtxDestroy 
       
   217  * function.
       
   218  *
       
   219  * Returns pointer to newly allocated object or NULL if an error occurs.
       
   220  */
       
   221 EXPORT_C
       
   222 xmlSecKeyInfoCtxPtr 
       
   223 xmlSecKeyInfoCtxCreate(xmlSecKeysMngrPtr keysMngr) {
       
   224     xmlSecKeyInfoCtxPtr keyInfoCtx;
       
   225     int ret;
       
   226     
       
   227     /* Allocate a new xmlSecKeyInfoCtx and fill the fields. */
       
   228     keyInfoCtx = (xmlSecKeyInfoCtxPtr)xmlMalloc(sizeof(xmlSecKeyInfoCtx));
       
   229     if(keyInfoCtx == NULL) {
       
   230 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   231 		    NULL,
       
   232 		    NULL,
       
   233 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   234 		    "size=%d", sizeof(xmlSecKeyInfoCtx)); 
       
   235 	return(NULL);
       
   236     }
       
   237     
       
   238     ret = xmlSecKeyInfoCtxInitialize(keyInfoCtx, keysMngr);
       
   239     if(ret < 0) {
       
   240 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   241 		    NULL,
       
   242 		    "xmlSecKeyInfoCtxInitialize",
       
   243 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   244 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   245 	xmlSecKeyInfoCtxDestroy(keyInfoCtx);
       
   246 	return(NULL);
       
   247     }
       
   248     
       
   249     return(keyInfoCtx);
       
   250 }
       
   251 
       
   252 /** 
       
   253  * xmlSecKeyInfoCtxDestroy:
       
   254  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   255  *
       
   256  * Destroys @keyInfoCtx object created with #xmlSecKeyInfoCtxCreate function.
       
   257  */
       
   258 EXPORT_C
       
   259 void 
       
   260 xmlSecKeyInfoCtxDestroy(xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   261     xmlSecAssert(keyInfoCtx != NULL);
       
   262     
       
   263     xmlSecKeyInfoCtxFinalize(keyInfoCtx);
       
   264     xmlFree(keyInfoCtx);
       
   265 }
       
   266 
       
   267 /** 
       
   268  * xmlSecKeyInfoCtxInitialize:
       
   269  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   270  * @keysMngr: 		the pointer to keys manager (may be NULL).
       
   271  *
       
   272  * Initializes <dsig:KeyInfo/> element processing context. Caller is 
       
   273  * responsible for cleaning it up by #xmlSecKeyInfoCtxFinalize function.
       
   274  * 
       
   275  * Returns 0 on success and a negative value if an error occurs.
       
   276  */
       
   277 EXPORT_C
       
   278 int 
       
   279 xmlSecKeyInfoCtxInitialize(xmlSecKeyInfoCtxPtr keyInfoCtx, xmlSecKeysMngrPtr keysMngr) {
       
   280     int ret;
       
   281     
       
   282     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
   283     
       
   284     memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
       
   285     keyInfoCtx->keysMngr = keysMngr;
       
   286     keyInfoCtx->base64LineSize = XMLSEC_BASE64_LINESIZE;    
       
   287     ret = xmlSecPtrListInitialize(&(keyInfoCtx->enabledKeyData), xmlSecKeyDataIdListId);
       
   288     if(ret < 0) {
       
   289 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   290 		    NULL,
       
   291 		    "xmlSecPtrListInitialize",
       
   292 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   293 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   294 	return(-1);
       
   295     }
       
   296 
       
   297     keyInfoCtx->maxRetrievalMethodLevel = 1;
       
   298     ret = xmlSecTransformCtxInitialize(&(keyInfoCtx->retrievalMethodCtx));
       
   299     if(ret < 0) {
       
   300 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   301 		    NULL,
       
   302 		    "xmlSecTransformCtxInitialize",
       
   303 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   304 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   305 	return(-1);
       
   306     }
       
   307 
       
   308 #ifndef XMLSEC_NO_XMLENC
       
   309     keyInfoCtx->maxEncryptedKeyLevel = 1;
       
   310 #endif /* XMLSEC_NO_XMLENC */
       
   311 
       
   312 #ifndef XMLSEC_NO_X509
       
   313     keyInfoCtx->certsVerificationDepth= 9;
       
   314 #endif /* XMLSEC_NO_X509 */
       
   315 
       
   316     ret = xmlSecKeyReqInitialize(&(keyInfoCtx->keyReq));
       
   317     if(ret < 0) {
       
   318 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   319 		    NULL,
       
   320 		    "xmlSecKeyReqInitialize",
       
   321 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   322 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   323 	return(-1);
       
   324     }
       
   325         
       
   326     return(0);
       
   327 }
       
   328 
       
   329 /** 
       
   330  * xmlSecKeyInfoCtxFinalize:
       
   331  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   332  *
       
   333  * Cleans up the @keyInfoCtx initialized with #xmlSecKeyInfoCtxInitialize
       
   334  * function.
       
   335  */
       
   336 EXPORT_C
       
   337 void 
       
   338 xmlSecKeyInfoCtxFinalize(xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   339     xmlSecAssert(keyInfoCtx != NULL);
       
   340     
       
   341     xmlSecPtrListFinalize(&(keyInfoCtx->enabledKeyData));
       
   342     xmlSecTransformCtxFinalize(&(keyInfoCtx->retrievalMethodCtx));
       
   343     xmlSecKeyReqFinalize(&(keyInfoCtx->keyReq));
       
   344 
       
   345 #ifndef XMLSEC_NO_XMLENC
       
   346     if(keyInfoCtx->encCtx != NULL) {
       
   347         xmlSecEncCtxDestroy(keyInfoCtx->encCtx);
       
   348     }
       
   349 #endif /* XMLSEC_NO_XMLENC */
       
   350 
       
   351     memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
       
   352 }
       
   353 
       
   354 /** 
       
   355  * xmlSecKeyInfoCtxReset:
       
   356  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   357  * 
       
   358  * Resets the @keyInfoCtx state. User settings are not changed.
       
   359  */
       
   360 EXPORT_C
       
   361 void 
       
   362 xmlSecKeyInfoCtxReset(xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   363     xmlSecAssert(keyInfoCtx != NULL);
       
   364     
       
   365     xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
       
   366     keyInfoCtx->curRetrievalMethodLevel = 0;
       
   367 
       
   368 #ifndef XMLSEC_NO_XMLENC
       
   369     if(keyInfoCtx->encCtx != NULL) { 	   
       
   370         xmlSecEncCtxReset(keyInfoCtx->encCtx);
       
   371     }
       
   372     keyInfoCtx->curEncryptedKeyLevel = 0;
       
   373 #endif /* XMLSEC_NO_XMLENC */
       
   374     
       
   375     xmlSecKeyReqReset(&(keyInfoCtx->keyReq));
       
   376 }
       
   377 
       
   378 /** 
       
   379  * xmlSecKeyInfoCtxCreateEncCtx:
       
   380  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   381  * 
       
   382  * Creates encryption context form processing <enc:EncryptedKey/> child
       
   383  * of <dsig:KeyInfo/> element.
       
   384  * 
       
   385  * Returns 0 on success and a negative value if an error occurs.
       
   386  */
       
   387 EXPORT_C
       
   388 int 
       
   389 xmlSecKeyInfoCtxCreateEncCtx(xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   390 #ifndef XMLSEC_NO_XMLENC
       
   391     xmlSecEncCtxPtr tmp;
       
   392     int ret;
       
   393     
       
   394     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
   395     xmlSecAssert2(keyInfoCtx->encCtx == NULL, -1);
       
   396 
       
   397     /* we have to use tmp variable to avoid a recursive loop */ 
       
   398     tmp = xmlSecEncCtxCreate(keyInfoCtx->keysMngr);
       
   399     if(tmp == NULL) {
       
   400 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   401 		    NULL,
       
   402 		    "xmlSecEncCtxCreate",
       
   403 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   404 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   405 	return(-1);
       
   406     }
       
   407     tmp->mode = xmlEncCtxModeEncryptedKey;
       
   408         
       
   409     /* copy user preferences from our current ctx */
       
   410     switch(keyInfoCtx->mode) {
       
   411 	case xmlSecKeyInfoModeRead:
       
   412 	    ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoReadCtx), keyInfoCtx);
       
   413 	    if(ret < 0) {
       
   414 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   415 			    NULL,
       
   416 			    "xmlSecKeyInfoCtxCopyUserPref",
       
   417 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   418 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   419 		xmlSecEncCtxDestroy(tmp);
       
   420 		return(-1);
       
   421 	    }    
       
   422 	    break;
       
   423 	case xmlSecKeyInfoModeWrite:
       
   424 	    ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoWriteCtx), keyInfoCtx);
       
   425 	    if(ret < 0) {
       
   426 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   427 			    NULL,
       
   428 			    "xmlSecKeyInfoCtxCopyUserPref",
       
   429 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   430 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   431 		xmlSecEncCtxDestroy(tmp);
       
   432 		return(-1);
       
   433 	    }
       
   434 	    break;
       
   435     }    
       
   436     keyInfoCtx->encCtx = tmp;
       
   437         
       
   438     return(0);
       
   439 #else /* XMLSEC_NO_XMLENC */    
       
   440     xmlSecError(XMLSEC_ERRORS_HERE,
       
   441 		NULL,
       
   442 		"xml encryption",
       
   443 		XMLSEC_ERRORS_R_DISABLED,
       
   444 		XMLSEC_ERRORS_NO_MESSAGE);
       
   445     return(-1);
       
   446 #endif /* XMLSEC_NO_XMLENC */    
       
   447 }
       
   448 
       
   449 /** 
       
   450  * xmlSecKeyInfoCtxCopyUserPref:
       
   451  * @dst:		the pointer to destination context object.
       
   452  * @src:		the pointer to source context object.
       
   453  *
       
   454  * Copies user preferences from @src context to @dst context.
       
   455  *  
       
   456  * Returns 0 on success and a negative value if an error occurs.
       
   457  */
       
   458 EXPORT_C
       
   459 int 
       
   460 xmlSecKeyInfoCtxCopyUserPref(xmlSecKeyInfoCtxPtr dst, xmlSecKeyInfoCtxPtr src) {
       
   461     int ret;
       
   462     
       
   463     xmlSecAssert2(dst != NULL, -1);
       
   464     xmlSecAssert2(src != NULL, -1);
       
   465     
       
   466     dst->userData 	= src->userData;
       
   467     dst->flags		= src->flags;
       
   468     dst->flags2		= src->flags2;
       
   469     dst->keysMngr	= src->keysMngr;
       
   470     dst->mode		= src->mode;
       
   471     dst->base64LineSize	= src->base64LineSize;
       
   472 
       
   473     ret = xmlSecPtrListCopy(&(dst->enabledKeyData), &(src->enabledKeyData));
       
   474     if(ret < 0) {
       
   475 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   476 		    NULL,
       
   477 		    "xmlSecPtrListCopy",
       
   478 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   479 		    "enabledKeyData");    
       
   480 	return(-1);
       
   481     }
       
   482     
       
   483     /* <dsig:RetrievalMethod/> */
       
   484     dst->maxRetrievalMethodLevel= src->maxRetrievalMethodLevel;
       
   485     ret = xmlSecTransformCtxCopyUserPref(&(dst->retrievalMethodCtx), 
       
   486 					 &(src->retrievalMethodCtx));
       
   487     if(ret < 0) {
       
   488 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   489 		    NULL,
       
   490 		    "xmlSecTransformCtxCopyUserPref",
       
   491 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   492 		    "enabledKeyData");    
       
   493 	return(-1);
       
   494     }
       
   495 
       
   496     /* <enc:EncryptedContext /> */    
       
   497 #ifndef XMLSEC_NO_XMLENC
       
   498     xmlSecAssert2(dst->encCtx == NULL, -1);
       
   499     if(src->encCtx != NULL) { 	   	
       
   500 	dst->encCtx = xmlSecEncCtxCreate(dst->keysMngr);
       
   501 	if(dst->encCtx == NULL) {
       
   502 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   503 		        NULL,
       
   504 			"xmlSecEncCtxCreate",
       
   505 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   506 		        XMLSEC_ERRORS_NO_MESSAGE);
       
   507 	    return(-1);
       
   508 	}
       
   509 	
       
   510 	dst->encCtx->mode = xmlEncCtxModeEncryptedKey;
       
   511         ret = xmlSecEncCtxCopyUserPref(dst->encCtx, src->encCtx);
       
   512 	if(ret < 0) {
       
   513 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   514 		        NULL,
       
   515 			"xmlSecEncCtxCopyUserPref",
       
   516 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   517 		        XMLSEC_ERRORS_NO_MESSAGE);
       
   518 	    return(-1);
       
   519 	}
       
   520     }
       
   521     dst->maxEncryptedKeyLevel	= src->maxEncryptedKeyLevel;
       
   522 #endif /* XMLSEC_NO_XMLENC */
       
   523 
       
   524     /* <dsig:X509Data /> */    
       
   525 #ifndef XMLSEC_NO_X509
       
   526     dst->certsVerificationTime	= src->certsVerificationTime;
       
   527     dst->certsVerificationDepth	= src->certsVerificationDepth;
       
   528 #endif /* XMLSEC_NO_X509 */
       
   529     
       
   530     return(0);
       
   531 }
       
   532 
       
   533 /** 
       
   534  * xmlSecKeyInfoCtxDebugDump:
       
   535  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   536  * @output:		the output file pointer.
       
   537  *
       
   538  * Prints user settings and current context state to @output.
       
   539  */
       
   540 EXPORT_C
       
   541 void 
       
   542 xmlSecKeyInfoCtxDebugDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
       
   543     xmlSecAssert(keyInfoCtx != NULL);
       
   544     xmlSecAssert(output != NULL);
       
   545 
       
   546     switch(keyInfoCtx->mode) {
       
   547 	case xmlSecKeyInfoModeRead:
       
   548 	    fprintf(output, "= KEY INFO READ CONTEXT\n");
       
   549 	    break;
       
   550 	case xmlSecKeyInfoModeWrite:
       
   551 	    fprintf(output, "= KEY INFO WRITE CONTEXT\n");
       
   552 	    break;
       
   553     }
       
   554     
       
   555     fprintf(output, "== flags: 0x%08x\n", keyInfoCtx->flags);
       
   556     fprintf(output, "== flags2: 0x%08x\n", keyInfoCtx->flags2);
       
   557     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
       
   558 	fprintf(output, "== enabled key data: ");
       
   559 	xmlSecKeyDataIdListDebugDump(&(keyInfoCtx->enabledKeyData), output);
       
   560     } else {
       
   561 	fprintf(output, "== enabled key data: all\n");
       
   562     }
       
   563     fprintf(output, "== RetrievalMethod level (cur/max): %d/%d\n",
       
   564 	    keyInfoCtx->curRetrievalMethodLevel, 
       
   565 	    keyInfoCtx->maxRetrievalMethodLevel);
       
   566     xmlSecTransformCtxDebugDump(&(keyInfoCtx->retrievalMethodCtx), output);
       
   567     
       
   568 #ifndef XMLSEC_NO_XMLENC
       
   569     fprintf(output, "== EncryptedKey level (cur/max): %d/%d\n",
       
   570 	    keyInfoCtx->curEncryptedKeyLevel, 
       
   571 	    keyInfoCtx->maxEncryptedKeyLevel);
       
   572     if(keyInfoCtx->encCtx != NULL) {
       
   573 	xmlSecEncCtxDebugDump(keyInfoCtx->encCtx, output);
       
   574     }
       
   575 #endif /* XMLSEC_NO_XMLENC */
       
   576 
       
   577     xmlSecKeyReqDebugDump(&(keyInfoCtx->keyReq), output);
       
   578 }
       
   579 
       
   580 /** 
       
   581  * xmlSecKeyInfoCtxDebugXmlDump:
       
   582  * @keyInfoCtx:		the pointer to <dsig:KeyInfo/> element processing context.
       
   583  * @output:		the output file pointer.
       
   584  *
       
   585  * Prints user settings and current context state in XML format to @output. 
       
   586  */
       
   587 EXPORT_C
       
   588 void 
       
   589 xmlSecKeyInfoCtxDebugXmlDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
       
   590     xmlSecAssert(keyInfoCtx != NULL);
       
   591     xmlSecAssert(output != NULL);
       
   592 
       
   593     switch(keyInfoCtx->mode) {
       
   594 	case xmlSecKeyInfoModeRead:
       
   595 	    fprintf(output, "<KeyInfoReadContext>\n");
       
   596 	    break;
       
   597 	case xmlSecKeyInfoModeWrite:
       
   598 	    fprintf(output, "<KeyInfoWriteContext>\n");
       
   599 	    break;
       
   600     }
       
   601     	    
       
   602     fprintf(output, "<Flags>%08x</Flags>\n", keyInfoCtx->flags);
       
   603     fprintf(output, "<Flags2>%08x</Flags2>\n", keyInfoCtx->flags2);
       
   604     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
       
   605 	fprintf(output, "<EnabledKeyData>\n");
       
   606 	xmlSecKeyDataIdListDebugXmlDump(&(keyInfoCtx->enabledKeyData), output);
       
   607 	fprintf(output, "</EnabledKeyData>\n");
       
   608     } else {
       
   609 	fprintf(output, "<EnabledKeyData>all</EnabledKeyData>\n");
       
   610     }
       
   611 
       
   612     fprintf(output, "<RetrievalMethodLevel cur=\"%d\" max=\"%d\" />\n",
       
   613 	    keyInfoCtx->curRetrievalMethodLevel, 
       
   614 	    keyInfoCtx->maxRetrievalMethodLevel);
       
   615     xmlSecTransformCtxDebugXmlDump(&(keyInfoCtx->retrievalMethodCtx), output);
       
   616 
       
   617 #ifndef XMLSEC_NO_XMLENC
       
   618     fprintf(output, "<EncryptedKeyLevel cur=\"%d\" max=\"%d\" />\n",
       
   619 	    keyInfoCtx->curEncryptedKeyLevel, 
       
   620 	    keyInfoCtx->maxEncryptedKeyLevel);
       
   621     if(keyInfoCtx->encCtx != NULL) {
       
   622 	xmlSecEncCtxDebugXmlDump(keyInfoCtx->encCtx, output);
       
   623     }
       
   624 #endif /* XMLSEC_NO_XMLENC */
       
   625     
       
   626     xmlSecKeyReqDebugXmlDump(&(keyInfoCtx->keyReq), output);
       
   627     switch(keyInfoCtx->mode) {
       
   628 	case xmlSecKeyInfoModeRead:
       
   629 	    fprintf(output, "</KeyInfoReadContext>\n");
       
   630 	    break;
       
   631 	case xmlSecKeyInfoModeWrite:
       
   632 	    fprintf(output, "</KeyInfoWriteContext>\n");
       
   633 	    break;
       
   634     }
       
   635 }
       
   636 
       
   637 /**************************************************************************
       
   638  *
       
   639  * <dsig:KeyName/> processing
       
   640  *
       
   641  *************************************************************************/
       
   642 static int			xmlSecKeyDataNameXmlRead	(xmlSecKeyDataId id,
       
   643 								 xmlSecKeyPtr key,
       
   644 								 xmlNodePtr node,
       
   645 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
   646 static int			xmlSecKeyDataNameXmlWrite	(xmlSecKeyDataId id,
       
   647 								 xmlSecKeyPtr key,
       
   648 								 xmlNodePtr node,
       
   649 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
   650 
       
   651 static xmlSecKeyDataKlass xmlSecKeyDataNameKlass = {
       
   652     sizeof(xmlSecKeyDataKlass),
       
   653     sizeof(xmlSecKeyData),
       
   654 
       
   655     /* data */
       
   656     xmlSecNameKeyName,
       
   657     xmlSecKeyDataUsageKeyInfoNode, 		/* xmlSecKeyDataUsage usage; */
       
   658     NULL,					/* const xmlChar* href; */
       
   659     xmlSecNodeKeyName,				/* const xmlChar* dataNodeName; */
       
   660     xmlSecDSigNs,				/* const xmlChar* dataNodeNs; */
       
   661     
       
   662     /* constructors/destructor */
       
   663     NULL,					/* xmlSecKeyDataInitializeMethod initialize; */
       
   664     NULL,					/* xmlSecKeyDataDuplicateMethod duplicate; */
       
   665     NULL,					/* xmlSecKeyDataFinalizeMethod finalize; */
       
   666     NULL,					/* xmlSecKeyDataGenerateMethod generate; */
       
   667     
       
   668     /* get info */
       
   669     NULL,					/* xmlSecKeyDataGetTypeMethod getType; */
       
   670     NULL,					/* xmlSecKeyDataGetSizeMethod getSize; */
       
   671     NULL,					/* xmlSecKeyDataGetIdentifier getIdentifier; */    
       
   672 
       
   673     /* read/write */
       
   674     xmlSecKeyDataNameXmlRead,			/* xmlSecKeyDataXmlReadMethod xmlRead; */
       
   675     xmlSecKeyDataNameXmlWrite,   		/* xmlSecKeyDataXmlWriteMethod xmlWrite; */
       
   676     NULL,					/* xmlSecKeyDataBinReadMethod binRead; */
       
   677     NULL,					/* xmlSecKeyDataBinWriteMethod binWrite; */
       
   678 
       
   679     /* debug */
       
   680     NULL,					/* xmlSecKeyDataDebugDumpMethod debugDump; */
       
   681     NULL,					/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
       
   682 
       
   683     /* reserved for the future */
       
   684     NULL,					/* void* reserved0; */
       
   685     NULL,					/* void* reserved1; */
       
   686 };
       
   687 
       
   688 /** 
       
   689  * xmlSecKeyDataNameGetKlass:
       
   690  *
       
   691  * The <dsig:KeyName/> element key data klass 
       
   692  * (http://www.w3.org/TR/xmldsig-core/#sec-KeyName):
       
   693  *
       
   694  * The KeyName element contains a string value (in which white space is 
       
   695  * significant) which may be used by the signer to communicate a key 
       
   696  * identifier to the recipient. Typically, KeyName contains an identifier 
       
   697  * related to the key pair used to sign the message, but it may contain 
       
   698  * other protocol-related information that indirectly identifies a key pair. 
       
   699  * (Common uses of KeyName include simple string names for keys, a key index, 
       
   700  * a distinguished name (DN), an email address, etc.) 
       
   701  *
       
   702  * Returns the <dsig:KeyName/> element processing key data klass.
       
   703  */
       
   704 EXPORT_C
       
   705 xmlSecKeyDataId 
       
   706 xmlSecKeyDataNameGetKlass(void) {
       
   707     return(&xmlSecKeyDataNameKlass);
       
   708 }
       
   709 
       
   710 static int 
       
   711 xmlSecKeyDataNameXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   712     const xmlChar* oldName;
       
   713     xmlChar* newName;
       
   714     int ret;
       
   715 
       
   716     xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
       
   717     xmlSecAssert2(key != NULL, -1);
       
   718     xmlSecAssert2(node != NULL, -1);
       
   719     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
   720     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
       
   721 
       
   722     oldName = xmlSecKeyGetName(key);
       
   723     newName = xmlNodeGetContent(node);
       
   724     if(newName == NULL) {
       
   725 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   726 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   727 		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
       
   728 		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
       
   729 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   730 	return(-1);
       
   731     }
       
   732     
       
   733     /* compare name values */
       
   734     if((oldName != NULL) && !xmlStrEqual(oldName, newName)) {
       
   735 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   736 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   737 		    "key name is already specified",
       
   738 		    XMLSEC_ERRORS_R_INVALID_KEY_DATA,
       
   739 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   740 	xmlFree(newName);
       
   741 	return(-1);
       
   742     }
       
   743 
       
   744     /* try to find key in the manager */
       
   745     if((xmlSecKeyGetValue(key) == NULL) && (keyInfoCtx->keysMngr != NULL)) {
       
   746 	xmlSecKeyPtr tmpKey;
       
   747 
       
   748 	tmpKey = xmlSecKeysMngrFindKey(keyInfoCtx->keysMngr, newName, keyInfoCtx);
       
   749 	if(tmpKey != NULL) {
       
   750 	    /* erase any current information in the key */
       
   751 	    xmlSecKeyEmpty(key);
       
   752 
       
   753 	     
       
   754 	    /* and copy what we've found */
       
   755 	    ret = xmlSecKeyCopy(key, tmpKey);
       
   756 	    
       
   757 	    if(ret < 0) {
       
   758 		xmlSecError(XMLSEC_ERRORS_HERE,
       
   759 			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   760 			    "xmlSecKeyCopy",
       
   761 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   762 			    XMLSEC_ERRORS_NO_MESSAGE); 
       
   763 		xmlSecKeyDestroy(tmpKey);
       
   764 		xmlFree(newName);
       
   765 		return(-1);
       
   766 	    }
       
   767 	    tmpKey->value=NULL;
       
   768 	    xmlSecKeyDestroy(tmpKey);
       
   769 	}
       
   770     }		
       
   771     
       
   772     /* finally set key name if it is not there */
       
   773     if(xmlSecKeyGetName(key) == NULL) {
       
   774 	xmlSecKeySetName(key, newName);
       
   775     }
       
   776     xmlFree(newName);
       
   777     return(0);
       
   778 }
       
   779 
       
   780 static int 
       
   781 xmlSecKeyDataNameXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   782     const xmlChar* name;
       
   783 
       
   784     xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
       
   785     xmlSecAssert2(key != NULL, -1);
       
   786     xmlSecAssert2(node != NULL, -1);
       
   787     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
   788     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
       
   789 
       
   790     name = xmlSecKeyGetName(key);
       
   791     if(name != NULL) {
       
   792 	xmlNodeSetContent(node, name);
       
   793 	if (OOM_FLAG)
       
   794 	    {
       
   795 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   796 			NULL,
       
   797 			"xmlNodeSetContent",
       
   798 			XMLSEC_ERRORS_R_MALLOC_FAILED,
       
   799 			XMLSEC_ERRORS_NO_MESSAGE);
       
   800 	    return(-1);
       
   801 	    }
       
   802     }
       
   803     return(0);
       
   804 }
       
   805 
       
   806 /**************************************************************************
       
   807  *
       
   808  * <dsig:KeyValue/> processing
       
   809  *
       
   810  *************************************************************************/
       
   811 static int			xmlSecKeyDataValueXmlRead	(xmlSecKeyDataId id,
       
   812 								 xmlSecKeyPtr key,
       
   813 								 xmlNodePtr node,
       
   814 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
   815 static int			xmlSecKeyDataValueXmlWrite	(xmlSecKeyDataId id,
       
   816 								 xmlSecKeyPtr key,
       
   817 								 xmlNodePtr node,
       
   818 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
   819 
       
   820 static xmlSecKeyDataKlass xmlSecKeyDataValueKlass = {
       
   821     sizeof(xmlSecKeyDataKlass),
       
   822     sizeof(xmlSecKeyData),
       
   823 
       
   824     /* data */
       
   825     xmlSecNameKeyValue,
       
   826     xmlSecKeyDataUsageKeyInfoNode, 		/* xmlSecKeyDataUsage usage; */
       
   827     NULL,					/* const xmlChar* href; */
       
   828     xmlSecNodeKeyValue,				/* const xmlChar* dataNodeName; */
       
   829     xmlSecDSigNs,				/* const xmlChar* dataNodeNs; */
       
   830     
       
   831     /* constructors/destructor */
       
   832     NULL,					/* xmlSecKeyDataInitializeMethod initialize; */
       
   833     NULL,					/* xmlSecKeyDataDuplicateMethod duplicate; */
       
   834     NULL,					/* xmlSecKeyDataFinalizeMethod finalize; */
       
   835     NULL,					/* xmlSecKeyDataGenerateMethod generate; */
       
   836     
       
   837     /* get info */
       
   838     NULL,					/* xmlSecKeyDataGetTypeMethod getType; */
       
   839     NULL,					/* xmlSecKeyDataGetSizeMethod getSize; */
       
   840     NULL,					/* xmlSecKeyDataGetIdentifier getIdentifier; */    
       
   841 
       
   842     /* read/write */
       
   843     xmlSecKeyDataValueXmlRead,			/* xmlSecKeyDataXmlReadMethod xmlRead; */
       
   844     xmlSecKeyDataValueXmlWrite, 	  	/* xmlSecKeyDataXmlWriteMethod xmlWrite; */
       
   845     NULL,					/* xmlSecKeyDataBinReadMethod binRead; */
       
   846     NULL,					/* xmlSecKeyDataBinWriteMethod binWrite; */
       
   847 
       
   848     /* debug */
       
   849     NULL,					/* xmlSecKeyDataDebugDumpMethod debugDump; */
       
   850     NULL,					/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
       
   851 
       
   852     /* reserved for the future */
       
   853     NULL,					/* void* reserved0; */
       
   854     NULL,					/* void* reserved1; */
       
   855 };
       
   856 
       
   857 /** 
       
   858  * xmlSecKeyDataValueGetKlass:
       
   859  *
       
   860  * The <dsig:KeyValue/> element key data klass 
       
   861  * (http://www.w3.org/TR/xmldsig-core/#sec-KeyValue):
       
   862  *
       
   863  * The KeyValue element contains a single public key that may be useful in 
       
   864  * validating the signature. 
       
   865  * 
       
   866  * Returns the <dsig:KeyValue/> element processing key data klass.
       
   867  */
       
   868 EXPORT_C
       
   869 xmlSecKeyDataId 
       
   870 xmlSecKeyDataValueGetKlass(void) {
       
   871     return(&xmlSecKeyDataValueKlass);
       
   872 }
       
   873 
       
   874 static int 
       
   875 xmlSecKeyDataValueXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   876     const xmlChar* nodeName;
       
   877     const xmlChar* nodeNs;
       
   878     xmlSecKeyDataId dataId;
       
   879     xmlNodePtr cur;
       
   880     int ret;
       
   881 
       
   882     xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
       
   883     xmlSecAssert2(key != NULL, -1);
       
   884     xmlSecAssert2(node != NULL, -1);
       
   885     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
   886     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
       
   887 
       
   888     cur = xmlSecGetNextElementNode(node->children);
       
   889     if(cur == NULL) {
       
   890 	/* just an empty node */
       
   891 	return(0);
       
   892     }
       
   893 
       
   894     /* find data id */
       
   895     nodeName = cur->name;
       
   896     nodeNs = xmlSecGetNodeNsHref(cur);
       
   897 
       
   898     /* use global list only if we don't have a local one */
       
   899     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
       
   900 	dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
       
   901 			    nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
       
   902     } else {	
       
   903     	dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
       
   904 			    nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
       
   905     }
       
   906     if(dataId != xmlSecKeyDataIdUnknown) {
       
   907 	/* read data node */
       
   908 	ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
       
   909 	if(ret < 0) {
       
   910 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   911 			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   912 			"xmlSecKeyDataXmlRead",
       
   913 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   914 			"node=%s",
       
   915 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   916 	    return(-1);
       
   917 	}
       
   918     } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
       
   919 	/* laxi schema validation but application can disable it */
       
   920 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   921 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   922 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   923 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   924 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   925 	return(-1);	
       
   926     }
       
   927 
       
   928     /* <dsig:KeyValue/> might have only one node */
       
   929     cur = xmlSecGetNextElementNode(cur->next);  
       
   930     if(cur != NULL) {
       
   931 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   932 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   933 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   934 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
   935 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   936 	return(-1);
       
   937     }
       
   938     
       
   939     return(0);
       
   940 }
       
   941 
       
   942 static int 
       
   943 xmlSecKeyDataValueXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
   944     const xmlChar* nodeName;
       
   945     const xmlChar* nodeNs;  
       
   946     xmlNodePtr cur;
       
   947     int ret;
       
   948     
       
   949     xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
       
   950     xmlSecAssert2(key != NULL, -1);
       
   951     xmlSecAssert2(node != NULL, -1);
       
   952     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
   953     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
       
   954 
       
   955     if(!xmlSecKeyDataIsValid(key->value) || 
       
   956        !xmlSecKeyDataCheckUsage(key->value, xmlSecKeyDataUsageKeyValueNodeWrite)){
       
   957 	/* nothing to write */
       
   958 	return(0);
       
   959     }
       
   960     if((xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) && 
       
   961         (xmlSecKeyDataIdListFind(&(keyInfoCtx->enabledKeyData), id) != 1)) {
       
   962 
       
   963 	/* we are not enabled to write out key data with this id */
       
   964 	return(0);
       
   965     }
       
   966     if(xmlSecKeyReqMatchKey(&(keyInfoCtx->keyReq), key) != 1) {
       
   967 	/* we are not allowed to write out this key */
       
   968 	return(0);
       
   969     }
       
   970 
       
   971     nodeName = key->value->id->dataNodeName;
       
   972     nodeNs = key->value->id->dataNodeNs;
       
   973     xmlSecAssert2(nodeName != NULL, -1);
       
   974     
       
   975     /* remove all existing key value */
       
   976     xmlNodeSetContent(node, NULL);
       
   977     
       
   978     /* create key node */
       
   979     cur = xmlSecAddChild(node, nodeName, nodeNs);
       
   980     if(cur == NULL) {
       
   981 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   982 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   983 		    "xmlSecAddChild",
       
   984 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   985 		    "node=%s",
       
   986 		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
       
   987 	return(-1);	
       
   988     }
       
   989 
       
   990     ret = xmlSecKeyDataXmlWrite(key->value->id, key, cur, keyInfoCtx);
       
   991     if(ret < 0) {
       
   992 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   993 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
   994 		    "xmlSecKeyDataXmlWrite",
       
   995 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   996 		    "node=%s",
       
   997 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   998 	return(-1);	
       
   999     }
       
  1000 
       
  1001     return(0);
       
  1002 }
       
  1003 
       
  1004 /**************************************************************************
       
  1005  *
       
  1006  * <dsig:RetrievalMethod/> processing
       
  1007  *
       
  1008  *************************************************************************/
       
  1009 static int			xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id,
       
  1010 								 xmlSecKeyPtr key,
       
  1011 								 xmlNodePtr node,
       
  1012 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
  1013 static int			xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id,
       
  1014 								 xmlSecKeyPtr key,
       
  1015 								 xmlNodePtr node,
       
  1016 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
  1017 
       
  1018 
       
  1019 
       
  1020 static xmlSecKeyDataKlass xmlSecKeyDataRetrievalMethodKlass = {
       
  1021     sizeof(xmlSecKeyDataKlass),
       
  1022     sizeof(xmlSecKeyData),
       
  1023 
       
  1024     /* data */
       
  1025     xmlSecNameRetrievalMethod,
       
  1026     xmlSecKeyDataUsageKeyInfoNode, 		/* xmlSecKeyDataUsage usage; */
       
  1027     NULL,					/* const xmlChar* href; */
       
  1028     xmlSecNodeRetrievalMethod,			/* const xmlChar* dataNodeName; */
       
  1029     xmlSecDSigNs,				/* const xmlChar* dataNodeNs; */
       
  1030     
       
  1031     /* constructors/destructor */
       
  1032     NULL,					/* xmlSecKeyDataInitializeMethod initialize; */
       
  1033     NULL,					/* xmlSecKeyDataDuplicateMethod duplicate; */
       
  1034     NULL,					/* xmlSecKeyDataFinalizeMethod finalize; */
       
  1035     NULL,					/* xmlSecKeyDataGenerateMethod generate; */
       
  1036     
       
  1037     /* get info */
       
  1038     NULL,					/* xmlSecKeyDataGetTypeMethod getType; */
       
  1039     NULL,					/* xmlSecKeyDataGetSizeMethod getSize; */
       
  1040     NULL,					/* xmlSecKeyDataGetIdentifier getIdentifier; */    
       
  1041 
       
  1042     /* read/write */
       
  1043     xmlSecKeyDataRetrievalMethodXmlRead,	/* xmlSecKeyDataXmlReadMethod xmlRead; */
       
  1044     xmlSecKeyDataRetrievalMethodXmlWrite,   	/* xmlSecKeyDataXmlWriteMethod xmlWrite; */
       
  1045     NULL,					/* xmlSecKeyDataBinReadMethod binRead; */
       
  1046     NULL,					/* xmlSecKeyDataBinWriteMethod binWrite; */
       
  1047 
       
  1048     /* debug */
       
  1049     NULL,					/* xmlSecKeyDataDebugDumpMethod debugDump; */
       
  1050     NULL,					/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
       
  1051 
       
  1052     /* reserved for the future */
       
  1053     NULL,					/* void* reserved0; */
       
  1054     NULL,					/* void* reserved1; */
       
  1055 };
       
  1056 
       
  1057 static int			xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId,
       
  1058 								 xmlSecKeyPtr key,
       
  1059 								 const xmlChar* buffer,
       
  1060 								 xmlSecSize bufferSize,
       
  1061 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
  1062 
       
  1063 /** 
       
  1064  * xmlSecKeyDataRetrievalMethodGetKlass:
       
  1065  *
       
  1066  * The <dsig:RetrievalMethod/> element key data klass 
       
  1067  * (http://www.w3.org/TR/xmldsig-core/#sec-RetrievalMethod):
       
  1068  * A RetrievalMethod element within KeyInfo is used to convey a reference to 
       
  1069  * KeyInfo information that is stored at another location. For example, 
       
  1070  * several signatures in a document might use a key verified by an X.509v3 
       
  1071  * certificate chain appearing once in the document or remotely outside the 
       
  1072  * document; each signature's KeyInfo can reference this chain using a single 
       
  1073  * RetrievalMethod element instead of including the entire chain with a 
       
  1074  * sequence of X509Certificate elements.
       
  1075  *
       
  1076  * RetrievalMethod uses the same syntax and dereferencing behavior as 
       
  1077  * Reference's URI and The Reference Processing Model.
       
  1078  * 
       
  1079  * Returns the <dsig:RetrievalMethod/> element processing key data klass.
       
  1080  */
       
  1081 EXPORT_C
       
  1082 xmlSecKeyDataId 
       
  1083 xmlSecKeyDataRetrievalMethodGetKlass(void) {
       
  1084     return(&xmlSecKeyDataRetrievalMethodKlass);
       
  1085 }
       
  1086 
       
  1087 static int 
       
  1088 xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
  1089     xmlSecKeyDataId dataId = xmlSecKeyDataIdUnknown;
       
  1090     xmlChar *retrType = NULL;
       
  1091     xmlChar *uri = NULL;
       
  1092     xmlNodePtr cur;
       
  1093     int res = -1;
       
  1094     int ret;
       
  1095     
       
  1096     xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
       
  1097     xmlSecAssert2(key != NULL, -1);
       
  1098     xmlSecAssert2(node != NULL, -1);
       
  1099     xmlSecAssert2(node->doc != NULL, -1);
       
  1100     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
  1101     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
       
  1102 
       
  1103     /* check retrieval level */
       
  1104     if(keyInfoCtx->curRetrievalMethodLevel >= keyInfoCtx->maxRetrievalMethodLevel) {
       
  1105 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1106 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1107 		    NULL,
       
  1108 		    XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,
       
  1109 		    "cur=%d;max=%d", 
       
  1110 		    keyInfoCtx->curRetrievalMethodLevel,
       
  1111 		    keyInfoCtx->maxRetrievalMethodLevel);
       
  1112 	goto done;
       
  1113     }
       
  1114     ++keyInfoCtx->curRetrievalMethodLevel;
       
  1115 
       
  1116     retrType = xmlGetProp(node, xmlSecAttrType);
       
  1117     if(retrType != NULL) {
       
  1118 	/* use global list only if we don't have a local one */
       
  1119 	if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
       
  1120 	    dataId = xmlSecKeyDataIdListFindByHref(&(keyInfoCtx->enabledKeyData),
       
  1121 			    retrType, xmlSecKeyDataUsageRetrievalMethodNode);
       
  1122 	} else {	
       
  1123     	    dataId = xmlSecKeyDataIdListFindByHref(xmlSecKeyDataIdsGet(),
       
  1124 			    retrType, xmlSecKeyDataUsageRetrievalMethodNode);
       
  1125 	}
       
  1126     }
       
  1127 
       
  1128     /* laxi schema validation but aplication can disable it */
       
  1129     if(dataId == xmlSecKeyDataIdUnknown) {
       
  1130 	if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_UNKNOWN_HREF) != 0) {
       
  1131 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1132 		        xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1133 			xmlSecErrorsSafeString(xmlSecAttrType),
       
  1134 			XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
       
  1135 			"value=%s", xmlSecErrorsSafeString(retrType));
       
  1136 	} else {
       
  1137 	    res = 0;
       
  1138 	}
       
  1139 	goto done;
       
  1140     }
       
  1141 
       
  1142     /* destroy prev retrieval method context */
       
  1143     xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
       
  1144 
       
  1145     /* set start URI and check that it is enabled */
       
  1146     uri = xmlGetProp(node, xmlSecAttrURI);
       
  1147     ret = xmlSecTransformCtxSetUri(&(keyInfoCtx->retrievalMethodCtx), uri, node);
       
  1148     if(ret < 0) {
       
  1149 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1150 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1151 		    "xmlSecTransformCtxSetUri",
       
  1152 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1153 		    "uri=%s",
       
  1154 		    xmlSecErrorsSafeString(uri));
       
  1155 	goto done;
       
  1156     }
       
  1157 
       
  1158     /* the only one node is optional Transforms node */
       
  1159     cur = xmlSecGetNextElementNode(node->children);
       
  1160     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
       
  1161 	ret = xmlSecTransformCtxNodesListRead(&(keyInfoCtx->retrievalMethodCtx), 
       
  1162 					    cur, xmlSecTransformUsageDSigTransform);
       
  1163 	if(ret < 0) {
       
  1164 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1165 			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1166 			"xmlSecTransformCtxNodesListRead",
       
  1167 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1168 			"node=%s",
       
  1169 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
  1170 	    goto done;
       
  1171 	}	
       
  1172         cur = xmlSecGetNextElementNode(cur->next);
       
  1173     }
       
  1174 
       
  1175     if(cur != NULL) {
       
  1176 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1177 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1178 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
  1179 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
  1180 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1181 	goto done;
       
  1182     }
       
  1183 
       
  1184     /* finally get transforms results */
       
  1185     ret = xmlSecTransformCtxExecute(&(keyInfoCtx->retrievalMethodCtx), node->doc);
       
  1186     if((ret < 0) || 
       
  1187        (keyInfoCtx->retrievalMethodCtx.result == NULL) ||
       
  1188        (xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result) == NULL)) {
       
  1189 
       
  1190 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1191 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1192 		    "xmlSecTransformCtxExecute",
       
  1193 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1194 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1195 	goto done;
       
  1196     }
       
  1197 
       
  1198 
       
  1199     /* assume that the data is in XML if we could not find id */    
       
  1200     if((dataId == xmlSecKeyDataIdUnknown) || 
       
  1201        ((dataId->usage & xmlSecKeyDataUsageRetrievalMethodNodeXml) != 0)) {
       
  1202 
       
  1203 	ret = xmlSecKeyDataRetrievalMethodReadXmlResult(dataId, key,
       
  1204 		    xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
       
  1205                     xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
       
  1206 		    keyInfoCtx);
       
  1207 	if(ret < 0) {
       
  1208 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1209 			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1210 			"xmlSecKeyDataRetrievalMethodReadXmlResult",
       
  1211 	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1212 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1213 	    goto done;
       
  1214 	}    
       
  1215     } else {
       
  1216 	ret = xmlSecKeyDataBinRead(dataId, key, 
       
  1217 		    xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
       
  1218                     xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
       
  1219 		    keyInfoCtx);
       
  1220 	if(ret < 0) {
       
  1221 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1222 			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1223 			"xmlSecKeyDataBinRead",
       
  1224 	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1225 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1226 	    goto done;
       
  1227 	}    
       
  1228     }
       
  1229     --keyInfoCtx->curRetrievalMethodLevel;
       
  1230     
       
  1231     res = 0;    
       
  1232 done:
       
  1233     if(uri != NULL) {
       
  1234 	xmlFree(uri);
       
  1235     }
       
  1236     if(retrType != NULL) {
       
  1237 	xmlFree(retrType);
       
  1238     }
       
  1239     return(res);
       
  1240 }
       
  1241 
       
  1242 static int 
       
  1243 xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
  1244     xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
       
  1245     xmlSecAssert2(key != NULL, -1);
       
  1246     xmlSecAssert2(node != NULL, -1);
       
  1247     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
  1248     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
       
  1249 
       
  1250     /* just do nothing */
       
  1251     return(0);
       
  1252 }
       
  1253 
       
  1254 static int
       
  1255 xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId, xmlSecKeyPtr key,
       
  1256 					  const xmlChar* buffer, xmlSecSize bufferSize,
       
  1257 					  xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
  1258     xmlDocPtr doc;
       
  1259     xmlNodePtr cur;
       
  1260     const xmlChar* nodeName;
       
  1261     const xmlChar* nodeNs;
       
  1262     xmlSecKeyDataId dataId;
       
  1263     int ret;
       
  1264     
       
  1265     xmlSecAssert2(key != NULL, -1);
       
  1266     xmlSecAssert2(buffer != NULL, -1);
       
  1267     xmlSecAssert2(bufferSize > 0, -1); 
       
  1268     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
  1269     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
       
  1270 
       
  1271     doc = xmlRecoverMemory((const char*)buffer, bufferSize);
       
  1272     if(doc == NULL) {
       
  1273 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1274 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
       
  1275 		    "xmlRecoverMemory",
       
  1276 		    XMLSEC_ERRORS_R_XML_FAILED,
       
  1277 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1278 	return(-1);
       
  1279     }
       
  1280 	
       
  1281     cur = xmlDocGetRootElement(doc);
       
  1282     if(cur == NULL) {
       
  1283 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1284 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
       
  1285 		    "xmlDocGetRootElement",
       
  1286 		    XMLSEC_ERRORS_R_XML_FAILED,
       
  1287 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1288 	xmlFreeDoc(doc);
       
  1289 	return(-1);	
       
  1290     }
       
  1291 
       
  1292     nodeName = cur->name;
       
  1293     nodeNs = xmlSecGetNodeNsHref(cur);
       
  1294 
       
  1295     /* use global list only if we don't have a local one */
       
  1296     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
       
  1297 	dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
       
  1298 			    nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
       
  1299     } else {	
       
  1300     	dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
       
  1301 			    nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
       
  1302     }
       
  1303     if(dataId == xmlSecKeyDataIdUnknown) {
       
  1304 	xmlFreeDoc(doc);
       
  1305 
       
  1306 	/* laxi schema validation but application can disable it */
       
  1307 	if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
       
  1308 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1309 			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
       
  1310 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
  1311 			XMLSEC_ERRORS_R_INVALID_NODE,
       
  1312 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1313 	    return(-1);
       
  1314 	}
       
  1315 	return(0);
       
  1316     } else if((typeId != xmlSecKeyDataIdUnknown) && (typeId != dataId) &&
       
  1317 	      ((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_MISMATCH_HREF) != 0)) {
       
  1318 	
       
  1319 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1320 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
       
  1321 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),		    
       
  1322 		    XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,
       
  1323 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1324 	xmlFreeDoc(doc);
       
  1325 	return(-1);
       
  1326     }
       
  1327 
       
  1328     /* read data node */
       
  1329     ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
       
  1330     if(ret < 0) {
       
  1331 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1332 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
       
  1333 		    "xmlSecKeyDataXmlRead",
       
  1334 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1335 		    "node=%s",
       
  1336 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
  1337 	xmlFreeDoc(doc);
       
  1338 	return(-1);
       
  1339     }
       
  1340     
       
  1341     xmlFreeDoc(doc);
       
  1342     return(0);
       
  1343 }
       
  1344 
       
  1345 
       
  1346 #ifndef XMLSEC_NO_XMLENC
       
  1347 /**************************************************************************
       
  1348  *
       
  1349  * <enc:EncryptedKey/> processing
       
  1350  *
       
  1351  *************************************************************************/
       
  1352 static int	xmlSecKeyDataEncryptedKeyXmlRead	(xmlSecKeyDataId id,
       
  1353 							 xmlSecKeyPtr key,
       
  1354 							 xmlNodePtr node,
       
  1355 							 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
  1356 static int	xmlSecKeyDataEncryptedKeyXmlWrite	(xmlSecKeyDataId id,
       
  1357 							 xmlSecKeyPtr key,
       
  1358 							 xmlNodePtr node,
       
  1359 							 xmlSecKeyInfoCtxPtr keyInfoCtx);
       
  1360 
       
  1361 
       
  1362 
       
  1363 static xmlSecKeyDataKlass xmlSecKeyDataEncryptedKeyKlass = {
       
  1364     sizeof(xmlSecKeyDataKlass),
       
  1365     sizeof(xmlSecKeyData),
       
  1366 
       
  1367     /* data */
       
  1368     xmlSecNameEncryptedKey,
       
  1369     xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, 		
       
  1370 						/* xmlSecKeyDataUsage usage; */
       
  1371     xmlSecHrefEncryptedKey,			/* const xmlChar* href; */
       
  1372     xmlSecNodeEncryptedKey,			/* const xmlChar* dataNodeName; */
       
  1373     xmlSecEncNs,				/* const xmlChar* dataNodeNs; */
       
  1374     
       
  1375     /* constructors/destructor */
       
  1376     NULL,					/* xmlSecKeyDataInitializeMethod initialize; */
       
  1377     NULL,					/* xmlSecKeyDataDuplicateMethod duplicate; */
       
  1378     NULL,					/* xmlSecKeyDataFinalizeMethod finalize; */
       
  1379     NULL,					/* xmlSecKeyDataGenerateMethod generate; */
       
  1380     
       
  1381     /* get info */
       
  1382     NULL,					/* xmlSecKeyDataGetTypeMethod getType; */
       
  1383     NULL,					/* xmlSecKeyDataGetSizeMethod getSize; */
       
  1384     NULL,					/* xmlSecKeyDataGetIdentifier getIdentifier; */    
       
  1385 
       
  1386     /* read/write */
       
  1387     xmlSecKeyDataEncryptedKeyXmlRead,		/* xmlSecKeyDataXmlReadMethod xmlRead; */
       
  1388     xmlSecKeyDataEncryptedKeyXmlWrite,   	/* xmlSecKeyDataXmlWriteMethod xmlWrite; */
       
  1389     NULL,					/* xmlSecKeyDataBinReadMethod binRead; */
       
  1390     NULL,					/* xmlSecKeyDataBinWriteMethod binWrite; */
       
  1391 
       
  1392     /* debug */
       
  1393     NULL,					/* xmlSecKeyDataDebugDumpMethod debugDump; */
       
  1394     NULL,					/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
       
  1395 
       
  1396     /* reserved for the future */
       
  1397     NULL,					/* void* reserved0; */
       
  1398     NULL,					/* void* reserved1; */
       
  1399 };
       
  1400 
       
  1401 /** 
       
  1402  * xmlSecKeyDataEncryptedKeyGetKlass:
       
  1403  *
       
  1404  * The <enc:EncryptedKey/> element key data klass 
       
  1405  * (http://www.w3.org/TR/xmlenc-core/#sec-EncryptedKey):
       
  1406  *
       
  1407  * The EncryptedKey element is used to transport encryption keys from 
       
  1408  * the originator to a known recipient(s). It may be used as a stand-alone 
       
  1409  * XML document, be placed within an application document, or appear inside 
       
  1410  * an EncryptedData element as a child of a ds:KeyInfo element. The key value 
       
  1411  * is always encrypted to the recipient(s). When EncryptedKey is decrypted the 
       
  1412  * resulting octets are made available to the EncryptionMethod algorithm 
       
  1413  * without any additional processing.
       
  1414  * 
       
  1415  * Returns the <enc:EncryptedKey/> element processing key data klass.
       
  1416  */
       
  1417 EXPORT_C
       
  1418 xmlSecKeyDataId 
       
  1419 xmlSecKeyDataEncryptedKeyGetKlass(void) {
       
  1420     return(&xmlSecKeyDataEncryptedKeyKlass);
       
  1421 }
       
  1422 
       
  1423 static int 
       
  1424 xmlSecKeyDataEncryptedKeyXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
  1425     xmlSecBufferPtr result;
       
  1426     int ret;
       
  1427 
       
  1428     xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
       
  1429     xmlSecAssert2(key != NULL, -1);
       
  1430     xmlSecAssert2(node != NULL, -1);
       
  1431     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
  1432     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
       
  1433 
       
  1434     /* check the enc level */    
       
  1435     if(keyInfoCtx->curEncryptedKeyLevel >= keyInfoCtx->maxEncryptedKeyLevel) {
       
  1436         xmlSecError(XMLSEC_ERRORS_HERE,
       
  1437 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1438 		    NULL,
       
  1439 		    XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL,
       
  1440 		    "cur=%d;max=%d", 
       
  1441 		    keyInfoCtx->curEncryptedKeyLevel,
       
  1442 		    keyInfoCtx->maxEncryptedKeyLevel);
       
  1443 	return(-1);
       
  1444     }
       
  1445     ++keyInfoCtx->curEncryptedKeyLevel;
       
  1446 
       
  1447     /* init Enc context */    
       
  1448     if(keyInfoCtx->encCtx != NULL) {
       
  1449 	xmlSecEncCtxReset(keyInfoCtx->encCtx);
       
  1450     } else {
       
  1451 	ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
       
  1452 	if(ret < 0) {
       
  1453 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1454 			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1455 		        "xmlSecKeyInfoCtxCreateEncCtx",
       
  1456 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1457 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1458 	    return(-1);		
       
  1459         }
       
  1460     }
       
  1461     xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
       
  1462     
       
  1463     result = xmlSecEncCtxDecryptToBuffer(keyInfoCtx->encCtx, node);
       
  1464     if((result == NULL) || (xmlSecBufferGetData(result) == NULL)) {
       
  1465 	/* We might have multiple EncryptedKey elements, encrypted 
       
  1466 	 * for different receipints but application can enforce
       
  1467 	 * correct enc key.
       
  1468 	 */
       
  1469         if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_ENCKEY_DONT_STOP_ON_FAILED_DECRYPTION) != 0) {
       
  1470 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1471 			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1472 			"xmlSecEncCtxDecryptToBuffer",
       
  1473 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1474 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1475 	    return(-1);
       
  1476 	}
       
  1477 	return(0);
       
  1478     }
       
  1479 	 
       
  1480     ret = xmlSecKeyDataBinRead(keyInfoCtx->keyReq.keyId, key,
       
  1481 			   xmlSecBufferGetData(result),
       
  1482 			   xmlSecBufferGetSize(result),
       
  1483 			   keyInfoCtx);
       
  1484     if(ret < 0) {
       
  1485 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1486 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1487 		    "xmlSecKeyDataBinRead",
       
  1488 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1489 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1490 	return(-1);
       
  1491     }			   
       
  1492     --keyInfoCtx->curEncryptedKeyLevel;
       
  1493 
       
  1494     return(0);
       
  1495 }
       
  1496 
       
  1497 static int 
       
  1498 xmlSecKeyDataEncryptedKeyXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
       
  1499     xmlSecKeyInfoCtx keyInfoCtx2;
       
  1500     xmlSecByte *keyBuf = NULL;
       
  1501     xmlSecSize keySize = 0;
       
  1502     int res = -1;
       
  1503     int ret;
       
  1504 
       
  1505     xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
       
  1506     xmlSecAssert2(key != NULL, -1);
       
  1507     xmlSecAssert2(xmlSecKeyIsValid(key), -1);
       
  1508     xmlSecAssert2(node != NULL, -1);
       
  1509     xmlSecAssert2(keyInfoCtx != NULL, -1);
       
  1510     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
       
  1511     
       
  1512     /* dump key to a binary buffer */
       
  1513     ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx2, NULL);
       
  1514     if(ret < 0) {
       
  1515 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1516 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1517 		    "xmlSecKeyInfoCtxInitialize",
       
  1518 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1519 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1520 	goto done;
       
  1521     }
       
  1522     
       
  1523     ret = xmlSecKeyInfoCtxCopyUserPref(&keyInfoCtx2, keyInfoCtx);
       
  1524     if(ret < 0) {
       
  1525 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1526 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1527 		    "xmlSecKeyInfoCtxCopyUserPref",
       
  1528 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1529 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1530 	xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
       
  1531 	goto done;
       
  1532     }
       
  1533 
       
  1534     keyInfoCtx2.keyReq.keyType = xmlSecKeyDataTypeAny;
       
  1535     ret = xmlSecKeyDataBinWrite(key->value->id, key, &keyBuf, &keySize, &keyInfoCtx2);
       
  1536     if(ret < 0) {
       
  1537 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1538 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1539 		    "xmlSecKeyDataBinWrite",
       
  1540 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1541 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1542 	xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
       
  1543 	goto done;
       
  1544     }
       
  1545     xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
       
  1546     
       
  1547     /* init Enc context */    
       
  1548     if(keyInfoCtx->encCtx != NULL) {
       
  1549 	xmlSecEncCtxReset(keyInfoCtx->encCtx);
       
  1550     } else {
       
  1551 	ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
       
  1552 	if(ret < 0) {
       
  1553 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1554 		        xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1555 			"xmlSecKeyInfoCtxCreateEncCtx",
       
  1556 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1557 		        XMLSEC_ERRORS_NO_MESSAGE);
       
  1558     	    goto done;	
       
  1559 	}
       
  1560     }
       
  1561     xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
       
  1562 
       
  1563     ret = xmlSecEncCtxBinaryEncrypt(keyInfoCtx->encCtx, node, keyBuf, keySize);
       
  1564     if(ret < 0) {
       
  1565 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1566 		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
       
  1567 		    "xmlSecEncCtxBinaryEncrypt",
       
  1568 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1569 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1570 	goto done;	
       
  1571     }
       
  1572     
       
  1573     res = 0;
       
  1574 done:
       
  1575     if(keyBuf != NULL) {
       
  1576 	memset(keyBuf, 0, keySize);
       
  1577 	xmlFree(keyBuf); keyBuf = NULL;
       
  1578     }
       
  1579     return(res);
       
  1580 }
       
  1581 
       
  1582 #endif /* XMLSEC_NO_XMLENC */
       
  1583