/**
 * 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 */
