summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS8
-rw-r--r--cipher/ChangeLog15
-rw-r--r--cipher/cipher.c389
-rw-r--r--random/ChangeLog7
-rw-r--r--random/rndw32.c9
-rw-r--r--tests/ChangeLog6
-rw-r--r--tests/basic.c81
-rw-r--r--tests/benchmark.c15
8 files changed, 342 insertions, 188 deletions
diff --git a/NEWS b/NEWS
index ba2c3abc..f97f0e20 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,14 @@ Noteworthy changes in version 1.5.x (unreleased)
* New cipher algorithm mode for AES-WRAP.
+ * Fix minor memory leak in DSA key generation.
+
+ * No switch into FIPS mode if /proc/version is not readable.
+
+ * Fix sigill during Padlock detection on old CPUs.
+
+ * Fix a hang on some W2000 machines.
+
* Interface changes relative to the 1.4.2 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRY_CIPHER_MODE_AESWRAP NEW.
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 2ddd1d95..26b9e7ba 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,18 @@
+2009-12-10 Werner Koch <wk@g10code.com>
+
+ * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for
+ suitable value. Add check for valid inputlen. Wipe temporary
+ memory.
+ (do_ctr_decrypt): Likewise.
+ (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for
+ suitable value. Move check for valid inputlen to here; change
+ returned error from INV_ARG to INV_LENGTH.
+ (do_ecb_encrypt, do_ecb_decrypt): Ditto.
+ (do_cfb_encrypt, do_cfb_decrypt): Ditto.
+ (do_ofb_encrypt, do_ofb_decrypt): Ditto.
+ (cipher_encrypt, cipher_encrypt): Adjust for above changes.
+ (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify.
+
2009-12-09 Werner Koch <wk@g10code.com>
* cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP.
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 355ba689..4808a5fb 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -1,6 +1,6 @@
/* cipher.c - cipher dispatcher
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- * 2005, 2007, 2008 Free Software Foundation, Inc.
+ * 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -937,48 +937,78 @@ cipher_reset (gcry_cipher_hd_t c)
}
-static void
-do_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nblocks )
+
+static gcry_err_code_t
+do_ecb_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
- unsigned int n;
+ unsigned int blocksize = c->cipher->blocksize;
+ unsigned int n, nblocks;
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ if ((inbuflen % blocksize))
+ return GPG_ERR_INV_LENGTH;
+
+ nblocks = inbuflen / c->cipher->blocksize;
+
for (n=0; n < nblocks; n++ )
{
- c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
- inbuf += c->cipher->blocksize;
- outbuf += c->cipher->blocksize;
+ c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
+ inbuf += blocksize;
+ outbuf += blocksize;
}
+ return 0;
}
-static void
-do_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nblocks )
+static gcry_err_code_t
+do_ecb_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
- unsigned int n;
+ unsigned int blocksize = c->cipher->blocksize;
+ unsigned int n, nblocks;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+ if ((inbuflen % blocksize))
+ return GPG_ERR_INV_LENGTH;
+ nblocks = inbuflen / c->cipher->blocksize;
for (n=0; n < nblocks; n++ )
{
- c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
- inbuf += c->cipher->blocksize;
- outbuf += c->cipher->blocksize;
+ c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf );
+ inbuf += blocksize;
+ outbuf += blocksize;
}
+
+ return 0;
}
-static void
-do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes )
+static gcry_err_code_t
+do_cbc_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned int n;
unsigned char *ivp;
int i;
size_t blocksize = c->cipher->blocksize;
- unsigned nblocks = nbytes / blocksize;
+ unsigned nblocks = inbuflen / blocksize;
+
+ if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen))
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ((inbuflen % c->cipher->blocksize)
+ && !(inbuflen > c->cipher->blocksize
+ && (c->flags & GCRY_CIPHER_CBC_CTS)))
+ return GPG_ERR_INV_LENGTH;
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
{
- if ((nbytes % blocksize) == 0)
+ if ((inbuflen % blocksize) == 0)
nblocks--;
}
@@ -1004,17 +1034,17 @@ do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
}
}
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
{
/* We have to be careful here, since outbuf might be equal to
inbuf. */
int restbytes;
unsigned char b;
- if ((nbytes % blocksize) == 0)
+ if ((inbuflen % blocksize) == 0)
restbytes = blocksize;
else
- restbytes = nbytes % blocksize;
+ restbytes = inbuflen % blocksize;
outbuf -= blocksize;
for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++)
@@ -1029,23 +1059,34 @@ do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
c->cipher->encrypt (&c->context.c, outbuf, outbuf);
memcpy (c->u_iv.iv, outbuf, blocksize);
}
+
+ return 0;
}
-static void
-do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes)
+static gcry_err_code_t
+do_cbc_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned int n;
unsigned char *ivp;
int i;
size_t blocksize = c->cipher->blocksize;
- unsigned int nblocks = nbytes / blocksize;
+ unsigned int nblocks = inbuflen / blocksize;
+
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ((inbuflen % c->cipher->blocksize)
+ && !(inbuflen > c->cipher->blocksize
+ && (c->flags & GCRY_CIPHER_CBC_CTS)))
+ return GPG_ERR_INV_LENGTH;
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
{
nblocks--;
- if ((nbytes % blocksize) == 0)
+ if ((inbuflen % blocksize) == 0)
nblocks--;
memcpy (c->lastiv, c->u_iv.iv, blocksize);
}
@@ -1073,14 +1114,14 @@ do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
}
}
- if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize)
+ if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
{
int restbytes;
- if ((nbytes % blocksize) == 0)
+ if ((inbuflen % blocksize) == 0)
restbytes = blocksize;
else
- restbytes = nbytes % blocksize;
+ restbytes = inbuflen % blocksize;
memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
@@ -1097,32 +1138,38 @@ do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
outbuf[i] ^= *ivp++;
/* c->lastiv is now really lastlastiv, does this matter? */
}
+
+ return 0;
}
-static void
-do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes )
+static gcry_err_code_t
+do_cfb_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned char *ivp;
size_t blocksize = c->cipher->blocksize;
size_t blocksize_x_2 = blocksize + blocksize;
- if ( nbytes <= c->unused )
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ( inbuflen <= c->unused )
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV and store input into IV. */
for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
- nbytes;
- nbytes--, c->unused-- )
+ inbuflen;
+ inbuflen--, c->unused-- )
*outbuf++ = (*ivp++ ^= *inbuf++);
- return;
+ return 0;
}
if ( c->unused )
{
/* XOR the input with the IV and store input into IV */
- nbytes -= c->unused;
+ inbuflen -= c->unused;
for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
*outbuf++ = (*ivp++ ^= *inbuf++);
}
@@ -1130,17 +1177,17 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
/* Now we can process complete blocks. We use a loop as long as we
have at least 2 blocks and use conditions for the rest. This
also allows to use a bulk encryption function if available. */
- if (nbytes >= blocksize_x_2 && c->bulk.cfb_enc)
+ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc)
{
- unsigned int nblocks = nbytes / blocksize;
+ unsigned int nblocks = inbuflen / blocksize;
c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
outbuf += nblocks * blocksize;
inbuf += nblocks * blocksize;
- nbytes -= nblocks * blocksize;
+ inbuflen -= nblocks * blocksize;
}
else
{
- while ( nbytes >= blocksize_x_2 )
+ while ( inbuflen >= blocksize_x_2 )
{
int i;
/* Encrypt the IV. */
@@ -1148,11 +1195,11 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
/* XOR the input with the IV and store input into IV. */
for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
*outbuf++ = (*ivp++ ^= *inbuf++);
- nbytes -= blocksize;
+ inbuflen -= blocksize;
}
}
- if ( nbytes >= blocksize )
+ if ( inbuflen >= blocksize )
{
int i;
/* Save the current IV and then encrypt the IV. */
@@ -1161,25 +1208,27 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
/* XOR the input with the IV and store input into IV */
for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
*outbuf++ = (*ivp++ ^= *inbuf++);
- nbytes -= blocksize;
+ inbuflen -= blocksize;
}
- if ( nbytes )
+ if ( inbuflen )
{
/* Save the current IV and then encrypt the IV. */
memcpy( c->lastiv, c->u_iv.iv, blocksize );
c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
c->unused = blocksize;
/* Apply the XOR. */
- c->unused -= nbytes;
- for(ivp=c->u_iv.iv; nbytes; nbytes-- )
+ c->unused -= inbuflen;
+ for(ivp=c->u_iv.iv; inbuflen; inbuflen-- )
*outbuf++ = (*ivp++ ^= *inbuf++);
}
+ return 0;
}
-static void
-do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
- const unsigned char *inbuf, unsigned int nbytes )
+static gcry_err_code_t
+do_cfb_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned char *ivp;
unsigned long temp;
@@ -1187,25 +1236,28 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
size_t blocksize = c->cipher->blocksize;
size_t blocksize_x_2 = blocksize + blocksize;
- if (nbytes <= c->unused)
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if (inbuflen <= c->unused)
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV and store input into IV. */
for (ivp=c->u_iv.iv+blocksize - c->unused;
- nbytes;
- nbytes--, c->unused--)
+ inbuflen;
+ inbuflen--, c->unused--)
{
temp = *inbuf++;
*outbuf++ = *ivp ^ temp;
*ivp++ = temp;
}
- return;
+ return 0;
}
if (c->unused)
{
/* XOR the input with the IV and store input into IV. */
- nbytes -= c->unused;
+ inbuflen -= c->unused;
for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
{
temp = *inbuf++;
@@ -1217,17 +1269,17 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
/* Now we can process complete blocks. We use a loop as long as we
have at least 2 blocks and use conditions for the rest. This
also allows to use a bulk encryption function if available. */
- if (nbytes >= blocksize_x_2 && c->bulk.cfb_dec)
+ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec)
{
- unsigned int nblocks = nbytes / blocksize;
+ unsigned int nblocks = inbuflen / blocksize;
c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
outbuf += nblocks * blocksize;
inbuf += nblocks * blocksize;
- nbytes -= nblocks * blocksize;
+ inbuflen -= nblocks * blocksize;
}
else
{
- while (nbytes >= blocksize_x_2 )
+ while (inbuflen >= blocksize_x_2 )
{
/* Encrypt the IV. */
c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
@@ -1238,11 +1290,11 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
*outbuf++ = *ivp ^ temp;
*ivp++ = temp;
}
- nbytes -= blocksize;
+ inbuflen -= blocksize;
}
}
- if (nbytes >= blocksize )
+ if (inbuflen >= blocksize )
{
/* Save the current IV and then encrypt the IV. */
memcpy ( c->lastiv, c->u_iv.iv, blocksize);
@@ -1254,54 +1306,59 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf,
*outbuf++ = *ivp ^ temp;
*ivp++ = temp;
}
- nbytes -= blocksize;
+ inbuflen -= blocksize;
}
- if (nbytes)
+ if (inbuflen)
{
/* Save the current IV and then encrypt the IV. */
memcpy ( c->lastiv, c->u_iv.iv, blocksize );
c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
c->unused = blocksize;
/* Apply the XOR. */
- c->unused -= nbytes;
- for (ivp=c->u_iv.iv; nbytes; nbytes-- )
+ c->unused -= inbuflen;
+ for (ivp=c->u_iv.iv; inbuflen; inbuflen-- )
{
temp = *inbuf++;
*outbuf++ = *ivp ^ temp;
*ivp++ = temp;
}
}
+ return 0;
}
-static void
-do_ofb_encrypt( gcry_cipher_hd_t c,
- byte *outbuf, const byte *inbuf, unsigned nbytes )
+static gcry_err_code_t
+do_ofb_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
- byte *ivp;
+ unsigned char *ivp;
size_t blocksize = c->cipher->blocksize;
- if ( nbytes <= c->unused )
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ( inbuflen <= c->unused )
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV */
for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused;
- nbytes;
- nbytes--, c->unused-- )
+ inbuflen;
+ inbuflen--, c->unused-- )
*outbuf++ = (*ivp++ ^ *inbuf++);
- return;
+ return 0;
}
if( c->unused )
{
- nbytes -= c->unused;
+ inbuflen -= c->unused;
for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
*outbuf++ = (*ivp++ ^ *inbuf++);
}
/* Now we can process complete blocks. */
- while ( nbytes >= blocksize )
+ while ( inbuflen >= blocksize )
{
int i;
/* Encrypt the IV (and save the current one). */
@@ -1310,43 +1367,48 @@ do_ofb_encrypt( gcry_cipher_hd_t c,
for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
*outbuf++ = (*ivp++ ^ *inbuf++);
- nbytes -= blocksize;
+ inbuflen -= blocksize;
}
- if ( nbytes )
+ if ( inbuflen )
{ /* process the remaining bytes */
memcpy( c->lastiv, c->u_iv.iv, blocksize );
c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
c->unused = blocksize;
- c->unused -= nbytes;
- for(ivp=c->u_iv.iv; nbytes; nbytes-- )
+ c->unused -= inbuflen;
+ for(ivp=c->u_iv.iv; inbuflen; inbuflen-- )
*outbuf++ = (*ivp++ ^ *inbuf++);
}
+ return 0;
}
-static void
-do_ofb_decrypt( gcry_cipher_hd_t c,
- byte *outbuf, const byte *inbuf, unsigned int nbytes )
+static gcry_err_code_t
+do_ofb_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
- byte *ivp;
+ unsigned char *ivp;
size_t blocksize = c->cipher->blocksize;
- if( nbytes <= c->unused )
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if( inbuflen <= c->unused )
{
/* Short enough to be encoded by the remaining XOR mask. */
- for (ivp=c->u_iv.iv+blocksize - c->unused; nbytes; nbytes--,c->unused--)
+ for (ivp=c->u_iv.iv+blocksize - c->unused; inbuflen; inbuflen--,c->unused--)
*outbuf++ = *ivp++ ^ *inbuf++;
- return;
+ return 0;
}
if ( c->unused )
{
- nbytes -= c->unused;
+ inbuflen -= c->unused;
for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- )
*outbuf++ = *ivp++ ^ *inbuf++;
}
/* Now we can process complete blocks. */
- while ( nbytes >= blocksize )
+ while ( inbuflen >= blocksize )
{
int i;
/* Encrypt the IV (and save the current one). */
@@ -1354,36 +1416,45 @@ do_ofb_decrypt( gcry_cipher_hd_t c,
c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ )
*outbuf++ = *ivp++ ^ *inbuf++;
- nbytes -= blocksize;
+ inbuflen -= blocksize;
}
- if ( nbytes )
+ if ( inbuflen )
{ /* Process the remaining bytes. */
/* Encrypt the IV (and save the current one). */
memcpy( c->lastiv, c->u_iv.iv, blocksize );
c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
c->unused = blocksize;
- c->unused -= nbytes;
- for (ivp=c->u_iv.iv; nbytes; nbytes-- )
+ c->unused -= inbuflen;
+ for (ivp=c->u_iv.iv; inbuflen; inbuflen-- )
*outbuf++ = *ivp++ ^ *inbuf++;
}
+ return 0;
}
-static void
-do_ctr_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nbytes )
+static gcry_err_code_t
+do_ctr_encrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned int n;
- byte tmp[MAX_BLOCKSIZE];
+ unsigned char tmp[MAX_BLOCKSIZE];
int i;
+ unsigned int blocksize = c->cipher->blocksize;
- for(n=0; n < nbytes; n++)
+ if (outbuflen < inbuflen)
+ return GPG_ERR_BUFFER_TOO_SHORT;
+
+ if ((inbuflen % blocksize))
+ return GPG_ERR_INV_LENGTH;
+
+ for (n=0; n < inbuflen; n++)
{
- if ((n % c->cipher->blocksize) == 0)
+ if ((n % blocksize) == 0)
{
c->cipher->encrypt (&c->context.c, tmp, c->ctr);
- for (i = c->cipher->blocksize; i > 0; i--)
+ for (i = blocksize; i > 0; i--)
{
c->ctr[i-1]++;
if (c->ctr[i-1] != 0)
@@ -1391,16 +1462,20 @@ do_ctr_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
}
}
- /* XOR input with encrypted counter and store in output. */
- outbuf[n] = inbuf[n] ^ tmp[n % c->cipher->blocksize];
+ /* XOR input with encrypted counter and store in output. */
+ outbuf[n] = inbuf[n] ^ tmp[n % blocksize];
}
+
+ wipememory (tmp, sizeof tmp);
+ return 0;
}
-static void
-do_ctr_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
- unsigned int nbytes )
+static gcry_err_code_t
+do_ctr_decrypt (gcry_cipher_hd_t c,
+ unsigned char *outbuf, unsigned int outbuflen,
+ const unsigned char *inbuf, unsigned int inbuflen)
{
- do_ctr_encrypt (c, outbuf, inbuf, nbytes);
+ return do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
}
@@ -1578,45 +1653,38 @@ static gcry_err_code_t
cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
const byte *inbuf, unsigned int inbuflen)
{
- gcry_err_code_t rc = 0;
+ gcry_err_code_t rc;
switch (c->mode)
{
case GCRY_CIPHER_MODE_ECB:
- if (!(inbuflen % c->cipher->blocksize))
- do_ecb_encrypt(c, outbuf, inbuf, inbuflen/c->cipher->blocksize );
- else
- rc = GPG_ERR_INV_ARG;
+ rc = do_ecb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_CBC:
- if (!(inbuflen % c->cipher->blocksize)
- || (inbuflen > c->cipher->blocksize
- && (c->flags & GCRY_CIPHER_CBC_CTS)))
- do_cbc_encrypt(c, outbuf, inbuf, inbuflen );
- else
- rc = GPG_ERR_INV_ARG;
+ rc = do_cbc_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_CFB:
- do_cfb_encrypt(c, outbuf, inbuf, inbuflen );
+ rc = do_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_OFB:
- do_ofb_encrypt(c, outbuf, inbuf, inbuflen );
+ rc = do_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_CTR:
- do_ctr_encrypt(c, outbuf, inbuf, inbuflen );
+ rc = do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_AESWRAP:
- rc = do_aeswrap_encrypt (c, outbuf, outbuflen, inbuf, inbuflen );
+ rc = do_aeswrap_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_STREAM:
c->cipher->stencrypt (&c->context.c,
- outbuf, (byte*)/*arggg*/inbuf, inbuflen );
+ outbuf, (byte*)/*arggg*/inbuf, inbuflen);
+ rc = 0;
break;
case GCRY_CIPHER_MODE_NONE:
@@ -1627,8 +1695,9 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
}
else
{
- if ( inbuf != outbuf )
+ if (inbuf != outbuf)
memmove (outbuf, inbuf, inbuflen);
+ rc = 0;
}
break;
@@ -1652,20 +1721,8 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
{
gcry_err_code_t err;
- if (!in)
- {
- /* Caller requested in-place encryption. */
- err = cipher_encrypt (h, out, outsize, out, outsize);
- }
- else if (outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ?
- h->cipher->blocksize : inlen))
- err = GPG_ERR_BUFFER_TOO_SHORT;
- else if ((h->mode == GCRY_CIPHER_MODE_ECB
- || (h->mode == GCRY_CIPHER_MODE_CBC
- && (! ((h->flags & GCRY_CIPHER_CBC_CTS)
- && (inlen > h->cipher->blocksize)))))
- && (inlen % h->cipher->blocksize))
- err = GPG_ERR_INV_ARG;
+ if (!in) /* Caller requested in-place encryption. */
+ err = cipher_encrypt (h, out, outsize, out, outsize);
else
err = cipher_encrypt (h, out, outsize, in, inlen);
@@ -1682,51 +1739,44 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
/****************
* Decrypt INBUF to OUTBUF with the mode selected at open.
* inbuf and outbuf may overlap or be the same.
- * Depending on the mode some some contraints apply to NBYTES.
+ * Depending on the mode some some contraints apply to INBUFLEN.
*/
static gcry_err_code_t
cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
const byte *inbuf, unsigned int inbuflen)
{
- gcry_err_code_t rc = 0;
+ gcry_err_code_t rc;
switch (c->mode)
{
case GCRY_CIPHER_MODE_ECB:
- if (!(inbuflen % c->cipher->blocksize))
- do_ecb_decrypt (c, outbuf, inbuf, inbuflen/c->cipher->blocksize );
- else
- rc = GPG_ERR_INV_ARG;
+ rc = do_ecb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_CBC:
- if (!(inbuflen % c->cipher->blocksize)
- || (inbuflen > c->cipher->blocksize
- && (c->flags & GCRY_CIPHER_CBC_CTS)))
- do_cbc_decrypt (c, outbuf, inbuf, inbuflen );
- else
- rc = GPG_ERR_INV_ARG;
+ rc = do_cbc_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_CFB:
- do_cfb_decrypt (c, outbuf, inbuf, inbuflen );
-
+ rc = do_cfb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
+
case GCRY_CIPHER_MODE_OFB:
- do_ofb_decrypt (c, outbuf, inbuf, inbuflen );
+ rc = do_ofb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_CTR:
- do_ctr_decrypt (c, outbuf, inbuf, inbuflen );
+ rc = do_ctr_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_AESWRAP:
- rc = do_aeswrap_decrypt (c, outbuf, outbuflen, inbuf, inbuflen );
+ rc = do_aeswrap_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
case GCRY_CIPHER_MODE_STREAM:
c->cipher->stdecrypt (&c->context.c,
- outbuf, (byte*)/*arggg*/inbuf, inbuflen );
+ outbuf, (byte*)/*arggg*/inbuf, inbuflen);
+ rc = 0;
break;
case GCRY_CIPHER_MODE_NONE:
@@ -1739,6 +1789,7 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen,
{
if (inbuf != outbuf)
memmove (outbuf, inbuf, inbuflen);
+ rc = 0;
}
break;
@@ -1756,26 +1807,10 @@ gcry_error_t
gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
const void *in, size_t inlen)
{
- gcry_err_code_t err = 0;
+ gcry_err_code_t err;
- if (!in)
- {
- /* Caller requested in-place encryption. */
- err = cipher_decrypt (h, out, outsize, out, outsize);
- }
- else if (outsize < inlen && h->mode != GCRY_CIPHER_MODE_AESWRAP)
- {
- /* Note that do_aeswrap_decrypt does its own length checking.
- Fixme: we should move all buffer length checkings to teh
- actual decryption functions. */
- err = GPG_ERR_BUFFER_TOO_SHORT;
- }
- else if (((h->mode == GCRY_CIPHER_MODE_ECB)
- || ((h->mode == GCRY_CIPHER_MODE_CBC)
- && (! ((h->flags & GCRY_CIPHER_CBC_CTS)
- && (inlen > h->cipher->blocksize)))))
- && (inlen % h->cipher->blocksize) != 0)
- err = GPG_ERR_INV_ARG;
+ if (!in) /* Caller requested in-place encryption. */
+ err = cipher_decrypt (h, out, outsize, out, outsize);
else
err = cipher_decrypt (h, out, outsize, in, inlen);
diff --git a/random/ChangeLog b/random/ChangeLog
index 1c29a7ad..31208b6e 100644
--- a/random/ChangeLog
+++ b/random/ChangeLog
@@ -1,3 +1,10 @@
+2009-12-10 Werner Koch <wk@g10code.com>
+
+ * rndw32.c (system_is_w2000): New.
+ (_gcry_rndw32_gather_random): Set it.
+ (slow_gatherer): Ignore SystemObjectInformation on W2000. Fixes
+ bug#1167.
+
2009-07-09 Werner Koch <wk@g10code.com>
* rndlinux.c (_gcry_rndlinux_gather_random): Print real values for
diff --git a/random/rndw32.c b/random/rndw32.c
index c514019f..d250c061 100644
--- a/random/rndw32.c
+++ b/random/rndw32.c
@@ -245,6 +245,8 @@ static HCRYPTPROV hRNGProv; /* Handle to Intel RNG CSP. */
static int debug_me; /* Debug flag. */
+static int system_is_w2000; /* True if running on W2000. */
+
@@ -643,6 +645,12 @@ slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
{
switch (dwType)
{
+ /* ID 17 = SystemObjectInformation hangs on some win2k systems. */
+ case 17:
+ if (system_is_w2000)
+ continue;
+ break;
+
/* Some information types are write-only (the IDs are shared with
a set-information call), we skip these. */
case 26: case 27: case 38: case 46: case 47: case 48: case 52:
@@ -768,6 +776,7 @@ _gcry_rndw32_gather_random (void (*add)(const void*, size_t,
GetVersionEx( &osvi );
if ( osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
log_fatal ("can only run on a Windows NT platform\n" );
+ system_is_w2000 = (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0);
init_system_rng ();
is_initialized = 1;
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index c8332a6e..e4776cfd 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2009-12-10 Werner Koch <wk@g10code.com>
+
+ * basic.c (check_ctr_cipher): Add some return code checks.
+
+ * benchmark.c (cipher_bench): Merge Stream with ECB column.
+
2009-12-09 Werner Koch <wk@g10code.com>
* aeswrap.c: New.
diff --git a/tests/basic.c b/tests/basic.c
index 53305dda..2cd6d9f8 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -1,5 +1,6 @@
/* basic.c - basic regression tests
- * Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2005, 2008,
+ * 2009 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -459,7 +460,7 @@ check_ctr_cipher (void)
}
if (verbose)
- fprintf (stderr, " checking CTR mode for for %s [%i]\n",
+ fprintf (stderr, " checking CTR mode for %s [%i]\n",
gcry_cipher_algo_name (tv[i].algo),
tv[i].algo);
for (j = 0; tv[i].data[j].inlen; j++)
@@ -493,8 +494,82 @@ check_ctr_cipher (void)
if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen))
fail ("aes-ctr, decrypt mismatch entry %d:%d\n", i, j);
- }
+ }
+
+ /* Now check that we get valid return codes back for good and
+ bad inputs. */
+ err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
+ "1234567890123456", 16);
+ if (err)
+ fail ("aes-ctr, encryption failed for valid input");
+
+ err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
+ "1234567890123456", 15);
+ if (gpg_err_code (err) != GPG_ERR_INV_LENGTH)
+ fail ("aes-ctr, too short input returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
+ "12345678901234567", 17);
+ if (gpg_err_code (err) != GPG_ERR_INV_LENGTH)
+ fail ("aes-ctr, too long input returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_encrypt (hde, out, 15,
+ "1234567890123456", 16);
+ if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
+ fail ("aes-ctr, too short output buffer returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_encrypt (hde, out, 0,
+ "1234567890123456", 16);
+ if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
+ fail ("aes-ctr, 0 length output buffer returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_encrypt (hde, out, 16,
+ "1234567890123456", 16);
+ if (err)
+ fail ("aes-ctr, correct length output buffer returned error: %s\n",
+ gpg_strerror (err));
+
+ /* Again, now for decryption. */
+ err = gcry_cipher_decrypt (hde, out, MAX_DATA_LEN,
+ "1234567890123456", 16);
+ if (err)
+ fail ("aes-ctr, decryption failed for valid input");
+
+ err = gcry_cipher_decrypt (hde, out, MAX_DATA_LEN,
+ "1234567890123456", 15);
+ if (gpg_err_code (err) != GPG_ERR_INV_LENGTH)
+ fail ("aes-ctr, too short input returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_decrypt (hde, out, MAX_DATA_LEN,
+ "12345678901234567", 17);
+ if (gpg_err_code (err) != GPG_ERR_INV_LENGTH)
+ fail ("aes-ctr, too long input returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_decrypt (hde, out, 15,
+ "1234567890123456", 16);
+ if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
+ fail ("aes-ctr, too short output buffer returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_decrypt (hde, out, 0,
+ "1234567890123456", 16);
+ if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
+ fail ("aes-ctr, 0 length output buffer returned wrong error: %s\n",
+ gpg_strerror (err));
+
+ err = gcry_cipher_decrypt (hde, out, 16,
+ "1234567890123456", 16);
+ if (err)
+ fail ("aes-ctr, correct length output buffer returned error: %s\n",
+ gpg_strerror (err));
+
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
diff --git a/tests/benchmark.c b/tests/benchmark.c
index 83ddf373..214858df 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -460,12 +460,12 @@ cipher_bench ( const char *algoname )
size_t allocated_buflen, buflen;
int repetitions;
static struct { int mode; const char *name; int blocked; } modes[] = {
- { GCRY_CIPHER_MODE_ECB, " ECB", 1 },
+ { GCRY_CIPHER_MODE_ECB, " ECB/Stream", 1 },
{ GCRY_CIPHER_MODE_CBC, " CBC", 1 },
{ GCRY_CIPHER_MODE_CFB, " CFB", 0 },
{ GCRY_CIPHER_MODE_OFB, " OFB", 0 },
{ GCRY_CIPHER_MODE_CTR, " CTR", 0 },
- { GCRY_CIPHER_MODE_STREAM, " STREAM", 0 },
+ { GCRY_CIPHER_MODE_STREAM, "", 0 },
{0}
};
int modeidx;
@@ -501,11 +501,13 @@ cipher_bench ( const char *algoname )
printf ("Running each test %d times.\n", cipher_repetitions);
printf ("%-12s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
- printf (" %-15s", modes[modeidx].name );
+ if (*modes[modeidx].name)
+ printf (" %-15s", modes[modeidx].name );
putchar ('\n');
printf ("%-12s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
- printf (" ---------------" );
+ if (*modes[modeidx].name)
+ printf (" ---------------" );
putchar ('\n');
header_printed = 1;
}
@@ -548,10 +550,7 @@ cipher_bench ( const char *algoname )
{
if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
| (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
- {
- printf (" " );
- continue;
- }
+ continue;
for (i=0; i < sizeof buf; i++)
buf[i] = i;