diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2021-09-07 10:42:19 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2021-09-07 11:34:55 +0900 |
commit | 28771d4b7f59375394cdfc5d8d94b6e23d8b0842 (patch) | |
tree | 452e2e0dd12643bd54b017875b8516708c664fb7 | |
parent | cb8d1b68546c8a3cda87a761ea4eb4d9fcf10343 (diff) | |
download | libgcrypt-28771d4b7f59375394cdfc5d8d94b6e23d8b0842.tar.gz |
experiment: Factor out Ed25519 implementation into a single file.
* cipher/pkey-ed25519.c: New.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r-- | cipher/Makefile.am | 2 | ||||
-rw-r--r-- | cipher/pkey-ed25519.c | 224 | ||||
-rw-r--r-- | cipher/pkey-internal.h | 55 | ||||
-rw-r--r-- | cipher/pkey.c | 191 |
4 files changed, 283 insertions, 189 deletions
diff --git a/cipher/Makefile.am b/cipher/Makefile.am index fb41d55d..b0f0f3fc 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -57,7 +57,7 @@ libcipher_la_SOURCES = \ cipher-gcm-siv.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ - pkey.c \ + pkey.c pkey-internal.h pkey-ed25519.c \ md.c \ mac.c mac-internal.h \ mac-hmac.c mac-cmac.c mac-gmac.c mac-poly1305.c \ diff --git a/cipher/pkey-ed25519.c b/cipher/pkey-ed25519.c new file mode 100644 index 00000000..e0edbf6d --- /dev/null +++ b/cipher/pkey-ed25519.c @@ -0,0 +1,224 @@ +/* pkey-ed25519.c - PKEY API implementation for Ed25519 + * Copyright (C) 2021 g10 Code GmbH + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> + +#include "g10lib.h" +#include "gcrypt-int.h" +#include "pkey-internal.h" + +gcry_error_t +_gcry_pkey_ed25519_sign (gcry_pkey_hd_t h, + int num_in, const unsigned char *const in[], + const size_t in_len[], + 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_msg= NULL; + gcry_sexp_t s_sig= NULL; + + gcry_sexp_t s_tmp, s_tmp2; + + if ((h->flags & GCRY_PKEY_FLAG_CONTEXT)) + { + if (num_in != 2 || (h->flags & GCRY_PKEY_FLAG_PREHASH)) + return gpg_error (GPG_ERR_INV_ARG); + } + else + { + if (num_in != 1) + return gpg_error (GPG_ERR_INV_ARG); + } + + 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; + + if ((h->flags & GCRY_PKEY_FLAG_CONTEXT)) + err = sexp_build (&s_msg, NULL, + "(data" + " (flags eddsa)" + " (hash-algo sha512)" + " (value %b)" + " (label %b))", + (int)in_len[0], in[0], + (int)in_len[1], in[1]); + else if ((h->flags & GCRY_PKEY_FLAG_PREHASH)) + err = sexp_build (&s_msg, NULL, + "(data" + " (flags eddsa prehash)" + " (hash-algo sha512)" + " (value %b))", (int)in_len[0], in[0]); + else + 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); + + return err; +} + +gcry_error_t +_gcry_pkey_ed25519_verify (gcry_pkey_hd_t h, + int num_in, const unsigned char *const in[], + const size_t in_len[]) +{ + gcry_error_t err = 0; + gcry_sexp_t s_pk = NULL; + gcry_sexp_t s_msg= NULL; + gcry_sexp_t s_sig= NULL; + + if ((h->flags & GCRY_PKEY_FLAG_CONTEXT)) + { + if (num_in != 4 || (h->flags & GCRY_PKEY_FLAG_PREHASH)) + return gpg_error (GPG_ERR_INV_ARG); + } + else + { + if (num_in != 3) + return gpg_error (GPG_ERR_INV_ARG); + } + + 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; + + if (h->flags & GCRY_PKEY_FLAG_CONTEXT) + err = sexp_build (&s_msg, NULL, + "(data" + " (flags eddsa)" + " (hash-algo sha512)" + " (value %b)" + " (label %b))", + (int)in_len[0], in[0], + (int)in_len[3], in[3]); + else if ((h->flags & GCRY_PKEY_FLAG_PREHASH)) + err = sexp_build (&s_msg, NULL, + "(data" + " (flags eddsa prehash)" + " (hash-algo sha512)" + " (value %b))", (int)in_len[0], in[0]); + else + 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); + + return err; +} diff --git a/cipher/pkey-internal.h b/cipher/pkey-internal.h new file mode 100644 index 00000000..a63206ed --- /dev/null +++ b/cipher/pkey-internal.h @@ -0,0 +1,55 @@ +/* pkey-internal.h - Internal defs for pkey.c + * Copyright (C) 2021 g10 Code GmbH + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +gcry_error_t _gcry_pkey_ed25519_sign (gcry_pkey_hd_t h, + int num_in, const unsigned char *const in[], + const size_t in_len[], + int num_out, unsigned char *out[], + size_t out_len[]); + +gcry_error_t _gcry_pkey_ed25519_verify (gcry_pkey_hd_t h, + int num_in, const unsigned char *const in[], + const size_t in_len[]); + +gcry_error_t _gcry_pkey_ed448_sign (gcry_pkey_hd_t h, + int num_in, const unsigned char *const in[], + const size_t in_len[], + int num_out, unsigned char *out[], + size_t out_len[]); + +gcry_error_t _gcry_pkey_ed448_verify (gcry_pkey_hd_t h, + int num_in, const unsigned char *const in[], + const size_t in_len[]); + + +struct gcry_pkey_handle { + int algo; + unsigned int flags; + + /* FIXME: Use of union would be better, here. */ + + int curve; + + unsigned char *pk; + size_t pk_len; + + unsigned char *sk; + size_t sk_len; +}; diff --git a/cipher/pkey.c b/cipher/pkey.c index 207d60aa..a6ed67de 100644 --- a/cipher/pkey.c +++ b/cipher/pkey.c @@ -27,21 +27,7 @@ #include "g10lib.h" #include "gcrypt-int.h" - -struct gcry_pkey_handle { - int algo; - unsigned int flags; - - /* FIXME: Use of union would be better, here. */ - - int curve; - - unsigned char *pk; - size_t pk_len; - - unsigned char *sk; - size_t sk_len; -}; +#include "pkey-internal.h" gcry_error_t _gcry_pkey_vopen (gcry_pkey_hd_t *h_p, int algo, unsigned int flags, @@ -176,183 +162,12 @@ _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; /* Just for Ed25519 for now. Will support more... */ if (cmd == GCRY_PKEY_OP_SIGN) - { - gcry_sexp_t s_tmp, s_tmp2; - - if ((h->flags & GCRY_PKEY_FLAG_CONTEXT)) - { - if (num_in != 2 || (h->flags & GCRY_PKEY_FLAG_PREHASH)) - return gpg_error (GPG_ERR_INV_ARG); - } - else - { - if (num_in != 1) - return gpg_error (GPG_ERR_INV_ARG); - } - - 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; - - if ((h->flags & GCRY_PKEY_FLAG_CONTEXT)) - err = sexp_build (&s_msg, NULL, - "(data" - " (flags eddsa)" - " (hash-algo sha512)" - " (value %b)" - " (label %b))", - (int)in_len[0], in[0], - (int)in_len[1], in[1]); - else if ((h->flags & GCRY_PKEY_FLAG_PREHASH)) - err = sexp_build (&s_msg, NULL, - "(data" - " (flags eddsa prehash)" - " (hash-algo sha512)" - " (value %b))", (int)in_len[0], in[0]); - else - 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); - } + err = _gcry_pkey_ed25519_sign (h, num_in, in, in_len, num_out, out, out_len); else if (cmd == GCRY_PKEY_OP_VERIFY) - { - if ((h->flags & GCRY_PKEY_FLAG_CONTEXT)) - { - if (num_in != 4 || (h->flags & GCRY_PKEY_FLAG_PREHASH)) - return gpg_error (GPG_ERR_INV_ARG); - } - else - { - if (num_in != 3) - return gpg_error (GPG_ERR_INV_ARG); - } - - 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; - - if (h->flags & GCRY_PKEY_FLAG_CONTEXT) - err = sexp_build (&s_msg, NULL, - "(data" - " (flags eddsa)" - " (hash-algo sha512)" - " (value %b)" - " (label %b))", - (int)in_len[0], in[0], - (int)in_len[3], in[3]); - else if ((h->flags & GCRY_PKEY_FLAG_PREHASH)) - err = sexp_build (&s_msg, NULL, - "(data" - " (flags eddsa prehash)" - " (hash-algo sha512)" - " (value %b))", (int)in_len[0], in[0]); - else - 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); - } + err = _gcry_pkey_ed25519_verify (h, num_in, in, in_len); else err = gpg_error (GPG_ERR_INV_OP); |