summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2002-11-10 18:03:28 +0000
committerWerner Koch <wk@gnupg.org>2002-11-10 18:03:28 +0000
commit6322f8255a6a7d23f6bb09e5449007efcd87e727 (patch)
treef149e0d19846852d42f37392b152483f05129c74
parente836e23303243e73bf4ee674716d7a5642aae949 (diff)
downloadlibgcrypt-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/ChangeLog14
-rw-r--r--cipher/Makefile.am3
-rw-r--r--cipher/cipher.c99
-rw-r--r--cipher/md.c3
-rw-r--r--cipher/md4.c0
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