* cipher.c (gcry_cipher_open): Don't reject CTS flag.
authorWerner Koch <wk@gnupg.org>
Sun, 10 Nov 2002 18:03:28 +0000 (18:03 +0000)
committerWerner Koch <wk@gnupg.org>
Sun, 10 Nov 2002 18:03:28 +0000 (18:03 +0000)
(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.

cipher/ChangeLog
cipher/Makefile.am
cipher/cipher.c
cipher/md.c
cipher/md4.c [new file with mode: 0644]

index 9b34162..01c4126 100644 (file)
@@ -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
index 49c5389..9ce1cd0 100644 (file)
@@ -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
index b688aed..2119fc9 100644 (file)
@@ -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
index 51cfdb6..4f41a7a 100644 (file)
@@ -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 (file)
index 0000000..e69de29