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