| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /* |
| * XSEC |
| * |
| * WinCAPICryptoX509:= Windows CAPI based class for handling X509 (V3) certificates |
| * |
| * Author(s): Berin Lautenbach |
| * |
| * $Id$ |
| * |
| */ |
| |
| #include <xsec/framework/XSECDefs.hpp> |
| #include <xsec/framework/XSECError.hpp> |
| #include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp> |
| #include <xsec/enc/WinCAPI/WinCAPICryptoX509.hpp> |
| #include <xsec/enc/WinCAPI/WinCAPICryptoKeyDSA.hpp> |
| #include <xsec/enc/WinCAPI/WinCAPICryptoKeyRSA.hpp> |
| #include <xsec/enc/XSECCryptoException.hpp> |
| #include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp> |
| |
| #if defined (XSEC_HAVE_WINCAPI) |
| |
| #include <xercesc/util/Janitor.hpp> |
| |
| XSEC_USING_XERCES(ArrayJanitor); |
| |
| WinCAPICryptoX509::WinCAPICryptoX509(HCRYPTPROV provRSA, HCRYPTPROV provDSS) : |
| m_DERX509(""), mp_certContext(NULL), m_pRSA(provRSA), m_pDSS(provDSS) { |
| |
| |
| } |
| |
| WinCAPICryptoX509::WinCAPICryptoX509(PCCERT_CONTEXT pCertContext, |
| HCRYPTPROV provRSA, HCRYPTPROV provDSS) : |
| m_pRSA(provRSA), m_pDSS(provDSS) { |
| |
| // Build this from an existing PCCERT_CONTEXT structure |
| |
| mp_certContext = pCertContext; |
| |
| unsigned char * encCert; |
| unsigned long len = mp_certContext->cbCertEncoded * 2; |
| XSECnew(encCert, unsigned char [len]); |
| ArrayJanitor<unsigned char> j_encCert(encCert); |
| |
| // Base64 Encode |
| XSCryptCryptoBase64 b64; |
| |
| b64.encodeInit(); |
| unsigned long encCertLen = b64.encode(mp_certContext->pbCertEncoded, mp_certContext->cbCertEncoded, encCert, len); |
| encCertLen += b64.encodeFinish(&encCert[encCertLen], len - encCertLen); |
| |
| // Check the result |
| if (encCert == NULL) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "WinCAPIX509:WinCAPIX509 - Error encoding certificate"); |
| } |
| |
| m_DERX509.sbMemcpyIn(encCert, encCertLen); |
| m_DERX509[encCertLen] = '\0'; |
| |
| } |
| |
| WinCAPICryptoX509::~WinCAPICryptoX509() { |
| |
| if (mp_certContext != NULL) |
| CertFreeCertificateContext(mp_certContext); |
| |
| } |
| |
| const XMLCh * WinCAPICryptoX509::getProviderName() const { |
| return DSIGConstants::s_unicodeStrPROVWinCAPI; |
| } |
| |
| // load functions |
| |
| void WinCAPICryptoX509::loadX509Base64Bin(const char * buf, unsigned int len) { |
| |
| unsigned char * rawCert; |
| XSECnew(rawCert, unsigned char [len]); |
| ArrayJanitor<unsigned char> j_rawCert(rawCert); |
| |
| // Base64 Decode |
| XSCryptCryptoBase64 b64; |
| |
| b64.decodeInit(); |
| unsigned int rawCertLen = b64.decode((unsigned char *) buf, len, rawCert, len); |
| rawCertLen += b64.decodeFinish(&rawCert[rawCertLen], len - rawCertLen); |
| |
| // Now load certificate into Win32 CSP |
| |
| mp_certContext = CertCreateCertificateContext( |
| X509_ASN_ENCODING, |
| rawCert, |
| rawCertLen); |
| |
| if (mp_certContext == 0) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "WinCAPIX509:loadX509Base64Bin - Error decoding certificate"); |
| } |
| |
| |
| m_DERX509.sbMemcpyIn(buf, len); |
| m_DERX509[len] = '\0'; |
| |
| } |
| |
| // Info functions |
| |
| XSECCryptoKey::KeyType WinCAPICryptoX509::getPublicKeyType() const { |
| |
| if (mp_certContext == NULL) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "WinCAPI:X509 - getPublicKeyType called before X509 loaded"); |
| } |
| |
| if (lstrcmp(mp_certContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, CRYPTO_OID_DSA) == 0) |
| return XSECCryptoKey::KEY_DSA_PUBLIC; |
| |
| if (lstrcmp(mp_certContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_RSA_RSA) == 0) |
| return XSECCryptoKey::KEY_RSA_PUBLIC; |
| |
| return XSECCryptoKey::KEY_NONE; |
| |
| } |
| |
| |
| // Get functions |
| XSECCryptoKey * WinCAPICryptoX509::clonePublicKey() const { |
| |
| |
| if (mp_certContext == NULL) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "WinCAPI:X509 - clonePublicKey called before X509 loaded"); |
| } |
| |
| // Import the key into the provider to get a pointer to the key |
| |
| HCRYPTKEY key; |
| BOOL fResult; |
| |
| if (getPublicKeyType() == XSECCryptoKey::KEY_DSA_PUBLIC) { |
| |
| fResult= CryptImportPublicKeyInfo( |
| m_pDSS, |
| X509_ASN_ENCODING, |
| &(mp_certContext->pCertInfo->SubjectPublicKeyInfo), |
| &key); |
| |
| |
| if (fResult == FALSE) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "WinCAPI:X509 - Error loading public key info from certificate"); |
| } |
| |
| // Now that we have a handle for the DSA key, create a DSA Key object to |
| // wrap it in |
| |
| WinCAPICryptoKeyDSA * ret; |
| XSECnew(ret, WinCAPICryptoKeyDSA(m_pDSS, key)); |
| |
| return ret; |
| |
| } |
| |
| if (getPublicKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC) { |
| |
| fResult= CryptImportPublicKeyInfo( |
| m_pRSA, |
| X509_ASN_ENCODING, |
| &(mp_certContext->pCertInfo->SubjectPublicKeyInfo), |
| &key); |
| |
| |
| if (fResult == FALSE) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "WinCAPI:X509 - Error loading public key info from certificate"); |
| } |
| |
| // Now that we have a handle for the DSA key, create a DSA Key object to |
| // wrap it in |
| |
| WinCAPICryptoKeyRSA * ret; |
| XSECnew(ret, WinCAPICryptoKeyRSA(m_pRSA, key)); |
| |
| return ret; |
| |
| } |
| |
| return NULL; // Unknown key type, but not necessarily an error |
| |
| } |
| |
| #endif /* XSEC_HAVE_WINCAPI */ |
| |
| |