import_key surgery at least doesn't BREAK anything now. Needs to be tested on its explicitly added functionality, however. ENGINE-630
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Tue, 10 Sep 2019 15:04:36 +0200
branchENGINE-630
changeset 40657f0cf93bc2af
parent 4050 6608abc1ce8c
child 4071 68f242584e18
child 4072 5d367773c44f
import_key surgery at least doesn't BREAK anything now. Needs to be tested on its explicitly added functionality, however.
src/cryptotech.c
src/cryptotech.h
src/pEpEngine.c
src/pEpEngine.h
src/pEp_internal.h
src/pgp_gpg.c
src/pgp_gpg.h
src/pgp_sequoia.c
src/pgp_sequoia.h
     1.1 --- a/src/cryptotech.c	Wed Sep 04 18:53:09 2019 +0200
     1.2 +++ b/src/cryptotech.c	Tue Sep 10 15:04:36 2019 +0200
     1.3 @@ -48,7 +48,7 @@
     1.4          cryptotech[PEP_crypt_OpenPGP].find_keys = pgp_find_keys;
     1.5          cryptotech[PEP_crypt_OpenPGP].generate_keypair = pgp_generate_keypair;
     1.6          cryptotech[PEP_crypt_OpenPGP].get_key_rating = pgp_get_key_rating;
     1.7 -        cryptotech[PEP_crypt_OpenPGP].import_key = pgp_import_keydata;
     1.8 +        cryptotech[PEP_crypt_OpenPGP]._import_key_with_fpr_return = pgp_import_keydata;
     1.9          cryptotech[PEP_crypt_OpenPGP].recv_key = pgp_recv_key;
    1.10          cryptotech[PEP_crypt_OpenPGP].send_key = pgp_send_key;
    1.11          cryptotech[PEP_crypt_OpenPGP].renew_key = pgp_renew_key;
     2.1 --- a/src/cryptotech.h	Wed Sep 04 18:53:09 2019 +0200
     2.2 +++ b/src/cryptotech.h	Tue Sep 10 15:04:36 2019 +0200
     2.3 @@ -64,8 +64,8 @@
     2.4          PEP_comm_type *comm_type
     2.5      );
     2.6  
     2.7 -typedef PEP_STATUS (*import_key_t)(PEP_SESSION session, const char *key_data,
     2.8 -        size_t size, identity_list **private_keys);
     2.9 +typedef PEP_STATUS (*import_key_with_fpr_return_t)(PEP_SESSION session, const char *key_data,
    2.10 +        size_t size, identity_list **private_idents, stringlist_t** imported_keys);
    2.11  
    2.12  typedef PEP_STATUS (*recv_key_t)(PEP_SESSION session, const char *pattern);
    2.13  
    2.14 @@ -113,7 +113,7 @@
    2.15      find_keys_t find_keys;
    2.16      generate_keypair_t generate_keypair;
    2.17      get_key_rating_t get_key_rating;
    2.18 -    import_key_t import_key;
    2.19 +    import_key_with_fpr_return_t _import_key_with_fpr_return;
    2.20      recv_key_t recv_key;
    2.21      send_key_t send_key;
    2.22      renew_key_t renew_key;
    2.23 @@ -133,4 +133,3 @@
    2.24  
    2.25  PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first);
    2.26  void release_cryptotech(PEP_SESSION session, bool out_last);
    2.27 -
     3.1 --- a/src/pEpEngine.c	Wed Sep 04 18:53:09 2019 +0200
     3.2 +++ b/src/pEpEngine.c	Tue Sep 10 15:04:36 2019 +0200
     3.3 @@ -4543,7 +4543,7 @@
     3.4          PEP_SESSION session,
     3.5          const char *key_data,
     3.6          size_t size,
     3.7 -        identity_list **private_keys
     3.8 +        identity_list **private_idents
     3.9      )
    3.10  {
    3.11      assert(session);
    3.12 @@ -4552,10 +4552,28 @@
    3.13      if (!(session && key_data))
    3.14          return PEP_ILLEGAL_VALUE;
    3.15  
    3.16 -    return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
    3.17 -            size, private_keys);
    3.18 +    return _import_key_with_fpr_return(session, key_data,
    3.19 +            size, private_idents, NULL);
    3.20  }
    3.21  
    3.22 +PEP_STATUS _import_key_with_fpr_return(
    3.23 +        PEP_SESSION session,
    3.24 +        const char *key_data,
    3.25 +        size_t size,
    3.26 +        identity_list **private_idents,
    3.27 +        stringlist_t** imported_keys
    3.28 +    )
    3.29 +{
    3.30 +    assert(session);
    3.31 +    assert(key_data);
    3.32 +
    3.33 +    if (!(session && key_data))
    3.34 +        return PEP_ILLEGAL_VALUE;
    3.35 +
    3.36 +    return session->cryptotech[PEP_crypt_OpenPGP]._import_key_with_fpr_return(session, key_data,
    3.37 +            size, private_idents, imported_keys);    
    3.38 +}    
    3.39 +
    3.40  DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
    3.41  {
    3.42      assert(session);
     4.1 --- a/src/pEpEngine.h	Wed Sep 04 18:53:09 2019 +0200
     4.2 +++ b/src/pEpEngine.h	Tue Sep 10 15:04:36 2019 +0200
     4.3 @@ -874,7 +874,7 @@
     4.4  //      session (in)            session handle
     4.5  //      key_data (in)           key data, i.e. ASCII armored OpenPGP key
     4.6  //      size (in)               amount of data to handle
     4.7 -//      private_keys (out)      list of private keys that have been imported
     4.8 +//      private_idents (out)    List of identities representing imported private keys
     4.9  //
    4.10  //  return value:
    4.11  //      PEP_STATUS_OK = 0       key was successfully imported
    4.12 @@ -889,7 +889,7 @@
    4.13          PEP_SESSION session,
    4.14          const char *key_data,
    4.15          size_t size,
    4.16 -        identity_list **private_keys
    4.17 +        identity_list **private_idents
    4.18      );
    4.19  
    4.20  
     5.1 --- a/src/pEp_internal.h	Wed Sep 04 18:53:09 2019 +0200
     5.2 +++ b/src/pEp_internal.h	Tue Sep 10 15:04:36 2019 +0200
     5.3 @@ -298,6 +298,13 @@
     5.4      bool add_version,
     5.5      bool clobber);
     5.6  
     5.7 +PEP_STATUS _import_key_with_fpr_return(
     5.8 +        PEP_SESSION session,
     5.9 +        const char *key_data,
    5.10 +        size_t size,
    5.11 +        identity_list **private_idents,
    5.12 +        stringlist_t** imported_keys);
    5.13 +
    5.14  #if defined(NDEBUG) || defined(NOLOG)
    5.15  #define DEBUG_LOG(TITLE, ENTITY, DESC)
    5.16  #else
    5.17 @@ -566,4 +573,3 @@
    5.18      } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
    5.19      return rc;
    5.20  }
    5.21 -
     6.1 --- a/src/pgp_gpg.c	Wed Sep 04 18:53:09 2019 +0200
     6.2 +++ b/src/pgp_gpg.c	Tue Sep 10 15:04:36 2019 +0200
     6.3 @@ -1481,7 +1481,8 @@
     6.4  }
     6.5  
     6.6  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
     6.7 -                              size_t size, identity_list **private_idents)
     6.8 +                              size_t size, identity_list **private_idents,
     6.9 +                              stringlist_t** imported_keys)
    6.10  {
    6.11      gpgme_error_t gpgme_error;
    6.12      gpgme_data_t dh;
    6.13 @@ -1491,6 +1492,9 @@
    6.14  
    6.15      if(private_idents)
    6.16          *private_idents = NULL;
    6.17 +        
    6.18 +    if(imported_keys)
    6.19 +        *imported_keys = NULL;
    6.20  
    6.21      gpgme_error = gpg.gpgme_data_new_from_mem(&dh, key_data, size, 0);
    6.22      gpgme_error = _GPGERR(gpgme_error);
    6.23 @@ -1524,64 +1528,80 @@
    6.24              gpg.gpgme_data_release(dh);
    6.25              return PEP_UNKNOWN_ERROR;
    6.26          }
    6.27 -        // considered seems to only be true if it was 
    6.28 -        // actually a key
    6.29 -        if (gpgme_import_result->considered > 0)
    6.30 -            // gpgme_import_result->imported > 0 ||
    6.31 -            // gpgme_import_result->secret_imported > 0 ||
    6.32 -            // gpgme_import_result->unchanged > 0 ||
    6.33 -            // gpgme_import_result->secret_unchanged > 0)
    6.34 -            key_imported = true;
    6.35 +
    6.36 +        /* N.B. If this breaks, maybe we need to use considered again also? Documentation is 
    6.37 +           totally freaking unclear if the struct did not in fact actually get 
    6.38 +           broken without however it changed in 2.2.17. */
    6.39 +        key_imported = gpgme_import_result->imported |
    6.40 +                       gpgme_import_result->secret_imported |
    6.41 +                       gpgme_import_result->unchanged |
    6.42 +                       gpgme_import_result->secret_unchanged |
    6.43 +                       gpgme_import_result->secret_imported |
    6.44 +                       gpgme_import_result->secret_read |
    6.45 +                       gpgme_import_result->new_user_ids |
    6.46 +                       gpgme_import_result->new_sub_keys |
    6.47 +                       gpgme_import_result->new_revocations |
    6.48 +                       gpgme_import_result->new_signatures;
    6.49              
    6.50 -        if(private_idents)
    6.51 +        if(private_idents || imported_keys)
    6.52          {
    6.53              gpgme_import_status_t import;
    6.54 +            identity_list** identcurr_pp = private_idents;
    6.55 +            stringlist_t** keylist_pp = imported_keys;
    6.56              for (import = gpgme_import_result->imports;
    6.57                   import;
    6.58                   import = import->next)
    6.59               {
    6.60                  if (import &&
    6.61 -                    import->result == GPG_ERR_NO_ERROR &&
    6.62 -                    import->status & GPGME_IMPORT_SECRET )
    6.63 -                {
    6.64 -                    gpgme_key_t key = NULL;
    6.65 -
    6.66 -                    gpgme_error = gpg.gpgme_get_key(session->ctx,
    6.67 -                        import->fpr, &key, 0);
    6.68 -                    gpgme_error = _GPGERR(gpgme_error);
    6.69 -                    assert(gpgme_error != GPG_ERR_ENOMEM);
    6.70 -                    if (gpgme_error == GPG_ERR_ENOMEM) {
    6.71 -                        gpg.gpgme_data_release(dh);
    6.72 -                        return PEP_OUT_OF_MEMORY;
    6.73 -                    }
    6.74 -
    6.75 -                    if (gpgme_error == GPG_ERR_NO_ERROR &&
    6.76 -                        key && key->uids &&
    6.77 -                        key->uids->email && key->uids->name)
    6.78 -                    {
    6.79 -                        pEp_identity *ident = new_identity(
    6.80 -                             key->uids->email, import->fpr, NULL, key->uids->name);
    6.81 -
    6.82 -                        gpg.gpgme_key_unref(key);
    6.83 -
    6.84 -                        if (ident == NULL) {
    6.85 +                    import->result == GPG_ERR_NO_ERROR) {
    6.86 +                        
    6.87 +                    if (keylist_pp) {
    6.88 +                        if ((*keylist_pp = new_stringlist(import->fpr)) == NULL) {
    6.89                              gpg.gpgme_data_release(dh);
    6.90                              return PEP_OUT_OF_MEMORY;
    6.91                          }
    6.92 -
    6.93 -                        *private_idents = identity_list_add(*private_idents, ident);
    6.94 -
    6.95 -                        if (*private_idents == NULL) {
    6.96 +                        keylist_pp = &((*keylist_pp)->next);    
    6.97 +                    }
    6.98 +
    6.99 +                    // This might not work - if they key was already known, this might be 0!
   6.100 +                    // We don't differentiate between known keys and new keys, so we will have 
   6.101 +                    // to do something else here.
   6.102 +
   6.103 +                    if (identcurr_pp && import->status & GPGME_IMPORT_SECRET) {
   6.104 +                        gpgme_key_t key = NULL;
   6.105 +
   6.106 +                        gpgme_error = gpg.gpgme_get_key(session->ctx,
   6.107 +                            import->fpr, &key, 0);
   6.108 +                        gpgme_error = _GPGERR(gpgme_error);
   6.109 +                        assert(gpgme_error != GPG_ERR_ENOMEM);
   6.110 +                        if (gpgme_error == GPG_ERR_ENOMEM) {
   6.111                              gpg.gpgme_data_release(dh);
   6.112                              return PEP_OUT_OF_MEMORY;
   6.113                          }
   6.114 -                    }
   6.115 -                    else
   6.116 -                    {
   6.117 -                        gpg.gpgme_key_unref(key);
   6.118 -                        gpg.gpgme_data_release(dh);
   6.119 -                        return PEP_UNKNOWN_ERROR;
   6.120 -                    }
   6.121 +
   6.122 +                        if (gpgme_error == GPG_ERR_NO_ERROR &&
   6.123 +                            key && key->uids &&
   6.124 +                            key->uids->email && key->uids->name)
   6.125 +                        {
   6.126 +                            pEp_identity *ident = new_identity(
   6.127 +                                 key->uids->email, import->fpr, NULL, key->uids->name);
   6.128 +
   6.129 +                            gpg.gpgme_key_unref(key);
   6.130 +
   6.131 +                            if (ident == NULL ||
   6.132 +                                (*identcurr_pp = new_identity_list(ident)) == NULL) {
   6.133 +                                gpg.gpgme_data_release(dh);
   6.134 +                                return PEP_OUT_OF_MEMORY;
   6.135 +                            }
   6.136 +                            identcurr_pp = &((*identcurr_pp)->next);
   6.137 +                        }
   6.138 +                        else
   6.139 +                        {
   6.140 +                            gpg.gpgme_key_unref(key);
   6.141 +                            gpg.gpgme_data_release(dh);
   6.142 +                            return PEP_UNKNOWN_ERROR;
   6.143 +                        }
   6.144 +                    }    
   6.145                  }
   6.146              }
   6.147          }
   6.148 @@ -3129,4 +3149,3 @@
   6.149              return PEP_CANNOT_CONFIG;
   6.150      }
   6.151  }
   6.152 -
     7.1 --- a/src/pgp_gpg.h	Wed Sep 04 18:53:09 2019 +0200
     7.2 +++ b/src/pgp_gpg.h	Tue Sep 10 15:04:36 2019 +0200
     7.3 @@ -227,7 +227,8 @@
     7.4          PEP_SESSION session,
     7.5          const char *key_data,
     7.6          size_t size,
     7.7 -        identity_list **private_idents
     7.8 +        identity_list **private_idents,
     7.9 +        stringlist_t** imported_keys
    7.10      );
    7.11  
    7.12  PEP_STATUS pgp_import_private_keydata(
     8.1 --- a/src/pgp_sequoia.c	Wed Sep 04 18:53:09 2019 +0200
     8.2 +++ b/src/pgp_sequoia.c	Tue Sep 10 15:04:36 2019 +0200
     8.3 @@ -701,10 +701,14 @@
     8.4  // Saves the specified TPK.
     8.5  //
     8.6  // This function takes ownership of TPK.
     8.7 -static PEP_STATUS tpk_save(PEP_SESSION, pgp_tpk_t, identity_list **)
     8.8 +// Also, since this apparently only saves one primary key (since it only generates one identity in the private key case),
     8.9 +// it will also only RETURN one. So the private_ident and imported_key return values are 
    8.10 +// singular, and we expect a valid ** which points to the address of an empty list element IF 
    8.11 +// that value should be filled.
    8.12 +static PEP_STATUS tpk_save(PEP_SESSION, pgp_tpk_t, identity_list **, stringlist_t **)
    8.13      __attribute__((nonnull(1, 2)));
    8.14  static PEP_STATUS tpk_save(PEP_SESSION session, pgp_tpk_t tpk,
    8.15 -                           identity_list **private_idents)
    8.16 +                           identity_list **private_ident, stringlist_t **imported_key)
    8.17  {
    8.18      PEP_STATUS status = PEP_STATUS_OK;
    8.19      pgp_error_t err = NULL;
    8.20 @@ -717,6 +721,12 @@
    8.21      pgp_user_id_binding_iter_t user_id_iter = NULL;
    8.22      char *email = NULL;
    8.23      char *name = NULL;
    8.24 +    
    8.25 +    if (private_ident)
    8.26 +        *private_ident = NULL;
    8.27 +        
    8.28 +    if (imported_key)
    8.29 +        *imported_key = NULL;
    8.30  
    8.31      sqlite3_stmt *stmt = session->sq_sql.begin_transaction;
    8.32      int sqlite_result = Sqlite3_step(stmt);
    8.33 @@ -728,7 +738,8 @@
    8.34  
    8.35      pgp_fpr = pgp_tpk_fingerprint(tpk);
    8.36      fpr = pgp_fingerprint_to_hex(pgp_fpr);
    8.37 -    T("(%s, private_idents: %s)", fpr, private_idents ? "yes" : "no");
    8.38 +    
    8.39 +    T("(%s, private_ident: %s)", fpr, private_ident ? "yes" : "no");
    8.40  
    8.41      // Merge any existing data into TPK.
    8.42      pgp_tpk_t current = NULL;
    8.43 @@ -743,6 +754,12 @@
    8.44              ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Merging TPKs");
    8.45      }
    8.46  
    8.47 +    // Save the import info for return.
    8.48 +    if (imported_key) {
    8.49 +        if ((*imported_key = new_stringlist(fpr)) == NULL)
    8.50 +            ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "new_stringlist");
    8.51 +    }        
    8.52 +
    8.53      int is_tsk = pgp_tpk_is_tsk(tpk);
    8.54  
    8.55      // Serialize it.
    8.56 @@ -839,20 +856,17 @@
    8.57                            "Updating userids: %s", sqlite3_errmsg(session->key_db));
    8.58              }
    8.59          }
    8.60 -
    8.61 -        if (first && private_idents && is_tsk) {
    8.62 +        
    8.63 +        if (private_ident && is_tsk && first) {
    8.64              first = 0;
    8.65 -
    8.66              // Create an identity for the primary user id.
    8.67              pEp_identity *ident = new_identity(email, fpr, NULL, name);
    8.68              if (ident == NULL)
    8.69                  ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "new_identity");
    8.70  
    8.71 -            *private_idents = identity_list_add(*private_idents, ident);
    8.72 -            if (*private_idents == NULL)
    8.73 -                ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "identity_list_add");
    8.74 -        }
    8.75 -
    8.76 +            if ((*private_ident = new_identity_list(ident)) == NULL) 
    8.77 +                ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "new_identity_list");
    8.78 +        }        
    8.79      }
    8.80      pgp_user_id_binding_iter_free(user_id_iter);
    8.81      user_id_iter = NULL;
    8.82 @@ -1849,7 +1863,7 @@
    8.83      pgp_fpr = pgp_tpk_fingerprint(tpk);
    8.84      fpr = pgp_fingerprint_to_hex(pgp_fpr);
    8.85  
    8.86 -    status = tpk_save(session, tpk, NULL);
    8.87 +    status = tpk_save(session, tpk, NULL, NULL);
    8.88      tpk = NULL;
    8.89      if (status != 0)
    8.90          ERROR_OUT(NULL, PEP_CANNOT_CREATE_KEY, "saving TSK");
    8.91 @@ -1922,15 +1936,22 @@
    8.92      return retval;
    8.93   }
    8.94  
    8.95 +// FIXME: arg names, because of below
    8.96 +// N.B. This is a misnomer - this only imports one key at a time, regardless 
    8.97 +// of what sequoia supports, for reasons (getting fprs back, multiple statuses, etc)
    8.98  PEP_STATUS _pgp_import_keydata(PEP_SESSION session, const char *key_data,
    8.99 -                              size_t size, identity_list **private_idents)
   8.100 +                              size_t size, identity_list **private_ident,
   8.101 +                              stringlist_t ** imported_key)
   8.102  {
   8.103      PEP_STATUS status = PEP_NO_KEY_IMPORTED;
   8.104      pgp_error_t err;
   8.105      pgp_tpk_parser_t parser = NULL;
   8.106 -
   8.107 -    if (private_idents)
   8.108 -        *private_idents = NULL;
   8.109 +    
   8.110 +    if (imported_key)
   8.111 +        *imported_key = NULL;
   8.112 +
   8.113 +    if (private_ident)
   8.114 +        *private_ident = NULL;
   8.115  
   8.116      T("parsing %zd bytes", size);
   8.117  
   8.118 @@ -1998,7 +2019,7 @@
   8.119              if (! tpk)
   8.120                  ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Merging signature");
   8.121  
   8.122 -            status = tpk_save(session, tpk, NULL);
   8.123 +            status = tpk_save(session, tpk, NULL, NULL);
   8.124              if (status)
   8.125                  ERROR_OUT(NULL, status, "saving merged TPK");
   8.126              status = PEP_KEY_IMPORTED;
   8.127 @@ -2020,7 +2041,7 @@
   8.128  
   8.129              // If private_idents is not NULL and there is any private key
   8.130              // material, it will be saved.
   8.131 -            status = tpk_save(session, tpk, private_idents);
   8.132 +            status = tpk_save(session, tpk, private_ident, imported_key);
   8.133              if (status == PEP_STATUS_OK)
   8.134                  status = PEP_KEY_IMPORTED;
   8.135              else
   8.136 @@ -2054,12 +2075,16 @@
   8.137      return status;
   8.138  }
   8.139  
   8.140 +// private_idents has to point to a valid identity_list* (which can point to NULL) for private idents to be filled in.
   8.141 +// imported_keys has to do the same, but with a stringlist_t*.
   8.142 +// Because the outer function breaks things up to calculate status correctly, the internal function only ever sends back
   8.143 +// one identity and one fpr, so we can do this by double pointer advancement.
   8.144  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
   8.145 -                              size_t size, identity_list **private_idents)
   8.146 +                              size_t size, identity_list **private_idents, stringlist_t** imported_keys)
   8.147  {
   8.148      unsigned int keycount = count_keydata_parts(key_data, size);
   8.149      if (keycount < 2)
   8.150 -        return(_pgp_import_keydata(session, key_data, size, private_idents));
   8.151 +        return(_pgp_import_keydata(session, key_data, size, private_idents, imported_keys));
   8.152  
   8.153      const char* pgp_begin = "-----BEGIN PGP";
   8.154      size_t prefix_len = strlen(pgp_begin);
   8.155 @@ -2068,10 +2093,12 @@
   8.156      const char* curr_begin;
   8.157      size_t curr_size;
   8.158      
   8.159 -    identity_list* collected_idents = NULL;        
   8.160 +    stringlist_t** keylist_curr = imported_keys;
   8.161 +    identity_list** identlist_curr = private_idents;      
   8.162      
   8.163      PEP_STATUS retval = PEP_KEY_IMPORTED;
   8.164      
   8.165 +    // We STILL only import individual keys. So...    
   8.166      for (i = 0, curr_begin = key_data; i < keycount; i++) {
   8.167          const char* next_begin = NULL;
   8.168  
   8.169 @@ -2086,15 +2113,14 @@
   8.170          else
   8.171              curr_size = (key_data + size) - curr_begin;
   8.172          
   8.173 -        PEP_STATUS curr_status = _pgp_import_keydata(session, curr_begin, curr_size, private_idents);
   8.174 -        if (private_idents && *private_idents) {
   8.175 -            if (!collected_idents)
   8.176 -                collected_idents = *private_idents;
   8.177 -            else 
   8.178 -                identity_list_join(collected_idents, *private_idents);
   8.179 -            *private_idents = NULL;    
   8.180 -        }
   8.181 +        PEP_STATUS curr_status = _pgp_import_keydata(session, curr_begin, curr_size, identlist_curr, keylist_curr);
   8.182          
   8.183 +        // If we added an element to the list, advance head->next ptr
   8.184 +        if (identlist_curr && *identlist_curr && (*identlist_curr)->ident)
   8.185 +            identlist_curr = &((*identlist_curr)->next);
   8.186 +        if (keylist_curr && *keylist_curr && (*keylist_curr)->value)
   8.187 +            keylist_curr = &((*keylist_curr)->next);
   8.188 +            
   8.189          if (curr_status != retval) {
   8.190              switch (curr_status) {
   8.191                  case PEP_NO_KEY_IMPORTED:
   8.192 @@ -2119,10 +2145,7 @@
   8.193          }        
   8.194          curr_begin = next_begin;     
   8.195      }
   8.196 -    
   8.197 -    if (private_idents)
   8.198 -        *private_idents = collected_idents;
   8.199 -    
   8.200 +                
   8.201      return retval;    
   8.202  }
   8.203  
   8.204 @@ -2463,7 +2486,7 @@
   8.205      if (! tpk)
   8.206          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
   8.207  
   8.208 -    status = tpk_save(session, tpk, NULL);
   8.209 +    status = tpk_save(session, tpk, NULL, NULL);
   8.210      tpk = NULL;
   8.211      ERROR_OUT(NULL, status, "Saving %s", fpr);
   8.212  
   8.213 @@ -2520,7 +2543,7 @@
   8.214      assert(pgp_revocation_status_variant(pgp_tpk_revocation_status(tpk))
   8.215             == PGP_REVOCATION_STATUS_REVOKED);
   8.216  
   8.217 -    status = tpk_save(session, tpk, NULL);
   8.218 +    status = tpk_save(session, tpk, NULL, NULL);
   8.219      tpk = NULL;
   8.220      ERROR_OUT(NULL, status, "Saving %s", fpr);
   8.221  
     9.1 --- a/src/pgp_sequoia.h	Wed Sep 04 18:53:09 2019 +0200
     9.2 +++ b/src/pgp_sequoia.h	Tue Sep 10 15:04:36 2019 +0200
     9.3 @@ -62,7 +62,8 @@
     9.4      );
     9.5  
     9.6  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
     9.7 -                              size_t size, identity_list **private_idents);
     9.8 +                              size_t size, identity_list **private_idents,
     9.9 +                              stringlist_t** imported_keys);
    9.10  
    9.11  PEP_STATUS pgp_import_private_keydata(PEP_SESSION session, const char *key_data,
    9.12                                        size_t size, identity_list **private_idents);