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