ff7fb5262f85b68cfd1c0f1c2d460cbc82296d8a
[shibboleth/cpp-xmltooling.git] / xmltooling / security / impl / BasicX509Credential.cpp
1 /*
2  *  Copyright 2001-2007 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * BasicX509Credential.cpp
19  * 
20  * Wraps an X.509-based Credential by storing key/cert objects inside. 
21  */
22
23 #include "internal.h"
24 #include "security/BasicX509Credential.h"
25 #include "signature/KeyInfo.h"
26
27 #include <algorithm>
28 #include <openssl/x509v3.h>
29 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
30
31 using namespace xmlsignature;
32 using namespace xmltooling;
33 using namespace std;
34
35 BasicX509Credential::~BasicX509Credential()
36 {
37     delete m_key;
38     if (m_ownCerts)
39         for_each(m_xseccerts.begin(), m_xseccerts.end(), xmltooling::cleanup<XSECCryptoX509>());
40     delete m_crl;
41     delete m_keyInfo;
42     delete m_compactKeyInfo;
43 }
44
45 void BasicX509Credential::initKeyInfo()
46 {
47     delete m_keyInfo;
48     m_keyInfo = NULL;
49     delete m_compactKeyInfo;
50     m_compactKeyInfo = NULL;
51
52     const set<string>& names = getKeyNames();
53     if (!names.empty()) {
54         m_compactKeyInfo = KeyInfoBuilder::buildKeyInfo();
55         VectorOf(KeyName) knames = m_compactKeyInfo->getKeyNames();
56         for (set<string>::const_iterator n = names.begin(); n!=names.end(); ++n) {
57             if (*n == m_subjectName)
58                 continue;
59             auto_ptr_XMLCh wide(n->c_str());
60             KeyName* kname = KeyNameBuilder::buildKeyName();
61             kname->setName(wide.get());
62             knames.push_back(kname);
63         }
64     }
65
66     if (!m_subjectName.empty() || (!m_issuerName.empty() && m_serial >= 0)) {
67         if (!m_compactKeyInfo)
68             m_compactKeyInfo = KeyInfoBuilder::buildKeyInfo();
69         X509Data* x509Data=X509DataBuilder::buildX509Data();
70         m_compactKeyInfo->getX509Datas().push_back(x509Data);
71         if (!m_subjectName.empty()) {
72             X509SubjectName* sn = X509SubjectNameBuilder::buildX509SubjectName();
73             auto_ptr_XMLCh wide(m_subjectName.c_str());
74             sn->setName(wide.get());
75             x509Data->getX509SubjectNames().push_back(sn);
76         }
77         
78         if (!m_issuerName.empty() && m_serial >= 0) {
79             X509IssuerSerial* is = X509IssuerSerialBuilder::buildX509IssuerSerial();
80             X509IssuerName* in = X509IssuerNameBuilder::buildX509IssuerName();
81             auto_ptr_XMLCh wide(m_issuerName.c_str());
82             in->setName(wide.get());
83             is->setX509IssuerName(in);
84             X509SerialNumber* ser = X509SerialNumberBuilder::buildX509SerialNumber();
85             char buf[64];
86             sprintf(buf,"%d",m_serial);
87             auto_ptr_XMLCh wide2(buf);
88             ser->setSerialNumber(wide2.get());
89             is->setX509SerialNumber(ser);
90             x509Data->getX509IssuerSerials().push_back(is);
91         }
92     }
93     
94     if (!m_xseccerts.empty()) {
95         m_keyInfo = m_compactKeyInfo ? m_compactKeyInfo->cloneKeyInfo() : KeyInfoBuilder::buildKeyInfo();
96         if (m_keyInfo->getX509Datas().empty())
97             m_keyInfo->getX509Datas().push_back(X509DataBuilder::buildX509Data());
98         for (vector<XSECCryptoX509*>::const_iterator x = m_xseccerts.begin(); x!=m_xseccerts.end(); ++x) {
99             safeBuffer& buf=(*x)->getDEREncodingSB();
100             X509Certificate* x509=X509CertificateBuilder::buildX509Certificate();
101             x509->setValue(buf.sbStrToXMLCh());
102             m_keyInfo->getX509Datas().front()->getX509Certificates().push_back(x509);
103         }
104     }
105 }
106
107 void BasicX509Credential::extract()
108 {
109     XSECCryptoX509* x509 = m_xseccerts.empty() ? NULL : m_xseccerts.front();
110     if (!x509 || x509->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL)
111         return;
112     X509* cert = static_cast<OpenSSLCryptoX509*>(x509)->getOpenSSLX509();
113     if (!cert)
114         return;
115
116     BIO* b;
117     int len;
118     char buf[256];
119
120     X509_NAME* issuer=X509_get_issuer_name(cert);
121     if (issuer) {
122         memset(buf,0,sizeof(buf));
123         b = BIO_new(BIO_s_mem());
124         BIO_set_mem_eof_return(b, 0);
125         len=X509_NAME_print_ex(b,issuer,0,XN_FLAG_RFC2253);
126         BIO_flush(b);
127         m_issuerName.erase();
128         while ((len = BIO_read(b, buf, 255)) > 0) {
129             buf[len] = '\0';
130             m_issuerName+=buf;
131         }
132         BIO_free(b);
133     }
134
135     ASN1_INTEGER* serialASN = X509_get_serialNumber(cert);
136     BIGNUM* serialBN = ASN1_INTEGER_to_BN(serialASN, NULL);
137     if (serialBN) {
138         char* serial = BN_bn2dec(serialBN);
139         if (serial) {
140             m_serial = atoi(serial);
141             free(serial);
142         }
143         BN_free(serialBN);
144     }
145     
146     X509_NAME* subject=X509_get_subject_name(cert);
147     if (subject) {
148         memset(buf,0,sizeof(buf));
149         b = BIO_new(BIO_s_mem());
150         BIO_set_mem_eof_return(b, 0);
151         len=X509_NAME_print_ex(b,subject,0,XN_FLAG_RFC2253);
152         BIO_flush(b);
153         m_subjectName.erase();
154         while ((len = BIO_read(b, buf, 255)) > 0) {
155             buf[len] = '\0';
156             m_subjectName+=buf;
157         }
158         m_keyNames.insert(m_subjectName);
159         BIO_free(b);
160
161         memset(buf,0,sizeof(buf));
162         if (X509_NAME_get_text_by_NID(subject,NID_commonName,buf,255)>0)
163             m_keyNames.insert(buf);
164
165         STACK_OF(GENERAL_NAME)* altnames=(STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
166         if (altnames) {
167             string alt;
168             int numalts = sk_GENERAL_NAME_num(altnames);
169             for (int an=0; an<numalts; an++) {
170                 const GENERAL_NAME* check = sk_GENERAL_NAME_value(altnames, an);
171                 if (check->type==GEN_DNS || check->type==GEN_URI) {
172                     const char* altptr = (char*)ASN1_STRING_data(check->d.ia5);
173                     const int altlen = ASN1_STRING_length(check->d.ia5);
174                     if (altlen>0) {
175                         alt.erase();
176                         alt.append(altptr,altlen);
177                         m_keyNames.insert(alt);
178                     }
179                 }
180             }
181         }
182         GENERAL_NAMES_free(altnames);
183     }
184 }
185
186 const char* BasicX509Credential::getAlgorithm() const
187 {
188     if (m_key) {
189         switch (m_key->getKeyType()) {
190             case XSECCryptoKey::KEY_RSA_PRIVATE:
191             case XSECCryptoKey::KEY_RSA_PUBLIC:
192             case XSECCryptoKey::KEY_RSA_PAIR:
193                 return "RSA";
194
195             case XSECCryptoKey::KEY_DSA_PRIVATE:
196             case XSECCryptoKey::KEY_DSA_PUBLIC:
197             case XSECCryptoKey::KEY_DSA_PAIR:
198                 return "DSA";
199             
200             case XSECCryptoKey::KEY_HMAC:
201                 return "HMAC";
202
203             case XSECCryptoKey::KEY_SYMMETRIC: {
204                 switch (static_cast<XSECCryptoSymmetricKey*>(m_key)->getSymmetricKeyType()) {
205                     case XSECCryptoSymmetricKey::KEY_3DES_192:
206                         return "DESede";
207                     case XSECCryptoSymmetricKey::KEY_AES_128:
208                         return "AES";
209                     case XSECCryptoSymmetricKey::KEY_AES_192:
210                         return "AES";
211                     case XSECCryptoSymmetricKey::KEY_AES_256:
212                         return "AES";
213                 }
214             }
215         }
216     }
217     return NULL;
218 }
219
220 unsigned int BasicX509Credential::getKeySize() const
221 {
222     if (m_key) {
223         switch (m_key->getKeyType()) {
224             case XSECCryptoKey::KEY_RSA_PRIVATE:
225             case XSECCryptoKey::KEY_RSA_PUBLIC:
226             case XSECCryptoKey::KEY_RSA_PAIR: {
227                 XSECCryptoKeyRSA* rkey = static_cast<XSECCryptoKeyRSA*>(m_key);
228                 return rkey->getLength();
229             }
230
231             case XSECCryptoKey::KEY_SYMMETRIC: {
232                 switch (static_cast<XSECCryptoSymmetricKey*>(m_key)->getSymmetricKeyType()) {
233                     case XSECCryptoSymmetricKey::KEY_3DES_192:
234                         return 192;
235                     case XSECCryptoSymmetricKey::KEY_AES_128:
236                         return 128;
237                     case XSECCryptoSymmetricKey::KEY_AES_192:
238                         return 192;
239                     case XSECCryptoSymmetricKey::KEY_AES_256:
240                         return 256;
241                 }
242             }
243         }
244     }
245     return 0;
246 }