summaryrefslogtreecommitdiff
path: root/src/utilities.h
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 /src/utilities.h
parent8df0af8301aca112804768f532a4a62dcf3d61d6 (diff)
Generate a key pair.
Diffstat (limited to 'src/utilities.h')
-rw-r--r--src/utilities.h285
1 files changed, 285 insertions, 0 deletions
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 */