1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 */
25
26 #include <krypto/extern.h>
27 #include <klib/defs.h>
28
29 /* CIPHER_IMPL and BLOCKCIPHER_IMPL are defined in this header */
30 #include "ncbi-priv.h"
31 /* CIPHER_IMPL is used in this header */
32 #include "cipher-impl.h"
33 /* BLOCKCIPHER_IMPL is used in this header */
34 #include "blockcipher-impl.h"
35
36 #include "aes-ncbi-priv.h"
37 #include "null-ncbi-priv.h"
38 #include "cipher-priv.h"
39 #include "blockcipher-priv.h"
40
41 #include <krypto/cipher.h>
42 #include <krypto/ciphermgr.h>
43
44 #include <klib/defs.h>
45 #include <klib/refcount.h>
46 #include <klib/out.h>
47 #include <klib/rc.h>
48
49 #include <sysalloc.h>
50
51 #include <stdlib.h>
52 #include <string.h>
53 #include <assert.h>
54
55
56 const char CMEMBER(ClassName)[] = CLASS_STRING(CIPHER_IMPL);
57
58
59
60 struct CIPHER_IMPL
61 {
62 KCipher dad;
63 const KBlockCipherVec * block_cipher;
64 };
65
66 typedef union CipherVec_u
67 {
68 CipherVec vec;
69 CipherBlock block;
70 } CipherVec_u;
71
72 /*
73 * Read a blocks worth of bytes into an AESState
74 */
CipherVecIn(const void * cvin)75 static __inline__ CipherVec CipherVecIn (const void * cvin)
76 {
77 #if USE_VEC_REG
78 register CipherVec cv;
79
80 __asm__ (
81 "movdqu (%[a]),%[s]" : [s] "=x" (cv) : [a] "D" (cvin)
82 );
83
84 return cv;
85 #else
86 CipherVec_u u;
87
88 memmove (&u.block, cvin, sizeof (u));
89 return u.vec;
90 #endif
91 }
92
93
94
95 /*
96 * Write a block's worth of bytes out from an AESState
97 */
CipherVecOut(const CipherVec cv,void * cvout)98 static __inline__ void CipherVecOut (const CipherVec cv, void * cvout)
99 {
100 #if USE_VEC_REG
101 register CipherVec rcv = cv;
102
103 __asm__ (
104 "movdqu %[s],(%[a])" : : [s] "x" (rcv), [a] "D" (cvout)
105 );
106 #else
107 CipherVec lcv = cv;
108 memmove (cvout, &lcv, sizeof (lcv));
109 #endif
110 }
111
112
CMEMBER(Destroy)113 static rc_t CMEMBER(Destroy) (CIPHER_IMPL * self)
114 {
115 rc_t rc = 0;
116
117 if (self)
118 {
119 rc = KCipherDestroy (&self->dad);
120 free (self);
121 }
122 return rc;
123 }
124
125
CMEMBER(SetEncryptKey)126 static rc_t CMEMBER(SetEncryptKey)(CIPHER_IMPL * self,
127 const char * user_key,
128 uint32_t user_key_bits)
129 {
130 rc_t rc = 0;
131
132 assert (self);
133 assert (user_key);
134 assert (user_key_bits);
135
136 switch (self->block_cipher->version.maj)
137 {
138 default:
139 rc = RC (rcKrypto, rcCipher, rcUpdating, rcBlockCipher, rcBadVersion);
140 break;
141
142 case 1:
143 self->block_cipher->v1.set_encrypt_key (self->dad.encrypt_key, user_key,
144 user_key_bits);
145 break;
146 }
147 return rc;
148 }
149
150
CMEMBER(SetDecryptKey)151 static rc_t CMEMBER(SetDecryptKey)(CIPHER_IMPL * self,
152 const char * user_key,
153 uint32_t user_key_bits)
154 {
155 rc_t rc = 0;
156
157 assert (self);
158 assert (user_key);
159 assert (user_key_bits);
160
161 switch (self->block_cipher->version.maj)
162 {
163 default:
164 rc = RC (rcKrypto, rcCipher, rcUpdating, rcBlockCipher, rcBadVersion);
165 break;
166
167 case 1:
168 self->block_cipher->v1.set_decrypt_key (self->dad.decrypt_key, user_key,
169 user_key_bits);
170 break;
171 }
172 return rc;
173 }
174
175
176 static
CMEMBER(SetEncryptIvec)177 rc_t CMEMBER(SetEncryptIvec) (CIPHER_IMPL * self,
178 const void * ivec)
179 {
180 assert (self);
181 assert (ivec);
182
183 memmove (self->dad.encrypt_ivec, ivec, self->dad.block_size);
184
185 return 0;
186 }
187
188
189 static
CMEMBER(SetDecryptIvec)190 rc_t CMEMBER(SetDecryptIvec) (CIPHER_IMPL * self,
191 const void * ivec)
192 {
193 assert (self);
194 assert (ivec);
195
196 memmove (self->dad.decrypt_ivec, ivec, self->dad.block_size);
197
198 return 0;
199 }
200
201
202 static
CMEMBER(SetEncryptCounterFunc)203 rc_t CMEMBER(SetEncryptCounterFunc) (CIPHER_IMPL * self,
204 cipher_ctr_func func)
205 {
206 assert (self);
207 assert (func);
208
209 self->dad.encrypt_counter_func = func;
210
211 return 0;
212 }
213
214
215 static
CMEMBER(SetDecryptCounterFunc)216 rc_t CMEMBER(SetDecryptCounterFunc) (CIPHER_IMPL * self,
217 cipher_ctr_func func)
218 {
219 assert (self);
220 assert (func);
221
222 self->dad.decrypt_counter_func = func;
223
224 return 0;
225 }
226
227
CMEMBER(EncryptV1)228 static __inline__ CipherVec CMEMBER(EncryptV1)(const CIPHER_IMPL * self,
229 register CipherVec cv)
230 {
231 return self->block_cipher->v1.encrypt (cv, self->dad.encrypt_key);
232 }
233
234
CMEMBER(DecryptV1)235 static __inline__ CipherVec CMEMBER(DecryptV1)(const CIPHER_IMPL * self,
236 register CipherVec cv)
237 {
238 return self->block_cipher->v1.decrypt (cv, self->dad.decrypt_key);
239 }
240
241
CMEMBER(EncryptV1Int)242 static __inline__ rc_t CMEMBER(EncryptV1Int)(const CIPHER_IMPL * self,
243 const void * in, void * out)
244 {
245 CipherVec cv;
246
247 cv = CipherVecIn(in);
248 cv = CMEMBER(EncryptV1)(self, cv);
249 CipherVecOut(cv, out);
250 return 0;
251 }
252
253
CMEMBER(DecryptV1Int)254 static __inline__ rc_t CMEMBER(DecryptV1Int)(const CIPHER_IMPL * self,
255 const void * in, void * out)
256 {
257 CipherVec cv;
258
259 cv = CipherVecIn(in);
260 cv = CMEMBER(DecryptV1)(self, cv);
261 CipherVecOut(cv, out);
262 return 0;
263 }
264
265
CMEMBER(Encrypt)266 static rc_t CMEMBER(Encrypt) (const CIPHER_IMPL * self, const void * in, void * out)
267 {
268 rc_t rc;
269
270 switch (self->block_cipher->version.maj)
271 {
272 default:
273 rc = RC (rcKrypto, rcCipher, rcEncoding, rcBlockCipher, rcBadVersion);
274 break;
275
276 case 1:
277 rc = CMEMBER(EncryptV1Int)(self, in, out);
278 break;
279 }
280
281 return rc;
282 }
283
284
285 static
CMEMBER(Decrypt)286 rc_t CMEMBER(Decrypt) (const CIPHER_IMPL * self, const void * in, void * out)
287 {
288 rc_t rc = 0;
289
290 switch (self->block_cipher->version.maj)
291 {
292 default:
293 rc = RC (rcKrypto, rcCipher, rcEncoding, rcBlockCipher, rcBadVersion);
294 break;
295
296 case 1:
297 rc = CMEMBER(DecryptV1Int)(self, in, out);
298 break;
299 }
300
301 return rc;
302 }
303
304
305 /* ====================
306 * longer runs of multiple blocks.
307 *
308 * The algorithms are well defined and standard in most cases
309 *
310 * These aremore or elss equivalent to class functions as they do not depend upon
311 * the operation of the cipher and the algorithms are independent of anything about
312 * the cipher other than its block size.
313 *
314 * PT: plain text block
315 * CT: cipher text block
316 * EK: encryption key
317 * DK: decryption key (might be sthe same as EK)
318 * ENC: encrypt cipher function on a block using a key
319 * DEC: decrypt cipher function on a block using a key
320 * IV: initialization vector - used as feedback for chaining
321 * N: number used once (nonce)
322 * FB: feedback is the next IV in a chained/feedback mode
323 */
324
325
326 /* -----
327 * NOTE:
328 * 'in' can be the same as 'out' but other overlaps are dangers as a block at a
329 * time is written. The code does not look for overlaps at this point.
330 */
331
332 /* ----------
333 * Electronic Code Book - simple cipher with no chaining feedback just iterate
334 * simple encrypt/decrypt with the plain, text, cipher text and key/
335 *
336 * CT = ENC (PT,EK)
337 * PT = DEC (CT,DK)
338 */
339
340 /* -----
341 * NOTE: currently an implmentation detail limits us to 8192 bit cipher block
342 * size. Changing MAX_BLOCK_SIZE in cipher.c can up that limit without
343 * causing any other compatibility issues.
344 *
345 * Two local byte arrays are defined on the stack of 1024 bytes or 8192 bits.
346 */
347 static
CMEMBER(EncryptEcb)348 rc_t CMEMBER(EncryptEcb) (const CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
349 {
350 const uint8_t * pin;
351 uint8_t * pout;
352
353 for ((pin = in), (pout = out);
354 block_count --;
355 (pin += self->dad.block_size), (pout += self->dad.block_size))
356 {
357 CMEMBER(EncryptV1Int)(self, pin, pout);
358 }
359 return 0;
360 }
361
362
363 static
CMEMBER(DecryptEcb)364 rc_t CMEMBER(DecryptEcb) (const CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
365 {
366 const uint8_t * pin;
367 uint8_t * pout;
368
369 for ((pin = in), (pout = out);
370 block_count --;
371 (pin += self->dad.block_size), (pout += self->dad.block_size))
372 {
373 CMEMBER(DecryptV1Int)(self, pin, pout);
374 }
375
376 return 0;
377 }
378
379
380 /* ----------
381 * Cipher-Block Chaining
382 * CT = (FB = ENC (PT^IV, EK))
383 * PT = DEC ((FB = CT), DK)
384 */
385 static
CMEMBER(EncryptCbc)386 rc_t CMEMBER(EncryptCbc) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
387 {
388 CipherVec cv;
389 CipherVec ivec;
390 const uint8_t * pin;
391 uint8_t * pout;
392
393 #if 0
394 ivec = *(const CipherVec*)self->dad.encrypt_ivec;
395 #else
396 ivec = CipherVecIn (self->dad.encrypt_ivec);
397 #endif
398
399 for ((pin = in), (pout = out);
400 block_count --;
401 (pin += self->dad.block_size), (pout += self->dad.block_size))
402 {
403 cv = CipherVecIn (pin);
404 cv ^= ivec;
405 ivec = CMEMBER(EncryptV1)(self, cv);
406 CipherVecOut (ivec, pout);
407 }
408
409 #if 0
410 *(CipherVec*)self->dad.encrypt_ivec = ivec;
411 #else
412 CipherVecOut (ivec, self->dad.encrypt_ivec);
413 #endif
414
415 return 0;
416 }
417
418
419 static
CMEMBER(DecryptCbc)420 rc_t CMEMBER(DecryptCbc) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
421 {
422 CipherVec cv;
423 CipherVec ivec;
424 const uint8_t * pin;
425 uint8_t * pout;
426
427 ivec = CipherVecIn (self->dad.decrypt_ivec);
428
429 for ((pin = in), (pout = out);
430 block_count --;
431 (pin += self->dad.block_size), (pout += self->dad.block_size))
432 {
433 CipherVec temp;
434
435 cv = CipherVecIn (pin);
436 #if 0
437 temp = cv;
438 temp = CMEMBER(DecryptV1)(self, temp);
439 #else
440 temp = CMEMBER(DecryptV1)(self, cv);
441 #endif
442 temp ^= ivec;
443 CipherVecOut (temp, pout);
444 ivec = cv;
445 }
446
447 *(CipherVec*)self->dad.decrypt_ivec = ivec;
448 return 0;
449 }
450
451
452 /* ----------
453 * Propagating cipher-block chaining
454 * FB = PT ^ (CT = ENC ((PT^IV), EK))
455 * FB = CT ^ (PT = DEC (CT,DK) ^ IV)
456 */
457 static
CMEMBER(EncryptPcbc)458 rc_t CMEMBER(EncryptPcbc) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
459 {
460 #if 1
461 CipherVec cv;
462 CipherVec ivec;
463 const uint8_t * pin;
464 uint8_t * pout;
465
466 ivec = *(const CipherVec*)self->dad.encrypt_ivec;
467
468 for ((pin = in), (pout = out);
469 block_count --;
470 (pin += self->dad.block_size), (pout += self->dad.block_size))
471 {
472 CipherVec temp;
473
474 cv = CipherVecIn (pin);
475 temp = cv ^ ivec;
476 temp = CMEMBER(EncryptV1)(self, temp);
477 ivec = cv ^ temp;
478 CipherVecOut (temp, pout);
479 }
480
481 *(CipherVec*)self->dad.encrypt_ivec = ivec;
482
483 return 0;
484 #else
485 return RC (rcKrypto, rcCipher, rcEncoding, rcFunction, rcUnsupported);
486 #endif
487 }
488
489
490 static
CMEMBER(DecryptPcbc)491 rc_t CMEMBER(DecryptPcbc) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
492 {
493 #if 1
494 CipherVec cv;
495 CipherVec ivec;
496 const uint8_t * pin;
497 uint8_t * pout;
498
499 ivec = *(const CipherVec*)self->dad.encrypt_ivec;
500
501 for ((pin = in), (pout = out);
502 block_count --;
503 (pin += self->dad.block_size), (pout += self->dad.block_size))
504 {
505 CipherVec temp;
506
507 cv = CipherVecIn (pin);
508 temp = CMEMBER(DecryptV1)(self, cv);
509 ivec ^= temp;
510 CipherVecOut (temp, pout);
511 }
512
513 *(CipherVec*)self->dad.encrypt_ivec = ivec;
514
515 return 0;
516 #else
517 return RC (rcKrypto, rcCipher, rcEncoding, rcFunction, rcUnsupported);
518 #endif
519 }
520
521
522 /* ----------
523 * Cipher Feedback
524 * CT = (FB = PT) ^ ENC (IV, EK))
525 * PT = (FB = CT) ^ DEC (IV, DK)
526 */
527 static
CMEMBER(EncryptCfb)528 rc_t CMEMBER(EncryptCfb) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
529 {
530 #if 1
531 CipherVec cv;
532 CipherVec ivec;
533 const uint8_t * pin;
534 uint8_t * pout;
535
536 ivec = *(const CipherVec*)self->dad.encrypt_ivec;
537
538 for ((pin = in), (pout = out);
539 block_count --;
540 (pin += self->dad.block_size), (pout += self->dad.block_size))
541 {
542 ivec = CMEMBER(EncryptV1)(self, ivec);
543 cv = CipherVecIn (pin);
544 ivec ^= cv;
545 CipherVecOut (ivec, pout);
546 }
547
548 *(CipherVec*)self->dad.encrypt_ivec = ivec;
549
550 return 0;
551 #else
552 return RC (rcKrypto, rcCipher, rcEncoding, rcFunction, rcUnsupported);
553 #endif
554 }
555
556
557 static
CMEMBER(DecryptCfb)558 rc_t CMEMBER(DecryptCfb) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
559 {
560 #if 1
561 CipherVec cv;
562 CipherVec ivec;
563 const uint8_t * pin;
564 uint8_t * pout;
565
566 ivec = *(const CipherVec*)self->dad.encrypt_ivec;
567
568 for ((pin = in), (pout = out);
569 block_count --;
570 (pin += self->dad.block_size), (pout += self->dad.block_size))
571 {
572 cv = CMEMBER(EncryptV1)(self, ivec);
573 ivec = CipherVecIn (pin);
574 cv ^= ivec;
575 CipherVecOut (cv, pout);
576 }
577
578 *(CipherVec*)self->dad.encrypt_ivec = ivec;
579
580 return 0;
581 #else
582 return RC (rcKrypto, rcCipher, rcEncoding, rcFunction, rcUnsupported);
583 #endif
584 }
585
586
587 /* ----------
588 * Output Feedback
589 * CT = PT ^ (FB = ENC (IV, EK))
590 * PT = CT ^ (FB = DEC (IV, DK))
591 */
592 static
CMEMBER(EncryptOfb)593 rc_t CMEMBER(EncryptOfb) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
594 {
595 #if 1
596 CipherVec cv;
597 CipherVec ivec;
598 const uint8_t * pin;
599 uint8_t * pout;
600
601 ivec = *(const CipherVec*)self->dad.encrypt_ivec;
602
603 for ((pin = in), (pout = out);
604 block_count --;
605 (pin += self->dad.block_size), (pout += self->dad.block_size))
606 {
607 ivec = CMEMBER(EncryptV1)(self, ivec);
608 cv = CipherVecIn (pin);
609 cv ^= ivec;
610 CipherVecOut (cv, pout);
611 }
612
613 *(CipherVec*)self->dad.encrypt_ivec = ivec;
614
615 return 0;
616 #else
617 return RC (rcKrypto, rcCipher, rcEncoding, rcFunction, rcUnsupported);
618 #endif
619 }
620
621
622 static
CMEMBER(DecryptOfb)623 rc_t CMEMBER(DecryptOfb) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
624 {
625 return CMEMBER(EncryptOfb)(self, in, out, block_count);
626 }
627
628
629 /* Counter
630 * IV is a nonce and not re-used as FB
631 * CT = PT ^ ENC (N, EK)
632 * PT = CT ^ ENC (N, DK)
633 * Note decrypt is encrypt.
634 * nonce is a function that given an iv generates the next iv
635 */
636 static
CMEMBER(EncryptCtr)637 rc_t CMEMBER(EncryptCtr) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
638 {
639 return RC (rcKrypto, rcCipher, rcEncoding, rcFunction, rcUnsupported);
640 }
641
642
643 static
CMEMBER(DecryptCtr)644 rc_t CMEMBER(DecryptCtr) (CIPHER_IMPL * self, const void * in, void * out, uint32_t block_count)
645 {
646 return RC (rcKrypto, rcCipher, rcEncoding, rcFunction, rcUnsupported);
647 }
648
649 static
650 struct KCipher_vt_v1 CMEMBER(_vt_v1) =
651 {
652 { 1, 0 },
653
654 CMEMBER(Destroy),
655 CMEMBER(SetEncryptKey),
656 CMEMBER(SetDecryptKey),
657 CMEMBER(SetEncryptIvec),
658 CMEMBER(SetDecryptIvec),
659 CMEMBER(SetEncryptCounterFunc),
660 CMEMBER(SetDecryptCounterFunc),
661 CMEMBER(Encrypt),
662 CMEMBER(Decrypt),
663 CMEMBER(EncryptEcb),
664 CMEMBER(DecryptEcb),
665 CMEMBER(EncryptCbc),
666 CMEMBER(DecryptCbc),
667 CMEMBER(EncryptPcbc),
668 CMEMBER(DecryptPcbc),
669 CMEMBER(EncryptCfb),
670 CMEMBER(DecryptCfb),
671 CMEMBER(EncryptOfb),
672 CMEMBER(DecryptOfb),
673 CMEMBER(EncryptCtr),
674 CMEMBER(DecryptCtr)
675 };
676
677
678 static __inline__
CMEMBER(AllocAes)679 rc_t CMEMBER(AllocAes)(CIPHER_IMPL ** pobj,
680 const KBlockCipher * block_cipher)
681 {
682 CipherAes * obj;
683
684 obj = calloc (1, sizeof (*obj));
685 *pobj = (CIPHER_IMPL*)obj;
686
687 return (obj ? 0 : RC (rcKrypto, rcCipher, rcConstructing, rcMemory, rcExhausted));
688 }
689
690
691 static __inline__
CMEMBER(InitAes)692 rc_t CMEMBER(InitAes) (CIPHER_IMPL * self,
693 const KBlockCipher * block_cipher)
694 {
695 KCipher * dad = &self->dad;
696 CipherAes * aes = (struct CipherAes*)self;
697
698 KCipherInit (dad, sizeof (CipherVec),
699 (const KCipher_vt*)&CMEMBER(_vt_v1),
700 CMEMBER(ClassName));
701
702 dad->encrypt_key = &aes->e_key;
703 dad->decrypt_key = &aes->d_key;
704 dad->encrypt_ivec = &aes->e_ivec;
705 dad->decrypt_ivec = &aes->d_ivec;
706
707 self->block_cipher = &block_cipher->vec;
708
709 return 0;
710 }
711
712
713 static __inline__
CMEMBER(AllocNull)714 rc_t CMEMBER(AllocNull)(CIPHER_IMPL ** pobj,
715 const KBlockCipher * block_cipher)
716 {
717 CipherNull * obj;
718
719 obj = calloc (1, sizeof (*obj));
720 *pobj = (CIPHER_IMPL*)obj;
721
722 return (obj ? 0 : RC (rcKrypto, rcCipher, rcConstructing, rcMemory, rcExhausted));
723 }
724
725
726 static __inline__
CMEMBER(InitNull)727 rc_t CMEMBER(InitNull) (CIPHER_IMPL * self,
728 const KBlockCipher * block_cipher)
729 {
730 KCipher * dad = &self->dad;
731 CipherNull * null = (CipherNull*)self;
732
733 KCipherInit (dad, sizeof (CipherVec),
734 (const KCipher_vt*)&CMEMBER(_vt_v1),
735 CMEMBER(ClassName));
736
737 dad->encrypt_key = &null->e_ivec;
738 dad->decrypt_key = &null->d_ivec;
739 dad->encrypt_ivec = &null->e_ivec;
740 dad->decrypt_ivec = &null->d_ivec;
741
742 self->block_cipher = &block_cipher->vec;
743
744 return 0;
745 }
746
747
CMEMBER(Make)748 rc_t CMEMBER(Make) (KCipher ** new_obj, kcipher_type type)
749 {
750 rc_t rc;
751 KBlockCipher * block_cipher;
752
753 if (new_obj == NULL)
754 return RC (rcKrypto, rcCipher, rcConstructing, rcSelf, rcNull);
755
756 *new_obj = NULL;
757
758 switch (type)
759 {
760 default:
761 return RC (rcKrypto, rcCipher, rcConstructing, rcParam, rcInvalid);
762
763 case kcipher_null:
764 rc = NULLBCMEMBER(Make)(&block_cipher);
765 break;
766
767 case kcipher_AES:
768 rc = AESBCMEMBER(Make)(&block_cipher);
769 break;
770 }
771
772 if (rc == 0)
773 {
774 CIPHER_IMPL * obj;
775
776 switch (type)
777 {
778 case kcipher_null:
779 rc = CMEMBER(AllocNull) (&obj, block_cipher);
780 if (rc == 0)
781 {
782 rc = CMEMBER(InitNull) (obj, block_cipher);
783 if (rc == 0)
784 *new_obj = (KCipher*)obj;
785 else
786 free (obj);
787 }
788 break;
789 case kcipher_AES:
790 rc = CMEMBER(AllocAes) (&obj, block_cipher);
791 if (rc == 0)
792 {
793 rc = CMEMBER(InitAes) (obj, block_cipher);
794 if (rc == 0)
795 *new_obj = (KCipher*)obj;
796 else
797 free (obj);
798 }
799 default:
800 /* can't really get here */
801 break;
802 }
803 }
804 return rc;
805 }
806
807
808 /* EOF */
809