summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-04-11 20:27:46 +0200
committerWerner Koch <wk@gnupg.org>2013-04-11 20:27:46 +0200
commit1f3cfad66456dd6f2e48f20b8eb0c51343449a1c (patch)
tree46076f365f00ae81e800a7a30bdcf3d5ab69192d
parenta4e1f6ae7ea7f140e36c331a362bc299dce08416 (diff)
downloadlibgcrypt-1f3cfad66456dd6f2e48f20b8eb0c51343449a1c.tar.gz
Add gcry_pubkey_get_sexp.
* src/gcrypt.h.in (GCRY_PK_GET_PUBKEY): New. (GCRY_PK_GET_SECKEY): New. (gcry_pubkey_get_sexp): New. * src/visibility.c (gcry_pubkey_get_sexp): New. * src/visibility.h (gcry_pubkey_get_sexp): Mark visible. * src/libgcrypt.def, src/libgcrypt.vers: Add new function. * cipher/pubkey-internal.h: New. * cipher/Makefile.am (libcipher_la_SOURCES): Add new file. * cipher/ecc.c: Include pubkey-internal.h (_gcry_pk_ecc_get_sexp): New. * cipher/pubkey.c: Include pubkey-internal.h and context.h. (_gcry_pubkey_get_sexp): New. * src/context.c (_gcry_ctx_find_pointer): New. * src/cipher-proto.h: Add _gcry_pubkey_get_sexp. * tests/t-mpi-point.c (print_sexp): New. (context_param, basic_ec_math_simplified): Add tests for the new function. * configure.ac (NEED_GPG_ERROR_VERSION): Set to 1.11. (AH_BOTTOM) Add error codes from gpg-error 1.12 * src/g10lib.h (fips_not_operational): Use GPG_ERR_NOT_OPERATIONAL. * mpi/ec.c (_gcry_mpi_ec_get_mpi): Fix computation of Q. (_gcry_mpi_ec_get_point): Ditto. -- While checking the new code I figured that the auto-computation of Q must have led to a segv. It seems we had no test case for that. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--NEWS4
-rw-r--r--cipher/Makefile.am3
-rw-r--r--cipher/ecc.c74
-rw-r--r--cipher/pubkey-internal.h29
-rw-r--r--cipher/pubkey.c45
-rw-r--r--configure.ac16
-rw-r--r--doc/gcrypt.texi44
-rw-r--r--mpi/ec.c10
-rw-r--r--src/cipher-proto.h6
-rw-r--r--src/context.c19
-rw-r--r--src/context.h1
-rw-r--r--src/g10lib.h2
-rw-r--r--src/gcrypt.h.in7
-rw-r--r--src/libgcrypt.def2
-rw-r--r--src/libgcrypt.vers2
-rw-r--r--src/visibility.c11
-rw-r--r--src/visibility.h1
-rw-r--r--tests/t-mpi-point.c104
18 files changed, 367 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index 926e531e..c4f89c17 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,8 @@ Noteworthy changes in version 1.6.0 (unreleased)
------------------------------------------------
* Removed the long deprecated gcry_ac interface. Thus Libgcrypt is
- not anymore ABI compatible too previous versions.
+ not anymore ABI compatible to previous versions if they used the ac
+ interface.
* Removed the module register subsystem.
@@ -61,6 +62,7 @@ Noteworthy changes in version 1.6.0 (unreleased)
GCRYMPI_FLAG_CONST NEW.
GCRYPT_VERSION_NUMBER NEW.
GCRY_KDF_SCRYPT NEW.
+ gcry_pubkey_get_sexp NEW.
Noteworthy changes in version 1.5.0 (2011-06-29)
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index 51897949..396e5a2a 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -40,7 +40,8 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES)
libcipher_la_SOURCES = \
cipher.c cipher-internal.h \
cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \
-pubkey.c md.c \
+pubkey.c pubkey-internal.h \
+md.c \
kdf.c kdf-internal.h \
hmac-tests.c \
bithelp.h \
diff --git a/cipher/ecc.c b/cipher/ecc.c
index fbd8c6a3..34ed2c38 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -66,6 +66,7 @@
#include "cipher.h"
#include "context.h"
#include "ec-context.h"
+#include "pubkey-internal.h"
/* Definition of a curve. */
typedef struct
@@ -1985,6 +1986,79 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
}
+/* This is the wroker function for gcry_pubkey_get_sexp for ECC
+ algorithms. Note that the caller has already stored NULL at
+ R_SEXP. */
+gpg_err_code_t
+_gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
+{
+ gpg_err_code_t rc;
+ gcry_mpi_t mpi_G = NULL;
+ gcry_mpi_t mpi_Q = NULL;
+
+ if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n)
+ return GPG_ERR_BAD_CRYPT_CTX;
+
+ if (mode == GCRY_PK_GET_SECKEY && !ec->d)
+ return GPG_ERR_NO_SECKEY;
+
+ /* Compute the public point if it is missing. */
+ if (!ec->Q && ec->d)
+ {
+ ec->Q = gcry_mpi_point_new (0);
+ _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
+ }
+
+ /* Encode G and Q. */
+ mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
+ if (!mpi_G)
+ {
+ rc = GPG_ERR_BROKEN_PUBKEY;
+ goto leave;
+ }
+ if (!ec->Q)
+ {
+ rc = GPG_ERR_BAD_CRYPT_CTX;
+ goto leave;
+ }
+ mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
+ if (!mpi_Q)
+ {
+ rc = GPG_ERR_BROKEN_PUBKEY;
+ goto leave;
+ }
+
+ /* Fixme: We should return a curve name instead of the parameters if
+ if know that they match a curve. */
+
+ if (ec->d && (!mode || mode == GCRY_PK_GET_SECKEY))
+ {
+ /* Let's return a private key. */
+ rc = gpg_err_code
+ (gcry_sexp_build
+ (r_sexp, NULL,
+ "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))",
+ ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q, ec->d));
+ }
+ else if (ec->Q)
+ {
+ /* Let's return a public key. */
+ rc = gpg_err_code
+ (gcry_sexp_build
+ (r_sexp, NULL,
+ "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
+ ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q));
+ }
+ else
+ rc = GPG_ERR_BAD_CRYPT_CTX;
+
+ leave:
+ mpi_free (mpi_Q);
+ mpi_free (mpi_G);
+ return rc;
+}
+
+
/*
Self-test section.
diff --git a/cipher/pubkey-internal.h b/cipher/pubkey-internal.h
new file mode 100644
index 00000000..0ca17a50
--- /dev/null
+++ b/cipher/pubkey-internal.h
@@ -0,0 +1,29 @@
+/* pubkey-internal.h - Internal defs for pubkey.c
+ * Copyright (C) 2013 g10 code GmbH
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_PUBKEY_INTERNAL_H
+#define GCRY_PUBKEY_INTERNAL_H
+
+
+/*-- ecc.c --*/
+gpg_err_code_t _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode,
+ mpi_ec_t ec);
+
+
+#endif /*GCRY_PUBKEY_INTERNAL_H*/
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 8b6356f8..00317b5b 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -1,6 +1,7 @@
/* pubkey.c - pubkey dispatcher
* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
* 2007, 2008, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
@@ -28,6 +29,8 @@
#include "mpi.h"
#include "cipher.h"
#include "ath.h"
+#include "context.h"
+#include "pubkey-internal.h"
static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result,
@@ -4068,6 +4071,48 @@ gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
}
+/* Return an S-expression representing the context CTX. Depending on
+ the state of that context, the S-expression may either be a public
+ key, a private key or any other object used with public key
+ operations. On success a new S-expression is stored at R_SEXP and
+ 0 is returned, on error NULL is store there and an error code is
+ returned. MODE is either 0 or one of the GCRY_PK_GET_xxx values.
+
+ As of now it only support certain ECC operations because a context
+ object is right now only defined for ECC. Over time this function
+ will be extended to cover more algorithms. Note also that the name
+ of the function is gcry_pubkey_xxx and not gcry_pk_xxx. The idea
+ is that we will eventually provide variants of the existing
+ gcry_pk_xxx functions which will take a context parameter. */
+gcry_err_code_t
+_gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
+{
+ mpi_ec_t ec;
+
+ if (!r_sexp)
+ return GPG_ERR_INV_VALUE;
+ *r_sexp = NULL;
+ switch (mode)
+ {
+ case 0:
+ case GCRY_PK_GET_PUBKEY:
+ case GCRY_PK_GET_SECKEY:
+ break;
+ default:
+ return GPG_ERR_INV_VALUE;
+ }
+ if (!ctx)
+ return GPG_ERR_NO_CRYPT_CTX;
+
+ ec = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_EC);
+ if (ec)
+ return _gcry_pk_ecc_get_sexp (r_sexp, mode, ec);
+
+ return GPG_ERR_WRONG_CRYPT_CTX;
+}
+
+
+
/* Explicitly initialize this module. */
gcry_err_code_t
_gcry_pk_init (void)
diff --git a/configure.ac b/configure.ac
index c5973896..079951db 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# Configure.ac script for Libgcrypt
# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
# 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
-# Copyright (C) 2012 g10 Code GmbH
+# Copyright (C) 2012, 2013 g10 Code GmbH
#
# This file is part of Libgcrypt.
#
@@ -65,7 +65,7 @@ LIBGCRYPT_LT_REVISION=0
# If the API is changed in an incompatible way: increment the next counter.
LIBGCRYPT_CONFIG_API_VERSION=1
-NEED_GPG_ERROR_VERSION=1.8
+NEED_GPG_ERROR_VERSION=1.11
PACKAGE=$PACKAGE_NAME
VERSION=$PACKAGE_VERSION
@@ -105,10 +105,14 @@ AH_BOTTOM([
properly prefixed. */
#define CAMELLIA_EXT_SYM_PREFIX _gcry_
-/* This error code is only available with gpg-error 1.7. Thus
- we define it here with the usual gcry prefix. */
-#define GCRY_GPG_ERR_NOT_OPERATIONAL 176
-
+/* These error codes are used but not defined in the required
+ libgpg-error 1.11. Define them here. */
+#define GPG_ERR_NO_CRYPT_CTX 191
+#define GPG_ERR_WRONG_CRYPT_CTX 192
+#define GPG_ERR_BAD_CRYPT_CTX 193
+#define GPG_ERR_CRYPT_CTX_CONFLICT 194
+#define GPG_ERR_BROKEN_PUBKEY 195
+#define GPG_ERR_BROKEN_SECKEY 196
#endif /*_GCRYPT_CONFIG_H_INCLUDED*/
])
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 888a7408..5d9bd2fc 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -2722,6 +2722,50 @@ algorithm provides them.
@end deftypefun
@c end gcry_pk_genkey
+
+@noindent
+Future versions of Libgcrypt will have extended versions of the public
+key interfaced which will take an additional context to allow for
+pre-computations, special operations, and other optimization. As a
+first step a new function is introduced to help using the ECC
+algorithms in new ways:
+
+@deftypefun gcry_error_t gcry_pubkey_get_sexp (@w{gcry_sexp_t *@var{r_sexp}}, @
+ w{int @var{mode}}, @w{gcry_ctx_t @var{ctx}})
+
+Return an S-expression representing the context @var{ctx}. Depending
+on the state of that context, the S-expression may either be a public
+key, a private key or any other object used with public key
+operations. On success 0 is returned and a new S-expression is stored
+at @var{r_sexp}; on error an error code is returned and NULL is stored
+at @var{r_sexp}. @var{mode} must be one of:
+
+@table @code
+@item 0
+Decide what to return depending on the context. For example if the
+private key parameter is available a private key is returned, if not a
+public key is returned.
+
+@item GCRY_PK_GET_PUBKEY
+Return the public key even if the context has the private key
+parameter.
+
+@item GCRY_PK_GET_SECKEY
+Return the private key or the error @code{GPG_ERR_NO_SECKEY} if it is
+not possible.
+@end table
+
+As of now this function supports only certain ECC operations because a
+context object is right now only defined for ECC. Over time this
+function will be extended to cover more algorithms.
+
+@end deftypefun
+@c end gcry_pubkey_get_sexp
+
+
+
+
+
@c **********************************************************
@c ******************* Hash Functions *********************
@c **********************************************************
diff --git a/mpi/ec.c b/mpi/ec.c
index cd19c81a..c7367069 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -546,7 +546,10 @@ _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy)
{
/* If only the private key is given, compute the public key. */
if (!ec->Q && ec->d && ec->G && ec->p && ec->a)
- _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
+ {
+ ec->Q = gcry_mpi_point_new (0);
+ _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
+ }
if (ec->Q)
return _gcry_mpi_ec_ec2os (ec->Q, ec);
@@ -569,7 +572,10 @@ _gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy)
{
/* If only the private key is given, compute the public key. */
if (!ec->Q && ec->d && ec->G && ec->p && ec->a)
- _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
+ {
+ ec->Q = gcry_mpi_point_new (0);
+ _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
+ }
if (ec->Q)
return point_copy (ec->Q);
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 347681ff..e2f913df 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -121,4 +121,10 @@ gcry_error_t _gcry_hmac_selftest (int algo, int extended,
gcry_error_t _gcry_random_selftest (selftest_report_func_t report);
+
+/*-- pubkey.c --*/
+gcry_err_code_t _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp,
+ int reserved, gcry_ctx_t ctx);
+
+
#endif /*G10_CIPHER_PROTO_H*/
diff --git a/src/context.c b/src/context.c
index 2c02c9c4..1b8090de 100644
--- a/src/context.c
+++ b/src/context.c
@@ -94,6 +94,25 @@ _gcry_ctx_get_pointer (gcry_ctx_t ctx, int type)
return &ctx->u;
}
+/* Return a pointer to the private part of the context CTX. TYPE is
+ the requested context type. Using an explicit type allows to cross
+ check the type and eventually allows to store several private
+ contexts in one context object. In contrast to
+ _gcry_ctx_get_pointer, this function returns NULL if no context for
+ the given type was found. If CTX is NULL the function does not
+ abort but returns NULL. */
+void *
+_gcry_ctx_find_pointer (gcry_ctx_t ctx, int type)
+{
+ if (!ctx)
+ return NULL;
+ if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
+ log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx);
+ if (ctx->type != type)
+ return NULL;
+ return &ctx->u;
+}
+
/* Release the generic context CTX. */
void
diff --git a/src/context.h b/src/context.h
index 72f14d48..875de243 100644
--- a/src/context.h
+++ b/src/context.h
@@ -26,6 +26,7 @@
gcry_ctx_t _gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*));
void *_gcry_ctx_get_pointer (gcry_ctx_t ctx, int type);
+void *_gcry_ctx_find_pointer (gcry_ctx_t ctx, int type);
#endif /*GCRY_CONTEXT_H*/
diff --git a/src/g10lib.h b/src/g10lib.h
index d1bcfa9a..23ea0960 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -394,7 +394,7 @@ void _gcry_fips_signal_error (const char *srcfile,
int _gcry_fips_is_operational (void);
#define fips_is_operational() (_gcry_global_is_operational ())
-#define fips_not_operational() (GCRY_GPG_ERR_NOT_OPERATIONAL)
+#define fips_not_operational() (GPG_ERR_NOT_OPERATIONAL)
int _gcry_fips_test_operational (void);
int _gcry_fips_test_error_or_operational (void);
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 72fb6d33..85213ea4 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -944,6 +944,10 @@ enum gcry_pk_algos
#define GCRY_PK_USAGE_AUTH 8 /* Good for authentication. */
#define GCRY_PK_USAGE_UNKN 128 /* Unknown usage flag. */
+/* Modes used with gcry_pubkey_get_sexp. */
+#define GCRY_PK_GET_PUBKEY 1
+#define GCRY_PK_GET_SECKEY 2
+
/* Encrypt the DATA using the public key PKEY and store the result as
a newly created S-expression at RESULT. */
gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result,
@@ -1007,6 +1011,9 @@ gcry_sexp_t gcry_pk_get_param (int algo, const char *name);
#define gcry_pk_test_algo(a) \
gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
+/* Return an S-expression representing the context CTX. */
+gcry_error_t gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp,
+ int mode, gcry_ctx_t ctx);
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 061c7e36..4da46232 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -232,3 +232,5 @@ EXPORTS
gcry_mpi_ec_dup @209
gcry_mpi_ec_add @210
gcry_mpi_ec_mul @211
+
+ gcry_pubkey_get_sexp @212
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 65959d36..29e46dbe 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -58,6 +58,8 @@ GCRYPT_1.6 {
gcry_pk_testkey; gcry_pk_verify;
gcry_pk_get_curve; gcry_pk_get_param;
+ gcry_pubkey_get_sexp;
+
gcry_kdf_derive;
gcry_prime_check; gcry_prime_generate;
diff --git a/src/visibility.c b/src/visibility.c
index ed68b860..b503be66 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -862,6 +862,17 @@ gcry_pk_get_param (int algo, const char *name)
}
gcry_error_t
+gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
+{
+ if (!fips_is_operational ())
+ {
+ *r_sexp = NULL;
+ return gpg_error (fips_not_operational ());
+ }
+ return gpg_error (_gcry_pubkey_get_sexp (r_sexp, mode, ctx));
+}
+
+gcry_error_t
gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
{
if (!fips_is_operational ())
diff --git a/src/visibility.h b/src/visibility.h
index 031537a1..1564e865 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -494,6 +494,7 @@ MARK_VISIBLE (gcry_pk_map_name)
MARK_VISIBLE (gcry_pk_sign)
MARK_VISIBLE (gcry_pk_testkey)
MARK_VISIBLE (gcry_pk_verify)
+MARK_VISIBLEX(gcry_pubkey_get_sexp)
MARK_VISIBLE (gcry_kdf_derive)
diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c
index a3b6c569..9f7360e2 100644
--- a/tests/t-mpi-point.c
+++ b/tests/t-mpi-point.c
@@ -216,6 +216,23 @@ print_point (const char *text, gcry_mpi_point_t a)
}
+static void
+print_sexp (const char *prefix, gcry_sexp_t a)
+{
+ char *buf;
+ size_t size;
+
+ if (prefix)
+ fputs (prefix, stderr);
+ size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+ buf = gcry_xmalloc (size);
+
+ gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
+ fprintf (stderr, "%.*s", (int)size, buf);
+ gcry_free (buf);
+}
+
+
static gcry_mpi_t
hex2mpi (const char *string)
{
@@ -500,9 +517,34 @@ context_param (void)
gpg_strerror (err));
else
{
+ gcry_sexp_t sexp;
+
get_and_cmp_mpi ("q", sample_p256_q, "NIST P-256", ctx);
get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "NIST P-256",
ctx);
+
+ err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
+ if (err)
+ fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
+ else if (debug)
+ print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
+ gcry_sexp_release (sexp);
+
+ err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
+ if (err)
+ fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
+ gpg_strerror (err));
+ else if (debug)
+ print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
+ gcry_sexp_release (sexp);
+
+ err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
+ if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
+ fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
+ gpg_strerror (err));
+ gcry_sexp_release (sexp);
+
+ gcry_ctx_release (ctx);
}
gcry_sexp_release (keyparam);
@@ -537,7 +579,7 @@ basic_ec_math (void)
gcry_mpi_t d;
gcry_mpi_t x, y, z;
- wherestr = "set_get_point";
+ wherestr = "basic_ec_math";
show ("checking basic math functions for EC\n");
P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
@@ -600,8 +642,9 @@ basic_ec_math_simplified (void)
gcry_mpi_point_t G, Q;
gcry_mpi_t d;
gcry_mpi_t x, y, z;
+ gcry_sexp_t sexp;
- wherestr = "set_get_point";
+ wherestr = "basic_ec_math_simplified";
show ("checking basic math functions for EC (variant)\n");
d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
@@ -644,6 +687,63 @@ basic_ec_math_simplified (void)
gcry_mpi_release (z);
gcry_mpi_release (y);
gcry_mpi_release (x);
+
+ /* Let us also check wheer we can update the context. */
+ err = gcry_mpi_ec_set_point ("g", G, ctx);
+ if (err)
+ die ("gcry_mpi_ec_set_point(G) failed\n");
+ err = gcry_mpi_ec_set_mpi ("d", d, ctx);
+ if (err)
+ die ("gcry_mpi_ec_set_mpi(d) failed\n");
+
+ /* FIXME: Below we need to check that the returned S-expression is
+ as requested. For now we use manual inspection using --debug. */
+
+ /* Does get_sexp return the private key? */
+ err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
+ if (err)
+ fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
+ else if (verbose)
+ print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
+ gcry_sexp_release (sexp);
+
+ /* Does get_sexp return the public key if requested? */
+ err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
+ if (err)
+ fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err));
+ else if (verbose)
+ print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
+ gcry_sexp_release (sexp);
+
+ /* Does get_sexp return the public key if after d has been deleted? */
+ err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
+ if (err)
+ die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n");
+ err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
+ if (err)
+ fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err));
+ else if (verbose)
+ print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp);
+ gcry_sexp_release (sexp);
+
+ /* Does get_sexp return an error after d has been deleted? */
+ err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
+ if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
+ fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
+ gpg_strerror (err));
+ gcry_sexp_release (sexp);
+
+ /* Does get_sexp return an error after d and Q have been deleted? */
+ err = gcry_mpi_ec_set_point ("q", NULL, ctx);
+ if (err)
+ die ("gcry_mpi_ec_set_point(q=NULL) failed\n");
+ err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
+ if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX)
+ fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n",
+ gpg_strerror (err));
+ gcry_sexp_release (sexp);
+
+
gcry_mpi_point_release (Q);
gcry_mpi_release (d);
gcry_mpi_point_release (G);