1/* ac-schemes.c - Tests for ES/SSA
2   Copyright (C) 2003, 2005 Free Software Foundation, Inc.
3
4   This file is part of Libgcrypt.
5
6   This program is free software; you can redistribute it and/or
7   modify it under the terms of the GNU General Public License as
8   published by the Free Software Foundation; either version 2 of the
9   License, or (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.  */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24#include <stdarg.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <assert.h>
29#include <errno.h>
30
31#include "../src/gcrypt.h"
32
33static unsigned int verbose;
34
35static void
36die (const char *format, ...)
37{
38  va_list arg_ptr ;
39
40  va_start( arg_ptr, format ) ;
41  vfprintf (stderr, format, arg_ptr );
42  va_end(arg_ptr);
43  exit (1);
44}
45
46typedef struct scheme_spec
47{
48  unsigned int idx;
49  gcry_ac_scheme_t scheme;
50  unsigned int flags;
51  const char *m;
52  size_t m_n;
53} scheme_spec_t;
54
55#define SCHEME_SPEC_FLAG_GET_OPTS (1 << 0)
56
57#define FILL(idx, scheme, flags, m) \
58    { idx, GCRY_AC_##scheme, flags, m, sizeof (m) }
59
60scheme_spec_t es_specs[] =
61  {
62    FILL (0, ES_PKCS_V1_5, 0, "foobar"),
63    FILL (1, ES_PKCS_V1_5, 0, "")
64  };
65
66scheme_spec_t ssa_specs[] =
67  {
68    FILL (0, SSA_PKCS_V1_5, SCHEME_SPEC_FLAG_GET_OPTS, "foobar")
69  };
70
71#undef FILL
72
73gcry_err_code_t
74scheme_get_opts (scheme_spec_t specs, void **opts)
75{
76  gcry_err_code_t err = GPG_ERR_NO_ERROR;
77  void *opts_new = NULL;
78
79  switch (specs.scheme)
80    {
81    case GCRY_AC_SSA_PKCS_V1_5:
82      {
83	gcry_ac_ssa_pkcs_v1_5_t *opts_pkcs_v1_5 = NULL;
84
85	opts_new = gcry_malloc (sizeof (gcry_ac_ssa_pkcs_v1_5_t));
86	if (! opts_new)
87	  err = gpg_err_code_from_errno (ENOMEM);
88	else
89	  {
90	    opts_pkcs_v1_5 = (gcry_ac_ssa_pkcs_v1_5_t *) opts_new;
91
92	    switch (specs.idx)
93	      {
94	      case 0:
95		opts_pkcs_v1_5->md = GCRY_MD_SHA1;
96		break;
97	      case 1:
98		opts_pkcs_v1_5->md = GCRY_MD_MD5;
99		break;
100	      }
101	  }
102      }
103    case GCRY_AC_ES_PKCS_V1_5:
104      break;
105    }
106
107  if (! err)
108    *opts = opts_new;
109
110  return err;
111}
112
113gcry_error_t
114es_check (gcry_ac_handle_t handle, scheme_spec_t spec,
115	  gcry_ac_key_t key_public, gcry_ac_key_t key_secret)
116{
117  gcry_error_t err = GPG_ERR_NO_ERROR;
118  char *c = NULL;
119  char *m2 = NULL;
120  size_t c_n = 0;
121  size_t m2_n = 0;
122  void *opts = NULL;
123  gcry_ac_io_t io_m;
124  gcry_ac_io_t io_c;
125  gcry_ac_io_t io_m2;
126
127  if (spec.flags & SCHEME_SPEC_FLAG_GET_OPTS)
128    err = scheme_get_opts (spec, &opts);
129  if (! err)
130    {
131      c = NULL;
132      m2 = NULL;
133
134      gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE,
135		       GCRY_AC_IO_STRING, spec.m, spec.m_n);
136      gcry_ac_io_init (&io_c, GCRY_AC_IO_WRITABLE,
137		       GCRY_AC_IO_STRING, &c, &c_n);
138
139      err = gcry_ac_data_encrypt_scheme (handle, GCRY_AC_ES_PKCS_V1_5, 0, opts, key_public,
140					 &io_m, &io_c);
141      if (! err)
142	{
143	  gcry_ac_io_init (&io_c, GCRY_AC_IO_READABLE,
144			   GCRY_AC_IO_STRING, c, c_n);
145	  gcry_ac_io_init (&io_m2, GCRY_AC_IO_WRITABLE,
146			   GCRY_AC_IO_STRING, &m2, &m2_n);
147
148	  err = gcry_ac_data_decrypt_scheme (handle, GCRY_AC_ES_PKCS_V1_5, 0,
149					     opts, key_secret, &io_c, &io_m2);
150	}
151      if (! err)
152	assert ((spec.m_n == m2_n) && (! strncmp (spec.m, m2, spec.m_n)));
153
154      if (c)
155	gcry_free (c);
156      if (m2)
157	gcry_free (m2);
158    }
159
160  if (opts)
161    gcry_free (opts);
162
163  return err;
164}
165
166gcry_error_t
167ssa_check (gcry_ac_handle_t handle, scheme_spec_t spec,
168	   gcry_ac_key_t key_public, gcry_ac_key_t key_secret)
169{
170  gcry_error_t err = GPG_ERR_NO_ERROR;
171  unsigned char *s = NULL;
172  size_t s_n = 0;
173  void *opts = NULL;
174  gcry_ac_io_t io_m;
175  gcry_ac_io_t io_s;
176
177  if (spec.flags & SCHEME_SPEC_FLAG_GET_OPTS)
178    err = scheme_get_opts (spec, &opts);
179  if (! err)
180    {
181      gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE,
182		       GCRY_AC_IO_STRING, spec.m, spec.m_n);
183      gcry_ac_io_init (&io_s, GCRY_AC_IO_WRITABLE,
184		       GCRY_AC_IO_STRING, &s, &s_n);
185
186      err = gcry_ac_data_sign_scheme (handle, GCRY_AC_SSA_PKCS_V1_5, 0, opts, key_secret,
187				      &io_m, &io_s);
188      if (! err)
189	{
190	  gcry_ac_io_init (&io_m, GCRY_AC_IO_READABLE,
191			   GCRY_AC_IO_STRING, spec.m, spec.m_n);
192	  gcry_ac_io_init (&io_s, GCRY_AC_IO_READABLE,
193			   GCRY_AC_IO_STRING, s, s_n);
194	  err = gcry_ac_data_verify_scheme (handle, GCRY_AC_SSA_PKCS_V1_5, 0, opts, key_public,
195					    &io_m, &io_s);
196	}
197      assert (! err);
198
199      if (s)
200	gcry_free (s);
201    }
202
203  if (opts)
204    gcry_free (opts);
205
206  return err;
207}
208
209void
210es_checks (gcry_ac_handle_t handle, gcry_ac_key_t key_public, gcry_ac_key_t key_secret)
211{
212  gcry_error_t err = GPG_ERR_NO_ERROR;
213  unsigned int i = 0;
214
215  for (i = 0; (i < (sizeof (es_specs) / sizeof (*es_specs))) && (! err); i++)
216    err = es_check (handle, es_specs[i], key_public, key_secret);
217
218  assert (! err);
219}
220
221void
222ssa_checks (gcry_ac_handle_t handle, gcry_ac_key_t key_public, gcry_ac_key_t key_secret)
223{
224  gcry_error_t err = GPG_ERR_NO_ERROR;
225  unsigned int i = 0;
226
227  for (i = 0; (i < (sizeof (ssa_specs) / sizeof (*ssa_specs))) && (! err); i++)
228    err = ssa_check (handle, ssa_specs[i], key_public, key_secret);
229
230  assert (! err);
231}
232
233#define KEY_TYPE_PUBLIC (1 << 0)
234#define KEY_TYPE_SECRET (1 << 1)
235
236typedef struct key_spec
237{
238  const char *name;
239  unsigned int flags;
240  const char *mpi_string;
241} key_spec_t;
242
243key_spec_t key_specs[] =
244  {
245    { "n", KEY_TYPE_PUBLIC | KEY_TYPE_SECRET,
246      "e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
247      "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
248      "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
249      "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251" },
250    { "e", KEY_TYPE_PUBLIC | KEY_TYPE_SECRET,
251      "010001" },
252    { "d", KEY_TYPE_SECRET,
253      "046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
254      "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
255      "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
256      "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781" },
257    { "p", KEY_TYPE_SECRET,
258      "00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
259      "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1" },
260    { "q", KEY_TYPE_SECRET,
261      "00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9"
262      "35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361" },
263    { "u", KEY_TYPE_SECRET,
264      "304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
265      "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b" },
266    { NULL },
267  };
268
269gcry_error_t
270key_init (gcry_ac_key_type_t type, gcry_ac_key_t *key)
271{
272  gcry_error_t err = GPG_ERR_NO_ERROR;
273  gcry_ac_data_t key_data = NULL;
274  gcry_ac_key_t key_new = NULL;
275  gcry_mpi_t mpi = NULL;
276  unsigned int i = 0;
277
278  err = gcry_ac_data_new (&key_data);
279  for (i = 0; key_specs[i].name && (! err); i++)
280    {
281      if (((type == GCRY_AC_KEY_PUBLIC) && (key_specs[i].flags & KEY_TYPE_PUBLIC))
282	  || ((type == GCRY_AC_KEY_SECRET) && (key_specs[i].flags & KEY_TYPE_SECRET)))
283	{
284	  err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, key_specs[i].mpi_string, 0, NULL);
285	  if (! err)
286	    {
287	      gcry_ac_data_set (key_data, GCRY_AC_FLAG_COPY | GCRY_AC_FLAG_DEALLOC,
288				key_specs[i].name, mpi);
289	      gcry_mpi_release (mpi);
290	    }
291	}
292    }
293  if (! err)
294    err = gcry_ac_key_init (&key_new, NULL, type, key_data);
295
296  if (key_data)
297    gcry_ac_data_destroy (key_data);
298
299  if (! err)
300    *key = key_new;
301
302  return err;
303}
304
305static void
306check_run (void)
307{
308  gcry_ac_handle_t handle = NULL;
309  gcry_error_t err = GPG_ERR_NO_ERROR;
310  gcry_ac_key_t key_public = NULL, key_secret = NULL;
311
312  err = key_init (GCRY_AC_KEY_PUBLIC, &key_public);
313  if (! err)
314    err = key_init (GCRY_AC_KEY_SECRET, &key_secret);
315
316  if (! err)
317    err = gcry_ac_open (&handle, GCRY_AC_RSA, 0);
318  if (! err)
319    {
320      es_checks (handle, key_public, key_secret);
321      ssa_checks (handle, key_public, key_secret);
322    }
323
324  assert (! err);
325}
326
327int
328main (int argc, char **argv)
329{
330  unsigned int debug = 0;
331
332  if ((argc > 1) && (! strcmp (argv[1], "--verbose")))
333    verbose = 1;
334  else if ((argc > 1) && (! strcmp (argv[1], "--debug")))
335    verbose = debug = 1;
336
337  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
338  if (! gcry_check_version (GCRYPT_VERSION))
339    die ("version mismatch\n");
340  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
341  if (debug)
342    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
343
344  check_run ();
345
346  return 0;
347}
348