Added (back) RFC5081 support in client mode.
[gnutls.git] / lib / openpgp / pgp.c
blob9dc9cc76312ba1ff279868278d8875d5f459fd44
1 /*
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Timo Schulz, 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 key parsing
26 #include <gnutls_int.h>
27 #include <gnutls_datum.h>
28 #include <gnutls_global.h>
29 #include <gnutls_errors.h>
30 #include <openpgp_int.h>
31 #include <gnutls_str.h>
32 #include <gnutls_num.h>
33 #include <x509/common.h>
35 /**
36 * gnutls_openpgp_crt_init:
37 * @key: The structure to be initialized
39 * This function will initialize an OpenPGP key structure.
41 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
42 **/
43 int
44 gnutls_openpgp_crt_init (gnutls_openpgp_crt_t * key)
46 *key = gnutls_calloc (1, sizeof (gnutls_openpgp_crt_int));
48 if (*key)
49 return 0; /* success */
50 return GNUTLS_E_MEMORY_ERROR;
53 /**
54 * gnutls_openpgp_crt_deinit:
55 * @key: The structure to be initialized
57 * This function will deinitialize a key structure.
58 **/
59 void
60 gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key)
62 if (!key)
63 return;
65 if (key->knode)
67 cdk_kbnode_release (key->knode);
68 key->knode = NULL;
71 gnutls_free (key);
74 /**
75 * gnutls_openpgp_crt_import:
76 * @key: The structure to store the parsed key.
77 * @data: The RAW or BASE64 encoded key.
78 * @format: One of gnutls_openpgp_crt_fmt_t elements.
80 * This function will convert the given RAW or Base64 encoded key to
81 * the native #gnutls_openpgp_crt_t format. The output will be stored
82 * in 'key'.
84 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
85 **/
86 int
87 gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key,
88 const gnutls_datum_t * data,
89 gnutls_openpgp_crt_fmt_t format)
91 cdk_packet_t pkt;
92 int rc, armor;
94 if (data->data == NULL || data->size == 0)
96 gnutls_assert ();
97 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
100 if (format == GNUTLS_OPENPGP_FMT_RAW) armor = 0;
101 else armor = 1;
103 rc = cdk_kbnode_read_from_mem (&key->knode, armor, data->data, data->size);
104 if (rc)
106 rc = _gnutls_map_cdk_rc (rc);
107 gnutls_assert ();
108 return rc;
111 /* Test if the import was successful. */
112 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
113 if (pkt == NULL)
115 gnutls_assert ();
116 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
119 return 0;
122 int _gnutls_openpgp_export2 (cdk_kbnode_t node,
123 gnutls_openpgp_crt_fmt_t format,
124 gnutls_datum_t* out, int priv)
126 int ret;
127 size_t size = 0;
129 ret = _gnutls_openpgp_export(node, format, NULL, &size, priv);
130 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
132 out->data = gnutls_malloc(size);
134 ret = _gnutls_openpgp_export(node, format, out->data, &size, priv);
135 if (ret < 0)
137 gnutls_free(out->data);
138 return gnutls_assert_val(ret);
140 out->size = size;
142 else if (ret < 0)
143 return gnutls_assert_val(ret);
145 return 0;
148 /* internal version of export
151 _gnutls_openpgp_export (cdk_kbnode_t node,
152 gnutls_openpgp_crt_fmt_t format,
153 void *output_data,
154 size_t * output_data_size, int priv)
156 size_t input_data_size = *output_data_size;
157 size_t calc_size;
158 int rc;
160 rc = cdk_kbnode_write_to_mem (node, output_data, output_data_size);
161 if (rc)
163 rc = _gnutls_map_cdk_rc (rc);
164 gnutls_assert ();
165 return rc;
168 /* If the caller uses output_data == NULL then return what he expects.
170 if (!output_data && format != GNUTLS_OPENPGP_FMT_BASE64)
172 gnutls_assert ();
173 return GNUTLS_E_SHORT_MEMORY_BUFFER;
176 if (format == GNUTLS_OPENPGP_FMT_BASE64)
178 unsigned char *in = gnutls_calloc (1, *output_data_size);
179 memcpy (in, output_data, *output_data_size);
181 /* Calculate the size of the encoded data and check if the provided
182 buffer is large enough. */
183 rc = cdk_armor_encode_buffer (in, *output_data_size,
184 NULL, 0, &calc_size,
185 priv ? CDK_ARMOR_SECKEY :
186 CDK_ARMOR_PUBKEY);
187 if (rc || calc_size > input_data_size)
189 gnutls_free (in);
190 *output_data_size = calc_size;
191 gnutls_assert ();
192 return GNUTLS_E_SHORT_MEMORY_BUFFER;
195 rc = cdk_armor_encode_buffer (in, *output_data_size,
196 output_data, input_data_size, &calc_size,
197 priv ? CDK_ARMOR_SECKEY :
198 CDK_ARMOR_PUBKEY);
199 gnutls_free (in);
200 *output_data_size = calc_size;
202 if (rc)
204 rc = _gnutls_map_cdk_rc (rc);
205 gnutls_assert ();
206 return rc;
210 return 0;
215 * gnutls_openpgp_crt_export:
216 * @key: Holds the key.
217 * @format: One of gnutls_openpgp_crt_fmt_t elements.
218 * @output_data: will contain the raw or base64 encoded key
219 * @output_data_size: holds the size of output_data (and will
220 * be replaced by the actual size of parameters)
222 * This function will convert the given key to RAW or Base64 format.
223 * If the buffer provided is not long enough to hold the output, then
224 * %GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
226 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
229 gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key,
230 gnutls_openpgp_crt_fmt_t format,
231 void *output_data, size_t * output_data_size)
233 return _gnutls_openpgp_export (key->knode, format, output_data,
234 output_data_size, 0);
238 * gnutls_openpgp_crt_export2:
239 * @key: Holds the key.
240 * @format: One of gnutls_openpgp_crt_fmt_t elements.
241 * @out: will contain the raw or base64 encoded key
243 * This function will convert the given key to RAW or Base64 format.
244 * The output buffer is allocated using gnutls_malloc().
246 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
249 gnutls_openpgp_crt_export2 (gnutls_openpgp_crt_t key,
250 gnutls_openpgp_crt_fmt_t format,
251 gnutls_datum_t *out)
253 return _gnutls_openpgp_export2 (key->knode, format, out, 0);
257 * gnutls_openpgp_crt_get_fingerprint:
258 * @key: the raw data that contains the OpenPGP public key.
259 * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
260 * @fprlen: the integer to save the length of the fingerprint.
262 * Get key fingerprint. Depending on the algorithm, the fingerprint
263 * can be 16 or 20 bytes.
265 * Returns: On success, 0 is returned. Otherwise, an error code.
268 gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key,
269 void *fpr, size_t * fprlen)
271 cdk_packet_t pkt;
272 cdk_pkt_pubkey_t pk = NULL;
274 if (!fpr || !fprlen)
276 gnutls_assert ();
277 return GNUTLS_E_INVALID_REQUEST;
280 *fprlen = 0;
282 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
283 if (!pkt)
284 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
286 pk = pkt->pkt.public_key;
287 *fprlen = 20;
289 /* FIXME: Check if the draft allows old PGP keys. */
290 if (is_RSA (pk->pubkey_algo) && pk->version < 4)
291 *fprlen = 16;
292 cdk_pk_get_fingerprint (pk, fpr);
294 return 0;
297 static int
298 _gnutls_openpgp_count_key_names (gnutls_openpgp_crt_t key)
300 cdk_kbnode_t p, ctx;
301 cdk_packet_t pkt;
302 int nuids;
304 if (key == NULL)
306 gnutls_assert ();
307 return 0;
310 ctx = NULL;
311 nuids = 0;
312 while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
314 pkt = cdk_kbnode_get_packet (p);
315 if (pkt->pkttype == CDK_PKT_USER_ID)
316 nuids++;
319 return nuids;
324 * gnutls_openpgp_crt_get_name:
325 * @key: the structure that contains the OpenPGP public key.
326 * @idx: the index of the ID to extract
327 * @buf: a pointer to a structure to hold the name, may be %NULL
328 * to only get the @sizeof_buf.
329 * @sizeof_buf: holds the maximum size of @buf, on return hold the
330 * actual/required size of @buf.
332 * Extracts the userID from the parsed OpenPGP key.
334 * Returns: %GNUTLS_E_SUCCESS on success, and if the index of the ID
335 * does not exist %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE, or an
336 * error code.
339 gnutls_openpgp_crt_get_name (gnutls_openpgp_crt_t key,
340 int idx, char *buf, size_t * sizeof_buf)
342 cdk_kbnode_t ctx = NULL, p;
343 cdk_packet_t pkt = NULL;
344 cdk_pkt_userid_t uid = NULL;
345 int pos = 0;
347 if (!key)
349 gnutls_assert ();
350 return GNUTLS_E_INVALID_REQUEST;
353 if (idx < 0 || idx >= _gnutls_openpgp_count_key_names (key))
354 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
356 pos = 0;
357 while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
359 pkt = cdk_kbnode_get_packet (p);
360 if (pkt->pkttype == CDK_PKT_USER_ID)
362 if (pos == idx)
363 break;
364 pos++;
368 if (!pkt)
370 gnutls_assert ();
371 return GNUTLS_E_INTERNAL_ERROR;
374 uid = pkt->pkt.user_id;
375 if (uid->len >= *sizeof_buf)
377 gnutls_assert ();
378 *sizeof_buf = uid->len + 1;
379 return GNUTLS_E_SHORT_MEMORY_BUFFER;
382 if (buf)
384 memcpy (buf, uid->name, uid->len);
385 buf[uid->len] = '\0'; /* make sure it's a string */
387 *sizeof_buf = uid->len + 1;
389 if (uid->is_revoked)
390 return GNUTLS_E_OPENPGP_UID_REVOKED;
392 return 0;
396 * gnutls_openpgp_crt_get_pk_algorithm:
397 * @key: is an OpenPGP key
398 * @bits: if bits is non null it will hold the size of the parameters' in bits
400 * This function will return the public key algorithm of an OpenPGP
401 * certificate.
403 * If bits is non null, it should have enough size to hold the parameters
404 * size in bits. For RSA the bits returned is the modulus.
405 * For DSA the bits returned are of the public exponent.
407 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
408 * success, or GNUTLS_PK_UNKNOWN on error.
410 gnutls_pk_algorithm_t
411 gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key,
412 unsigned int *bits)
414 cdk_packet_t pkt;
415 int algo = 0, ret;
416 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
418 if (!key)
420 gnutls_assert ();
421 return GNUTLS_PK_UNKNOWN;
424 ret = gnutls_openpgp_crt_get_preferred_key_id (key, keyid);
425 if (ret == 0)
427 int idx;
429 idx = gnutls_openpgp_crt_get_subkey_idx (key, keyid);
430 if (idx != GNUTLS_OPENPGP_MASTER_KEYID_IDX)
432 algo =
433 gnutls_openpgp_crt_get_subkey_pk_algorithm (key, idx, bits);
434 return algo;
438 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
439 if (pkt)
441 if (bits)
442 *bits = cdk_pk_get_nbits (pkt->pkt.public_key);
443 algo = _gnutls_openpgp_get_algo (pkt->pkt.public_key->pubkey_algo);
446 return algo;
451 * gnutls_openpgp_crt_get_version:
452 * @key: the structure that contains the OpenPGP public key.
454 * Extract the version of the OpenPGP key.
456 * Returns: the version number is returned, or a negative error code on errors.
459 gnutls_openpgp_crt_get_version (gnutls_openpgp_crt_t key)
461 cdk_packet_t pkt;
462 int version;
464 if (!key)
465 return -1;
467 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
468 if (pkt)
469 version = pkt->pkt.public_key->version;
470 else
471 version = 0;
473 return version;
478 * gnutls_openpgp_crt_get_creation_time:
479 * @key: the structure that contains the OpenPGP public key.
481 * Get key creation time.
483 * Returns: the timestamp when the OpenPGP key was created.
485 time_t
486 gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key)
488 cdk_packet_t pkt;
489 time_t timestamp;
491 if (!key)
492 return (time_t) - 1;
494 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
495 if (pkt)
496 timestamp = pkt->pkt.public_key->timestamp;
497 else
498 timestamp = 0;
500 return timestamp;
505 * gnutls_openpgp_crt_get_expiration_time:
506 * @key: the structure that contains the OpenPGP public key.
508 * Get key expiration time. A value of '0' means that the key doesn't
509 * expire at all.
511 * Returns: the time when the OpenPGP key expires.
513 time_t
514 gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key)
516 cdk_packet_t pkt;
517 time_t expiredate;
519 if (!key)
520 return (time_t) - 1;
522 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
523 if (pkt)
524 expiredate = pkt->pkt.public_key->expiredate;
525 else
526 expiredate = 0;
528 return expiredate;
532 * gnutls_openpgp_crt_get_key_id:
533 * @key: the structure that contains the OpenPGP public key.
534 * @keyid: the buffer to save the keyid.
536 * Get key id string.
538 * Returns: the 64-bit keyID of the OpenPGP key.
540 * Since: 2.4.0
543 gnutls_openpgp_crt_get_key_id (gnutls_openpgp_crt_t key,
544 gnutls_openpgp_keyid_t keyid)
546 cdk_packet_t pkt;
547 uint32_t kid[2];
549 if (!key || !keyid)
551 gnutls_assert ();
552 return GNUTLS_E_INVALID_REQUEST;
555 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
556 if (!pkt)
557 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
559 cdk_pk_get_keyid (pkt->pkt.public_key, kid);
560 _gnutls_write_uint32 (kid[0], keyid);
561 _gnutls_write_uint32 (kid[1], keyid + 4);
563 return 0;
567 * gnutls_openpgp_crt_get_revoked_status:
568 * @key: the structure that contains the OpenPGP public key.
570 * Get revocation status of key.
572 * Returns: true (1) if the key has been revoked, or false (0) if it
573 * has not.
575 * Since: 2.4.0
578 gnutls_openpgp_crt_get_revoked_status (gnutls_openpgp_crt_t key)
580 cdk_packet_t pkt;
582 if (!key)
584 gnutls_assert ();
585 return GNUTLS_E_INVALID_REQUEST;
588 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
589 if (!pkt)
590 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
592 if (pkt->pkt.public_key->is_revoked != 0)
593 return 1;
594 return 0;
598 * gnutls_openpgp_crt_check_hostname:
599 * @key: should contain a #gnutls_openpgp_crt_t structure
600 * @hostname: A null terminated string that contains a DNS name
602 * This function will check if the given key's owner matches the
603 * given hostname. This is a basic implementation of the matching
604 * described in RFC2818 (HTTPS), which takes into account wildcards.
606 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
609 gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key,
610 const char *hostname)
612 char dnsname[MAX_CN];
613 size_t dnsnamesize;
614 int ret = 0;
615 int i;
617 /* Check through all included names. */
618 for (i = 0; !(ret < 0); i++)
620 dnsnamesize = sizeof (dnsname);
621 ret = gnutls_openpgp_crt_get_name (key, i, dnsname, &dnsnamesize);
623 if (ret == 0)
625 /* Length returned by gnutls_openpgp_crt_get_name includes
626 the terminating (0). */
627 dnsnamesize--;
629 if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname, 0))
630 return 1;
634 /* not found a matching name */
635 return 0;
638 unsigned int
639 _gnutls_get_pgp_key_usage (unsigned int cdk_usage)
641 unsigned int usage = 0;
643 if (cdk_usage & CDK_KEY_USG_CERT_SIGN)
644 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
645 if (cdk_usage & CDK_KEY_USG_DATA_SIGN)
646 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
647 if (cdk_usage & CDK_KEY_USG_COMM_ENCR)
648 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
649 if (cdk_usage & CDK_KEY_USG_STORAGE_ENCR)
650 usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
651 if (cdk_usage & CDK_KEY_USG_AUTH)
652 usage |= GNUTLS_KEY_KEY_AGREEMENT;
654 return usage;
658 * gnutls_openpgp_crt_get_key_usage:
659 * @key: should contain a gnutls_openpgp_crt_t structure
660 * @key_usage: where the key usage bits will be stored
662 * This function will return certificate's key usage, by checking the
663 * key algorithm. The key usage value will ORed values of the:
664 * %GNUTLS_KEY_DIGITAL_SIGNATURE, %GNUTLS_KEY_KEY_ENCIPHERMENT.
666 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
669 gnutls_openpgp_crt_get_key_usage (gnutls_openpgp_crt_t key,
670 unsigned int *key_usage)
672 cdk_packet_t pkt;
674 if (!key)
676 gnutls_assert ();
677 return GNUTLS_E_INVALID_REQUEST;
680 pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
681 if (!pkt)
682 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
684 *key_usage = _gnutls_get_pgp_key_usage (pkt->pkt.public_key->pubkey_usage);
686 return 0;
690 * gnutls_openpgp_crt_get_subkey_count:
691 * @key: is an OpenPGP key
693 * This function will return the number of subkeys present in the
694 * given OpenPGP certificate.
696 * Returns: the number of subkeys, or a negative error code on error.
698 * Since: 2.4.0
701 gnutls_openpgp_crt_get_subkey_count (gnutls_openpgp_crt_t key)
703 cdk_kbnode_t p, ctx;
704 cdk_packet_t pkt;
705 int subkeys;
707 if (key == NULL)
709 gnutls_assert ();
710 return 0;
713 ctx = NULL;
714 subkeys = 0;
715 while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
717 pkt = cdk_kbnode_get_packet (p);
718 if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
719 subkeys++;
722 return subkeys;
725 /* returns the subkey with the given index */
726 static cdk_packet_t
727 _get_public_subkey (gnutls_openpgp_crt_t key, unsigned int indx)
729 cdk_kbnode_t p, ctx;
730 cdk_packet_t pkt;
731 unsigned int subkeys;
733 if (key == NULL)
735 gnutls_assert ();
736 return NULL;
739 ctx = NULL;
740 subkeys = 0;
741 while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
743 pkt = cdk_kbnode_get_packet (p);
744 if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY && indx == subkeys++)
745 return pkt;
748 return NULL;
751 /* returns the key with the given keyid. It can be either key or subkey.
752 * depending on what requested:
753 * pkt->pkt.secret_key;
754 * pkt->pkt.public_key;
756 cdk_packet_t
757 _gnutls_openpgp_find_key (cdk_kbnode_t knode, uint32_t keyid[2],
758 unsigned int priv)
760 cdk_kbnode_t p, ctx;
761 cdk_packet_t pkt;
762 uint32_t local_keyid[2];
764 ctx = NULL;
765 while ((p = cdk_kbnode_walk (knode, &ctx, 0)))
767 pkt = cdk_kbnode_get_packet (p);
769 if ((priv == 0
770 && (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
771 || pkt->pkttype == CDK_PKT_PUBLIC_KEY)) || (priv != 0
772 && (pkt->pkttype ==
773 CDK_PKT_SECRET_SUBKEY
774 || pkt->pkttype
776 CDK_PKT_SECRET_KEY)))
778 if (priv == 0)
779 cdk_pk_get_keyid (pkt->pkt.public_key, local_keyid);
780 else
781 cdk_pk_get_keyid (pkt->pkt.secret_key->pk, local_keyid);
783 if (local_keyid[0] == keyid[0] && local_keyid[1] == keyid[1])
785 return pkt;
790 gnutls_assert ();
791 return NULL;
794 /* returns the key with the given keyid
795 * depending on what requested:
796 * pkt->pkt.secret_key;
797 * pkt->pkt.public_key;
800 _gnutls_openpgp_find_subkey_idx (cdk_kbnode_t knode, uint32_t keyid[2],
801 unsigned int priv)
803 cdk_kbnode_t p, ctx;
804 cdk_packet_t pkt;
805 int i = 0;
806 uint32_t local_keyid[2];
808 _gnutls_hard_log ("Looking keyid: %x.%x\n", keyid[0], keyid[1]);
810 ctx = NULL;
811 while ((p = cdk_kbnode_walk (knode, &ctx, 0)))
813 pkt = cdk_kbnode_get_packet (p);
815 if ((priv == 0 && (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)) ||
816 (priv != 0 && (pkt->pkttype == CDK_PKT_SECRET_SUBKEY)))
818 if (priv == 0)
819 cdk_pk_get_keyid (pkt->pkt.public_key, local_keyid);
820 else
821 cdk_pk_get_keyid (pkt->pkt.secret_key->pk, local_keyid);
823 _gnutls_hard_log ("Found keyid: %x.%x\n", local_keyid[0],
824 local_keyid[1]);
825 if (local_keyid[0] == keyid[0] && local_keyid[1] == keyid[1])
827 return i;
829 i++;
833 gnutls_assert ();
834 return GNUTLS_E_OPENPGP_SUBKEY_ERROR;
838 * gnutls_openpgp_crt_get_subkey_revoked_status:
839 * @key: the structure that contains the OpenPGP public key.
840 * @idx: is the subkey index
842 * Get subkey revocation status. A negative error code indicates an error.
844 * Returns: true (1) if the key has been revoked, or false (0) if it
845 * has not.
847 * Since: 2.4.0
850 gnutls_openpgp_crt_get_subkey_revoked_status (gnutls_openpgp_crt_t key,
851 unsigned int idx)
853 cdk_packet_t pkt;
855 if (!key)
857 gnutls_assert ();
858 return GNUTLS_E_INVALID_REQUEST;
861 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
862 return gnutls_openpgp_crt_get_revoked_status(key);
864 pkt = _get_public_subkey (key, idx);
865 if (!pkt)
866 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
868 if (pkt->pkt.public_key->is_revoked != 0)
869 return 1;
870 return 0;
874 * gnutls_openpgp_crt_get_subkey_pk_algorithm:
875 * @key: is an OpenPGP key
876 * @idx: is the subkey index
877 * @bits: if bits is non null it will hold the size of the parameters' in bits
879 * This function will return the public key algorithm of a subkey of an OpenPGP
880 * certificate.
882 * If bits is non null, it should have enough size to hold the
883 * parameters size in bits. For RSA the bits returned is the modulus.
884 * For DSA the bits returned are of the public exponent.
886 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
887 * success, or GNUTLS_PK_UNKNOWN on error.
889 * Since: 2.4.0
891 gnutls_pk_algorithm_t
892 gnutls_openpgp_crt_get_subkey_pk_algorithm (gnutls_openpgp_crt_t key,
893 unsigned int idx,
894 unsigned int *bits)
896 cdk_packet_t pkt;
897 int algo;
899 if (!key)
901 gnutls_assert ();
902 return GNUTLS_PK_UNKNOWN;
905 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
906 return gnutls_openpgp_crt_get_pk_algorithm(key, bits);
908 pkt = _get_public_subkey (key, idx);
910 algo = 0;
911 if (pkt)
913 if (bits)
914 *bits = cdk_pk_get_nbits (pkt->pkt.public_key);
915 algo = _gnutls_openpgp_get_algo (pkt->pkt.public_key->pubkey_algo);
918 return algo;
922 * gnutls_openpgp_crt_get_subkey_creation_time:
923 * @key: the structure that contains the OpenPGP public key.
924 * @idx: the subkey index
926 * Get subkey creation time.
928 * Returns: the timestamp when the OpenPGP sub-key was created.
930 * Since: 2.4.0
932 time_t
933 gnutls_openpgp_crt_get_subkey_creation_time (gnutls_openpgp_crt_t key,
934 unsigned int idx)
936 cdk_packet_t pkt;
937 time_t timestamp;
939 if (!key)
940 return (time_t) - 1;
942 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
943 return gnutls_openpgp_crt_get_creation_time(key);
945 pkt = _get_public_subkey (key, idx);
946 if (pkt)
947 timestamp = pkt->pkt.public_key->timestamp;
948 else
949 timestamp = 0;
951 return timestamp;
956 * gnutls_openpgp_crt_get_subkey_expiration_time:
957 * @key: the structure that contains the OpenPGP public key.
958 * @idx: the subkey index
960 * Get subkey expiration time. A value of '0' means that the key
961 * doesn't expire at all.
963 * Returns: the time when the OpenPGP key expires.
965 * Since: 2.4.0
967 time_t
968 gnutls_openpgp_crt_get_subkey_expiration_time (gnutls_openpgp_crt_t key,
969 unsigned int idx)
971 cdk_packet_t pkt;
972 time_t expiredate;
974 if (!key)
975 return (time_t) - 1;
977 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
978 return gnutls_openpgp_crt_get_expiration_time(key);
980 pkt = _get_public_subkey (key, idx);
981 if (pkt)
982 expiredate = pkt->pkt.public_key->expiredate;
983 else
984 expiredate = 0;
986 return expiredate;
990 * gnutls_openpgp_crt_get_subkey_id:
991 * @key: the structure that contains the OpenPGP public key.
992 * @idx: the subkey index
993 * @keyid: the buffer to save the keyid.
995 * Get the subkey's key-id.
997 * Returns: the 64-bit keyID of the OpenPGP key.
1000 gnutls_openpgp_crt_get_subkey_id (gnutls_openpgp_crt_t key,
1001 unsigned int idx,
1002 gnutls_openpgp_keyid_t keyid)
1004 cdk_packet_t pkt;
1005 uint32_t kid[2];
1007 if (!key || !keyid)
1009 gnutls_assert ();
1010 return GNUTLS_E_INVALID_REQUEST;
1013 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
1014 return gnutls_openpgp_crt_get_key_id(key, keyid);
1016 pkt = _get_public_subkey (key, idx);
1017 if (!pkt)
1018 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
1020 cdk_pk_get_keyid (pkt->pkt.public_key, kid);
1021 _gnutls_write_uint32 (kid[0], keyid);
1022 _gnutls_write_uint32 (kid[1], keyid + 4);
1024 return 0;
1028 * gnutls_openpgp_crt_get_subkey_fingerprint:
1029 * @key: the raw data that contains the OpenPGP public key.
1030 * @idx: the subkey index
1031 * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
1032 * @fprlen: the integer to save the length of the fingerprint.
1034 * Get key fingerprint of a subkey. Depending on the algorithm, the
1035 * fingerprint can be 16 or 20 bytes.
1037 * Returns: On success, 0 is returned. Otherwise, an error code.
1039 * Since: 2.4.0
1042 gnutls_openpgp_crt_get_subkey_fingerprint (gnutls_openpgp_crt_t key,
1043 unsigned int idx,
1044 void *fpr, size_t * fprlen)
1046 cdk_packet_t pkt;
1047 cdk_pkt_pubkey_t pk = NULL;
1049 if (!fpr || !fprlen)
1051 gnutls_assert ();
1052 return GNUTLS_E_INVALID_REQUEST;
1055 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
1056 return gnutls_openpgp_crt_get_fingerprint(key, fpr, fprlen);
1058 *fprlen = 0;
1060 pkt = _get_public_subkey (key, idx);
1061 if (!pkt)
1062 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
1064 pk = pkt->pkt.public_key;
1065 *fprlen = 20;
1067 /* FIXME: Check if the draft allows old PGP keys. */
1068 if (is_RSA (pk->pubkey_algo) && pk->version < 4)
1069 *fprlen = 16;
1070 cdk_pk_get_fingerprint (pk, fpr);
1072 return 0;
1076 * gnutls_openpgp_crt_get_subkey_idx:
1077 * @key: the structure that contains the OpenPGP public key.
1078 * @keyid: the keyid.
1080 * Get subkey's index.
1082 * Returns: the index of the subkey or a negative error value.
1084 * Since: 2.4.0
1087 gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key,
1088 const gnutls_openpgp_keyid_t keyid)
1090 int ret;
1091 uint32_t kid[2];
1092 uint8_t master_id[GNUTLS_OPENPGP_KEYID_SIZE];
1094 if (!key)
1096 gnutls_assert ();
1097 return GNUTLS_E_INVALID_REQUEST;
1100 ret = gnutls_openpgp_crt_get_key_id (key, master_id);
1101 if (ret < 0)
1102 return gnutls_assert_val(ret);
1103 if (memcmp(master_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE)==0)
1104 return GNUTLS_OPENPGP_MASTER_KEYID_IDX;
1106 KEYID_IMPORT (kid, keyid);
1107 ret = _gnutls_openpgp_find_subkey_idx (key->knode, kid, 0);
1109 if (ret < 0)
1111 gnutls_assert ();
1114 return ret;
1118 * gnutls_openpgp_crt_get_subkey_usage:
1119 * @key: should contain a gnutls_openpgp_crt_t structure
1120 * @idx: the subkey index
1121 * @key_usage: where the key usage bits will be stored
1123 * This function will return certificate's key usage, by checking the
1124 * key algorithm. The key usage value will ORed values of
1125 * %GNUTLS_KEY_DIGITAL_SIGNATURE or %GNUTLS_KEY_KEY_ENCIPHERMENT.
1127 * A negative error code may be returned in case of parsing error.
1129 * Returns: key usage value.
1131 * Since: 2.4.0
1134 gnutls_openpgp_crt_get_subkey_usage (gnutls_openpgp_crt_t key,
1135 unsigned int idx,
1136 unsigned int *key_usage)
1138 cdk_packet_t pkt;
1140 if (!key)
1142 gnutls_assert ();
1143 return GNUTLS_E_INVALID_REQUEST;
1146 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
1147 return gnutls_openpgp_crt_get_key_usage(key, key_usage);
1149 pkt = _get_public_subkey (key, idx);
1150 if (!pkt)
1151 return GNUTLS_E_OPENPGP_SUBKEY_ERROR;
1153 *key_usage = _gnutls_get_pgp_key_usage (pkt->pkt.public_key->pubkey_usage);
1155 return 0;
1159 _gnutls_read_pgp_mpi (cdk_packet_t pkt, unsigned int priv, size_t idx,
1160 bigint_t * m)
1162 size_t buf_size = 512;
1163 uint8_t *buf = gnutls_malloc (buf_size);
1164 int err;
1165 unsigned int max_pub_params = 0;
1167 if (priv != 0)
1168 max_pub_params = cdk_pk_get_npkey (pkt->pkt.secret_key->pk->pubkey_algo);
1170 if (buf == NULL)
1172 gnutls_assert ();
1173 return GNUTLS_E_MEMORY_ERROR;
1176 /* FIXME: Note that opencdk doesn't like the buf to be NULL.
1178 if (priv == 0)
1179 err =
1180 cdk_pk_get_mpi (pkt->pkt.public_key, idx, buf, buf_size, &buf_size,
1181 NULL);
1182 else
1184 if (idx < max_pub_params)
1185 err =
1186 cdk_pk_get_mpi (pkt->pkt.secret_key->pk, idx, buf, buf_size,
1187 &buf_size, NULL);
1188 else
1190 err =
1191 cdk_sk_get_mpi (pkt->pkt.secret_key, idx - max_pub_params, buf,
1192 buf_size, &buf_size, NULL);
1196 if (err == CDK_Too_Short)
1198 buf = gnutls_realloc_fast (buf, buf_size);
1199 if (buf == NULL)
1201 gnutls_assert ();
1202 return GNUTLS_E_MEMORY_ERROR;
1205 if (priv == 0)
1206 err =
1207 cdk_pk_get_mpi (pkt->pkt.public_key, idx, buf, buf_size, &buf_size,
1208 NULL);
1209 else
1211 if (idx < max_pub_params)
1212 err =
1213 cdk_pk_get_mpi (pkt->pkt.secret_key->pk, idx, buf, buf_size,
1214 &buf_size, NULL);
1215 else
1217 err =
1218 cdk_sk_get_mpi (pkt->pkt.secret_key, idx - max_pub_params,
1219 buf, buf_size, &buf_size, NULL);
1224 if (err != CDK_Success)
1226 gnutls_assert ();
1227 gnutls_free (buf);
1228 return _gnutls_map_cdk_rc (err);
1231 err = _gnutls_mpi_scan (m, buf, buf_size);
1232 gnutls_free (buf);
1234 if (err < 0)
1236 gnutls_assert ();
1237 return err;
1240 return 0;
1244 /* Extracts DSA and RSA parameters from a certificate.
1247 _gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert,
1248 uint32_t * keyid /* [2] */ ,
1249 gnutls_pk_params_st * params)
1251 int result, i;
1252 int pk_algorithm, local_params;
1253 cdk_packet_t pkt;
1255 if (keyid == NULL)
1256 pkt = cdk_kbnode_find_packet (cert->knode, CDK_PKT_PUBLIC_KEY);
1257 else
1258 pkt = _gnutls_openpgp_find_key (cert->knode, keyid, 0);
1260 if (pkt == NULL)
1262 gnutls_assert ();
1263 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
1266 pk_algorithm = _gnutls_openpgp_get_algo (pkt->pkt.public_key->pubkey_algo);
1268 switch (pk_algorithm)
1270 case GNUTLS_PK_RSA:
1271 local_params = RSA_PUBLIC_PARAMS;
1272 break;
1273 case GNUTLS_PK_DSA:
1274 local_params = DSA_PUBLIC_PARAMS;
1275 break;
1276 default:
1277 gnutls_assert ();
1278 return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
1281 gnutls_pk_params_init(params);
1283 for (i = 0; i < local_params; i++)
1285 result = _gnutls_read_pgp_mpi (pkt, 0, i, &params->params[i]);
1286 if (result < 0)
1288 gnutls_assert ();
1289 goto error;
1291 params->params_nr++;
1294 return 0;
1296 error:
1297 gnutls_pk_params_release(params);
1299 return result;
1302 /* The internal version of export
1304 static int
1305 _get_pk_rsa_raw (gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t keyid,
1306 gnutls_datum_t * m, gnutls_datum_t * e)
1308 int pk_algorithm, ret;
1309 cdk_packet_t pkt;
1310 uint32_t kid32[2];
1311 gnutls_pk_params_st params;
1313 gnutls_pk_params_init(&params);
1315 if (crt == NULL)
1317 gnutls_assert ();
1318 return GNUTLS_E_INVALID_REQUEST;
1321 KEYID_IMPORT (kid32, keyid);
1323 pkt = _gnutls_openpgp_find_key (crt->knode, kid32, 0);
1324 if (pkt == NULL)
1326 gnutls_assert ();
1327 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
1330 pk_algorithm = _gnutls_openpgp_get_algo (pkt->pkt.public_key->pubkey_algo);
1332 if (pk_algorithm != GNUTLS_PK_RSA)
1334 gnutls_assert ();
1335 return GNUTLS_E_INVALID_REQUEST;
1338 ret = _gnutls_openpgp_crt_get_mpis (crt, kid32, &params);
1339 if (ret < 0)
1341 gnutls_assert ();
1342 return ret;
1345 ret = _gnutls_mpi_dprint (params.params[0], m);
1346 if (ret < 0)
1348 gnutls_assert ();
1349 goto cleanup;
1352 ret = _gnutls_mpi_dprint (params.params[1], e);
1353 if (ret < 0)
1355 gnutls_assert ();
1356 _gnutls_free_datum (m);
1357 goto cleanup;
1360 ret = 0;
1362 cleanup:
1363 gnutls_pk_params_release(&params);
1364 return ret;
1367 static int
1368 _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t keyid,
1369 gnutls_datum_t * p, gnutls_datum_t * q,
1370 gnutls_datum_t * g, gnutls_datum_t * y)
1372 int pk_algorithm, ret;
1373 cdk_packet_t pkt;
1374 uint32_t kid32[2];
1375 gnutls_pk_params_st params;
1377 gnutls_pk_params_init(&params);
1379 if (crt == NULL)
1381 gnutls_assert ();
1382 return GNUTLS_E_INVALID_REQUEST;
1385 KEYID_IMPORT (kid32, keyid);
1387 pkt = _gnutls_openpgp_find_key (crt->knode, kid32, 0);
1388 if (pkt == NULL)
1390 gnutls_assert ();
1391 return GNUTLS_E_OPENPGP_GETKEY_FAILED;
1394 pk_algorithm = _gnutls_openpgp_get_algo (pkt->pkt.public_key->pubkey_algo);
1396 if (pk_algorithm != GNUTLS_PK_DSA)
1398 gnutls_assert ();
1399 return GNUTLS_E_INVALID_REQUEST;
1402 ret = _gnutls_openpgp_crt_get_mpis (crt, kid32, &params);
1403 if (ret < 0)
1405 gnutls_assert ();
1406 return ret;
1409 /* P */
1410 ret = _gnutls_mpi_dprint (params.params[0], p);
1411 if (ret < 0)
1413 gnutls_assert ();
1414 goto cleanup;
1417 /* Q */
1418 ret = _gnutls_mpi_dprint (params.params[1], q);
1419 if (ret < 0)
1421 gnutls_assert ();
1422 _gnutls_free_datum (p);
1423 goto cleanup;
1427 /* G */
1428 ret = _gnutls_mpi_dprint (params.params[2], g);
1429 if (ret < 0)
1431 gnutls_assert ();
1432 _gnutls_free_datum (p);
1433 _gnutls_free_datum (q);
1434 goto cleanup;
1438 /* Y */
1439 ret = _gnutls_mpi_dprint (params.params[3], y);
1440 if (ret < 0)
1442 gnutls_assert ();
1443 _gnutls_free_datum (p);
1444 _gnutls_free_datum (g);
1445 _gnutls_free_datum (q);
1446 goto cleanup;
1449 ret = 0;
1451 cleanup:
1452 gnutls_pk_params_release(&params);
1453 return ret;
1458 * gnutls_openpgp_crt_get_pk_rsa_raw:
1459 * @crt: Holds the certificate
1460 * @m: will hold the modulus
1461 * @e: will hold the public exponent
1463 * This function will export the RSA public key's parameters found in
1464 * the given structure. The new parameters will be allocated using
1465 * gnutls_malloc() and will be stored in the appropriate datum.
1467 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1469 * Since: 2.4.0
1472 gnutls_openpgp_crt_get_pk_rsa_raw (gnutls_openpgp_crt_t crt,
1473 gnutls_datum_t * m, gnutls_datum_t * e)
1475 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1476 int ret;
1478 ret = gnutls_openpgp_crt_get_key_id (crt, keyid);
1479 if (ret < 0)
1481 gnutls_assert ();
1482 return ret;
1485 return _get_pk_rsa_raw (crt, keyid, m, e);
1489 * gnutls_openpgp_crt_get_pk_dsa_raw:
1490 * @crt: Holds the certificate
1491 * @p: will hold the p
1492 * @q: will hold the q
1493 * @g: will hold the g
1494 * @y: will hold the y
1496 * This function will export the DSA public key's parameters found in
1497 * the given certificate. The new parameters will be allocated using
1498 * gnutls_malloc() and will be stored in the appropriate datum.
1500 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1502 * Since: 2.4.0
1505 gnutls_openpgp_crt_get_pk_dsa_raw (gnutls_openpgp_crt_t crt,
1506 gnutls_datum_t * p, gnutls_datum_t * q,
1507 gnutls_datum_t * g, gnutls_datum_t * y)
1509 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1510 int ret;
1512 ret = gnutls_openpgp_crt_get_key_id (crt, keyid);
1513 if (ret < 0)
1515 gnutls_assert ();
1516 return ret;
1519 return _get_pk_dsa_raw (crt, keyid, p, q, g, y);
1523 * gnutls_openpgp_crt_get_subkey_pk_rsa_raw:
1524 * @crt: Holds the certificate
1525 * @idx: Is the subkey index
1526 * @m: will hold the modulus
1527 * @e: will hold the public exponent
1529 * This function will export the RSA public key's parameters found in
1530 * the given structure. The new parameters will be allocated using
1531 * gnutls_malloc() and will be stored in the appropriate datum.
1533 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1535 * Since: 2.4.0
1538 gnutls_openpgp_crt_get_subkey_pk_rsa_raw (gnutls_openpgp_crt_t crt,
1539 unsigned int idx,
1540 gnutls_datum_t * m,
1541 gnutls_datum_t * e)
1543 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1544 int ret;
1546 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
1547 return gnutls_openpgp_crt_get_pk_rsa_raw(crt, m, e);
1549 ret = gnutls_openpgp_crt_get_subkey_id (crt, idx, keyid);
1550 if (ret < 0)
1552 gnutls_assert ();
1553 return ret;
1556 return _get_pk_rsa_raw (crt, keyid, m, e);
1560 * gnutls_openpgp_crt_get_subkey_pk_dsa_raw:
1561 * @crt: Holds the certificate
1562 * @idx: Is the subkey index
1563 * @p: will hold the p
1564 * @q: will hold the q
1565 * @g: will hold the g
1566 * @y: will hold the y
1568 * This function will export the DSA public key's parameters found in
1569 * the given certificate. The new parameters will be allocated using
1570 * gnutls_malloc() and will be stored in the appropriate datum.
1572 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1574 * Since: 2.4.0
1577 gnutls_openpgp_crt_get_subkey_pk_dsa_raw (gnutls_openpgp_crt_t crt,
1578 unsigned int idx,
1579 gnutls_datum_t * p,
1580 gnutls_datum_t * q,
1581 gnutls_datum_t * g,
1582 gnutls_datum_t * y)
1584 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1585 int ret;
1587 if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX)
1588 return gnutls_openpgp_crt_get_pk_dsa_raw(crt, p,q, g, y);
1590 ret = gnutls_openpgp_crt_get_subkey_id (crt, idx, keyid);
1591 if (ret < 0)
1593 gnutls_assert ();
1594 return ret;
1597 return _get_pk_dsa_raw (crt, keyid, p, q, g, y);
1601 * gnutls_openpgp_crt_get_preferred_key_id:
1602 * @key: the structure that contains the OpenPGP public key.
1603 * @keyid: the struct to save the keyid.
1605 * Get preferred key id. If it hasn't been set it returns
1606 * %GNUTLS_E_INVALID_REQUEST.
1608 * Returns: the 64-bit preferred keyID of the OpenPGP key.
1611 gnutls_openpgp_crt_get_preferred_key_id (gnutls_openpgp_crt_t key,
1612 gnutls_openpgp_keyid_t keyid)
1614 if (!key->preferred_set)
1615 return gnutls_assert_val(GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR);
1617 if (!key || !keyid)
1619 gnutls_assert ();
1620 return GNUTLS_E_INVALID_REQUEST;
1623 memcpy (keyid, key->preferred_keyid, GNUTLS_OPENPGP_KEYID_SIZE);
1625 return 0;
1629 * gnutls_openpgp_crt_set_preferred_key_id:
1630 * @key: the structure that contains the OpenPGP public key.
1631 * @keyid: the selected keyid
1633 * This allows setting a preferred key id for the given certificate.
1634 * This key will be used by functions that involve key handling.
1636 * If the provided @keyid is %NULL then the master key is
1637 * set as preferred.
1639 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
1640 * otherwise a negative error code is returned.
1643 gnutls_openpgp_crt_set_preferred_key_id (gnutls_openpgp_crt_t key,
1644 const gnutls_openpgp_keyid_t keyid)
1646 int ret;
1648 if (!key)
1650 gnutls_assert ();
1651 return GNUTLS_E_INVALID_REQUEST;
1654 if (keyid == NULL) /* set the master as preferred */
1656 uint8_t tmp[GNUTLS_OPENPGP_KEYID_SIZE];
1658 ret = gnutls_openpgp_crt_get_key_id (key, tmp);
1659 if (ret < 0)
1660 return gnutls_assert_val(ret);
1662 key->preferred_set = 1;
1663 memcpy (key->preferred_keyid, tmp, GNUTLS_OPENPGP_KEYID_SIZE);
1665 return 0;
1668 /* check if the id is valid */
1669 ret = gnutls_openpgp_crt_get_subkey_idx (key, keyid);
1670 if (ret < 0)
1672 _gnutls_debug_log ("the requested subkey does not exist\n");
1673 gnutls_assert ();
1674 return ret;
1677 key->preferred_set = 1;
1678 memcpy (key->preferred_keyid, keyid, GNUTLS_OPENPGP_KEYID_SIZE);
1680 return 0;
1684 * gnutls_openpgp_crt_get_auth_subkey:
1685 * @crt: the structure that contains the OpenPGP public key.
1686 * @keyid: the struct to save the keyid.
1687 * @flag: Non-zero indicates that a valid subkey is always returned.
1689 * Returns the 64-bit keyID of the first valid OpenPGP subkey marked
1690 * for authentication. If flag is non-zero and no authentication
1691 * subkey exists, then a valid subkey will be returned even if it is
1692 * not marked for authentication.
1694 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
1697 gnutls_openpgp_crt_get_auth_subkey (gnutls_openpgp_crt_t crt,
1698 gnutls_openpgp_keyid_t keyid,
1699 unsigned int flag)
1701 int ret, subkeys, i;
1702 unsigned int usage;
1703 unsigned int keyid_init = 0;
1705 subkeys = gnutls_openpgp_crt_get_subkey_count (crt);
1706 if (subkeys <= 0)
1708 gnutls_assert ();
1709 return GNUTLS_E_OPENPGP_SUBKEY_ERROR;
1712 /* Try to find a subkey with the authentication flag set.
1713 * if none exists use the last one found
1715 for (i = 0; i < subkeys; i++)
1717 ret = gnutls_openpgp_crt_get_subkey_pk_algorithm(crt, i, NULL);
1718 if (ret == GNUTLS_PK_UNKNOWN)
1719 continue;
1721 ret = gnutls_openpgp_crt_get_subkey_revoked_status (crt, i);
1722 if (ret != 0) /* it is revoked. ignore it */
1723 continue;
1725 if (keyid_init == 0)
1726 { /* keep the first valid subkey */
1727 ret = gnutls_openpgp_crt_get_subkey_id (crt, i, keyid);
1728 if (ret < 0)
1730 gnutls_assert ();
1731 return ret;
1734 keyid_init = 1;
1737 ret = gnutls_openpgp_crt_get_subkey_usage (crt, i, &usage);
1738 if (ret < 0)
1740 gnutls_assert ();
1741 return ret;
1744 if (usage & GNUTLS_KEY_KEY_AGREEMENT)
1746 ret = gnutls_openpgp_crt_get_subkey_id (crt, i, keyid);
1747 if (ret < 0)
1749 gnutls_assert ();
1750 return ret;
1752 return 0;
1756 if (flag && keyid_init)
1757 return 0;
1758 else
1759 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;