See ChangeLog: Mon Jul 17 16:35:47 CEST 2000 Werner Koch
[gnupg.git] / cipher / cipher.c
1 /* cipher.c  -  cipher dispatcher
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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
28 #include "g10lib.h"
29 #include "cipher.h"
30 #include "des.h"
31 #include "blowfish.h"
32 #include "cast5.h"
33 #include "dynload.h"
34
35 #define MAX_BLOCKSIZE 16
36 #define TABLE_SIZE 10
37 #define CTX_MAGIC_NORMAL 0x24091964
38 #define CTX_MAGIC_SECURE 0x46919042
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, byte *key, unsigned keylen );
47     void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
48     void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
49 };
50
51 static struct cipher_table_s cipher_table[TABLE_SIZE];
52 static int disabled_algos[TABLE_SIZE];
53
54 struct gcry_cipher_handle {
55     int magic;
56     int  algo;
57     int  mode;
58     unsigned int flags;
59     size_t blocksize;
60     byte iv[MAX_BLOCKSIZE];     /* (this should be ulong aligned) */
61     byte lastiv[MAX_BLOCKSIZE];
62     int  unused;  /* in IV */
63     int  (*setkey)( void *c, byte *key, unsigned keylen );
64     void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
65     void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
66     PROPERLY_ALIGNED_TYPE context;
67 };
68
69
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
77
78
79 /****************
80  * Put the static entries into the table.
81  */
82 static void
83 setup_cipher_table(void)
84 {
85
86     int i;
87
88     i = 0;
89     cipher_table[i].algo = CIPHER_ALGO_TWOFISH;
90     cipher_table[i].name = twofish_get_info( cipher_table[i].algo,
91                                          &cipher_table[i].keylen,
92                                          &cipher_table[i].blocksize,
93                                          &cipher_table[i].contextsize,
94                                          &cipher_table[i].setkey,
95                                          &cipher_table[i].encrypt,
96                                          &cipher_table[i].decrypt     );
97     if( !cipher_table[i].name )
98         BUG();
99     i++;
100     cipher_table[i].algo = CIPHER_ALGO_BLOWFISH;
101     cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
102                                          &cipher_table[i].keylen,
103                                          &cipher_table[i].blocksize,
104                                          &cipher_table[i].contextsize,
105                                          &cipher_table[i].setkey,
106                                          &cipher_table[i].encrypt,
107                                          &cipher_table[i].decrypt     );
108     if( !cipher_table[i].name )
109         BUG();
110     i++;
111     cipher_table[i].algo = CIPHER_ALGO_CAST5;
112     cipher_table[i].name = cast5_get_info( cipher_table[i].algo,
113                                          &cipher_table[i].keylen,
114                                          &cipher_table[i].blocksize,
115                                          &cipher_table[i].contextsize,
116                                          &cipher_table[i].setkey,
117                                          &cipher_table[i].encrypt,
118                                          &cipher_table[i].decrypt     );
119     if( !cipher_table[i].name )
120         BUG();
121     i++;
122     cipher_table[i].algo = CIPHER_ALGO_3DES;
123     cipher_table[i].name = des_get_info( cipher_table[i].algo,
124                                          &cipher_table[i].keylen,
125                                          &cipher_table[i].blocksize,
126                                          &cipher_table[i].contextsize,
127                                          &cipher_table[i].setkey,
128                                          &cipher_table[i].encrypt,
129                                          &cipher_table[i].decrypt     );
130     if( !cipher_table[i].name )
131         BUG();
132     i++;
133     cipher_table[i].algo = CIPHER_ALGO_DUMMY;
134     cipher_table[i].name = "DUMMY";
135     cipher_table[i].blocksize = 8;
136     cipher_table[i].keylen = 128;
137     cipher_table[i].contextsize = 0;
138     cipher_table[i].setkey = dummy_setkey;
139     cipher_table[i].encrypt = dummy_encrypt_block;
140     cipher_table[i].decrypt = dummy_decrypt_block;
141     i++;
142
143     for( ; i < TABLE_SIZE; i++ )
144         cipher_table[i].name = NULL;
145 }
146
147
148 /****************
149  * Try to load all modules and return true if new modules are available
150  */
151 static int
152 load_cipher_modules(void)
153 {
154     static int done = 0;
155     static int initialized = 0;
156     void *context = NULL;
157     struct cipher_table_s *ct;
158     int ct_idx;
159     int i;
160     const char *name;
161     int any = 0;
162
163     if( !initialized ) {
164         cipher_modules_constructor();
165         setup_cipher_table(); /* load static modules on the first call */
166         initialized = 1;
167         return 1;
168     }
169
170     if( done )
171         return 0;
172     done = 1;
173
174     for(ct_idx=0, ct = cipher_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
175         if( !ct->name )
176             break;
177     }
178     if( ct_idx >= TABLE_SIZE-1 )
179         BUG(); /* table already full */
180     /* now load all extensions */
181     while( (name = enum_gnupgext_ciphers( &context, &ct->algo,
182                                 &ct->keylen, &ct->blocksize, &ct->contextsize,
183                                 &ct->setkey, &ct->encrypt, &ct->decrypt)) ) {
184         if( ct->blocksize != 8 && ct->blocksize != 16 ) {
185             log_info("skipping cipher %d: unsupported blocksize\n", ct->algo);
186             continue;
187         }
188         for(i=0; cipher_table[i].name; i++ )
189             if( cipher_table[i].algo == ct->algo )
190                 break;
191         if( cipher_table[i].name ) {
192             log_info("skipping cipher %d: already loaded\n", ct->algo );
193             continue;
194         }
195         /* put it into the table */
196         if( g10_log_verbosity( 2 ) )
197             log_info("loaded cipher %d (%s)\n", ct->algo, name);
198         ct->name = name;
199         ct_idx++;
200         ct++;
201         any = 1;
202         /* check whether there are more available table slots */
203         if( ct_idx >= TABLE_SIZE-1 ) {
204             log_info("cipher table full; ignoring other extensions\n");
205             break;
206         }
207     }
208     enum_gnupgext_ciphers( &context, NULL, NULL, NULL, NULL,
209                                            NULL, NULL, NULL );
210     return any;
211 }
212
213
214 /****************
215  * Map a string to the cipher algo.
216  * Returns: The algo ID of the cipher for the gioven name or
217  *          0 if the name is not known.
218  */
219 int
220 gcry_cipher_map_name( const char *string )
221 {
222     int i;
223     const char *s;
224
225     do {
226         for(i=0; (s=cipher_table[i].name); i++ )
227             if( !stricmp( s, string ) )
228                 return cipher_table[i].algo;
229     } while( load_cipher_modules() );
230     return 0;
231 }
232
233 /****************
234  * Map a cipher algo to a string
235  */
236 static const char *
237 cipher_algo_to_string( int algo )
238 {
239     int i;
240
241     do {
242         for(i=0; cipher_table[i].name; i++ )
243             if( cipher_table[i].algo == algo )
244                 return cipher_table[i].name;
245     } while( load_cipher_modules() );
246     return NULL;
247 }
248
249 /****************
250  * This function simply returns the name of the algorithm or some constant
251  * string when there is no algo.  It will never return NULL.
252  */
253 const char *
254 gcry_cipher_algo_name( int algo )
255 {
256     const char *s = cipher_algo_to_string( algo );
257     return s? s: "";
258 }
259
260
261
262 static void
263 disable_cipher_algo( int algo )
264 {
265     int i;
266
267     for(i=0; i < DIM(disabled_algos); i++ ) {
268         if( !disabled_algos[i] || disabled_algos[i] == algo ) {
269             disabled_algos[i] = algo;
270             return;
271         }
272     }
273     /* fixme: we should use a linked list */
274     log_fatal("can't disable cipher algo %d: table full\n", algo );
275 }
276
277 /****************
278  * Return 0 if the cipher algo is available
279  */
280 static int
281 check_cipher_algo( int algo )
282 {
283     int i;
284
285     do {
286        for(i=0; cipher_table[i].name; i++ )
287            if( cipher_table[i].algo == algo ) {
288                 for(i=0; i < DIM(disabled_algos); i++ ) {
289                    if( disabled_algos[i] == algo )
290                        return GCRYERR_INV_CIPHER_ALGO;
291                 }
292                 return 0; /* okay */
293            }
294     } while( load_cipher_modules() );
295     return GCRYERR_INV_CIPHER_ALGO;
296 }
297
298
299 static unsigned
300 cipher_get_keylen( int algo )
301 {
302     int i;
303     unsigned len = 0;
304
305     do {
306         for(i=0; cipher_table[i].name; i++ ) {
307             if( cipher_table[i].algo == algo ) {
308                 len = cipher_table[i].keylen;
309                 if( !len )
310                     log_bug("cipher %d w/o key length\n", algo );
311                 return len;
312             }
313         }
314     } while( load_cipher_modules() );
315     log_bug("cipher %d not found\n", algo );
316     return 0;
317 }
318
319 static unsigned
320 cipher_get_blocksize( int algo )
321 {
322     int i;
323     unsigned len = 0;
324
325     do {
326         for(i=0; cipher_table[i].name; i++ ) {
327             if( cipher_table[i].algo == algo ) {
328                 len = cipher_table[i].blocksize;
329                 if( !len )
330                     log_bug("cipher %d w/o blocksize\n", algo );
331                 return len;
332             }
333         }
334     } while( load_cipher_modules() );
335     log_bug("cipher %d not found\n", algo );
336     return 0;
337 }
338
339
340 /****************
341  * Open a cipher handle for use with algorithm ALGO, in mode MODE
342  * and return the handle.  Return NULL and set the internal error variable
343  * if something goes wrong.
344  */
345
346 GCRY_CIPHER_HD
347 gcry_cipher_open( int algo, int mode, unsigned int flags )
348 {
349     GCRY_CIPHER_HD h;
350     int idx;
351     int secure = (flags & GCRY_CIPHER_SECURE);
352
353     fast_random_poll();
354
355     /* check whether the algo is available */
356     if( check_cipher_algo( algo ) ) {
357         set_lasterr( GCRYERR_INV_CIPHER_ALGO );
358         return NULL;
359     }
360
361     /* check flags */
362     if( (flags & ~(GCRY_CIPHER_SECURE|GCRY_CIPHER_ENABLE_SYNC)) ) {
363         set_lasterr( GCRYERR_INV_CIPHER_ALGO );
364         return NULL;
365     }
366
367     /* get the table index of the algo */
368     for(idx=0; cipher_table[idx].name; idx++ )
369         if( cipher_table[idx].algo == algo )
370             break;
371     if( !cipher_table[idx].name )
372         BUG(); /* check_cipher_algo() should have loaded the algo */
373
374     if( algo == CIPHER_ALGO_DUMMY )
375         mode = GCRY_CIPHER_MODE_NONE;  /* force this mode for dummy algo */
376
377     /* check that a valid mode has been requested */
378     switch( mode ) {
379       case GCRY_CIPHER_MODE_ECB:
380       case GCRY_CIPHER_MODE_CBC:
381       case GCRY_CIPHER_MODE_CFB:
382         break;
383       case GCRY_CIPHER_MODE_NONE:
384         /* FIXME: issue a warning when this mode is used */
385         break;
386       default:
387         set_lasterr( GCRYERR_INV_CIPHER_ALGO );
388         return NULL;
389     }
390
391     /* ? perform selftest here and mark this with a flag in cipher_table ? */
392
393     h = secure ? g10_calloc_secure( 1, sizeof *h
394                                        + cipher_table[idx].contextsize
395                                        - sizeof(PROPERLY_ALIGNED_TYPE) )
396                : g10_calloc( 1, sizeof *h + cipher_table[idx].contextsize
397                                            - sizeof(PROPERLY_ALIGNED_TYPE)  );
398     if( !h ) {
399         set_lasterr( GCRYERR_NO_MEM );
400         return NULL;
401     }
402     h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
403     h->algo = algo;
404     h->mode = mode;
405     h->flags = flags;
406     h->blocksize = cipher_table[idx].blocksize;
407     h->setkey  = cipher_table[idx].setkey;
408     h->encrypt = cipher_table[idx].encrypt;
409     h->decrypt = cipher_table[idx].decrypt;
410
411     return h;
412 }
413
414
415 void
416 gcry_cipher_close( GCRY_CIPHER_HD h )
417 {
418     if( !h )
419         return;
420     if( h->magic != CTX_MAGIC_SECURE && h->magic != CTX_MAGIC_NORMAL )
421         g10_fatal_error(GCRYERR_INTERNAL,
422                         "gcry_cipher_close: already closed/invalid handle");
423     h->magic = 0;
424     g10_free(h);
425 }
426
427
428 static int
429 cipher_setkey( GCRY_CIPHER_HD c, byte *key, unsigned keylen )
430 {
431     return (*c->setkey)( &c->context.c, key, keylen );
432 }
433
434
435 static void
436 cipher_setiv( GCRY_CIPHER_HD c, const byte *iv, unsigned ivlen )
437 {
438     memset( c->iv, 0, c->blocksize );
439     if( iv ) {
440         if( ivlen != c->blocksize )
441             log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
442                                              ivlen, (unsigned)c->blocksize );
443         if( ivlen > c->blocksize )
444             ivlen = c->blocksize;
445         memcpy( c->iv, iv, ivlen );
446     }
447     c->unused = 0;
448 }
449
450
451
452 static void
453 do_ecb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
454 {
455     unsigned n;
456
457     for(n=0; n < nblocks; n++ ) {
458         (*c->encrypt)( &c->context.c, outbuf, inbuf );
459         inbuf  += c->blocksize;
460         outbuf += c->blocksize;
461     }
462 }
463
464 static void
465 do_ecb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
466 {
467     unsigned n;
468
469     for(n=0; n < nblocks; n++ ) {
470         (*c->decrypt)( &c->context.c, outbuf, inbuf );
471         inbuf  += c->blocksize;
472         outbuf += c->blocksize;
473     }
474 }
475
476 static void
477 do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
478 {
479     unsigned int n;
480     byte *ivp;
481     int i;
482     size_t blocksize = c->blocksize;
483
484     for(n=0; n < nblocks; n++ ) {
485         /* fixme: the xor should works on words and not on
486          * bytes.  Maybe it is a good idea to enhance the cipher backend
487          * API to allow for CBC handling in the backend */
488         for(ivp=c->iv,i=0; i < blocksize; i++ )
489             outbuf[i] = inbuf[i] ^ *ivp++;
490         (*c->encrypt)( &c->context.c, outbuf, outbuf );
491         memcpy(c->iv, outbuf, blocksize );
492         inbuf  += c->blocksize;
493         outbuf += c->blocksize;
494     }
495 }
496
497 static void
498 do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
499 {
500     unsigned int n;
501     byte *ivp;
502     int i;
503     size_t blocksize = c->blocksize;
504
505     for(n=0; n < nblocks; n++ ) {
506         /* because outbuf and inbuf might be the same, we have
507          * to save the original ciphertext block.  We use lastiv
508          * for this here because it is not used otherwise */
509         memcpy(c->lastiv, inbuf, blocksize );
510         (*c->decrypt)( &c->context.c, outbuf, inbuf );
511         for(ivp=c->iv,i=0; i < blocksize; i++ )
512             outbuf[i] ^= *ivp++;
513         memcpy(c->iv, c->lastiv, blocksize );
514         inbuf  += c->blocksize;
515         outbuf += c->blocksize;
516     }
517 }
518
519
520 static void
521 do_cfb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes )
522 {
523     byte *ivp;
524     size_t blocksize = c->blocksize;
525
526     if( nbytes <= c->unused ) {
527         /* short enough to be encoded by the remaining XOR mask */
528         /* XOR the input with the IV and store input into IV */
529         for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- )
530             *outbuf++ = (*ivp++ ^= *inbuf++);
531         return;
532     }
533
534     if( c->unused ) {
535         /* XOR the input with the IV and store input into IV */
536         nbytes -= c->unused;
537         for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- )
538             *outbuf++ = (*ivp++ ^= *inbuf++);
539     }
540
541     /* now we can process complete blocks */
542     while( nbytes >= blocksize ) {
543         int i;
544         /* encrypt the IV (and save the current one) */
545         memcpy( c->lastiv, c->iv, blocksize );
546         (*c->encrypt)( &c->context.c, c->iv, c->iv );
547         /* XOR the input with the IV and store input into IV */
548         for(ivp=c->iv,i=0; i < blocksize; i++ )
549             *outbuf++ = (*ivp++ ^= *inbuf++);
550         nbytes -= blocksize;
551     }
552     if( nbytes ) { /* process the remaining bytes */
553         /* encrypt the IV (and save the current one) */
554         memcpy( c->lastiv, c->iv, blocksize );
555         (*c->encrypt)( &c->context.c, c->iv, c->iv );
556         c->unused = blocksize;
557         /* and apply the xor */
558         c->unused -= nbytes;
559         for(ivp=c->iv; nbytes; nbytes-- )
560             *outbuf++ = (*ivp++ ^= *inbuf++);
561     }
562 }
563
564 static void
565 do_cfb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes )
566 {
567     byte *ivp;
568     ulong temp;
569     size_t blocksize = c->blocksize;
570
571     if( nbytes <= c->unused ) {
572         /* short enough to be encoded by the remaining XOR mask */
573         /* XOR the input with the IV and store input into IV */
574         for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){
575             temp = *inbuf++;
576             *outbuf++ = *ivp ^ temp;
577             *ivp++ = temp;
578         }
579         return;
580     }
581
582     if( c->unused ) {
583         /* XOR the input with the IV and store input into IV */
584         nbytes -= c->unused;
585         for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) {
586             temp = *inbuf++;
587             *outbuf++ = *ivp ^ temp;
588             *ivp++ = temp;
589         }
590     }
591
592     /* now we can process complete blocks */
593     while( nbytes >= blocksize ) {
594         int i;
595         /* encrypt the IV (and save the current one) */
596         memcpy( c->lastiv, c->iv, blocksize );
597         (*c->encrypt)( &c->context.c, c->iv, c->iv );
598         /* XOR the input with the IV and store input into IV */
599         for(ivp=c->iv,i=0; i < blocksize; i++ ) {
600             temp = *inbuf++;
601             *outbuf++ = *ivp ^ temp;
602             *ivp++ = temp;
603         }
604         nbytes -= blocksize;
605     }
606     if( nbytes ) { /* process the remaining bytes */
607         /* encrypt the IV (and save the current one) */
608         memcpy( c->lastiv, c->iv, blocksize );
609         (*c->encrypt)( &c->context.c, c->iv, c->iv );
610         c->unused = blocksize;
611         /* and apply the xor */
612         c->unused -= nbytes;
613         for(ivp=c->iv; nbytes; nbytes-- ) {
614             temp = *inbuf++;
615             *outbuf++ = *ivp ^ temp;
616             *ivp++ = temp;
617         }
618     }
619 }
620
621
622 /****************
623  * Encrypt INBUF to OUTBUF with the mode selected at open.
624  * inbuf and outbuf may overlap or be the same.
625  * Depending on the mode some some contraints apply to NBYTES.
626  */
627 static void
628 cipher_encrypt( GCRY_CIPHER_HD c, byte *outbuf,
629                                   const byte *inbuf, unsigned nbytes )
630 {
631     switch( c->mode ) {
632       case GCRY_CIPHER_MODE_ECB:
633         assert(!(nbytes%8));
634         do_ecb_encrypt(c, outbuf, inbuf, nbytes/8 );
635         break;
636       case GCRY_CIPHER_MODE_CBC:
637         assert(!(nbytes%8));  /* fixme: should be blocksize */
638         do_cbc_encrypt(c, outbuf, inbuf, nbytes/8 );
639         break;
640       case GCRY_CIPHER_MODE_CFB:
641         do_cfb_encrypt(c, outbuf, inbuf, nbytes );
642         break;
643       case GCRY_CIPHER_MODE_NONE:
644         if( inbuf != outbuf )
645             memmove( outbuf, inbuf, nbytes );
646         break;
647       default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
648     }
649 }
650
651
652 /****************
653  * Encrypt IN and write it to OUT.  If IN is NULL, in-place encryption has
654  * been requested,
655  */
656 int
657 gcry_cipher_encrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
658                                        const byte  *in, size_t inlen )
659 {
660     if( !in ) {
661         /* caller requested in-place encryption */
662         /* actullay cipher_encrypt() does not need to know about it, but
663          * we may chnage this to get better performace */
664         cipher_encrypt( h, out, out, outsize );
665     }
666     else {
667         if( outsize < inlen )
668             return set_lasterr( GCRYERR_TOO_SHORT );
669         /* fixme: check that the inlength is a multipe of the blocksize
670          * if a blockoriented mode is used, or modify cipher_encrypt to
671          * return an error in this case */
672         cipher_encrypt( h, out, in, inlen );
673     }
674     return 0;
675 }
676
677
678
679 /****************
680  * Decrypt INBUF to OUTBUF with the mode selected at open.
681  * inbuf and outbuf may overlap or be the same.
682  * Depending on the mode some some contraints apply to NBYTES.
683  */
684 static void
685 cipher_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf,
686                                                         unsigned nbytes )
687 {
688     switch( c->mode ) {
689       case GCRY_CIPHER_MODE_ECB:
690         assert(!(nbytes%8));
691         do_ecb_decrypt(c, outbuf, inbuf, nbytes/8 );
692         break;
693       case GCRY_CIPHER_MODE_CBC:
694         assert(!(nbytes%8));    /* fixme: should assert on blocksize */
695         do_cbc_decrypt(c, outbuf, inbuf, nbytes/8 );
696         break;
697       case GCRY_CIPHER_MODE_CFB:
698         do_cfb_decrypt(c, outbuf, inbuf, nbytes );
699         break;
700       case GCRY_CIPHER_MODE_NONE:
701         if( inbuf != outbuf )
702             memmove( outbuf, inbuf, nbytes );
703         break;
704       default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode );
705     }
706 }
707
708
709 int
710 gcry_cipher_decrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
711                                  const byte  *in, size_t inlen )
712 {
713     if( !in ) {
714         /* caller requested in-place encryption */
715         /* actullay cipher_encrypt() does not need to know about it, but
716          * we may chnage this to get better performace */
717         cipher_decrypt( h, out, out, outsize );
718     }
719     else {
720         if( outsize < inlen )
721             return set_lasterr( GCRYERR_TOO_SHORT );
722         /* fixme: check that the inlength is a multipe of the blocksize
723          * if a blockoriented mode is used, or modify cipher_encrypt to
724          * return an error in this case */
725         cipher_decrypt( h, out, in, inlen );
726     }
727     return 0;
728 }
729
730
731
732 /****************
733  * Used for PGP's somewhat strange CFB mode. Only works if
734  * the corresponding flag is set.
735  */
736 static void
737 cipher_sync( GCRY_CIPHER_HD c )
738 {
739     if( (c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused ) {
740         memmove(c->iv + c->unused, c->iv, c->blocksize - c->unused );
741         memcpy(c->iv, c->lastiv + c->blocksize - c->unused, c->unused);
742         c->unused = 0;
743     }
744 }
745
746
747 int
748 gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen)
749 {
750     switch( cmd ) {
751       case GCRYCTL_SET_KEY:
752         cipher_setkey( h, buffer, buflen );
753         break;
754       case GCRYCTL_SET_IV:
755         cipher_setiv( h, buffer, buflen );
756         break;
757       case GCRYCTL_CFB_SYNC:
758         cipher_sync( h );
759         break;
760
761       case GCRYCTL_DISABLE_ALGO:
762         /* this one expects a NULL handle and buffer pointing to an
763          * integer with the algo number.
764          */
765         if( h || !buffer || buflen != sizeof(int) )
766             return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
767         disable_cipher_algo( *(int*)buffer );
768         break;
769
770       default:
771         return set_lasterr( GCRYERR_INV_OP );
772     }
773     return 0;
774 }
775
776
777 /****************
778  * Return information about the cipher handle.
779  * -1 is returned on error and gcry_errno() may be used to get more information
780  * about the error.
781  */
782 int
783 gcry_cipher_info( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t *nbytes)
784 {
785     switch( cmd ) {
786       default:
787         set_lasterr( GCRYERR_INV_OP );
788         return -1;
789     }
790     return 0;
791 }
792
793 /****************
794  * Return information about the given cipher algorithm
795  * WHAT select the kind of information returned:
796  *  GCRYCTL_GET_KEYLEN:
797  *      Return the length of the key, if the algorithm
798  *      supports multiple key length, the maximum supported value
799  *      is returnd.  The length is return as number of octets.
800  *      buffer and nbytes must be zero.
801  *      The keylength is returned in _bytes_.
802  *  GCRYCTL_GET_BLKLEN:
803  *      Return the blocklength of the algorithm counted in octets.
804  *      buffer and nbytes must be zero.
805  *  GCRYCTL_TEST_ALGO:
806  *      Returns 0 when the specified algorithm is available for use.
807  *      buffer and nbytes must be zero.
808  *
809  * On error the value -1 is returned and the error reason may be
810  * retrieved by gcry_errno().
811  * Note:  Because this function is in most caes used to return an
812  * integer value, we can make it easier for the caller to just look at
813  * the return value.  The caller will in all cases consult the value
814  * and thereby detecting whether a error occured or not (i.e. while checking
815  * the block size)
816  */
817 int
818 gcry_cipher_algo_info( int algo, int what, void *buffer, size_t *nbytes)
819 {
820     unsigned int ui;
821
822     switch( what ) {
823       case GCRYCTL_GET_KEYLEN:
824         if( buffer || nbytes ) {
825             set_lasterr( GCRYERR_INV_CIPHER_ALGO );
826             break;
827         }
828         ui = cipher_get_keylen( algo );
829         if( ui > 0 && ui <= 512 )
830             return (int)ui/8;
831         /* the only reason is an invalid algo or a strange blocksize */
832         set_lasterr( GCRYERR_INV_CIPHER_ALGO );
833         break;
834
835       case GCRYCTL_GET_BLKLEN:
836         if( buffer || nbytes ) {
837             set_lasterr( GCRYERR_INV_CIPHER_ALGO );
838             break;
839         }
840         ui = cipher_get_blocksize( algo );
841         if( ui > 0 && ui < 10000 )
842             return (int)ui;
843         /* the only reason is an invalid algo or a strange blocksize */
844         set_lasterr( GCRYERR_INV_CIPHER_ALGO );
845         break;
846
847       case GCRYCTL_TEST_ALGO:
848         if( buffer || nbytes ) {
849             set_lasterr( GCRYERR_INV_ARG );
850             break;
851         }
852         if( check_cipher_algo( algo ) ) {
853             set_lasterr( GCRYERR_INV_CIPHER_ALGO );
854             break;
855         }
856         return 0;
857
858       default:
859         set_lasterr( GCRYERR_INV_OP );
860     }
861     return -1;
862 }
863
864
865