2 * XML Security Library (http://www.aleksey.com/xmlsec).
4 * <dsig:KeyInfo/> element processing
5 * (http://www.w3.org/TR/xmlSec-core/#sec-KeyInfo:
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.
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 -->
29 * <attribute name="Id" type="ID" use="optional"/>
34 * <!ELEMENT KeyInfo (#PCDATA|KeyName|KeyValue|RetrievalMethod|
35 * X509Data|PGPData|SPKIData|MgmtData %KeyInfo.ANY;)* >
36 * <!ATTLIST KeyInfo Id ID #IMPLIED >
39 * This is free software; see Copyright file in the source
40 * distribution for preciese wording.
42 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
49 #include <libxml/tree.h>
51 #include <xmlsec/xmlsec.h>
52 #include <xmlsec/xmltree.h>
53 #include <xmlsec/base64.h>
54 #include <xmlsec/keys.h>
55 #include <xmlsec/keysmngr.h>
56 #include <xmlsec/transforms.h>
57 #include <xmlsec/xmlenc.h>
58 #include <xmlsec/keyinfo.h>
59 #include <xmlsec/errors.h>
62 /**************************************************************************
66 *************************************************************************/
68 * xmlSecKeyInfoNodeRead:
69 * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
70 * @key: the pointer to result key object.
71 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
73 * Parses the <dsig:KeyInfo/> element @keyInfoNode, extracts the key data
74 * and stores into @key.
76 * Returns: 0 on success or -1 if an error occurs.
79 xmlSecKeyInfoNodeRead(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
80 const xmlChar* nodeName;
81 const xmlChar* nodeNs;
82 xmlSecKeyDataId dataId;
86 xmlSecAssert2(keyInfoNode != NULL, -1);
87 xmlSecAssert2(key != NULL, -1);
88 xmlSecAssert2(keyInfoCtx != NULL, -1);
89 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
91 for(cur = xmlSecGetNextElementNode(keyInfoNode->children);
93 (((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND) != 0) ||
94 (xmlSecKeyIsValid(key) == 0) ||
95 (xmlSecKeyMatch(key, NULL, &(keyInfoCtx->keyReq)) == 0));
96 cur = xmlSecGetNextElementNode(cur->next)) {
100 nodeNs = xmlSecGetNodeNsHref(cur);
102 /* use global list only if we don't have a local one */
103 if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
104 dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
105 nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
107 dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
108 nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
110 if(dataId != xmlSecKeyDataIdUnknown) {
112 ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
114 xmlSecError(XMLSEC_ERRORS_HERE,
115 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
116 "xmlSecKeyDataXmlRead",
117 XMLSEC_ERRORS_R_XMLSEC_FAILED,
119 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
122 } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
123 /* there is a laxi schema validation but application may
124 * desire to disable unknown nodes*/
125 xmlSecError(XMLSEC_ERRORS_HERE,
127 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
128 XMLSEC_ERRORS_R_INVALID_NODE,
129 XMLSEC_ERRORS_NO_MESSAGE);
138 * xmlSecKeyInfoNodeWrite:
139 * @keyInfoNode: the pointer to <dsig:KeyInfo/> node.
140 * @key: the pointer to key object.
141 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
143 * Writes the @key into the <dsig:KeyInfo/> element template @keyInfoNode.
145 * Returns: 0 on success or -1 if an error occurs.
148 xmlSecKeyInfoNodeWrite(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
149 const xmlChar* nodeName;
150 const xmlChar* nodeNs;
151 xmlSecKeyDataId dataId;
155 xmlSecAssert2(keyInfoNode != NULL, -1);
156 xmlSecAssert2(key != NULL, -1);
157 xmlSecAssert2(keyInfoCtx != NULL, -1);
158 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
160 for(cur = xmlSecGetNextElementNode(keyInfoNode->children);
162 cur = xmlSecGetNextElementNode(cur->next)) {
165 nodeName = cur->name;
166 nodeNs = xmlSecGetNodeNsHref(cur);
168 /* use global list only if we don't have a local one */
169 if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
170 dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
172 xmlSecKeyDataUsageKeyInfoNodeWrite);
174 dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
176 xmlSecKeyDataUsageKeyInfoNodeWrite);
178 if(dataId != xmlSecKeyDataIdUnknown) {
179 ret = xmlSecKeyDataXmlWrite(dataId, key, cur, keyInfoCtx);
181 xmlSecError(XMLSEC_ERRORS_HERE,
182 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
183 "xmlSecKeyDataXmlWrite",
184 XMLSEC_ERRORS_R_XMLSEC_FAILED,
186 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
189 } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
190 /* laxi schema validation but application can disable it*/
191 xmlSecError(XMLSEC_ERRORS_HERE,
193 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
194 XMLSEC_ERRORS_R_INVALID_NODE,
195 XMLSEC_ERRORS_NO_MESSAGE);
203 /**************************************************************************
207 *************************************************************************/
209 * xmlSecKeyInfoCtxCreate:
210 * @keysMngr: the pointer to keys manager (may be NULL).
212 * Allocates and initializes <dsig:KeyInfo/> element processing context.
213 * Caller is responsible for freeing it by calling #xmlSecKeyInfoCtxDestroy
216 * Returns: pointer to newly allocated object or NULL if an error occurs.
219 xmlSecKeyInfoCtxCreate(xmlSecKeysMngrPtr keysMngr) {
220 xmlSecKeyInfoCtxPtr keyInfoCtx;
223 /* Allocate a new xmlSecKeyInfoCtx and fill the fields. */
224 keyInfoCtx = (xmlSecKeyInfoCtxPtr)xmlMalloc(sizeof(xmlSecKeyInfoCtx));
225 if(keyInfoCtx == NULL) {
226 xmlSecError(XMLSEC_ERRORS_HERE,
229 XMLSEC_ERRORS_R_MALLOC_FAILED,
230 "size=%d", sizeof(xmlSecKeyInfoCtx));
234 ret = xmlSecKeyInfoCtxInitialize(keyInfoCtx, keysMngr);
236 xmlSecError(XMLSEC_ERRORS_HERE,
238 "xmlSecKeyInfoCtxInitialize",
239 XMLSEC_ERRORS_R_XMLSEC_FAILED,
240 XMLSEC_ERRORS_NO_MESSAGE);
241 xmlSecKeyInfoCtxDestroy(keyInfoCtx);
249 * xmlSecKeyInfoCtxDestroy:
250 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
252 * Destroys @keyInfoCtx object created with #xmlSecKeyInfoCtxCreate function.
255 xmlSecKeyInfoCtxDestroy(xmlSecKeyInfoCtxPtr keyInfoCtx) {
256 xmlSecAssert(keyInfoCtx != NULL);
258 xmlSecKeyInfoCtxFinalize(keyInfoCtx);
263 * xmlSecKeyInfoCtxInitialize:
264 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
265 * @keysMngr: the pointer to keys manager (may be NULL).
267 * Initializes <dsig:KeyInfo/> element processing context. Caller is
268 * responsible for cleaning it up by #xmlSecKeyInfoCtxFinalize function.
270 * Returns: 0 on success and a negative value if an error occurs.
273 xmlSecKeyInfoCtxInitialize(xmlSecKeyInfoCtxPtr keyInfoCtx, xmlSecKeysMngrPtr keysMngr) {
276 xmlSecAssert2(keyInfoCtx != NULL, -1);
278 memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
279 keyInfoCtx->keysMngr = keysMngr;
280 keyInfoCtx->base64LineSize = xmlSecBase64GetDefaultLineSize();
281 ret = xmlSecPtrListInitialize(&(keyInfoCtx->enabledKeyData), xmlSecKeyDataIdListId);
283 xmlSecError(XMLSEC_ERRORS_HERE,
285 "xmlSecPtrListInitialize",
286 XMLSEC_ERRORS_R_XMLSEC_FAILED,
287 XMLSEC_ERRORS_NO_MESSAGE);
291 keyInfoCtx->maxRetrievalMethodLevel = 1;
292 ret = xmlSecTransformCtxInitialize(&(keyInfoCtx->retrievalMethodCtx));
294 xmlSecError(XMLSEC_ERRORS_HERE,
296 "xmlSecTransformCtxInitialize",
297 XMLSEC_ERRORS_R_XMLSEC_FAILED,
298 XMLSEC_ERRORS_NO_MESSAGE);
302 #ifndef XMLSEC_NO_XMLENC
303 keyInfoCtx->maxEncryptedKeyLevel = 1;
304 #endif /* XMLSEC_NO_XMLENC */
306 #ifndef XMLSEC_NO_X509
307 keyInfoCtx->certsVerificationDepth= 9;
308 #endif /* XMLSEC_NO_X509 */
310 ret = xmlSecKeyReqInitialize(&(keyInfoCtx->keyReq));
312 xmlSecError(XMLSEC_ERRORS_HERE,
314 "xmlSecKeyReqInitialize",
315 XMLSEC_ERRORS_R_XMLSEC_FAILED,
316 XMLSEC_ERRORS_NO_MESSAGE);
324 * xmlSecKeyInfoCtxFinalize:
325 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
327 * Cleans up the @keyInfoCtx initialized with #xmlSecKeyInfoCtxInitialize
331 xmlSecKeyInfoCtxFinalize(xmlSecKeyInfoCtxPtr keyInfoCtx) {
332 xmlSecAssert(keyInfoCtx != NULL);
334 xmlSecPtrListFinalize(&(keyInfoCtx->enabledKeyData));
335 xmlSecTransformCtxFinalize(&(keyInfoCtx->retrievalMethodCtx));
336 xmlSecKeyReqFinalize(&(keyInfoCtx->keyReq));
338 #ifndef XMLSEC_NO_XMLENC
339 if(keyInfoCtx->encCtx != NULL) {
340 xmlSecEncCtxDestroy(keyInfoCtx->encCtx);
342 #endif /* XMLSEC_NO_XMLENC */
344 memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
348 * xmlSecKeyInfoCtxReset:
349 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
351 * Resets the @keyInfoCtx state. User settings are not changed.
354 xmlSecKeyInfoCtxReset(xmlSecKeyInfoCtxPtr keyInfoCtx) {
355 xmlSecAssert(keyInfoCtx != NULL);
357 xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
358 keyInfoCtx->curRetrievalMethodLevel = 0;
360 #ifndef XMLSEC_NO_XMLENC
361 if(keyInfoCtx->encCtx != NULL) {
362 xmlSecEncCtxReset(keyInfoCtx->encCtx);
364 keyInfoCtx->curEncryptedKeyLevel = 0;
365 #endif /* XMLSEC_NO_XMLENC */
367 xmlSecKeyReqReset(&(keyInfoCtx->keyReq));
371 * xmlSecKeyInfoCtxCreateEncCtx:
372 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
374 * Creates encryption context form processing <enc:EncryptedKey/> child
375 * of <dsig:KeyInfo/> element.
377 * Returns: 0 on success and a negative value if an error occurs.
380 xmlSecKeyInfoCtxCreateEncCtx(xmlSecKeyInfoCtxPtr keyInfoCtx) {
381 #ifndef XMLSEC_NO_XMLENC
385 xmlSecAssert2(keyInfoCtx != NULL, -1);
386 xmlSecAssert2(keyInfoCtx->encCtx == NULL, -1);
388 /* we have to use tmp variable to avoid a recursive loop */
389 tmp = xmlSecEncCtxCreate(keyInfoCtx->keysMngr);
391 xmlSecError(XMLSEC_ERRORS_HERE,
393 "xmlSecEncCtxCreate",
394 XMLSEC_ERRORS_R_XMLSEC_FAILED,
395 XMLSEC_ERRORS_NO_MESSAGE);
398 tmp->mode = xmlEncCtxModeEncryptedKey;
400 /* copy user preferences from our current ctx */
401 switch(keyInfoCtx->mode) {
402 case xmlSecKeyInfoModeRead:
403 ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoReadCtx), keyInfoCtx);
405 xmlSecError(XMLSEC_ERRORS_HERE,
407 "xmlSecKeyInfoCtxCopyUserPref",
408 XMLSEC_ERRORS_R_XMLSEC_FAILED,
409 XMLSEC_ERRORS_NO_MESSAGE);
410 xmlSecEncCtxDestroy(tmp);
414 case xmlSecKeyInfoModeWrite:
415 ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoWriteCtx), keyInfoCtx);
417 xmlSecError(XMLSEC_ERRORS_HERE,
419 "xmlSecKeyInfoCtxCopyUserPref",
420 XMLSEC_ERRORS_R_XMLSEC_FAILED,
421 XMLSEC_ERRORS_NO_MESSAGE);
422 xmlSecEncCtxDestroy(tmp);
427 keyInfoCtx->encCtx = tmp;
430 #else /* XMLSEC_NO_XMLENC */
431 xmlSecError(XMLSEC_ERRORS_HERE,
434 XMLSEC_ERRORS_R_DISABLED,
435 XMLSEC_ERRORS_NO_MESSAGE);
437 #endif /* XMLSEC_NO_XMLENC */
441 * xmlSecKeyInfoCtxCopyUserPref:
442 * @dst: the pointer to destination context object.
443 * @src: the pointer to source context object.
445 * Copies user preferences from @src context to @dst context.
447 * Returns: 0 on success and a negative value if an error occurs.
450 xmlSecKeyInfoCtxCopyUserPref(xmlSecKeyInfoCtxPtr dst, xmlSecKeyInfoCtxPtr src) {
453 xmlSecAssert2(dst != NULL, -1);
454 xmlSecAssert2(src != NULL, -1);
456 dst->userData = src->userData;
457 dst->flags = src->flags;
458 dst->flags2 = src->flags2;
459 dst->keysMngr = src->keysMngr;
460 dst->mode = src->mode;
461 dst->base64LineSize = src->base64LineSize;
463 ret = xmlSecPtrListCopy(&(dst->enabledKeyData), &(src->enabledKeyData));
465 xmlSecError(XMLSEC_ERRORS_HERE,
468 XMLSEC_ERRORS_R_XMLSEC_FAILED,
473 /* <dsig:RetrievalMethod/> */
474 dst->maxRetrievalMethodLevel= src->maxRetrievalMethodLevel;
475 ret = xmlSecTransformCtxCopyUserPref(&(dst->retrievalMethodCtx),
476 &(src->retrievalMethodCtx));
478 xmlSecError(XMLSEC_ERRORS_HERE,
480 "xmlSecTransformCtxCopyUserPref",
481 XMLSEC_ERRORS_R_XMLSEC_FAILED,
486 /* <enc:EncryptedContext /> */
487 #ifndef XMLSEC_NO_XMLENC
488 xmlSecAssert2(dst->encCtx == NULL, -1);
489 if(src->encCtx != NULL) {
490 dst->encCtx = xmlSecEncCtxCreate(dst->keysMngr);
491 if(dst->encCtx == NULL) {
492 xmlSecError(XMLSEC_ERRORS_HERE,
494 "xmlSecEncCtxCreate",
495 XMLSEC_ERRORS_R_XMLSEC_FAILED,
496 XMLSEC_ERRORS_NO_MESSAGE);
500 dst->encCtx->mode = xmlEncCtxModeEncryptedKey;
501 ret = xmlSecEncCtxCopyUserPref(dst->encCtx, src->encCtx);
503 xmlSecError(XMLSEC_ERRORS_HERE,
505 "xmlSecEncCtxCopyUserPref",
506 XMLSEC_ERRORS_R_XMLSEC_FAILED,
507 XMLSEC_ERRORS_NO_MESSAGE);
511 dst->maxEncryptedKeyLevel = src->maxEncryptedKeyLevel;
512 #endif /* XMLSEC_NO_XMLENC */
514 /* <dsig:X509Data /> */
515 #ifndef XMLSEC_NO_X509
516 dst->certsVerificationTime = src->certsVerificationTime;
517 dst->certsVerificationDepth = src->certsVerificationDepth;
518 #endif /* XMLSEC_NO_X509 */
524 * xmlSecKeyInfoCtxDebugDump:
525 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
526 * @output: the output file pointer.
528 * Prints user settings and current context state to @output.
531 xmlSecKeyInfoCtxDebugDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
532 xmlSecAssert(keyInfoCtx != NULL);
533 xmlSecAssert(output != NULL);
535 switch(keyInfoCtx->mode) {
536 case xmlSecKeyInfoModeRead:
537 fprintf(output, "= KEY INFO READ CONTEXT\n");
539 case xmlSecKeyInfoModeWrite:
540 fprintf(output, "= KEY INFO WRITE CONTEXT\n");
544 fprintf(output, "== flags: 0x%08x\n", keyInfoCtx->flags);
545 fprintf(output, "== flags2: 0x%08x\n", keyInfoCtx->flags2);
546 if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
547 fprintf(output, "== enabled key data: ");
548 xmlSecKeyDataIdListDebugDump(&(keyInfoCtx->enabledKeyData), output);
550 fprintf(output, "== enabled key data: all\n");
552 fprintf(output, "== RetrievalMethod level (cur/max): %d/%d\n",
553 keyInfoCtx->curRetrievalMethodLevel,
554 keyInfoCtx->maxRetrievalMethodLevel);
555 xmlSecTransformCtxDebugDump(&(keyInfoCtx->retrievalMethodCtx), output);
557 #ifndef XMLSEC_NO_XMLENC
558 fprintf(output, "== EncryptedKey level (cur/max): %d/%d\n",
559 keyInfoCtx->curEncryptedKeyLevel,
560 keyInfoCtx->maxEncryptedKeyLevel);
561 if(keyInfoCtx->encCtx != NULL) {
562 xmlSecEncCtxDebugDump(keyInfoCtx->encCtx, output);
564 #endif /* XMLSEC_NO_XMLENC */
566 xmlSecKeyReqDebugDump(&(keyInfoCtx->keyReq), output);
570 * xmlSecKeyInfoCtxDebugXmlDump:
571 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
572 * @output: the output file pointer.
574 * Prints user settings and current context state in XML format to @output.
577 xmlSecKeyInfoCtxDebugXmlDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
578 xmlSecAssert(keyInfoCtx != NULL);
579 xmlSecAssert(output != NULL);
581 switch(keyInfoCtx->mode) {
582 case xmlSecKeyInfoModeRead:
583 fprintf(output, "<KeyInfoReadContext>\n");
585 case xmlSecKeyInfoModeWrite:
586 fprintf(output, "<KeyInfoWriteContext>\n");
590 fprintf(output, "<Flags>%08x</Flags>\n", keyInfoCtx->flags);
591 fprintf(output, "<Flags2>%08x</Flags2>\n", keyInfoCtx->flags2);
592 if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
593 fprintf(output, "<EnabledKeyData>\n");
594 xmlSecKeyDataIdListDebugXmlDump(&(keyInfoCtx->enabledKeyData), output);
595 fprintf(output, "</EnabledKeyData>\n");
597 fprintf(output, "<EnabledKeyData>all</EnabledKeyData>\n");
600 fprintf(output, "<RetrievalMethodLevel cur=\"%d\" max=\"%d\" />\n",
601 keyInfoCtx->curRetrievalMethodLevel,
602 keyInfoCtx->maxRetrievalMethodLevel);
603 xmlSecTransformCtxDebugXmlDump(&(keyInfoCtx->retrievalMethodCtx), output);
605 #ifndef XMLSEC_NO_XMLENC
606 fprintf(output, "<EncryptedKeyLevel cur=\"%d\" max=\"%d\" />\n",
607 keyInfoCtx->curEncryptedKeyLevel,
608 keyInfoCtx->maxEncryptedKeyLevel);
609 if(keyInfoCtx->encCtx != NULL) {
610 xmlSecEncCtxDebugXmlDump(keyInfoCtx->encCtx, output);
612 #endif /* XMLSEC_NO_XMLENC */
614 xmlSecKeyReqDebugXmlDump(&(keyInfoCtx->keyReq), output);
615 switch(keyInfoCtx->mode) {
616 case xmlSecKeyInfoModeRead:
617 fprintf(output, "</KeyInfoReadContext>\n");
619 case xmlSecKeyInfoModeWrite:
620 fprintf(output, "</KeyInfoWriteContext>\n");
625 /**************************************************************************
627 * <dsig:KeyName/> processing
629 *************************************************************************/
630 static int xmlSecKeyDataNameXmlRead (xmlSecKeyDataId id,
633 xmlSecKeyInfoCtxPtr keyInfoCtx);
634 static int xmlSecKeyDataNameXmlWrite (xmlSecKeyDataId id,
637 xmlSecKeyInfoCtxPtr keyInfoCtx);
639 static xmlSecKeyDataKlass xmlSecKeyDataNameKlass = {
640 sizeof(xmlSecKeyDataKlass),
641 sizeof(xmlSecKeyData),
645 xmlSecKeyDataUsageKeyInfoNode, /* xmlSecKeyDataUsage usage; */
646 NULL, /* const xmlChar* href; */
647 xmlSecNodeKeyName, /* const xmlChar* dataNodeName; */
648 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
650 /* constructors/destructor */
651 NULL, /* xmlSecKeyDataInitializeMethod initialize; */
652 NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */
653 NULL, /* xmlSecKeyDataFinalizeMethod finalize; */
654 NULL, /* xmlSecKeyDataGenerateMethod generate; */
657 NULL, /* xmlSecKeyDataGetTypeMethod getType; */
658 NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
659 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
662 xmlSecKeyDataNameXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
663 xmlSecKeyDataNameXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
664 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
665 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
668 NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
669 NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
671 /* reserved for the future */
672 NULL, /* void* reserved0; */
673 NULL, /* void* reserved1; */
677 * xmlSecKeyDataNameGetKlass:
679 * The <dsig:KeyName/> element key data klass
680 * (http://www.w3.org/TR/xmldsig-core/#sec-KeyName):
682 * The KeyName element contains a string value (in which white space is
683 * significant) which may be used by the signer to communicate a key
684 * identifier to the recipient. Typically, KeyName contains an identifier
685 * related to the key pair used to sign the message, but it may contain
686 * other protocol-related information that indirectly identifies a key pair.
687 * (Common uses of KeyName include simple string names for keys, a key index,
688 * a distinguished name (DN), an email address, etc.)
690 * Returns: the <dsig:KeyName/> element processing key data klass.
693 xmlSecKeyDataNameGetKlass(void) {
694 return(&xmlSecKeyDataNameKlass);
698 xmlSecKeyDataNameXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
699 const xmlChar* oldName;
703 xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
704 xmlSecAssert2(key != NULL, -1);
705 xmlSecAssert2(node != NULL, -1);
706 xmlSecAssert2(keyInfoCtx != NULL, -1);
707 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
709 oldName = xmlSecKeyGetName(key);
710 newName = xmlNodeGetContent(node);
711 if(newName == NULL) {
712 xmlSecError(XMLSEC_ERRORS_HERE,
713 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
714 xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
715 XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
716 XMLSEC_ERRORS_NO_MESSAGE);
719 /* TODO: do we need to decode the name? */
721 /* compare name values */
722 if((oldName != NULL) && !xmlStrEqual(oldName, newName)) {
723 xmlSecError(XMLSEC_ERRORS_HERE,
724 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
725 "key name is already specified",
726 XMLSEC_ERRORS_R_INVALID_KEY_DATA,
727 XMLSEC_ERRORS_NO_MESSAGE);
732 /* try to find key in the manager */
733 if((xmlSecKeyGetValue(key) == NULL) && (keyInfoCtx->keysMngr != NULL)) {
736 tmpKey = xmlSecKeysMngrFindKey(keyInfoCtx->keysMngr, newName, keyInfoCtx);
738 /* erase any current information in the key */
741 /* TODO: since we will destroy tmpKey anyway, we can easily
742 * just re-assign key data values. It'll save use some memory
746 /* and copy what we've found */
747 ret = xmlSecKeyCopy(key, tmpKey);
749 xmlSecError(XMLSEC_ERRORS_HERE,
750 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
752 XMLSEC_ERRORS_R_XMLSEC_FAILED,
753 XMLSEC_ERRORS_NO_MESSAGE);
754 xmlSecKeyDestroy(tmpKey);
758 xmlSecKeyDestroy(tmpKey);
762 /* finally set key name if it is not there */
763 if(xmlSecKeyGetName(key) == NULL) {
764 xmlSecKeySetName(key, newName);
771 xmlSecKeyDataNameXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
774 xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
775 xmlSecAssert2(key != NULL, -1);
776 xmlSecAssert2(node != NULL, -1);
777 xmlSecAssert2(keyInfoCtx != NULL, -1);
778 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
780 name = xmlSecKeyGetName(key);
782 xmlSecNodeEncodeAndSetContent(node, name);
787 /**************************************************************************
789 * <dsig:KeyValue/> processing
791 *************************************************************************/
792 static int xmlSecKeyDataValueXmlRead (xmlSecKeyDataId id,
795 xmlSecKeyInfoCtxPtr keyInfoCtx);
796 static int xmlSecKeyDataValueXmlWrite (xmlSecKeyDataId id,
799 xmlSecKeyInfoCtxPtr keyInfoCtx);
801 static xmlSecKeyDataKlass xmlSecKeyDataValueKlass = {
802 sizeof(xmlSecKeyDataKlass),
803 sizeof(xmlSecKeyData),
807 xmlSecKeyDataUsageKeyInfoNode, /* xmlSecKeyDataUsage usage; */
808 NULL, /* const xmlChar* href; */
809 xmlSecNodeKeyValue, /* const xmlChar* dataNodeName; */
810 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
812 /* constructors/destructor */
813 NULL, /* xmlSecKeyDataInitializeMethod initialize; */
814 NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */
815 NULL, /* xmlSecKeyDataFinalizeMethod finalize; */
816 NULL, /* xmlSecKeyDataGenerateMethod generate; */
819 NULL, /* xmlSecKeyDataGetTypeMethod getType; */
820 NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
821 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
824 xmlSecKeyDataValueXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
825 xmlSecKeyDataValueXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
826 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
827 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
830 NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
831 NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
833 /* reserved for the future */
834 NULL, /* void* reserved0; */
835 NULL, /* void* reserved1; */
839 * xmlSecKeyDataValueGetKlass:
841 * The <dsig:KeyValue/> element key data klass
842 * (http://www.w3.org/TR/xmldsig-core/#sec-KeyValue):
844 * The KeyValue element contains a single public key that may be useful in
845 * validating the signature.
847 * Returns: the <dsig:KeyValue/> element processing key data klass.
850 xmlSecKeyDataValueGetKlass(void) {
851 return(&xmlSecKeyDataValueKlass);
855 xmlSecKeyDataValueXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
856 const xmlChar* nodeName;
857 const xmlChar* nodeNs;
858 xmlSecKeyDataId dataId;
862 xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
863 xmlSecAssert2(key != NULL, -1);
864 xmlSecAssert2(node != NULL, -1);
865 xmlSecAssert2(keyInfoCtx != NULL, -1);
866 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
868 cur = xmlSecGetNextElementNode(node->children);
870 /* just an empty node */
875 nodeName = cur->name;
876 nodeNs = xmlSecGetNodeNsHref(cur);
878 /* use global list only if we don't have a local one */
879 if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
880 dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
881 nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
883 dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
884 nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
886 if(dataId != xmlSecKeyDataIdUnknown) {
888 ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
890 xmlSecError(XMLSEC_ERRORS_HERE,
891 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
892 "xmlSecKeyDataXmlRead",
893 XMLSEC_ERRORS_R_XMLSEC_FAILED,
895 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
898 } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
899 /* laxi schema validation but application can disable it */
900 xmlSecError(XMLSEC_ERRORS_HERE,
901 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
902 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
903 XMLSEC_ERRORS_R_INVALID_NODE,
904 XMLSEC_ERRORS_NO_MESSAGE);
908 /* <dsig:KeyValue/> might have only one node */
909 cur = xmlSecGetNextElementNode(cur->next);
911 xmlSecError(XMLSEC_ERRORS_HERE,
912 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
913 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
914 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
915 XMLSEC_ERRORS_NO_MESSAGE);
923 xmlSecKeyDataValueXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
924 const xmlChar* nodeName;
925 const xmlChar* nodeNs;
929 xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
930 xmlSecAssert2(key != NULL, -1);
931 xmlSecAssert2(node != NULL, -1);
932 xmlSecAssert2(keyInfoCtx != NULL, -1);
933 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
935 if(!xmlSecKeyDataIsValid(key->value) ||
936 !xmlSecKeyDataCheckUsage(key->value, xmlSecKeyDataUsageKeyValueNodeWrite)){
937 /* nothing to write */
940 if((xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) &&
941 (xmlSecKeyDataIdListFind(&(keyInfoCtx->enabledKeyData), id) != 1)) {
943 /* we are not enabled to write out key data with this id */
946 if(xmlSecKeyReqMatchKey(&(keyInfoCtx->keyReq), key) != 1) {
947 /* we are not allowed to write out this key */
951 nodeName = key->value->id->dataNodeName;
952 nodeNs = key->value->id->dataNodeNs;
953 xmlSecAssert2(nodeName != NULL, -1);
955 /* remove all existing key value */
956 xmlNodeSetContent(node, NULL);
958 /* create key node */
959 cur = xmlSecAddChild(node, nodeName, nodeNs);
961 xmlSecError(XMLSEC_ERRORS_HERE,
962 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
964 XMLSEC_ERRORS_R_XMLSEC_FAILED,
966 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
970 ret = xmlSecKeyDataXmlWrite(key->value->id, key, cur, keyInfoCtx);
972 xmlSecError(XMLSEC_ERRORS_HERE,
973 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
974 "xmlSecKeyDataXmlWrite",
975 XMLSEC_ERRORS_R_XMLSEC_FAILED,
977 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
984 /**************************************************************************
986 * <dsig:RetrievalMethod/> processing
988 *************************************************************************/
989 static int xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id,
992 xmlSecKeyInfoCtxPtr keyInfoCtx);
993 static int xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id,
996 xmlSecKeyInfoCtxPtr keyInfoCtx);
1000 static xmlSecKeyDataKlass xmlSecKeyDataRetrievalMethodKlass = {
1001 sizeof(xmlSecKeyDataKlass),
1002 sizeof(xmlSecKeyData),
1005 xmlSecNameRetrievalMethod,
1006 xmlSecKeyDataUsageKeyInfoNode, /* xmlSecKeyDataUsage usage; */
1007 NULL, /* const xmlChar* href; */
1008 xmlSecNodeRetrievalMethod, /* const xmlChar* dataNodeName; */
1009 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
1011 /* constructors/destructor */
1012 NULL, /* xmlSecKeyDataInitializeMethod initialize; */
1013 NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */
1014 NULL, /* xmlSecKeyDataFinalizeMethod finalize; */
1015 NULL, /* xmlSecKeyDataGenerateMethod generate; */
1018 NULL, /* xmlSecKeyDataGetTypeMethod getType; */
1019 NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
1020 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
1023 xmlSecKeyDataRetrievalMethodXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
1024 xmlSecKeyDataRetrievalMethodXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1025 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
1026 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
1029 NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
1030 NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1032 /* reserved for the future */
1033 NULL, /* void* reserved0; */
1034 NULL, /* void* reserved1; */
1037 static int xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId,
1039 const xmlChar* buffer,
1040 xmlSecSize bufferSize,
1041 xmlSecKeyInfoCtxPtr keyInfoCtx);
1044 * xmlSecKeyDataRetrievalMethodGetKlass:
1046 * The <dsig:RetrievalMethod/> element key data klass
1047 * (http://www.w3.org/TR/xmldsig-core/#sec-RetrievalMethod):
1048 * A RetrievalMethod element within KeyInfo is used to convey a reference to
1049 * KeyInfo information that is stored at another location. For example,
1050 * several signatures in a document might use a key verified by an X.509v3
1051 * certificate chain appearing once in the document or remotely outside the
1052 * document; each signature's KeyInfo can reference this chain using a single
1053 * RetrievalMethod element instead of including the entire chain with a
1054 * sequence of X509Certificate elements.
1056 * RetrievalMethod uses the same syntax and dereferencing behavior as
1057 * Reference's URI and The Reference Processing Model.
1059 * Returns: the <dsig:RetrievalMethod/> element processing key data klass.
1062 xmlSecKeyDataRetrievalMethodGetKlass(void) {
1063 return(&xmlSecKeyDataRetrievalMethodKlass);
1067 xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1068 xmlSecKeyDataId dataId = xmlSecKeyDataIdUnknown;
1069 xmlChar *retrType = NULL;
1070 xmlChar *uri = NULL;
1075 xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
1076 xmlSecAssert2(key != NULL, -1);
1077 xmlSecAssert2(node != NULL, -1);
1078 xmlSecAssert2(node->doc != NULL, -1);
1079 xmlSecAssert2(keyInfoCtx != NULL, -1);
1080 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
1082 /* check retrieval level */
1083 if(keyInfoCtx->curRetrievalMethodLevel >= keyInfoCtx->maxRetrievalMethodLevel) {
1084 xmlSecError(XMLSEC_ERRORS_HERE,
1085 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1087 XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,
1089 keyInfoCtx->curRetrievalMethodLevel,
1090 keyInfoCtx->maxRetrievalMethodLevel);
1093 ++keyInfoCtx->curRetrievalMethodLevel;
1095 retrType = xmlGetProp(node, xmlSecAttrType);
1096 if(retrType != NULL) {
1097 /* use global list only if we don't have a local one */
1098 if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
1099 dataId = xmlSecKeyDataIdListFindByHref(&(keyInfoCtx->enabledKeyData),
1100 retrType, xmlSecKeyDataUsageRetrievalMethodNode);
1102 dataId = xmlSecKeyDataIdListFindByHref(xmlSecKeyDataIdsGet(),
1103 retrType, xmlSecKeyDataUsageRetrievalMethodNode);
1107 /* laxi schema validation but aplication can disable it */
1108 if(dataId == xmlSecKeyDataIdUnknown) {
1109 if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_UNKNOWN_HREF) != 0) {
1110 xmlSecError(XMLSEC_ERRORS_HERE,
1111 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1112 xmlSecErrorsSafeString(xmlSecAttrType),
1113 XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE,
1114 "value=%s", xmlSecErrorsSafeString(retrType));
1121 /* destroy prev retrieval method context */
1122 xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
1124 /* set start URI and check that it is enabled */
1125 uri = xmlGetProp(node, xmlSecAttrURI);
1126 ret = xmlSecTransformCtxSetUri(&(keyInfoCtx->retrievalMethodCtx), uri, node);
1128 xmlSecError(XMLSEC_ERRORS_HERE,
1129 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1130 "xmlSecTransformCtxSetUri",
1131 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1133 xmlSecErrorsSafeString(uri));
1137 /* the only one node is optional Transforms node */
1138 cur = xmlSecGetNextElementNode(node->children);
1139 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
1140 ret = xmlSecTransformCtxNodesListRead(&(keyInfoCtx->retrievalMethodCtx),
1141 cur, xmlSecTransformUsageDSigTransform);
1143 xmlSecError(XMLSEC_ERRORS_HERE,
1144 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1145 "xmlSecTransformCtxNodesListRead",
1146 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1148 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1151 cur = xmlSecGetNextElementNode(cur->next);
1155 xmlSecError(XMLSEC_ERRORS_HERE,
1156 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1157 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1158 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1159 XMLSEC_ERRORS_NO_MESSAGE);
1163 /* finally get transforms results */
1164 ret = xmlSecTransformCtxExecute(&(keyInfoCtx->retrievalMethodCtx), node->doc);
1166 (keyInfoCtx->retrievalMethodCtx.result == NULL) ||
1167 (xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result) == NULL)) {
1169 xmlSecError(XMLSEC_ERRORS_HERE,
1170 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1171 "xmlSecTransformCtxExecute",
1172 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1173 XMLSEC_ERRORS_NO_MESSAGE);
1178 /* assume that the data is in XML if we could not find id */
1179 if((dataId == xmlSecKeyDataIdUnknown) ||
1180 ((dataId->usage & xmlSecKeyDataUsageRetrievalMethodNodeXml) != 0)) {
1182 ret = xmlSecKeyDataRetrievalMethodReadXmlResult(dataId, key,
1183 xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
1184 xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
1187 xmlSecError(XMLSEC_ERRORS_HERE,
1188 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1189 "xmlSecKeyDataRetrievalMethodReadXmlResult",
1190 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1191 XMLSEC_ERRORS_NO_MESSAGE);
1195 ret = xmlSecKeyDataBinRead(dataId, key,
1196 xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
1197 xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
1200 xmlSecError(XMLSEC_ERRORS_HERE,
1201 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1202 "xmlSecKeyDataBinRead",
1203 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1204 XMLSEC_ERRORS_NO_MESSAGE);
1208 --keyInfoCtx->curRetrievalMethodLevel;
1215 if(retrType != NULL) {
1222 xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1223 xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
1224 xmlSecAssert2(key != NULL, -1);
1225 xmlSecAssert2(node != NULL, -1);
1226 xmlSecAssert2(keyInfoCtx != NULL, -1);
1227 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
1229 /* just do nothing */
1234 xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId, xmlSecKeyPtr key,
1235 const xmlChar* buffer, xmlSecSize bufferSize,
1236 xmlSecKeyInfoCtxPtr keyInfoCtx) {
1239 const xmlChar* nodeName;
1240 const xmlChar* nodeNs;
1241 xmlSecKeyDataId dataId;
1244 xmlSecAssert2(key != NULL, -1);
1245 xmlSecAssert2(buffer != NULL, -1);
1246 xmlSecAssert2(bufferSize > 0, -1);
1247 xmlSecAssert2(keyInfoCtx != NULL, -1);
1248 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
1250 doc = xmlRecoverMemory((const char*)buffer, bufferSize);
1252 xmlSecError(XMLSEC_ERRORS_HERE,
1253 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
1255 XMLSEC_ERRORS_R_XML_FAILED,
1256 XMLSEC_ERRORS_NO_MESSAGE);
1260 cur = xmlDocGetRootElement(doc);
1262 xmlSecError(XMLSEC_ERRORS_HERE,
1263 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
1264 "xmlDocGetRootElement",
1265 XMLSEC_ERRORS_R_XML_FAILED,
1266 XMLSEC_ERRORS_NO_MESSAGE);
1271 nodeName = cur->name;
1272 nodeNs = xmlSecGetNodeNsHref(cur);
1274 /* use global list only if we don't have a local one */
1275 if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
1276 dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
1277 nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
1279 dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
1280 nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
1282 if(dataId == xmlSecKeyDataIdUnknown) {
1285 /* laxi schema validation but application can disable it */
1286 if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
1287 xmlSecError(XMLSEC_ERRORS_HERE,
1288 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
1289 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1290 XMLSEC_ERRORS_R_INVALID_NODE,
1291 XMLSEC_ERRORS_NO_MESSAGE);
1295 } else if((typeId != xmlSecKeyDataIdUnknown) && (typeId != dataId) &&
1296 ((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_MISMATCH_HREF) != 0)) {
1298 xmlSecError(XMLSEC_ERRORS_HERE,
1299 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
1300 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(dataId)),
1301 XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,
1302 XMLSEC_ERRORS_NO_MESSAGE);
1307 /* read data node */
1308 ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
1310 xmlSecError(XMLSEC_ERRORS_HERE,
1311 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)),
1312 "xmlSecKeyDataXmlRead",
1313 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1315 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1325 #ifndef XMLSEC_NO_XMLENC
1326 /**************************************************************************
1328 * <enc:EncryptedKey/> processing
1330 *************************************************************************/
1331 static int xmlSecKeyDataEncryptedKeyXmlRead (xmlSecKeyDataId id,
1334 xmlSecKeyInfoCtxPtr keyInfoCtx);
1335 static int xmlSecKeyDataEncryptedKeyXmlWrite (xmlSecKeyDataId id,
1338 xmlSecKeyInfoCtxPtr keyInfoCtx);
1342 static xmlSecKeyDataKlass xmlSecKeyDataEncryptedKeyKlass = {
1343 sizeof(xmlSecKeyDataKlass),
1344 sizeof(xmlSecKeyData),
1347 xmlSecNameEncryptedKey,
1348 xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
1349 /* xmlSecKeyDataUsage usage; */
1350 xmlSecHrefEncryptedKey, /* const xmlChar* href; */
1351 xmlSecNodeEncryptedKey, /* const xmlChar* dataNodeName; */
1352 xmlSecEncNs, /* const xmlChar* dataNodeNs; */
1354 /* constructors/destructor */
1355 NULL, /* xmlSecKeyDataInitializeMethod initialize; */
1356 NULL, /* xmlSecKeyDataDuplicateMethod duplicate; */
1357 NULL, /* xmlSecKeyDataFinalizeMethod finalize; */
1358 NULL, /* xmlSecKeyDataGenerateMethod generate; */
1361 NULL, /* xmlSecKeyDataGetTypeMethod getType; */
1362 NULL, /* xmlSecKeyDataGetSizeMethod getSize; */
1363 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
1366 xmlSecKeyDataEncryptedKeyXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
1367 xmlSecKeyDataEncryptedKeyXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1368 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
1369 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
1372 NULL, /* xmlSecKeyDataDebugDumpMethod debugDump; */
1373 NULL, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1375 /* reserved for the future */
1376 NULL, /* void* reserved0; */
1377 NULL, /* void* reserved1; */
1381 * xmlSecKeyDataEncryptedKeyGetKlass:
1383 * The <enc:EncryptedKey/> element key data klass
1384 * (http://www.w3.org/TR/xmlenc-core/#sec-EncryptedKey):
1386 * The EncryptedKey element is used to transport encryption keys from
1387 * the originator to a known recipient(s). It may be used as a stand-alone
1388 * XML document, be placed within an application document, or appear inside
1389 * an EncryptedData element as a child of a ds:KeyInfo element. The key value
1390 * is always encrypted to the recipient(s). When EncryptedKey is decrypted the
1391 * resulting octets are made available to the EncryptionMethod algorithm
1392 * without any additional processing.
1394 * Returns: the <enc:EncryptedKey/> element processing key data klass.
1397 xmlSecKeyDataEncryptedKeyGetKlass(void) {
1398 return(&xmlSecKeyDataEncryptedKeyKlass);
1402 xmlSecKeyDataEncryptedKeyXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1403 xmlSecBufferPtr result;
1406 xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
1407 xmlSecAssert2(key != NULL, -1);
1408 xmlSecAssert2(node != NULL, -1);
1409 xmlSecAssert2(keyInfoCtx != NULL, -1);
1410 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
1412 /* check the enc level */
1413 if(keyInfoCtx->curEncryptedKeyLevel >= keyInfoCtx->maxEncryptedKeyLevel) {
1414 xmlSecError(XMLSEC_ERRORS_HERE,
1415 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1417 XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL,
1419 keyInfoCtx->curEncryptedKeyLevel,
1420 keyInfoCtx->maxEncryptedKeyLevel);
1423 ++keyInfoCtx->curEncryptedKeyLevel;
1425 /* init Enc context */
1426 if(keyInfoCtx->encCtx != NULL) {
1427 xmlSecEncCtxReset(keyInfoCtx->encCtx);
1429 ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
1431 xmlSecError(XMLSEC_ERRORS_HERE,
1432 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1433 "xmlSecKeyInfoCtxCreateEncCtx",
1434 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1435 XMLSEC_ERRORS_NO_MESSAGE);
1439 xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
1441 result = xmlSecEncCtxDecryptToBuffer(keyInfoCtx->encCtx, node);
1442 if((result == NULL) || (xmlSecBufferGetData(result) == NULL)) {
1443 /* We might have multiple EncryptedKey elements, encrypted
1444 * for different receipints but application can enforce
1447 if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_ENCKEY_DONT_STOP_ON_FAILED_DECRYPTION) != 0) {
1448 xmlSecError(XMLSEC_ERRORS_HERE,
1449 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1450 "xmlSecEncCtxDecryptToBuffer",
1451 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1452 XMLSEC_ERRORS_NO_MESSAGE);
1458 ret = xmlSecKeyDataBinRead(keyInfoCtx->keyReq.keyId, key,
1459 xmlSecBufferGetData(result),
1460 xmlSecBufferGetSize(result),
1463 xmlSecError(XMLSEC_ERRORS_HERE,
1464 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1465 "xmlSecKeyDataBinRead",
1466 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1467 XMLSEC_ERRORS_NO_MESSAGE);
1470 --keyInfoCtx->curEncryptedKeyLevel;
1476 xmlSecKeyDataEncryptedKeyXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1477 xmlSecKeyInfoCtx keyInfoCtx2;
1478 xmlSecByte *keyBuf = NULL;
1479 xmlSecSize keySize = 0;
1483 xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
1484 xmlSecAssert2(key != NULL, -1);
1485 xmlSecAssert2(xmlSecKeyIsValid(key), -1);
1486 xmlSecAssert2(node != NULL, -1);
1487 xmlSecAssert2(keyInfoCtx != NULL, -1);
1488 xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
1490 /* dump key to a binary buffer */
1491 ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx2, NULL);
1493 xmlSecError(XMLSEC_ERRORS_HERE,
1494 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1495 "xmlSecKeyInfoCtxInitialize",
1496 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1497 XMLSEC_ERRORS_NO_MESSAGE);
1501 ret = xmlSecKeyInfoCtxCopyUserPref(&keyInfoCtx2, keyInfoCtx);
1503 xmlSecError(XMLSEC_ERRORS_HERE,
1504 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1505 "xmlSecKeyInfoCtxCopyUserPref",
1506 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1507 XMLSEC_ERRORS_NO_MESSAGE);
1508 xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
1512 keyInfoCtx2.keyReq.keyType = xmlSecKeyDataTypeAny;
1513 ret = xmlSecKeyDataBinWrite(key->value->id, key, &keyBuf, &keySize, &keyInfoCtx2);
1515 xmlSecError(XMLSEC_ERRORS_HERE,
1516 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1517 "xmlSecKeyDataBinWrite",
1518 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1519 XMLSEC_ERRORS_NO_MESSAGE);
1520 xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
1523 xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
1525 /* init Enc context */
1526 if(keyInfoCtx->encCtx != NULL) {
1527 xmlSecEncCtxReset(keyInfoCtx->encCtx);
1529 ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
1531 xmlSecError(XMLSEC_ERRORS_HERE,
1532 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1533 "xmlSecKeyInfoCtxCreateEncCtx",
1534 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1535 XMLSEC_ERRORS_NO_MESSAGE);
1539 xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
1541 ret = xmlSecEncCtxBinaryEncrypt(keyInfoCtx->encCtx, node, keyBuf, keySize);
1543 xmlSecError(XMLSEC_ERRORS_HERE,
1544 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1545 "xmlSecEncCtxBinaryEncrypt",
1546 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1547 XMLSEC_ERRORS_NO_MESSAGE);
1553 if(keyBuf != NULL) {
1554 memset(keyBuf, 0, keySize);
1555 xmlFree(keyBuf); keyBuf = NULL;
1560 #endif /* XMLSEC_NO_XMLENC */