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