diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-10-11 20:47:46 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-10-11 22:05:44 +0200 |
commit | 00ff88629c1c8a391a0515e87e5cd98259b77c6c (patch) | |
tree | fc30a7c610d0b6e4831cb29f3da54b15fb4ea26c | |
parent | 3a8d9b33d8bf9d5fb53f051e92db5d4d88fc1f90 (diff) | |
download | gnutls-00ff88629c1c8a391a0515e87e5cd98259b77c6c.tar.gz |
Several OpenPGP updates.
Exported gnutls_certificate_get_peers_subkey_id().
Removed compatibility code with RFC5081.
The gnutls_openpgp_*_get_subkey_*() functions return the master key parameters if provided with GNUTLS_OPENPGP_MASTER_KEYID_IDX.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | lib/auth/cert.c | 115 | ||||
-rw-r--r-- | lib/auth/cert.h | 1 | ||||
-rw-r--r-- | lib/gnutls_pcert.c | 3 | ||||
-rw-r--r-- | lib/gnutls_pubkey.c | 9 | ||||
-rw-r--r-- | lib/gnutls_ui.c | 27 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 3 | ||||
-rw-r--r-- | lib/includes/gnutls/openpgp.h | 3 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/openpgp/pgp.c | 56 | ||||
-rw-r--r-- | lib/openpgp/privkey.c | 73 |
11 files changed, 182 insertions, 113 deletions
@@ -27,6 +27,9 @@ response corresponds to the given certificate. OCSP certificate status request extensions by default. The flag GNUTLS_NO_EXTENSIONS can be used to prevent that. +** libgnutls: Compatibility code with RFC5081 was removed. The OpenPGP +code now is RFC6091 compliant only. + ** libgnutls-dane: Added. It is a library to provide DANE with DNSSEC certificate verification. @@ -35,6 +38,7 @@ certificate verification. ** certtool: The --dane-tlsa-rr option generates DANE TLSA Resource Records (RR). ** API and ABI modifications: +gnutls_certificate_get_peers_subkey_id: Added gnutls_certificate_set_ocsp_status_request_function: Added gnutls_certificate_set_ocsp_status_request_file: Added gnutls_ocsp_status_request_enable_client: Added diff --git a/lib/auth/cert.c b/lib/auth/cert.c index 34bc6d2dd4..95bd6d06e5 100644 --- a/lib/auth/cert.c +++ b/lib/auth/cert.c @@ -73,7 +73,7 @@ typedef enum CertificateSigType * exported certificate struct (cert_auth_info_t) */ static int -_gnutls_copy_certificate_auth_info (cert_auth_info_t info, gnutls_pcert_st * certs, size_t ncerts, int subkey_used, /* openpgp only */ +_gnutls_copy_certificate_auth_info (cert_auth_info_t info, gnutls_pcert_st * certs, size_t ncerts, /* openpgp only */ void *keyid) { /* Copy peer's information to auth_info_t @@ -123,7 +123,6 @@ _gnutls_copy_certificate_auth_info (cert_auth_info_t info, gnutls_pcert_st * cer #ifdef ENABLE_OPENPGP if (certs[0].type == GNUTLS_CRT_OPENPGP) { - info->use_subkey = subkey_used; if (keyid) memcpy (info->subkey_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE); } @@ -846,7 +845,7 @@ _gnutls_gen_x509_crt (gnutls_session_t session, gnutls_buffer_st * data) } enum PGPKeyDescriptorType -{ PGP_KEY_FINGERPRINT, PGP_KEY, PGP_KEY_SUBKEY, PGP_KEY_FINGERPRINT_SUBKEY }; +{ PGP_EMPTY_KEY=1, PGP_KEY_SUBKEY, PGP_KEY_FINGERPRINT_SUBKEY }; #ifdef ENABLE_OPENPGP static int @@ -860,7 +859,6 @@ _gnutls_gen_openpgp_certificate (gnutls_session_t session, uint8_t type; uint8_t fpr[20]; size_t fpr_size; - unsigned int use_subkey = 0; /* find the appropriate certificate */ if ((ret = @@ -880,12 +878,11 @@ _gnutls_gen_openpgp_certificate (gnutls_session_t session, fpr_size = sizeof (fpr); ret = gnutls_pubkey_get_openpgp_key_id (apr_cert_list[0].pubkey, 0, fpr, - &fpr_size, &use_subkey); + &fpr_size, NULL); if (ret < 0) return gnutls_assert_val (ret); - if (use_subkey != 0) - ret += 1 + fpr_size; /* for the keyid */ + ret += 1 + fpr_size; /* for the keyid */ ret += apr_cert_list[0].cert.size; } @@ -897,25 +894,15 @@ _gnutls_gen_openpgp_certificate (gnutls_session_t session, if (apr_cert_list_length > 0) { - if (use_subkey != 0) - { - type = PGP_KEY_SUBKEY; + type = PGP_KEY_SUBKEY; - ret = _gnutls_buffer_append_data (data, &type, 1); - if (ret < 0) - return gnutls_assert_val (ret); + ret = _gnutls_buffer_append_data (data, &type, 1); + if (ret < 0) + return gnutls_assert_val (ret); - ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size); - if (ret < 0) - return gnutls_assert_val (ret); - } - else - { - type = PGP_KEY; - ret = _gnutls_buffer_append_data (data, &type, 1); - if (ret < 0) - return gnutls_assert_val (ret); - } + ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size); + if (ret < 0) + return gnutls_assert_val (ret); ret = _gnutls_buffer_append_data_prefix (data, 24, @@ -926,7 +913,7 @@ _gnutls_gen_openpgp_certificate (gnutls_session_t session, } else /* empty - no certificate */ { - type = PGP_KEY; + type = PGP_EMPTY_KEY; ret = _gnutls_buffer_append_data (data, &type, 1); if (ret < 0) @@ -950,7 +937,6 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session, gnutls_pcert_st *apr_cert_list; gnutls_privkey_t apr_pkey; int apr_cert_list_length; - unsigned int use_subkey = 0; /* find the appropriate certificate */ if ((ret = @@ -964,14 +950,12 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session, fpr_size = sizeof (fpr); ret = gnutls_pubkey_get_openpgp_key_id (apr_cert_list[0].pubkey, 0, fpr, - &fpr_size, &use_subkey); + &fpr_size, NULL); if (ret < 0) return gnutls_assert_val (ret); packet_size = 3 + 1; - - if (use_subkey) - packet_size += 1 + fpr_size; /* for the keyid */ + packet_size += 1 + fpr_size; /* for the keyid */ /* Only v4 fingerprints are sent */ @@ -984,33 +968,10 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session, if (ret < 0) return gnutls_assert_val (ret); - if (use_subkey) - { - type = PGP_KEY_FINGERPRINT_SUBKEY; - ret = _gnutls_buffer_append_data (data, &type, 1); - if (ret < 0) - return gnutls_assert_val (ret); - - ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size); - if (ret < 0) - return gnutls_assert_val (ret); - } - else - { - type = PGP_KEY_FINGERPRINT; /* key fingerprint */ - ret = _gnutls_buffer_append_data (data, &type, 1); - if (ret < 0) - return gnutls_assert_val (ret); - } - - fpr_size = sizeof (fpr); - if ((ret = - _gnutls_openpgp_fingerprint (&apr_cert_list[0].cert, fpr, - &fpr_size)) < 0) - { - gnutls_assert (); - return ret; - } + type = PGP_KEY_FINGERPRINT_SUBKEY; + ret = _gnutls_buffer_append_data (data, &type, 1); + if (ret < 0) + return gnutls_assert_val (ret); ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size); if (ret < 0) @@ -1182,7 +1143,7 @@ _gnutls_proc_x509_server_crt (gnutls_session_t session, if ((ret = _gnutls_copy_certificate_auth_info (info, peer_certificate_list, - peer_certificate_list_size, 0, + peer_certificate_list_size, NULL)) < 0) { gnutls_assert (); @@ -1220,7 +1181,6 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, gnutls_pcert_st *peer_certificate_list = NULL; gnutls_datum_t tmp, akey = { NULL, 0 }; uint8_t subkey_id[GNUTLS_OPENPGP_KEYID_SIZE]; - unsigned int subkey_id_set = 0; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session, GNUTLS_CRD_CERTIFICATE, NULL); @@ -1278,16 +1238,10 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, DECR_LEN (dsize, GNUTLS_OPENPGP_KEYID_SIZE); memcpy (subkey_id, p, GNUTLS_OPENPGP_KEYID_SIZE); p += GNUTLS_OPENPGP_KEYID_SIZE; - - subkey_id_set = 1; - } - /* read the actual key or fingerprint */ - if (key_type == PGP_KEY_FINGERPRINT || - key_type == PGP_KEY_FINGERPRINT_SUBKEY) - { /* the fingerprint */ - + if (key_type == PGP_KEY_FINGERPRINT_SUBKEY) + { DECR_LEN (dsize, 1); len = (uint8_t) * p; p++; @@ -1311,7 +1265,7 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, } tmp = akey; } - else if (key_type == PGP_KEY || key_type == PGP_KEY_SUBKEY) + else if (key_type == PGP_KEY_SUBKEY) { /* the whole key */ /* Read the actual certificate */ @@ -1323,7 +1277,7 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, { gnutls_assert (); /* no certificate was sent */ - return GNUTLS_E_NO_CERTIFICATE_FOUND; + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); } DECR_LEN (dsize, len); @@ -1332,6 +1286,19 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, tmp.data = p; } + else if (key_type == PGP_EMPTY_KEY) + { /* the whole key */ + + /* Read the actual certificate */ + DECR_LEN (dsize, 3); + len = _gnutls_read_uint24 (p); + p += 3; + + if (len != 0) /* PGP_EMPTY_KEY */ + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + else + return GNUTLS_E_NO_CERTIFICATE_FOUND; + } else { gnutls_assert (); @@ -1341,8 +1308,7 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, /* ok we now have the peer's key in tmp datum */ peer_certificate_list = - gnutls_calloc (1, - sizeof (gnutls_pcert_st)); + gnutls_calloc (1, sizeof (gnutls_pcert_st)); if (peer_certificate_list == NULL) { gnutls_assert (); @@ -1354,7 +1320,7 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, gnutls_pcert_import_openpgp_raw (&peer_certificate_list[0], &tmp, GNUTLS_OPENPGP_FMT_RAW, - (subkey_id_set != 0) ? subkey_id : NULL, + subkey_id, 0); if (ret < 0) { @@ -1365,10 +1331,7 @@ _gnutls_proc_openpgp_server_crt (gnutls_session_t session, ret = _gnutls_copy_certificate_auth_info (info, peer_certificate_list, - 1, - subkey_id_set, - (subkey_id_set != - 0) ? subkey_id : NULL); + 1, subkey_id); if (ret < 0) { gnutls_assert (); diff --git a/lib/auth/cert.h b/lib/auth/cert.h index b253e79349..93f7e52e6b 100644 --- a/lib/auth/cert.h +++ b/lib/auth/cert.h @@ -118,7 +118,6 @@ typedef struct cert_auth_info_st gnutls_certificate_type_t cert_type; #ifdef ENABLE_OPENPGP - int use_subkey; uint8_t subkey_id[GNUTLS_OPENPGP_KEYID_SIZE]; #endif } *cert_auth_info_t; diff --git a/lib/gnutls_pcert.c b/lib/gnutls_pcert.c index 1211e2d6fb..3a6b6fee5c 100644 --- a/lib/gnutls_pcert.c +++ b/lib/gnutls_pcert.c @@ -396,8 +396,7 @@ _gnutls_get_auth_info_pcert (gnutls_pcert_st* pcert, return gnutls_pcert_import_openpgp_raw(pcert, &info->raw_certificate_list[0], GNUTLS_OPENPGP_FMT_RAW, - info->use_subkey ? info-> - subkey_id : NULL, GNUTLS_PCERT_NO_CERT); + info->subkey_id, GNUTLS_PCERT_NO_CERT); #endif default: gnutls_assert (); diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index c492445e94..253b72249e 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -420,14 +420,13 @@ gnutls_pubkey_import_openpgp (gnutls_pubkey_t key, * replaced by the actual size of parameters) * @subkey: Will be non zero if the key ID corresponds to a subkey * - * This function will return a unique ID the depends on the public - * key parameters. This ID can be used in checking whether a - * certificate corresponds to the given public key. + * This function returned the OpenPGP key ID of the corresponding key. + * The key is a unique ID the depends on the public + * key parameters. * * If the buffer provided is not long enough to hold the output, then * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will - * be returned. The output will normally be a SHA-1 hash output, - * which is 20 bytes. + * be returned. The output is %GNUTLS_OPENPGP_KEYID_SIZE bytes long. * * Returns: In case of failure a negative error code will be * returned, and 0 on success. diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c index 654810abbc..1cd53f273c 100644 --- a/lib/gnutls_ui.c +++ b/lib/gnutls_ui.c @@ -552,6 +552,33 @@ gnutls_certificate_get_peers (gnutls_session_t return info->raw_certificate_list; } +/** + * gnutls_certificate_get_peers_subkey_id: + * @session: is a gnutls session + * @id: will contain the ID + * + * Get the peer's subkey ID when OpenPGP certificates are + * used. The returned @id should be treated as constant. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise + * an error code is returned. + **/ +int gnutls_certificate_get_peers_subkey_id(gnutls_session_t session, + gnutls_datum_t *id) +{ + cert_auth_info_t info; + + CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); + + info = _gnutls_get_auth_info (session); + if (info == NULL) + return GNUTLS_E_INVALID_REQUEST; + + id->data = info->subkey_id; + id->size = GNUTLS_OPENPGP_KEYID_SIZE; + + return 0; +} /** * gnutls_certificate_client_get_request_status: diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index ec553a03f3..55928ce268 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1684,6 +1684,9 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); const gnutls_datum_t *gnutls_certificate_get_ours (gnutls_session_t session); + int gnutls_certificate_get_peers_subkey_id(gnutls_session_t session, + gnutls_datum_t *id); + time_t gnutls_certificate_activation_time_peers (gnutls_session_t session); time_t gnutls_certificate_expiration_time_peers (gnutls_session_t session); diff --git a/lib/includes/gnutls/openpgp.h b/lib/includes/gnutls/openpgp.h index bed810168b..ae612f5fa5 100644 --- a/lib/includes/gnutls/openpgp.h +++ b/lib/includes/gnutls/openpgp.h @@ -28,6 +28,7 @@ #define GNUTLS_OPENPGP_H #include <gnutls/gnutls.h> +#include <limits.h> #ifdef __cplusplus extern "C" @@ -79,6 +80,8 @@ extern "C" /* The key_usage flags are defined in gnutls.h. They are * the GNUTLS_KEY_* definitions. */ +#define GNUTLS_OPENPGP_MASTER_KEYID_IDX INT_MAX + int gnutls_openpgp_crt_get_key_usage (gnutls_openpgp_crt_t key, unsigned int *key_usage); int gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key, void *fpr, diff --git a/lib/libgnutls.map b/lib/libgnutls.map index c795ab1843..438120e044 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -856,6 +856,7 @@ GNUTLS_3_1_0 { gnutls_pkcs12_export2; gnutls_pubkey_import_openpgp_raw; gnutls_pubkey_import_x509_raw; + gnutls_certificate_get_peers_subkey_id; } GNUTLS_3_0_0; GNUTLS_PRIVATE { diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c index 78ef7882b8..97f9491132 100644 --- a/lib/openpgp/pgp.c +++ b/lib/openpgp/pgp.c @@ -427,20 +427,22 @@ gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key, int idx; idx = gnutls_openpgp_crt_get_subkey_idx (key, keyid); - algo = - gnutls_openpgp_crt_get_subkey_pk_algorithm (key, idx, NULL); - } - else - { - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (pkt) + if (idx != GNUTLS_OPENPGP_MASTER_KEYID_IDX) { - if (bits) - *bits = cdk_pk_get_nbits (pkt->pkt.public_key); - algo = _gnutls_openpgp_get_algo (pkt->pkt.public_key->pubkey_algo); + algo = + gnutls_openpgp_crt_get_subkey_pk_algorithm (key, idx, bits); + return algo; } } + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); + if (pkt) + { + if (bits) + *bits = cdk_pk_get_nbits (pkt->pkt.public_key); + algo = _gnutls_openpgp_get_algo (pkt->pkt.public_key->pubkey_algo); + } + return algo; } @@ -856,6 +858,9 @@ gnutls_openpgp_crt_get_subkey_revoked_status (gnutls_openpgp_crt_t key, return GNUTLS_E_INVALID_REQUEST; } + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_revoked_status(key); + pkt = _get_public_subkey (key, idx); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; @@ -897,6 +902,9 @@ gnutls_openpgp_crt_get_subkey_pk_algorithm (gnutls_openpgp_crt_t key, return GNUTLS_PK_UNKNOWN; } + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_pk_algorithm(key, bits); + pkt = _get_public_subkey (key, idx); algo = 0; @@ -931,6 +939,9 @@ gnutls_openpgp_crt_get_subkey_creation_time (gnutls_openpgp_crt_t key, if (!key) return (time_t) - 1; + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_creation_time(key); + pkt = _get_public_subkey (key, idx); if (pkt) timestamp = pkt->pkt.public_key->timestamp; @@ -963,6 +974,9 @@ gnutls_openpgp_crt_get_subkey_expiration_time (gnutls_openpgp_crt_t key, if (!key) return (time_t) - 1; + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_expiration_time(key); + pkt = _get_public_subkey (key, idx); if (pkt) expiredate = pkt->pkt.public_key->expiredate; @@ -995,6 +1009,9 @@ gnutls_openpgp_crt_get_subkey_id (gnutls_openpgp_crt_t key, gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } + + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_key_id(key, keyid); pkt = _get_public_subkey (key, idx); if (!pkt) @@ -1034,6 +1051,9 @@ gnutls_openpgp_crt_get_subkey_fingerprint (gnutls_openpgp_crt_t key, gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } + + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_fingerprint(key, fpr, fprlen); *fprlen = 0; @@ -1069,6 +1089,7 @@ gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key, { int ret; uint32_t kid[2]; + uint8_t master_id[GNUTLS_OPENPGP_KEYID_SIZE]; if (!key) { @@ -1076,6 +1097,12 @@ gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key, return GNUTLS_E_INVALID_REQUEST; } + ret = gnutls_openpgp_crt_get_key_id (key, master_id); + if (ret < 0) + return gnutls_assert_val(ret); + if (memcmp(master_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE)==0) + return GNUTLS_OPENPGP_MASTER_KEYID_IDX; + KEYID_IMPORT (kid, keyid); ret = _gnutls_openpgp_find_subkey_idx (key->knode, kid, 0); @@ -1116,6 +1143,9 @@ gnutls_openpgp_crt_get_subkey_usage (gnutls_openpgp_crt_t key, return GNUTLS_E_INVALID_REQUEST; } + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_key_usage(key, key_usage); + pkt = _get_public_subkey (key, idx); if (!pkt) return GNUTLS_E_OPENPGP_SUBKEY_ERROR; @@ -1513,6 +1543,9 @@ gnutls_openpgp_crt_get_subkey_pk_rsa_raw (gnutls_openpgp_crt_t crt, uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; int ret; + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_pk_rsa_raw(crt, m, e); + ret = gnutls_openpgp_crt_get_subkey_id (crt, idx, keyid); if (ret < 0) { @@ -1551,6 +1584,9 @@ gnutls_openpgp_crt_get_subkey_pk_dsa_raw (gnutls_openpgp_crt_t crt, uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; int ret; + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_crt_get_pk_dsa_raw(crt, p,q, g, y); + ret = gnutls_openpgp_crt_get_subkey_id (crt, idx, keyid); if (ret < 0) { diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c index 461aa9d0e6..9498353b04 100644 --- a/lib/openpgp/privkey.c +++ b/lib/openpgp/privkey.c @@ -293,20 +293,22 @@ gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, int idx; idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); - algo = - gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, NULL); - } - else - { - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); - if (pkt) + if (idx != GNUTLS_OPENPGP_MASTER_KEYID_IDX) { - if (bits) - *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); - algo = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); + algo = + gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, bits); + return algo; } } + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); + if (pkt) + { + if (bits) + *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); + algo = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); + } + return algo; } @@ -440,7 +442,6 @@ gnutls_openpgp_privkey_get_key_id (gnutls_openpgp_privkey_t key, return 0; } - /** * gnutls_openpgp_privkey_get_subkey_count: * @key: is an OpenPGP key @@ -521,6 +522,9 @@ gnutls_openpgp_privkey_get_subkey_revoked_status (gnutls_openpgp_privkey_t return GNUTLS_E_INVALID_REQUEST; } + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_privkey_get_revoked_status(key); + pkt = _get_secret_subkey (key, idx); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; @@ -562,6 +566,9 @@ gnutls_openpgp_privkey_get_subkey_pk_algorithm (gnutls_openpgp_privkey_t key, return GNUTLS_PK_UNKNOWN; } + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_privkey_get_pk_algorithm(key, bits); + pkt = _get_secret_subkey (key, idx); algo = 0; @@ -598,6 +605,7 @@ gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key, { int ret; uint32_t kid[2]; + uint8_t master_id[GNUTLS_OPENPGP_KEYID_SIZE]; if (!key) { @@ -605,6 +613,12 @@ gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key, return GNUTLS_E_INVALID_REQUEST; } + ret = gnutls_openpgp_privkey_get_key_id (key, master_id); + if (ret < 0) + return gnutls_assert_val(ret); + if (memcmp(master_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE)==0) + return GNUTLS_OPENPGP_MASTER_KEYID_IDX; + KEYID_IMPORT (kid, keyid); ret = _gnutls_openpgp_find_subkey_idx (key->knode, kid, 1); @@ -637,7 +651,11 @@ gnutls_openpgp_privkey_get_subkey_creation_time (gnutls_openpgp_privkey_t key, if (!key) return (time_t) - 1; - pkt = _get_secret_subkey (key, idx); + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); + else + pkt = _get_secret_subkey (key, idx); + if (pkt) timestamp = pkt->pkt.secret_key->pk->timestamp; else @@ -663,18 +681,22 @@ gnutls_openpgp_privkey_get_subkey_expiration_time (gnutls_openpgp_privkey_t key, unsigned int idx) { cdk_packet_t pkt; - time_t expiredate; + time_t timestamp; if (!key) return (time_t) - 1; - pkt = _get_secret_subkey (key, idx); + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); + else + pkt = _get_secret_subkey (key, idx); + if (pkt) - expiredate = pkt->pkt.secret_key->expiredate; + timestamp = pkt->pkt.secret_key->pk->expiredate; else - expiredate = 0; + timestamp = 0; - return expiredate; + return timestamp; } /** @@ -703,6 +725,9 @@ gnutls_openpgp_privkey_get_subkey_id (gnutls_openpgp_privkey_t key, return GNUTLS_E_INVALID_REQUEST; } + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_privkey_get_key_id(key, keyid); + pkt = _get_secret_subkey (key, idx); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; @@ -742,6 +767,9 @@ gnutls_openpgp_privkey_get_subkey_fingerprint (gnutls_openpgp_privkey_t key, return GNUTLS_E_INVALID_REQUEST; } + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + return gnutls_openpgp_privkey_get_fingerprint(key, fpr, fprlen); + *fprlen = 0; pkt = _get_secret_subkey (key, idx); @@ -1143,7 +1171,10 @@ gnutls_openpgp_privkey_export_subkey_rsa_raw (gnutls_openpgp_privkey_t pkey, uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; int ret; - ret = gnutls_openpgp_privkey_get_subkey_id (pkey, idx, keyid); + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + ret = gnutls_openpgp_privkey_get_key_id (pkey, keyid); + else + ret = gnutls_openpgp_privkey_get_subkey_id (pkey, idx, keyid); if (ret < 0) { gnutls_assert (); @@ -1183,7 +1214,11 @@ gnutls_openpgp_privkey_export_subkey_dsa_raw (gnutls_openpgp_privkey_t pkey, uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; int ret; - ret = gnutls_openpgp_privkey_get_subkey_id (pkey, idx, keyid); + if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) + ret = gnutls_openpgp_privkey_get_key_id (pkey, keyid); + else + ret = gnutls_openpgp_privkey_get_subkey_id (pkey, idx, keyid); + if (ret < 0) { gnutls_assert (); |