diff --git a/cipher/pkey-rsa.c b/cipher/pkey-rsa.c index 1c9b3c48..44e0cd66 100644 --- a/cipher/pkey-rsa.c +++ b/cipher/pkey-rsa.c @@ -1,672 +1,692 @@ /* 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) + if (num_in != 1 && 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; case GCRY_MD_SHA512_224: md_name = "sha512-224"; break; case GCRY_MD_SHA512_256: md_name = "sha512-256"; 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 (num_in == 1) + err = sexp_build (&s_msg, NULL, + "(data" + " (flags pss)" + " (hash-algo %s)" + " (value %b)" + " (salt-length %d))", + md_name, + (int)in_len[0], in[0], 0); + else + 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]); 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) + if (num_in != 2 && 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; case GCRY_MD_SHA512_224: md_name = "sha512-224"; break; case GCRY_MD_SHA512_256: md_name = "sha512-256"; 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 (num_in == 2) + err = sexp_build (&s_msg, NULL, + "(data" + " (flags pss)" + " (hash-algo %s)" + " (value %b)" + " (salt-length %d))", + md_name, + (int)in_len[0], in[0], 0); + else + 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]); + (int)in_len[num_in-1], in[num_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; } 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; case GCRY_MD_SHA512_224: md_name = "sha512-224"; break; case GCRY_MD_SHA512_256: md_name = "sha512-256"; 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]); 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; case GCRY_MD_SHA512_224: md_name = "sha512-224"; break; case GCRY_MD_SHA512_256: md_name = "sha512-256"; 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 fixedlen)" " (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) { out[0] = sexp_nth_buffer (s_tmp, 1, &out_len[0]); 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 fixedlen)" " (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; } /* We check two possible signature; * This allows invalid signature (by another value). * We should support X9.31 signature scheme in lower level. */ 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/tests/t-rsa-pss.c b/tests/t-rsa-pss.c index e72f10e2..2a00a715 100644 --- a/tests/t-rsa-pss.c +++ b/tests/t-rsa-pss.c @@ -1,456 +1,463 @@ /* t-rsa-pss.c - Check the RSA-PSS crypto * 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 . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-rsa-pss" #include "t-common.h" #define N_TESTS 120 static int no_verify; static int custom_data_file; static int in_fips_mode = 0; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '='); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void one_test (const char *n, const char *e, const char *d, const char *sha_alg, const char *msg, const char *s, const char *salt_val) { gpg_error_t err; int i; char *p; void *buffer = NULL; void *buffer2 = NULL; void *buffer3 = NULL; size_t buflen, buflen2, buflen3; gcry_pkey_hd_t h0 = NULL; gcry_pkey_hd_t h1 = NULL; char *sig_string = NULL; const unsigned char *in[3]; size_t in_len[3]; unsigned char *out[1] = { NULL }; size_t out_len[1] = { 0 }; unsigned int flags = 0; int md_algo; + int num_in; if (verbose > 1) info ("Running test %s\n", sha_alg); if (!strcmp (sha_alg, "SHA224")) md_algo = GCRY_MD_SHA224; else if (!strcmp (sha_alg, "SHA256")) md_algo = GCRY_MD_SHA256; else if (!strcmp (sha_alg, "SHA384")) md_algo = GCRY_MD_SHA384; else if (!strcmp (sha_alg, "SHA512")) md_algo = GCRY_MD_SHA512; else if (!strcmp (sha_alg, "SHA512224")) md_algo = GCRY_MD_SHA512_224; else if (!strcmp (sha_alg, "SHA512256")) md_algo = GCRY_MD_SHA512_256; else { fail ("error for test, %s: %s", "d", "invalid hex string"); goto leave; } if (!(buffer = hex2buffer (n, &buflen))) { fail ("error parsing for test, %s: %s", "n", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (e, &buflen2))) { fail ("error parsing for test, %s: %s", "e", "invalid hex string"); goto leave; } if (!(buffer3 = hex2buffer (d, &buflen3))) { fail ("error parsing for test, %s: %s", "d", "invalid hex string"); goto leave; } flags |= GCRY_PKEY_FLAG_SECRET; err = gcry_pkey_open (&h0, GCRY_PKEY_RSA, flags, GCRY_PKEY_RSA_PSS, md_algo, buffer, buflen, buffer2, buflen2, buffer3, buflen3); if (err) { fail ("error opening PKEY for test, %s: %s", "sk", gpg_strerror (err)); goto leave; } flags &= ~GCRY_PKEY_FLAG_SECRET; err = gcry_pkey_open (&h1, GCRY_PKEY_RSA, flags, GCRY_PKEY_RSA_PSS, md_algo, buffer, buflen, buffer2, buflen2); if (err) { fail ("error opening PKEY for test, %s: %s", "pk", gpg_strerror (err)); goto leave; } xfree (buffer); xfree (buffer2); xfree (buffer3); buffer = buffer2 = buffer3 = NULL; if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error parsing for test, %s: %s", "msg", "invalid hex string"); goto leave; } in[0] = buffer; in_len[0] = buflen; if (!(buffer2 = hex2buffer (salt_val, &buflen2))) { fail ("error parsing for test, %s: %s", "salt_val", "invalid hex string"); goto leave; } in[1] = buffer2; in_len[1] = buflen2; - err = gcry_pkey_op (h0, GCRY_PKEY_OP_SIGN, 2, in, in_len, 1, out, out_len); + /* SaltVal = 00 means no salt. */ + if (buflen2 == 1 && ((char *)buffer2)[0] == 0) + num_in = 1; + else + num_in = 2; + + err = gcry_pkey_op (h0, GCRY_PKEY_OP_SIGN, num_in, in, in_len, 1, out, out_len); if (err) fail ("gcry_pkey_op failed: %s", gpg_strerror (err)); sig_string = xmalloc (2*out_len[0]+1); p = sig_string; *p = 0; for (i=0; i < out_len[0]; i++, p += 2) snprintf (p, 3, "%02x", out[0][i]); if (strcmp (sig_string, s)) { fail ("gcry_pkey_op failed: %s", "wrong value returned"); info (" expected: '%s'", s); info (" got: '%s'", sig_string); } if (!no_verify) { - in[2] = out[0]; - in_len[2] = out_len[0]; + in[num_in] = out[0]; + in_len[num_in] = out_len[0]; if ((err = gcry_pkey_op (h1, GCRY_PKEY_OP_VERIFY, - 3, in, in_len, 0, NULL, 0))) + num_in+1, in, in_len, 0, NULL, 0))) fail ("GCRY_PKEY_OP_VERIFY failed for test: %s", gpg_strerror (err)); } leave: xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (out[0]); xfree (sig_string); gcry_pkey_close (h0); gcry_pkey_close (h1); } static void check_rsa_pss (const char *fname) { FILE *fp; int lineno, ntests; char *line; char *n, *e, *d; char *sha_alg, *msg, *s, *salt_val; info ("Checking RSASSA-PSS.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); n = e = d = NULL; sha_alg = msg = s = salt_val = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "[mod", 4)) /* Skip the annotation for modulus. */ ; else if (!strncmp (line, "n =", 3)) copy_data (&n, line, lineno); else if (!strncmp (line, "e =", 3)) copy_data (&e, line, lineno); else if (!strncmp (line, "d =", 3)) copy_data (&d, line, lineno); else if (!strncmp (line, "SHAAlg =", 8)) copy_data (&sha_alg, line, lineno); else if (!strncmp (line, "Msg =", 5)) copy_data (&msg, line, lineno); else if (!strncmp (line, "S =", 3)) copy_data (&s, line, lineno); else if (!strncmp (line, "SaltVal =", 9)) copy_data (&salt_val, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (n && e && d && sha_alg && msg && s && salt_val) { one_test (n, e, d, sha_alg, msg, s, salt_val); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); xfree (sha_alg); sha_alg = NULL; xfree (msg); msg = NULL; xfree (s); s = NULL; xfree (salt_val); salt_val = NULL; } } xfree (n); xfree (e); xfree (d); xfree (sha_alg); xfree (msg); xfree (s); xfree (salt_val); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-rsa-pss.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_rsa_pss (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; }