diff options
Diffstat (limited to 'src/utilities.h')
-rw-r--r-- | src/utilities.h | 285 |
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 */ |