blob: 02af3b1d959cff622d0dc5c7173019081e4cd458 [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
*
* NSSCryptoHashHMAC := NSS Implementation of HMAC
*
* Author(s): Milan Tomic
*
*/
#include <xsec/enc/NSS/NSSCryptoHashHMAC.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/enc/NSS/NSSCryptoKeyHMAC.hpp>
#if defined (XSEC_HAVE_NSS)
#include "../../utils/XSECDOMUtils.hpp"
#include <memory.h>
// --------------------------------------------------------------------------------
// Constructor
// --------------------------------------------------------------------------------
NSSCryptoHashHMAC::NSSCryptoHashHMAC(HashType alg) {
switch (alg) {
case (XSECCryptoHash::HASH_SHA1) :
mp_md = PK11_CreateDigestContext(SEC_OID_SHA1);
break;
case (XSECCryptoHash::HASH_SHA256) :
mp_md = PK11_CreateDigestContext(SEC_OID_SHA256);
break;
case (XSECCryptoHash::HASH_SHA384) :
mp_md = PK11_CreateDigestContext(SEC_OID_SHA384);
break;
case (XSECCryptoHash::HASH_SHA512) :
mp_md = PK11_CreateDigestContext(SEC_OID_SHA512);
break;
case (XSECCryptoHash::HASH_MD5) :
mp_md = PK11_CreateDigestContext(SEC_OID_MD5);
break;
default :
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:Hash - Unknown algorithm");
}
m_hashType = alg;
m_blockSize = XSEC_MAX_HASH_BLOCK_SIZE;
SECStatus s = PK11_DigestBegin(mp_md);
if (s != SECSuccess) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:Hash - Error initializing Message Digest");
}
}
// --------------------------------------------------------------------------------
// Destructor
// --------------------------------------------------------------------------------
NSSCryptoHashHMAC::~NSSCryptoHashHMAC() {
if (mp_md != 0)
PK11_DestroyContext(mp_md, PR_TRUE);
}
// --------------------------------------------------------------------------------
// Reset
// --------------------------------------------------------------------------------
void NSSCryptoHashHMAC::reset() {
SECStatus s = PK11_DigestBegin(mp_md);
if (s != SECSuccess) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:Hash - Error initializing Message Digest");
}
}
// --------------------------------------------------------------------------------
// Key manipulation
// --------------------------------------------------------------------------------
void NSSCryptoHashHMAC::setKey(const XSECCryptoKey *key) {
if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:HashHMAC - Non HMAC Key passed to HashHMAC");
}
m_keyLen = ((XSECCryptoKeyHMAC *) key)->getKey(m_keyBuf);
PK11SlotInfo * slot = PK11_GetInternalKeySlot();
if (slot == 0) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:HashHMAC - Failed to get internal key slot");
}
SECItem keyItem;
keyItem.data = (unsigned char *) m_keyBuf.rawBuffer();
keyItem.len = m_keyLen;
CK_MECHANISM_TYPE hmacType;
switch (m_hashType) {
case (XSECCryptoHash::HASH_SHA1) :
hmacType = CKM_SHA_1_HMAC;
break;
case (XSECCryptoHash::HASH_SHA224) :
hmacType = CKM_SHA224_HMAC;
break;
case (XSECCryptoHash::HASH_SHA256) :
hmacType = CKM_SHA256_HMAC;
break;
case (XSECCryptoHash::HASH_SHA384) :
hmacType = CKM_SHA384_HMAC;
break;
case (XSECCryptoHash::HASH_SHA512) :
hmacType = CKM_SHA512_HMAC;
break;
case (XSECCryptoHash::HASH_MD5) :
hmacType = CKM_MD5_HMAC;
break;
default :
hmacType = 0;
}
if(hmacType == 0) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:Hash - Unknown algorithm");
}
PK11SymKey * symKey = PK11_ImportSymKey(slot,
hmacType,
PK11_OriginUnwrap,
CKA_SIGN,
&keyItem,
NULL);
SECItem noParams;
noParams.data = 0;
noParams.len = 0;
mp_md = PK11_CreateContextBySymKey(hmacType,
CKA_SIGN,
symKey,
&noParams);
if(mp_md == 0) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:Hash - Unknown algorithm");
}
if (symKey)
PK11_FreeSymKey(symKey);
if (slot)
PK11_FreeSlot(slot);
}
// --------------------------------------------------------------------------------
// Perform hash operation
// --------------------------------------------------------------------------------
void NSSCryptoHashHMAC::hash(unsigned char * data,
unsigned int length) {
if (mp_md == 0) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:HashHMAC - hash called prior to setKey");
}
SECStatus s = PK11_DigestOp(mp_md, data, length);
if (s != SECSuccess) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:Hash - Error Hashing Data");
}
}
// --------------------------------------------------------------------------------
// Finish
// --------------------------------------------------------------------------------
unsigned int NSSCryptoHashHMAC::finish(unsigned char * hash,
unsigned int maxLength) {
unsigned int retLen = XSEC_MAX_HASH_SIZE;
SECStatus s = PK11_DigestFinal(mp_md, m_mdValue, &retLen, XSEC_MAX_HASH_SIZE);
if (s != SECSuccess) {
throw XSECCryptoException(XSECCryptoException::MDError,
"NSS:Hash - Error getting hash value");
}
m_mdLen = retLen;
retLen = (maxLength > m_mdLen ? m_mdLen : maxLength);
memcpy(hash, m_mdValue, retLen);
return (unsigned int) retLen;
}
// --------------------------------------------------------------------------------
// Get information
// --------------------------------------------------------------------------------
XSECCryptoHash::HashType NSSCryptoHashHMAC::getHashType(void) const {
return m_hashType; // This could be any kind of hash
}
#endif /* XSEC_HAVE_NSS */