removed unused variables.
[gnutls.git] / lib / opencdk / pubkey.c
blob492a0f2ef3066de6020bf9547fa908f6db4b4552
1 /* pubkey.c - Public key API
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Timo Schulz
6 * This file is part of OpenCDK.
8 * The OpenCDK library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include <gnutls_int.h>
27 #include <gnutls_datum.h>
28 #include <gnutls_pk.h>
29 #include <gnutls_sig.h>
30 #include <x509/common.h>
31 #include "opencdk.h"
32 #include "main.h"
33 #include "packet.h"
35 /* This function gets the signature parameters and encodes
36 * them into a way for _gnutls_pk_verify to use.
38 static cdk_error_t
39 sig_to_datum (gnutls_datum_t * r_sig, cdk_pkt_signature_t sig)
41 int err;
42 cdk_error_t rc;
44 if (!r_sig || !sig)
45 return CDK_Inv_Value;
47 rc = 0;
48 if (is_RSA (sig->pubkey_algo))
50 err = _gnutls_mpi_dprint (sig->mpi[0], r_sig);
51 if (err < 0)
52 rc = map_gnutls_error (err);
54 else if (is_DSA (sig->pubkey_algo))
56 err = _gnutls_encode_ber_rs (r_sig, sig->mpi[0], sig->mpi[1]);
57 if (err < 0)
58 rc = map_gnutls_error (err);
60 else
61 rc = CDK_Inv_Algo;
62 return rc;
65 /**
66 * cdk_pk_verify:
67 * @pk: the public key
68 * @sig: signature
69 * @md: the message digest
71 * Verify the signature in @sig and compare it with the message digest in @md.
72 **/
73 cdk_error_t
74 cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
76 gnutls_datum_t s_sig = { NULL, 0}, di = {NULL, 0};
77 byte *encmd = NULL;
78 size_t enclen;
79 cdk_error_t rc;
80 int ret, algo;
81 unsigned int i;
82 gnutls_pk_params_st params;
84 if (!pk || !sig || !md)
86 gnutls_assert ();
87 return CDK_Inv_Value;
90 if (is_DSA (pk->pubkey_algo))
91 algo = GNUTLS_PK_DSA;
92 else if (is_RSA (pk->pubkey_algo))
93 algo = GNUTLS_PK_RSA;
94 else
96 gnutls_assert ();
97 return CDK_Inv_Value;
100 rc = sig_to_datum (&s_sig, sig);
101 if (rc)
103 gnutls_assert ();
104 goto leave;
107 rc = _gnutls_set_datum (&di, md, _gnutls_hash_get_algo_len (sig->digest_algo));
108 if (rc < 0)
110 rc = gnutls_assert_val(CDK_Out_Of_Core);
111 goto leave;
114 rc = pk_prepare_hash (algo, sig->digest_algo, &di);
115 if (rc < 0)
117 rc = gnutls_assert_val(CDK_General_Error);
118 goto leave;
121 params.params_nr = cdk_pk_get_npkey (pk->pubkey_algo);
122 for (i = 0; i < params.params_nr; i++)
123 params.params[i] = pk->mpi[i];
124 params.flags = 0;
125 ret = _gnutls_pk_verify (algo, &di, &s_sig, &params);
127 if (ret < 0)
129 gnutls_assert ();
130 rc = map_gnutls_error (ret);
131 goto leave;
134 rc = 0;
136 leave:
137 _gnutls_free_datum (&s_sig);
138 _gnutls_free_datum (&di);
139 cdk_free (encmd);
140 return rc;
145 * cdk_pk_get_nbits:
146 * @pk: the public key
148 * Return the length of the public key in bits.
149 * The meaning of length is actually the size of the 'prime'
150 * object in the key. For RSA keys the modulus, for ElG/DSA
151 * the size of the public prime.
154 cdk_pk_get_nbits (cdk_pubkey_t pk)
156 if (!pk || !pk->mpi[0])
157 return 0;
158 return _gnutls_mpi_get_nbits (pk->mpi[0]);
163 * cdk_pk_get_npkey:
164 * @algo: The public key algorithm.
166 * Return the number of multiprecison integer forming an public
167 * key with the given algorithm.
170 cdk_pk_get_npkey (int algo)
172 if (is_RSA (algo))
173 return RSA_PUBLIC_PARAMS;
174 else if (is_DSA (algo))
175 return DSA_PUBLIC_PARAMS;
176 else if (is_ELG (algo))
177 return 3;
178 else
180 gnutls_assert ();
181 return 0;
187 * cdk_pk_get_nskey:
188 * @algo: the public key algorithm
190 * Return the number of multiprecision integers forming an
191 * secret key with the given algorithm.
194 cdk_pk_get_nskey (int algo)
196 int ret;
198 if (is_RSA (algo))
199 ret = RSA_PRIVATE_PARAMS - 2; /* we don't have exp1 and exp2 */
200 else if (is_DSA (algo))
201 ret = DSA_PRIVATE_PARAMS;
202 else if (is_ELG (algo))
203 ret = 4;
204 else
206 gnutls_assert ();
207 return 0;
210 ret -= cdk_pk_get_npkey (algo);
211 return ret;
216 * cdk_pk_get_nbits:
217 * @algo: the public key algorithm
219 * Return the number of MPIs a signature consists of.
222 cdk_pk_get_nsig (int algo)
224 if (is_RSA (algo))
225 return 1;
226 else if (is_DSA (algo))
227 return 2;
228 else
229 return 0;
234 * cdk_pk_get_nenc:
235 * @algo: the public key algorithm
237 * Return the number of MPI's the encrypted data consists of.
240 cdk_pk_get_nenc (int algo)
242 if (is_RSA (algo))
243 return 1;
244 else if (is_ELG (algo))
245 return 2;
246 else
247 return 0;
252 _cdk_pk_algo_usage (int algo)
254 int usage;
256 /* The ElGamal sign+encrypt algorithm is not supported any longer. */
257 switch (algo)
259 case CDK_PK_RSA:
260 usage = CDK_KEY_USG_SIGN | CDK_KEY_USG_ENCR;
261 break;
262 case CDK_PK_RSA_E:
263 usage = CDK_KEY_USG_ENCR;
264 break;
265 case CDK_PK_RSA_S:
266 usage = CDK_KEY_USG_SIGN;
267 break;
268 case CDK_PK_ELG_E:
269 usage = CDK_KEY_USG_ENCR;
270 break;
271 case CDK_PK_DSA:
272 usage = CDK_KEY_USG_SIGN;
273 break;
274 default:
275 usage = 0;
277 return usage;
280 /* You can use a NULL buf to get the output size only
282 static cdk_error_t
283 mpi_to_buffer (bigint_t a, byte * buf, size_t buflen,
284 size_t * r_nwritten, size_t * r_nbits)
286 size_t nbits;
287 int err;
289 if (!a || !r_nwritten)
291 gnutls_assert ();
292 return CDK_Inv_Value;
295 nbits = _gnutls_mpi_get_nbits (a);
296 if (r_nbits)
297 *r_nbits = nbits;
299 if (r_nwritten)
300 *r_nwritten = (nbits + 7) / 8 + 2;
302 if ((nbits + 7) / 8 + 2 > buflen)
303 return CDK_Too_Short;
305 *r_nwritten = buflen;
306 err = _gnutls_mpi_print (a, buf, r_nwritten);
307 if (err < 0)
309 gnutls_assert ();
310 return map_gnutls_error (err);
313 return 0;
318 * cdk_pk_get_mpi:
319 * @pk: public key
320 * @idx: index of the MPI to retrieve
321 * @buf: buffer to hold the raw data
322 * @r_nwritten: output how large the raw data is
323 * @r_nbits: size of the MPI in bits.
325 * Return the MPI with the given index of the public key.
327 cdk_error_t
328 cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx,
329 byte * buf, size_t buflen, size_t * r_nwritten,
330 size_t * r_nbits)
332 if (!pk || !r_nwritten)
333 return CDK_Inv_Value;
335 if ((ssize_t) idx > cdk_pk_get_npkey (pk->pubkey_algo))
336 return CDK_Inv_Value;
337 return mpi_to_buffer (pk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
342 * cdk_sk_get_mpi:
343 * @sk: secret key
344 * @idx: index of the MPI to retrieve
345 * @buf: buffer to hold the raw data
346 * @r_nwritten: output length of the raw data
347 * @r_nbits: length of the MPI data in bits.
349 * Return the MPI of the given secret key with the
350 * index @idx. It is important to check if the key
351 * is protected and thus no real MPI data will be returned then.
353 cdk_error_t
354 cdk_sk_get_mpi (cdk_pkt_seckey_t sk, size_t idx,
355 byte * buf, size_t buflen, size_t * r_nwritten,
356 size_t * r_nbits)
358 if (!sk || !r_nwritten)
359 return CDK_Inv_Value;
361 if ((ssize_t) idx > cdk_pk_get_nskey (sk->pubkey_algo))
362 return CDK_Inv_Value;
363 return mpi_to_buffer (sk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
367 static u16
368 checksum_mpi (bigint_t m)
370 byte buf[MAX_MPI_BYTES + 2];
371 size_t nread;
372 unsigned int i;
373 u16 chksum = 0;
375 if (!m)
376 return 0;
377 nread = DIM (buf);
378 if (_gnutls_mpi_print_pgp (m, buf, &nread) < 0)
379 return 0;
380 for (i = 0; i < nread; i++)
381 chksum += buf[i];
382 return chksum;
386 * cdk_pk_from_secret_key:
387 * @sk: the secret key
388 * @ret_pk: the new public key
390 * Create a new public key from a secret key.
392 cdk_error_t
393 cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t * ret_pk)
395 if (!sk)
396 return CDK_Inv_Value;
397 return _cdk_copy_pubkey (ret_pk, sk->pk);
402 _cdk_sk_get_csum (cdk_pkt_seckey_t sk)
404 u16 csum = 0, i;
406 if (!sk)
407 return 0;
408 for (i = 0; i < cdk_pk_get_nskey (sk->pubkey_algo); i++)
409 csum += checksum_mpi (sk->mpi[i]);
410 return csum;
415 * cdk_pk_get_fingerprint:
416 * @pk: the public key
417 * @fpr: the buffer to hold the fingerprint
419 * Return the fingerprint of the given public key.
420 * The buffer must be at least 20 octets.
421 * This function should be considered deprecated and
422 * the new cdk_pk_to_fingerprint() should be used whenever
423 * possible to avoid overflows.
425 cdk_error_t
426 cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr)
428 digest_hd_st hd;
429 int md_algo;
430 int dlen = 0;
431 int err;
433 if (!pk || !fpr)
434 return CDK_Inv_Value;
436 if (pk->version < 4 && is_RSA (pk->pubkey_algo))
437 md_algo = GNUTLS_DIG_MD5; /* special */
438 else
439 md_algo = GNUTLS_DIG_SHA1;
440 dlen = _gnutls_hash_get_algo_len (md_algo);
441 err = _gnutls_hash_init (&hd, md_algo);
442 if (err < 0)
444 gnutls_assert ();
445 return map_gnutls_error (err);
447 _cdk_hash_pubkey (pk, &hd, 1);
448 _gnutls_hash_deinit (&hd, fpr);
449 if (dlen == 16)
450 memset (fpr + 16, 0, 4);
451 return 0;
456 * cdk_pk_to_fingerprint:
457 * @pk: the public key
458 * @fprbuf: buffer to save the fingerprint
459 * @fprbuflen: buffer size
460 * @r_nout: actual length of the fingerprint.
462 * Calculate a fingerprint of the given key and
463 * return it in the given byte array.
465 cdk_error_t
466 cdk_pk_to_fingerprint (cdk_pubkey_t pk,
467 byte * fprbuf, size_t fprbuflen, size_t * r_nout)
469 size_t key_fprlen;
470 cdk_error_t err;
472 if (!pk)
473 return CDK_Inv_Value;
475 if (pk->version < 4)
476 key_fprlen = 16;
477 else
478 key_fprlen = 20;
480 /* Only return the required buffer size for the fingerprint. */
481 if (!fprbuf && !fprbuflen && r_nout)
483 *r_nout = key_fprlen;
484 return 0;
487 if (!fprbuf || key_fprlen > fprbuflen)
488 return CDK_Too_Short;
490 err = cdk_pk_get_fingerprint (pk, fprbuf);
491 if (r_nout)
492 *r_nout = key_fprlen;
494 return err;
499 * cdk_pk_fingerprint_get_keyid:
500 * @fpr: the key fingerprint
501 * @fprlen: the length of the fingerprint
503 * Derive the key ID from the key fingerprint.
504 * For version 3 keys, this is not working.
507 cdk_pk_fingerprint_get_keyid (const byte * fpr, size_t fprlen, u32 * keyid)
509 u32 lowbits = 0;
511 /* In this case we say the key is a V3 RSA key and we can't
512 use the fingerprint to get the keyid. */
513 if (fpr && fprlen == 16)
515 keyid[0] = 0;
516 keyid[1] = 0;
517 return 0;
519 else if (keyid && fpr)
521 keyid[0] = _cdk_buftou32 (fpr + 12);
522 keyid[1] = _cdk_buftou32 (fpr + 16);
523 lowbits = keyid[1];
525 else if (fpr)
526 lowbits = _cdk_buftou32 (fpr + 16);
527 return lowbits;
532 * cdk_pk_get_keyid:
533 * @pk: the public key
534 * @keyid: buffer to store the key ID
536 * Calculate the key ID of the given public key.
539 cdk_pk_get_keyid (cdk_pubkey_t pk, u32 * keyid)
541 u32 lowbits = 0;
542 byte buf[24];
544 if (pk && (!pk->keyid[0] || !pk->keyid[1]))
546 if (pk->version < 4 && is_RSA (pk->pubkey_algo))
548 byte p[MAX_MPI_BYTES];
549 size_t n;
551 n = MAX_MPI_BYTES;
552 _gnutls_mpi_print (pk->mpi[0], p, &n);
553 pk->keyid[0] =
554 p[n - 8] << 24 | p[n - 7] << 16 | p[n - 6] << 8 | p[n - 5];
555 pk->keyid[1] =
556 p[n - 4] << 24 | p[n - 3] << 16 | p[n - 2] << 8 | p[n - 1];
558 else if (pk->version == 4)
560 cdk_pk_get_fingerprint (pk, buf);
561 pk->keyid[0] = _cdk_buftou32 (buf + 12);
562 pk->keyid[1] = _cdk_buftou32 (buf + 16);
565 lowbits = pk ? pk->keyid[1] : 0;
566 if (keyid && pk)
568 keyid[0] = pk->keyid[0];
569 keyid[1] = pk->keyid[1];
572 return lowbits;
577 * cdk_sk_get_keyid:
578 * @sk: the secret key
579 * @keyid: buffer to hold the key ID
581 * Calculate the key ID of the secret key, actually the public key.
584 cdk_sk_get_keyid (cdk_pkt_seckey_t sk, u32 * keyid)
586 u32 lowbits = 0;
588 if (sk && sk->pk)
590 lowbits = cdk_pk_get_keyid (sk->pk, keyid);
591 sk->keyid[0] = sk->pk->keyid[0];
592 sk->keyid[1] = sk->pk->keyid[1];
595 return lowbits;
600 * cdk_sig_get_keyid:
601 * @sig: the signature
602 * @keyid: buffer to hold the key ID
604 * Retrieve the key ID from the given signature.
607 cdk_sig_get_keyid (cdk_pkt_signature_t sig, u32 * keyid)
609 u32 lowbits = sig ? sig->keyid[1] : 0;
611 if (keyid && sig)
613 keyid[0] = sig->keyid[0];
614 keyid[1] = sig->keyid[1];
616 return lowbits;
620 /* Return the key ID from the given packet.
621 If this is not possible, 0 is returned */
623 _cdk_pkt_get_keyid (cdk_packet_t pkt, u32 * keyid)
625 u32 lowbits;
627 if (!pkt)
628 return 0;
630 switch (pkt->pkttype)
632 case CDK_PKT_PUBLIC_KEY:
633 case CDK_PKT_PUBLIC_SUBKEY:
634 lowbits = cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
635 break;
637 case CDK_PKT_SECRET_KEY:
638 case CDK_PKT_SECRET_SUBKEY:
639 lowbits = cdk_sk_get_keyid (pkt->pkt.secret_key, keyid);
640 break;
642 case CDK_PKT_SIGNATURE:
643 lowbits = cdk_sig_get_keyid (pkt->pkt.signature, keyid);
644 break;
646 default:
647 lowbits = 0;
648 break;
651 return lowbits;
655 /* Get the fingerprint of the packet if possible. */
656 cdk_error_t
657 _cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte * fpr)
659 if (!pkt || !fpr)
660 return CDK_Inv_Value;
662 switch (pkt->pkttype)
664 case CDK_PKT_PUBLIC_KEY:
665 case CDK_PKT_PUBLIC_SUBKEY:
666 return cdk_pk_get_fingerprint (pkt->pkt.public_key, fpr);
668 case CDK_PKT_SECRET_KEY:
669 case CDK_PKT_SECRET_SUBKEY:
670 return cdk_pk_get_fingerprint (pkt->pkt.secret_key->pk, fpr);
672 default:
673 return CDK_Inv_Mode;
675 return 0;