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