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/c++/provider/DHKeyAgreement.h"
24 #include "beecrypt/c++/provider/DHPublicKeyImpl.h"
25 
26 #include "beecrypt/c++/crypto/interfaces/DHPrivateKey.h"
27 using beecrypt::crypto::interfaces::DHPrivateKey;
28 #include "beecrypt/c++/crypto/interfaces/DHPublicKey.h"
29 using beecrypt::crypto::interfaces::DHPublicKey;
30 #include "beecrypt/c++/crypto/SecretKeyFactory.h"
31 using beecrypt::crypto::SecretKeyFactory;
32 #include "beecrypt/c++/crypto/spec/SecretKeySpec.h"
33 using beecrypt::crypto::spec::SecretKeySpec;
34 #include "beecrypt/c++/security/ProviderException.h"
35 using beecrypt::security::ProviderException;
36 
37 #include <memory>
38 using std::auto_ptr;
39 
40 using namespace beecrypt::provider;
41 
DHKeyAgreement()42 DHKeyAgreement::DHKeyAgreement()
43 {
44 	_state = UNINITIALIZED;
45 	_secret = 0;
46 }
47 
~DHKeyAgreement()48 DHKeyAgreement::~DHKeyAgreement()
49 {
50 	delete _secret;
51 }
52 
engineDoPhase(const Key & key,bool lastPhase)53 Key* DHKeyAgreement::engineDoPhase(const Key& key, bool lastPhase) throw (InvalidKeyException, IllegalStateException)
54 {
55 	if (_state == INITIALIZED)
56 	{
57 		const DHPublicKey* pub = dynamic_cast<const DHPublicKey*>(&key);
58 		if (pub)
59 		{
60 			transform(_y, pub->getY());
61 
62 			if (mpz(_y.size, _y.data) || mpgex(_y.size, _y.data, _param.p.size, _param.p.modl))
63 				throw InvalidKeyException("y must be in range [1 .. (p-1)]");
64 
65 			mpnumber _s;
66 
67 			if (dlsvdp_pDHSecret(&_param, &_x, &_y, &_s))
68 			   throw ProviderException("BeeCrypt internal error in dlsvdp_pDHSecret");
69 
70 			if (lastPhase)
71 			{
72 				size_t req = (_s.bitlength() + 8) >> 3;
73 
74 				_secret = new bytearray(req);
75 
76 				i2osp(_secret->data(), _secret->size(), _s.data, _s.size);
77 
78 				_state = SHARED;
79 
80 				return 0;
81 			}
82 			else
83 			{
84 				// multi-party DH
85 				return new DHPublicKeyImpl(_param, _s);
86 			}
87 		}
88 		else
89 			throw InvalidKeyException("not a DHPublicKey");
90 	}
91 	else
92 		throw IllegalStateException("DHKeyAgreement wasn't initialized");
93 }
94 
95 
engineInit(const Key & key,SecureRandom * random)96 void DHKeyAgreement::engineInit(const Key& key, SecureRandom* random) throw (InvalidKeyException)
97 {
98 	const DHPrivateKey* pri = dynamic_cast<const DHPrivateKey*>(&key);
99 	if (pri)
100 	{
101 		transform(_param.p, pri->getParams().getP());
102 		transform(_param.g, pri->getParams().getG());
103 
104 		transform(_x, pri->getX());
105 
106 		_state = INITIALIZED;
107 	}
108 	else
109 		throw InvalidKeyException("not a DHPrivateKey");
110 }
111 
engineGenerateSecret()112 bytearray* DHKeyAgreement::engineGenerateSecret() throw (IllegalStateException)
113 {
114 	if (_state == SHARED)
115 	{
116 		bytearray* tmp = _secret;
117 		_secret = 0;
118 
119 		_state = INITIALIZED;
120 
121 		return tmp;
122 	}
123 	else
124 		throw IllegalStateException();
125 }
126 
engineGenerateSecret(bytearray & b,int offset)127 int DHKeyAgreement::engineGenerateSecret(bytearray& b, int offset) throw (IllegalStateException, ShortBufferException)
128 {
129 	if (_state == SHARED)
130 	{
131 		int size = _secret->size();
132 
133 		if ((b.size() - offset) > size)
134 			throw ShortBufferException();
135 
136 		memcpy(b.data() + offset, _secret->data(), size);
137 
138 		delete _secret;
139 		_secret = 0;
140 
141 		_state = INITIALIZED;
142 
143 		return size;
144 	}
145 	else
146 		throw IllegalStateException();
147 }
148 
engineGenerateSecret(const String & algorithm)149 SecretKey* DHKeyAgreement::engineGenerateSecret(const String& algorithm) throw (IllegalStateException, NoSuchAlgorithmException, InvalidKeyException)
150 {
151 	if (_state == SHARED)
152 	{
153 		_state = INITIALIZED;
154 
155 		SecretKeyFactory* skf = SecretKeyFactory::getInstance(algorithm);
156 
157 		SecretKeySpec spec(*_secret, algorithm);
158 
159 		delete _secret;
160 		_secret = 0;
161 
162 		try
163 		{
164 			auto_ptr<SecretKey> tmp(skf->generateSecret(spec));
165 
166 			return tmp.release();
167 		}
168 		catch (InvalidKeySpecException& e)
169 		{
170 			throw InvalidKeyException().initCause(e);
171 		}
172 	}
173 	else
174 		throw IllegalStateException();
175 }
176 
engineInit(const Key & key,const AlgorithmParameterSpec & spec,SecureRandom * random)177 void DHKeyAgreement::engineInit(const Key& key, const AlgorithmParameterSpec& spec, SecureRandom* random) throw (InvalidKeyException, InvalidAlgorithmParameterException)
178 {
179 	engineInit(key, random);
180 }
181