summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-11-05 17:21:57 +0000
committerWerner Koch <wk@gnupg.org>2008-11-05 17:21:57 +0000
commit76116202872239eaa02a92f08a2f5bd69325debc (patch)
tree5f7c0b6ec158567b38497bcea6edf06bc68e9d11
parent179d9f61f703cbfccd171257c390cfa197723be9 (diff)
downloadlibgcrypt-76116202872239eaa02a92f08a2f5bd69325debc.tar.gz
Add a method to disable the weak key detection.
Add a method to return the current input block. Use this in the FIPS driver.
-rw-r--r--NEWS2
-rw-r--r--cipher/ChangeLog11
-rw-r--r--cipher/cipher.c42
-rw-r--r--cipher/des.c37
-rw-r--r--src/ChangeLog7
-rw-r--r--src/cipher-proto.h5
-rw-r--r--src/cipher.h2
-rw-r--r--src/fips.c4
-rw-r--r--src/gcrypt.h.in2
-rw-r--r--src/global.c6
-rw-r--r--tests/ChangeLog4
-rw-r--r--tests/fipsdrv.c111
12 files changed, 196 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index 76dada39..9587a011 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,7 @@ Noteworthy changes in version 1.4.4
------------------------------------------------
* Publish GCRY_MODULE_ID_USER and GCRY_MODULE_ID_USER_LAST constants.
- This functionality is in Libgcrypt since 1.3.0.
+ This functionality has been in Libgcrypt since 1.3.0.
* MD5 may now be used in non-enforced fips mode.
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 6e24cfc0..3ec9050b 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,14 @@
+2008-11-05 Werner Koch <wk@g10code.com>
+
+ * cipher.c (gcry_cipher_handle): Add field EXTRASPEC.
+ (gcry_cipher_open): Set it.
+ (gcry_cipher_ctl): Add private control code to disable weak key
+ detection and to return the current input block.
+ * des.c (_tripledes_ctx): Add field FLAGS.
+ (do_tripledes_set_extra_info): New.
+ (_gcry_cipher_extraspec_tripledes): Add new function.
+ (do_tripledes_setkey): Disable weak key detection.
+
2008-10-24 Werner Koch <wk@g10code.com>
* md.c (digest_table): Allow MD5 in fips mode.
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 77682ce6..2c33ee94 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -161,6 +161,7 @@ struct gcry_cipher_handle
size_t actual_handle_size; /* Allocated size of this handle. */
size_t handle_offset; /* Offset to the malloced block. */
gcry_cipher_spec_t *cipher;
+ cipher_extra_spec_t *extraspec;
gcry_module_t module;
/* The algorithm id. This is a hack required because the module
@@ -669,6 +670,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
{
int secure = (flags & GCRY_CIPHER_SECURE);
gcry_cipher_spec_t *cipher = NULL;
+ cipher_extra_spec_t *extraspec = NULL;
gcry_module_t module = NULL;
gcry_cipher_hd_t h = NULL;
gcry_err_code_t err = 0;
@@ -694,7 +696,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
_gcry_module_release (module);
}
else
- cipher = (gcry_cipher_spec_t *) module->spec;
+ {
+ cipher = (gcry_cipher_spec_t *) module->spec;
+ extraspec = module->extraspec;
+ }
}
else
err = GPG_ERR_CIPHER_ALGO;
@@ -731,7 +736,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
break;
case GCRY_CIPHER_MODE_NONE:
- /* This mode may be used for debbuging. It copies the main
+ /* This mode may be used for debugging. It copies the main
text verbatim to the ciphertext. We do not allow this in
fips mode or if no debug flag has been set. */
if (fips_mode () || !_gcry_get_debug_flag (0))
@@ -783,6 +788,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
h->actual_handle_size = size - off;
h->handle_offset = off;
h->cipher = cipher;
+ h->extraspec = extraspec;
h->module = module;
h->algo = algo;
h->mode = mode;
@@ -1681,6 +1687,38 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
rc = GPG_ERR_INV_ARG;
break;
+ case 61: /* Disable weak key detection (private). */
+ if (h->extraspec->set_extra_info)
+ rc = h->extraspec->set_extra_info
+ (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0);
+ else
+ rc = GPG_ERR_NOT_SUPPORTED;
+ break;
+
+ case 62: /* Return current input vector (private). */
+ /* This is the input block as used in CFB and OFB mode which has
+ initially been set as IV. The returned format is:
+ 1 byte Actual length of the block in bytes.
+ n byte The block.
+ If the provided buffer is too short, an error is returned. */
+ if (buflen < (1 + h->cipher->blocksize))
+ rc = GPG_ERR_TOO_SHORT;
+ else
+ {
+ unsigned char *ivp;
+ unsigned char *dst = buffer;
+ int n = h->unused;
+
+ if (!n)
+ n = h->cipher->blocksize;
+ gcry_assert (n <= h->cipher->blocksize);
+ *dst++ = n;
+ ivp = h->u_iv.iv + h->cipher->blocksize - n;
+ while (n--)
+ *dst++ = *ivp++;
+ }
+ break;
+
default:
rc = GPG_ERR_INV_OP;
}
diff --git a/cipher/des.c b/cipher/des.c
index 5839df16..f91df777 100644
--- a/cipher/des.c
+++ b/cipher/des.c
@@ -1,5 +1,6 @@
/* des.c - DES and Triple-DES encryption/decryption Algorithm
- * Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2001, 2002, 2003,
+ * 2008 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -152,6 +153,9 @@ typedef struct _tripledes_ctx
{
u32 encrypt_subkeys[96];
u32 decrypt_subkeys[96];
+ struct {
+ int no_weak_key;
+ } flags;
}
tripledes_ctx[1];
@@ -1013,7 +1017,9 @@ do_tripledes_setkey ( void *context, const byte *key, unsigned keylen )
tripledes_set3keys ( ctx, key, key+8, key+16);
- if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) )
+ if (ctx->flags.no_weak_key)
+ ; /* Detection has been disabled. */
+ else if (is_weak_key (key) || is_weak_key (key+8) || is_weak_key (key+16))
{
_gcry_burn_stack (64);
return GPG_ERR_WEAK_KEY;
@@ -1024,6 +1030,30 @@ do_tripledes_setkey ( void *context, const byte *key, unsigned keylen )
}
+static gcry_err_code_t
+do_tripledes_set_extra_info (void *context, int what,
+ const void *buffer, size_t buflen)
+{
+ struct _tripledes_ctx *ctx = (struct _tripledes_ctx *)context;
+ gpg_err_code_t ec = 0;
+
+ (void)buffer;
+ (void)buflen;
+
+ switch (what)
+ {
+ case CIPHER_INFO_NO_WEAK_KEY:
+ ctx->flags.no_weak_key = 1;
+ break;
+
+ default:
+ ec = GPG_ERR_INV_OP;
+ break;
+ }
+ return ec;
+}
+
+
static void
do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf )
{
@@ -1161,5 +1191,6 @@ gcry_cipher_spec_t _gcry_cipher_spec_tripledes =
cipher_extra_spec_t _gcry_cipher_extraspec_tripledes =
{
- run_selftests
+ run_selftests,
+ do_tripledes_set_extra_info
};
diff --git a/src/ChangeLog b/src/ChangeLog
index 86fd72d3..c255fda2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2008-11-05 Werner Koch <wk@g10code.com>
+
+ * cipher.h (CIPHER_INFO_NO_WEAK_KEY): New.
+
+ * cipher-proto.h (cipher_set_extra_info_t): New.
+ (cipher_extra_spec): Add field SET_EXTRA_INFO.
+
2008-10-30 Werner Koch <wk@g10code.com>
* g10lib.h (GCC_ATTR_FORMAT_ARG): New.
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 43ed0886..975a2a11 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -55,6 +55,10 @@ typedef gcry_err_code_t (*pk_ext_generate_t)
typedef gpg_err_code_t (*pk_comp_keygrip_t)
(gcry_md_hd_t md, gcry_sexp_t keyparm);
+/* The type used to convey additional information to a cipher. */
+typedef gpg_err_code_t (*cipher_set_extra_info_t)
+ (void *c, int what, const void *buffer, size_t buflen);
+
/* Extra module specification structures. These are used for internal
modules which provide more functions than available through the
@@ -62,6 +66,7 @@ typedef gpg_err_code_t (*pk_comp_keygrip_t)
typedef struct cipher_extra_spec
{
selftest_func_t selftest;
+ cipher_set_extra_info_t set_extra_info;
} cipher_extra_spec_t;
typedef struct md_extra_spec
diff --git a/src/cipher.h b/src/cipher.h
index 3e0ba9d2..f84d9ad7 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -29,6 +29,8 @@
#define PUBKEY_FLAG_NO_BLINDING (1 << 0)
#define PUBKEY_FLAG_TRANSIENT_KEY (1 << 1)
+#define CIPHER_INFO_NO_WEAK_KEY 1
+
#include "cipher-proto.h"
diff --git a/src/fips.c b/src/fips.c
index f2d898b1..6e0c9ece 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -262,8 +262,8 @@ unlock_fsm (void)
int
_gcry_fips_mode (void)
{
- /* No locking is required becuase we have the requirement that this
- variable is only intialized once with no other threads
+ /* No locking is required because we have the requirement that this
+ variable is only initialized once with no other threads
existing. */
return !no_fips_mode_required;
}
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index ae34d106..864a300a 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -410,7 +410,7 @@ enum gcry_ctl_cmds
GCRYCTL_FIPS_MODE_P = 55,
GCRYCTL_FORCE_FIPS_MODE = 56,
GCRYCTL_SELFTEST = 57
- /* Note: 58, 59 and 60 are used internally. */
+ /* Note: 58 .. 62 are used internally. */
};
/* Perform various operations defined by CMD. */
diff --git a/src/global.c b/src/global.c
index 3177a02b..d2361de5 100644
--- a/src/global.c
+++ b/src/global.c
@@ -529,7 +529,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
err = _gcry_fips_run_selftests (1);
break;
- case 58:
+ case 58: /* Init external random test. */
{
void **rctx = va_arg (arg_ptr, void **);
unsigned int flags = va_arg (arg_ptr, unsigned int);
@@ -546,7 +546,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
seed, seedlen, dt, dtlen);
}
break;
- case 59:
+ case 59: /* Run external random test. */
{
void *ctx = va_arg (arg_ptr, void *);
void *buffer = va_arg (arg_ptr, void *);
@@ -557,7 +557,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
err = _gcry_random_run_external_test (ctx, buffer, buflen);
}
break;
- case 60:
+ case 60: /* Deinit external random test. */
{
void *ctx = va_arg (arg_ptr, void *);
_gcry_random_deinit_external_test (ctx);
diff --git a/tests/ChangeLog b/tests/ChangeLog
index d0198cd1..c438778a 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2008-11-05 Werner Koch <wk@g10code.com>
+
+ * fipsdrv.c (run_encrypt_decrypt): Disable weak key detection.
+
2008-10-31 Werner Koch <wk@g10code.com>
* fipsdrv.c (run_rsa_sign): Buffer needs to be larger for SHA512.
diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c
index 6d83aaf5..fdffdbbf 100644
--- a/tests/fipsdrv.c
+++ b/tests/fipsdrv.c
@@ -48,6 +48,13 @@
#define DIMof(type,member) DIM(((type *)0)->member)
+#define PRIV_CTL_INIT_EXTRNG_TEST 58
+#define PRIV_CTL_RUN_EXTRNG_TEST 59
+#define PRIV_CTL_DEINIT_EXTRNG_TEST 60
+#define PRIV_CTL_DISABLE_WEAK_KEY 61
+#define PRIV_CTL_GET_INPUT_VECTOR 62
+
+
/* Verbose mode flag. */
static int verbose;
@@ -63,6 +70,10 @@ static int base64_output;
/* We need to know whetehr we are in loop_mode. */
static int loop_mode;
+/* If true the input vectors are printed before and after encryption
+ and decryption. */
+static int print_ivs;
+
/* ASN.1 classes. */
enum
{
@@ -747,7 +758,7 @@ init_external_rng_test (void **r_context,
const void *seed, size_t seedlen,
const void *dt, size_t dtlen)
{
- return gcry_control (58,
+ return gcry_control (PRIV_CTL_INIT_EXTRNG_TEST,
r_context, flags,
key, keylen,
seed, seedlen,
@@ -757,13 +768,13 @@ init_external_rng_test (void **r_context,
static gcry_error_t
run_external_rng_test (void *context, void *buffer, size_t buflen)
{
- return gcry_control (59, context, buffer, buflen);
+ return gcry_control (PRIV_CTL_RUN_EXTRNG_TEST, context, buffer, buflen);
}
static void
deinit_external_rng_test (void *context)
{
- gcry_control (60, context);
+ gcry_control (PRIV_CTL_DEINIT_EXTRNG_TEST, context);
}
@@ -856,12 +867,18 @@ run_encrypt_decrypt (int encrypt_mode,
size_t outbuflen;
void *inbuf;
size_t inbuflen;
+ size_t blocklen;
err = gcry_cipher_open (&hd, cipher_algo, cipher_mode, 0);
if (err)
die ("gcry_cipher_open failed for algo %d, mode %d: %s\n",
cipher_algo, cipher_mode, gpg_strerror (err));
+ blocklen = gcry_cipher_get_algo_blklen (cipher_algo);
+ assert (blocklen);
+
+ gcry_cipher_ctl (hd, PRIV_CTL_DISABLE_WEAK_KEY, NULL, 0);
+
err = gcry_cipher_setkey (hd, key_buffer, key_buflen);
if (err)
die ("gcry_cipher_setkey failed with keylen %u: %s\n",
@@ -877,7 +894,7 @@ run_encrypt_decrypt (int encrypt_mode,
inbuf = data? NULL : gcry_xmalloc (datalen);
outbuflen = datalen;
- outbuf = gcry_xmalloc (outbuflen);
+ outbuf = gcry_xmalloc (outbuflen < blocklen? blocklen:outbuflen);
do
{
@@ -892,14 +909,52 @@ run_encrypt_decrypt (int encrypt_mode,
else
inbuflen = datalen;
- if (encrypt_mode)
- err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, inbuflen);
+ if (print_ivs)
+ {
+ /* If we want to print the input vectors we need to pass the
+ data block by block to the encryption function. */
+ unsigned char tmp[17];
+ const unsigned char *iptr = data;
+ size_t ilen;
+
+ do
+ {
+ ilen = inbuflen > blocklen? blocklen : inbuflen;
+
+ if (gcry_cipher_ctl (hd, PRIV_CTL_GET_INPUT_VECTOR,
+ tmp, sizeof tmp))
+ die ("error getting input block\n");
+ print_buffer (tmp+1, *tmp);
+ putchar ('\n');
+
+ if (encrypt_mode)
+ err = gcry_cipher_encrypt (hd, outbuf, blocklen, iptr, ilen);
+ else
+ err = gcry_cipher_decrypt (hd, outbuf, blocklen, iptr, ilen);
+ if (err)
+ die ("gcry_cipher_%scrypt failed: %s\n",
+ encrypt_mode? "en":"de", gpg_strerror (err));
+
+ print_buffer (outbuf, blocklen);
+ putchar ('\n');
+
+ iptr += ilen;
+ inbuflen -= ilen;
+ }
+ while (inbuflen);
+ }
else
- err = gcry_cipher_decrypt (hd, outbuf, outbuflen, data, inbuflen);
- if (err)
- die ("gcry_cipher_%scrypt failed: %s\n",
- encrypt_mode? "en":"de", gpg_strerror (err));
- print_buffer (outbuf, outbuflen);
+ {
+ if (encrypt_mode)
+ err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, inbuflen);
+ else
+ err = gcry_cipher_decrypt (hd, outbuf, outbuflen, data, inbuflen);
+ if (err)
+ die ("gcry_cipher_%scrypt failed: %s\n",
+ encrypt_mode? "en":"de", gpg_strerror (err));
+
+ print_buffer (outbuf, outbuflen);
+ }
}
while (inbuf);
@@ -1301,20 +1356,21 @@ usage (int show_help)
"MODE:\n"
" encrypt, decrypt, digest, random, hmac-sha, rsa-{gen,sign,verify}\n"
"OPTIONS:\n"
- " --verbose print additional information\n"
- " --binary input and output is in binary form\n"
- " --no-fips do not force FIPS mode\n"
- " --key KEY use the hex encoded KEY\n"
- " --iv IV use the hex encoded IV\n"
- " --dt DT use the hex encoded DT for the RNG\n"
- " --algo NAME use algorithm NAME\n"
- " --keysize N use a keysize of N bits\n"
- " --signature NAME take signature from file NAME\n"
- " --chunk N read in chunks of N bytes (implies --binary)\n"
- " --pkcs1 use PKCS#1 encoding\n"
- " --loop enable random loop mode\n"
- " --progress print pogress indicators\n"
- " --help print this text\n"
+ " --verbose Print additional information\n"
+ " --binary Input and output is in binary form\n"
+ " --no-fips Do not force FIPS mode\n"
+ " --key KEY Use the hex encoded KEY\n"
+ " --iv IV Use the hex encoded IV\n"
+ " --dt DT Use the hex encoded DT for the RNG\n"
+ " --algo NAME Use algorithm NAME\n"
+ " --keysize N Use a keysize of N bits\n"
+ " --signature NAME Take signature from file NAME\n"
+ " --chunk N Read in chunks of N bytes (implies --binary)\n"
+ " --pkcs1 Use PKCS#1 encoding\n"
+ " --print-ivs Print input vectors\n"
+ " --loop Enable random loop mode\n"
+ " --progress Print pogress indicators\n"
+ " --help Print this text\n"
"With no FILE, or when FILE is -, read standard input.\n"
"Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout);
exit (0);
@@ -1448,6 +1504,11 @@ main (int argc, char **argv)
use_pkcs1 = 1;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--print-ivs"))
+ {
+ print_ivs = 1;
+ argc--; argv++;
+ }
}
if (!argc || argc > 2)