summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO6
-rw-r--r--cipher/ChangeLog9
-rw-r--r--cipher/ecc.c108
-rw-r--r--cipher/pubkey.c62
-rw-r--r--cipher/rsa.c41
-rw-r--r--doc/gcrypt.texi8
-rw-r--r--mpi/mpicoder.c4
-rw-r--r--src/ChangeLog8
-rw-r--r--src/cipher-proto.h5
-rw-r--r--src/fips.c7
-rw-r--r--tests/ChangeLog4
-rw-r--r--tests/keygrip.c70
12 files changed, 277 insertions, 55 deletions
diff --git a/TODO b/TODO
index 43310273..1d61390d 100644
--- a/TODO
+++ b/TODO
@@ -12,10 +12,6 @@ What's left to do -*- outline -*-
This requires the introduction of a parameter names (say) U which
is calculated according to OpenSSL/PKCS#1 rules.
-* Add a warning to the manual, to check that libgcrypt actually has
- been compiled with thread support when used by a threaded
- application.
-
* linker script test
Write an autoconf test to check whether the linker supports a
version script.
@@ -97,5 +93,3 @@ What's left to do -*- outline -*-
** C++ tests
We have some code to allow using libgcrypt from C++, so we also
should have a test case.
-
-* The prime generator always uses very-strong-random.
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 28fdf072..a026bad6 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,12 @@
+2008-08-29 Werner Koch <wk@g10code.com>
+
+ * pubkey.c (gcry_pk_get_keygrip): Remove the special case for RSA
+ and check whether a custom computation function has been setup.
+ * rsa.c (compute_keygrip): New.
+ (_gcry_pubkey_extraspec_rsa): Setup this function.
+ * ecc.c (compute_keygrip): New.
+ (_gcry_pubkey_extraspec_ecdsa): Setup this function.
+
2008-08-28 Werner Koch <wk@g10code.com>
* cipher.c (cipher_decrypt, cipher_encrypt): Return an error if
diff --git a/cipher/ecc.c b/cipher/ecc.c
index c75fd4ef..5d5c322e 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1182,6 +1182,110 @@ ecc_get_nbits (int algo, gcry_mpi_t *pkey)
}
+
+/* See rsa.c for a description of this function. */
+static gpg_err_code_t
+compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
+{
+ gpg_err_code_t ec = 0;
+ gcry_sexp_t l1;
+ static const char const names[] = "pabgnq";
+ gcry_mpi_t values[6];
+ int idx;
+
+ /* Clear the values for easier error cleanup. */
+ for (idx=0; idx < 6; idx++)
+ values[idx] = NULL;
+
+ /* Fill values with all available parameters. */
+ for (idx=0; idx < 6; idx++)
+ {
+ l1 = gcry_sexp_find_token (keyparam, names+idx, 1);
+ if (l1)
+ {
+ values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release (l1);
+ if (!values[idx])
+ {
+ ec = GPG_ERR_INV_OBJ;
+ goto leave;
+ }
+ }
+ }
+
+ /* Check whether a curve parameter is available and use that to fill
+ in missing values. */
+ l1 = gcry_sexp_find_token (keyparam, "curve", 5);
+ if (l1)
+ {
+ char *curve;
+ gcry_mpi_t tmpvalues[6];
+
+ for (idx = 0; idx < 6; idx++)
+ tmpvalues[idx] = NULL;
+
+ curve = _gcry_sexp_nth_string (l1, 1);
+ if (!curve)
+ {
+ ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
+ goto leave;
+ }
+ ec = _gcry_ecc_get_param (curve, tmpvalues);
+ gcry_free (curve);
+ if (ec)
+ goto leave;
+
+ for (idx = 0; idx < 6; idx++)
+ {
+ if (!values[idx])
+ values[idx] = tmpvalues[idx];
+ else
+ mpi_free (tmpvalues[idx]);
+ }
+ }
+
+ /* Check that all parameters are known and normalize all MPIs (that
+ should not be required but we use an internal fucntion later and
+ thus we better make 100% sure that they are normalized). */
+ for (idx = 0; idx < 6; idx++)
+ if (!values[idx])
+ {
+ ec = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
+ else
+ _gcry_mpi_normalize (values[idx]);
+
+ /* Hash them all. */
+ for (idx = 0; idx < 6; idx++)
+ {
+ char buf[30];
+ unsigned char *rawmpi;
+ unsigned int rawmpilen;
+
+ rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL);
+ if (!rawmpi)
+ {
+ ec = gpg_err_code_from_syserror ();
+ goto leave;
+ }
+ snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
+ gcry_md_write (md, buf, strlen (buf));
+ gcry_md_write (md, rawmpi, rawmpilen);
+ gcry_md_write (md, ")", 1);
+ gcry_free (rawmpi);
+ }
+
+ leave:
+ for (idx = 0; idx < 6; idx++)
+ _gcry_mpi_release (values[idx]);
+
+ return ec;
+}
+
+
+
+
/*
Self-test section.
@@ -1254,6 +1358,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
};
pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa =
{
- run_selftests
+ run_selftests,
+ NULL,
+ compute_keygrip
};
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 8c35390d..74a40cc5 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -878,7 +878,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
const char *name;
gcry_sexp_t list;
- /* Clear the array for easir error cleanup. */
+ /* Clear the array for easier error cleanup. */
for (name = element_names, idx = 0; *name; name++, idx++)
elements[idx] = NULL;
gcry_assert (idx >= 6); /* We know that ECC has at least 6 elements. */
@@ -2432,10 +2432,10 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
gcry_sexp_t list = NULL, l2 = NULL;
gcry_pk_spec_t *pubkey = NULL;
gcry_module_t module = NULL;
+ pk_extra_spec_t *extraspec;
const char *s;
char *name = NULL;
int idx;
- int is_rsa;
const char *elems;
gcry_md_hd_t md = NULL;
@@ -2469,53 +2469,45 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
goto fail; /* Unknown algorithm. */
pubkey = (gcry_pk_spec_t *) module->spec;
+ extraspec = module->extraspec;
- /* FIXME, special handling should be implemented by the algorithms,
- not by the libgcrypt core. */
- is_rsa = module->mod_id == GCRY_PK_RSA;
elems = pubkey->elements_grip;
- if (! elems)
+ if (!elems)
goto fail; /* No grip parameter. */
if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
goto fail;
-#if USE_ECC
-# ifdef __GNUC__
-# warning needs to be fixed for ECC.
-# endif
-#endif
-
- for (idx = 0, s = elems; *s; s++, idx++)
+ if (extraspec && extraspec->comp_keygrip)
{
- const char *data;
- size_t datalen;
-
- l2 = gcry_sexp_find_token (list, s, 1);
- if (! l2)
- goto fail;
- data = gcry_sexp_nth_data (l2, 1, &datalen);
- if (! data)
+ /* Module specific method to compute a keygrip. */
+ if (extraspec->comp_keygrip (md, list))
goto fail;
- if (!is_rsa)
+ }
+ else
+ {
+ /* Generic method to compute a keygrip. */
+ for (idx = 0, s = elems; *s; s++, idx++)
{
+ const char *data;
+ size_t datalen;
char buf[30];
-
- sprintf (buf, "(1:%c%u:", *s, (unsigned int)datalen);
+
+ l2 = gcry_sexp_find_token (list, s, 1);
+ if (! l2)
+ goto fail;
+ data = gcry_sexp_nth_data (l2, 1, &datalen);
+ if (! data)
+ goto fail;
+
+ snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
gcry_md_write (md, buf, strlen (buf));
+ gcry_md_write (md, data, datalen);
+ gcry_sexp_release (l2);
+ gcry_md_write (md, ")", 1);
}
-
- /* PKCS-15 says that for RSA only the modulus should be hashed -
- however, it is not clear wether this is meant to use the raw
- bytes (assuming this is an unsigned integer) or whether the DER
- required 0 should be prefixed. We hash the raw bytes. For
- non-RSA we hash S-expressions. */
- gcry_md_write (md, data, datalen);
- gcry_sexp_release (l2);
- if (!is_rsa)
- gcry_md_write (md, ")", 1);
}
-
+
if (!array)
{
array = gcry_malloc (20);
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 8ca8f314..9a7b94df 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -686,6 +686,44 @@ _gcry_rsa_get_nbits (int algo, gcry_mpi_t *pkey)
}
+/* Compute a keygrip. MD is the hash context which we are going to
+ update. KEYPARAM is an S-expression with the key parameters, this
+ is usually a public key but may also be a secret key. An example
+ of such an S-expression is:
+
+ (rsa
+ (n #00B...#)
+ (e #010001#))
+
+ PKCS-15 says that for RSA only the modulus should be hashed -
+ however, it is not clear wether this is meant to use the raw bytes
+ (assuming this is an unsigned integer) or whether the DER required
+ 0 should be prefixed. We hash the raw bytes. */
+static gpg_err_code_t
+compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
+{
+ gcry_sexp_t l1;
+ const char *data;
+ size_t datalen;
+
+ l1 = gcry_sexp_find_token (keyparam, "n", 1);
+ if (!l1)
+ return GPG_ERR_NO_OBJ;
+
+ data = gcry_sexp_nth_data (l1, 1, &datalen);
+ if (!data)
+ {
+ gcry_sexp_release (l1);
+ return GPG_ERR_NO_OBJ;
+ }
+
+ gcry_md_write (md, data, datalen);
+ gcry_sexp_release (l1);
+
+ return 0;
+}
+
+
/*
@@ -761,6 +799,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_rsa =
pk_extra_spec_t _gcry_pubkey_extraspec_rsa =
{
run_selftests,
- rsa_generate
+ rsa_generate,
+ compute_keygrip
};
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index b3daa07e..55fae683 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -529,10 +529,10 @@ Libgcrypt into this mode:
@itemize
@item
-If the file @file{/proc/fips140} exists and contains the string value
-@code{1}, Libgcrypt is put into FIPS mode at initialization time.
-Obviously this works only on systems with a @code{proc} file system
-(ie.e GNU/Linux).
+If the file @file{/proc/sys/crypto/fips_enabled} exists and contains a
+numeric value other than @code{0}, Libgcrypt is put into FIPS mode at
+initialization time. Obviously this works only on systems with a
+@code{proc} file system (ie.e GNU/Linux).
@item
If the file @file{/etc/gcrypt/fips140.force} exists, Libgcrypt is put
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index 0c19941b..d8f860ce 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -247,8 +247,8 @@ do_get_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign, int force_secure )
#endif
}
- /* this is sub-optimal but we need to do the shift oepration because
- * the caller has to free the returned buffer */
+ /* This is sub-optimal but we need to do the shift operation
+ because the caller has to free the returned buffer */
for(p=buffer; !*p && *nbytes; p++, --*nbytes )
;
if( p != buffer )
diff --git a/src/ChangeLog b/src/ChangeLog
index d72ef544..be3cc2ea 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2008-08-29 Werner Koch <wk@g10code.com>
+
+ * fips.c (_gcry_initialize_fips_mode): Changed /proc file to test
+ for FIPS mode.
+
+ * cipher-proto.h (pk_compute_keygrip_t): New.
+ (pk_extra_spec): Add field comp_keygrip.
+
2008-08-28 Werner Koch <wk@g10code.com>
* hwfeatures.c (_gcry_detect_hw_features): Disable hardware
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 4ca76b55..39a91012 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -48,6 +48,10 @@ typedef gcry_err_code_t (*pk_ext_generate_t)
gcry_mpi_t *skey,
gcry_mpi_t **retfactors);
+/* The type is used to compute the keygrip. */
+typedef gpg_err_code_t (*pk_comp_keygrip_t)
+ (gcry_md_hd_t md, gcry_sexp_t keyparm);
+
/* Extra module specification structures. These are used for internal
modules which provide more functions than available through the
@@ -66,6 +70,7 @@ typedef struct pk_extra_spec
{
selftest_func_t selftest;
pk_ext_generate_t ext_generate;
+ pk_comp_keygrip_t comp_keygrip;
} pk_extra_spec_t;
diff --git a/src/fips.c b/src/fips.c
index c9f29bd2..04b34d87 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -115,13 +115,14 @@ _gcry_initialize_fips_mode (int force)
{
FILE *fp;
int saved_errno;
+ static const char const procfname[] = "/proc/sys/crypto/fips_enabled";
- fp = fopen ("/proc/fips140", "r");
+ fp = fopen (procfname, "r");
if (fp)
{
char line[256];
- if (fgets (line, sizeof line, fp) && atoi (line) == 1)
+ if (fgets (line, sizeof line, fp) && atoi (line))
{
/* System is in fips mode. */
fclose (fp);
@@ -136,7 +137,7 @@ _gcry_initialize_fips_mode (int force)
/* Problem reading the fips file despite that we have the proc
file system. We better stop right away. */
log_info ("FATAL: error reading `%s' in libgcrypt: %s\n",
- "/proc/fips140", strerror (saved_errno));
+ procfname, strerror (saved_errno));
abort ();
}
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index c08d544c..7d91d096 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2008-08-29 Werner Koch <wk@g10code.com>
+
+ * keygrip.c: Update to also check ECDSA.
+
2008-08-28 Werner Koch <wk@g10code.com>
* rsa-16k.key: New sample key.
diff --git a/tests/keygrip.c b/tests/keygrip.c
index 351139f1..e1908ba3 100644
--- a/tests/keygrip.c
+++ b/tests/keygrip.c
@@ -45,15 +45,29 @@ die (const char *format, ...)
exit (1);
}
+static void
+print_hex (const char *text, const void *buf, size_t n)
+{
+ const unsigned char *p = buf;
+
+ fputs (text, stdout);
+ for (; n; n--, p++)
+ printf ("%02X", *p);
+ putchar ('\n');
+}
+
+
static struct
{
+ int algo;
const char *key;
const unsigned char grip[20];
} key_grips[] =
{
{
+ GCRY_PK_RSA,
"(private-key"
" (rsa"
" (n #00B6B509596A9ECABC939212F891E656A626BA07DA8521A9CAD4C08E640C04052FBB87F424EF1A0275A48A9299AC9DB69ABE3D0124E6C756B1F7DFB9B842D6251AEA6EE85390495CADA73D671537FCE5850A932F32BAB60AB1AC1F852C1F83C625E7A7D70CDA9EF16D5C8E47739D77DF59261ABE8454807FF441E143FBD37F8545#)"
@@ -65,6 +79,7 @@ static struct
"\x32\xCF\xFA\x85\xB1\x79\x1F\xBB\x26\x14\xE9\x1A\xFD\xF3\xAF\xE3\x32\x08\x2E\x25"
},
{
+ GCRY_PK_DSA,
" (public-key"
" (dsa"
" (p #0084E4C626E16005770BD9509ABF7354492E85B8C0060EFAAAEC617F725B592FAA59DF5460575F41022776A9718CE62EDD542AB73C7720869EBDBC834D174ADCD7136827DF51E2613545A25CA573BC502A61B809000B6E35F5EB7FD6F18C35678C23EA1C3638FB9CFDBA2800EE1B62F41A4479DE824F2834666FBF8DC5B53C2617#)"
@@ -75,6 +90,7 @@ static struct
},
{
+ GCRY_PK_DSA,
"(private-key"
" (dsa"
" (p #0084E4C626E16005770BD9509ABF7354492E85B8C0060EFAAAEC617F725B592FAA59DF5460575F41022776A9718CE62EDD542AB73C7720869EBDBC834D174ADCD7136827DF51E2613545A25CA573BC502A61B809000B6E35F5EB7FD6F18C35678C23EA1C3638FB9CFDBA2800EE1B62F41A4479DE824F2834666FBF8DC5B53C2617#)"
@@ -83,7 +99,40 @@ static struct
" (y #3D5DD14AFA2BF24A791E285B90232213D0E3BA74AB1109E768AED19639A322F84BB7D959E2BA92EF73DE4C7F381AA9F4053CFA3CD4527EF9043E304E5B95ED0A3A5A9D590AA641C13DB2B6E32B9B964A6A2C730DD3EA7C8E13F7A140AFF1A91CE375E9B9B960384779DC4EA180FA1F827C52288F366C0770A220F50D6D8FD6F6#)"
" (x #0087F9E91BFBCC1163DE71ED86D557708E32F8ADDE#)))",
"\x04\xA3\x4F\xA0\x2B\x03\x94\xD7\x32\xAD\xD5\x9B\x50\xAF\xDB\x5D\x57\x22\xA6\x10"
+ },
+ {
+ GCRY_PK_ECDSA,
+ "(public-key"
+ " (ecdsa"
+ " (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)"
+ " (a #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC#)"
+ " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)"
+ " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)"
+ " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)"
+ " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
+ "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
+ },
+ {
+ GCRY_PK_ECDSA,
+ "(public-key"
+ " (ecdsa"
+ " (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)"
+ " (curve \"NIST P-256\")"
+ " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)"
+ " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)"
+ " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)"
+ " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
+ "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
+ },
+ {
+ GCRY_PK_ECDSA,
+ "(public-key"
+ " (ecdsa"
+ " (curve secp256r1)"
+ " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
+ "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
}
+
};
static void
@@ -97,12 +146,27 @@ check (void)
for (i = 0; i < (sizeof (key_grips) / sizeof (*key_grips)); i++)
{
+ if (gcry_pk_test_algo (key_grips[i].algo))
+ {
+ if (verbose)
+ fprintf (stderr, "algo %d not available; test skipped\n",
+ key_grips[i].algo);
+ continue;
+ }
err = gcry_sexp_sscan (&sexp, NULL, key_grips[i].key,
strlen (key_grips[i].key));
- assert (! err);
+ if (err)
+ die ("scanning data %d failed: %s\n", i, gpg_strerror (err));
ret = gcry_pk_get_keygrip (sexp, buf);
- assert (ret);
- assert (! memcmp (key_grips[i].grip, buf, sizeof (buf)));
+ if (!ret)
+ die ("gcry_pk_get_keygrip failed for %d\n", i);
+
+ if ( memcmp (key_grips[i].grip, buf, sizeof (buf)) )
+ {
+ print_hex ("keygrip: ", buf, sizeof buf);
+ die ("keygrip for %d does not match\n", i);
+ }
+
gcry_sexp_release (sexp);
}
}