| /** |
| * 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 |
| * |
| * OpenSSLCryptoX509:= OpenSSL based class for handling X509 (V3) certificates |
| * |
| * Author(s): Berin Lautenbach |
| * |
| * $Id$ |
| * |
| */ |
| |
| #include <xsec/framework/XSECDefs.hpp> |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| |
| #include <xsec/dsig/DSIGConstants.hpp> |
| #include <xsec/framework/XSECError.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyEC.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLSupport.hpp> |
| #include <xsec/enc/XSECCryptoException.hpp> |
| #include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp> |
| |
| #include <xercesc/util/Janitor.hpp> |
| |
| XSEC_USING_XERCES(ArrayJanitor); |
| XSEC_USING_XERCES(Janitor); |
| |
| #include <openssl/evp.h> |
| |
| OpenSSLCryptoX509::OpenSSLCryptoX509() : |
| m_DERX509("") { |
| |
| mp_X509 = NULL; |
| |
| } |
| |
| OpenSSLCryptoX509::~OpenSSLCryptoX509() { |
| |
| if (mp_X509 != NULL) |
| X509_free(mp_X509); |
| |
| } |
| |
| OpenSSLCryptoX509::OpenSSLCryptoX509(X509 * x) { |
| |
| // Build this from an existing X509 structure |
| |
| mp_X509 = X509_dup(x); |
| |
| // Now need to create the DER encoding |
| |
| BIO * b64 = BIO_new(BIO_f_base64()); |
| BIO * bmem = BIO_new(BIO_s_mem()); |
| |
| BIO_set_mem_eof_return(bmem, 0); |
| b64 = BIO_push(b64, bmem); |
| |
| // Translate X509 to Base64 |
| |
| i2d_X509_bio(b64, x); |
| |
| BIO_flush(b64); |
| |
| char buf[1024]; |
| unsigned int l; |
| |
| m_DERX509.sbStrcpyIn(""); |
| |
| while ((l = BIO_read(bmem, buf, 1023)) > 0) { |
| buf[l] = '\0'; |
| m_DERX509.sbStrcatIn(buf); |
| } |
| |
| BIO_free_all(b64); |
| |
| } |
| |
| // load functions |
| |
| void OpenSSLCryptoX509::loadX509Base64Bin(const char * buf, unsigned int len) { |
| |
| // Free anything currently held. |
| |
| if (mp_X509 != NULL) |
| X509_free(mp_X509); |
| |
| // Have to implement using EVP_Decode routines due to a bug in older |
| // versions of OpenSSL BIO_f_base64 |
| |
| int bufLen = len; |
| unsigned char * outBuf; |
| XSECnew(outBuf, unsigned char[len + 1]); |
| ArrayJanitor<unsigned char> j_outBuf(outBuf); |
| |
| /* Had to move to our own Base64 decoder because it handles non-wrapped b64 |
| better. Grrr. */ |
| |
| XSCryptCryptoBase64 *b64; |
| XSECnew(b64, XSCryptCryptoBase64); |
| Janitor<XSCryptCryptoBase64> j_b64(b64); |
| |
| b64->decodeInit(); |
| bufLen = b64->decode((unsigned char *) buf, len, outBuf, len); |
| bufLen += b64->decodeFinish(&outBuf[bufLen], len-bufLen); |
| |
| /* |
| |
| EVP_ENCODE_CTX m_dctx; |
| EVP_DecodeInit(&m_dctx); |
| |
| int rc = EVP_DecodeUpdate(&m_dctx, |
| outBuf, |
| &bufLen, |
| (unsigned char *) buf, |
| len); |
| |
| if (rc < 0) { |
| |
| throw XSECCryptoException(XSECCryptoException::Base64Error, |
| "OpenSSL:Base64 - Error during Base64 Decode of X509 Certificate"); |
| } |
| |
| int finalLen; |
| EVP_DecodeFinal(&m_dctx, &outBuf[bufLen], &finalLen); |
| |
| bufLen += finalLen; |
| */ |
| if (bufLen > 0) { |
| #if defined(XSEC_OPENSSL_D2IX509_CONST_BUFFER) |
| mp_X509= d2i_X509(NULL, (const unsigned char **) (&outBuf), bufLen); |
| #else |
| mp_X509= d2i_X509(NULL, &outBuf, bufLen); |
| #endif |
| } |
| |
| // Check to see if we have a certificate.... |
| if (mp_X509 == NULL) { |
| |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "OpenSSL:X509 - Error translating Base64 DER encoding into OpenSSL X509 structure"); |
| |
| } |
| |
| m_DERX509.sbStrcpyIn(buf); |
| |
| } |
| |
| // Info functions |
| |
| const XMLCh * OpenSSLCryptoX509::getProviderName() const { |
| |
| return DSIGConstants::s_unicodeStrPROVOpenSSL; |
| |
| } |
| |
| XSECCryptoKey::KeyType OpenSSLCryptoX509::getPublicKeyType() const { |
| |
| if (mp_X509 == NULL) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "OpenSSL:X509 - getPublicKeyType called before X509 loaded"); |
| } |
| |
| EVP_PKEY *pkey; |
| |
| pkey = X509_get_pubkey(mp_X509); |
| |
| if (pkey == NULL) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "OpenSSL:X509 - cannot retrieve public key from cert"); |
| } |
| |
| XSECCryptoKey::KeyType ret; |
| |
| switch (EVP_PKEY_id(pkey)) { |
| |
| case EVP_PKEY_DSA : |
| |
| ret = XSECCryptoKey::KEY_DSA_PUBLIC; |
| break; |
| |
| case EVP_PKEY_RSA : |
| |
| ret = XSECCryptoKey::KEY_RSA_PUBLIC; |
| break; |
| |
| #if defined(XSEC_OPENSSL_HAVE_EC) |
| case EVP_PKEY_EC : |
| |
| ret = XSECCryptoKey::KEY_EC_PUBLIC; |
| break; |
| #endif |
| |
| default : |
| |
| ret = XSECCryptoKey::KEY_NONE; |
| |
| } |
| |
| EVP_PKEY_free (pkey); |
| |
| return ret; |
| |
| } |
| |
| |
| // Get functions |
| XSECCryptoKey * OpenSSLCryptoX509::clonePublicKey() const { |
| |
| if (mp_X509 == NULL) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "OpenSSL:X509 - clonePublicKey called before X509 loaded"); |
| } |
| |
| EVP_PKEY *pkey; |
| XSECCryptoKey * ret; |
| |
| pkey = X509_get_pubkey(mp_X509); |
| |
| if (pkey == NULL) { |
| throw XSECCryptoException(XSECCryptoException::X509Error, |
| "OpenSSL:X509 - cannot retrieve public key from cert"); |
| } |
| |
| switch (EVP_PKEY_id(pkey)) { |
| |
| case EVP_PKEY_DSA : |
| |
| ret = new OpenSSLCryptoKeyDSA(pkey); |
| break; |
| |
| case EVP_PKEY_RSA : |
| |
| ret = new OpenSSLCryptoKeyRSA(pkey); |
| break; |
| |
| #if defined(XSEC_OPENSSL_HAVE_EC) |
| case EVP_PKEY_EC : |
| |
| ret = new OpenSSLCryptoKeyEC(pkey); |
| break; |
| #endif |
| |
| default : |
| |
| ret = NULL; |
| |
| } |
| |
| EVP_PKEY_free (pkey); |
| |
| return ret; |
| |
| } |
| |
| #endif /* XSEC_HAVE_OPENSSL */ |