summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2020-01-01 00:00:00 +0100
committerVivien Kraus <vivien@planete-kraus.eu>2021-06-05 16:10:24 +0200
commitd1b71f1ab4e85e7c583fc748888b7a2a46cb1705 (patch)
tree45cda9d5c252ac7da49e7f7a05c4f7ba6017985d
parent8df0af8301aca112804768f532a4a62dcf3d61d6 (diff)
Generate a key pair.
-rw-r--r--ChangeLog1
-rw-r--r--NEWS2
-rw-r--r--po/ChangeLog1
-rw-r--r--po/POTFILES.in2
-rw-r--r--po/fr.po11
-rw-r--r--po/webid-oidc.pot7
-rw-r--r--src/ChangeLog5
-rw-r--r--src/Makefile.am1
-rw-r--r--src/jwk/ChangeLog8
-rw-r--r--src/jwk/Makefile.am13
-rw-r--r--src/jwk/generate-key.c59
-rw-r--r--src/jwk/libwebidoidc-jwk.c118
-rw-r--r--src/libwebidoidc.c2
-rw-r--r--src/scm/webid-oidc/stubs.scm3
-rw-r--r--src/utilities.h285
15 files changed, 511 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 3a6d4da..484f88a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,7 @@
2020-11-25 Vivien Kraus <vivien@planete-kraus.eu>
* NEWS (A random number generator): Update NEWS
+ (Generating a key pair): Update NEWS
2020-11-22 Vivien Kraus <vivien@planete-kraus.eu>
diff --git a/NEWS b/NEWS
index 0c91be2..9a99d63 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@
** Add base64 encoding and decoding
** A random number generator
The code provides a thread-safe, parallel, random number generator.
+** Generating a key pair
+There is a function to generate a RSA or ECC key pair.
# Local Variables:
# mode: org
diff --git a/po/ChangeLog b/po/ChangeLog
index 7001ddd..aaa33ce 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,6 +1,7 @@
2020-11-25 Vivien Kraus <vivien@planete-kraus.eu>
* POTFILES.in: Put the random submodule in the list.
+ Put the jwk submodule in the list.
2020-11-22 Vivien Kraus <vivien@planete-kraus.eu>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3b2cece..844066a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,4 +3,6 @@ src/libwebidoidc.c
src/random/random.c
src/random/libwebidoidc-random.c
src/random/generate-random.c
+src/jwk/libwebidoidc-jwk.c
+src/jwk/generate-key.c
src/scm/webid-oidc/errors.scm
diff --git a/po/fr.po b/po/fr.po
index 857f50c..b27cff8 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -12,7 +12,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: src/libwebidoidc.c:8
+#: src/libwebidoidc.c:9
msgid "This is the main function."
msgstr "Ceci est la fonction principale."
@@ -121,6 +121,11 @@ msgstr ""
msgid "Usage: generate-random [NUMBER OF BYTES]\n"
msgstr "Utilisation : generate-random [NOMBRE D'OCTETS]\n"
+#: src/jwk/generate-key.c:32
+#, c-format
+msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
+msgstr "Utilisation : generate-key [NOMBRE DE BITS | COURBE]\n"
+
#: src/scm/webid-oidc/errors.scm:35
msgid "that’s how it is"
msgstr "c’est comme ça"
@@ -172,10 +177,6 @@ msgstr "il y a un type et des arguments"
msgid "Unhandled exception type ~a."
msgstr "Type d’exception non pris en charge ~a."
-#, c-format
-#~ msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
-#~ msgstr "Utilisation : generate-key [NOMBRE DE BITS | COURBE]\n"
-
#, scheme-format
#~ msgid "the value ~s is not JSON (because ~a)"
#~ msgstr "la valeur ~s n’est pas du JSON (parce que ~a)"
diff --git a/po/webid-oidc.pot b/po/webid-oidc.pot
index 4c608e8..ee78ff7 100644
--- a/po/webid-oidc.pot
+++ b/po/webid-oidc.pot
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: src/libwebidoidc.c:8
+#: src/libwebidoidc.c:9
msgid "This is the main function."
msgstr ""
@@ -117,6 +117,11 @@ msgstr ""
msgid "Usage: generate-random [NUMBER OF BYTES]\n"
msgstr ""
+#: src/jwk/generate-key.c:32
+#, c-format
+msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
+msgstr ""
+
#: src/scm/webid-oidc/errors.scm:35
msgid "that’s how it is"
msgstr ""
diff --git a/src/ChangeLog b/src/ChangeLog
index e2e9bea..3b99888 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,6 +1,11 @@
2020-11-25 Vivien Kraus <vivien@planete-kraus.eu>
+ * utilities.h: Add functions for the jwk submodule.
+
+ * libwebidoidc.c (init_webidoidc): Initialize the jwk submodule.
+
* Makefile.am (%canon_reldir%_libwebidoidc_la_SOURCES): the common code is considered a source.
+ Build the "jwk" submodule.
* utilities.h: Put the common code in that header.
diff --git a/src/Makefile.am b/src/Makefile.am
index 732a941..1d5f61c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,6 +25,7 @@ install_mod_targets = install-webidoidcmodDATA install-dist_webidoidcmodDATA
include %reldir%/base64/Makefile.am
include %reldir%/random/Makefile.am
+include %reldir%/jwk/Makefile.am
include %reldir%/pre-inst/Makefile.am
include %reldir%/inst/Makefile.am
include %reldir%/scm/Makefile.am
diff --git a/src/jwk/ChangeLog b/src/jwk/ChangeLog
new file mode 100644
index 0000000..10e590f
--- /dev/null
+++ b/src/jwk/ChangeLog
@@ -0,0 +1,8 @@
+2020-11-25 Vivien Kraus <vivien@planete-kraus.eu>
+
+ * libwebidoidc-jwk.c: new file.
+
+ * generate-key.c: new file.
+
+ * Makefile.am: new file.
+
diff --git a/src/jwk/Makefile.am b/src/jwk/Makefile.am
new file mode 100644
index 0000000..686f450
--- /dev/null
+++ b/src/jwk/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES += %reldir%/libwebidoidc-jwk.la
+noinst_PROGRAMS += %reldir%/generate-key
+EXTRA_DIST += %reldir%/libwebidoidc-jwk.x
+BUILT_SOURCES += %reldir%/libwebidoidc-jwk.x
+
+%canon_reldir%_libwebidoidc_jwk_la_LIBADD = $(GUILE_LIBS) $(NETTLE_LIBS) $(HOGWEED_LIBS)
+%canon_reldir%_generate_key_LDADD = src/libwebidoidc.la $(GUILE_LIBS)
+
+AM_CFLAGS += -I %reldir% -I $(srcdir)/%reldir%
+
+INDENTED += %reldir%/libwebidoidc-jwk.c %reldir%/generate-key.c
+
+%reldir%/libwebidoidc-jwk.o: %reldir%/libwebidoidc-jwk.x
diff --git a/src/jwk/generate-key.c b/src/jwk/generate-key.c
new file mode 100644
index 0000000..ec8ce76
--- /dev/null
+++ b/src/jwk/generate-key.c
@@ -0,0 +1,59 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libguile.h>
+#include <gettext.h>
+
+#define _(s) gettext (s)
+
+SCM webidoidc_generate_key_g (SCM args);
+
+extern int init_webidoidc (void);
+
+static void
+run (void *params, int argc, char *argv[])
+{
+ SCM data;
+ char *end;
+ size_t n_size = 0;
+ (void) params;
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+ if (argc != 2
+ || (strcmp (argv[1], "P-256") != 0
+ && strcmp (argv[1], "P-384") != 0
+ && strcmp (argv[1], "P-521") != 0
+ && ((n_size = strtoull (argv[1], &end, 10)) == 0 || *end != '\0')))
+ {
+ fprintf (stderr, _("Usage: generate-key [NUMBER OF BITS | CURVE]\n"));
+ exit (1);
+ }
+ init_webidoidc ();
+ if (strcmp (argv[1], "P-256") == 0
+ || strcmp (argv[1], "P-384") == 0 || strcmp (argv[1], "P-521") == 0)
+ {
+ data =
+ webidoidc_generate_key_g (scm_list_2
+ (scm_from_utf8_keyword ("crv"),
+ scm_from_utf8_symbol (argv[1])));
+ }
+ else
+ {
+ data =
+ webidoidc_generate_key_g (scm_list_2
+ (scm_from_utf8_keyword ("n-size"),
+ scm_from_size_t (n_size)));
+ }
+ scm_display (data, scm_current_output_port ());
+}
+
+int
+main (int argc, char *argv[])
+{
+ scm_boot_guile (argc, argv, run, NULL);
+ return 0;
+}
diff --git a/src/jwk/libwebidoidc-jwk.c b/src/jwk/libwebidoidc-jwk.c
new file mode 100644
index 0000000..85386fb
--- /dev/null
+++ b/src/jwk/libwebidoidc-jwk.c
@@ -0,0 +1,118 @@
+#include <utilities.h>
+
+#define _(s) dgettext (PACKAGE, s)
+
+void webid_oidc_random (size_t len, uint8_t * dst);
+
+/* Register "generate-key", a guile function to generate a keypair. */
+void init_webidoidc_jwk (void);
+
+SCM_KEYWORD (kw_crv, "crv");
+SCM_KEYWORD (kw_e, "e");
+SCM_KEYWORD (kw_n_size, "n-size");
+SCM_KEYWORD (kw_e_size, "e-size");
+
+SCM_SYMBOL (kty_ec, "EC");
+SCM_SYMBOL (kty_rsa, "RSA");
+
+SCM_SYMBOL (unsupported_kty, "unsupported-kty");
+SCM_SYMBOL (unsupported_crv, "unsupported-crv");
+SCM_SYMBOL (invalid_parameters, "invalid-parameters");
+SCM_SYMBOL (base64_decoding_error, "base64-decoding-error");
+
+/* Required for utilities.h */
+SCM_SYMBOL (p256, "P-256");
+SCM_SYMBOL (p384, "P-384");
+SCM_SYMBOL (p521, "P-521");
+SCM_SYMBOL (kcrv, "crv");
+SCM_SYMBOL (kx, "x");
+SCM_SYMBOL (ky, "y");
+SCM_SYMBOL (kd, "d");
+SCM_SYMBOL (kn, "n");
+SCM_SYMBOL (ke, "e");
+SCM_SYMBOL (kp, "p");
+SCM_SYMBOL (kq, "q");
+SCM_SYMBOL (kdp, "dp");
+SCM_SYMBOL (kdq, "dq");
+SCM_SYMBOL (kqi, "qi");
+
+SCM_SYMBOL (kkty, "kty");
+
+static void
+generate_random (void *unused, size_t len, uint8_t * dst)
+{
+ (void) unused;
+ webid_oidc_random (len, dst);
+}
+
+SCM_DEFINE (webidoidc_generate_key_g, "generate-key", 0, 0, 1, (SCM rest),
+ "Generate a key pair. The parameters are passed as keyword arguments: @code{#:crv}, @code{#:n-size}, @code{#:e} or @code{#:e-size}. Return an alist of the parameters. If @code{#:crv} is specified, generate an EC key pair using the curve, @code{'P-256}, @code{'P-384} or @code{'P-521}. If @code{#:n-size} is specified, generate an RSA key pair that many bits long. Otherwise, this is an error. If @code{#:e} is set, use that for the exponent instead of AQAB. If @code{#:e-size} is set, generate the exponent that many bits long.")
+{
+ SCM crv = SCM_UNDEFINED;
+ SCM n_size = SCM_UNDEFINED;
+ SCM e_size = scm_from_int (0);
+ SCM e = scm_from_utf8_string ("AQAB");
+ const struct ecc_curve *c_crv = NULL;
+ SCM ret = SCM_EOL;
+ scm_c_bind_keyword_arguments ("generate-key", rest, 0,
+ kw_crv, &crv,
+ kw_n_size, &n_size,
+ kw_e_size, &e_size, kw_e, &e, SCM_UNDEFINED);
+ if (!SCM_UNBNDP (crv))
+ {
+ c_crv = do_ecc_curve_load (crv, 1);
+ }
+ else if (!SCM_UNBNDP (n_size))
+ {
+ /* This is a RSA key pair */
+ }
+ else
+ {
+ scm_throw (unsupported_kty, SCM_EOL);
+ }
+ if (c_crv)
+ {
+ struct ecc_point c_point;
+ struct ecc_scalar c_scalar;
+ scm_dynwind_begin (0);
+ ecc_point_init (&c_point, c_crv);
+ dynwind_ecc_point_clear (&c_point);
+ ecc_scalar_init (&c_scalar, c_crv);
+ dynwind_ecc_scalar_clear (&c_scalar);
+ ecdsa_generate_keypair (&c_point, &c_scalar, NULL, generate_random);
+ ret = wrap_ecc_key_pair (c_crv, &c_point, &c_scalar);
+ scm_dynwind_end ();
+ }
+ else
+ {
+ struct rsa_public_key c_pub;
+ struct rsa_private_key c_key;
+ scm_dynwind_begin (0);
+ rsa_public_key_init (&c_pub);
+ dynwind_rsa_public_key_clear (&c_pub);
+ rsa_private_key_init (&c_key);
+ dynwind_rsa_private_key_clear (&c_key);
+ do_mpz_t_load (c_pub.e, e, 1);
+ if (rsa_generate_keypair (&c_pub, &c_key,
+ NULL, &generate_random,
+ NULL, NULL,
+ scm_to_uint (n_size), scm_to_uint (e_size)))
+ {
+ ret = wrap_rsa_key_pair (&c_pub, &c_key);;
+ }
+ else
+ {
+ scm_throw (invalid_parameters, scm_list_3 (n_size, e_size, e));
+ }
+ scm_dynwind_end ();
+ }
+ return ret;
+}
+
+void
+init_webidoidc_jwk (void)
+{
+#ifndef SCM_MAGIC_SNARFER
+#include "libwebidoidc-jwk.x"
+#endif /* not SCM_MAGIC_SNARFER */
+}
diff --git a/src/libwebidoidc.c b/src/libwebidoidc.c
index af26ae0..514a51c 100644
--- a/src/libwebidoidc.c
+++ b/src/libwebidoidc.c
@@ -1,6 +1,7 @@
#define N_(s)
void init_webidoidc_base64 (void);
void init_webidoidc_random (void);
+void init_webidoidc_jwk (void);
void
init_webidoidc (void)
@@ -8,4 +9,5 @@ init_webidoidc (void)
N_("This is the main function.");
init_webidoidc_base64 ();
init_webidoidc_random ();
+ init_webidoidc_jwk ();
}
diff --git a/src/scm/webid-oidc/stubs.scm b/src/scm/webid-oidc/stubs.scm
index b022ef2..5858986 100644
--- a/src/scm/webid-oidc/stubs.scm
+++ b/src/scm/webid-oidc/stubs.scm
@@ -17,4 +17,5 @@
base64-encode
(fix-base64-decode . base64-decode)
random
- random-init!)
+ random-init!
+ generate-key)
diff --git a/src/utilities.h b/src/utilities.h
index b5b91f9..d17f647 100644
--- a/src/utilities.h
+++ b/src/utilities.h
@@ -19,12 +19,58 @@
#include <stdio.h>
#include <unistd.h>
+/* The symbols are used as parameter names for crypto keys */
+static SCM p256;
+static SCM p384;
+static SCM p521;
+static SCM kcrv;
+static SCM kx;
+static SCM ky;
+static SCM kd;
+static SCM kn;
+static SCM ke;
+static SCM kp;
+static SCM kq;
+static SCM kdp;
+static SCM kdq;
+static SCM kqi;
+
/* Return a base64 encoding of some raw data. */
static SCM wrap_bytevector (size_t length, uint8_t * data);
+/* Return a base64 encoding of the bigint z. */
+static SCM wrap_mpz_t (mpz_t z);
+
+/* Return an alist for a key */
+static SCM wrap_ecc_point (const struct ecc_curve *crv,
+ const struct ecc_point *x);
+static SCM wrap_ecc_scalar (const struct ecc_curve *crv,
+ const struct ecc_scalar *x);
+static SCM wrap_ecc_key_pair (const struct ecc_curve *crv,
+ const struct ecc_point *point,
+ const struct ecc_scalar *scalar);
+static SCM wrap_rsa_public_key (struct rsa_public_key *x);
+static SCM wrap_rsa_private_key (struct rsa_private_key *x);
+static SCM wrap_rsa_key_pair (struct rsa_public_key *pub,
+ struct rsa_private_key *key);
+
/* Decode a base64 of binary data. */
static uint8_t *get_as_bytevector (SCM data, size_t *size, int throw_if_fail);
+/* Parse a bigint (data) as base64 and store it in x. */
+static int do_mpz_t_load (mpz_t x, SCM data, int throw_if_fail);
+
+/* Parse an ECC curve */
+static const struct ecc_curve *do_ecc_curve_load (SCM data,
+ int throw_if_fail);
+
+/* Register x to be destroyed at the end of the dynamic wind. */
+static void dynwind_mpz_t_clear (mpz_t x);
+static void dynwind_ecc_point_clear (struct ecc_point *x);
+static void dynwind_ecc_scalar_clear (struct ecc_scalar *x);
+static void dynwind_rsa_public_key_clear (struct rsa_public_key *x);
+static void dynwind_rsa_private_key_clear (struct rsa_private_key *x);
+
static inline SCM
wrap_bytevector (size_t length, uint8_t * data)
{
@@ -52,6 +98,129 @@ wrap_bytevector (size_t length, uint8_t * data)
return ret;
}
+static uint8_t *
+export_mpz_t (mpz_t data, size_t *length)
+{
+ size_t check_length;
+ uint8_t *ret = NULL;
+ *length = (mpz_sizeinbase (data, 2) + 7) / 8;
+ ret = scm_malloc (*length);
+ mpz_export (ret, &check_length, 1, 1, 1, 0, data);
+ assert (*length == check_length);
+ return ret;
+}
+
+static inline SCM
+wrap_mpz_t (mpz_t data)
+{
+ size_t length;
+ uint8_t *c_data;
+ SCM ret;
+ scm_dynwind_begin (0);
+ c_data = export_mpz_t (data, &length);
+ scm_dynwind_free (c_data);
+ ret = wrap_bytevector (length, c_data);
+ scm_dynwind_end ();
+ return ret;
+}
+
+static SCM
+wrap_ecc_curve (const struct ecc_curve *crv)
+{
+ static const struct ecc_curve *p_256 = NULL;
+ static const struct ecc_curve *p_384 = NULL;
+ static const struct ecc_curve *p_521 = NULL;
+ static int init = 0;
+ if (!init)
+ {
+ init = 1;
+ p_256 = nettle_get_secp_256r1 ();
+ p_384 = nettle_get_secp_384r1 ();
+ p_521 = nettle_get_secp_521r1 ();
+ }
+ if (crv == p_256)
+ {
+ return p256; /* the symbol */
+ }
+ if (crv == p_384)
+ {
+ return p384;
+ }
+ if (crv == p_521)
+ {
+ return p521;
+ }
+ abort ();
+ return SCM_UNDEFINED;
+}
+
+static inline SCM
+wrap_ecc_point (const struct ecc_curve *crv, const struct ecc_point *point)
+{
+ mpz_t x, y;
+ SCM ret;
+ scm_dynwind_begin (0);
+ mpz_init (x);
+ dynwind_mpz_t_clear (x);
+ mpz_init (y);
+ dynwind_mpz_t_clear (y);
+ ecc_point_get (point, x, y);
+ ret =
+ scm_list_3 (scm_cons (kcrv, wrap_ecc_curve (crv)),
+ scm_cons (kx, wrap_mpz_t (x)), scm_cons (ky, wrap_mpz_t (y)));
+ scm_dynwind_end ();
+ return ret;
+}
+
+static inline SCM
+wrap_ecc_scalar (const struct ecc_curve *crv, const struct ecc_scalar *scalar)
+{
+ mpz_t z;
+ SCM ret;
+ scm_dynwind_begin (0);
+ mpz_init (z);
+ dynwind_mpz_t_clear (z);
+ ecc_scalar_get (scalar, z);
+ ret =
+ scm_list_2 (scm_cons (kcrv, wrap_ecc_curve (crv)),
+ scm_cons (kd, wrap_mpz_t (z)));
+ scm_dynwind_end ();
+ return ret;
+}
+
+static inline SCM
+wrap_ecc_key_pair (const struct ecc_curve *crv, const struct ecc_point *point,
+ const struct ecc_scalar *scalar)
+{
+ return scm_append (scm_list_2 (wrap_ecc_point (crv, point),
+ wrap_ecc_scalar (crv, scalar)));
+}
+
+static inline SCM
+wrap_rsa_public_key (struct rsa_public_key *x)
+{
+ return scm_list_2 (scm_cons (kn, wrap_mpz_t (x->n)),
+ scm_cons (ke, wrap_mpz_t (x->e)));
+}
+
+static inline SCM
+wrap_rsa_private_key (struct rsa_private_key *x)
+{
+ return scm_list_n (scm_cons (kd, wrap_mpz_t (x->d)),
+ scm_cons (kp, wrap_mpz_t (x->p)),
+ scm_cons (kq, wrap_mpz_t (x->q)),
+ scm_cons (kdp, wrap_mpz_t (x->a)),
+ scm_cons (kdq, wrap_mpz_t (x->b)),
+ scm_cons (kqi, wrap_mpz_t (x->c)), SCM_UNDEFINED);
+}
+
+static inline SCM
+wrap_rsa_key_pair (struct rsa_public_key *pub, struct rsa_private_key *key)
+{
+ return scm_append (scm_list_2 (wrap_rsa_public_key (pub),
+ wrap_rsa_private_key (key)));
+}
+
static inline uint8_t *
get_as_bytevector (SCM data, size_t *size, int throw_if_fail)
{
@@ -85,4 +254,120 @@ get_as_bytevector (SCM data, size_t *size, int throw_if_fail)
return ret;
}
+static inline int
+do_mpz_t_load (mpz_t x, SCM data, int throw_if_fail)
+{
+ size_t size;
+ uint8_t *c_data;
+ int ret = 1;
+ scm_dynwind_begin (0);
+ c_data = get_as_bytevector (data, &size, throw_if_fail);
+ if (c_data)
+ {
+ scm_dynwind_free (c_data);
+ mpz_import (x, size, 1, 1, 1, 0, c_data);
+ }
+ else
+ {
+ ret = 0;
+ }
+ scm_dynwind_end ();
+ return ret;
+}
+
+static inline const struct ecc_curve *
+do_ecc_curve_load (SCM crv, int throw_if_fail)
+{
+ if (scm_is_string (crv))
+ {
+ return do_ecc_curve_load (scm_string_to_symbol (crv), throw_if_fail);
+ }
+ if (scm_is_eq (crv, p256))
+ {
+ return nettle_get_secp_256r1 ();
+ }
+ if (scm_is_eq (crv, p384))
+ {
+ return nettle_get_secp_384r1 ();
+ }
+ if (scm_is_eq (crv, p521))
+ {
+ return nettle_get_secp_521r1 ();
+ }
+ if (throw_if_fail)
+ {
+ scm_throw (scm_from_utf8_symbol ("unsupported-crv"), scm_list_1 (crv));
+ }
+ return NULL;
+}
+
+static void
+do_mpz_t_clear (void *ptr)
+{
+ mpz_t *z = ptr;
+ mpz_clear (*z);
+}
+
+static void
+do_rsa_public_key_clear (void *ptr)
+{
+ struct rsa_public_key *pub = ptr;
+ rsa_public_key_clear (pub);
+}
+
+static void
+do_rsa_private_key_clear (void *ptr)
+{
+ struct rsa_private_key *key = ptr;
+ rsa_private_key_clear (key);
+}
+
+static void
+do_ecc_point_clear (void *ptr)
+{
+ struct ecc_point *point = ptr;
+ ecc_point_clear (point);
+}
+
+static void
+do_ecc_scalar_clear (void *ptr)
+{
+ struct ecc_scalar *scalar = ptr;
+ ecc_scalar_clear (scalar);
+}
+
+static inline void
+dynwind_mpz_t_clear (mpz_t z)
+{
+ scm_dynwind_unwind_handler (do_mpz_t_clear, &z, SCM_F_WIND_EXPLICITLY);
+}
+
+static inline void
+dynwind_rsa_public_key_clear (struct rsa_public_key *pub)
+{
+ scm_dynwind_unwind_handler (do_rsa_public_key_clear, pub,
+ SCM_F_WIND_EXPLICITLY);
+}
+
+static inline void
+dynwind_rsa_private_key_clear (struct rsa_private_key *key)
+{
+ scm_dynwind_unwind_handler (do_rsa_private_key_clear, key,
+ SCM_F_WIND_EXPLICITLY);
+}
+
+static inline void
+dynwind_ecc_point_clear (struct ecc_point *point)
+{
+ scm_dynwind_unwind_handler (do_ecc_point_clear, point,
+ SCM_F_WIND_EXPLICITLY);
+}
+
+static inline void
+dynwind_ecc_scalar_clear (struct ecc_scalar *scalar)
+{
+ scm_dynwind_unwind_handler (do_ecc_scalar_clear, scalar,
+ SCM_F_WIND_EXPLICITLY);
+}
+
#endif /* not H_UTILITIES_INCLUDED */