1 /*
2  * Copyright (c) 2004 Beeyond Software Holding BV
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22 
23 #include "beecrypt/pkcs12.h"
24 
25 #include "beecrypt/c++/crypto/interfaces/PBEKey.h"
26 using beecrypt::crypto::interfaces::PBEKey;
27 #include "beecrypt/c++/lang/NullPointerException.h"
28 using beecrypt::lang::NullPointerException;
29 #include "beecrypt/c++/provider/HMAC.h"
30 
31 using namespace beecrypt::provider;
32 
HMAC(const keyedHashFunction & mac,const hashFunction & hash)33 HMAC::HMAC(const keyedHashFunction& mac, const hashFunction& hash) : _digest(mac.digestsize), _ctxt(&mac)
34 {
35 	_kf = &mac;
36 	_hf = &hash;
37 }
38 
engineDoFinal()39 const bytearray& HMAC::engineDoFinal()
40 {
41 	keyedHashFunctionContextDigest(&_ctxt, _digest.data());
42 
43 	return _digest;
44 }
45 
engineDoFinal(byte * data,int offset,int length)46 int HMAC::engineDoFinal(byte* data, int offset, int length) throw (ShortBufferException)
47 {
48 	if (!data)
49 		throw NullPointerException();
50 
51 	if (length < _digest.size())
52 		throw ShortBufferException();
53 
54 	keyedHashFunctionContextDigest(&_ctxt, data);
55 
56 	return _digest.size();
57 }
58 
engineGetMacLength()59 int HMAC::engineGetMacLength()
60 {
61 	return _digest.size();
62 }
63 
engineReset()64 void HMAC::engineReset()
65 {
66 	keyedHashFunctionContextReset(&_ctxt);
67 }
68 
engineUpdate(byte b)69 void HMAC::engineUpdate(byte b)
70 {
71 	keyedHashFunctionContextUpdate(&_ctxt, &b, 1);
72 }
73 
engineUpdate(const byte * data,int offset,int length)74 void HMAC::engineUpdate(const byte* data, int offset, int length)
75 {
76 	keyedHashFunctionContextUpdate(&_ctxt, data+offset, length);
77 }
78 
engineInit(const Key & key,const AlgorithmParameterSpec * spec)79 void HMAC::engineInit(const Key& key, const AlgorithmParameterSpec* spec) throw (InvalidKeyException, InvalidAlgorithmParameterException)
80 {
81 	if (spec)
82 		throw InvalidAlgorithmParameterException("No AlgorithmParameterSpec supported");
83 
84 #if 0 // key derivation should be done by caller; we can't know whether it's PKCS#5 or PKCS#12
85 	const PBEKey* pbe = dynamic_cast<const PBEKey*>(&key);
86 	if (pbe)
87 	{
88 		bytearray _rawk, _salt, _mack(_digest.size());
89 		int _iter;
90 
91 		if (pbe->getEncoded())
92 			_rawk = *(pbe->getEncoded());
93 		else
94 			throw InvalidKeyException("PBEKey must have an encoding");
95 
96 		if (pbe->getSalt())
97 			_salt = *(pbe->getSalt());
98 
99 		_iter = pbe->getIterationCount();
100 
101 		if (pkcs12_derive_key(_hf, PKCS12_ID_MAC, _rawk.data(), _rawk.size(), _salt.data(), _salt.size(), _iter, _mack.data(), _mack.size()))
102 			throw InvalidKeyException("pkcs12_derive_key returned error");
103 
104 		keyedHashFunctionContextSetup(&_ctxt, _mack.data(), _mack.size() << 3);
105 
106 		return;
107 	}
108 #endif
109 
110 	const SecretKey* sec = dynamic_cast<const SecretKey*>(&key);
111 	if (sec)
112 	{
113 		bytearray _rawk;
114 		if (sec->getEncoded())
115 			_rawk = *(sec->getEncoded());
116 		else
117 			throw InvalidKeyException("SecretKey must have an encoding");
118 
119 		keyedHashFunctionContextSetup(&_ctxt, _rawk.data(), _rawk.size() << 3);
120 
121 		return;
122 	}
123 
124 	throw InvalidKeyException("expected a SecretKey or a PBEKey");
125 }
126