]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Several OpenPGP updates.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 11 Oct 2012 18:47:46 +0000 (20:47 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 11 Oct 2012 20:05:44 +0000 (22:05 +0200)
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.

NEWS
lib/auth/cert.c
lib/auth/cert.h
lib/gnutls_pcert.c
lib/gnutls_pubkey.c
lib/gnutls_ui.c
lib/includes/gnutls/gnutls.h.in
lib/includes/gnutls/openpgp.h
lib/libgnutls.map
lib/openpgp/pgp.c
lib/openpgp/privkey.c

diff --git a/NEWS b/NEWS
index 21c7777c6b4720869e50ba072c9b315511607baa..b2fc91d3bec3aaa955cc3cd53f9b5940a2d9df02 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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
index 34bc6d2dd44cb7128a5bc210895e7f57dda45951..95bd6d06e5b263f23ca8e0de27a31bd2a6a880bf 100644 (file)
@@ -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 ();
index b253e793490885bd14ba0ccb312119459516b682..93f7e52e6bc725154ef15d646b19b0b213547f8f 100644 (file)
@@ -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;
index 1211e2d6fb9f23dced3458605e1c8e8ec13e9014..3a6b6fee5c74a02abcf4812d656987ad0a094bf9 100644 (file)
@@ -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 ();
index c492445e9477f251cf8e90005ef9ed73e1379bf3..253b72249e45be0e42f177f135cb06ae17982f79 100644 (file)
@@ -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.
index 654810abbc4c773f8338bf1ddd1ab03a627e744c..1cd53f273cf4927d262d3952c5a0547558ca1655 100644 (file)
@@ -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:
index ec553a03f36a119c078aead528bde69477c972e9..55928ce268a516925b1d1988014aebaf4a268b43 100644 (file)
@@ -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);
 
index bed810168be1668225678743a92ccab83e38255a..ae612f5fa51e8bb8bc0592d59cc28b0f22061975 100644 (file)
@@ -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,
index c795ab18438834a1f30779db19ba753d206c534a..438120e044b0828ac5cdfaee9b4aa35dc78736c0 100644 (file)
@@ -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 {
index 78ef7882b842670577e99d0cbe9f36a739074c08..97f9491132b21d1c21346d648801345d6b37e5ad 100644 (file)
@@ -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)
     {
index 461aa9d0e6136d27fc1ebe73578c02f00874a57a..9498353b045fa9c089e29f27d6b60d384f927147 100644 (file)
@@ -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 ();