summaryrefslogtreecommitdiff
path: root/cipher/ecc.c
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 /cipher/ecc.c
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>
Diffstat (limited to 'cipher/ecc.c')
-rw-r--r--cipher/ecc.c74
1 files changed, 74 insertions, 0 deletions
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.