1 /*
2  * Copyright (c) 1999, 2000, 2001, 2002, 2004 X-Way Rights 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 /*!\file beecrypt.c
20  * \brief BeeCrypt API.
21  * \author Bob Deblier <bob.deblier@telenet.be>
22  * \ingroup ES_m PRNG_m HASH_m HMAC_m BC_m
23  */
24 
25 #define BEECRYPT_DLL_EXPORT
26 
27 #if HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 #include "beecrypt/beecrypt.h"
32 
33 #include "beecrypt/entropy.h"
34 
35 #include "beecrypt/fips186.h"
36 #include "beecrypt/mtprng.h"
37 
38 #include "beecrypt/md4.h"
39 #include "beecrypt/md5.h"
40 #include "beecrypt/ripemd128.h"
41 #include "beecrypt/ripemd160.h"
42 #include "beecrypt/ripemd256.h"
43 #include "beecrypt/ripemd320.h"
44 #include "beecrypt/sha1.h"
45 #include "beecrypt/sha224.h"
46 #include "beecrypt/sha256.h"
47 #include "beecrypt/sha384.h"
48 #include "beecrypt/sha512.h"
49 
50 #include "beecrypt/hmacmd5.h"
51 #include "beecrypt/hmacsha1.h"
52 #include "beecrypt/hmacsha224.h"
53 #include "beecrypt/hmacsha256.h"
54 #include "beecrypt/hmacsha384.h"
55 #include "beecrypt/hmacsha512.h"
56 
57 #include "beecrypt/aes.h"
58 #include "beecrypt/blowfish.h"
59 #include "beecrypt/blockmode.h"
60 
61 static entropySource entropySourceList[] =
62 {
63 #if WIN32
64 	{ "wincrypt", entropy_wincrypt },
65 	{ "console", entropy_console },
66 	{ "wavein", entropy_wavein },
67 #else
68 # if HAVE_DEV_URANDOM
69 	{ "urandom", entropy_dev_urandom },
70 # endif
71 # if HAVE_DEV_RANDOM
72 	{ "random", entropy_dev_random },
73 # endif
74 # if HAVE_DEV_TTY
75 	{ "tty", entropy_dev_tty },
76 # endif
77 # if HAVE_DEV_AUDIO
78 	{ "audio", entropy_dev_audio },
79 # endif
80 # if HAVE_DEV_DSP
81 	{ "dsp", entropy_dev_dsp },
82 # endif
83 #endif
84 };
85 
86 #define ENTROPYSOURCES (sizeof(entropySourceList) / sizeof(entropySource))
87 
entropySourceCount()88 int entropySourceCount()
89 {
90 	return ENTROPYSOURCES;
91 }
92 
entropySourceGet(int n)93 const entropySource* entropySourceGet(int n)
94 {
95 	if ((n < 0) || (n >= ENTROPYSOURCES))
96 		return (const entropySource*) 0;
97 
98 	return entropySourceList+n;
99 }
100 
entropySourceFind(const char * name)101 const entropySource* entropySourceFind(const char* name)
102 {
103 	register int index;
104 
105 	for (index = 0; index < ENTROPYSOURCES; index++)
106 	{
107 		if (strcmp(name, entropySourceList[index].name) == 0)
108 			return entropySourceList+index;
109 	}
110 	return (const entropySource*) 0;
111 }
112 
entropySourceDefault()113 const entropySource* entropySourceDefault()
114 {
115 	const char* selection = getenv("BEECRYPT_ENTROPY");
116 
117 	if (selection)
118 	{
119 		return entropySourceFind(selection);
120 	}
121 	else if (ENTROPYSOURCES)
122 	{
123 		return entropySourceList+0;
124 	}
125 	return (const entropySource*) 0;
126 }
127 
entropyGatherNext(byte * data,size_t size)128 int entropyGatherNext(byte* data, size_t size)
129 {
130 	const char* selection = getenv("BEECRYPT_ENTROPY");
131 
132 	if (selection)
133 	{
134 		const entropySource* ptr = entropySourceFind(selection);
135 
136 		if (ptr)
137 			return ptr->next(data, size);
138 	}
139 	else
140 	{
141 		register int index;
142 
143 		for (index = 0; index < ENTROPYSOURCES; index++)
144 		{
145 			if (entropySourceList[index].next(data, size) == 0)
146 				return 0;
147 		}
148 	}
149 	return -1;
150 }
151 
152 static const randomGenerator* randomGeneratorList[] =
153 {
154 	&fips186prng,
155 	&mtprng
156 };
157 
158 #define RANDOMGENERATORS	(sizeof(randomGeneratorList) / sizeof(randomGenerator*))
159 
randomGeneratorCount()160 int randomGeneratorCount()
161 {
162 	return RANDOMGENERATORS;
163 }
164 
randomGeneratorGet(int index)165 const randomGenerator* randomGeneratorGet(int index)
166 {
167 	if ((index < 0) || (index >= RANDOMGENERATORS))
168 		return (const randomGenerator*) 0;
169 
170 	return randomGeneratorList[index];
171 }
172 
randomGeneratorFind(const char * name)173 const randomGenerator* randomGeneratorFind(const char* name)
174 {
175 	register int index;
176 
177 	for (index = 0; index < RANDOMGENERATORS; index++)
178 	{
179 		if (strcmp(name, randomGeneratorList[index]->name) == 0)
180 			return randomGeneratorList[index];
181 	}
182 	return (const randomGenerator*) 0;
183 }
184 
randomGeneratorDefault()185 const randomGenerator* randomGeneratorDefault()
186 {
187 	char* selection = getenv("BEECRYPT_RANDOM");
188 
189 	if (selection)
190 		return randomGeneratorFind(selection);
191 	else
192 		return &fips186prng;
193 }
194 
randomGeneratorContextInit(randomGeneratorContext * ctxt,const randomGenerator * rng)195 int randomGeneratorContextInit(randomGeneratorContext* ctxt, const randomGenerator* rng)
196 {
197 	if (ctxt == (randomGeneratorContext*) 0)
198 		return -1;
199 
200 	if (rng == (randomGenerator*) 0)
201 		return -1;
202 
203 	ctxt->rng = rng;
204 
205 	if (rng->paramsize)
206 	{
207 		ctxt->param = (randomGeneratorParam*) calloc(rng->paramsize, 1);
208 		if (ctxt->param == (randomGeneratorParam*) 0)
209 			return -1;
210 	}
211 	else
212 		ctxt->param = (randomGeneratorParam*) 0;
213 
214 	return ctxt->rng->setup(ctxt->param);
215 }
216 
randomGeneratorContextFree(randomGeneratorContext * ctxt)217 int randomGeneratorContextFree(randomGeneratorContext* ctxt)
218 {
219 	register int rc = 0;
220 
221 	if (ctxt == (randomGeneratorContext*) 0)
222 		return -1;
223 
224 	if (ctxt->rng == (randomGenerator*) 0)
225 		return -1;
226 
227 	if (ctxt->rng->paramsize)
228 	{
229 		if (ctxt->param == (randomGeneratorParam*) 0)
230 			return -1;
231 
232 		rc = ctxt->rng->cleanup(ctxt->param);
233 
234 		free(ctxt->param);
235 
236 		ctxt->param = (randomGeneratorParam*) 0;
237 	}
238 
239 	return rc;
240 }
241 
randomGeneratorContextNext(randomGeneratorContext * ctxt,byte * data,size_t size)242 int randomGeneratorContextNext(randomGeneratorContext* ctxt, byte* data, size_t size)
243 {
244 	return ctxt->rng->next(ctxt->param, data, size);
245 }
246 
randomGeneratorContextSeed(randomGeneratorContext * ctxt,const byte * data,size_t size)247 int randomGeneratorContextSeed(randomGeneratorContext* ctxt, const byte* data, size_t size)
248 {
249 	return ctxt->rng->seed(ctxt->param, data, size);
250 }
251 
252 static const hashFunction* hashFunctionList[] =
253 {
254 	&md4,
255 	&md5,
256 	&ripemd128,
257 	&ripemd160,
258 	&ripemd256,
259 	&ripemd320,
260 	&sha1,
261 	&sha224,
262 	&sha256,
263 	&sha384,
264 	&sha512
265 };
266 
267 #define HASHFUNCTIONS (sizeof(hashFunctionList) / sizeof(hashFunction*))
268 
hashFunctionCount()269 int hashFunctionCount()
270 {
271 	return HASHFUNCTIONS;
272 }
273 
hashFunctionDefault()274 const hashFunction* hashFunctionDefault()
275 {
276 	char* selection = getenv("BEECRYPT_HASH");
277 
278 	if (selection)
279 		return hashFunctionFind(selection);
280 	else
281 		return &sha1;
282 }
283 
hashFunctionGet(int index)284 const hashFunction* hashFunctionGet(int index)
285 {
286 	if ((index < 0) || (index >= HASHFUNCTIONS))
287 		return (const hashFunction*) 0;
288 
289 	return hashFunctionList[index];
290 }
291 
hashFunctionFind(const char * name)292 const hashFunction* hashFunctionFind(const char* name)
293 {
294 	register int index;
295 
296 	for (index = 0; index < HASHFUNCTIONS; index++)
297 	{
298 		if (strcmp(name, hashFunctionList[index]->name) == 0)
299 			return hashFunctionList[index];
300 	}
301 	return (const hashFunction*) 0;
302 }
303 
hashFunctionContextInit(hashFunctionContext * ctxt,const hashFunction * hash)304 int hashFunctionContextInit(hashFunctionContext* ctxt, const hashFunction* hash)
305 {
306 	if (ctxt == (hashFunctionContext*) 0)
307 		return -1;
308 
309 	if (hash == (hashFunction*) 0)
310 		return -1;
311 
312 	ctxt->algo = hash;
313 	ctxt->param = (hashFunctionParam*) calloc(hash->paramsize, 1);
314 
315 	if (ctxt->param == (hashFunctionParam*) 0)
316 		return -1;
317 
318 	return ctxt->algo->reset(ctxt->param);
319 }
320 
hashFunctionContextFree(hashFunctionContext * ctxt)321 int hashFunctionContextFree(hashFunctionContext* ctxt)
322 {
323 	if (ctxt == (hashFunctionContext*) 0)
324 		return -1;
325 
326 	if (ctxt->param == (hashFunctionParam*) 0)
327 		return -1;
328 
329 	free(ctxt->param);
330 
331 	ctxt->param = (hashFunctionParam*) 0;
332 
333 	return 0;
334 }
335 
hashFunctionContextReset(hashFunctionContext * ctxt)336 int hashFunctionContextReset(hashFunctionContext* ctxt)
337 {
338 	if (ctxt == (hashFunctionContext*) 0)
339 		return -1;
340 
341 	if (ctxt->algo == (hashFunction*) 0)
342 		return -1;
343 
344 	if (ctxt->param == (hashFunctionParam*) 0)
345 		return -1;
346 
347 	return ctxt->algo->reset(ctxt->param);
348 }
349 
hashFunctionContextUpdate(hashFunctionContext * ctxt,const byte * data,size_t size)350 int hashFunctionContextUpdate(hashFunctionContext* ctxt, const byte* data, size_t size)
351 {
352 	if (ctxt == (hashFunctionContext*) 0)
353 		return -1;
354 
355 	if (ctxt->algo == (hashFunction*) 0)
356 		return -1;
357 
358 	if (ctxt->param == (hashFunctionParam*) 0)
359 		return -1;
360 
361 	if (data == (const byte*) 0)
362 		return -1;
363 
364 	return ctxt->algo->update(ctxt->param, data, size);
365 }
366 
hashFunctionContextUpdateMC(hashFunctionContext * ctxt,const memchunk * m)367 int hashFunctionContextUpdateMC(hashFunctionContext* ctxt, const memchunk* m)
368 {
369 	if (ctxt == (hashFunctionContext*) 0)
370 		return -1;
371 
372 	if (ctxt->algo == (hashFunction*) 0)
373 		return -1;
374 
375 	if (ctxt->param == (hashFunctionParam*) 0)
376 		return -1;
377 
378 	if (m == (memchunk*) 0)
379 		return -1;
380 
381 	return ctxt->algo->update(ctxt->param, m->data, m->size);
382 }
383 
hashFunctionContextUpdateMP(hashFunctionContext * ctxt,const mpnumber * n)384 int hashFunctionContextUpdateMP(hashFunctionContext* ctxt, const mpnumber* n)
385 {
386 	if (ctxt == (hashFunctionContext*) 0)
387 		return -1;
388 
389 	if (ctxt->algo == (hashFunction*) 0)
390 		return -1;
391 
392 	if (ctxt->param == (hashFunctionParam*) 0)
393 		return -1;
394 
395 	if (n != (mpnumber*) 0)
396 	{
397 		int rc;
398 
399 		/* get the number of significant bits in the number */
400 		size_t sigbits = mpbits(n->size, n->data);
401 
402 		/* calculate how many bytes we need for a java-style encoding;
403 		 * if the most significant bit of the most significant byte
404 		 * is set, then we need to prefix a zero byte.
405 		 */
406 		size_t req = ((sigbits+8) >> 3);
407 
408 		byte* tmp = (byte*) malloc(req);
409 
410 		if (tmp == (byte*) 0)
411 			return -1;
412 
413 		i2osp(tmp, req, n->data, n->size);
414 
415 		rc = ctxt->algo->update(ctxt->param, tmp, req);
416 
417 		free(tmp);
418 
419 		return rc;
420 	}
421 	return -1;
422 }
423 
hashFunctionContextDigest(hashFunctionContext * ctxt,byte * digest)424 int hashFunctionContextDigest(hashFunctionContext* ctxt, byte *digest)
425 {
426 	if (ctxt == (hashFunctionContext*) 0)
427 		return -1;
428 
429 	if (ctxt->algo == (hashFunction*) 0)
430 		return -1;
431 
432 	if (ctxt->param == (hashFunctionParam*) 0)
433 		return -1;
434 
435 	if (digest == (byte*) 0)
436 		return -1;
437 
438 	return ctxt->algo->digest(ctxt->param, digest);
439 }
440 
hashFunctionContextDigestMP(hashFunctionContext * ctxt,mpnumber * d)441 int hashFunctionContextDigestMP(hashFunctionContext* ctxt, mpnumber* d)
442 {
443 	if (ctxt == (hashFunctionContext*) 0)
444 		return -1;
445 
446 	if (ctxt->algo == (hashFunction*) 0)
447 		return -1;
448 
449 	if (ctxt->param == (hashFunctionParam*) 0)
450 		return -1;
451 
452 	if (d != (mpnumber*) 0)
453 	{
454 		int rc;
455 
456 		byte *digest = (byte*) malloc(ctxt->algo->digestsize);
457 
458 		if (digest == (byte*) 0)
459 			return -1;
460 
461 		if (ctxt->algo->digest(ctxt->param, digest))
462 		{
463 			free(digest);
464 			return -1;
465 		}
466 
467 		rc = mpnsetbin(d, digest, ctxt->algo->digestsize);
468 
469 		free(digest);
470 
471 		return rc;
472 	}
473 	return -1;
474 }
475 
hashFunctionContextDigestMatch(hashFunctionContext * ctxt,const mpnumber * d)476 int hashFunctionContextDigestMatch(hashFunctionContext* ctxt, const mpnumber* d)
477 {
478 	int rc = 0;
479 
480 	mpnumber match;
481 
482 	mpnzero(&match);
483 
484 	if (hashFunctionContextDigestMP(ctxt, &match) == 0)
485 		rc = mpeqx(d->size, d->data, match.size, match.data);
486 
487 	mpnfree(&match);
488 
489 	return rc;
490 }
491 
492 static const keyedHashFunction* keyedHashFunctionList[] =
493 {
494 	&hmacmd5,
495 	&hmacsha1,
496 	&hmacsha224,
497 	&hmacsha256,
498 	&hmacsha384,
499 	&hmacsha512
500 };
501 
502 #define KEYEDHASHFUNCTIONS 	(sizeof(keyedHashFunctionList) / sizeof(keyedHashFunction*))
503 
keyedHashFunctionCount()504 int keyedHashFunctionCount()
505 {
506 	return KEYEDHASHFUNCTIONS;
507 }
508 
keyedHashFunctionDefault()509 const keyedHashFunction* keyedHashFunctionDefault()
510 {
511 	char* selection = getenv("BEECRYPT_KEYEDHASH");
512 
513 	if (selection)
514 		return keyedHashFunctionFind(selection);
515 	else
516 		return &hmacsha1;
517 }
518 
keyedHashFunctionGet(int index)519 const keyedHashFunction* keyedHashFunctionGet(int index)
520 {
521 	if ((index < 0) || (index >= KEYEDHASHFUNCTIONS))
522 		return (const keyedHashFunction*) 0;
523 
524 	return keyedHashFunctionList[index];
525 }
526 
keyedHashFunctionFind(const char * name)527 const keyedHashFunction* keyedHashFunctionFind(const char* name)
528 {
529 	register int index;
530 
531 	for (index = 0; index < KEYEDHASHFUNCTIONS; index++)
532 	{
533 		if (strcmp(name, keyedHashFunctionList[index]->name) == 0)
534 			return keyedHashFunctionList[index];
535 	}
536 	return (const keyedHashFunction*) 0;
537 }
538 
keyedHashFunctionContextInit(keyedHashFunctionContext * ctxt,const keyedHashFunction * mac)539 int keyedHashFunctionContextInit(keyedHashFunctionContext* ctxt, const keyedHashFunction* mac)
540 {
541 	if (ctxt == (keyedHashFunctionContext*) 0)
542 		return -1;
543 
544 	if (mac == (keyedHashFunction*) 0)
545 		return -1;
546 
547 	ctxt->algo = mac;
548 	ctxt->param = (keyedHashFunctionParam*) calloc(mac->paramsize, 1);
549 
550 	if (ctxt->param == (keyedHashFunctionParam*) 0)
551 		return -1;
552 
553 	return ctxt->algo->reset(ctxt->param);
554 }
555 
keyedHashFunctionContextFree(keyedHashFunctionContext * ctxt)556 int keyedHashFunctionContextFree(keyedHashFunctionContext* ctxt)
557 {
558 	if (ctxt == (keyedHashFunctionContext*) 0)
559 		return -1;
560 
561 	if (ctxt->algo == (keyedHashFunction*) 0)
562 		return -1;
563 
564 	if (ctxt->param == (keyedHashFunctionParam*) 0)
565 		return -1;
566 
567 	free(ctxt->param);
568 
569 	ctxt->param = (keyedHashFunctionParam*) 0;
570 
571 	return 0;
572 }
573 
keyedHashFunctionContextSetup(keyedHashFunctionContext * ctxt,const byte * key,size_t keybits)574 int keyedHashFunctionContextSetup(keyedHashFunctionContext* ctxt, const byte* key, size_t keybits)
575 {
576 	if (ctxt == (keyedHashFunctionContext*) 0)
577 		return -1;
578 
579 	if (ctxt->algo == (keyedHashFunction*) 0)
580 		return -1;
581 
582 	if (ctxt->param == (keyedHashFunctionParam*) 0)
583 		return -1;
584 
585 	if (key == (byte*) 0)
586 		return -1;
587 
588 	return ctxt->algo->setup(ctxt->param, key, keybits);
589 }
590 
keyedHashFunctionContextReset(keyedHashFunctionContext * ctxt)591 int keyedHashFunctionContextReset(keyedHashFunctionContext* ctxt)
592 {
593 	if (ctxt == (keyedHashFunctionContext*) 0)
594 		return -1;
595 
596 	if (ctxt->algo == (keyedHashFunction*) 0)
597 		return -1;
598 
599 	if (ctxt->param == (keyedHashFunctionParam*) 0)
600 		return -1;
601 
602 	return ctxt->algo->reset(ctxt->param);
603 }
604 
keyedHashFunctionContextUpdate(keyedHashFunctionContext * ctxt,const byte * data,size_t size)605 int keyedHashFunctionContextUpdate(keyedHashFunctionContext* ctxt, const byte* data, size_t size)
606 {
607 	if (ctxt == (keyedHashFunctionContext*) 0)
608 		return -1;
609 
610 	if (ctxt->algo == (keyedHashFunction*) 0)
611 		return -1;
612 
613 	if (ctxt->param == (keyedHashFunctionParam*) 0)
614 		return -1;
615 
616 	if (data == (byte*) 0)
617 		return -1;
618 
619 	return ctxt->algo->update(ctxt->param, data, size);
620 }
621 
keyedHashFunctionContextUpdateMC(keyedHashFunctionContext * ctxt,const memchunk * m)622 int keyedHashFunctionContextUpdateMC(keyedHashFunctionContext* ctxt, const memchunk* m)
623 {
624 	if (ctxt == (keyedHashFunctionContext*) 0)
625 		return -1;
626 
627 	if (ctxt->algo == (keyedHashFunction*) 0)
628 		return -1;
629 
630 	if (ctxt->param == (keyedHashFunctionParam*) 0)
631 		return -1;
632 
633 	if (m == (memchunk*) 0)
634 		return -1;
635 
636 	return ctxt->algo->update(ctxt->param, m->data, m->size);
637 }
638 
keyedHashFunctionContextUpdateMP(keyedHashFunctionContext * ctxt,const mpnumber * n)639 int keyedHashFunctionContextUpdateMP(keyedHashFunctionContext* ctxt, const mpnumber* n)
640 {
641 	if (ctxt == (keyedHashFunctionContext*) 0)
642 		return -1;
643 
644 	if (ctxt->algo == (keyedHashFunction*) 0)
645 		return -1;
646 
647 	if (ctxt->param == (keyedHashFunctionParam*) 0)
648 		return -1;
649 
650 	if (n != (mpnumber*) 0)
651 	{
652 		int rc;
653 
654 		/* get the number of significant bits in the number */
655 		size_t sigbits = mpbits(n->size, n->data);
656 
657 		/* calculate how many bytes we need a java-style encoding; if the
658 		 * most significant bit of the most significant byte is set, then
659 		 * we need to prefix a zero byte.
660 		 */
661 		size_t req = ((sigbits+8) >> 3);
662 
663 		byte* tmp = (byte*) malloc(req);
664 
665 		if (tmp == (byte*) 0)
666 			return -1;
667 
668 		i2osp(tmp, req, n->data, n->size);
669 
670 		rc = ctxt->algo->update(ctxt->param, tmp, req);
671 
672 		free(tmp);
673 
674 		return rc;
675 	}
676 	return -1;
677 }
678 
keyedHashFunctionContextDigest(keyedHashFunctionContext * ctxt,byte * digest)679 int keyedHashFunctionContextDigest(keyedHashFunctionContext* ctxt, byte* digest)
680 {
681 	if (ctxt == (keyedHashFunctionContext*) 0)
682 		return -1;
683 
684 	if (ctxt->algo == (keyedHashFunction*) 0)
685 		return -1;
686 
687 	if (ctxt->param == (keyedHashFunctionParam*) 0)
688 		return -1;
689 
690 	if (digest == (byte*) 0)
691 		return -1;
692 
693 	return ctxt->algo->digest(ctxt->param, digest);
694 }
695 
keyedHashFunctionContextDigestMP(keyedHashFunctionContext * ctxt,mpnumber * d)696 int keyedHashFunctionContextDigestMP(keyedHashFunctionContext* ctxt, mpnumber* d)
697 {
698 	if (ctxt == (keyedHashFunctionContext*) 0)
699 		return -1;
700 
701 	if (ctxt->algo == (keyedHashFunction*) 0)
702 		return -1;
703 
704 	if (ctxt->param == (keyedHashFunctionParam*) 0)
705 		return -1;
706 
707 	if (d != (mpnumber*) 0)
708 	{
709 		int rc;
710 
711 		byte *digest = (byte*) malloc(ctxt->algo->digestsize);
712 
713 		if (digest == (byte*) 0)
714 			return -1;
715 
716 		if (ctxt->algo->digest(ctxt->param, digest))
717 		{
718 			free(digest);
719 			return -1;
720 		}
721 
722 		rc = os2ip(d->data, d->size, digest, ctxt->algo->digestsize);
723 
724 		free(digest);
725 
726 		return rc;
727 	}
728 	return -1;
729 }
730 
keyedHashFunctionContextDigestMatch(keyedHashFunctionContext * ctxt,const mpnumber * d)731 int keyedHashFunctionContextDigestMatch(keyedHashFunctionContext* ctxt, const mpnumber* d)
732 {
733 	int rc = 0;
734 
735 	mpnumber match;
736 
737 	mpnzero(&match);
738 
739 	if (keyedHashFunctionContextDigestMP(ctxt, &match) == 0)
740 		rc = mpeqx(d->size, d->data, match.size, match.data);
741 
742 	mpnfree(&match);
743 
744 	return rc;
745 }
746 
747 static const blockCipher* blockCipherList[] =
748 {
749 	&aes,
750 	&blowfish
751 };
752 
753 #define BLOCKCIPHERS (sizeof(blockCipherList) / sizeof(blockCipher*))
754 
blockCipherCount()755 int blockCipherCount()
756 {
757 	return BLOCKCIPHERS;
758 }
759 
blockCipherDefault()760 const blockCipher* blockCipherDefault()
761 {
762 	char* selection = getenv("BEECRYPT_CIPHER");
763 
764 	if (selection)
765 		return blockCipherFind(selection);
766 	else
767 		return &aes;
768 }
769 
blockCipherGet(int index)770 const blockCipher* blockCipherGet(int index)
771 {
772 	if ((index < 0) || (index >= BLOCKCIPHERS))
773 		return (const blockCipher*) 0;
774 
775 	return blockCipherList[index];
776 }
777 
blockCipherFind(const char * name)778 const blockCipher* blockCipherFind(const char* name)
779 {
780 	register int index;
781 
782 	for (index = 0; index < BLOCKCIPHERS; index++)
783 	{
784 		if (strcmp(name, blockCipherList[index]->name) == 0)
785 			return blockCipherList[index];
786 	}
787 
788 	return (const blockCipher*) 0;
789 }
790 
blockCipherContextInit(blockCipherContext * ctxt,const blockCipher * ciph)791 int blockCipherContextInit(blockCipherContext* ctxt, const blockCipher* ciph)
792 {
793 	if (ctxt == (blockCipherContext*) 0)
794 		return -1;
795 
796 	if (ciph == (blockCipher*) 0)
797 		return -1;
798 
799 	ctxt->algo = ciph;
800 	ctxt->param = (blockCipherParam*) calloc(ciph->paramsize, 1);
801 	ctxt->op = NOCRYPT;
802 
803 	if (ctxt->param == (blockCipherParam*) 0)
804 		return -1;
805 
806 	return 0;
807 }
808 
blockCipherContextSetup(blockCipherContext * ctxt,const byte * key,size_t keybits,cipherOperation op)809 int blockCipherContextSetup(blockCipherContext* ctxt, const byte* key, size_t keybits, cipherOperation op)
810 {
811 	if (ctxt == (blockCipherContext*) 0)
812 		return -1;
813 
814 	if (ctxt->algo == (blockCipher*) 0)
815 		return -1;
816 
817 	if (ctxt->param == (blockCipherParam*) 0)
818 		return -1;
819 
820 	ctxt->op = op;
821 
822 	if (key == (byte*) 0)
823 		return -1;
824 
825 	return ctxt->algo->setup(ctxt->param, key, keybits, op);
826 }
827 
blockCipherContextSetIV(blockCipherContext * ctxt,const byte * iv)828 int blockCipherContextSetIV(blockCipherContext* ctxt, const byte* iv)
829 {
830 	if (ctxt == (blockCipherContext*) 0)
831 		return -1;
832 
833 	if (ctxt->algo == (blockCipher*) 0)
834 		return -1;
835 
836 	if (ctxt->param == (blockCipherParam*) 0)
837 		return -1;
838 
839 	/* null is an allowed value for iv, so don't test it */
840 
841 	return ctxt->algo->setiv(ctxt->param, iv);
842 }
843 
blockCipherContextSetCTR(blockCipherContext * ctxt,const byte * nivz,size_t counter)844 int blockCipherContextSetCTR(blockCipherContext* ctxt, const byte* nivz, size_t counter)
845 {
846 	if (ctxt == (blockCipherContext*) 0)
847 		return -1;
848 
849 	if (ctxt->algo == (blockCipher*) 0)
850 		return -1;
851 
852 	if (ctxt->param == (blockCipherParam*) 0)
853 		return -1;
854 
855 	return ctxt->algo->setctr(ctxt->param, nivz, counter);
856 }
857 
blockCipherContextFree(blockCipherContext * ctxt)858 int blockCipherContextFree(blockCipherContext* ctxt)
859 {
860 	if (ctxt == (blockCipherContext*) 0)
861 		return -1;
862 
863 	if (ctxt->param == (blockCipherParam*) 0)
864 		return -1;
865 
866 	free(ctxt->param);
867 
868 	ctxt->param = (blockCipherParam*) 0;
869 
870 	return 0;
871 }
872 
blockCipherContextValidKeylen(blockCipherContext * ctxt,size_t bits)873 int blockCipherContextValidKeylen(blockCipherContext* ctxt, size_t bits)
874 {
875 	if (ctxt == (blockCipherContext*) 0)
876 		return -1;
877 
878 	if (ctxt->algo == (blockCipher*) 0)
879 		return -1;
880 
881 	if (bits < ctxt->algo->keybitsmin || bits > ctxt->algo->keybitsmax)
882 		return 0;
883 
884 	return ((bits - ctxt->algo->keybitsmin) % ctxt->algo->keybitsinc) == 0;
885 }
886 
blockCipherContextECB(blockCipherContext * ctxt,uint32_t * dst,const uint32_t * src,int nblocks)887 int blockCipherContextECB(blockCipherContext* ctxt, uint32_t* dst, const uint32_t* src, int nblocks)
888 {
889 	switch (ctxt->op)
890 	{
891 	case NOCRYPT:
892 		memcpy(dst, src, nblocks * ctxt->algo->blocksize);
893 		return 0;
894 	case ENCRYPT:
895 		return (ctxt->algo->ecb.encrypt) ?
896 			ctxt->algo->ecb.encrypt(ctxt->param, dst, src, nblocks) :
897 			blockEncryptECB(ctxt->algo, ctxt->param, dst, src, nblocks);
898 	case DECRYPT:
899 		return (ctxt->algo->ecb.decrypt) ?
900 			ctxt->algo->ecb.decrypt(ctxt->param, dst, src, nblocks) :
901 			blockDecryptECB(ctxt->algo, ctxt->param, dst, src, nblocks);
902 	}
903 	return -1;
904 }
905 
blockCipherContextCBC(blockCipherContext * ctxt,uint32_t * dst,const uint32_t * src,int nblocks)906 int blockCipherContextCBC(blockCipherContext* ctxt, uint32_t* dst, const uint32_t* src, int nblocks)
907 {
908 	switch (ctxt->op)
909 	{
910 	case NOCRYPT:
911 		memcpy(dst, src, nblocks * ctxt->algo->blocksize);
912 		return 0;
913 	case ENCRYPT:
914 		return (ctxt->algo->cbc.encrypt) ?
915 			ctxt->algo->cbc.encrypt(ctxt->param, dst, src, nblocks) :
916 			blockEncryptCBC(ctxt->algo, ctxt->param, dst, src, nblocks);
917 	case DECRYPT:
918 		return (ctxt->algo->cbc.decrypt) ?
919 			ctxt->algo->cbc.decrypt(ctxt->param, dst, src, nblocks) :
920 			blockDecryptCBC(ctxt->algo, ctxt->param, dst, src, nblocks);
921 	}
922 	return -1;
923 }
924 
blockCipherContextCTR(blockCipherContext * ctxt,uint32_t * dst,const uint32_t * src,int nblocks)925 int blockCipherContextCTR(blockCipherContext* ctxt, uint32_t* dst, const uint32_t* src, int nblocks)
926 {
927 	switch (ctxt->op)
928 	{
929 	case NOCRYPT:
930 		memcpy(dst, src, nblocks * ctxt->algo->blocksize);
931 		return 0;
932 	case ENCRYPT:
933 	case DECRYPT: /* encrypt and decrypt are the same operation in ctr mode */
934 		return (ctxt->algo->ctr.encrypt) ?
935 			ctxt->algo->ctr.encrypt(ctxt->param, dst, src, nblocks) :
936 			blockEncryptCTR(ctxt->algo, ctxt->param, dst, src, nblocks);
937 	}
938 	return -1;
939 }
940 
941 #if WIN32
942 __declspec(dllexport)
DllMain(HINSTANCE hInst,DWORD fdwReason,LPVOID lpReserved)943 BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpReserved)
944 {
945 	switch (fdwReason)
946 	{
947    	case DLL_PROCESS_ATTACH:
948    		entropy_provider_setup(hInst);
949    		break;
950 	case DLL_PROCESS_DETACH:
951 		entropy_provider_cleanup();
952 		break;
953    	}
954 
955 	return TRUE;
956 }
957 #endif
958