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