/* ac-schemes.c - Tests for ES/SSA Copyright (C) 2003, 2005 Free Software Foundation, Inc. This file is part of Libgcrypt. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "../src/gcrypt.h" static unsigned int verbose; static void die (const char *format, ...) { va_list arg_ptr ; va_start( arg_ptr, format ) ; vfprintf (stderr, format, arg_ptr ); va_end(arg_ptr); exit (1); } typedef struct scheme_spec { unsigned int idx; gcry_ac_scheme_t scheme; unsigned int flags; unsigned char *m; size_t m_n; } scheme_spec_t; #define SCHEME_SPEC_FLAG_GET_OPTS (1 << 0) #define FILL(idx, scheme, flags, m) \ { idx, GCRY_AC_##scheme, flags, m, sizeof (m) } scheme_spec_t es_specs[] = { FILL (0, ES_PKCS_V1_5, 0, "foobar"), FILL (1, ES_PKCS_V1_5, 0, "") }; scheme_spec_t ssa_specs[] = { FILL (0, SSA_PKCS_V1_5, SCHEME_SPEC_FLAG_GET_OPTS, "foobar") }; #undef FILL gcry_err_code_t scheme_get_opts (scheme_spec_t specs, void **opts) { gcry_err_code_t err = GPG_ERR_NO_ERROR; void *opts_new = NULL; switch (specs.scheme) { case GCRY_AC_SSA_PKCS_V1_5: { gcry_ac_ssa_pkcs_v1_5_t *opts_pkcs_v1_5 = NULL; opts_new = gcry_malloc (sizeof (gcry_ac_ssa_pkcs_v1_5_t)); if (! opts_new) err = gpg_err_code_from_errno (ENOMEM); else { opts_pkcs_v1_5 = (gcry_ac_ssa_pkcs_v1_5_t *) opts_new; switch (specs.idx) { case 0: opts_pkcs_v1_5->md = GCRY_MD_SHA1; break; case 1: opts_pkcs_v1_5->md = GCRY_MD_MD5; break; } } } case GCRY_AC_ES_PKCS_V1_5: break; } if (! err) *opts = opts_new; return err; } gcry_error_t es_check (gcry_ac_handle_t handle, scheme_spec_t spec, gcry_ac_key_t key_public, gcry_ac_key_t key_secret) { gcry_error_t err = GPG_ERR_NO_ERROR; unsigned char *c = NULL, *m2 = NULL; size_t c_n = 0, m2_n = 0; void *opts = NULL; gcry_ac_io_t io_m; gcry_ac_io_t io_c; gcry_ac_io_t io_m2; if (spec.flags & SCHEME_SPEC_FLAG_GET_OPTS) err = scheme_get_opts (spec, &opts); if (! err) { c = NULL; m2 = NULL; gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE, GCRY_AC_IO_STRING, spec.m, spec.m_n); gcry_ac_io_init (&io_c, GCRY_AC_IO_WRITABLE, GCRY_AC_IO_STRING, &c, &c_n); err = gcry_ac_data_encrypt_scheme (handle, GCRY_AC_ES_PKCS_V1_5, 0, opts, key_public, &io_m, &io_c); if (! err) { gcry_ac_io_init (&io_c, GCRY_AC_IO_READABLE, GCRY_AC_IO_STRING, c, c_n); gcry_ac_io_init (&io_m2, GCRY_AC_IO_WRITABLE, GCRY_AC_IO_STRING, &m2, &m2_n); err = gcry_ac_data_decrypt_scheme (handle, GCRY_AC_ES_PKCS_V1_5, 0, opts, key_secret, &io_c, &io_m2); } if (! err) assert ((spec.m_n == m2_n) && (! strncmp (spec.m, m2, spec.m_n))); if (c) gcry_free (c); if (m2) gcry_free (m2); } if (opts) gcry_free (opts); return err; } gcry_error_t ssa_check (gcry_ac_handle_t handle, scheme_spec_t spec, gcry_ac_key_t key_public, gcry_ac_key_t key_secret) { gcry_error_t err = GPG_ERR_NO_ERROR; unsigned char *s = NULL; size_t s_n = 0; void *opts = NULL; gcry_ac_io_t io_m; gcry_ac_io_t io_s; if (spec.flags & SCHEME_SPEC_FLAG_GET_OPTS) err = scheme_get_opts (spec, &opts); if (! err) { gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE, GCRY_AC_IO_STRING, spec.m, spec.m_n); gcry_ac_io_init (&io_s, GCRY_AC_IO_WRITABLE, GCRY_AC_IO_STRING, &s, &s_n); err = gcry_ac_data_sign_scheme (handle, GCRY_AC_SSA_PKCS_V1_5, 0, opts, key_secret, &io_m, &io_s); if (! err) { gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE, GCRY_AC_IO_STRING, spec.m, spec.m_n); gcry_ac_io_init (&io_s, GCRY_AC_IO_READABLE, GCRY_AC_IO_STRING, s, s_n); err = gcry_ac_data_verify_scheme (handle, GCRY_AC_SSA_PKCS_V1_5, 0, opts, key_public, &io_m, &io_s); } assert (! err); if (s) gcry_free (s); } if (opts) gcry_free (opts); return err; } void es_checks (gcry_ac_handle_t handle, gcry_ac_key_t key_public, gcry_ac_key_t key_secret) { gcry_error_t err = GPG_ERR_NO_ERROR; unsigned int i = 0; for (i = 0; (i < (sizeof (es_specs) / sizeof (*es_specs))) && (! err); i++) err = es_check (handle, es_specs[i], key_public, key_secret); assert (! err); } void ssa_checks (gcry_ac_handle_t handle, gcry_ac_key_t key_public, gcry_ac_key_t key_secret) { gcry_error_t err = GPG_ERR_NO_ERROR; unsigned int i = 0; for (i = 0; (i < (sizeof (ssa_specs) / sizeof (*ssa_specs))) && (! err); i++) err = ssa_check (handle, ssa_specs[i], key_public, key_secret); assert (! err); } #define KEY_TYPE_PUBLIC (1 << 0) #define KEY_TYPE_SECRET (1 << 1) typedef struct key_spec { const char *name; unsigned int flags; const char *mpi_string; } key_spec_t; key_spec_t key_specs[] = { { "n", KEY_TYPE_PUBLIC | KEY_TYPE_SECRET, "e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251" }, { "e", KEY_TYPE_PUBLIC | KEY_TYPE_SECRET, "010001" }, { "d", KEY_TYPE_SECRET, "046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781" }, { "p", KEY_TYPE_SECRET, "00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1" }, { "q", KEY_TYPE_SECRET, "00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" "35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361" }, { "u", KEY_TYPE_SECRET, "304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b" }, { NULL }, }; gcry_error_t key_init (gcry_ac_key_type_t type, gcry_ac_key_t *key) { gcry_error_t err = GPG_ERR_NO_ERROR; gcry_ac_data_t key_data = NULL; gcry_ac_key_t key_new = NULL; gcry_mpi_t mpi = NULL; unsigned int i = 0; err = gcry_ac_data_new (&key_data); for (i = 0; key_specs[i].name && (! err); i++) { if (((type == GCRY_AC_KEY_PUBLIC) && (key_specs[i].flags & KEY_TYPE_PUBLIC)) || ((type == GCRY_AC_KEY_SECRET) && (key_specs[i].flags & KEY_TYPE_SECRET))) { err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, key_specs[i].mpi_string, 0, NULL); if (! err) { gcry_ac_data_set (key_data, GCRY_AC_FLAG_COPY | GCRY_AC_FLAG_DEALLOC, key_specs[i].name, mpi); gcry_mpi_release (mpi); } } } if (! err) err = gcry_ac_key_init (&key_new, NULL, type, key_data); if (key_data) gcry_ac_data_destroy (key_data); if (! err) *key = key_new; return err; } static void check_run (void) { gcry_ac_handle_t handle = NULL; gcry_error_t err = GPG_ERR_NO_ERROR; gcry_ac_key_t key_public = NULL, key_secret = NULL; err = key_init (GCRY_AC_KEY_PUBLIC, &key_public); if (! err) err = key_init (GCRY_AC_KEY_SECRET, &key_secret); if (! err) err = gcry_ac_open (&handle, GCRY_AC_RSA, 0); if (! err) { es_checks (handle, key_public, key_secret); ssa_checks (handle, key_public, key_secret); } assert (! err); } int main (int argc, char **argv) { unsigned int debug = 0; if ((argc > 1) && (! strcmp (argv[1], "--verbose"))) verbose = 1; else if ((argc > 1) && (! strcmp (argv[1], "--debug"))) verbose = debug = 1; gcry_control (GCRYCTL_DISABLE_SECMEM, 0); if (! gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (debug) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); check_run (); return 0; }