1 /**
2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
6 *
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
10 * License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
19 */
20
21 /**
22 * BasicX509Credential.cpp
23 *
24 * Wraps an X.509-based Credential by storing key/cert objects inside.
25 */
26
27 #include "internal.h"
28 #include "security/BasicX509Credential.h"
29 #include "security/KeyInfoCredentialContext.h"
30 #include "security/OpenSSLCredential.h"
31 #include "security/SecurityHelper.h"
32 #include "security/XSECCryptoX509CRL.h"
33 #include "signature/KeyInfo.h"
34
35 #include <algorithm>
36 #include <openssl/x509v3.h>
37 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
38 #include <xercesc/util/Base64.hpp>
39
40 using namespace xmlsignature;
41 using namespace xmltooling;
42 using namespace xercesc;
43 using namespace std;
44
Credential()45 Credential::Credential()
46 {
47 }
48
~Credential()49 Credential::~Credential()
50 {
51 }
52
getCredentialContext() const53 const CredentialContext* Credential::getCredentialContext() const
54 {
55 return nullptr;
56 }
57
X509Credential()58 X509Credential::X509Credential()
59 {
60 }
61
~X509Credential()62 X509Credential::~X509Credential()
63 {
64 }
65
OpenSSLCredential()66 OpenSSLCredential::OpenSSLCredential()
67 {
68 }
69
~OpenSSLCredential()70 OpenSSLCredential::~OpenSSLCredential()
71 {
72 }
73
CredentialContext()74 CredentialContext::CredentialContext()
75 {
76 }
77
~CredentialContext()78 CredentialContext::~CredentialContext()
79 {
80 }
81
KeyInfoCredentialContext(const KeyInfo * keyInfo)82 KeyInfoCredentialContext::KeyInfoCredentialContext(const KeyInfo* keyInfo) : m_keyInfo(keyInfo), m_nativeKeyInfo(nullptr)
83 {
84 }
85
KeyInfoCredentialContext(DSIGKeyInfoList * keyInfo)86 KeyInfoCredentialContext::KeyInfoCredentialContext(DSIGKeyInfoList* keyInfo) : m_keyInfo(nullptr), m_nativeKeyInfo(keyInfo)
87 {
88 }
89
~KeyInfoCredentialContext()90 KeyInfoCredentialContext::~KeyInfoCredentialContext()
91 {
92 }
93
getKeyInfo() const94 const KeyInfo* KeyInfoCredentialContext::getKeyInfo() const
95 {
96 return m_keyInfo;
97 }
98
getNativeKeyInfo() const99 DSIGKeyInfoList* KeyInfoCredentialContext::getNativeKeyInfo() const
100 {
101 return m_nativeKeyInfo;
102 }
103
BasicX509Credential(bool ownCerts)104 BasicX509Credential::BasicX509Credential(bool ownCerts) : m_key(nullptr), m_ownCerts(ownCerts), m_keyInfo(nullptr), m_compactKeyInfo(nullptr)
105 {
106 }
107
BasicX509Credential(XSECCryptoKey * key,const vector<XSECCryptoX509 * > & certs,XSECCryptoX509CRL * crl)108 BasicX509Credential::BasicX509Credential(XSECCryptoKey* key, const vector<XSECCryptoX509*>& certs, XSECCryptoX509CRL* crl)
109 : m_key(key), m_xseccerts(certs), m_ownCerts(true), m_keyInfo(nullptr), m_compactKeyInfo(nullptr)
110 {
111 if (crl)
112 m_crls.push_back(crl);
113 }
114
BasicX509Credential(XSECCryptoKey * key,const vector<XSECCryptoX509 * > & certs,const vector<XSECCryptoX509CRL * > & crls)115 BasicX509Credential::BasicX509Credential(XSECCryptoKey* key, const vector<XSECCryptoX509*>& certs, const vector<XSECCryptoX509CRL*>& crls)
116 : m_key(key), m_xseccerts(certs), m_ownCerts(true), m_crls(crls), m_keyInfo(nullptr), m_compactKeyInfo(nullptr)
117 {
118 }
119
~BasicX509Credential()120 BasicX509Credential::~BasicX509Credential()
121 {
122 if (m_ownCerts)
123 for_each(m_xseccerts.begin(), m_xseccerts.end(), xmltooling::cleanup<XSECCryptoX509>());
124 for_each(m_crls.begin(), m_crls.end(), xmltooling::cleanup<XSECCryptoX509CRL>());
125 }
126
initKeyInfo(unsigned int types)127 void BasicX509Credential::initKeyInfo(unsigned int types)
128 {
129 m_keyInfo.reset();
130 m_compactKeyInfo.reset();
131
132 // Default will disable X509IssuerSerial due to schema validation issues.
133 if (types == 0)
134 types = KEYINFO_KEY_VALUE | KEYINFO_KEY_NAME | KEYINFO_X509_CERTIFICATE | KEYINFO_X509_SUBJECTNAME | KEYINFO_X509_DIGEST;
135
136 if (types & KEYINFO_KEY_NAME) {
137 const set<string>& names = getKeyNames();
138 if (!names.empty()) {
139 m_compactKeyInfo.reset(KeyInfoBuilder::buildKeyInfo());
140 VectorOf(KeyName) knames = m_compactKeyInfo->getKeyNames();
141 for (set<string>::const_iterator n = names.begin(); n!=names.end(); ++n) {
142 if (*n == m_subjectName)
143 continue;
144 auto_ptr_XMLCh wide(n->c_str());
145 KeyName* kname = KeyNameBuilder::buildKeyName();
146 kname->setName(wide.get());
147 knames.push_back(kname);
148 }
149 }
150 }
151
152 if (types & KEYINFO_X509_SUBJECTNAME || types & KEYINFO_X509_ISSUERSERIAL) {
153 if (!m_subjectName.empty() || (!m_issuerName.empty() && !m_serial.empty())) {
154 if (!m_compactKeyInfo)
155 m_compactKeyInfo.reset(KeyInfoBuilder::buildKeyInfo());
156 X509Data* x509Data=X509DataBuilder::buildX509Data();
157 m_compactKeyInfo->getX509Datas().push_back(x509Data);
158 if (types & KEYINFO_X509_SUBJECTNAME && !m_subjectName.empty()) {
159 X509SubjectName* sn = X509SubjectNameBuilder::buildX509SubjectName();
160 auto_ptr_XMLCh wide(m_subjectName.c_str());
161 sn->setName(wide.get());
162 x509Data->getX509SubjectNames().push_back(sn);
163 }
164
165 if (types & KEYINFO_X509_ISSUERSERIAL && !m_issuerName.empty() && !m_serial.empty()) {
166 X509IssuerSerial* is = X509IssuerSerialBuilder::buildX509IssuerSerial();
167 X509IssuerName* in = X509IssuerNameBuilder::buildX509IssuerName();
168 auto_ptr_XMLCh wide(m_issuerName.c_str());
169 in->setName(wide.get());
170 is->setX509IssuerName(in);
171 X509SerialNumber* ser = X509SerialNumberBuilder::buildX509SerialNumber();
172 auto_ptr_XMLCh wide2(m_serial.c_str());
173 ser->setSerialNumber(wide2.get());
174 is->setX509SerialNumber(ser);
175 x509Data->getX509IssuerSerials().push_back(is);
176 }
177 }
178 }
179
180 if (types & KEYINFO_X509_CERTIFICATE && !m_xseccerts.empty()) {
181 m_keyInfo.reset(m_compactKeyInfo ? m_compactKeyInfo->cloneKeyInfo() : KeyInfoBuilder::buildKeyInfo());
182 if (m_keyInfo->getX509Datas().empty())
183 m_keyInfo->getX509Datas().push_back(X509DataBuilder::buildX509Data());
184 for (vector<XSECCryptoX509*>::const_iterator x = m_xseccerts.begin(); x!=m_xseccerts.end(); ++x) {
185 safeBuffer& buf=(*x)->getDEREncodingSB();
186 X509Certificate* x509=X509CertificateBuilder::buildX509Certificate();
187 x509->setValue(buf.sbStrToXMLCh());
188 m_keyInfo->getX509Datas().front()->getX509Certificates().push_back(x509);
189 }
190 }
191
192 if (types & KEYINFO_X509_DIGEST && !m_xseccerts.empty()) {
193 if (!m_compactKeyInfo)
194 m_compactKeyInfo.reset(KeyInfoBuilder::buildKeyInfo());
195 if (m_compactKeyInfo->getX509Datas().empty())
196 m_compactKeyInfo->getX509Datas().push_back(X509DataBuilder::buildX509Data());
197 safeBuffer& buf=m_xseccerts.front()->getDEREncodingSB();
198 XMLSize_t x;
199 XMLByte* decoded = Base64::decode(reinterpret_cast<const XMLByte*>(buf.rawCharBuffer()), &x);
200 if (decoded) {
201 string xdig = SecurityHelper::doHash("SHA1", reinterpret_cast<char*>(decoded), x, false);
202 XMLString::release((char**)&decoded);
203 XMLByte* encoded = Base64::encode(reinterpret_cast<const XMLByte*>(xdig.c_str()), xdig.length(), &x);
204 if (encoded) {
205 auto_ptr_XMLCh widenit(reinterpret_cast<char*>(encoded));
206 XMLString::release((char**)&encoded);
207 X509Digest* x509dig = X509DigestBuilder::buildX509Digest();
208 x509dig->setValue(widenit.get());
209 x509dig->setAlgorithm(DSIGConstants::s_unicodeStrURISHA1);
210 m_compactKeyInfo->getX509Datas().front()->getX509Digests().push_back(x509dig);
211 }
212 }
213 }
214 }
215
getUsage() const216 unsigned int BasicX509Credential::getUsage() const
217 {
218 return UNSPECIFIED_CREDENTIAL;
219 }
220
getAlgorithm() const221 const char* BasicX509Credential::getAlgorithm() const
222 {
223 XSECCryptoKey::KeyType type = m_key ? m_key->getKeyType() : XSECCryptoKey::KEY_NONE;
224
225 switch (type) {
226 case XSECCryptoKey::KEY_RSA_PRIVATE:
227 case XSECCryptoKey::KEY_RSA_PUBLIC:
228 case XSECCryptoKey::KEY_RSA_PAIR:
229 return "RSA";
230
231 case XSECCryptoKey::KEY_DSA_PRIVATE:
232 case XSECCryptoKey::KEY_DSA_PUBLIC:
233 case XSECCryptoKey::KEY_DSA_PAIR:
234 return "DSA";
235
236 case XSECCryptoKey::KEY_EC_PRIVATE:
237 case XSECCryptoKey::KEY_EC_PUBLIC:
238 case XSECCryptoKey::KEY_EC_PAIR:
239 return "EC";
240
241 case XSECCryptoKey::KEY_HMAC:
242 return "HMAC";
243
244 case XSECCryptoKey::KEY_SYMMETRIC:
245 {
246 switch (static_cast<XSECCryptoSymmetricKey*>(m_key.get())->getSymmetricKeyType()) {
247 case XSECCryptoSymmetricKey::KEY_3DES_192:
248 return "DESede";
249 case XSECCryptoSymmetricKey::KEY_AES_128:
250 return "AES";
251 case XSECCryptoSymmetricKey::KEY_AES_192:
252 return "AES";
253 case XSECCryptoSymmetricKey::KEY_AES_256:
254 return "AES";
255
256 default:
257 return nullptr;
258 }
259 }
260
261 default:
262 return nullptr;
263 }
264 }
265
getKeySize() const266 unsigned int BasicX509Credential::getKeySize() const
267 {
268 XSECCryptoKey::KeyType type = m_key ? m_key->getKeyType() : XSECCryptoKey::KEY_NONE;
269
270 switch (type) {
271 case XSECCryptoKey::KEY_RSA_PRIVATE:
272 case XSECCryptoKey::KEY_RSA_PUBLIC:
273 case XSECCryptoKey::KEY_RSA_PAIR:
274 {
275 XSECCryptoKeyRSA* rkey = static_cast<XSECCryptoKeyRSA*>(m_key.get());
276 return 8 * rkey->getLength();
277 }
278
279 case XSECCryptoKey::KEY_SYMMETRIC:
280 {
281 switch (static_cast<XSECCryptoSymmetricKey*>(m_key.get())->getSymmetricKeyType()) {
282 case XSECCryptoSymmetricKey::KEY_3DES_192:
283 return 192;
284 case XSECCryptoSymmetricKey::KEY_AES_128:
285 return 128;
286 case XSECCryptoSymmetricKey::KEY_AES_192:
287 return 192;
288 case XSECCryptoSymmetricKey::KEY_AES_256:
289 return 256;
290
291 default:
292 return 0;
293 }
294 }
295
296 default:
297 return 0;
298 }
299 }
300
getPrivateKey() const301 const XSECCryptoKey* BasicX509Credential::getPrivateKey() const
302 {
303 XSECCryptoKey::KeyType type = m_key ? m_key->getKeyType() : XSECCryptoKey::KEY_NONE;
304
305 switch(type) {
306 case XSECCryptoKey::KEY_RSA_PRIVATE:
307 case XSECCryptoKey::KEY_DSA_PRIVATE:
308 case XSECCryptoKey::KEY_EC_PRIVATE:
309 case XSECCryptoKey::KEY_RSA_PAIR:
310 case XSECCryptoKey::KEY_DSA_PAIR:
311 case XSECCryptoKey::KEY_EC_PAIR:
312 return m_key.get();
313
314 default:
315 return nullptr;
316 }
317 }
318
getPublicKey() const319 const XSECCryptoKey* BasicX509Credential::getPublicKey() const
320 {
321 XSECCryptoKey::KeyType type = m_key ? m_key->getKeyType() : XSECCryptoKey::KEY_NONE;
322
323 switch(type) {
324 case XSECCryptoKey::KEY_RSA_PUBLIC:
325 case XSECCryptoKey::KEY_DSA_PUBLIC:
326 case XSECCryptoKey::KEY_EC_PUBLIC:
327 case XSECCryptoKey::KEY_RSA_PAIR:
328 case XSECCryptoKey::KEY_DSA_PAIR:
329 case XSECCryptoKey::KEY_EC_PAIR:
330 return m_key.get();
331
332 default:
333 return nullptr;
334 }
335 }
336
getKeyNames() const337 const set<string>& BasicX509Credential::getKeyNames() const
338 {
339 return m_keyNames;
340 }
341
getKeyInfo(bool compact) const342 KeyInfo* BasicX509Credential::getKeyInfo(bool compact) const
343 {
344 if (compact || !m_keyInfo)
345 return m_compactKeyInfo ? m_compactKeyInfo->cloneKeyInfo() : nullptr;
346 return m_keyInfo->cloneKeyInfo();
347 }
348
getEntityCertificateChain() const349 const vector<XSECCryptoX509*>& BasicX509Credential::getEntityCertificateChain() const
350 {
351 return m_xseccerts;
352 }
353
getCRLs() const354 const vector<XSECCryptoX509CRL*>& BasicX509Credential::getCRLs() const
355 {
356 return m_crls;
357 }
358
getSubjectName() const359 const char* BasicX509Credential::getSubjectName() const
360 {
361 return m_subjectName.c_str();
362 }
363
getIssuerName() const364 const char* BasicX509Credential::getIssuerName() const
365 {
366 return m_issuerName.c_str();
367 }
368
getSerialNumber() const369 const char* BasicX509Credential::getSerialNumber() const
370 {
371 return m_serial.c_str();
372 }
373
extract()374 void BasicX509Credential::extract()
375 {
376 XSECCryptoX509* x509 = m_xseccerts.empty() ? nullptr : m_xseccerts.front();
377 if (!x509 || x509->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL)
378 return;
379 X509* cert = static_cast<OpenSSLCryptoX509*>(x509)->getOpenSSLX509();
380 if (!cert)
381 return;
382
383 X509_NAME* issuer=X509_get_issuer_name(cert);
384 if (issuer) {
385 BIO* b = BIO_new(BIO_s_mem());
386 X509_NAME_print_ex(b,issuer,0,XN_FLAG_RFC2253);
387 BIO_flush(b);
388 BUF_MEM* bptr=nullptr;
389 BIO_get_mem_ptr(b, &bptr);
390 m_issuerName.erase();
391 m_issuerName.append(bptr->data, bptr->length);
392 BIO_free(b);
393 }
394
395 ASN1_INTEGER* serialASN = X509_get_serialNumber(cert);
396 BIGNUM* serialBN = ASN1_INTEGER_to_BN(serialASN, nullptr);
397 if (serialBN) {
398 char* serial = BN_bn2dec(serialBN);
399 if (serial) {
400 m_serial = serial;
401 OPENSSL_free(serial);
402 }
403 BN_free(serialBN);
404 }
405
406 X509_NAME* subject=X509_get_subject_name(cert);
407 if (subject) {
408 BIO* b = BIO_new(BIO_s_mem());
409 X509_NAME_print_ex(b,subject,0,XN_FLAG_RFC2253);
410 BIO_flush(b);
411 BUF_MEM* bptr=nullptr;
412 BIO_get_mem_ptr(b, &bptr);
413 m_subjectName.erase();
414 m_subjectName.append(bptr->data, bptr->length);
415 m_keyNames.insert(m_subjectName);
416 BIO_free(b);
417
418 // Fetch the last CN RDN.
419 char* peer_CN = nullptr;
420 int j,i = -1;
421 while ((j=X509_NAME_get_index_by_NID(subject, NID_commonName, i)) >= 0)
422 i = j;
423 if (i >= 0) {
424 ASN1_STRING* tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i));
425 // Copied in from libcurl.
426 /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
427 is already UTF-8 encoded. We check for this case and copy the raw
428 string manually to avoid the problem. */
429 if(tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
430 j = ASN1_STRING_length(tmp);
431 if(j >= 0) {
432 peer_CN = (char*)OPENSSL_malloc(j + 1);
433 memcpy(peer_CN, ASN1_STRING_data(tmp), j);
434 peer_CN[j] = '\0';
435 }
436 }
437 else /* not a UTF8 name */ {
438 j = ASN1_STRING_to_UTF8(reinterpret_cast<unsigned char**>(&peer_CN), tmp);
439 }
440
441 if (j > 0)
442 m_keyNames.insert(string(peer_CN, j));
443 if(peer_CN)
444 OPENSSL_free(peer_CN);
445 }
446
447 STACK_OF(GENERAL_NAME)* altnames=(STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr);
448 if (altnames) {
449 int numalts = sk_GENERAL_NAME_num(altnames);
450 for (int an=0; an<numalts; an++) {
451 const GENERAL_NAME* check = sk_GENERAL_NAME_value(altnames, an);
452 if (check->type==GEN_DNS || check->type==GEN_URI) {
453 const char* altptr = (char*)ASN1_STRING_data(check->d.ia5);
454 const int altlen = ASN1_STRING_length(check->d.ia5);
455 if (altlen > 0)
456 m_keyNames.insert(string(altptr, altlen));
457 }
458 }
459 }
460 GENERAL_NAMES_free(altnames);
461 }
462 }
463