xsec/enc/OpenSSL/OpenSSLCryptoBase64.cpp (102 lines of code) (raw):

/** * 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 * * OpenSSLCryptoBase64 := Base virtual class to define a base64 encoder/decoder * * Author(s): Berin Lautenbach * * $ID$ * * $LOG$ * */ #include <xsec/framework/XSECDefs.hpp> #if defined (XSEC_HAVE_OPENSSL) #include <xsec/enc/OpenSSL/OpenSSLCryptoBase64.hpp> #include <xsec/enc/XSECCryptoException.hpp> #include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp> #include <xsec/framework/XSECError.hpp> #include <xercesc/util/Janitor.hpp> #include <openssl/err.h> XERCES_CPP_NAMESPACE_USE // -------------------------------------------------------------------------------- // Construction/Destruction // -------------------------------------------------------------------------------- #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \ ((defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x30500000L)) OpenSSLCryptoBase64::OpenSSLCryptoBase64() : mp_ectx(&m_ectx_store), mp_dctx(&m_dctx_store) { } OpenSSLCryptoBase64::~OpenSSLCryptoBase64() { } #else OpenSSLCryptoBase64::OpenSSLCryptoBase64() : mp_ectx(EVP_ENCODE_CTX_new()), mp_dctx(EVP_ENCODE_CTX_new()) { if (!mp_ectx || !mp_dctx) throw XSECCryptoException(XSECCryptoException::ECError, "OpenSSL:CrypoBase64 - cannot allocate contexts"); }; OpenSSLCryptoBase64::~OpenSSLCryptoBase64() { EVP_ENCODE_CTX_free(mp_ectx); EVP_ENCODE_CTX_free(mp_dctx); } #endif // -------------------------------------------------------------------------------- // Decoding // -------------------------------------------------------------------------------- void OpenSSLCryptoBase64::decodeInit(void) { EVP_DecodeInit(mp_dctx); } unsigned int OpenSSLCryptoBase64::decode(const unsigned char * inData, unsigned int inLength, unsigned char * outData, unsigned int outLength) { int rc; int outLen; if (outLength < inLength) { throw XSECCryptoException(XSECCryptoException::MemoryError, "OpenSSL:Base64 - Output buffer not big enough for Base64 decode"); } rc = EVP_DecodeUpdate(mp_dctx, outData, &outLen, (unsigned char *) inData, inLength); if (rc < 0) { throw XSECCryptoException(XSECCryptoException::Base64Error, "OpenSSL:Base64 - Error during Base64 Decode"); } if (outLen > (int) outLength) { throw XSECCryptoException(XSECCryptoException::MemoryError, "OpenSSL:Base64 - Output buffer not big enough for Base64 decode and overflowed"); } return outLen; } unsigned int OpenSSLCryptoBase64::decodeFinish(unsigned char * outData, unsigned int outLength) { int outLen; outLen = outLength; EVP_DecodeFinal(mp_dctx, outData, &outLen); return outLen; } // -------------------------------------------------------------------------------- // Encoding // -------------------------------------------------------------------------------- void OpenSSLCryptoBase64::encodeInit(void) { EVP_EncodeInit(mp_ectx); } unsigned int OpenSSLCryptoBase64::encode(const unsigned char * inData, unsigned int inLength, unsigned char * outData, unsigned int outLength) { int outLen; if (outLength + 24 < inLength) { throw XSECCryptoException(XSECCryptoException::MemoryError, "OpenSSL:Base64 - Output buffer not big enough for Base64 encode"); } EVP_EncodeUpdate( mp_ectx, outData, &outLen, (unsigned char *) inData, inLength); if (outLen > (int) outLength) { throw XSECCryptoException(XSECCryptoException::MemoryError, "OpenSSL:Base64 - Output buffer not big enough for Base64 encode and overflowed"); } return outLen; } unsigned int OpenSSLCryptoBase64::encodeFinish(unsigned char * outData, unsigned int outLength) { int outLen; outLen = outLength; EVP_EncodeFinal(mp_ectx, outData, &outLen); return outLen; } // -------------------------------------------------------------------------------- // Utility functions // -------------------------------------------------------------------------------- BIGNUM * OpenSSLCryptoBase64::b642BN(char * b64in, unsigned int len) { if (len > 1024) return NULL; int bufLen; unsigned char buf[1024]; /* EVP_ENCODE_CTX m_dctx; EVP_DecodeInit(&m_dctx); int rc = EVP_DecodeUpdate(&m_dctx, buf, &bufLen, (unsigned char *) b64in, len); if (rc < 0) { throw XSECCryptoException(XSECCryptoException::Base64Error, "OpenSSL:Base64 - Error during Base64 Decode of BIGNUMS"); } int finalLen; EVP_DecodeFinal(&m_dctx, &buf[bufLen], &finalLen); bufLen += finalLen; */ XSCryptCryptoBase64 *b64; XSECnew(b64, XSCryptCryptoBase64); Janitor<XSCryptCryptoBase64> j_b64(b64); b64->decodeInit(); bufLen = b64->decode((unsigned char *) b64in, len, buf, len); bufLen += b64->decodeFinish(&buf[bufLen], len-bufLen); // Now translate to a bignum return BN_bin2bn(buf, bufLen, NULL); } #endif /* XSEC_HAVE_OPENSSL */