df3d1aa7562294116980a67b1c639e32b16f9545
[shibboleth/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             auto_ptr_XMLCh wide(n->c_str());
58             KeyName* kname = KeyNameBuilder::buildKeyName();
59             kname->setName(wide.get());
60             knames.push_back(kname);
61         }
62     }
63     
64     if (!m_xseccerts.empty()) {
65         m_keyInfo = m_compactKeyInfo ? m_compactKeyInfo->cloneKeyInfo() : KeyInfoBuilder::buildKeyInfo();
66         X509Data* x509Data=X509DataBuilder::buildX509Data();
67         m_keyInfo->getX509Datas().push_back(x509Data);
68         for (vector<XSECCryptoX509*>::const_iterator x = m_xseccerts.begin(); x!=m_xseccerts.end(); ++x) {
69             safeBuffer& buf=(*x)->getDEREncodingSB();
70             X509Certificate* x509=X509CertificateBuilder::buildX509Certificate();
71             x509->setValue(buf.sbStrToXMLCh());
72             x509Data->getX509Certificates().push_back(x509);
73         }
74     }
75 }
76
77 void X509Credential::extractNames(XSECCryptoX509* x509, set<string>& names)
78 {
79     if (!x509 || x509->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL)
80         return;
81     
82     X509* cert = static_cast<OpenSSLCryptoX509*>(x509)->getOpenSSLX509();
83     if (!cert)
84         return;
85         
86     X509_NAME* subject=X509_get_subject_name(cert);
87     if (subject) {
88         char buf[256];
89         memset(buf,0,sizeof(buf));
90         if (X509_NAME_get_text_by_NID(subject,NID_commonName,buf,255)>0)
91             names.insert(buf);
92
93         STACK_OF(GENERAL_NAME)* altnames=(STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
94         if (altnames) {
95             string alt;
96             int numalts = sk_GENERAL_NAME_num(altnames);
97             for (int an=0; an<numalts; an++) {
98                 const GENERAL_NAME* check = sk_GENERAL_NAME_value(altnames, an);
99                 if (check->type==GEN_DNS || check->type==GEN_URI) {
100                     const char* altptr = (char*)ASN1_STRING_data(check->d.ia5);
101                     const int altlen = ASN1_STRING_length(check->d.ia5);
102                     if (altlen>0) {
103                         alt.erase();
104                         alt.append(altptr,altlen);
105                         names.insert(alt);
106                     }
107                 }
108             }
109         }
110         GENERAL_NAMES_free(altnames);
111     }
112 }
113
114 const char* BasicX509Credential::getAlgorithm() const
115 {
116     if (m_key) {
117         switch (m_key->getKeyType()) {
118             case XSECCryptoKey::KEY_RSA_PRIVATE:
119             case XSECCryptoKey::KEY_RSA_PUBLIC:
120             case XSECCryptoKey::KEY_RSA_PAIR:
121                 return "RSA";
122
123             case XSECCryptoKey::KEY_DSA_PRIVATE:
124             case XSECCryptoKey::KEY_DSA_PUBLIC:
125             case XSECCryptoKey::KEY_DSA_PAIR:
126                 return "DSA";
127             
128             case XSECCryptoKey::KEY_HMAC:
129                 return "HMAC";
130
131             case XSECCryptoKey::KEY_SYMMETRIC: {
132                 switch (static_cast<XSECCryptoSymmetricKey*>(m_key)->getSymmetricKeyType()) {
133                     case XSECCryptoSymmetricKey::KEY_3DES_192:
134                         return "DESede";
135                     case XSECCryptoSymmetricKey::KEY_AES_128:
136                         return "AES";
137                     case XSECCryptoSymmetricKey::KEY_AES_192:
138                         return "AES";
139                     case XSECCryptoSymmetricKey::KEY_AES_256:
140                         return "AES";
141                 }
142             }
143         }
144     }
145     return NULL;
146 }
147
148 unsigned int BasicX509Credential::getKeySize() const
149 {
150     if (m_key) {
151         switch (m_key->getKeyType()) {
152             case XSECCryptoKey::KEY_RSA_PRIVATE:
153             case XSECCryptoKey::KEY_RSA_PUBLIC:
154             case XSECCryptoKey::KEY_RSA_PAIR: {
155                 XSECCryptoKeyRSA* rkey = static_cast<XSECCryptoKeyRSA*>(m_key);
156                 return rkey->getLength();
157             }
158
159             case XSECCryptoKey::KEY_SYMMETRIC: {
160                 switch (static_cast<XSECCryptoSymmetricKey*>(m_key)->getSymmetricKeyType()) {
161                     case XSECCryptoSymmetricKey::KEY_3DES_192:
162                         return 192;
163                     case XSECCryptoSymmetricKey::KEY_AES_128:
164                         return 128;
165                     case XSECCryptoSymmetricKey::KEY_AES_192:
166                         return 192;
167                     case XSECCryptoSymmetricKey::KEY_AES_256:
168                         return 256;
169                 }
170             }
171         }
172     }
173     return 0;
174 }