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