1 /* pubkey.c - pubkey dispatcher
2 * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
3 * 2007, 2008, 2011 Free Software Foundation, Inc.
4 * Copyright (C) 2013 g10 Code GmbH
5 *
6 * This file is part of Libgcrypt.
7 *
8 * Libgcrypt is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser general Public License as
10 * published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * Libgcrypt is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include "g10lib.h"
29 #include "mpi.h"
30 #include "cipher.h"
31 #include "context.h"
32 #include "pubkey-internal.h"
33
34
35 /* This is the list of the public-key algorithms included in
36 Libgcrypt. */
37 static gcry_pk_spec_t * const pubkey_list[] =
38 {
39 #if USE_ECC
40 &_gcry_pubkey_spec_ecc,
41 #endif
42 #if USE_RSA
43 &_gcry_pubkey_spec_rsa,
44 #endif
45 #if USE_DSA
46 &_gcry_pubkey_spec_dsa,
47 #endif
48 #if USE_ELGAMAL
49 &_gcry_pubkey_spec_elg,
50 #endif
51 NULL
52 };
53
54
55 static int
map_algo(int algo)56 map_algo (int algo)
57 {
58 switch (algo)
59 {
60 case GCRY_PK_RSA_E: return GCRY_PK_RSA;
61 case GCRY_PK_RSA_S: return GCRY_PK_RSA;
62 case GCRY_PK_ELG_E: return GCRY_PK_ELG;
63 case GCRY_PK_ECDSA: return GCRY_PK_ECC;
64 case GCRY_PK_EDDSA: return GCRY_PK_ECC;
65 case GCRY_PK_ECDH: return GCRY_PK_ECC;
66 default: return algo;
67 }
68 }
69
70
71 /* Return the spec structure for the public key algorithm ALGO. For
72 an unknown algorithm NULL is returned. */
73 static gcry_pk_spec_t *
spec_from_algo(int algo)74 spec_from_algo (int algo)
75 {
76 int idx;
77 gcry_pk_spec_t *spec;
78
79 algo = map_algo (algo);
80
81 for (idx = 0; (spec = pubkey_list[idx]); idx++)
82 if (algo == spec->algo)
83 return spec;
84 return NULL;
85 }
86
87
88 /* Return the spec structure for the public key algorithm with NAME.
89 For an unknown name NULL is returned. */
90 static gcry_pk_spec_t *
spec_from_name(const char * name)91 spec_from_name (const char *name)
92 {
93 gcry_pk_spec_t *spec;
94 int idx;
95 const char **aliases;
96
97 for (idx=0; (spec = pubkey_list[idx]); idx++)
98 {
99 if (!stricmp (name, spec->name))
100 return spec;
101 for (aliases = spec->aliases; *aliases; aliases++)
102 if (!stricmp (name, *aliases))
103 return spec;
104 }
105
106 return NULL;
107 }
108
109
110
111 /* Given the s-expression SEXP with the first element be either
112 * "private-key" or "public-key" return the spec structure for it. We
113 * look through the list to find a list beginning with "private-key"
114 * or "public-key" - the first one found is used. If WANT_PRIVATE is
115 * set the function will only succeed if a private key has been given.
116 * On success the spec is stored at R_SPEC. On error NULL is stored
117 * at R_SPEC and an error code returned. If R_PARMS is not NULL and
118 * the function returns success, the parameter list below
119 * "private-key" or "public-key" is stored there and the caller must
120 * call gcry_sexp_release on it.
121 */
122 static gcry_err_code_t
spec_from_sexp(gcry_sexp_t sexp,int want_private,gcry_pk_spec_t ** r_spec,gcry_sexp_t * r_parms)123 spec_from_sexp (gcry_sexp_t sexp, int want_private,
124 gcry_pk_spec_t **r_spec, gcry_sexp_t *r_parms)
125 {
126 gcry_sexp_t list, l2;
127 char *name;
128 gcry_pk_spec_t *spec;
129
130 *r_spec = NULL;
131 if (r_parms)
132 *r_parms = NULL;
133
134 /* Check that the first element is valid. If we are looking for a
135 public key but a private key was supplied, we allow the use of
136 the private key anyway. The rationale for this is that the
137 private key is a superset of the public key. */
138 list = sexp_find_token (sexp, want_private? "private-key":"public-key", 0);
139 if (!list && !want_private)
140 list = sexp_find_token (sexp, "private-key", 0);
141 if (!list)
142 return GPG_ERR_INV_OBJ; /* Does not contain a key object. */
143
144 l2 = sexp_cadr (list);
145 sexp_release (list);
146 list = l2;
147 name = sexp_nth_string (list, 0);
148 if (!name)
149 {
150 sexp_release ( list );
151 return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
152 }
153 spec = spec_from_name (name);
154 xfree (name);
155 if (!spec)
156 {
157 sexp_release (list);
158 return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
159 }
160 *r_spec = spec;
161 if (r_parms)
162 *r_parms = list;
163 else
164 sexp_release (list);
165 return 0;
166 }
167
168
169
170 /* Disable the use of the algorithm ALGO. This is not thread safe and
171 should thus be called early. */
172 static void
disable_pubkey_algo(int algo)173 disable_pubkey_algo (int algo)
174 {
175 gcry_pk_spec_t *spec = spec_from_algo (algo);
176
177 if (spec)
178 spec->flags.disabled = 1;
179 }
180
181
182
183 /*
184 * Map a string to the pubkey algo
185 */
186 int
_gcry_pk_map_name(const char * string)187 _gcry_pk_map_name (const char *string)
188 {
189 gcry_pk_spec_t *spec;
190
191 if (!string)
192 return 0;
193 spec = spec_from_name (string);
194 if (!spec)
195 return 0;
196 if (spec->flags.disabled)
197 return 0;
198 return spec->algo;
199 }
200
201
202 /* Map the public key algorithm whose ID is contained in ALGORITHM to
203 a string representation of the algorithm name. For unknown
204 algorithm IDs this functions returns "?". */
205 const char *
_gcry_pk_algo_name(int algo)206 _gcry_pk_algo_name (int algo)
207 {
208 gcry_pk_spec_t *spec;
209
210 spec = spec_from_algo (algo);
211 if (spec)
212 return spec->name;
213 return "?";
214 }
215
216
217 /****************
218 * A USE of 0 means: don't care.
219 */
220 static gcry_err_code_t
check_pubkey_algo(int algo,unsigned use)221 check_pubkey_algo (int algo, unsigned use)
222 {
223 gcry_err_code_t err = 0;
224 gcry_pk_spec_t *spec;
225
226 spec = spec_from_algo (algo);
227 if (spec)
228 {
229 if (((use & GCRY_PK_USAGE_SIGN)
230 && (! (spec->use & GCRY_PK_USAGE_SIGN)))
231 || ((use & GCRY_PK_USAGE_ENCR)
232 && (! (spec->use & GCRY_PK_USAGE_ENCR))))
233 err = GPG_ERR_WRONG_PUBKEY_ALGO;
234 }
235 else
236 err = GPG_ERR_PUBKEY_ALGO;
237
238 return err;
239 }
240
241
242 /****************
243 * Return the number of public key material numbers
244 */
245 static int
pubkey_get_npkey(int algo)246 pubkey_get_npkey (int algo)
247 {
248 gcry_pk_spec_t *spec = spec_from_algo (algo);
249
250 return spec? strlen (spec->elements_pkey) : 0;
251 }
252
253
254 /****************
255 * Return the number of secret key material numbers
256 */
257 static int
pubkey_get_nskey(int algo)258 pubkey_get_nskey (int algo)
259 {
260 gcry_pk_spec_t *spec = spec_from_algo (algo);
261
262 return spec? strlen (spec->elements_skey) : 0;
263 }
264
265
266 /****************
267 * Return the number of signature material numbers
268 */
269 static int
pubkey_get_nsig(int algo)270 pubkey_get_nsig (int algo)
271 {
272 gcry_pk_spec_t *spec = spec_from_algo (algo);
273
274 return spec? strlen (spec->elements_sig) : 0;
275 }
276
277 /****************
278 * Return the number of encryption material numbers
279 */
280 static int
pubkey_get_nenc(int algo)281 pubkey_get_nenc (int algo)
282 {
283 gcry_pk_spec_t *spec = spec_from_algo (algo);
284
285 return spec? strlen (spec->elements_enc) : 0;
286 }
287
288
289
290 /*
291 Do a PK encrypt operation
292
293 Caller has to provide a public key as the SEXP pkey and data as a
294 SEXP with just one MPI in it. Alternatively S_DATA might be a
295 complex S-Expression, similar to the one used for signature
296 verification. This provides a flag which allows to handle PKCS#1
297 block type 2 padding. The function returns a sexp which may be
298 passed to to pk_decrypt.
299
300 Returns: 0 or an errorcode.
301
302 s_data = See comment for _gcry_pk_util_data_to_mpi
303 s_pkey = <key-as-defined-in-sexp_to_key>
304 r_ciph = (enc-val
305 (<algo>
306 (<param_name1> <mpi>)
307 ...
308 (<param_namen> <mpi>)
309 ))
310
311 */
312 gcry_err_code_t
_gcry_pk_encrypt(gcry_sexp_t * r_ciph,gcry_sexp_t s_data,gcry_sexp_t s_pkey)313 _gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
314 {
315 gcry_err_code_t rc;
316 gcry_pk_spec_t *spec;
317 gcry_sexp_t keyparms;
318
319 *r_ciph = NULL;
320
321 rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
322 if (rc)
323 goto leave;
324
325 if (spec->encrypt)
326 rc = spec->encrypt (r_ciph, s_data, keyparms);
327 else
328 rc = GPG_ERR_NOT_IMPLEMENTED;
329
330 leave:
331 sexp_release (keyparms);
332 return rc;
333 }
334
335
336 /*
337 Do a PK decrypt operation
338
339 Caller has to provide a secret key as the SEXP skey and data in a
340 format as created by gcry_pk_encrypt. For historic reasons the
341 function returns simply an MPI as an S-expression part; this is
342 deprecated and the new method should be used which returns a real
343 S-expressionl this is selected by adding at least an empty flags
344 list to S_DATA.
345
346 Returns: 0 or an errorcode.
347
348 s_data = (enc-val
349 [(flags [raw, pkcs1, oaep])]
350 (<algo>
351 (<param_name1> <mpi>)
352 ...
353 (<param_namen> <mpi>)
354 ))
355 s_skey = <key-as-defined-in-sexp_to_key>
356 r_plain= Either an incomplete S-expression without the parentheses
357 or if the flags list is used (even if empty) a real S-expression:
358 (value PLAIN). In raw mode (or no flags given) the returned value
359 is to be interpreted as a signed MPI, thus it may have an extra
360 leading zero octet even if not included in the original data.
361 With pkcs1 or oaep decoding enabled the returned value is a
362 verbatim octet string.
363 */
364 gcry_err_code_t
_gcry_pk_decrypt(gcry_sexp_t * r_plain,gcry_sexp_t s_data,gcry_sexp_t s_skey)365 _gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
366 {
367 gcry_err_code_t rc;
368 gcry_pk_spec_t *spec;
369 gcry_sexp_t keyparms;
370
371 *r_plain = NULL;
372
373 rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
374 if (rc)
375 goto leave;
376
377 if (spec->decrypt)
378 rc = spec->decrypt (r_plain, s_data, keyparms);
379 else
380 rc = GPG_ERR_NOT_IMPLEMENTED;
381
382 leave:
383 sexp_release (keyparms);
384 return rc;
385 }
386
387
388
389 /*
390 Create a signature.
391
392 Caller has to provide a secret key as the SEXP skey and data
393 expressed as a SEXP list hash with only one element which should
394 instantly be available as a MPI. Alternatively the structure given
395 below may be used for S_HASH, it provides the abiliy to pass flags
396 to the operation; the flags defined by now are "pkcs1" which does
397 PKCS#1 block type 1 style padding and "pss" for PSS encoding.
398
399 Returns: 0 or an errorcode.
400 In case of 0 the function returns a new SEXP with the
401 signature value; the structure of this signature depends on the
402 other arguments but is always suitable to be passed to
403 gcry_pk_verify
404
405 s_hash = See comment for _gcry-pk_util_data_to_mpi
406
407 s_skey = <key-as-defined-in-sexp_to_key>
408 r_sig = (sig-val
409 (<algo>
410 (<param_name1> <mpi>)
411 ...
412 (<param_namen> <mpi>))
413 [(hash algo)])
414
415 Note that (hash algo) in R_SIG is not used.
416 */
417 gcry_err_code_t
_gcry_pk_sign(gcry_sexp_t * r_sig,gcry_sexp_t s_hash,gcry_sexp_t s_skey)418 _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
419 {
420 gcry_err_code_t rc;
421 gcry_pk_spec_t *spec;
422 gcry_sexp_t keyparms;
423
424 *r_sig = NULL;
425
426 rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
427 if (rc)
428 goto leave;
429
430 if (spec->sign)
431 rc = spec->sign (r_sig, s_hash, keyparms);
432 else
433 rc = GPG_ERR_NOT_IMPLEMENTED;
434
435 leave:
436 sexp_release (keyparms);
437 return rc;
438 }
439
440
441 /*
442 Verify a signature.
443
444 Caller has to supply the public key pkey, the signature sig and his
445 hashvalue data. Public key has to be a standard public key given
446 as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
447 must be an S-Exp like the one in sign too. */
448 gcry_err_code_t
_gcry_pk_verify(gcry_sexp_t s_sig,gcry_sexp_t s_hash,gcry_sexp_t s_pkey)449 _gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
450 {
451 gcry_err_code_t rc;
452 gcry_pk_spec_t *spec;
453 gcry_sexp_t keyparms;
454
455 rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
456 if (rc)
457 goto leave;
458
459 if (spec->verify)
460 rc = spec->verify (s_sig, s_hash, keyparms);
461 else
462 rc = GPG_ERR_NOT_IMPLEMENTED;
463
464 leave:
465 sexp_release (keyparms);
466 return rc;
467 }
468
469
470 /*
471 Test a key.
472
473 This may be used either for a public or a secret key to see whether
474 the internal structure is okay.
475
476 Returns: 0 or an errorcode.
477
478 NOTE: We currently support only secret key checking. */
479 gcry_err_code_t
_gcry_pk_testkey(gcry_sexp_t s_key)480 _gcry_pk_testkey (gcry_sexp_t s_key)
481 {
482 gcry_err_code_t rc;
483 gcry_pk_spec_t *spec;
484 gcry_sexp_t keyparms;
485
486 rc = spec_from_sexp (s_key, 1, &spec, &keyparms);
487 if (rc)
488 goto leave;
489
490 if (spec->check_secret_key)
491 rc = spec->check_secret_key (keyparms);
492 else
493 rc = GPG_ERR_NOT_IMPLEMENTED;
494
495 leave:
496 sexp_release (keyparms);
497 return rc;
498 }
499
500
501 /*
502 Create a public key pair and return it in r_key.
503 How the key is created depends on s_parms:
504 (genkey
505 (algo
506 (parameter_name_1 ....)
507 ....
508 (parameter_name_n ....)
509 ))
510 The key is returned in a format depending on the
511 algorithm. Both, private and secret keys are returned
512 and optionally some additional informatin.
513 For elgamal we return this structure:
514 (key-data
515 (public-key
516 (elg
517 (p <mpi>)
518 (g <mpi>)
519 (y <mpi>)
520 )
521 )
522 (private-key
523 (elg
524 (p <mpi>)
525 (g <mpi>)
526 (y <mpi>)
527 (x <mpi>)
528 )
529 )
530 (misc-key-info
531 (pm1-factors n1 n2 ... nn)
532 ))
533 */
534 gcry_err_code_t
_gcry_pk_genkey(gcry_sexp_t * r_key,gcry_sexp_t s_parms)535 _gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
536 {
537 gcry_pk_spec_t *spec = NULL;
538 gcry_sexp_t list = NULL;
539 gcry_sexp_t l2 = NULL;
540 char *name = NULL;
541 gcry_err_code_t rc;
542
543 *r_key = NULL;
544
545 list = sexp_find_token (s_parms, "genkey", 0);
546 if (!list)
547 {
548 rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
549 goto leave;
550 }
551
552 l2 = sexp_cadr (list);
553 sexp_release (list);
554 list = l2;
555 l2 = NULL;
556 if (! list)
557 {
558 rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
559 goto leave;
560 }
561
562 name = _gcry_sexp_nth_string (list, 0);
563 if (!name)
564 {
565 rc = GPG_ERR_INV_OBJ; /* Algo string missing. */
566 goto leave;
567 }
568
569 spec = spec_from_name (name);
570 xfree (name);
571 name = NULL;
572 if (!spec)
573 {
574 rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
575 goto leave;
576 }
577
578 if (spec->generate)
579 rc = spec->generate (list, r_key);
580 else
581 rc = GPG_ERR_NOT_IMPLEMENTED;
582
583 leave:
584 sexp_release (list);
585 xfree (name);
586 sexp_release (l2);
587
588 return rc;
589 }
590
591
592 /*
593 Get the number of nbits from the public key.
594
595 Hmmm: Should we have really this function or is it better to have a
596 more general function to retrieve different properties of the key? */
597 unsigned int
_gcry_pk_get_nbits(gcry_sexp_t key)598 _gcry_pk_get_nbits (gcry_sexp_t key)
599 {
600 gcry_pk_spec_t *spec;
601 gcry_sexp_t parms;
602 unsigned int nbits;
603
604 /* Parsing KEY might be considered too much overhead. For example
605 for RSA we would only need to look at P and stop parsing right
606 away. However, with ECC things are more complicate in that only
607 a curve name might be specified. Thus we need to tear the sexp
608 apart. */
609
610 if (spec_from_sexp (key, 0, &spec, &parms))
611 return 0; /* Error - 0 is a suitable indication for that. */
612
613 nbits = spec->get_nbits (parms);
614 sexp_release (parms);
615 return nbits;
616 }
617
618
619 /* Return the so called KEYGRIP which is the SHA-1 hash of the public
620 key parameters expressed in a way depending on the algorithm.
621
622 ARRAY must either be 20 bytes long or NULL; in the latter case a
623 newly allocated array of that size is returned, otherwise ARRAY or
624 NULL is returned to indicate an error which is most likely an
625 unknown algorithm. The function accepts public or secret keys. */
626 unsigned char *
_gcry_pk_get_keygrip(gcry_sexp_t key,unsigned char * array)627 _gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
628 {
629 gcry_sexp_t list = NULL;
630 gcry_sexp_t l2 = NULL;
631 gcry_pk_spec_t *spec = NULL;
632 const char *s;
633 char *name = NULL;
634 int idx;
635 const char *elems;
636 gcry_md_hd_t md = NULL;
637 int okay = 0;
638
639 /* Check that the first element is valid. */
640 list = sexp_find_token (key, "public-key", 0);
641 if (! list)
642 list = sexp_find_token (key, "private-key", 0);
643 if (! list)
644 list = sexp_find_token (key, "protected-private-key", 0);
645 if (! list)
646 list = sexp_find_token (key, "shadowed-private-key", 0);
647 if (! list)
648 return NULL; /* No public- or private-key object. */
649
650 l2 = sexp_cadr (list);
651 sexp_release (list);
652 list = l2;
653 l2 = NULL;
654
655 name = _gcry_sexp_nth_string (list, 0);
656 if (!name)
657 goto fail; /* Invalid structure of object. */
658
659 spec = spec_from_name (name);
660 if (!spec)
661 goto fail; /* Unknown algorithm. */
662
663 elems = spec->elements_grip;
664 if (!elems)
665 goto fail; /* No grip parameter. */
666
667 if (_gcry_md_open (&md, GCRY_MD_SHA1, 0))
668 goto fail;
669
670 if (spec->comp_keygrip)
671 {
672 /* Module specific method to compute a keygrip. */
673 if (spec->comp_keygrip (md, list))
674 goto fail;
675 }
676 else
677 {
678 /* Generic method to compute a keygrip. */
679 for (idx = 0, s = elems; *s; s++, idx++)
680 {
681 const char *data;
682 size_t datalen;
683 char buf[30];
684
685 l2 = sexp_find_token (list, s, 1);
686 if (! l2)
687 goto fail;
688 data = sexp_nth_data (l2, 1, &datalen);
689 if (! data)
690 goto fail;
691
692 snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
693 _gcry_md_write (md, buf, strlen (buf));
694 _gcry_md_write (md, data, datalen);
695 sexp_release (l2);
696 l2 = NULL;
697 _gcry_md_write (md, ")", 1);
698 }
699 }
700
701 if (!array)
702 {
703 array = xtrymalloc (20);
704 if (! array)
705 goto fail;
706 }
707
708 memcpy (array, _gcry_md_read (md, GCRY_MD_SHA1), 20);
709 okay = 1;
710
711 fail:
712 xfree (name);
713 sexp_release (l2);
714 _gcry_md_close (md);
715 sexp_release (list);
716 return okay? array : NULL;
717 }
718
719
720
721 const char *
_gcry_pk_get_curve(gcry_sexp_t key,int iterator,unsigned int * r_nbits)722 _gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
723 {
724 const char *result = NULL;
725 gcry_pk_spec_t *spec;
726 gcry_sexp_t keyparms = NULL;
727
728 if (r_nbits)
729 *r_nbits = 0;
730
731 if (key)
732 {
733 iterator = 0;
734
735 if (spec_from_sexp (key, 0, &spec, &keyparms))
736 return NULL;
737 }
738 else
739 {
740 spec = spec_from_name ("ecc");
741 if (!spec)
742 return NULL;
743 }
744
745 if (spec->get_curve)
746 result = spec->get_curve (keyparms, iterator, r_nbits);
747
748 sexp_release (keyparms);
749 return result;
750 }
751
752
753
754 gcry_sexp_t
_gcry_pk_get_param(int algo,const char * name)755 _gcry_pk_get_param (int algo, const char *name)
756 {
757 gcry_sexp_t result = NULL;
758 gcry_pk_spec_t *spec = NULL;
759
760 algo = map_algo (algo);
761
762 if (algo != GCRY_PK_ECC)
763 return NULL;
764
765 spec = spec_from_name ("ecc");
766 if (spec)
767 {
768 if (spec && spec->get_curve_param)
769 result = spec->get_curve_param (name);
770 }
771 return result;
772 }
773
774
775
776 gcry_err_code_t
_gcry_pk_ctl(int cmd,void * buffer,size_t buflen)777 _gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
778 {
779 gcry_err_code_t rc = 0;
780
781 switch (cmd)
782 {
783 case GCRYCTL_DISABLE_ALGO:
784 /* This one expects a buffer pointing to an integer with the
785 algo number. */
786 if ((! buffer) || (buflen != sizeof (int)))
787 rc = GPG_ERR_INV_ARG;
788 else
789 disable_pubkey_algo (*((int *) buffer));
790 break;
791
792 default:
793 rc = GPG_ERR_INV_OP;
794 }
795
796 return rc;
797 }
798
799
800 /* Return information about the given algorithm
801
802 WHAT selects the kind of information returned:
803
804 GCRYCTL_TEST_ALGO:
805 Returns 0 when the specified algorithm is available for use.
806 Buffer must be NULL, nbytes may have the address of a variable
807 with the required usage of the algorithm. It may be 0 for don't
808 care or a combination of the GCRY_PK_USAGE_xxx flags;
809
810 GCRYCTL_GET_ALGO_USAGE:
811 Return the usage flags for the given algo. An invalid algo
812 returns 0. Disabled algos are ignored here because we
813 only want to know whether the algo is at all capable of
814 the usage.
815
816 Note: Because this function is in most cases used to return an
817 integer value, we can make it easier for the caller to just look at
818 the return value. The caller will in all cases consult the value
819 and thereby detecting whether a error occurred or not (i.e. while
820 checking the block size) */
821 gcry_err_code_t
_gcry_pk_algo_info(int algorithm,int what,void * buffer,size_t * nbytes)822 _gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
823 {
824 gcry_err_code_t rc = 0;
825
826 switch (what)
827 {
828 case GCRYCTL_TEST_ALGO:
829 {
830 int use = nbytes ? *nbytes : 0;
831 if (buffer)
832 rc = GPG_ERR_INV_ARG;
833 else if (check_pubkey_algo (algorithm, use))
834 rc = GPG_ERR_PUBKEY_ALGO;
835 break;
836 }
837
838 case GCRYCTL_GET_ALGO_USAGE:
839 {
840 gcry_pk_spec_t *spec;
841
842 spec = spec_from_algo (algorithm);
843 *nbytes = spec? spec->use : 0;
844 break;
845 }
846
847 case GCRYCTL_GET_ALGO_NPKEY:
848 {
849 /* FIXME? */
850 int npkey = pubkey_get_npkey (algorithm);
851 *nbytes = npkey;
852 break;
853 }
854 case GCRYCTL_GET_ALGO_NSKEY:
855 {
856 /* FIXME? */
857 int nskey = pubkey_get_nskey (algorithm);
858 *nbytes = nskey;
859 break;
860 }
861 case GCRYCTL_GET_ALGO_NSIGN:
862 {
863 /* FIXME? */
864 int nsign = pubkey_get_nsig (algorithm);
865 *nbytes = nsign;
866 break;
867 }
868 case GCRYCTL_GET_ALGO_NENCR:
869 {
870 /* FIXME? */
871 int nencr = pubkey_get_nenc (algorithm);
872 *nbytes = nencr;
873 break;
874 }
875
876 default:
877 rc = GPG_ERR_INV_OP;
878 }
879
880 return rc;
881 }
882
883
884 /* Return an S-expression representing the context CTX. Depending on
885 the state of that context, the S-expression may either be a public
886 key, a private key or any other object used with public key
887 operations. On success a new S-expression is stored at R_SEXP and
888 0 is returned, on error NULL is store there and an error code is
889 returned. MODE is either 0 or one of the GCRY_PK_GET_xxx values.
890
891 As of now it only support certain ECC operations because a context
892 object is right now only defined for ECC. Over time this function
893 will be extended to cover more algorithms. Note also that the name
894 of the function is gcry_pubkey_xxx and not gcry_pk_xxx. The idea
895 is that we will eventually provide variants of the existing
896 gcry_pk_xxx functions which will take a context parameter. */
897 gcry_err_code_t
_gcry_pubkey_get_sexp(gcry_sexp_t * r_sexp,int mode,gcry_ctx_t ctx)898 _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
899 {
900 mpi_ec_t ec;
901
902 if (!r_sexp)
903 return GPG_ERR_INV_VALUE;
904 *r_sexp = NULL;
905 switch (mode)
906 {
907 case 0:
908 case GCRY_PK_GET_PUBKEY:
909 case GCRY_PK_GET_SECKEY:
910 break;
911 default:
912 return GPG_ERR_INV_VALUE;
913 }
914 if (!ctx)
915 return GPG_ERR_NO_CRYPT_CTX;
916
917 ec = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_EC);
918 if (ec)
919 return _gcry_pk_ecc_get_sexp (r_sexp, mode, ec);
920
921 return GPG_ERR_WRONG_CRYPT_CTX;
922 }
923
924
925
926 /* Explicitly initialize this module. */
927 gcry_err_code_t
_gcry_pk_init(void)928 _gcry_pk_init (void)
929 {
930 if (fips_mode())
931 {
932 /* disable algorithms that are disallowed in fips */
933 int idx;
934 gcry_pk_spec_t *spec;
935
936 for (idx = 0; (spec = pubkey_list[idx]); idx++)
937 if (!spec->flags.fips)
938 spec->flags.disabled = 1;
939 }
940
941 return 0;
942 }
943
944
945 /* Run the selftests for pubkey algorithm ALGO with optional reporting
946 function REPORT. */
947 gpg_error_t
_gcry_pk_selftest(int algo,int extended,selftest_report_func_t report)948 _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
949 {
950 gcry_err_code_t ec;
951 gcry_pk_spec_t *spec;
952
953 algo = map_algo (algo);
954 spec = spec_from_algo (algo);
955 if (spec && !spec->flags.disabled && spec->selftest)
956 ec = spec->selftest (algo, extended, report);
957 else
958 {
959 ec = GPG_ERR_PUBKEY_ALGO;
960 /* Fixme: We need to change the report function to allow passing
961 of an encryption mode (e.g. pkcs1, ecdsa, or ecdh). */
962 if (report)
963 report ("pubkey", algo, "module",
964 spec && !spec->flags.disabled?
965 "no selftest available" :
966 spec? "algorithm disabled" :
967 "algorithm not found");
968 }
969
970 return gpg_error (ec);
971 }
972