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>
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.
44 gnutls_openpgp_crt_init (gnutls_openpgp_crt_t
* key
)
46 *key
= gnutls_calloc (1, sizeof (gnutls_openpgp_crt_int
));
49 return 0; /* success */
50 return GNUTLS_E_MEMORY_ERROR
;
54 * gnutls_openpgp_crt_deinit:
55 * @key: The structure to be initialized
57 * This function will deinitialize a key structure.
60 gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key
)
67 cdk_kbnode_release (key
->knode
);
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
84 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
87 gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key
,
88 const gnutls_datum_t
* data
,
89 gnutls_openpgp_crt_fmt_t format
)
94 if (data
->data
== NULL
|| data
->size
== 0)
97 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
100 if (format
== GNUTLS_OPENPGP_FMT_RAW
) armor
= 0;
103 rc
= cdk_kbnode_read_from_mem (&key
->knode
, armor
, data
->data
, data
->size
);
106 rc
= _gnutls_map_cdk_rc (rc
);
111 /* Test if the import was successful. */
112 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
116 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
122 int _gnutls_openpgp_export2 (cdk_kbnode_t node
,
123 gnutls_openpgp_crt_fmt_t format
,
124 gnutls_datum_t
* out
, int priv
)
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
);
137 gnutls_free(out
->data
);
138 return gnutls_assert_val(ret
);
143 return gnutls_assert_val(ret
);
148 /* internal version of export
151 _gnutls_openpgp_export (cdk_kbnode_t node
,
152 gnutls_openpgp_crt_fmt_t format
,
154 size_t * output_data_size
, int priv
)
156 size_t input_data_size
= *output_data_size
;
160 rc
= cdk_kbnode_write_to_mem (node
, output_data
, output_data_size
);
163 rc
= _gnutls_map_cdk_rc (rc
);
168 /* If the caller uses output_data == NULL then return what he expects.
170 if (!output_data
&& format
!= GNUTLS_OPENPGP_FMT_BASE64
)
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
,
185 priv
? CDK_ARMOR_SECKEY
:
187 if (rc
|| calc_size
> input_data_size
)
190 *output_data_size
= calc_size
;
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
:
200 *output_data_size
= calc_size
;
204 rc
= _gnutls_map_cdk_rc (rc
);
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
,
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
)
272 cdk_pkt_pubkey_t pk
= NULL
;
277 return GNUTLS_E_INVALID_REQUEST
;
282 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
284 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
286 pk
= pkt
->pkt
.public_key
;
289 /* FIXME: Check if the draft allows old PGP keys. */
290 if (is_RSA (pk
->pubkey_algo
) && pk
->version
< 4)
292 cdk_pk_get_fingerprint (pk
, fpr
);
298 _gnutls_openpgp_count_key_names (gnutls_openpgp_crt_t key
)
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
)
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
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
;
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
;
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
)
371 return GNUTLS_E_INTERNAL_ERROR
;
374 uid
= pkt
->pkt
.user_id
;
375 if (uid
->len
>= *sizeof_buf
)
378 *sizeof_buf
= uid
->len
+ 1;
379 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
384 memcpy (buf
, uid
->name
, uid
->len
);
385 buf
[uid
->len
] = '\0'; /* make sure it's a string */
387 *sizeof_buf
= uid
->len
+ 1;
390 return GNUTLS_E_OPENPGP_UID_REVOKED
;
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
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
,
416 uint8_t keyid
[GNUTLS_OPENPGP_KEYID_SIZE
];
421 return GNUTLS_PK_UNKNOWN
;
424 ret
= gnutls_openpgp_crt_get_preferred_key_id (key
, keyid
);
429 idx
= gnutls_openpgp_crt_get_subkey_idx (key
, keyid
);
430 if (idx
!= GNUTLS_OPENPGP_MASTER_KEYID_IDX
)
433 gnutls_openpgp_crt_get_subkey_pk_algorithm (key
, idx
, bits
);
438 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
442 *bits
= cdk_pk_get_nbits (pkt
->pkt
.public_key
);
443 algo
= _gnutls_openpgp_get_algo (pkt
->pkt
.public_key
->pubkey_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
)
467 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
469 version
= pkt
->pkt
.public_key
->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.
486 gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key
)
494 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
496 timestamp
= pkt
->pkt
.public_key
->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
511 * Returns: the time when the OpenPGP key expires.
514 gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key
)
522 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
524 expiredate
= pkt
->pkt
.public_key
->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.
538 * Returns: the 64-bit keyID of the OpenPGP key.
543 gnutls_openpgp_crt_get_key_id (gnutls_openpgp_crt_t key
,
544 gnutls_openpgp_keyid_t keyid
)
552 return GNUTLS_E_INVALID_REQUEST
;
555 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
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);
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
578 gnutls_openpgp_crt_get_revoked_status (gnutls_openpgp_crt_t key
)
585 return GNUTLS_E_INVALID_REQUEST
;
588 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
590 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
592 if (pkt
->pkt
.public_key
->is_revoked
!= 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: non-zero for a successful match, and zero on failure.
609 gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key
,
610 const char *hostname
)
612 char dnsname
[MAX_CN
];
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
);
625 /* Length returned by gnutls_openpgp_crt_get_name includes
626 the terminating (0). */
629 if (_gnutls_hostname_compare (dnsname
, dnsnamesize
, hostname
, 0))
634 /* not found a matching name */
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
;
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
)
677 return GNUTLS_E_INVALID_REQUEST
;
680 pkt
= cdk_kbnode_find_packet (key
->knode
, CDK_PKT_PUBLIC_KEY
);
682 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
684 *key_usage
= _gnutls_get_pgp_key_usage (pkt
->pkt
.public_key
->pubkey_usage
);
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.
701 gnutls_openpgp_crt_get_subkey_count (gnutls_openpgp_crt_t key
)
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
)
725 /* returns the subkey with the given index */
727 _get_public_subkey (gnutls_openpgp_crt_t key
, unsigned int indx
)
731 unsigned int subkeys
;
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
++)
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;
757 _gnutls_openpgp_find_key (cdk_kbnode_t knode
, uint32_t keyid
[2],
762 uint32_t local_keyid
[2];
765 while ((p
= cdk_kbnode_walk (knode
, &ctx
, 0)))
767 pkt
= cdk_kbnode_get_packet (p
);
770 && (pkt
->pkttype
== CDK_PKT_PUBLIC_SUBKEY
771 || pkt
->pkttype
== CDK_PKT_PUBLIC_KEY
)) || (priv
!= 0
773 CDK_PKT_SECRET_SUBKEY
776 CDK_PKT_SECRET_KEY
)))
779 cdk_pk_get_keyid (pkt
->pkt
.public_key
, local_keyid
);
781 cdk_pk_get_keyid (pkt
->pkt
.secret_key
->pk
, local_keyid
);
783 if (local_keyid
[0] == keyid
[0] && local_keyid
[1] == keyid
[1])
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],
806 uint32_t local_keyid
[2];
808 _gnutls_hard_log ("Looking keyid: %x.%x\n", keyid
[0], keyid
[1]);
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
)))
819 cdk_pk_get_keyid (pkt
->pkt
.public_key
, local_keyid
);
821 cdk_pk_get_keyid (pkt
->pkt
.secret_key
->pk
, local_keyid
);
823 _gnutls_hard_log ("Found keyid: %x.%x\n", local_keyid
[0],
825 if (local_keyid
[0] == keyid
[0] && local_keyid
[1] == keyid
[1])
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
850 gnutls_openpgp_crt_get_subkey_revoked_status (gnutls_openpgp_crt_t key
,
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
);
866 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
868 if (pkt
->pkt
.public_key
->is_revoked
!= 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
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.
891 gnutls_pk_algorithm_t
892 gnutls_openpgp_crt_get_subkey_pk_algorithm (gnutls_openpgp_crt_t key
,
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
);
914 *bits
= cdk_pk_get_nbits (pkt
->pkt
.public_key
);
915 algo
= _gnutls_openpgp_get_algo (pkt
->pkt
.public_key
->pubkey_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.
933 gnutls_openpgp_crt_get_subkey_creation_time (gnutls_openpgp_crt_t key
,
942 if (idx
== GNUTLS_OPENPGP_MASTER_KEYID_IDX
)
943 return gnutls_openpgp_crt_get_creation_time(key
);
945 pkt
= _get_public_subkey (key
, idx
);
947 timestamp
= pkt
->pkt
.public_key
->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.
968 gnutls_openpgp_crt_get_subkey_expiration_time (gnutls_openpgp_crt_t key
,
977 if (idx
== GNUTLS_OPENPGP_MASTER_KEYID_IDX
)
978 return gnutls_openpgp_crt_get_expiration_time(key
);
980 pkt
= _get_public_subkey (key
, idx
);
982 expiredate
= pkt
->pkt
.public_key
->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
,
1002 gnutls_openpgp_keyid_t keyid
)
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
);
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);
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.
1042 gnutls_openpgp_crt_get_subkey_fingerprint (gnutls_openpgp_crt_t key
,
1044 void *fpr
, size_t * fprlen
)
1047 cdk_pkt_pubkey_t pk
= NULL
;
1049 if (!fpr
|| !fprlen
)
1052 return GNUTLS_E_INVALID_REQUEST
;
1055 if (idx
== GNUTLS_OPENPGP_MASTER_KEYID_IDX
)
1056 return gnutls_openpgp_crt_get_fingerprint(key
, fpr
, fprlen
);
1060 pkt
= _get_public_subkey (key
, idx
);
1062 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
1064 pk
= pkt
->pkt
.public_key
;
1067 /* FIXME: Check if the draft allows old PGP keys. */
1068 if (is_RSA (pk
->pubkey_algo
) && pk
->version
< 4)
1070 cdk_pk_get_fingerprint (pk
, fpr
);
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.
1087 gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key
,
1088 const gnutls_openpgp_keyid_t keyid
)
1092 uint8_t master_id
[GNUTLS_OPENPGP_KEYID_SIZE
];
1097 return GNUTLS_E_INVALID_REQUEST
;
1100 ret
= gnutls_openpgp_crt_get_key_id (key
, master_id
);
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);
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.
1134 gnutls_openpgp_crt_get_subkey_usage (gnutls_openpgp_crt_t key
,
1136 unsigned int *key_usage
)
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
);
1151 return GNUTLS_E_OPENPGP_SUBKEY_ERROR
;
1153 *key_usage
= _gnutls_get_pgp_key_usage (pkt
->pkt
.public_key
->pubkey_usage
);
1159 _gnutls_read_pgp_mpi (cdk_packet_t pkt
, unsigned int priv
, size_t idx
,
1162 size_t buf_size
= 512;
1163 uint8_t *buf
= gnutls_malloc (buf_size
);
1165 unsigned int max_pub_params
= 0;
1168 max_pub_params
= cdk_pk_get_npkey (pkt
->pkt
.secret_key
->pk
->pubkey_algo
);
1173 return GNUTLS_E_MEMORY_ERROR
;
1176 /* FIXME: Note that opencdk doesn't like the buf to be NULL.
1180 cdk_pk_get_mpi (pkt
->pkt
.public_key
, idx
, buf
, buf_size
, &buf_size
,
1184 if (idx
< max_pub_params
)
1186 cdk_pk_get_mpi (pkt
->pkt
.secret_key
->pk
, idx
, buf
, buf_size
,
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
);
1202 return GNUTLS_E_MEMORY_ERROR
;
1207 cdk_pk_get_mpi (pkt
->pkt
.public_key
, idx
, buf
, buf_size
, &buf_size
,
1211 if (idx
< max_pub_params
)
1213 cdk_pk_get_mpi (pkt
->pkt
.secret_key
->pk
, idx
, buf
, buf_size
,
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
)
1228 return _gnutls_map_cdk_rc (err
);
1231 err
= _gnutls_mpi_scan (m
, buf
, buf_size
);
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
)
1252 int pk_algorithm
, local_params
;
1256 pkt
= cdk_kbnode_find_packet (cert
->knode
, CDK_PKT_PUBLIC_KEY
);
1258 pkt
= _gnutls_openpgp_find_key (cert
->knode
, keyid
, 0);
1263 return GNUTLS_E_OPENPGP_GETKEY_FAILED
;
1266 pk_algorithm
= _gnutls_openpgp_get_algo (pkt
->pkt
.public_key
->pubkey_algo
);
1268 switch (pk_algorithm
)
1271 local_params
= RSA_PUBLIC_PARAMS
;
1274 local_params
= DSA_PUBLIC_PARAMS
;
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
, ¶ms
->params
[i
]);
1291 params
->params_nr
++;
1297 gnutls_pk_params_release(params
);
1302 /* The internal version of export
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
;
1311 gnutls_pk_params_st params
;
1313 gnutls_pk_params_init(¶ms
);
1318 return GNUTLS_E_INVALID_REQUEST
;
1321 KEYID_IMPORT (kid32
, keyid
);
1323 pkt
= _gnutls_openpgp_find_key (crt
->knode
, kid32
, 0);
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
)
1335 return GNUTLS_E_INVALID_REQUEST
;
1338 ret
= _gnutls_openpgp_crt_get_mpis (crt
, kid32
, ¶ms
);
1345 ret
= _gnutls_mpi_dprint (params
.params
[0], m
);
1352 ret
= _gnutls_mpi_dprint (params
.params
[1], e
);
1356 _gnutls_free_datum (m
);
1363 gnutls_pk_params_release(¶ms
);
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
;
1375 gnutls_pk_params_st params
;
1377 gnutls_pk_params_init(¶ms
);
1382 return GNUTLS_E_INVALID_REQUEST
;
1385 KEYID_IMPORT (kid32
, keyid
);
1387 pkt
= _gnutls_openpgp_find_key (crt
->knode
, kid32
, 0);
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
)
1399 return GNUTLS_E_INVALID_REQUEST
;
1402 ret
= _gnutls_openpgp_crt_get_mpis (crt
, kid32
, ¶ms
);
1410 ret
= _gnutls_mpi_dprint (params
.params
[0], p
);
1418 ret
= _gnutls_mpi_dprint (params
.params
[1], q
);
1422 _gnutls_free_datum (p
);
1428 ret
= _gnutls_mpi_dprint (params
.params
[2], g
);
1432 _gnutls_free_datum (p
);
1433 _gnutls_free_datum (q
);
1439 ret
= _gnutls_mpi_dprint (params
.params
[3], y
);
1443 _gnutls_free_datum (p
);
1444 _gnutls_free_datum (g
);
1445 _gnutls_free_datum (q
);
1452 gnutls_pk_params_release(¶ms
);
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.
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
];
1478 ret
= gnutls_openpgp_crt_get_key_id (crt
, keyid
);
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.
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
];
1512 ret
= gnutls_openpgp_crt_get_key_id (crt
, keyid
);
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.
1538 gnutls_openpgp_crt_get_subkey_pk_rsa_raw (gnutls_openpgp_crt_t crt
,
1543 uint8_t keyid
[GNUTLS_OPENPGP_KEYID_SIZE
];
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
);
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.
1577 gnutls_openpgp_crt_get_subkey_pk_dsa_raw (gnutls_openpgp_crt_t crt
,
1584 uint8_t keyid
[GNUTLS_OPENPGP_KEYID_SIZE
];
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
);
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
);
1620 return GNUTLS_E_INVALID_REQUEST
;
1623 memcpy (keyid
, key
->preferred_keyid
, GNUTLS_OPENPGP_KEYID_SIZE
);
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
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
)
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
);
1660 return gnutls_assert_val(ret
);
1662 key
->preferred_set
= 1;
1663 memcpy (key
->preferred_keyid
, tmp
, GNUTLS_OPENPGP_KEYID_SIZE
);
1668 /* check if the id is valid */
1669 ret
= gnutls_openpgp_crt_get_subkey_idx (key
, keyid
);
1672 _gnutls_debug_log ("the requested subkey does not exist\n");
1677 key
->preferred_set
= 1;
1678 memcpy (key
->preferred_keyid
, keyid
, GNUTLS_OPENPGP_KEYID_SIZE
);
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
,
1701 int ret
, subkeys
, i
;
1703 unsigned int keyid_init
= 0;
1705 subkeys
= gnutls_openpgp_crt_get_subkey_count (crt
);
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
)
1721 ret
= gnutls_openpgp_crt_get_subkey_revoked_status (crt
, i
);
1722 if (ret
!= 0) /* it is revoked. ignore it */
1725 if (keyid_init
== 0)
1726 { /* keep the first valid subkey */
1727 ret
= gnutls_openpgp_crt_get_subkey_id (crt
, i
, keyid
);
1737 ret
= gnutls_openpgp_crt_get_subkey_usage (crt
, i
, &usage
);
1744 if (usage
& GNUTLS_KEY_KEY_AGREEMENT
)
1746 ret
= gnutls_openpgp_crt_get_subkey_id (crt
, i
, keyid
);
1756 if (flag
&& keyid_init
)
1759 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;