| /** |
| * 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 |
| * |
| * OpenSSLCryptoProvider := Base class to define an OpenSSL module |
| * |
| * Author(s): Berin Lautenbach |
| * |
| * $Id$ |
| * |
| */ |
| |
| #include <xsec/framework/XSECDefs.hpp> |
| #if defined (XSEC_HAVE_OPENSSL) |
| |
| #include <xsec/framework/XSECError.hpp> |
| |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoProvider.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoHash.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoHashHMAC.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoBase64.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyEC.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLSupport.hpp> |
| |
| #include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp> |
| |
| #include <xsec/enc/XSECCryptoException.hpp> |
| |
| #include <xercesc/util/Janitor.hpp> |
| |
| XSEC_USING_XERCES(ArrayJanitor); |
| XSEC_USING_XERCES(Janitor); |
| |
| #include <openssl/rand.h> |
| #include <openssl/err.h> |
| #include <openssl/obj_mac.h> |
| |
| OpenSSLCryptoProvider::OpenSSLCryptoProvider() { |
| |
| OpenSSL_add_all_algorithms(); // Initialise Openssl |
| ERR_load_crypto_strings(); |
| |
| //SSLeay_add_all_algorithms(); |
| #ifdef XSEC_OPENSSL_HAVE_EC |
| // Populate curve names. |
| m_namedCurveMap["urn:oid:1.3.132.0.6"] = NID_secp112r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.7"] = NID_secp112r2; |
| m_namedCurveMap["urn:oid:1.3.132.0.28"] = NID_secp128r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.29"] = NID_secp128r2; |
| m_namedCurveMap["urn:oid:1.3.132.0.9"] = NID_secp160k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.8"] = NID_secp160r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.30"] = NID_secp160r2; |
| m_namedCurveMap["urn:oid:1.3.132.0.31"] = NID_secp192k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.32"] = NID_secp224k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.33"] = NID_secp224r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.10"] = NID_secp256k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.34"] = NID_secp384r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.35"] = NID_secp521r1; |
| |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.1.1"] = NID_X9_62_prime192v1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.1.2"] = NID_X9_62_prime192v2; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.1.3"] = NID_X9_62_prime192v3; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.1.4"] = NID_X9_62_prime239v1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.1.5"] = NID_X9_62_prime239v2; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.1.6"] = NID_X9_62_prime239v3; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.1.7"] = NID_X9_62_prime256v1; |
| |
| m_namedCurveMap["urn:oid:1.3.132.0.4"] = NID_sect113r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.5"] = NID_sect113r2; |
| m_namedCurveMap["urn:oid:1.3.132.0.22"] = NID_sect131r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.23"] = NID_sect131r2; |
| m_namedCurveMap["urn:oid:1.3.132.0.1"] = NID_sect163k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.2"] = NID_sect163r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.15"] = NID_sect163r2; |
| m_namedCurveMap["urn:oid:1.3.132.0.24"] = NID_sect193r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.25"] = NID_sect193r2; |
| m_namedCurveMap["urn:oid:1.3.132.0.26"] = NID_sect233k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.27"] = NID_sect233r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.3"] = NID_sect239k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.16"] = NID_sect283k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.17"] = NID_sect283r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.36"] = NID_sect409k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.37"] = NID_sect409r1; |
| m_namedCurveMap["urn:oid:1.3.132.0.38"] = NID_sect571k1; |
| m_namedCurveMap["urn:oid:1.3.132.0.39"] = NID_sect571r1; |
| |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.1"] = NID_X9_62_c2pnb163v1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.2"] = NID_X9_62_c2pnb163v2; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.3"] = NID_X9_62_c2pnb163v3; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.4"] = NID_X9_62_c2pnb176v1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.5"] = NID_X9_62_c2tnb191v1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.6"] = NID_X9_62_c2tnb191v2; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.7"] = NID_X9_62_c2tnb191v3; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.8"] = NID_X9_62_c2onb191v4; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.9"] = NID_X9_62_c2onb191v5; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.10"] = NID_X9_62_c2pnb208w1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.11"] = NID_X9_62_c2tnb239v1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.12"] = NID_X9_62_c2tnb239v2; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.13"] = NID_X9_62_c2tnb239v3; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.14"] = NID_X9_62_c2onb239v4; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.15"] = NID_X9_62_c2onb239v5; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.16"] = NID_X9_62_c2pnb272w1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.17"] = NID_X9_62_c2pnb304w1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.18"] = NID_X9_62_c2tnb359v1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.19"] = NID_X9_62_c2pnb368w1; |
| m_namedCurveMap["urn:oid:1.2.840.10045.3.0.20"] = NID_X9_62_c2tnb431r1; |
| |
| m_namedCurveMap["urn:oid:2.23.43.1.4.1"] = NID_wap_wsg_idm_ecid_wtls1; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.3"] = NID_wap_wsg_idm_ecid_wtls3; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.4"] = NID_wap_wsg_idm_ecid_wtls4; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.5"] = NID_wap_wsg_idm_ecid_wtls5; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.6"] = NID_wap_wsg_idm_ecid_wtls6; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.7"] = NID_wap_wsg_idm_ecid_wtls7; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.8"] = NID_wap_wsg_idm_ecid_wtls8; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.9"] = NID_wap_wsg_idm_ecid_wtls9; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.10"] = NID_wap_wsg_idm_ecid_wtls10; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.11"] = NID_wap_wsg_idm_ecid_wtls11; |
| m_namedCurveMap["urn:oid:2.23.43.1.4.12"] = NID_wap_wsg_idm_ecid_wtls12; |
| #endif |
| } |
| |
| |
| OpenSSLCryptoProvider::~OpenSSLCryptoProvider() { |
| |
| EVP_cleanup(); |
| ERR_free_strings(); |
| /* As suggested by Jesse Pelton */ |
| #if defined(XSEC_OPENSSL_HAVE_CRYPTO_CLEANUP_ALL_EX_DATA) |
| CRYPTO_cleanup_all_ex_data(); |
| #endif |
| RAND_cleanup(); |
| X509_TRUST_cleanup(); |
| ERR_remove_state(0); |
| } |
| |
| #ifdef XSEC_OPENSSL_HAVE_EC |
| int OpenSSLCryptoProvider::curveNameToNID(const char* curveName) const { |
| |
| std::map<std::string,int>::const_iterator i = m_namedCurveMap.find(curveName); |
| if (i == m_namedCurveMap.end()) |
| throw XSECCryptoException(XSECCryptoException::UnsupportedError, |
| "OpenSSLCryptoProvider::curveNameToNID - curve name not recognized"); |
| return i->second; |
| |
| } |
| #endif |
| |
| const XMLCh * OpenSSLCryptoProvider::getProviderName() const { |
| |
| return DSIGConstants::s_unicodeStrPROVOpenSSL; |
| |
| } |
| // Hashing classes |
| |
| unsigned int OpenSSLCryptoProvider::getMaxHashSize() const { |
| return 128; |
| } |
| |
| XSECCryptoHash * OpenSSLCryptoProvider::hash(XSECCryptoHash::HashType type) const { |
| OpenSSLCryptoHash* ret; |
| |
| XSECnew(ret, OpenSSLCryptoHash(type)); |
| |
| return ret; |
| } |
| |
| XSECCryptoHash * OpenSSLCryptoProvider::HMAC(XSECCryptoHash::HashType type) const { |
| OpenSSLCryptoHashHMAC* ret; |
| |
| XSECnew(ret, OpenSSLCryptoHashHMAC(type)); |
| |
| return ret; |
| } |
| |
| XSECCryptoKeyHMAC * OpenSSLCryptoProvider::keyHMAC(void) const { |
| OpenSSLCryptoKeyHMAC * ret; |
| |
| XSECnew(ret, OpenSSLCryptoKeyHMAC); |
| |
| return ret; |
| |
| } |
| |
| XSECCryptoKeyDSA * OpenSSLCryptoProvider::keyDSA() const { |
| OpenSSLCryptoKeyDSA * ret; |
| |
| XSECnew(ret, OpenSSLCryptoKeyDSA()); |
| |
| return ret; |
| |
| } |
| |
| XSECCryptoKeyRSA * OpenSSLCryptoProvider::keyRSA() const { |
| OpenSSLCryptoKeyRSA * ret; |
| |
| XSECnew(ret, OpenSSLCryptoKeyRSA()); |
| |
| return ret; |
| } |
| |
| XSECCryptoKeyEC * OpenSSLCryptoProvider::keyEC() const { |
| |
| #ifdef XSEC_OPENSSL_HAVE_EC |
| OpenSSLCryptoKeyEC * ret; |
| |
| XSECnew(ret, OpenSSLCryptoKeyEC()); |
| |
| return ret; |
| #else |
| throw XSECCryptoException(XSECCryptoException::UnsupportedError, |
| "OpenSSLCryptoProvider::keyEC - EC support not available"); |
| #endif |
| } |
| |
| XSECCryptoKey* OpenSSLCryptoProvider::keyDER(const char* buf, unsigned long len, bool base64) const { |
| |
| EVP_PKEY* pkey = NULL; |
| |
| if (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); |
| |
| BIO* b = BIO_new_mem_buf((void*)outBuf, bufLen); |
| pkey = d2i_PUBKEY_bio(b, NULL); |
| BIO_free(b); |
| |
| } |
| else { |
| |
| BIO* b = BIO_new_mem_buf((void*)buf, len); |
| pkey = d2i_PUBKEY_bio(b, NULL); |
| BIO_free(b); |
| |
| } |
| |
| if (pkey) { |
| XSECCryptoKey* ret = NULL; |
| try { |
| switch (EVP_PKEY_id(pkey)) { |
| case EVP_PKEY_RSA: |
| ret = new OpenSSLCryptoKeyRSA(pkey); |
| break; |
| |
| case EVP_PKEY_DSA: |
| ret = new OpenSSLCryptoKeyDSA(pkey); |
| break; |
| |
| #if defined(XSEC_OPENSSL_HAVE_EC) |
| case EVP_PKEY_EC: |
| ret = new OpenSSLCryptoKeyEC(pkey); |
| break; |
| #endif |
| } |
| } |
| catch (const XSECCryptoException&) { |
| EVP_PKEY_free(pkey); |
| throw; |
| } |
| |
| EVP_PKEY_free(pkey); |
| return ret; |
| } |
| |
| throw XSECCryptoException(XSECCryptoException::UnsupportedError, |
| "OpenSSLCryptoProvider::keyDER - Error decoding public key"); |
| } |
| |
| |
| XSECCryptoX509 * OpenSSLCryptoProvider::X509() const { |
| OpenSSLCryptoX509 * ret; |
| |
| XSECnew(ret, OpenSSLCryptoX509()); |
| |
| return ret; |
| } |
| |
| XSECCryptoBase64 * OpenSSLCryptoProvider::base64() const { |
| XSCryptCryptoBase64 *ret; |
| |
| XSECnew(ret, XSCryptCryptoBase64); |
| |
| return ret; |
| } |
| |
| bool OpenSSLCryptoProvider::algorithmSupported(XSECCryptoSymmetricKey::SymmetricKeyType alg) const { |
| switch (alg) { |
| |
| case (XSECCryptoSymmetricKey::KEY_AES_128) : |
| case (XSECCryptoSymmetricKey::KEY_AES_192) : |
| case (XSECCryptoSymmetricKey::KEY_AES_256) : |
| |
| #if !defined (XSEC_OPENSSL_HAVE_AES) |
| return false; |
| #endif |
| case (XSECCryptoSymmetricKey::KEY_3DES_192) : |
| |
| return true; |
| |
| default: |
| |
| return false; |
| |
| } |
| |
| return false; |
| } |
| |
| bool OpenSSLCryptoProvider::algorithmSupported(XSECCryptoHash::HashType alg) const { |
| switch (alg) { |
| |
| case (XSECCryptoHash::HASH_SHA1) : |
| case (XSECCryptoHash::HASH_MD5) : |
| return true; |
| |
| case (XSECCryptoHash::HASH_SHA224) : |
| case (XSECCryptoHash::HASH_SHA256) : |
| #if defined(XSEC_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA256) |
| return true; |
| #else |
| return false; |
| #endif |
| |
| case (XSECCryptoHash::HASH_SHA384) : |
| case (XSECCryptoHash::HASH_SHA512) : |
| #if defined(XSEC_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA512) |
| return true; |
| #else |
| return false; |
| #endif |
| |
| default: |
| return false; |
| } |
| |
| return false; |
| } |
| |
| |
| XSECCryptoSymmetricKey * OpenSSLCryptoProvider::keySymmetric(XSECCryptoSymmetricKey::SymmetricKeyType alg) const { |
| OpenSSLCryptoSymmetricKey * ret; |
| |
| XSECnew(ret, OpenSSLCryptoSymmetricKey(alg)); |
| |
| return ret; |
| } |
| |
| unsigned int OpenSSLCryptoProvider::getRandom(unsigned char * buffer, unsigned int numOctets) const { |
| if (RAND_status() != 1) { |
| |
| throw XSECCryptoException(XSECCryptoException::GeneralError, |
| "OpenSSLCryptoProvider::getRandom - OpenSSL random not properly initialised"); |
| } |
| |
| int res = RAND_bytes(buffer, numOctets); |
| |
| if (res == 0) { |
| |
| throw XSECCryptoException(XSECCryptoException::GeneralError, |
| "OpenSSLCryptoProvider::getRandom - Error obtaining random octets"); |
| |
| } |
| |
| return numOctets; |
| } |
| |
| |
| #endif /* XSEC_HAVE_OPENSSL */ |