summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2021-09-03 17:37:40 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2021-09-03 17:37:40 +0900
commit0fa9a7d42ff4dcf87b91de196ec10510a9f0eee2 (patch)
treed9160e6d87bd1073b945cb38a066388251f2cf7e
parent1031905f9bff94c9aaee609f6c11b1e200292092 (diff)
downloadlibgcrypt-0fa9a7d42ff4dcf87b91de196ec10510a9f0eee2.tar.gz
experiment: Implement gcry_pkey_op.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--cipher/pkey.c189
-rw-r--r--tests/t-ed25519.c11
2 files changed, 170 insertions, 30 deletions
diff --git a/cipher/pkey.c b/cipher/pkey.c
index bd0a358c..82bc4b3f 100644
--- a/cipher/pkey.c
+++ b/cipher/pkey.c
@@ -51,11 +51,11 @@ _gcry_pkey_vopen (gcry_pkey_hd_t *h_p, int algo, unsigned int flags,
gcry_pkey_hd_t h;
int curve;
unsigned char *pk;
- size_t pk_len;
unsigned char *sk;
- size_t sk_len;
- if (algo == GCRY_PKEY_RSA)
+ if (algo == GCRY_PKEY_ECC)
+ ;
+ else if (algo == GCRY_PKEY_RSA)
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
else if (algo == GCRY_PKEY_DSA)
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
@@ -89,19 +89,16 @@ _gcry_pkey_vopen (gcry_pkey_hd_t *h_p, int algo, unsigned int flags,
if (!(flags & GCRY_PKEY_FLAG_SECRET))
{
pk = va_arg (arg_ptr, unsigned char *);
- pk_len = va_arg (arg_ptr, size_t);
+ h->pk_len = va_arg (arg_ptr, size_t);
h->sk = sk = NULL;
- h->sk_len = sk_len = 0;
+ h->sk_len = 0;
}
else
{
pk = va_arg (arg_ptr, unsigned char *);
- pk_len = va_arg (arg_ptr, size_t);
+ h->pk_len = va_arg (arg_ptr, size_t);
sk = va_arg (arg_ptr, unsigned char *);
- sk_len = va_arg (arg_ptr, size_t);
- /* FIXME: PK is required for now. */
- if (!pk)
- err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ h->sk_len = va_arg (arg_ptr, size_t);
}
if (err)
@@ -110,26 +107,31 @@ _gcry_pkey_vopen (gcry_pkey_hd_t *h_p, int algo, unsigned int flags,
return err;
}
- h->pk = xtrymalloc (pk_len);
- if (h->pk)
+ if (pk)
{
- err = gpg_err_code_from_syserror ();
- xfree (h);
- return err;
+ h->pk = xtrymalloc (h->pk_len);
+ if (!h->pk)
+ {
+ err = gpg_err_code_from_syserror ();
+ xfree (h);
+ return err;
+ }
+ memcpy (h->pk, pk, h->pk_len);
}
- memcpy (h->pk, pk, pk_len);
+ else
+ h->pk = NULL;
if (sk)
{
- h->sk = xtrymalloc_secure (pk_len);
- if (h->sk)
+ h->sk = xtrymalloc_secure (h->sk_len);
+ if (!h->sk)
{
err = gpg_err_code_from_syserror ();
xfree (h->pk);
xfree (h);
return err;
}
- memcpy (h->sk, sk, sk_len);
+ memcpy (h->sk, sk, h->sk_len);
}
return err;
@@ -140,11 +142,13 @@ _gcry_pkey_ctl (gcry_pkey_hd_t h, int cmd, void *buffer, size_t buflen)
{
gcry_error_t err = 0;
- (void)h; (void)buffer; (void)buflen;
+ (void)h; (void)cmd; (void)buffer; (void)buflen;
/* FIXME: Not yet implemented anything. */
return err;
}
+/* For now, it uses SEXP implementation, because the purpose is
+ to test the API, but the implementation. Will be rewritten soon. */
gcry_error_t
_gcry_pkey_op (gcry_pkey_hd_t h, int cmd,
int num_in, const unsigned char *const in[],
@@ -152,6 +156,142 @@ _gcry_pkey_op (gcry_pkey_hd_t h, int cmd,
int num_out, unsigned char *out[], size_t out_len[])
{
gcry_error_t err = 0;
+ gcry_sexp_t s_sk = NULL;
+ gcry_sexp_t s_pk = NULL;
+ gcry_sexp_t s_msg= NULL;
+ gcry_sexp_t s_sig= NULL;
+
+ if (cmd == GCRY_PKEY_OP_SIGN)
+ {
+ gcry_sexp_t s_tmp, s_tmp2;
+
+ if ((h->flags & GCRY_PKEY_FLAG_PREHASH))
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ if ((h->flags & GCRY_PKEY_FLAG_CONTEXT))
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ if (num_in != 1)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ if (num_out != 2)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if (h->pk)
+ err = sexp_build (&s_sk, NULL,
+ "(private-key"
+ " (ecc"
+ " (curve \"Ed25519\")"
+ " (flags eddsa)"
+ " (q %b)"
+ " (d %b)))",
+ (int)h->pk_len, h->pk,
+ (int)h->sk_len, h->sk);
+ else
+ err = sexp_build (&s_sk, NULL,
+ "(private-key"
+ " (ecc"
+ " (curve \"Ed25519\")"
+ " (flags eddsa)"
+ " (d %b)))",
+ (int)h->sk_len, h->sk);
+ if (err)
+ return err;
+
+ err = sexp_build (&s_msg, NULL,
+ "(data"
+ " (flags eddsa)"
+ " (hash-algo sha512)"
+ " (value %b))", (int)in_len[0], in[0]);
+ if (err)
+ {
+ sexp_release (s_sk);
+ return err;
+ }
+
+ err = _gcry_pk_sign (&s_sig, s_msg, s_sk);
+ sexp_release (s_sk);
+ sexp_release (s_msg);
+ if (err)
+ return err;
+
+ out[0] = out[1] = NULL;
+ s_tmp2 = NULL;
+ s_tmp = sexp_find_token (s_sig, "sig-val", 0);
+ if (s_tmp)
+ {
+ s_tmp2 = s_tmp;
+ s_tmp = sexp_find_token (s_tmp2, "eddsa", 0);
+ if (s_tmp)
+ {
+ sexp_release (s_tmp2);
+ s_tmp2 = s_tmp;
+ s_tmp = sexp_find_token (s_tmp2, "r", 0);
+ if (s_tmp)
+ {
+ out[0] = sexp_nth_buffer (s_tmp, 1, &out_len[0]);
+ sexp_release (s_tmp);
+ }
+ s_tmp = sexp_find_token (s_tmp2, "s", 0);
+ if (s_tmp)
+ {
+ out[1] = sexp_nth_buffer (s_tmp, 1, &out_len[1]);
+ sexp_release (s_tmp);
+ }
+ }
+ }
+ sexp_release (s_tmp2);
+
+ if (out[0] == NULL || out[1] == NULL)
+ err = gpg_error (GPG_ERR_BAD_SIGNATURE);
+
+ sexp_release (s_sig);
+ }
+ else if (cmd == GCRY_PKEY_OP_VERIFY)
+ {
+ if (num_in != 3)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ err = sexp_build (&s_pk, NULL,
+ "(public-key"
+ " (ecc"
+ " (curve \"Ed25519\")"
+ " (flags eddsa)"
+ " (q %b)))",
+ (int)h->pk_len, h->pk);
+ if (err)
+ return err;
+
+ err = sexp_build (&s_msg, NULL,
+ "(data"
+ " (flags eddsa)"
+ " (hash-algo sha512)"
+ " (value %b))", (int)in_len[0], in[0]);
+ if (err)
+ {
+ sexp_release (s_pk);
+ return err;
+ }
+
+ err = sexp_build (&s_sig, NULL,
+ "(sig-val(eddsa(r %b)(s %b)))",
+ (int)in_len[1], in[1],
+ (int)in_len[2], in[2]);
+ if (err)
+ {
+ sexp_release (s_msg);
+ sexp_release (s_pk);
+ return err;
+ }
+
+ err = _gcry_pk_verify (s_sig, s_msg, s_pk);
+
+ sexp_release (s_sig);
+ sexp_release (s_msg);
+ sexp_release (s_pk);
+ }
+ else
+ err = gpg_error (GPG_ERR_INV_OP);
return err;
}
@@ -159,7 +299,10 @@ _gcry_pkey_op (gcry_pkey_hd_t h, int cmd,
void
_gcry_pkey_close (gcry_pkey_hd_t h)
{
- xfree (h->sk);
- xfree (h->pk);
- xfree (h);
+ if (h)
+ {
+ xfree (h->sk);
+ xfree (h->pk);
+ xfree (h);
+ }
}
diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c
index 48310b5f..08be2ec0 100644
--- a/tests/t-ed25519.c
+++ b/tests/t-ed25519.c
@@ -430,7 +430,7 @@ one_test_using_new_api (int testno, const char *alg,
gcry_pkey_hd_t h0 = NULL;
gcry_pkey_hd_t h1 = NULL;
char *sig_rs_string = NULL;
- const unsigned char * in[4];
+ const unsigned char *in[4];
size_t in_len[4];
unsigned char *out[2] = { NULL, NULL };
size_t out_len[2] = { 0, 0 };
@@ -467,13 +467,11 @@ one_test_using_new_api (int testno, const char *alg,
flags |= GCRY_PKEY_FLAG_SECRET;
if (sign_with_pk)
- err = gcry_pkey_open (&h0, GCRY_PKEY_ECC, flags,
- GCRY_PKEY_CURVE_ED25519,
+ err = gcry_pkey_open (&h0, GCRY_PKEY_ECC, flags, GCRY_PKEY_CURVE_ED25519,
buffer2, buflen2,
buffer, buflen);
else
- err = gcry_pkey_open (&h0, GCRY_PKEY_ECC, flags,
- GCRY_PKEY_CURVE_ED25519,
+ err = gcry_pkey_open (&h0, GCRY_PKEY_ECC, flags, GCRY_PKEY_CURVE_ED25519,
NULL, 0,
buffer, buflen);
if (err)
@@ -484,8 +482,7 @@ one_test_using_new_api (int testno, const char *alg,
}
flags &= ~GCRY_PKEY_FLAG_SECRET;
- err = gcry_pkey_open (&h1, GCRY_PKEY_ECC, flags,
- GCRY_PKEY_CURVE_ED25519,
+ err = gcry_pkey_open (&h1, GCRY_PKEY_ECC, flags, GCRY_PKEY_CURVE_ED25519,
buffer2, buflen2);
if (err)
{