diff options
author | Werner Koch <wk@gnupg.org> | 2002-11-10 18:03:28 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2002-11-10 18:03:28 +0000 |
commit | 6322f8255a6a7d23f6bb09e5449007efcd87e727 (patch) | |
tree | f149e0d19846852d42f37392b152483f05129c74 | |
parent | e836e23303243e73bf4ee674716d7a5642aae949 (diff) | |
download | libgcrypt-6322f8255a6a7d23f6bb09e5449007efcd87e727.tar.gz |
* cipher.c (gcry_cipher_open): Don't reject CTS flag.
(do_cbc_encrypt, do_cbc_decrypt, cipher_encrypt)
(gcry_cipher_encrypt, cipher_decrypt)
(gcry_cipher_decrypt): Support CTS flag.
(gcry_cipher_ctl): Toggle CTS flag.
* md4.c: New. By by Simon Josefsson.
* Makefile.am (EXTRA_PROGRAMS): Add md4.c.
* md.c (oid_table,gcry_md_get_algo_dlen): MD4 support.
-rw-r--r-- | cipher/ChangeLog | 14 | ||||
-rw-r--r-- | cipher/Makefile.am | 3 | ||||
-rw-r--r-- | cipher/cipher.c | 99 | ||||
-rw-r--r-- | cipher/md.c | 3 | ||||
-rw-r--r-- | cipher/md4.c | 0 |
5 files changed, 105 insertions, 14 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 9b341621..01c41267 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,17 @@ +2002-11-10 Simon Josefsson <jas@extundo.com> + + * cipher.c (gcry_cipher_open): Don't reject CTS flag. + (do_cbc_encrypt, do_cbc_decrypt, cipher_encrypt) + (gcry_cipher_encrypt, cipher_decrypt) + (gcry_cipher_decrypt): Support CTS flag. + (gcry_cipher_ctl): Toggle CTS flag. + +2002-11-10 Werner Koch <wk@gnupg.org> + + * md4.c: New. By by Simon Josefsson. + * Makefile.am (EXTRA_PROGRAMS): Add md4.c. + * md.c (oid_table,gcry_md_get_algo_dlen): MD4 support. + 2002-10-14 Werner Koch <wk@gnupg.org> * arcfour.c (do_encrypt_stream): Don't use increment op when diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 49c53893..9ce1cd04 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -28,12 +28,13 @@ noinst_LTLIBRARIES = libcipher.la # The configure script greps the module names from the EXTRA_PROGRAMS line -EXTRA_PROGRAMS = rndlinux rndunix rndegd rndw32 sha1 rmd160 md5 tiger +EXTRA_PROGRAMS = rndlinux rndunix rndegd rndw32 sha1 rmd160 md4 md5 tiger EXTRA_rndlinux_SOURCES = rndlinux.c EXTRA_rndunix_SOURCES = rndunix.c EXTRA_rndegd_SOURCES = rndegd.c EXTRA_rndw32_SOURCES = rndw32.c +EXTRA_md4_SOURCES = md4.c EXTRA_md5_SOURCES = md5.c EXTRA_rmd160_SOURCES = rmd160.c EXTRA_sha1_SOURCES = sha1.c diff --git a/cipher/cipher.c b/cipher/cipher.c index b688aed7..2119fc9c 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -513,7 +513,9 @@ gcry_cipher_open( int algo, int mode, unsigned int flags ) } /* check flags */ - if( (flags & ~(GCRY_CIPHER_SECURE|GCRY_CIPHER_ENABLE_SYNC)) ) { + if( (flags & ~(GCRY_CIPHER_SECURE| + GCRY_CIPHER_ENABLE_SYNC| + GCRY_CIPHER_CBC_CTS)) ) { set_lasterr( GCRYERR_INV_CIPHER_ALGO ); return NULL; } @@ -642,12 +644,18 @@ do_ecb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblo } static void -do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks ) +do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes ) { unsigned int n; byte *ivp; int i; size_t blocksize = c->blocksize; + unsigned nblocks = nbytes / blocksize; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) { + if ((nbytes % blocksize) == 0) + nblocks--; + } for(n=0; n < nblocks; n++ ) { /* fixme: the xor should works on words and not on @@ -660,15 +668,44 @@ do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblo inbuf += c->blocksize; outbuf += c->blocksize; } + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + { + int restbytes; + + if ((nbytes % blocksize) == 0) + restbytes = blocksize; + else + restbytes = nbytes % blocksize; + + memcpy(outbuf, outbuf - c->blocksize, restbytes); + outbuf -= c->blocksize; + + for(ivp=c->iv,i=0; i < restbytes; i++ ) + outbuf[i] = inbuf[i] ^ *ivp++; + for(; i < blocksize; i++ ) + outbuf[i] = 0 ^ *ivp++; + + (*c->encrypt)( &c->context.c, outbuf, outbuf ); + memcpy(c->iv, outbuf, blocksize ); + } } static void -do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks ) +do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes ) { unsigned int n; byte *ivp; int i; size_t blocksize = c->blocksize; + unsigned nblocks = nbytes / blocksize; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) { + nblocks--; + if ((nbytes % blocksize) == 0) + nblocks--; + memcpy(c->lastiv, c->iv, blocksize ); + } for(n=0; n < nblocks; n++ ) { /* because outbuf and inbuf might be the same, we have @@ -682,6 +719,30 @@ do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblo inbuf += c->blocksize; outbuf += c->blocksize; } + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) { + int restbytes; + + if ((nbytes % blocksize) == 0) + restbytes = blocksize; + else + restbytes = nbytes % blocksize; + + memcpy(c->lastiv, c->iv, blocksize ); /* save Cn-2 */ + memcpy(c->iv, inbuf + blocksize, restbytes ); /* save Cn */ + + (*c->decrypt)( &c->context.c, outbuf, (char*)/*argggg*/inbuf ); + for(ivp=c->iv,i=0; i < restbytes; i++ ) + outbuf[i] ^= *ivp++; + + memcpy(outbuf + blocksize, outbuf, restbytes); + for(i=restbytes; i < blocksize; i++) + c->iv[i] = outbuf[i]; + (*c->decrypt)( &c->context.c, outbuf, c->iv ); + for(ivp=c->lastiv,i=0; i < blocksize; i++ ) + outbuf[i] ^= *ivp++; + /* c->lastiv is now really lastlastiv, does this matter? */ + } } @@ -810,8 +871,9 @@ cipher_encrypt( GCRY_CIPHER_HD c, byte *outbuf, rc = GCRYERR_INV_ARG; break; case GCRY_CIPHER_MODE_CBC: - if (!(nbytes%c->blocksize)) - do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + if (!(nbytes%c->blocksize) || (nbytes > c->blocksize && + (c->flags & GCRY_CIPHER_CBC_CTS))) + do_cbc_encrypt(c, outbuf, inbuf, nbytes ); else rc = GCRYERR_INV_ARG; break; @@ -855,10 +917,12 @@ gcry_cipher_encrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize, if ( outsize < inlen ) return set_lasterr ( GCRYERR_TOO_SHORT ); if ( ( h->mode == GCRY_CIPHER_MODE_ECB || - h->mode == GCRY_CIPHER_MODE_CBC ) && - (inlen % h->blocksize) != 0 ) - return set_lasterr( GCRYERR_INV_ARG ); - + (h->mode == GCRY_CIPHER_MODE_CBC && + !((h->flags & GCRY_CIPHER_CBC_CTS) && + (inlen > h->blocksize)))) && + (inlen % h->blocksize) != 0 ) + return set_lasterr( GCRYERR_INV_ARG ); + rc = cipher_encrypt ( h, out, in, inlen ); } @@ -886,8 +950,9 @@ cipher_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, rc = GCRYERR_INV_ARG; break; case GCRY_CIPHER_MODE_CBC: - if (!(nbytes%c->blocksize)) - do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + if (!(nbytes%c->blocksize) || (nbytes > c->blocksize && + (c->flags & GCRY_CIPHER_CBC_CTS))) + do_cbc_decrypt(c, outbuf, inbuf, nbytes ); else rc = GCRYERR_INV_ARG; break; @@ -927,8 +992,10 @@ gcry_cipher_decrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize, if( outsize < inlen ) return set_lasterr( GCRYERR_TOO_SHORT ); if ( ( h->mode == GCRY_CIPHER_MODE_ECB || - h->mode == GCRY_CIPHER_MODE_CBC ) - && ( inlen % h->blocksize ) != 0 ) + (h->mode == GCRY_CIPHER_MODE_CBC && + !((h->flags & GCRY_CIPHER_CBC_CTS) && + (inlen > h->blocksize)))) && + (inlen % h->blocksize) != 0 ) return set_lasterr( GCRYERR_INV_ARG ); rc = cipher_decrypt( h, out, in, inlen ); @@ -969,6 +1036,12 @@ gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen) case GCRYCTL_CFB_SYNC: cipher_sync( h ); break; + case GCRYCTL_SET_CBC_CTS: + if (buflen) + h->flags |= GCRY_CIPHER_CBC_CTS; + else + h->flags &= ~GCRY_CIPHER_CBC_CTS; + break; case GCRYCTL_DISABLE_ALGO: /* this one expects a NULL handle and buffer pointing to an diff --git a/cipher/md.c b/cipher/md.c index 51cfdb60..4f41a7a0 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -49,6 +49,8 @@ static struct { { "1.2.840.113549.2.5", GCRY_MD_MD5 }, /* GNU.digestAlgorithm TIGER */ { "1.3.6.1.4.1.11591.12.2", GCRY_MD_TIGER }, + /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */ + { "1.2.840.113549.2.4", GCRY_MD_MD4 }, {NULL} }; @@ -819,6 +821,7 @@ gcry_md_get_algo_dlen( int algo ) /* we do some very quick checks here */ switch( algo ) { + case GCRY_MD_MD4: case GCRY_MD_MD5: return 16; case GCRY_MD_SHA1: case GCRY_MD_RMD160: return 20; diff --git a/cipher/md4.c b/cipher/md4.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/cipher/md4.c |