Added (back) RFC5081 support in client mode.
[gnutls.git] / lib / openpgp / privkey.c
blob77ef7b403ac341406f212b68dcdb26756ce93b59
1 /*
2 * Copyright (C) 2003-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS 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 /* Functions on OpenPGP privkey parsing
26 #include <gnutls_int.h>
27 #include <gnutls_datum.h>
28 #include <gnutls_global.h>
29 #include <gnutls_errors.h>
30 #include <gnutls_num.h>
31 #include <openpgp_int.h>
32 #include <gnutls_openpgp.h>
33 #include <gnutls_sig.h>
34 #include <gnutls_pk.h>
36 /**
37 * gnutls_openpgp_privkey_init:
38 * @key: The structure to be initialized
40 * This function will initialize an OpenPGP key structure.
42 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
43 **/
44 int
45 gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key)
47 *key = gnutls_calloc (1, sizeof (gnutls_openpgp_privkey_int));
49 if (*key)
50 return 0; /* success */
51 return GNUTLS_E_MEMORY_ERROR;
54 /**
55 * gnutls_openpgp_privkey_deinit:
56 * @key: The structure to be initialized
58 * This function will deinitialize a key structure.
59 **/
60 void
61 gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key)
63 if (!key)
64 return;
66 if (key->knode)
68 cdk_kbnode_release (key->knode);
69 key->knode = NULL;
72 gnutls_free (key);
75 /*-
76 * _gnutls_openpgp_privkey_cpy - This function copies a gnutls_openpgp_privkey_t structure
77 * @dest: The structure where to copy
78 * @src: The structure to be copied
80 * This function will copy an X.509 certificate structure.
82 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
83 * negative error value.
84 -*/
85 int
86 _gnutls_openpgp_privkey_cpy (gnutls_openpgp_privkey_t dest, gnutls_openpgp_privkey_t src)
88 int ret;
89 size_t raw_size=0;
90 uint8_t *der;
91 gnutls_datum_t tmp;
93 ret = gnutls_openpgp_privkey_export (src, GNUTLS_OPENPGP_FMT_RAW, NULL, 0, NULL, &raw_size);
94 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
95 return gnutls_assert_val(ret);
97 der = gnutls_malloc (raw_size);
98 if (der == NULL)
99 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
101 ret = gnutls_openpgp_privkey_export (src, GNUTLS_OPENPGP_FMT_RAW, NULL, 0, der, &raw_size);
102 if (ret < 0)
104 gnutls_assert ();
105 gnutls_free (der);
106 return ret;
109 tmp.data = der;
110 tmp.size = raw_size;
111 ret = gnutls_openpgp_privkey_import (dest, &tmp, GNUTLS_OPENPGP_FMT_RAW, NULL, 0);
113 gnutls_free (der);
115 if (ret < 0)
116 return gnutls_assert_val(ret);
118 memcpy(dest->preferred_keyid, src->preferred_keyid, GNUTLS_OPENPGP_KEYID_SIZE);
119 dest->preferred_set = src->preferred_set;
121 return 0;
125 * gnutls_openpgp_privkey_sec_param:
126 * @key: a key structure
128 * This function will return the security parameter appropriate with
129 * this private key.
131 * Returns: On success, a valid security parameter is returned otherwise
132 * %GNUTLS_SEC_PARAM_UNKNOWN is returned.
134 * Since: 2.12.0
136 gnutls_sec_param_t
137 gnutls_openpgp_privkey_sec_param (gnutls_openpgp_privkey_t key)
139 gnutls_pk_algorithm_t algo;
140 unsigned int bits;
142 algo = gnutls_openpgp_privkey_get_pk_algorithm (key, &bits);
143 if (algo == GNUTLS_PK_UNKNOWN)
145 gnutls_assert ();
146 return GNUTLS_SEC_PARAM_UNKNOWN;
149 return gnutls_pk_bits_to_sec_param (algo, bits);
153 * gnutls_openpgp_privkey_import:
154 * @key: The structure to store the parsed key.
155 * @data: The RAW or BASE64 encoded key.
156 * @format: One of #gnutls_openpgp_crt_fmt_t elements.
157 * @password: not used for now
158 * @flags: should be (0)
160 * This function will convert the given RAW or Base64 encoded key to
161 * the native gnutls_openpgp_privkey_t format. The output will be
162 * stored in 'key'.
164 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
167 gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key,
168 const gnutls_datum_t * data,
169 gnutls_openpgp_crt_fmt_t format,
170 const char *password, unsigned int flags)
172 cdk_packet_t pkt;
173 int rc, armor;
175 if (data->data == NULL || data->size == 0)
177 gnutls_assert ();
178 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
181 if (format == GNUTLS_OPENPGP_FMT_RAW)
182 armor = 0;
183 else armor = 1;
185 rc = cdk_kbnode_read_from_mem (&key->knode, armor, data->data, data->size);
186 if (rc != 0)
188 rc = _gnutls_map_cdk_rc (rc);
189 gnutls_assert ();
190 return rc;
193 /* Test if the import was successful. */
194 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
195 if (pkt == NULL)
197 gnutls_assert ();
198 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
201 return 0;
205 * gnutls_openpgp_privkey_export:
206 * @key: Holds the key.
207 * @format: One of gnutls_openpgp_crt_fmt_t elements.
208 * @password: the password that will be used to encrypt the key. (unused for now)
209 * @flags: (0) for future compatibility
210 * @output_data: will contain the key base64 encoded or raw
211 * @output_data_size: holds the size of output_data (and will be
212 * replaced by the actual size of parameters)
214 * This function will convert the given key to RAW or Base64 format.
215 * If the buffer provided is not long enough to hold the output, then
216 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
218 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
220 * Since: 2.4.0
223 gnutls_openpgp_privkey_export (gnutls_openpgp_privkey_t key,
224 gnutls_openpgp_crt_fmt_t format,
225 const char *password, unsigned int flags,
226 void *output_data, size_t * output_data_size)
228 /* FIXME for now we do not export encrypted keys */
229 return _gnutls_openpgp_export (key->knode, format, output_data,
230 output_data_size, 1);
234 * gnutls_openpgp_privkey_export2:
235 * @key: Holds the key.
236 * @format: One of gnutls_openpgp_crt_fmt_t elements.
237 * @password: the password that will be used to encrypt the key. (unused for now)
238 * @flags: (0) for future compatibility
239 * @out: will contain the raw or based64 encoded key
241 * This function will convert the given key to RAW or Base64 format.
242 * The output buffer is allocated using gnutls_malloc().
244 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
246 * Since: 3.1
249 gnutls_openpgp_privkey_export2 (gnutls_openpgp_privkey_t key,
250 gnutls_openpgp_crt_fmt_t format,
251 const char *password, unsigned int flags,
252 gnutls_datum_t *out)
254 /* FIXME for now we do not export encrypted keys */
255 return _gnutls_openpgp_export2 (key->knode, format, out, 1);
260 * gnutls_openpgp_privkey_get_pk_algorithm:
261 * @key: is an OpenPGP key
262 * @bits: if bits is non null it will hold the size of the parameters' in bits
264 * This function will return the public key algorithm of an OpenPGP
265 * certificate.
267 * If bits is non null, it should have enough size to hold the parameters
268 * size in bits. For RSA the bits returned is the modulus.
269 * For DSA the bits returned are of the public exponent.
271 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
272 * success, or a negative error code on error.
274 * Since: 2.4.0
276 gnutls_pk_algorithm_t
277 gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key,
278 unsigned int *bits)
280 cdk_packet_t pkt;
281 int algo = 0, ret;
282 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
284 if (!key)
286 gnutls_assert ();
287 return GNUTLS_PK_UNKNOWN;
290 ret = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid);
291 if (ret == 0)
293 int idx;
295 idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
296 if (idx != GNUTLS_OPENPGP_MASTER_KEYID_IDX)
298 algo =
299 gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, bits);
300 return algo;
304 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
305 if (pkt)
307 if (bits)
308 *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk);
309 algo = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo);
312 return algo;
316 _gnutls_openpgp_get_algo (int cdk_algo)
318 int algo;
320 if (is_RSA (cdk_algo))
321 algo = GNUTLS_PK_RSA;
322 else if (is_DSA (cdk_algo))
323 algo = GNUTLS_PK_DSA;
324 else
326 _gnutls_debug_log ("Unknown OpenPGP algorithm %d\n", cdk_algo);
327 algo = GNUTLS_PK_UNKNOWN;
330 return algo;
334 * gnutls_openpgp_privkey_get_revoked_status:
335 * @key: the structure that contains the OpenPGP private key.
337 * Get revocation status of key.
339 * Returns: true (1) if the key has been revoked, or false (0) if it
340 * has not, or a negative error code indicates an error.
342 * Since: 2.4.0
345 gnutls_openpgp_privkey_get_revoked_status (gnutls_openpgp_privkey_t key)
347 cdk_packet_t pkt;
349 if (!key)
351 gnutls_assert ();
352 return GNUTLS_E_INVALID_REQUEST;
355 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
356 if (!pkt)
357 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
359 if (pkt->pkt.secret_key->is_revoked != 0)
360 return 1;
361 return 0;
365 * gnutls_openpgp_privkey_get_fingerprint:
366 * @key: the raw data that contains the OpenPGP secret key.
367 * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
368 * @fprlen: the integer to save the length of the fingerprint.
370 * Get the fingerprint of the OpenPGP key. Depends on the
371 * algorithm, the fingerprint can be 16 or 20 bytes.
373 * Returns: On success, 0 is returned, or an error code.
375 * Since: 2.4.0
378 gnutls_openpgp_privkey_get_fingerprint (gnutls_openpgp_privkey_t key,
379 void *fpr, size_t * fprlen)
381 cdk_packet_t pkt;
382 cdk_pkt_pubkey_t pk = NULL;
384 if (!fpr || !fprlen)
386 gnutls_assert ();
387 return GNUTLS_E_INVALID_REQUEST;
390 *fprlen = 0;
392 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
393 if (!pkt)
395 gnutls_assert ();
396 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
399 pk = pkt->pkt.secret_key->pk;
400 *fprlen = 20;
402 if (is_RSA (pk->pubkey_algo) && pk->version < 4)
403 *fprlen = 16;
405 cdk_pk_get_fingerprint (pk, fpr);
407 return 0;
411 * gnutls_openpgp_privkey_get_key_id:
412 * @key: the structure that contains the OpenPGP secret key.
413 * @keyid: the buffer to save the keyid.
415 * Get key-id.
417 * Returns: the 64-bit keyID of the OpenPGP key.
419 * Since: 2.4.0
422 gnutls_openpgp_privkey_get_key_id (gnutls_openpgp_privkey_t key,
423 gnutls_openpgp_keyid_t keyid)
425 cdk_packet_t pkt;
426 uint32_t kid[2];
428 if (!key || !keyid)
430 gnutls_assert ();
431 return GNUTLS_E_INVALID_REQUEST;
434 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
435 if (!pkt)
436 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
438 cdk_sk_get_keyid (pkt->pkt.secret_key, kid);
439 _gnutls_write_uint32 (kid[0], keyid);
440 _gnutls_write_uint32 (kid[1], keyid + 4);
442 return 0;
446 * gnutls_openpgp_privkey_get_subkey_count:
447 * @key: is an OpenPGP key
449 * This function will return the number of subkeys present in the
450 * given OpenPGP certificate.
452 * Returns: the number of subkeys, or a negative error code on error.
454 * Since: 2.4.0
457 gnutls_openpgp_privkey_get_subkey_count (gnutls_openpgp_privkey_t key)
459 cdk_kbnode_t p, ctx;
460 cdk_packet_t pkt;
461 int subkeys;
463 if (key == NULL)
465 gnutls_assert ();
466 return 0;
469 ctx = NULL;
470 subkeys = 0;
471 while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
473 pkt = cdk_kbnode_get_packet (p);
474 if (pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
475 subkeys++;
478 return subkeys;
481 /* returns the subkey with the given index */
482 static cdk_packet_t
483 _get_secret_subkey (gnutls_openpgp_privkey_t key, unsigned int indx)
485 cdk_kbnode_t p, ctx;
486 cdk_packet_t pkt;
487 unsigned int subkeys;
489 ctx = NULL;
490 subkeys = 0;
491 while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
493 pkt = cdk_kbnode_get_packet (p);
494 if (pkt->pkttype == CDK_PKT_SECRET_SUBKEY && indx == subkeys++)
495 return pkt;
498 return NULL;
502 * gnutls_openpgp_privkey_get_subkey_revoked_status:
503 * @key: the structure that contains the OpenPGP private key.
504 * @idx: is the subkey index
506 * Get revocation status of key.
508 * Returns: true (1) if the key has been revoked, or false (0) if it
509 * has not, or a negative error code indicates an error.
511 * Since: 2.4.0
514 gnutls_openpgp_privkey_get_subkey_revoked_status (gnutls_openpgp_privkey_t
515 key, unsigned int idx)
517 cdk_packet_t pkt;
519 if (!key)
521 gnutls_assert ();
522 return GNUTLS_E_INVALID_REQUEST;
525 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
526 return gnutls_openpgp_privkey_get_revoked_status(key);
528 pkt = _get_secret_subkey (key, idx);
529 if (!pkt)
530 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
532 if (pkt->pkt.secret_key->is_revoked != 0)
533 return 1;
534 return 0;
538 * gnutls_openpgp_privkey_get_subkey_pk_algorithm:
539 * @key: is an OpenPGP key
540 * @idx: is the subkey index
541 * @bits: if bits is non null it will hold the size of the parameters' in bits
543 * This function will return the public key algorithm of a subkey of an OpenPGP
544 * certificate.
546 * If bits is non null, it should have enough size to hold the parameters
547 * size in bits. For RSA the bits returned is the modulus.
548 * For DSA the bits returned are of the public exponent.
550 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
551 * success, or a negative error code on error.
553 * Since: 2.4.0
555 gnutls_pk_algorithm_t
556 gnutls_openpgp_privkey_get_subkey_pk_algorithm (gnutls_openpgp_privkey_t key,
557 unsigned int idx,
558 unsigned int *bits)
560 cdk_packet_t pkt;
561 int algo;
563 if (!key)
565 gnutls_assert ();
566 return GNUTLS_PK_UNKNOWN;
569 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
570 return gnutls_openpgp_privkey_get_pk_algorithm(key, bits);
572 pkt = _get_secret_subkey (key, idx);
574 algo = 0;
575 if (pkt)
577 if (bits)
578 *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk);
579 algo = pkt->pkt.secret_key->pubkey_algo;
580 if (is_RSA (algo))
581 algo = GNUTLS_PK_RSA;
582 else if (is_DSA (algo))
583 algo = GNUTLS_PK_DSA;
584 else
585 algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
588 return algo;
592 * gnutls_openpgp_privkey_get_subkey_idx:
593 * @key: the structure that contains the OpenPGP private key.
594 * @keyid: the keyid.
596 * Get index of subkey.
598 * Returns: the index of the subkey or a negative error value.
600 * Since: 2.4.0
603 gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key,
604 const gnutls_openpgp_keyid_t keyid)
606 int ret;
607 uint32_t kid[2];
608 uint8_t master_id[GNUTLS_OPENPGP_KEYID_SIZE];
610 if (!key)
612 gnutls_assert ();
613 return GNUTLS_E_INVALID_REQUEST;
616 ret = gnutls_openpgp_privkey_get_key_id (key, master_id);
617 if (ret < 0)
618 return gnutls_assert_val(ret);
619 if (memcmp(master_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE)==0)
620 return GNUTLS_OPENPGP_MASTER_KEYID_IDX;
622 KEYID_IMPORT (kid, keyid);
623 ret = _gnutls_openpgp_find_subkey_idx (key->knode, kid, 1);
625 if (ret < 0)
627 gnutls_assert ();
630 return ret;
634 * gnutls_openpgp_privkey_get_subkey_creation_time:
635 * @key: the structure that contains the OpenPGP private key.
636 * @idx: the subkey index
638 * Get subkey creation time.
640 * Returns: the timestamp when the OpenPGP key was created.
642 * Since: 2.4.0
644 time_t
645 gnutls_openpgp_privkey_get_subkey_creation_time (gnutls_openpgp_privkey_t key,
646 unsigned int idx)
648 cdk_packet_t pkt;
649 time_t timestamp;
651 if (!key)
652 return (time_t) - 1;
654 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
655 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
656 else
657 pkt = _get_secret_subkey (key, idx);
659 if (pkt)
660 timestamp = pkt->pkt.secret_key->pk->timestamp;
661 else
662 timestamp = 0;
664 return timestamp;
668 * gnutls_openpgp_privkey_get_subkey_expiration_time:
669 * @key: the structure that contains the OpenPGP private key.
670 * @idx: the subkey index
672 * Get subkey expiration time. A value of '0' means that the key
673 * doesn't expire at all.
675 * Returns: the time when the OpenPGP key expires.
677 * Since: 2.4.0
679 time_t
680 gnutls_openpgp_privkey_get_subkey_expiration_time (gnutls_openpgp_privkey_t
681 key, unsigned int idx)
683 cdk_packet_t pkt;
684 time_t timestamp;
686 if (!key)
687 return (time_t) - 1;
689 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
690 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
691 else
692 pkt = _get_secret_subkey (key, idx);
694 if (pkt)
695 timestamp = pkt->pkt.secret_key->pk->expiredate;
696 else
697 timestamp = 0;
699 return timestamp;
703 * gnutls_openpgp_privkey_get_subkey_id:
704 * @key: the structure that contains the OpenPGP secret key.
705 * @idx: the subkey index
706 * @keyid: the buffer to save the keyid.
708 * Get the key-id for the subkey.
710 * Returns: the 64-bit keyID of the OpenPGP key.
712 * Since: 2.4.0
715 gnutls_openpgp_privkey_get_subkey_id (gnutls_openpgp_privkey_t key,
716 unsigned int idx,
717 gnutls_openpgp_keyid_t keyid)
719 cdk_packet_t pkt;
720 uint32_t kid[2];
722 if (!key || !keyid)
724 gnutls_assert ();
725 return GNUTLS_E_INVALID_REQUEST;
728 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
729 return gnutls_openpgp_privkey_get_key_id(key, keyid);
731 pkt = _get_secret_subkey (key, idx);
732 if (!pkt)
733 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
735 cdk_sk_get_keyid (pkt->pkt.secret_key, kid);
736 _gnutls_write_uint32 (kid[0], keyid);
737 _gnutls_write_uint32 (kid[1], keyid + 4);
739 return 0;
743 * gnutls_openpgp_privkey_get_subkey_fingerprint:
744 * @key: the raw data that contains the OpenPGP secret key.
745 * @idx: the subkey index
746 * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
747 * @fprlen: the integer to save the length of the fingerprint.
749 * Get the fingerprint of an OpenPGP subkey. Depends on the
750 * algorithm, the fingerprint can be 16 or 20 bytes.
752 * Returns: On success, 0 is returned, or an error code.
754 * Since: 2.4.0
757 gnutls_openpgp_privkey_get_subkey_fingerprint (gnutls_openpgp_privkey_t key,
758 unsigned int idx,
759 void *fpr, size_t * fprlen)
761 cdk_packet_t pkt;
762 cdk_pkt_pubkey_t pk = NULL;
764 if (!fpr || !fprlen)
766 gnutls_assert ();
767 return GNUTLS_E_INVALID_REQUEST;
770 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
771 return gnutls_openpgp_privkey_get_fingerprint(key, fpr, fprlen);
773 *fprlen = 0;
775 pkt = _get_secret_subkey (key, idx);
776 if (!pkt)
777 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
780 pk = pkt->pkt.secret_key->pk;
781 *fprlen = 20;
783 if (is_RSA (pk->pubkey_algo) && pk->version < 4)
784 *fprlen = 16;
786 cdk_pk_get_fingerprint (pk, fpr);
788 return 0;
791 /* Extracts DSA and RSA parameters from a certificate.
794 _gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey,
795 uint32_t * keyid /*[2] */ ,
796 gnutls_pk_params_st * params)
798 int result;
799 unsigned int i, pk_algorithm;
800 cdk_packet_t pkt;
802 gnutls_pk_params_init(params);
804 if (keyid == NULL)
805 pkt = cdk_kbnode_find_packet (pkey->knode, CDK_PKT_SECRET_KEY);
806 else
807 pkt = _gnutls_openpgp_find_key (pkey->knode, keyid, 1);
809 if (pkt == NULL)
811 gnutls_assert ();
812 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
815 pk_algorithm =
816 _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo);
818 switch (pk_algorithm)
820 case GNUTLS_PK_RSA:
821 /* openpgp does not hold all parameters as in PKCS #1
823 params->params_nr = RSA_PRIVATE_PARAMS - 2;
824 break;
825 case GNUTLS_PK_DSA:
826 params->params_nr = DSA_PRIVATE_PARAMS;
827 break;
828 default:
829 gnutls_assert ();
830 return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
833 for (i = 0; i < params->params_nr; i++)
835 result = _gnutls_read_pgp_mpi (pkt, 1, i, &params->params[i]);
836 if (result < 0)
838 gnutls_assert ();
839 goto error;
843 /* fixup will generate exp1 and exp2 that are not
844 * available here.
846 result = _gnutls_pk_fixup (pk_algorithm, GNUTLS_IMPORT, params);
847 if (result < 0)
849 gnutls_assert ();
850 goto error;
853 return 0;
855 error:
856 gnutls_pk_params_release(params);
858 return result;
861 /* The internal version of export
863 static int
864 _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, gnutls_openpgp_keyid_t keyid,
865 gnutls_datum_t * m, gnutls_datum_t * e,
866 gnutls_datum_t * d, gnutls_datum_t * p,
867 gnutls_datum_t * q, gnutls_datum_t * u)
869 int pk_algorithm, ret;
870 cdk_packet_t pkt;
871 uint32_t kid32[2];
872 gnutls_pk_params_st params;
874 if (pkey == NULL)
876 gnutls_assert ();
877 return GNUTLS_E_INVALID_REQUEST;
880 KEYID_IMPORT (kid32, keyid);
882 pkt = _gnutls_openpgp_find_key (pkey->knode, kid32, 1);
883 if (pkt == NULL)
885 gnutls_assert ();
886 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
889 pk_algorithm =
890 _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo);
892 if (pk_algorithm != GNUTLS_PK_RSA)
894 gnutls_assert ();
895 return GNUTLS_E_INVALID_REQUEST;
898 ret = _gnutls_openpgp_privkey_get_mpis (pkey, kid32, &params);
899 if (ret < 0)
901 gnutls_assert ();
902 return ret;
905 ret = _gnutls_mpi_dprint (params.params[0], m);
906 if (ret < 0)
908 gnutls_assert ();
909 goto cleanup;
912 ret = _gnutls_mpi_dprint (params.params[1], e);
913 if (ret < 0)
915 gnutls_assert ();
916 _gnutls_free_datum (m);
917 goto cleanup;
920 ret = _gnutls_mpi_dprint (params.params[2], d);
921 if (ret < 0)
923 gnutls_assert ();
924 _gnutls_free_datum (m);
925 _gnutls_free_datum (e);
926 goto cleanup;
929 ret = _gnutls_mpi_dprint (params.params[3], p);
930 if (ret < 0)
932 gnutls_assert ();
933 _gnutls_free_datum (m);
934 _gnutls_free_datum (e);
935 _gnutls_free_datum (d);
936 goto cleanup;
939 ret = _gnutls_mpi_dprint (params.params[4], q);
940 if (ret < 0)
942 gnutls_assert ();
943 _gnutls_free_datum (m);
944 _gnutls_free_datum (e);
945 _gnutls_free_datum (d);
946 _gnutls_free_datum (p);
947 goto cleanup;
950 ret = _gnutls_mpi_dprint (params.params[5], u);
951 if (ret < 0)
953 gnutls_assert ();
954 _gnutls_free_datum (q);
955 _gnutls_free_datum (m);
956 _gnutls_free_datum (e);
957 _gnutls_free_datum (d);
958 _gnutls_free_datum (p);
959 goto cleanup;
962 ret = 0;
964 cleanup:
965 gnutls_pk_params_release(&params);
966 return ret;
969 static int
970 _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, gnutls_openpgp_keyid_t keyid,
971 gnutls_datum_t * p, gnutls_datum_t * q,
972 gnutls_datum_t * g, gnutls_datum_t * y, gnutls_datum_t * x)
974 int pk_algorithm, ret;
975 cdk_packet_t pkt;
976 uint32_t kid32[2];
977 gnutls_pk_params_st params;
979 if (pkey == NULL)
981 gnutls_assert ();
982 return GNUTLS_E_INVALID_REQUEST;
985 KEYID_IMPORT (kid32, keyid);
987 pkt = _gnutls_openpgp_find_key (pkey->knode, kid32, 1);
988 if (pkt == NULL)
990 gnutls_assert ();
991 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
994 pk_algorithm =
995 _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo);
997 if (pk_algorithm != GNUTLS_PK_DSA)
999 gnutls_assert ();
1000 return GNUTLS_E_INVALID_REQUEST;
1003 ret = _gnutls_openpgp_privkey_get_mpis (pkey, kid32, &params);
1004 if (ret < 0)
1006 gnutls_assert ();
1007 return ret;
1010 /* P */
1011 ret = _gnutls_mpi_dprint (params.params[0], p);
1012 if (ret < 0)
1014 gnutls_assert ();
1015 goto cleanup;
1018 /* Q */
1019 ret = _gnutls_mpi_dprint (params.params[1], q);
1020 if (ret < 0)
1022 gnutls_assert ();
1023 _gnutls_free_datum (p);
1024 goto cleanup;
1028 /* G */
1029 ret = _gnutls_mpi_dprint (params.params[2], g);
1030 if (ret < 0)
1032 gnutls_assert ();
1033 _gnutls_free_datum (p);
1034 _gnutls_free_datum (q);
1035 goto cleanup;
1039 /* Y */
1040 ret = _gnutls_mpi_dprint (params.params[3], y);
1041 if (ret < 0)
1043 gnutls_assert ();
1044 _gnutls_free_datum (p);
1045 _gnutls_free_datum (g);
1046 _gnutls_free_datum (q);
1047 goto cleanup;
1050 ret = _gnutls_mpi_dprint (params.params[4], x);
1051 if (ret < 0)
1053 gnutls_assert ();
1054 _gnutls_free_datum (y);
1055 _gnutls_free_datum (p);
1056 _gnutls_free_datum (g);
1057 _gnutls_free_datum (q);
1058 goto cleanup;
1061 ret = 0;
1063 cleanup:
1064 gnutls_pk_params_release(&params);
1065 return ret;
1070 * gnutls_openpgp_privkey_export_rsa_raw:
1071 * @pkey: Holds the certificate
1072 * @m: will hold the modulus
1073 * @e: will hold the public exponent
1074 * @d: will hold the private exponent
1075 * @p: will hold the first prime (p)
1076 * @q: will hold the second prime (q)
1077 * @u: will hold the coefficient
1079 * This function will export the RSA private key's parameters found in
1080 * the given structure. The new parameters will be allocated using
1081 * gnutls_malloc() and will be stored in the appropriate datum.
1083 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1085 * Since: 2.4.0
1088 gnutls_openpgp_privkey_export_rsa_raw (gnutls_openpgp_privkey_t pkey,
1089 gnutls_datum_t * m, gnutls_datum_t * e,
1090 gnutls_datum_t * d, gnutls_datum_t * p,
1091 gnutls_datum_t * q, gnutls_datum_t * u)
1093 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1094 int ret;
1096 ret = gnutls_openpgp_privkey_get_key_id (pkey, keyid);
1097 if (ret < 0)
1099 gnutls_assert ();
1100 return ret;
1103 return _get_sk_rsa_raw (pkey, keyid, m, e, d, p, q, u);
1107 * gnutls_openpgp_privkey_export_dsa_raw:
1108 * @pkey: Holds the certificate
1109 * @p: will hold the p
1110 * @q: will hold the q
1111 * @g: will hold the g
1112 * @y: will hold the y
1113 * @x: will hold the x
1115 * This function will export the DSA private key's parameters found in
1116 * the given certificate. The new parameters will be allocated using
1117 * gnutls_malloc() and will be stored in the appropriate datum.
1119 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1121 * Since: 2.4.0
1124 gnutls_openpgp_privkey_export_dsa_raw (gnutls_openpgp_privkey_t pkey,
1125 gnutls_datum_t * p, gnutls_datum_t * q,
1126 gnutls_datum_t * g, gnutls_datum_t * y,
1127 gnutls_datum_t * x)
1129 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1130 int ret;
1132 ret = gnutls_openpgp_privkey_get_key_id (pkey, keyid);
1133 if (ret < 0)
1135 gnutls_assert ();
1136 return ret;
1139 return _get_sk_dsa_raw (pkey, keyid, p, q, g, y, x);
1143 * gnutls_openpgp_privkey_export_subkey_rsa_raw:
1144 * @pkey: Holds the certificate
1145 * @idx: Is the subkey index
1146 * @m: will hold the modulus
1147 * @e: will hold the public exponent
1148 * @d: will hold the private exponent
1149 * @p: will hold the first prime (p)
1150 * @q: will hold the second prime (q)
1151 * @u: will hold the coefficient
1153 * This function will export the RSA private key's parameters found in
1154 * the given structure. The new parameters will be allocated using
1155 * gnutls_malloc() and will be stored in the appropriate datum.
1157 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1159 * Since: 2.4.0
1162 gnutls_openpgp_privkey_export_subkey_rsa_raw (gnutls_openpgp_privkey_t pkey,
1163 unsigned int idx,
1164 gnutls_datum_t * m,
1165 gnutls_datum_t * e,
1166 gnutls_datum_t * d,
1167 gnutls_datum_t * p,
1168 gnutls_datum_t * q,
1169 gnutls_datum_t * u)
1171 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1172 int ret;
1174 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
1175 ret = gnutls_openpgp_privkey_get_key_id (pkey, keyid);
1176 else
1177 ret = gnutls_openpgp_privkey_get_subkey_id (pkey, idx, keyid);
1178 if (ret < 0)
1180 gnutls_assert ();
1181 return ret;
1184 return _get_sk_rsa_raw (pkey, keyid, m, e, d, p, q, u);
1188 * gnutls_openpgp_privkey_export_subkey_dsa_raw:
1189 * @pkey: Holds the certificate
1190 * @idx: Is the subkey index
1191 * @p: will hold the p
1192 * @q: will hold the q
1193 * @g: will hold the g
1194 * @y: will hold the y
1195 * @x: will hold the x
1197 * This function will export the DSA private key's parameters found
1198 * in the given certificate. The new parameters will be allocated
1199 * using gnutls_malloc() and will be stored in the appropriate datum.
1201 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1203 * Since: 2.4.0
1206 gnutls_openpgp_privkey_export_subkey_dsa_raw (gnutls_openpgp_privkey_t pkey,
1207 unsigned int idx,
1208 gnutls_datum_t * p,
1209 gnutls_datum_t * q,
1210 gnutls_datum_t * g,
1211 gnutls_datum_t * y,
1212 gnutls_datum_t * x)
1214 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1215 int ret;
1217 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
1218 ret = gnutls_openpgp_privkey_get_key_id (pkey, keyid);
1219 else
1220 ret = gnutls_openpgp_privkey_get_subkey_id (pkey, idx, keyid);
1222 if (ret < 0)
1224 gnutls_assert ();
1225 return ret;
1228 return _get_sk_dsa_raw (pkey, keyid, p, q, g, y, x);
1232 * gnutls_openpgp_privkey_get_preferred_key_id:
1233 * @key: the structure that contains the OpenPGP public key.
1234 * @keyid: the struct to save the keyid.
1236 * Get the preferred key-id for the key.
1238 * Returns: the 64-bit preferred keyID of the OpenPGP key, or if it
1239 * hasn't been set it returns %GNUTLS_E_INVALID_REQUEST.
1242 gnutls_openpgp_privkey_get_preferred_key_id (gnutls_openpgp_privkey_t key,
1243 gnutls_openpgp_keyid_t keyid)
1245 if (!key->preferred_set)
1246 return gnutls_assert_val(GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR);
1248 if (!key || !keyid)
1250 gnutls_assert ();
1251 return GNUTLS_E_INVALID_REQUEST;
1254 memcpy (keyid, key->preferred_keyid, GNUTLS_OPENPGP_KEYID_SIZE);
1256 return 0;
1260 * gnutls_openpgp_privkey_set_preferred_key_id:
1261 * @key: the structure that contains the OpenPGP public key.
1262 * @keyid: the selected keyid
1264 * This allows setting a preferred key id for the given certificate.
1265 * This key will be used by functions that involve key handling.
1267 * If the provided @keyid is %NULL then the master key is
1268 * set as preferred.
1270 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
1271 * otherwise a negative error code is returned.
1274 gnutls_openpgp_privkey_set_preferred_key_id (gnutls_openpgp_privkey_t key,
1275 const gnutls_openpgp_keyid_t
1276 keyid)
1278 int ret;
1280 if (!key)
1282 gnutls_assert ();
1283 return GNUTLS_E_INVALID_REQUEST;
1286 if (keyid == NULL) /* set the master as preferred */
1288 uint8_t tmp[GNUTLS_OPENPGP_KEYID_SIZE];
1290 ret = gnutls_openpgp_privkey_get_key_id (key, tmp);
1291 if (ret < 0)
1292 return gnutls_assert_val(ret);
1294 key->preferred_set = 1;
1295 memcpy (key->preferred_keyid, tmp, GNUTLS_OPENPGP_KEYID_SIZE);
1297 return 0;
1300 /* check if the id is valid */
1301 ret = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
1302 if (ret < 0)
1304 _gnutls_debug_log ("the requested subkey does not exist\n");
1305 gnutls_assert ();
1306 return ret;
1309 key->preferred_set = 1;
1310 memcpy (key->preferred_keyid, keyid, GNUTLS_OPENPGP_KEYID_SIZE);
1312 return 0;
1316 * gnutls_openpgp_privkey_sign_hash:
1317 * @key: Holds the key
1318 * @hash: holds the data to be signed
1319 * @signature: will contain newly allocated signature
1321 * This function will sign the given hash using the private key. You
1322 * should use gnutls_openpgp_privkey_set_preferred_key_id() before
1323 * calling this function to set the subkey to use.
1325 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1326 * negative error value.
1328 * Deprecated: Use gnutls_privkey_sign_hash() instead.
1331 gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key,
1332 const gnutls_datum_t * hash,
1333 gnutls_datum_t * signature)
1335 int result;
1336 gnutls_pk_params_st params;
1337 int pk_algorithm;
1338 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1340 if (key == NULL)
1342 gnutls_assert ();
1343 return GNUTLS_E_INVALID_REQUEST;
1346 result = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid);
1347 if (result == 0)
1349 uint32_t kid[2];
1350 int idx;
1352 KEYID_IMPORT (kid, keyid);
1354 idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
1355 pk_algorithm =
1356 gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, NULL);
1357 result =
1358 _gnutls_openpgp_privkey_get_mpis (key, kid, &params);
1360 else
1362 pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
1363 result = _gnutls_openpgp_privkey_get_mpis (key, NULL, &params);
1366 if (result < 0)
1368 gnutls_assert ();
1369 return result;
1373 result =
1374 _gnutls_pk_sign (pk_algorithm, signature, hash, &params);
1376 gnutls_pk_params_release(&params);
1378 if (result < 0)
1380 gnutls_assert ();
1381 return result;
1384 return 0;
1388 * _gnutls_openpgp_privkey_decrypt_data:
1389 * @key: Holds the key
1390 * @flags: (0) for now
1391 * @ciphertext: holds the data to be decrypted
1392 * @plaintext: will contain newly allocated plaintext
1394 * This function will sign the given hash using the private key. You
1395 * should use gnutls_openpgp_privkey_set_preferred_key_id() before
1396 * calling this function to set the subkey to use.
1398 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1399 * negative error value.
1402 _gnutls_openpgp_privkey_decrypt_data (gnutls_openpgp_privkey_t key,
1403 unsigned int flags,
1404 const gnutls_datum_t * ciphertext,
1405 gnutls_datum_t * plaintext)
1407 int result, i;
1408 gnutls_pk_params_st params;
1409 int pk_algorithm;
1410 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1412 if (key == NULL)
1414 gnutls_assert ();
1415 return GNUTLS_E_INVALID_REQUEST;
1418 result = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid);
1419 if (result == 0)
1421 uint32_t kid[2];
1423 KEYID_IMPORT (kid, keyid);
1424 result = _gnutls_openpgp_privkey_get_mpis (key, kid, &params);
1426 i = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
1428 pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL);
1430 else
1432 pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
1434 result = _gnutls_openpgp_privkey_get_mpis (key, NULL, &params);
1438 if (result < 0)
1440 gnutls_assert ();
1441 return result;
1444 result = _gnutls_pk_decrypt (pk_algorithm, plaintext, ciphertext, &params);
1446 gnutls_pk_params_release(&params);
1448 if (result < 0)
1449 return gnutls_assert_val(result);
1451 return 0;