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