Switched to GPLv3.
[gnupg.git] / cipher / cipher.c
1 /* cipher.c  -  cipher dispatcher
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3  *               2007 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include "util.h"
28 #include "errors.h"
29 #include "cipher.h"
30 #include "algorithms.h"
31
32 /* We have support for a DUMMY encryption cipher which comes handy to
33    debug MDCs and similar things.  Because this is a bit dangerous it
34    is not enabled. */
35 /*#define ALLOW_DUMMY 1 */
36
37 #define MAX_BLOCKSIZE 16
38 #define TABLE_SIZE 14
39
40 struct cipher_table_s {
41     const char *name;
42     int algo;
43     size_t blocksize;
44     size_t keylen;
45     size_t contextsize; /* allocate this amount of context */
46     int  (*setkey)( void *c, const byte *key, unsigned keylen );
47     void (*encrypt)( void *c, byte *outbuf, const byte *inbuf );
48     void (*decrypt)( void *c, byte *outbuf, const byte *inbuf );
49 };
50
51 static struct cipher_table_s cipher_table[TABLE_SIZE];
52 static int disabled_algos[TABLE_SIZE];
53
54
55 struct cipher_handle_s {
56     int  algo;
57     int  mode;
58     size_t blocksize;
59     byte iv[MAX_BLOCKSIZE];     /* (this should be ulong aligned) */
60     byte lastiv[MAX_BLOCKSIZE];
61     int  unused;  /* in IV */
62     int  (*setkey)( void *c, const byte *key, unsigned keylen );
63     void (*encrypt)( void *c, byte *outbuf, const byte *inbuf );
64     void (*decrypt)( void *c, byte *outbuf, const byte *inbuf );
65     PROPERLY_ALIGNED_TYPE context;
66 };
67
68
69 #ifdef ALLOW_DUMMY
70 static int
71 dummy_setkey( void *c, byte *key, unsigned keylen ) { return 0; }
72 static void
73 dummy_encrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); }
74 static void
75 dummy_decrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); }
76 #ifdef __GNUC__
77 # warning DUMMY cipher module is enabled
78 #endif
79 #endif
80
81
82 /****************
83  * Put the static entries into the table.
84  */
85 static void
86 setup_cipher_table(void)
87 {
88     int i=0;
89
90 #ifdef USE_AES
91     cipher_table[i].algo = CIPHER_ALGO_AES;
92     cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
93                                          &cipher_table[i].keylen,
94                                          &cipher_table[i].blocksize,
95                                          &cipher_table[i].contextsize,
96                                          &cipher_table[i].setkey,
97                                          &cipher_table[i].encrypt,
98                                          &cipher_table[i].decrypt     );
99     if( !cipher_table[i].name )
100         BUG();
101     i++;
102     cipher_table[i].algo = CIPHER_ALGO_AES192;
103     cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
104                                          &cipher_table[i].keylen,
105                                          &cipher_table[i].blocksize,
106                                          &cipher_table[i].contextsize,
107                                          &cipher_table[i].setkey,
108                                          &cipher_table[i].encrypt,
109                                          &cipher_table[i].decrypt     );
110     if( !cipher_table[i].name )
111         BUG();
112     i++;
113     cipher_table[i].algo = CIPHER_ALGO_AES256;
114     cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
115                                          &cipher_table[i].keylen,
116                                          &cipher_table[i].blocksize,
117                                          &cipher_table[i].contextsize,
118                                          &cipher_table[i].setkey,
119                                          &cipher_table[i].encrypt,
120                                          &cipher_table[i].decrypt     );
121     if( !cipher_table[i].name )
122         BUG();
123     i++;
124 #endif
125
126 #ifdef USE_TWOFISH
127     cipher_table[i].algo = CIPHER_ALGO_TWOFISH;
128     cipher_table[i].name = twofish_get_info( cipher_table[i].algo,
129                                          &cipher_table[i].keylen,
130                                          &cipher_table[i].blocksize,
131                                          &cipher_table[i].contextsize,
132                                          &cipher_table[i].setkey,
133                                          &cipher_table[i].encrypt,
134                                          &cipher_table[i].decrypt     );
135     if( !cipher_table[i].name )
136         BUG();
137     i++;
138 #endif
139
140 #ifdef USE_BLOWFISH
141     cipher_table[i].algo = CIPHER_ALGO_BLOWFISH;
142     cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
143                                          &cipher_table[i].keylen,
144                                          &cipher_table[i].blocksize,
145                                          &cipher_table[i].contextsize,
146                                          &cipher_table[i].setkey,
147                                          &cipher_table[i].encrypt,
148                                          &cipher_table[i].decrypt     );
149     if( !cipher_table[i].name )
150         BUG();
151     i++;
152 #endif
153
154 #ifdef USE_CAST5
155     cipher_table[i].algo = CIPHER_ALGO_CAST5;
156     cipher_table[i].name = cast5_get_info( cipher_table[i].algo,
157                                          &cipher_table[i].keylen,
158                                          &cipher_table[i].blocksize,
159                                          &cipher_table[i].contextsize,
160                                          &cipher_table[i].setkey,
161                                          &cipher_table[i].encrypt,
162                                          &cipher_table[i].decrypt     );
163     if( !cipher_table[i].name )
164         BUG();
165     i++;
166 #endif
167
168     cipher_table[i].algo = CIPHER_ALGO_3DES;
169     cipher_table[i].name = des_get_info( cipher_table[i].algo,
170                                          &cipher_table[i].keylen,
171                                          &cipher_table[i].blocksize,
172                                          &cipher_table[i].contextsize,
173                                          &cipher_table[i].setkey,
174                                          &cipher_table[i].encrypt,
175                                          &cipher_table[i].decrypt     );
176     if( !cipher_table[i].name )
177         BUG();
178     i++;
179
180 #ifdef USE_CAMELLIA
181     cipher_table[i].algo = CIPHER_ALGO_CAMELLIA;
182     cipher_table[i].name = camellia_get_info( cipher_table[i].algo,
183                                               &cipher_table[i].keylen,
184                                               &cipher_table[i].blocksize,
185                                               &cipher_table[i].contextsize,
186                                               &cipher_table[i].setkey,
187                                               &cipher_table[i].encrypt,
188                                               &cipher_table[i].decrypt     );
189     if( !cipher_table[i].name )
190         BUG();
191     i++;
192 #endif
193
194 #ifdef USE_IDEA
195     cipher_table[i].algo = CIPHER_ALGO_IDEA;
196     cipher_table[i].name = idea_get_info( cipher_table[i].algo,
197                                           &cipher_table[i].keylen,
198                                           &cipher_table[i].blocksize,
199                                           &cipher_table[i].contextsize,
200                                           &cipher_table[i].setkey,
201                                           &cipher_table[i].encrypt,
202                                           &cipher_table[i].decrypt     );
203     if (cipher_table[i].name)
204       i++;  /* Note that the loadable IDEA module may not be
205                available. */
206 #endif
207
208 #ifdef ALLOW_DUMMY
209     cipher_table[i].algo = CIPHER_ALGO_DUMMY;
210     cipher_table[i].name = "DUMMY";
211     cipher_table[i].blocksize = 8;
212     cipher_table[i].keylen = 128;
213     cipher_table[i].contextsize = 0;
214     cipher_table[i].setkey = dummy_setkey;
215     cipher_table[i].encrypt = dummy_encrypt_block;
216     cipher_table[i].decrypt = dummy_decrypt_block;
217     i++;
218 #endif
219
220     for( ; i < TABLE_SIZE; i++ )
221         cipher_table[i].name = NULL;
222 }
223
224
225 /****************
226  * Try to load all modules and return true if new modules are available
227  */
228 static int
229 load_cipher_modules(void)
230 {
231   static int initialized = 0;
232
233   if (!initialized ) 
234     {
235       setup_cipher_table(); /* load static modules on the first call */
236       initialized = 1;
237       return 1;
238     }
239   return 0;
240 }
241
242 /****************
243  * Map a string to the cipher algo
244  */
245 int
246 string_to_cipher_algo( const char *string )
247 {
248   int i;
249   const char *s;
250
251   /* kludge to alias RIJNDAEL to AES */
252   if ( *string == 'R' || *string == 'r')
253     {
254       if (!ascii_strcasecmp (string, "RIJNDAEL"))
255         string = "AES";
256       else if (!ascii_strcasecmp (string, "RIJNDAEL192"))
257         string = "AES192";
258       else if (!ascii_strcasecmp (string, "RIJNDAEL256"))
259         string = "AES256";
260     }
261
262   do
263     {
264       for(i=0; (s=cipher_table[i].name); i++ ) 
265         {
266           if( !ascii_strcasecmp( s, string ) )
267             return cipher_table[i].algo;
268         }
269     } while( load_cipher_modules() );
270
271     /* Didn't find it, so try the Sx format */
272     if(string[0]=='S' || string[0]=='s')
273       {
274         long val;
275         char *endptr;
276
277         string++;
278
279         val=strtol(string,&endptr,10);
280         if(*string!='\0' && *endptr=='\0' && check_cipher_algo(val)==0)
281           return val;
282       }
283
284   return 0;
285 }
286
287 /****************
288  * Map a cipher algo to a string
289  */
290 const char *
291 cipher_algo_to_string( int algo )
292 {
293     int i;
294
295     do {
296         for(i=0; cipher_table[i].name; i++ )
297             if( cipher_table[i].algo == algo )
298                 return cipher_table[i].name;
299     } while( load_cipher_modules() );
300     return NULL;
301 }
302
303
304 void
305 disable_cipher_algo( int algo )
306 {
307     int i;
308
309     for(i=0; i < DIM(disabled_algos); i++ ) {
310         if( !disabled_algos[i] || disabled_algos[i] == algo ) {
311             disabled_algos[i] = algo;
312             return;
313         }
314     }
315     /* fixme: we should use a linked list */
316     log_fatal("can't disable cipher algo %d: table full\n", algo );
317 }
318
319 /****************
320  * Return 0 if the cipher algo is available
321  */
322 int
323 check_cipher_algo( int algo )
324 {
325     int i;
326
327     do {
328        for(i=0; cipher_table[i].name; i++ )
329            if( cipher_table[i].algo == algo ) {
330                 for(i=0; i < DIM(disabled_algos); i++ ) {
331                    if( disabled_algos[i] == algo )
332                        return G10ERR_CIPHER_ALGO;
333                 }
334                 return 0; /* okay */
335            }
336     } while( load_cipher_modules() );
337     return G10ERR_CIPHER_ALGO;
338 }
339
340
341 unsigned
342 cipher_get_keylen( int algo )
343 {
344     int i;
345     unsigned len = 0;
346
347     do {
348         for(i=0; cipher_table[i].name; i++ ) {
349             if( cipher_table[i].algo == algo ) {
350                 len = cipher_table[i].keylen;
351                 if( !len )
352                     log_bug("cipher %d w/o key length\n", algo );
353                 return len;
354             }
355         }
356     } while( load_cipher_modules() );
357     log_bug("cipher %d not found\n", algo );
358     return 0;
359 }
360
361 unsigned
362 cipher_get_blocksize( int algo )
363 {
364     int i;
365     unsigned len = 0;
366
367     do {
368         for(i=0; cipher_table[i].name; i++ ) {
369             if( cipher_table[i].algo == algo ) {
370                 len = cipher_table[i].blocksize;
371                 if( !len )
372                     log_bug("cipher %d w/o blocksize\n", algo );
373                 return len;
374             }
375         }
376     } while( load_cipher_modules() );
377     log_bug("cipher %d not found\n", algo );
378     return 0;
379 }
380
381
382 /****************
383  * Open a cipher handle for use with algorithm ALGO, in mode MODE
384  * and put it into secure memory if SECURE is true.
385  */
386 CIPHER_HANDLE
387 cipher_open( int algo, int mode, int secure )
388 {
389     CIPHER_HANDLE hd;
390     int i;
391
392     fast_random_poll();
393     do {
394         for(i=0; cipher_table[i].name; i++ )
395             if( cipher_table[i].algo == algo )
396                 break;
397     } while( !cipher_table[i].name && load_cipher_modules() );
398     if( !cipher_table[i].name ) {
399         log_fatal("cipher_open: algorithm %d not available\n", algo );
400         return NULL;
401     }
402
403     /* ? perform selftest here and mark this with a flag in cipher_table ? */
404
405     hd = secure ? xmalloc_secure_clear( sizeof *hd
406                                         + cipher_table[i].contextsize
407                                         - sizeof(PROPERLY_ALIGNED_TYPE) )
408                 : xmalloc_clear( sizeof *hd + cipher_table[i].contextsize
409                                            - sizeof(PROPERLY_ALIGNED_TYPE)  );
410     hd->algo = algo;
411     hd->blocksize = cipher_table[i].blocksize;
412     hd->setkey  = cipher_table[i].setkey;
413     hd->encrypt = cipher_table[i].encrypt;
414     hd->decrypt = cipher_table[i].decrypt;
415
416     if( mode == CIPHER_MODE_AUTO_CFB ) {
417         if( algo >= 100 )
418             hd->mode = CIPHER_MODE_CFB;
419         else
420             hd->mode = CIPHER_MODE_PHILS_CFB;
421     }
422     else
423         hd->mode = mode;
424
425 #ifdef ALLOW_DUMMY
426     if( algo == CIPHER_ALGO_DUMMY )
427         hd->mode = CIPHER_MODE_DUMMY;
428 #endif
429
430     return hd;
431 }
432
433
434 void
435 cipher_close( CIPHER_HANDLE c )
436 {
437     xfree(c);
438 }
439
440
441 int
442 cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen )
443 {
444     return (*c->setkey)( &c->context.c, key, keylen );
445 }
446
447
448 void
449 cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen )
450 {
451     memset( c->iv, 0, c->blocksize );
452     if( iv ) {
453         if( ivlen != c->blocksize )
454             log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
455                                              ivlen, (unsigned)c->blocksize );
456         if( ivlen > c->blocksize )
457             ivlen = c->blocksize;
458         memcpy( c->iv, iv, ivlen );
459     }
460     c->unused = 0;
461 }
462
463 static void
464 do_ecb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
465 {
466     unsigned n;
467
468     for(n=0; n < nblocks; n++ ) {
469         (*c->encrypt)( &c->context.c, outbuf, inbuf );
470         inbuf  += c->blocksize;
471         outbuf += c->blocksize;
472     }
473 }
474
475 static void
476 do_ecb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
477 {
478     unsigned n;
479
480     for(n=0; n < nblocks; n++ ) {
481         (*c->decrypt)( &c->context.c, outbuf, inbuf );
482         inbuf  += c->blocksize;
483         outbuf += c->blocksize;
484     }
485 }
486
487 static void
488 do_cbc_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
489 {
490     unsigned int n;
491     byte *ivp;
492     int i;
493     size_t blocksize = c->blocksize;
494
495     for(n=0; n < nblocks; n++ ) {
496         /* fixme: the xor should works on words and not on
497          * bytes.  Maybe it is a good idea to enhance the cipher backend
498          * API to allow for CBC handling in the backend */
499         for(ivp=c->iv,i=0; i < blocksize; i++ )
500             outbuf[i] = inbuf[i] ^ *ivp++;
501         (*c->encrypt)( &c->context.c, outbuf, outbuf );
502         memcpy(c->iv, outbuf, blocksize );
503         inbuf  += c->blocksize;
504         outbuf += c->blocksize;
505     }
506 }
507
508 static void
509 do_cbc_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
510 {
511     unsigned int n;
512     byte *ivp;
513     int i;
514     size_t blocksize = c->blocksize;
515
516     for(n=0; n < nblocks; n++ ) {
517         /* because outbuf and inbuf might be the same, we have
518          * to save the original ciphertext block.  We use lastiv
519          * for this here because it is not used otherwise */
520         memcpy(c->lastiv, inbuf, blocksize );
521         (*c->decrypt)( &c->context.c, outbuf, inbuf );
522         for(ivp=c->iv,i=0; i < blocksize; i++ )
523             outbuf[i] ^= *ivp++;
524         memcpy(c->iv, c->lastiv, blocksize );
525         inbuf  += c->blocksize;
526         outbuf += c->blocksize;
527     }
528 }
529
530
531 static void
532 do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
533 {
534     byte *ivp;
535     size_t blocksize = c->blocksize;
536
537     if( nbytes <= c->unused ) {
538         /* short enough to be encoded by the remaining XOR mask */
539         /* XOR the input with the IV and store input into IV */
540         for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- )
541             *outbuf++ = (*ivp++ ^= *inbuf++);
542         return;
543     }
544
545     if( c->unused ) {
546         /* XOR the input with the IV and store input into IV */
547         nbytes -= c->unused;
548         for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- )
549             *outbuf++ = (*ivp++ ^= *inbuf++);
550     }
551
552     /* Now we can process complete blocks. */
553 #if 0 
554     /* Experimental code.  We may only use this for standard CFB
555        because for Phil's mode we need to save the IV of before the
556        last encryption - we don't want to do this in tghe fasf CFB
557        encryption routine.  */
558     if (c->algo == CIPHER_ALGO_AES
559         && nbytes >= blocksize 
560         && c->mode != CIPHER_MODE_PHILS_CFB) {
561         size_t n;
562
563         memcpy( c->lastiv, c->iv, blocksize );
564         n = (nbytes / blocksize) * blocksize;
565         rijndael_cfb_encrypt (&c->context.c, c->iv, outbuf, inbuf, n);
566         inbuf  += n;
567         outbuf += n;
568         nbytes -= n;
569     }
570 #endif
571     while( nbytes >= blocksize ) {
572         int i;
573         /* encrypt the IV (and save the current one) */
574         memcpy( c->lastiv, c->iv, blocksize );
575         (*c->encrypt)( &c->context.c, c->iv, c->iv );
576         /* XOR the input with the IV and store input into IV */
577         for(ivp=c->iv,i=0; i < blocksize; i++ )
578             *outbuf++ = (*ivp++ ^= *inbuf++);
579         nbytes -= blocksize;
580     }
581     if( nbytes ) { /* process the remaining bytes */
582         /* encrypt the IV (and save the current one) */
583         memcpy( c->lastiv, c->iv, blocksize );
584         (*c->encrypt)( &c->context.c, c->iv, c->iv );
585         c->unused = blocksize;
586         /* and apply the xor */
587         c->unused -= nbytes;
588         for(ivp=c->iv; nbytes; nbytes-- )
589             *outbuf++ = (*ivp++ ^= *inbuf++);
590     }
591 }
592
593 static void
594 do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
595 {
596     byte *ivp;
597     ulong temp;
598     size_t blocksize = c->blocksize;
599
600     if( nbytes <= c->unused ) {
601         /* short enough to be encoded by the remaining XOR mask */
602         /* XOR the input with the IV and store input into IV */
603         for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){
604             temp = *inbuf++;
605             *outbuf++ = *ivp ^ temp;
606             *ivp++ = temp;
607         }
608         return;
609     }
610
611     if( c->unused ) {
612         /* XOR the input with the IV and store input into IV */
613         nbytes -= c->unused;
614         for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) {
615             temp = *inbuf++;
616             *outbuf++ = *ivp ^ temp;
617             *ivp++ = temp;
618         }
619     }
620
621     /* now we can process complete blocks */
622     while( nbytes >= blocksize ) {
623         int i;
624         /* encrypt the IV (and save the current one) */
625         memcpy( c->lastiv, c->iv, blocksize );
626         (*c->encrypt)( &c->context.c, c->iv, c->iv );
627         /* XOR the input with the IV and store input into IV */
628         for(ivp=c->iv,i=0; i < blocksize; i++ ) {
629             temp = *inbuf++;
630             *outbuf++ = *ivp ^ temp;
631             *ivp++ = temp;
632         }
633         nbytes -= blocksize;
634     }
635     if( nbytes ) { /* process the remaining bytes */
636         /* encrypt the IV (and save the current one) */
637         memcpy( c->lastiv, c->iv, blocksize );
638         (*c->encrypt)( &c->context.c, c->iv, c->iv );
639         c->unused = blocksize;
640         /* and apply the xor */
641         c->unused -= nbytes;
642         for(ivp=c->iv; nbytes; nbytes-- ) {
643             temp = *inbuf++;
644             *outbuf++ = *ivp ^ temp;
645             *ivp++ = temp;
646         }
647     }
648 }
649
650
651 /****************
652  * Encrypt INBUF to OUTBUF with the mode selected at open.
653  * inbuf and outbuf may overlap or be the same.
654  * Depending on the mode some some contraints apply to NBYTES.
655  */
656 void
657 cipher_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
658 {
659     switch( c->mode ) {
660       case CIPHER_MODE_ECB:
661         assert(!(nbytes%c->blocksize));
662         do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
663         break;
664       case CIPHER_MODE_CBC:
665         assert(!(nbytes%c->blocksize));  
666         do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
667         break;
668       case CIPHER_MODE_CFB:
669       case CIPHER_MODE_PHILS_CFB:
670         do_cfb_encrypt(c, outbuf, inbuf, nbytes );
671         break;
672 #ifdef ALLOW_DUMMY
673       case CIPHER_MODE_DUMMY:
674         if( inbuf != outbuf )
675             memmove( outbuf, inbuf, nbytes );
676         break;
677 #endif
678       default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
679     }
680 }
681
682
683 /****************
684  * Decrypt INBUF to OUTBUF with the mode selected at open.
685  * inbuf and outbuf may overlap or be the same.
686  * Depending on the mode some some contraints apply to NBYTES.
687  */
688 void
689 cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
690 {
691     switch( c->mode ) {
692       case CIPHER_MODE_ECB:
693         assert(!(nbytes%c->blocksize));
694         do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
695         break;
696       case CIPHER_MODE_CBC:
697         assert(!(nbytes%c->blocksize));
698         do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
699         break;
700       case CIPHER_MODE_CFB:
701       case CIPHER_MODE_PHILS_CFB:
702         do_cfb_decrypt(c, outbuf, inbuf, nbytes );
703         break;
704 #ifdef ALLOW_DUMMY
705       case CIPHER_MODE_DUMMY:
706         if( inbuf != outbuf )
707             memmove( outbuf, inbuf, nbytes );
708         break;
709 #endif
710       default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode );
711     }
712 }
713
714
715
716 /****************
717  * Used for PGP's somewhat strange CFB mode. Only works if
718  * the handle is in PHILS_CFB mode
719  */
720 void
721 cipher_sync( CIPHER_HANDLE c )
722 {
723     if( c->mode == CIPHER_MODE_PHILS_CFB && c->unused ) {
724         memmove(c->iv + c->unused, c->iv, c->blocksize - c->unused );
725         memcpy(c->iv, c->lastiv + c->blocksize - c->unused, c->unused);
726         c->unused = 0;
727     }
728 }