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++/adapter.h"
24 #include "beecrypt/c++/lang/NullPointerException.h"
25 using beecrypt::lang::NullPointerException;
26 #include "beecrypt/c++/provider/SHA1withDSASignature.h"
27 #include "beecrypt/c++/security/interfaces/DSAPrivateKey.h"
28 using beecrypt::security::interfaces::DSAPrivateKey;
29 #include "beecrypt/c++/security/interfaces/DSAPublicKey.h"
30 using beecrypt::security::interfaces::DSAPublicKey;
31
32 namespace {
33 const byte TAG_SEQUENCE = 0x30;
34 const byte TAG_INTEGER = 0x02;
35
36 typedef int asn1error;
37
38 const asn1error DER_NOT_ENOUGH_DATA = -1;
39 const asn1error DER_IMPLICIT_TAG_LENGTH = -2;
40 const asn1error DER_TAG_TOO_LONG = -3;
41 const asn1error DER_FORMAT_ERROR = -4;
42 const asn1error DER_CONVERSION_ERROR = -5;
43
44 /* compute the size of a DER length encoding */
asn1_der_length(int length)45 int asn1_der_length(int length) throw ()
46 {
47 if (length < 0x80)
48 return 1;
49 if (length < 0x100)
50 return 2;
51 if (length < 0x10000)
52 return 3;
53 if (length < 0x1000000)
54 return 4;
55 else
56 return 5;
57 }
58
asn1_der_length_of(const mpnumber & n)59 int asn1_der_length_of(const mpnumber& n) throw ()
60 {
61 int sigbits = mpbits(n.size, n.data);
62
63 return ((sigbits + 7) >> 3) + (((sigbits & 7) == 0) ? 1 : 0);
64 }
65
asn1_der_length_of_rssig(const mpnumber & r,const mpnumber & s)66 int asn1_der_length_of_rssig(const mpnumber& r, const mpnumber& s) throw ()
67 {
68 int intlen, seqlen = 0;
69
70 intlen = asn1_der_length_of(r);
71
72 seqlen += 1 + asn1_der_length(intlen) + intlen;
73
74 intlen = asn1_der_length_of(s);
75
76 seqlen += 1 + asn1_der_length(intlen) + intlen;
77
78 return 1 + asn1_der_length(seqlen) + seqlen;
79 }
80
asn1_der_encode_length(byte * data,int length)81 int asn1_der_encode_length(byte* data, int length) throw ()
82 {
83 if (length < 0x80)
84 {
85 data[0] = (byte) length;
86 return 1;
87 }
88 else if (length < 0x100)
89 {
90 data[0] = (byte) 0x81;
91 data[1] = (byte) length;
92 return 2;
93 }
94 else if (length < 0x10000)
95 {
96 data[0] = (byte) 0x82;
97 data[1] = (byte) (length >> 8);
98 data[2] = (byte) (length );
99 return 3;
100 }
101 else if (length < 0x1000000)
102 {
103 data[0] = (byte) 0x83;
104 data[1] = (byte) (length >> 16);
105 data[2] = (byte) (length >> 8);
106 data[3] = (byte) (length );
107 return 4;
108 }
109 else
110 {
111 data[0] = (byte) 0x84;
112 data[1] = (byte) (length >> 24);
113 data[2] = (byte) (length >> 16);
114 data[3] = (byte) (length >> 8);
115 data[4] = (byte) (length );
116 return 5;
117 }
118 }
119
asn1_der_decode_length(const byte * data,int size,int * length)120 int asn1_der_decode_length(const byte* data, int size, int* length) throw (asn1error)
121 {
122 int length_bytes;
123 byte tmp;
124
125 if (size == 0)
126 throw DER_NOT_ENOUGH_DATA;
127
128 tmp = *(data++);
129
130 if (tmp < 0x80)
131 {
132 *length = tmp;
133 length_bytes = 0;
134 }
135 else
136 {
137 byte length_bytes = tmp & 0x7f;
138
139 if (length_bytes == 0)
140 throw DER_IMPLICIT_TAG_LENGTH;
141
142 if (length_bytes >= size)
143 throw DER_NOT_ENOUGH_DATA;
144
145 if (length_bytes > sizeof(int))
146 throw DER_TAG_TOO_LONG;
147
148 int temp = 0;
149
150 for (byte i = 0; i < length_bytes; i++)
151 {
152 tmp = *(data++);
153 temp <<= 8;
154 temp += tmp;
155 }
156
157 *length = temp;
158 }
159 return 1 + length_bytes;
160 }
161
asn1_der_encode(byte * data,const mpnumber & n)162 int asn1_der_encode(byte* data, const mpnumber& n) throw ()
163 {
164 int offset = 1, length = asn1_der_length_of(n);
165
166 data[0] = TAG_INTEGER;
167
168 offset += asn1_der_encode_length(data+offset, length);
169
170 i2osp(data+offset, length, n.data, n.size);
171
172 offset += length;
173
174 return offset;
175 }
176
asn1_der_decode(const byte * data,int size,mpnumber & n)177 int asn1_der_decode(const byte* data, int size, mpnumber& n) throw (asn1error)
178 {
179 int length, offset = 1;
180
181 if (size < 2)
182 throw DER_NOT_ENOUGH_DATA;
183
184 if (data[0] != TAG_INTEGER)
185 throw DER_FORMAT_ERROR;
186
187 offset += asn1_der_decode_length(data+offset, size-offset, &length);
188
189 if (length > (size-offset))
190 throw DER_NOT_ENOUGH_DATA;
191
192 if (mpnsetbin(&n, data+offset, length))
193 throw DER_CONVERSION_ERROR;
194
195 offset += length;
196
197 return offset;
198 }
199
asn1_der_encode_rssig(byte * data,const mpnumber & r,const mpnumber & s)200 int asn1_der_encode_rssig(byte* data, const mpnumber& r, const mpnumber& s) throw ()
201 {
202 int intlen, seqlen = 0;
203
204 intlen = asn1_der_length_of(r);
205 seqlen += 1 + asn1_der_length(intlen) + intlen;
206 intlen = asn1_der_length_of(s);
207 seqlen += 1 + asn1_der_length(intlen) + intlen;
208
209 *(data++) = TAG_SEQUENCE;
210
211 data += asn1_der_encode_length(data, seqlen);
212 data += asn1_der_encode(data, r);
213 data += asn1_der_encode(data, s);
214
215 return 1 + asn1_der_length(seqlen) + seqlen;
216 }
217
asn1_der_decode_rssig(const byte * data,int size,mpnumber & r,mpnumber & s)218 int asn1_der_decode_rssig(const byte* data, int size, mpnumber& r, mpnumber& s) throw (asn1error)
219 {
220 int tmp, length, offset = 1;
221
222 if (size < 2)
223 throw DER_NOT_ENOUGH_DATA;
224
225 if (data[0] != TAG_SEQUENCE)
226 throw DER_FORMAT_ERROR;
227
228 offset += asn1_der_decode_length(data+offset, size-offset, &length);
229
230 if (length > (size-offset))
231 throw DER_NOT_ENOUGH_DATA;
232
233 tmp = asn1_der_decode(data+offset, length, r);
234
235 offset += tmp;
236 length -= tmp;
237
238 tmp = asn1_der_decode(data+offset, length, s);
239
240 offset += tmp;
241 length -= tmp;
242
243 if (length > 0)
244 throw DER_FORMAT_ERROR;
245
246 return offset;
247 }
248 }
249
250 using namespace beecrypt::provider;
251
SHA1withDSASignature()252 SHA1withDSASignature::SHA1withDSASignature()
253 {
254 }
255
engineGetParameters() const256 AlgorithmParameters* SHA1withDSASignature::engineGetParameters() const
257 {
258 return 0;
259 }
260
engineSetParameter(const AlgorithmParameterSpec & spec)261 void SHA1withDSASignature::engineSetParameter(const AlgorithmParameterSpec& spec) throw (InvalidAlgorithmParameterException)
262 {
263 throw InvalidAlgorithmParameterException("not supported for this algorithm");
264 }
265
engineInitSign(const PrivateKey & key,SecureRandom * random)266 void SHA1withDSASignature::engineInitSign(const PrivateKey& key, SecureRandom* random) throw (InvalidKeyException)
267 {
268 const DSAPrivateKey* dsa = dynamic_cast<const DSAPrivateKey*>(&key);
269 if (dsa)
270 {
271 /* copy key information */
272 transform(_params.p, dsa->getParams().getP());
273 transform(_params.q, dsa->getParams().getQ());
274 transform(_params.g, dsa->getParams().getG());
275 transform(_x, dsa->getX());
276
277 /* reset the hash function */
278 sha1Reset(&_sp);
279
280 _srng = random;
281 }
282 else
283 throw InvalidKeyException("key must be a DSAPrivateKey");
284 }
285
engineInitVerify(const PublicKey & key)286 void SHA1withDSASignature::engineInitVerify(const PublicKey& key) throw (InvalidKeyException)
287 {
288 const DSAPublicKey* dsa = dynamic_cast<const DSAPublicKey*>(&key);
289 if (dsa)
290 {
291 /* copy key information */
292 transform(_params.p, dsa->getParams().getP());
293 transform(_params.q, dsa->getParams().getQ());
294 transform(_params.g, dsa->getParams().getG());
295 transform(_y, dsa->getY());
296
297 /* reset the hash function */
298 sha1Reset(&_sp);
299
300 _srng = 0;
301 }
302 else
303 throw InvalidKeyException("key must be a DSAPrivateKey");
304 }
305
engineUpdate(byte b)306 void SHA1withDSASignature::engineUpdate(byte b)
307 {
308 sha1Update(&_sp, &b, 1);
309 }
310
engineUpdate(const byte * data,int offset,int len)311 void SHA1withDSASignature::engineUpdate(const byte* data, int offset, int len)
312 {
313 sha1Update(&_sp, data+offset, len);
314 }
315
rawsign(mpnumber & r,mpnumber & s)316 void SHA1withDSASignature::rawsign(mpnumber& r, mpnumber& s) throw (SignatureException)
317 {
318 mpnumber hm;
319 byte digest[20];
320
321 sha1Digest(&_sp, digest);
322 mpnsetbin(&hm, digest, 20);
323
324 if (_srng)
325 {
326 randomGeneratorContextAdapter rngc(_srng);
327 if (dsasign(&_params.p, &_params.q, &_params.g, &rngc, &hm, &_x, &r, &s))
328 throw SignatureException("internal error in dsasign function");
329 }
330 else
331 {
332 randomGeneratorContext rngc(randomGeneratorDefault());
333 if (dsasign(&_params.p, &_params.q, &_params.g, &rngc, &hm, &_x, &r, &s))
334 throw SignatureException("internal error in dsasign function");
335 }
336 }
337
rawvrfy(const mpnumber & r,const mpnumber & s)338 bool SHA1withDSASignature::rawvrfy(const mpnumber& r, const mpnumber& s) throw ()
339 {
340 mpnumber hm;
341 byte digest[20];
342
343 sha1Digest(&_sp, digest);
344 mpnsetbin(&hm, digest, 20);
345
346 return dsavrfy(&_params.p, &_params.q, &_params.g, &hm, &_y, &r, &s);
347 }
348
engineSign()349 bytearray* SHA1withDSASignature::engineSign() throw (SignatureException)
350 {
351 mpnumber r, s;
352
353 rawsign(r, s);
354
355 bytearray* signature = new bytearray(asn1_der_length_of_rssig(r, s));
356
357 asn1_der_encode_rssig(signature->data(), r, s);
358
359 return signature;
360 }
361
engineSign(byte * signature,int offset,int len)362 int SHA1withDSASignature::engineSign(byte* signature, int offset, int len) throw (ShortBufferException, SignatureException)
363 {
364 if (!signature)
365 throw NullPointerException();
366
367 mpnumber r, s;
368
369 rawsign(r, s);
370
371 if (asn1_der_length_of_rssig(r, s) > (len - offset))
372 throw ShortBufferException();
373
374 return asn1_der_encode_rssig(signature+offset, r, s);
375 }
376
engineSign(bytearray & signature)377 int SHA1withDSASignature::engineSign(bytearray& signature) throw (SignatureException)
378 {
379 mpnumber r, s;
380
381 rawsign(r, s);
382
383 signature.resize(asn1_der_length_of_rssig(r, s));
384
385 return asn1_der_encode_rssig(signature.data(), r, s);
386 }
387
engineVerify(const byte * signature,int offset,int len)388 bool SHA1withDSASignature::engineVerify(const byte* signature, int offset, int len) throw (SignatureException)
389 {
390 if (!signature)
391 throw NullPointerException();
392
393 mpnumber r, s;
394
395 try
396 {
397 asn1_der_decode_rssig(signature+offset, len-offset, r, s);
398 }
399 catch (asn1error&)
400 {
401 throw SignatureException("invalid signature");
402 }
403
404 return rawvrfy(r, s);
405 }
406