diff options
Diffstat (limited to 'src/jwk')
-rw-r--r-- | src/jwk/ChangeLog | 8 | ||||
-rw-r--r-- | src/jwk/Makefile.am | 13 | ||||
-rw-r--r-- | src/jwk/generate-key.c | 59 | ||||
-rw-r--r-- | src/jwk/libwebidoidc-jwk.c | 118 |
4 files changed, 198 insertions, 0 deletions
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 */ +} |