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