1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 /*
21 * XSEC
22 *
23 * DSIGKeyX509 := A "Super" key that defines a certificate with a sub-key that defines
24 * the signing key
25 *
26 * $Id: DSIGKeyInfoX509.cpp 1833341 2018-06-11 16:25:41Z scantor $
27 *
28 */
29
30 #include <xsec/dsig/DSIGKeyInfoX509.hpp>
31 #include <xsec/dsig/DSIGSignature.hpp>
32 #include <xsec/framework/XSECEnv.hpp>
33 #include <xsec/framework/XSECError.hpp>
34 #include <xsec/utils/XSECPlatformUtils.hpp>
35
36 #include "../utils/XSECAutoPtr.hpp"
37 #include "../utils/XSECDOMUtils.hpp"
38
39 XERCES_CPP_NAMESPACE_USE
40
41 // --------------------------------------------------------------------------------
42 // Constructors and Destructors
43 // --------------------------------------------------------------------------------
44
45
DSIGKeyInfoX509(const XSECEnv * env,DOMNode * X509Data)46 DSIGKeyInfoX509::DSIGKeyInfoX509(const XSECEnv * env, DOMNode *X509Data) :
47 DSIGKeyInfo(env),
48 mp_X509IssuerName(NULL),
49 mp_X509SerialNumber(NULL),
50 mp_X509SubjectName(NULL),
51 mp_X509SKI(NULL),
52 mp_rawRetrievalURI(NULL),
53 mp_X509SubjectNameTextNode(0),
54 mp_X509IssuerNameTextNode(0),
55 mp_X509SerialNumberTextNode(0),
56 mp_X509SKITextNode(0),
57 mp_X509DigestTextNode(0) {
58
59 mp_keyInfoDOMNode = X509Data;
60 m_X509List.clear();
61 m_X509CRLList.clear();
62 }
63
DSIGKeyInfoX509(const XSECEnv * env)64 DSIGKeyInfoX509::DSIGKeyInfoX509(const XSECEnv * env) :
65 DSIGKeyInfo(env),
66 mp_X509IssuerName(NULL),
67 mp_X509SerialNumber(NULL),
68 mp_X509SubjectName(NULL),
69 mp_X509SKI(NULL),
70 mp_rawRetrievalURI(NULL),
71 mp_X509SubjectNameTextNode(0),
72 mp_X509IssuerNameTextNode(0),
73 mp_X509SerialNumberTextNode(0),
74 mp_X509SKITextNode(0),
75 mp_X509DigestTextNode(0){
76
77 mp_keyInfoDOMNode = 0;
78 m_X509List.clear();
79 m_X509CRLList.clear();
80 }
81
82
~DSIGKeyInfoX509()83 DSIGKeyInfoX509::~DSIGKeyInfoX509() {
84
85 // SubjectName and IssuerName are local (decoded) copies of the
86 // encoded DName held in the DOM
87
88 if (mp_X509IssuerName != NULL)
89 XSEC_RELEASE_XMLCH(mp_X509IssuerName);
90
91 if (mp_X509SubjectName != NULL)
92 XSEC_RELEASE_XMLCH(mp_X509SubjectName);
93
94 X509ListType::iterator i;
95
96 for (i = m_X509List.begin(); i != m_X509List.end(); ++i) {
97
98 if ((*i)->mp_cryptoX509 != NULL)
99 delete ((*i)->mp_cryptoX509);
100 delete (*i);
101
102 }
103
104 m_X509List.clear();
105 m_X509CRLList.clear();
106
107 if (mp_rawRetrievalURI != NULL)
108 XSEC_RELEASE_XMLCH(mp_rawRetrievalURI);
109
110
111 };
112
113 // --------------------------------------------------------------------------------
114 // Load and Get
115 // --------------------------------------------------------------------------------
116
117
118 // Methods unique to DSIGKeyInfoX509
119
load(void)120 void DSIGKeyInfoX509::load(void) {
121
122 // Assuming we have a valid DOM_Node to start with, load the signing key so that it can
123 // be used later on
124
125 if (mp_keyInfoDOMNode == NULL) {
126
127 // Attempt to load an empty signature element
128 throw XSECException(XSECException::LoadEmptyX509);
129
130 }
131
132 if (!strEquals(getDSIGLocalName(mp_keyInfoDOMNode), "X509Data")) {
133
134 throw XSECException(XSECException::LoadNonX509);
135
136 }
137
138 // Now check for an X509 Data Element we understand
139
140 DOMNode *tmpElt = mp_keyInfoDOMNode->getFirstChild();
141 DOMNode *child; // Worker
142
143 while (tmpElt != 0) {
144
145 if (tmpElt->getNodeType() == DOMNode::ELEMENT_NODE) {
146
147 // See if it's a known element type
148 if (strEquals(getDSIGLocalName(tmpElt), "X509Certificate")) {
149
150 // Loop over Text nodes until we successfully load a certificate.
151 // If we run out, throw out the last exception raised.
152
153 X509Holder * h;
154 XSECCryptoX509* cryptoX509 = XSECPlatformUtils::g_cryptoProvider->X509();
155 DOMNode *certElt = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
156 while (certElt) {
157 XSECAutoPtrChar charX509(certElt->getNodeValue());
158 try {
159 cryptoX509->loadX509Base64Bin(charX509.get(), (int) strlen(charX509.get()));
160
161 // Add to the list
162 XSECnew(h, X509Holder);
163 m_X509List.push_back(h);
164 h->mp_encodedX509 = certElt->getNodeValue();
165 h->mp_cryptoX509 = cryptoX509;
166 break;
167 }
168 catch (const XSECCryptoException&) {
169 certElt = findNextChildOfType(certElt, DOMNode::TEXT_NODE);
170 if (!certElt) {
171 delete cryptoX509;
172 throw;
173 }
174 }
175 }
176 }
177
178 else if (strEquals(getDSIGLocalName(tmpElt), "X509SubjectName")) {
179
180 child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
181
182 if (child == NULL) {
183
184 throw XSECException(XSECException::ExpectedDSIGChildNotFound,
185 "Expected TEXT_NODE child of <X509SubjectName>");
186
187 }
188
189 mp_X509SubjectName = decodeDName(child->getNodeValue());
190
191 }
192
193 else if (strEquals(getDSIGLocalName(tmpElt), "X509IssuerSerial")) {
194
195 child = tmpElt->getFirstChild();
196 while (child != 0 && child->getNodeType() != DOMNode::ELEMENT_NODE &&
197 !strEquals(getDSIGLocalName(child), "X509IssuerName"))
198 child = child->getNextSibling();
199
200 if (child == NULL) {
201
202 throw XSECException(XSECException::ExpectedDSIGChildNotFound,
203 "Expected <X509IssuerName> child of <X509IssuerSerial>");
204
205 }
206
207 child = child->getFirstChild();
208 while (child != 0 && child->getNodeType() != DOMNode::TEXT_NODE)
209 child = child->getNextSibling();
210
211 if (child == NULL) {
212
213 throw XSECException(XSECException::ExpectedDSIGChildNotFound,
214 "Expected TEXT_NODE child of <X509IssuerSerial>");
215
216 }
217
218 mp_X509IssuerName = decodeDName(child->getNodeValue());
219
220 // Now find the serial number
221 child = tmpElt->getFirstChild();
222 while (child != 0 && (child->getNodeType() != DOMNode::ELEMENT_NODE ||
223 !strEquals(getDSIGLocalName(child), "X509SerialNumber")))
224 child = child->getNextSibling();
225
226 if (child == NULL) {
227
228 throw XSECException(XSECException::ExpectedDSIGChildNotFound,
229 "Expected <X509SerialNumber> child of <X509IssuerSerial>");
230
231 }
232
233 child = child->getFirstChild();
234 while (child != 0 && child->getNodeType() != DOMNode::TEXT_NODE)
235 child = child->getNextSibling();
236
237 if (child == NULL) {
238
239 throw XSECException(XSECException::ExpectedDSIGChildNotFound,
240 "Expected TEXT_NODE child of <X509IssuerSerial>");
241
242 }
243
244 mp_X509SerialNumber = child->getNodeValue();
245
246 }
247
248 else if (strEquals(getDSIGLocalName(tmpElt), "X509CRL")) {
249
250 DOMNode *crlElt = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
251
252 if (crlElt != 0) {
253
254 // Add to the list
255 m_X509CRLList.push_back(crlElt->getNodeValue());
256
257 }
258
259 }
260 else if (strEquals(getDSIGLocalName(tmpElt), "X509SKI")) {
261
262 child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
263
264 if (child == NULL) {
265
266 throw XSECException(XSECException::ExpectedDSIGChildNotFound,
267 "Expected TEXT_NODE child of <X509SKI>");
268
269 }
270
271 mp_X509SKITextNode = child;
272 mp_X509SKI = child->getNodeValue();
273
274 }
275 else if (strEquals(getDSIG11LocalName(tmpElt), "X509Digest")) {
276
277 child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE);
278
279 if (child == NULL) {
280
281 throw XSECException(XSECException::ExpectedDSIGChildNotFound,
282 "Expected TEXT_NODE child of <X509Digest>");
283
284 }
285
286 mp_X509DigestTextNode = child;
287
288 }
289 }
290
291 // Go to next data element to load if we understand
292
293 tmpElt = tmpElt->getNextSibling();
294
295 }
296
297 }
298
getKeyName(void) const299 const XMLCh * DSIGKeyInfoX509::getKeyName(void) const {
300
301 return mp_X509SubjectName;
302
303 // Should return DN
304
305 }
306
getX509SubjectName(void) const307 const XMLCh * DSIGKeyInfoX509::getX509SubjectName(void) const {
308
309
310 return mp_X509SubjectName;
311
312 }
313
getX509DigestAlgorithm(void) const314 const XMLCh * DSIGKeyInfoX509::getX509DigestAlgorithm(void) const {
315
316 return mp_X509DigestTextNode ?
317 static_cast<DOMElement*>(mp_X509DigestTextNode->getParentNode())->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm) :
318 NULL;
319
320 }
321
getX509DigestValue(void) const322 const XMLCh * DSIGKeyInfoX509::getX509DigestValue(void) const {
323
324 return mp_X509DigestTextNode ? mp_X509DigestTextNode->getNodeValue() : NULL;
325
326 }
327
getX509IssuerName(void) const328 const XMLCh * DSIGKeyInfoX509::getX509IssuerName(void) const {
329
330 return mp_X509IssuerName;
331
332 }
333
getX509IssuerSerialNumber(void) const334 const XMLCh * DSIGKeyInfoX509::getX509IssuerSerialNumber(void) const {
335
336 return mp_X509SerialNumber;
337
338 }
339
getX509CRL(void) const340 const XMLCh * DSIGKeyInfoX509::getX509CRL(void) const {
341
342 return m_X509CRLList.empty() ? NULL : m_X509CRLList.front();
343
344 }
345
getX509CRLListSize(void) const346 int DSIGKeyInfoX509::getX509CRLListSize(void) const {
347
348 return (int) m_X509CRLList.size();
349
350 }
351
352
getX509CRLItem(int item) const353 const XMLCh * DSIGKeyInfoX509::getX509CRLItem(int item) const {
354
355 if (item >=0 && (unsigned int) item < m_X509CRLList.size())
356 return m_X509CRLList[item];
357
358 return 0;
359
360 }
361
getX509SKI(void) const362 const XMLCh * DSIGKeyInfoX509::getX509SKI(void) const {
363
364 return mp_X509SKI;
365
366 }
367
getCertificateListSize(void) const368 int DSIGKeyInfoX509::getCertificateListSize(void) const {
369
370 return (int) m_X509List.size();
371
372 }
373
getCertificateItem(int item) const374 const XMLCh * DSIGKeyInfoX509::getCertificateItem(int item) const {
375
376 if (item >=0 && (unsigned int) item < m_X509List.size())
377 return m_X509List[item]->mp_encodedX509;
378
379 return 0;
380
381 }
382
getCertificateCryptoItem(int item)383 XSECCryptoX509 * DSIGKeyInfoX509::getCertificateCryptoItem(int item) {
384
385 if (item >=0 && (unsigned int) item < m_X509List.size())
386 return m_X509List[item]->mp_cryptoX509;
387
388 return 0;
389 }
390
getCertificateCryptoItem(int item) const391 const XSECCryptoX509 * DSIGKeyInfoX509::getCertificateCryptoItem(int item) const {
392
393 if (item >=0 && (unsigned int) item < m_X509List.size())
394 return m_X509List[item]->mp_cryptoX509;
395
396 return 0;
397 }
398
getRawRetrievalURI(void) const399 const XMLCh * DSIGKeyInfoX509::getRawRetrievalURI(void) const {
400
401 return mp_rawRetrievalURI;
402
403 }
404
405 // --------------------------------------------------------------------------------
406 // Create and Set
407 // --------------------------------------------------------------------------------
408
createBlankX509Data(void)409 DOMElement * DSIGKeyInfoX509::createBlankX509Data(void) {
410
411 // Create the DOM Structure
412
413 safeBuffer str;
414 DOMDocument *doc = mp_env->getParentDocument();
415 const XMLCh * prefix = mp_env->getDSIGNSPrefix();
416
417 makeQName(str, prefix, "X509Data");
418
419 DOMElement *ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
420 mp_keyInfoDOMNode = ret;
421 mp_env->doPrettyPrint(ret);
422
423 return ret;
424
425 }
426
setX509CRL(const XMLCh * crl)427 void DSIGKeyInfoX509::setX509CRL(const XMLCh * crl) {
428 appendX509CRL(crl);
429 }
430
appendX509CRL(const XMLCh * crl)431 void DSIGKeyInfoX509::appendX509CRL(const XMLCh * crl) {
432
433 safeBuffer str;
434 DOMDocument *doc = mp_env->getParentDocument();
435 const XMLCh * prefix = mp_env->getDSIGNSPrefix();
436
437 makeQName(str, prefix, "X509CRL");
438
439 DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
440 DOMNode * b64Txt = doc->createTextNode(crl);
441 s->appendChild(b64Txt);
442
443 mp_keyInfoDOMNode->appendChild(s);
444 mp_env->doPrettyPrint(mp_keyInfoDOMNode);
445
446 // Add to the list
447
448 m_X509CRLList.push_back(b64Txt->getNodeValue());
449 }
450
setX509SKI(const XMLCh * ski)451 void DSIGKeyInfoX509::setX509SKI(const XMLCh * ski) {
452
453 if (mp_X509SKITextNode == 0) {
454
455 safeBuffer str;
456 DOMDocument *doc = mp_env->getParentDocument();
457 const XMLCh * prefix = mp_env->getDSIGNSPrefix();
458
459 makeQName(str, prefix, "X509SKI");
460
461 DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
462 mp_X509SKITextNode = doc->createTextNode(ski);
463 s->appendChild(mp_X509SKITextNode);
464
465 // Add to the over-arching node
466 mp_keyInfoDOMNode->appendChild(s);
467 mp_env->doPrettyPrint(mp_keyInfoDOMNode);
468
469 }
470
471 else {
472
473 mp_X509SKITextNode->setNodeValue(ski);
474
475 }
476
477 mp_X509SKI = mp_X509SKITextNode->getNodeValue();
478
479 }
480
setX509SubjectName(const XMLCh * name)481 void DSIGKeyInfoX509::setX509SubjectName(const XMLCh * name) {
482
483 if (mp_X509SubjectName != NULL)
484 XSEC_RELEASE_XMLCH(mp_X509SubjectName);
485
486 mp_X509SubjectName = XMLString::replicate(name);
487
488 XMLCh * encodedName = encodeDName(name);
489
490 if (mp_X509SubjectNameTextNode == 0) {
491
492 // Does not yet exist in the DOM
493
494 safeBuffer str;
495 DOMDocument *doc = mp_env->getParentDocument();
496 const XMLCh * prefix = mp_env->getDSIGNSPrefix();
497
498 makeQName(str, prefix, "X509SubjectName");
499
500 DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
501 mp_X509SubjectNameTextNode = doc->createTextNode(encodedName);
502 s->appendChild(mp_X509SubjectNameTextNode);
503
504 // Add to the over-arching node
505 mp_keyInfoDOMNode->appendChild(s);
506 mp_env->doPrettyPrint(mp_keyInfoDOMNode);
507
508 }
509
510 else {
511
512 mp_X509SubjectNameTextNode->setNodeValue(encodedName);
513
514 }
515 XSEC_RELEASE_XMLCH(encodedName);
516 }
517
setX509IssuerSerial(const XMLCh * name,const XMLCh * serial)518 void DSIGKeyInfoX509::setX509IssuerSerial(const XMLCh * name, const XMLCh * serial) {
519
520 if (mp_X509IssuerName != NULL)
521 XSEC_RELEASE_XMLCH(mp_X509IssuerName);
522
523 mp_X509IssuerName = XMLString::replicate(name);
524
525 XMLCh * encodedName = encodeDName(name);
526
527 if (mp_X509IssuerNameTextNode == 0) {
528
529 // Does not yet exist in the DOM
530
531 safeBuffer str;
532 DOMDocument *doc = mp_env->getParentDocument();
533 const XMLCh * prefix = mp_env->getDSIGNSPrefix();
534
535 makeQName(str, prefix, "X509IssuerSerial");
536
537 DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
538 mp_env->doPrettyPrint(s);
539
540 // Create the text nodes with the contents
541
542 mp_X509IssuerNameTextNode = doc->createTextNode(encodedName);
543 mp_X509SerialNumberTextNode = doc->createTextNode(serial);
544
545 // Create the sub elements
546
547 makeQName(str, prefix, "X509IssuerName");
548 DOMElement * t = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
549 t->appendChild(mp_X509IssuerNameTextNode);
550
551 s->appendChild(t);
552 mp_env->doPrettyPrint(s);
553
554 makeQName(str, prefix, "X509SerialNumber");
555 t = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
556 t->appendChild(mp_X509SerialNumberTextNode);
557
558 s->appendChild(t);
559 mp_env->doPrettyPrint(s);
560
561 // Add to the over-arching X509Data
562
563 mp_keyInfoDOMNode->appendChild(s);
564 mp_env->doPrettyPrint(mp_keyInfoDOMNode);
565
566 }
567
568 else {
569
570 mp_X509IssuerNameTextNode->setNodeValue(encodedName);
571 mp_X509SerialNumberTextNode->setNodeValue(serial);
572
573 }
574
575 XSEC_RELEASE_XMLCH(encodedName);
576 }
577
setX509Digest(const XMLCh * algorithm,const XMLCh * value)578 void DSIGKeyInfoX509::setX509Digest(const XMLCh * algorithm, const XMLCh * value) {
579
580 if (mp_X509DigestTextNode == 0) {
581
582 // Does not yet exist in the DOM
583
584 safeBuffer str;
585 DOMDocument *doc = mp_env->getParentDocument();
586 const XMLCh * prefix = mp_env->getDSIG11NSPrefix();
587
588 makeQName(str, prefix, "X509Digest");
589
590 DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG11, str.rawXMLChBuffer());
591 s->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, algorithm);
592
593 // Create the text node with the contents
594
595 mp_X509DigestTextNode = doc->createTextNode(value);
596 s->appendChild(mp_X509DigestTextNode);
597
598 mp_env->doPrettyPrint(s);
599
600 // Add to the over-arching X509Data
601
602 mp_keyInfoDOMNode->appendChild(s);
603 mp_env->doPrettyPrint(mp_keyInfoDOMNode);
604
605 }
606
607 else {
608
609 mp_X509DigestTextNode->setNodeValue(value);
610 static_cast<DOMElement*>(mp_X509DigestTextNode->getParentNode())->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, algorithm);
611
612 }
613
614 }
615
setRawRetrievalURI(const XMLCh * uri)616 void DSIGKeyInfoX509::setRawRetrievalURI(const XMLCh * uri) {
617
618 if (mp_rawRetrievalURI != NULL)
619 XSEC_RELEASE_XMLCH(mp_rawRetrievalURI);
620
621 mp_rawRetrievalURI = XMLString::replicate(uri);
622
623 }
624
appendX509Certificate(const XMLCh * base64Certificate)625 void DSIGKeyInfoX509::appendX509Certificate(const XMLCh * base64Certificate) {
626
627 safeBuffer str;
628 DOMDocument *doc = mp_env->getParentDocument();
629 const XMLCh * prefix = mp_env->getDSIGNSPrefix();
630
631 makeQName(str, prefix, "X509Certificate");
632
633 DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer());
634 DOMNode * b64Txt = doc->createTextNode(base64Certificate);
635 s->appendChild(b64Txt);
636
637 mp_keyInfoDOMNode->appendChild(s);
638 mp_env->doPrettyPrint(mp_keyInfoDOMNode);
639
640 // Add to the list
641
642 X509Holder * h;
643 XSECnew(h, X509Holder);
644 m_X509List.push_back(h);
645 h->mp_encodedX509 = b64Txt->getNodeValue();
646 h->mp_cryptoX509 = XSECPlatformUtils::g_cryptoProvider->X509();
647 XSECAutoPtrChar charX509(h->mp_encodedX509);
648 h->mp_cryptoX509->loadX509Base64Bin(charX509.get(), (unsigned int) strlen(charX509.get()));
649
650 }
651