blob: 2d7c19048b1f45d35c3822878356b5e79a19fa0e [file] [log] [blame]
/**
* 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
*
* OpenSSLCryptoHashHMAC := OpenSSL Implementation of HMAC
*
* Author(s): Berin Lautenbach
*
* $Id$
*
*/
#include <xsec/framework/XSECDefs.hpp>
#if defined (XSEC_HAVE_OPENSSL)
#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/enc/XSECCryptoKeyHMAC.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoHashHMAC.hpp>
#include <memory.h>
// Constructors/Destructors
OpenSSLCryptoHashHMAC::OpenSSLCryptoHashHMAC(HashType alg) : m_mdLen(0),
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
mp_hctx(&m_hctx_store)
#else
mp_hctx(HMAC_CTX_new())
#endif
, m_keyLen(0)
{
if (!mp_hctx)
throw XSECCryptoException(XSECCryptoException::ECError, "OpenSSL::CryptoHashHMAC - cannot allocate contexts");
// Initialise the digest
switch (alg) {
case (XSECCryptoHash::HASH_SHA1) :
mp_md = EVP_get_digestbyname("SHA1");
break;
case (XSECCryptoHash::HASH_MD5) :
mp_md = EVP_get_digestbyname("MD5");
break;
case (XSECCryptoHash::HASH_SHA224) :
mp_md = EVP_get_digestbyname("SHA224");
if (mp_md == NULL) {
throw XSECCryptoException(XSECCryptoException::MDError,
"OpenSSL:Hash - SHA224 not supported by this version of OpenSSL");
}
break;
case (XSECCryptoHash::HASH_SHA256) :
mp_md = EVP_get_digestbyname("SHA256");
if (mp_md == NULL) {
throw XSECCryptoException(XSECCryptoException::MDError,
"OpenSSL:Hash - SHA256 not supported by this version of OpenSSL");
}
break;
case (XSECCryptoHash::HASH_SHA384) :
mp_md = EVP_get_digestbyname("SHA384");
if (mp_md == NULL) {
throw XSECCryptoException(XSECCryptoException::MDError,
"OpenSSL:Hash - SHA384 not supported by this version of OpenSSL");
}
break;
case (XSECCryptoHash::HASH_SHA512) :
mp_md = EVP_get_digestbyname("SHA512");
if (mp_md == NULL) {
throw XSECCryptoException(XSECCryptoException::MDError,
"OpenSSL:Hash - SHA512 not supported by this version of OpenSSL");
}
break;
default :
mp_md = NULL;
}
if(!mp_md) {
throw XSECCryptoException(XSECCryptoException::MDError,
"OpenSSL:HashHMAC - Error loading Message Digest");
}
m_initialised = false;
m_hashType = alg;
}
const XMLCh* OpenSSLCryptoHashHMAC::getProviderName() const {
return DSIGConstants::s_unicodeStrPROVOpenSSL;
}
void OpenSSLCryptoHashHMAC::setKey(const XSECCryptoKey *key) {
// Use this to initialise the HMAC Context
if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) {
throw XSECCryptoException(XSECCryptoException::MDError,
"OpenSSL:HashHMAC - Non HMAC Key passed to OpenSSLHashHMAC");
}
m_keyLen = ((XSECCryptoKeyHMAC *) key)->getKey(m_keyBuf);
HMAC_Init(mp_hctx,
m_keyBuf.rawBuffer(),
m_keyLen,
mp_md);
m_initialised = true;
}
OpenSSLCryptoHashHMAC::~OpenSSLCryptoHashHMAC() {
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
if (m_initialised)
HMAC_CTX_cleanup(mp_hctx);
#else
HMAC_CTX_free(mp_hctx);
#endif
}
// Hashing Activities
void OpenSSLCryptoHashHMAC::reset(void) {
if (m_initialised) {
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
HMAC_CTX_cleanup(mp_hctx);
#endif
HMAC_Init(mp_hctx,
m_keyBuf.rawBuffer(),
m_keyLen,
mp_md);
}
}
void OpenSSLCryptoHashHMAC::hash(unsigned char * data,
unsigned int length) {
if (!m_initialised)
throw XSECCryptoException(XSECCryptoException::MDError,
"OpenSSL:HashHMAC - hash called prior to setKey");
HMAC_Update(mp_hctx, data, (int) length);
}
unsigned int OpenSSLCryptoHashHMAC::finish(unsigned char * hash,
unsigned int maxLength) {
unsigned int retLen;
// Finish up and copy out hash, returning the length
HMAC_Final(mp_hctx, m_mdValue, &m_mdLen);
// Copy to output buffer
retLen = (maxLength > m_mdLen ? m_mdLen : maxLength);
memcpy(hash, m_mdValue, retLen);
return retLen;
}
// Get information
XSECCryptoHash::HashType OpenSSLCryptoHashHMAC::getHashType(void) const {
return m_hashType; // This could be any kind of hash
}
#endif /* XSEC_HAVE_OPENSSL */