diff --git a/cipher/pkey-internal.h b/cipher/pkey-internal.h index 685d6be0..ec5f370e 100644 --- a/cipher/pkey-internal.h +++ b/cipher/pkey-internal.h @@ -1,94 +1,104 @@ /* 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 . * 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[]); gcry_error_t _gcry_pkey_rsapss_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_rsapss_verify (gcry_pkey_hd_t h, int num_in, const unsigned char *const in[], const size_t in_len[]); gcry_error_t _gcry_pkey_rsa15_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_rsa15_verify (gcry_pkey_hd_t h, int num_in, const unsigned char *const in[], const size_t in_len[]); +gcry_error_t _gcry_pkey_rsa931_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_rsa931_verify (gcry_pkey_hd_t h, + int num_in, const unsigned char *const in[], + const size_t in_len[]); + struct pkey_ecc { int curve; unsigned char *pk; size_t pk_len; unsigned char *sk; size_t sk_len; }; struct pkey_rsa { int scheme; int md_algo; unsigned char *n; size_t n_len; unsigned char *e; size_t e_len; unsigned char *d; size_t d_len; }; struct gcry_pkey_handle { int algo; unsigned int flags; union { struct pkey_ecc ecc; struct pkey_rsa rsa; }; }; diff --git a/cipher/pkey-rsa.c b/cipher/pkey-rsa.c index 29744f15..1389f265 100644 --- a/cipher/pkey-rsa.c +++ b/cipher/pkey-rsa.c @@ -1,367 +1,704 @@ -/* pkey-rsa.c - PKEY API implementation for RSA PSS/15/931 +/* pkey-rsa.c - PKEY API implementation for RSA PSS/15/931 * 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 . * SPDX-License-Identifier: LGPL-2.1+ */ #include #include #include #include #include #include #include "g10lib.h" #include "gcrypt-int.h" #include "pkey-internal.h" gcry_error_t _gcry_pkey_rsapss_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; const char *md_name; gcry_sexp_t s_tmp, s_tmp2; if (num_in != 2) return gpg_error (GPG_ERR_INV_ARG); if (num_out != 1) return gpg_error (GPG_ERR_INV_ARG); switch (h->rsa.md_algo) { case GCRY_MD_SHA224: md_name = "sha224"; break; case GCRY_MD_SHA256: md_name = "sha256"; break; case GCRY_MD_SHA384: md_name = "sha384"; break; case GCRY_MD_SHA512: md_name = "sha512"; break; default: return gpg_error (GPG_ERR_INV_ARG); } err = sexp_build (&s_sk, NULL, "(private-key (rsa (n %b)(e %b)(d %b)))", (int)h->rsa.n_len, h->rsa.n, (int)h->rsa.e_len, h->rsa.e, (int)h->rsa.d_len, h->rsa.d); if (err) return err; err = sexp_build (&s_msg, NULL, "(data" " (flags pss)" " (hash-algo %s)" " (value %b)" " (salt-length %d)" " (random-override %b))", md_name, (int)in_len[0], in[0], (int)in_len[1], (int)in_len[1], in[1]); 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] = 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, "rsa", 0); if (s_tmp) { sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { - out[0] = sexp_nth_buffer (s_tmp, 1, &out_len[0]); + const char *p; + size_t n; + + out_len[0] = h->rsa.n_len; + out[0] = xtrymalloc (h->rsa.n_len); + if (! out[0]) + { + err = gpg_error_from_syserror (); + sexp_release (s_tmp); + sexp_release (s_tmp2); + return err; + } + + p = sexp_nth_data (s_tmp, 1, &n); + if (n == h->rsa.n_len) + memcpy (out[0], p, h->rsa.n_len); + else + { + memset (out[0], 0, h->rsa.n_len - n); + memcpy (out[0] + h->rsa.n_len - n, p, n); + } sexp_release (s_tmp); } } } sexp_release (s_tmp2); if (out[0] == NULL) err = gpg_error (GPG_ERR_BAD_SIGNATURE); sexp_release (s_sig); return err; } gcry_error_t _gcry_pkey_rsapss_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; const char *md_name; gcry_sexp_t s_msg= NULL; gcry_sexp_t s_sig= NULL; if (num_in != 3) return gpg_error (GPG_ERR_INV_ARG); switch (h->rsa.md_algo) { case GCRY_MD_SHA224: md_name = "sha224"; break; case GCRY_MD_SHA256: md_name = "sha256"; break; case GCRY_MD_SHA384: md_name = "sha384"; break; case GCRY_MD_SHA512: md_name = "sha512"; break; default: return gpg_error (GPG_ERR_INV_ARG); } err = sexp_build (&s_pk, NULL, "(public-key (rsa (n %b)(e %b)))", (int)h->rsa.n_len, h->rsa.n, (int)h->rsa.e_len, h->rsa.e); if (err) return err; err = sexp_build (&s_msg, NULL, "(data" " (flags pss)" " (hash-algo %s)" " (value %b)" " (salt-length %d)" " (random-override %b))", md_name, (int)in_len[0], in[0], (int)in_len[1], (int)in_len[1], in[1]); if (err) { sexp_release (s_pk); return err; } err = sexp_build (&s_sig, NULL, "(sig-val(rsa(s %b)))", (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; } gcry_error_t _gcry_pkey_rsa15_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; const char *md_name; gcry_sexp_t s_tmp, s_tmp2; if (num_in != 1) return gpg_error (GPG_ERR_INV_ARG); if (num_out != 1) return gpg_error (GPG_ERR_INV_ARG); switch (h->rsa.md_algo) { case GCRY_MD_SHA224: md_name = "sha224"; break; case GCRY_MD_SHA256: md_name = "sha256"; break; case GCRY_MD_SHA384: md_name = "sha384"; break; case GCRY_MD_SHA512: md_name = "sha512"; break; default: return gpg_error (GPG_ERR_INV_ARG); } err = sexp_build (&s_sk, NULL, "(private-key (rsa (n %b)(e %b)(d %b)))", (int)h->rsa.n_len, h->rsa.n, (int)h->rsa.e_len, h->rsa.e, (int)h->rsa.d_len, h->rsa.d); if (err) return err; err = sexp_build (&s_msg, NULL, "(data" " (flags pkcs1 prehash)" " (hash-algo %s)" " (value %b))", md_name, (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] = 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, "rsa", 0); if (s_tmp) { sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { - out[0] = sexp_nth_buffer (s_tmp, 1, &out_len[0]); + const char *p; + size_t n; + + out_len[0] = h->rsa.n_len; + out[0] = xtrymalloc (h->rsa.n_len); + if (! out[0]) + { + err = gpg_error_from_syserror (); + sexp_release (s_tmp); + sexp_release (s_tmp2); + return err; + } + + p = sexp_nth_data (s_tmp, 1, &n); + if (n == h->rsa.n_len) + memcpy (out[0], p, h->rsa.n_len); + else + { + memset (out[0], 0, h->rsa.n_len - n); + memcpy (out[0] + h->rsa.n_len - n, p, n); + } sexp_release (s_tmp); } } } sexp_release (s_tmp2); if (out[0] == NULL) err = gpg_error (GPG_ERR_BAD_SIGNATURE); sexp_release (s_sig); return err; } gcry_error_t _gcry_pkey_rsa15_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; const char *md_name; gcry_sexp_t s_msg= NULL; gcry_sexp_t s_sig= NULL; if (num_in != 2) return gpg_error (GPG_ERR_INV_ARG); switch (h->rsa.md_algo) { case GCRY_MD_SHA224: md_name = "sha224"; break; case GCRY_MD_SHA256: md_name = "sha256"; break; case GCRY_MD_SHA384: md_name = "sha384"; break; case GCRY_MD_SHA512: md_name = "sha512"; break; default: return gpg_error (GPG_ERR_INV_ARG); } err = sexp_build (&s_pk, NULL, "(public-key (rsa (n %b)(e %b)))", (int)h->rsa.n_len, h->rsa.n, (int)h->rsa.e_len, h->rsa.e); if (err) return err; err = sexp_build (&s_msg, NULL, "(data" " (flags pkcs1 prehash)" " (hash-algo %s)" " (value %b))", md_name, (int)in_len[0], in[0]); if (err) { sexp_release (s_pk); return err; } err = sexp_build (&s_sig, NULL, "(sig-val(rsa(s %b)))", (int)in_len[1], in[1]); 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; } + + + +static void +x931_encode_sig (gcry_pkey_hd_t h, unsigned char md_number, + unsigned char *frame, + const unsigned char *input, size_t input_len) +{ + size_t hashlen; + size_t len_ps; + + hashlen = _gcry_md_get_algo_dlen (h->rsa.md_algo); + + len_ps = h->rsa.n_len - hashlen - 4; + frame[0] = 0x6b; + memset (frame+1, 0xbb, len_ps); + frame[1+len_ps] = 0xba; + _gcry_md_hash_buffer (h->rsa.md_algo, &frame[len_ps+2], input, input_len); + frame[h->rsa.n_len - 2] = md_number; + frame[h->rsa.n_len - 1] = 0xcc; +} + +static int +bn_sub (unsigned char *res, + const unsigned char *a, const unsigned char *b, size_t n) +{ + int i; + unsigned char borrow = 0; + + for (i = 0; i < (int)n; i++) + { + res[n-i-1] = a[n-i-1] - b[n-i-1] - borrow; + if ((int)a[n-i-1] < (int)b[n-i-1] + borrow) + borrow = 1; + else + borrow = 0; + } + + return borrow; +} + +static int +bn_cmp (const unsigned char *a, const unsigned char *b, size_t n) +{ + int i; + unsigned char borrow = 0; + + for (i = 0; i < (int)n; i++) + { + if ((int)a[n-i-1] < (int)b[n-i-1] + borrow) + borrow = 1; + else + borrow = 0; + } + + return borrow; +} + +gcry_error_t +_gcry_pkey_rsa931_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; + unsigned char md_number; + unsigned char *frame; + + if (num_in != 1) + return gpg_error (GPG_ERR_INV_ARG); + + if (num_out != 1) + return gpg_error (GPG_ERR_INV_ARG); + + switch (h->rsa.md_algo) + { + case GCRY_MD_SHA224: + md_number = 0x38; + break; + case GCRY_MD_SHA256: + md_number = 0x34; + break; + case GCRY_MD_SHA384: + md_number = 0x36; + break; + case GCRY_MD_SHA512: + md_number = 0x35; + break; + default: + return gpg_error (GPG_ERR_INV_ARG); + } + + if (!(frame = xtrymalloc (h->rsa.n_len))) + return gpg_error_from_syserror (); + + x931_encode_sig (h, md_number, frame, in[0], in_len[0]); + + err = sexp_build (&s_sk, NULL, + "(private-key (rsa (n %b)(e %b)(d %b)))", + (int)h->rsa.n_len, h->rsa.n, + (int)h->rsa.e_len, h->rsa.e, + (int)h->rsa.d_len, h->rsa.d); + if (err) + { + xfree (frame); + return err; + } + + err = sexp_build (&s_msg, NULL, + "(data" + " (flags raw)" + " (value %b))", + (int)h->rsa.n_len, frame); + if (err) + { + xfree (frame); + 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) + { + xfree (frame); + return err; + } + + out[0] = 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, "rsa", 0); + if (s_tmp) + { + sexp_release (s_tmp2); + s_tmp2 = s_tmp; + s_tmp = sexp_find_token (s_tmp2, "s", 0); + if (s_tmp) + { + const char *p; + size_t n; + + out_len[0] = h->rsa.n_len; + out[0] = xtrymalloc (h->rsa.n_len); + if (! out[0]) + { + err = gpg_error_from_syserror (); + xfree (frame); + sexp_release (s_tmp); + sexp_release (s_tmp2); + return err; + } + + p = sexp_nth_data (s_tmp, 1, &n); + if (n == h->rsa.n_len) + memcpy (out[0], p, h->rsa.n_len); + else + { + memset (out[0], 0, h->rsa.n_len - n); + memcpy (out[0] + h->rsa.n_len - n, p, n); + } + sexp_release (s_tmp); + } + } + } + sexp_release (s_tmp2); + + if (out[0] == NULL) + err = gpg_error (GPG_ERR_BAD_SIGNATURE); + else + { + /* X9.31 signature scheme is tricky; It selects minimum one. */ + if (!bn_sub (frame, h->rsa.n, out[0], h->rsa.n_len) + && bn_cmp (frame, out[0], h->rsa.n_len)) + memcpy (out[0], frame, h->rsa.n_len); + } + + sexp_release (s_sig); + xfree (frame); + + return err; +} + +gcry_error_t +_gcry_pkey_rsa931_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; + unsigned char md_number; + unsigned char *frame; + + if (num_in != 2) + return gpg_error (GPG_ERR_INV_ARG); + + switch (h->rsa.md_algo) + { + case GCRY_MD_SHA224: + md_number = 0x38; + break; + case GCRY_MD_SHA256: + md_number = 0x34; + break; + case GCRY_MD_SHA384: + md_number = 0x36; + break; + case GCRY_MD_SHA512: + md_number = 0x35; + break; + default: + return gpg_error (GPG_ERR_INV_ARG); + } + + if (!(frame = xtrymalloc (h->rsa.n_len))) + return gpg_error_from_syserror (); + + x931_encode_sig (h, md_number, frame, in[0], in_len[0]); + + err = sexp_build (&s_pk, NULL, + "(public-key (rsa (n %b)(e %b)))", + (int)h->rsa.n_len, h->rsa.n, + (int)h->rsa.e_len, h->rsa.e); + if (err) + { + xfree (frame); + return err; + } + + err = sexp_build (&s_msg, NULL, + "(data" + " (flags raw)" + " (value %b))", + (int)h->rsa.n_len, frame); + xfree (frame); + if (err) + { + sexp_release (s_pk); + return err; + } + + err = sexp_build (&s_sig, NULL, + "(sig-val(rsa(s %b)))", + (int)in_len[1], in[1]); + if (err) + { + sexp_release (s_msg); + sexp_release (s_pk); + return err; + } + + err = _gcry_pk_verify (s_sig, s_msg, s_pk); + + if (err) + { + unsigned char *alt; + + /* Try another. */ + sexp_release (s_sig); + + if (!(alt = xtrymalloc (h->rsa.n_len))) + { + sexp_release (s_msg); + sexp_release (s_pk); + return gpg_error_from_syserror (); + } + + bn_sub (alt, h->rsa.n, in[1], h->rsa.n_len); + err = sexp_build (&s_sig, NULL, + "(sig-val(rsa(s %b)))", + (int)in_len[1], alt); + 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.c b/cipher/pkey.c index 1ef0034a..9a0d12fa 100644 --- a/cipher/pkey.c +++ b/cipher/pkey.c @@ -1,342 +1,352 @@ -/* pkey.c - pubric key cryptography API +/* pkey.c - Pubric key cryptography API * 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 . * SPDX-License-Identifier: LGPL-2.1+ */ #include #include #include #include #include #include #include "g10lib.h" #include "gcrypt-int.h" #include "pkey-internal.h" gcry_error_t _gcry_pkey_vopen (gcry_pkey_hd_t *h_p, int algo, unsigned int flags, va_list arg_ptr) { gcry_error_t err = 0; gcry_pkey_hd_t h; if (algo == GCRY_PKEY_ECC) ; else if (algo == GCRY_PKEY_RSA) ; else if (algo == GCRY_PKEY_DSA) err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); else if (algo == GCRY_PKEY_ELG) err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); else err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); if (err) return err; if (!(h = xtrycalloc (1, sizeof (struct gcry_pkey_handle)))) - return gpg_err_code_from_syserror (); + return gpg_error_from_syserror (); h->algo = algo; h->flags = flags; if (algo == GCRY_PKEY_ECC) { int curve; unsigned char *pk; unsigned char *sk; curve = va_arg (arg_ptr, int); if (curve == GCRY_PKEY_CURVE_ED25519) ; else if (curve == GCRY_PKEY_CURVE_ED448) ; else err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); if (err) { xfree (h); return err; } h->ecc.curve = curve; if (!(flags & GCRY_PKEY_FLAG_SECRET)) { pk = va_arg (arg_ptr, unsigned char *); h->ecc.pk_len = va_arg (arg_ptr, size_t); h->ecc.sk = sk = NULL; h->ecc.sk_len = 0; } else { pk = va_arg (arg_ptr, unsigned char *); h->ecc.pk_len = va_arg (arg_ptr, size_t); sk = va_arg (arg_ptr, unsigned char *); h->ecc.sk_len = va_arg (arg_ptr, size_t); } if (err) { xfree (h); return err; } if (pk) { h->ecc.pk = xtrymalloc (h->ecc.pk_len); if (!h->ecc.pk) { - err = gpg_err_code_from_syserror (); + err = gpg_error_from_syserror (); xfree (h); return err; } memcpy (h->ecc.pk, pk, h->ecc.pk_len); } else h->ecc.pk = NULL; if (sk) { h->ecc.sk = xtrymalloc_secure (h->ecc.sk_len); if (!h->ecc.sk) { - err = gpg_err_code_from_syserror (); + err = gpg_error_from_syserror (); xfree (h->ecc.pk); xfree (h); return err; } memcpy (h->ecc.sk, sk, h->ecc.sk_len); } } else if (algo == GCRY_PKEY_RSA) { int scheme; int md_algo; unsigned char *n; unsigned char *e; unsigned char *d; scheme = va_arg (arg_ptr, int); if (scheme == GCRY_PKEY_RSA_PSS) ; else if (scheme == GCRY_PKEY_RSA_15) ; else if (scheme == GCRY_PKEY_RSA_931) - err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + ; else err = gpg_error (GPG_ERR_INV_ARG); if (err) { xfree (h); return err; } h->rsa.scheme = scheme; md_algo = va_arg (arg_ptr, int); h->rsa.md_algo = md_algo; if (!(flags & GCRY_PKEY_FLAG_SECRET)) { n = va_arg (arg_ptr, unsigned char *); h->rsa.n_len = va_arg (arg_ptr, size_t); e = va_arg (arg_ptr, unsigned char *); h->rsa.e_len = va_arg (arg_ptr, size_t); h->rsa.d = d = NULL; h->rsa.d_len = 0; } else { n = va_arg (arg_ptr, unsigned char *); h->rsa.n_len = va_arg (arg_ptr, size_t); e = va_arg (arg_ptr, unsigned char *); h->rsa.e_len = va_arg (arg_ptr, size_t); d = va_arg (arg_ptr, unsigned char *); h->rsa.d_len = va_arg (arg_ptr, size_t); } if (err) { xfree (h); return err; } if (n) { h->rsa.n = xtrymalloc (h->rsa.n_len); if (!h->rsa.n) { - err = gpg_err_code_from_syserror (); + err = gpg_error_from_syserror (); xfree (h); return err; } memcpy (h->rsa.n, n, h->rsa.n_len); } else h->rsa.n = NULL; if (e) { h->rsa.e = xtrymalloc (h->rsa.e_len); if (!h->rsa.e) { - err = gpg_err_code_from_syserror (); + err = gpg_error_from_syserror (); xfree (h); return err; } memcpy (h->rsa.e, e, h->rsa.e_len); } else h->rsa.e = NULL; if (d) { h->rsa.d = xtrymalloc (h->rsa.d_len); if (!h->rsa.d) { - err = gpg_err_code_from_syserror (); + err = gpg_error_from_syserror (); xfree (h); return err; } memcpy (h->rsa.d, d, h->rsa.d_len); } } *h_p = h; return err; } gcry_error_t _gcry_pkey_ctl (gcry_pkey_hd_t h, int cmd, void *buffer, size_t buflen) { gcry_error_t err = 0; (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 not the implementation). Will be rewritten soon. Currently, it's like: [ gcry_pkey_op API (with binary data) ] | [ gcry_pk_ API (with SEXP) ] | [ lower level public key implementations (with SEXP) ] It will be like: [ gcry_pk_ API with SEXP ] [ gcry_pkey_op API with binary data ] | | [ lower level public key implementations ] That is, lower level public key implementations won't have any (direct) handling of SEXP. */ gcry_error_t _gcry_pkey_op (gcry_pkey_hd_t h, int cmd, 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; if (h->algo == GCRY_PKEY_ECC) { /* Just for Ed25519 and Ed448 for now. Will support more... */ if (h->ecc.curve == GCRY_PKEY_CURVE_ED25519) { if (cmd == GCRY_PKEY_OP_SIGN) err = _gcry_pkey_ed25519_sign (h, num_in, in, in_len, num_out, out, out_len); else if (cmd == GCRY_PKEY_OP_VERIFY) err = _gcry_pkey_ed25519_verify (h, num_in, in, in_len); else err = gpg_error (GPG_ERR_INV_OP); } else if (h->ecc.curve == GCRY_PKEY_CURVE_ED448) { if (cmd == GCRY_PKEY_OP_SIGN) err = _gcry_pkey_ed448_sign (h, num_in, in, in_len, num_out, out, out_len); else if (cmd == GCRY_PKEY_OP_VERIFY) err = _gcry_pkey_ed448_verify (h, num_in, in, in_len); else err = gpg_error (GPG_ERR_INV_OP); } else err = gpg_error (GPG_ERR_INV_OP); } else if (h->algo == GCRY_PKEY_RSA) { if (h->rsa.scheme == GCRY_PKEY_RSA_PSS) { if (cmd == GCRY_PKEY_OP_SIGN) err = _gcry_pkey_rsapss_sign (h, num_in, in, in_len, num_out, out, out_len); else if (cmd == GCRY_PKEY_OP_VERIFY) err = _gcry_pkey_rsapss_verify (h, num_in, in, in_len); else err = gpg_error (GPG_ERR_INV_OP); } else if (h->rsa.scheme == GCRY_PKEY_RSA_15) { if (cmd == GCRY_PKEY_OP_SIGN) err = _gcry_pkey_rsa15_sign (h, num_in, in, in_len, num_out, out, out_len); else if (cmd == GCRY_PKEY_OP_VERIFY) err = _gcry_pkey_rsa15_verify (h, num_in, in, in_len); else err = gpg_error (GPG_ERR_INV_OP); } + else if (h->rsa.scheme == GCRY_PKEY_RSA_931) + { + if (cmd == GCRY_PKEY_OP_SIGN) + err = _gcry_pkey_rsa931_sign (h, num_in, in, in_len, + num_out, out, out_len); + else if (cmd == GCRY_PKEY_OP_VERIFY) + err = _gcry_pkey_rsa931_verify (h, num_in, in, in_len); + else + err = gpg_error (GPG_ERR_INV_OP); + } else err = gpg_error (GPG_ERR_INV_OP); } else err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); return err; } void _gcry_pkey_close (gcry_pkey_hd_t h) { if (h) { if (h->algo == GCRY_PKEY_ECC) { xfree (h->ecc.pk); xfree (h->ecc.sk); } else if (h->algo == GCRY_PKEY_RSA) { xfree (h->rsa.n); xfree (h->rsa.e); xfree (h->rsa.d); } xfree (h); } }