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);
}
}