Merged import_own_key
authorEdouard Tisserant
Mon, 20 Jun 2016 13:10:01 +0200
changeset 746753b1ec63285
parent 745 32d7952cccfa
parent 741 548a07ff87b9
child 747 d357dceebec6
child 748 967b0bae4f01
Merged import_own_key
src/message_api.c
test/message_api_test.cc
     1.1 --- a/src/cryptotech.h	Sun Jun 19 15:25:25 2016 +0200
     1.2 +++ b/src/cryptotech.h	Mon Jun 20 13:10:01 2016 +0200
     1.3 @@ -48,7 +48,7 @@
     1.4      );
     1.5  
     1.6  typedef PEP_STATUS (*import_key_t)(PEP_SESSION session, const char *key_data,
     1.7 -        size_t size);
     1.8 +        size_t size, identity_list **private_keys);
     1.9  
    1.10  typedef PEP_STATUS (*recv_key_t)(PEP_SESSION session, const char *pattern);
    1.11  
     2.1 --- a/src/identity_list.h	Sun Jun 19 15:25:25 2016 +0200
     2.2 +++ b/src/identity_list.h	Mon Jun 20 13:10:01 2016 +0200
     2.3 @@ -7,12 +7,6 @@
     2.4  #endif
     2.5  
     2.6  
     2.7 -typedef struct _identity_list {
     2.8 -    pEp_identity *ident;
     2.9 -    struct _identity_list *next;
    2.10 -} identity_list;
    2.11 -
    2.12 -
    2.13  // new_identity_list() - allocate a new identity list
    2.14  //
    2.15  //  parameters:
     3.1 --- a/src/message_api.c	Sun Jun 19 15:25:25 2016 +0200
     3.2 +++ b/src/message_api.c	Mon Jun 20 13:10:01 2016 +0200
     3.3 @@ -842,32 +842,21 @@
     3.4  
     3.5  static bool is_key(const bloblist_t *bl)
     3.6  {
     3.7 -    bool result = false;
     3.8 -
     3.9 -    // workaround for Apple Mail bugs
    3.10 -    if (is_mime_type(bl, "application/x-apple-msg-attachment")) {
    3.11 -        if (is_fileending(bl, ".asc")) {
    3.12 -            result = true;
    3.13 -        }
    3.14 -    }
    3.15 -    else if (bl->mime_type == NULL ||
    3.16 -                is_mime_type(bl, "application/octet-stream")) {
    3.17 -        if (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
    3.18 -                is_fileending(bl, ".key") || is_fileending(bl, ".asc")) {
    3.19 -            result = true;
    3.20 -        }
    3.21 -    }
    3.22 -    else if (is_mime_type(bl, "application/pgp-keys")) {
    3.23 -        result = true;
    3.24 -    }
    3.25 -    else if (is_mime_type(bl, "text/plain")) {
    3.26 -        if (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
    3.27 -                is_fileending(bl, ".key") || is_fileending(bl, ".asc")) {
    3.28 -            result = true;
    3.29 -        }
    3.30 -    }
    3.31 -
    3.32 -    return result;
    3.33 +    return (// workaround for Apple Mail bugs
    3.34 +            (is_mime_type(bl, "application/x-apple-msg-attachment") &&
    3.35 +             is_fileending(bl, ".asc")) ||
    3.36 +            // as binary, by file name
    3.37 +            ((bl->mime_type == NULL ||
    3.38 +              is_mime_type(bl, "application/octet-stream")) &&
    3.39 +             (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
    3.40 +                    is_fileending(bl, ".key") || is_fileending(bl, ".asc"))) ||
    3.41 +            // explicit mime type 
    3.42 +            is_mime_type(bl, "application/pgp-keys") ||
    3.43 +            // as text, by file name
    3.44 +            (is_mime_type(bl, "text/plain") &&
    3.45 +             (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
    3.46 +                    is_fileending(bl, ".key") || is_fileending(bl, ".asc")))
    3.47 +           );
    3.48  }
    3.49  
    3.50  static void remove_attached_keys(message *msg)
    3.51 @@ -894,7 +883,11 @@
    3.52      }
    3.53  }
    3.54  
    3.55 -bool import_attached_keys(PEP_SESSION session, message *msg)
    3.56 +bool import_attached_keys(
    3.57 +        PEP_SESSION session, 
    3.58 +        const message *msg,
    3.59 +        identity_list **private_idents
    3.60 +    )
    3.61  {
    3.62      assert(session);
    3.63      assert(msg);
    3.64 @@ -904,15 +897,13 @@
    3.65      bloblist_t *bl;
    3.66      for (bl = msg->attachments; bl && bl->value; bl = bl->next) {
    3.67          assert(bl && bl->value && bl->size);
    3.68 -        if (is_key(bl)) {
    3.69 -            import_key(session, bl->value, bl->size);
    3.70 +
    3.71 +        if (is_key(bl)) 
    3.72 +        {
    3.73 +            import_key(session, bl->value, bl->size, private_idents);
    3.74              remove = true;
    3.75          }
    3.76      }
    3.77 -
    3.78 -    if (msg->from && msg->from->user_id && msg->from->address)
    3.79 -        update_identity(session, msg->from);
    3.80 -
    3.81      return remove;
    3.82  }
    3.83  
    3.84 @@ -1184,12 +1175,14 @@
    3.85      return status;
    3.86  }
    3.87  
    3.88 -DYNAMIC_API PEP_STATUS decrypt_message(
    3.89 +DYNAMIC_API PEP_STATUS _decrypt_message(
    3.90          PEP_SESSION session,
    3.91          message *src,
    3.92          message **dst,
    3.93          stringlist_t **keylist,
    3.94 -        PEP_color *color
    3.95 +        PEP_color *color,
    3.96 +        PEP_decrypt_flags_t *flags, 
    3.97 +        identity_list **private_il
    3.98      )
    3.99  {
   3.100      PEP_STATUS status = PEP_STATUS_OK;
   3.101 @@ -1206,11 +1199,21 @@
   3.102      assert(dst);
   3.103      assert(keylist);
   3.104      assert(color);
   3.105 +    assert(flags);
   3.106  
   3.107 -    if (!(session && src && dst && keylist && color))
   3.108 +    if (!(session && src && dst && keylist && color && flags))
   3.109          return PEP_ILLEGAL_VALUE;
   3.110  
   3.111 -    bool imported_keys = import_attached_keys(session, src);
   3.112 +    *flags = 0;
   3.113 +
   3.114 +    // Private key in unencrypted mail are ignored -> NULL
   3.115 +    bool imported_keys = import_attached_keys(session, src, NULL);
   3.116 +
   3.117 +    // Update src->from in case we just imported a key
   3.118 +    // we would need to check signature
   3.119 +    if(src->from && src->from->user_id && src->from->address)
   3.120 +        update_identity(session, src->from);
   3.121 +
   3.122      PEP_cryptotech crypto = determine_encryption_format(src);
   3.123  
   3.124      *dst = NULL;
   3.125 @@ -1244,6 +1247,8 @@
   3.126  
   3.127      decrypt_status = status;
   3.128  
   3.129 +    bool imported_private_key_address = false; 
   3.130 +
   3.131      if (ptext) {
   3.132          switch (src->enc_format) {
   3.133              case PEP_enc_PGP_MIME:
   3.134 @@ -1376,14 +1381,34 @@
   3.135                  // BUG: must implement more
   3.136                  NOT_IMPLEMENTED
   3.137          }
   3.138 -        
   3.139 -        imported_keys = import_attached_keys(session, msg);
   3.140 -        
   3.141 -        if (decrypt_status == PEP_DECRYPTED) {
   3.142 +       
   3.143 +        // check for private key in decrypted message attachement while inporting
   3.144 +        identity_list *_private_il = NULL;
   3.145 +        imported_keys = import_attached_keys(session, msg, &_private_il);
   3.146 +        if (_private_il && 
   3.147 +            identity_list_length(_private_il) == 1 &&
   3.148 +            _private_il->ident->address)
   3.149 +        {
   3.150 +            imported_private_key_address = true;
   3.151 +        }
   3.152 +
   3.153 +        if(private_il && imported_private_key_address){
   3.154 +            *private_il = _private_il;
   3.155 +        }else{
   3.156 +            free_identity_list(_private_il);
   3.157 +        }
   3.158 +         
   3.159 +        if(decrypt_status == PEP_DECRYPTED){
   3.160 +
   3.161 +            // TODO optimize if import_attached_keys didn't import any key
   3.162              
   3.163              // In case message did decrypt, but no valid signature could be found
   3.164              // then retry decrypt+verify after importing key.
   3.165 -            // TODO optimize if import_attached_keys didn't import any key
   3.166 +
   3.167 +            // Update msg->from in case we just imported a key
   3.168 +            // we would need to check signature
   3.169 +            if(msg->from && msg->from->user_id && msg->from->address)
   3.170 +                 update_identity(session, msg->from);
   3.171              
   3.172              char *re_ptext = NULL;
   3.173              size_t re_psize;
   3.174 @@ -1445,6 +1470,19 @@
   3.175          goto pep_error;
   3.176      }
   3.177  
   3.178 +    // Case of own key imported from own trusted message
   3.179 +    if (// Message have been reliably decrypted 
   3.180 +        msg &&
   3.181 +        *color >= PEP_rating_green &&
   3.182 +        imported_private_key_address &&
   3.183 +        // to is [own]
   3.184 +        msg->to->ident->user_id &&
   3.185 +        strcmp(msg->to->ident->user_id, PEP_OWN_USERID) == 0 
   3.186 +        )
   3.187 +    {
   3.188 +        *flags |= PEP_decrypt_flag_own_private_key;
   3.189 +    }
   3.190 +
   3.191      if (msg) {
   3.192          decorate_message(msg, *color, _keylist);
   3.193          if (imported_keys)
   3.194 @@ -1466,6 +1504,54 @@
   3.195      return status;
   3.196  }
   3.197  
   3.198 +DYNAMIC_API PEP_STATUS decrypt_message(
   3.199 +        PEP_SESSION session,
   3.200 +        message *src,
   3.201 +        message **dst,
   3.202 +        stringlist_t **keylist,
   3.203 +        PEP_color *color,
   3.204 +        PEP_decrypt_flags_t *flags 
   3.205 +    )
   3.206 +{
   3.207 +    return _decrypt_message( session, src, dst, keylist, color, flags, NULL );
   3.208 +}
   3.209 +
   3.210 +DYNAMIC_API PEP_STATUS own_message_private_key_details(
   3.211 +        PEP_SESSION session,
   3.212 +        message *msg,
   3.213 +        pEp_identity **ident 
   3.214 +    )
   3.215 +{
   3.216 +    assert(session);
   3.217 +    assert(msg);
   3.218 +    assert(ident);
   3.219 +
   3.220 +    if (!(session && msg && ident))
   3.221 +        return PEP_ILLEGAL_VALUE;
   3.222 +
   3.223 +    message *dst; 
   3.224 +    stringlist_t *keylist;
   3.225 +    PEP_color color;
   3.226 +    PEP_decrypt_flags_t flags; 
   3.227 +
   3.228 +    *ident = NULL;
   3.229 +
   3.230 +    identity_list *private_il = NULL;
   3.231 +    PEP_STATUS status = _decrypt_message(session, msg,  &dst, &keylist, &color, &flags, &private_il);
   3.232 +
   3.233 +    if (status == PEP_STATUS_OK &&
   3.234 +        flags & PEP_decrypt_flag_own_private_key &&
   3.235 +        private_il)
   3.236 +    {
   3.237 +        *ident = identity_dup(private_il->ident);
   3.238 +    }
   3.239 +
   3.240 +    free_identity_list(private_il);
   3.241 +
   3.242 +    return status;
   3.243 +
   3.244 +}
   3.245 +
   3.246  DYNAMIC_API PEP_STATUS outgoing_message_color(
   3.247          PEP_SESSION session,
   3.248          message *msg,
     4.1 --- a/src/message_api.h	Sun Jun 19 15:25:25 2016 +0200
     4.2 +++ b/src/message_api.h	Mon Jun 20 13:10:01 2016 +0200
     4.3 @@ -10,7 +10,11 @@
     4.4  #endif
     4.5  
     4.6  
     4.7 -bool import_attached_keys(PEP_SESSION session, message *msg);
     4.8 +bool import_attached_keys(
     4.9 +        PEP_SESSION session, 
    4.10 +        const message *msg,
    4.11 +        identity_list **private_idents
    4.12 +    );
    4.13  void attach_own_key(PEP_SESSION session, message *msg);
    4.14  PEP_cryptotech determine_encryption_format(message *msg);
    4.15  
    4.16 @@ -64,6 +68,12 @@
    4.17      PEP_rating_under_attack = -3
    4.18  } PEP_color;
    4.19  
    4.20 +typedef enum _PEP_decrypt_flags {
    4.21 +    PEP_decrypt_flag_own_private_key = 0x1
    4.22 +} PEP_decrypt_flags; 
    4.23 +
    4.24 +typedef uint32_t PEP_decrypt_flags_t;
    4.25 +
    4.26  // decrypt_message() - decrypt message in memory
    4.27  //
    4.28  //  parameters:
    4.29 @@ -72,6 +82,7 @@
    4.30  //      dst (out)           pointer to new decrypted message or NULL on failure
    4.31  //      keylist (out)       stringlist with keyids
    4.32  //      color (out)         color for the message
    4.33 +//      flags (out)         flags to signal special message features
    4.34  //
    4.35  //  return value:
    4.36  //      error status or PEP_STATUS_OK on success
    4.37 @@ -88,9 +99,36 @@
    4.38          message *src,
    4.39          message **dst,
    4.40          stringlist_t **keylist,
    4.41 -        PEP_color *color
    4.42 -    );
    4.43 +        PEP_color *color,
    4.44 +        PEP_decrypt_flags_t *flags 
    4.45 +);
    4.46  
    4.47 +// own_message_private_key_details() - details on own key in own message
    4.48 +//
    4.49 +//  parameters:
    4.50 +//      session (in)        session handle
    4.51 +//      msg (in)            message to decrypt
    4.52 +//      ident (out)         identity containing uid, address and fpr of key
    4.53 +//
    4.54 +//  note:
    4.55 +//      In order to obtain details about key to be possibly imported
    4.56 +//      as a replacement of key currently used as own identity, 
    4.57 +//      application passes message that have been previously flagged by 
    4.58 +//      decrypt_message() as own message containing own key to this function
    4.59 +//
    4.60 +//  return value:
    4.61 +//      error status or PEP_STATUS_OK on success
    4.62 +//
    4.63 +//	caveat:
    4.64 +//	    the ownership of msg remains with the caller
    4.65 +//	    the ownership of ident goes to the caller
    4.66 +//	    msg MUST be encrypted so that this function can check own signature
    4.67 +
    4.68 +DYNAMIC_API PEP_STATUS own_message_private_key_details(
    4.69 +        PEP_SESSION session,
    4.70 +        message *msg,
    4.71 +        pEp_identity **ident 
    4.72 +);
    4.73  
    4.74  // outgoing_message_color() - get color for an outgoing message
    4.75  //
     5.1 --- a/src/pEpEngine.c	Sun Jun 19 15:25:25 2016 +0200
     5.2 +++ b/src/pEpEngine.c	Mon Jun 20 13:10:01 2016 +0200
     5.3 @@ -1151,7 +1151,12 @@
     5.4      return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
     5.5  }
     5.6  
     5.7 -DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
     5.8 +DYNAMIC_API PEP_STATUS import_key(
     5.9 +        PEP_SESSION session,
    5.10 +        const char *key_data,
    5.11 +        size_t size,
    5.12 +        identity_list **private_keys
    5.13 +    )
    5.14  {
    5.15      assert(session);
    5.16      assert(key_data);
    5.17 @@ -1159,7 +1164,7 @@
    5.18      if (!(session && key_data))
    5.19          return PEP_ILLEGAL_VALUE;
    5.20  
    5.21 -    return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
    5.22 +    return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size, private_keys);
    5.23  }
    5.24  
    5.25  DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
     6.1 --- a/src/pEpEngine.h	Sun Jun 19 15:25:25 2016 +0200
     6.2 +++ b/src/pEpEngine.h	Mon Jun 20 13:10:01 2016 +0200
     6.3 @@ -388,6 +388,11 @@
     6.4      bool me;                    // if this is the local user herself/himself
     6.5  } pEp_identity;
     6.6  
     6.7 +typedef struct _identity_list {
     6.8 +    pEp_identity *ident;
     6.9 +    struct _identity_list *next;
    6.10 +} identity_list;
    6.11 +
    6.12  
    6.13  // new_identity() - allocate memory and set the string and size fields
    6.14  //
    6.15 @@ -550,7 +555,12 @@
    6.16  //      PEP_OUT_OF_MEMORY       out of memory
    6.17  //      PEP_ILLEGAL_VALUE       there is no key data to import
    6.18  
    6.19 -DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size);
    6.20 +DYNAMIC_API PEP_STATUS import_key(
    6.21 +        PEP_SESSION session,
    6.22 +        const char *key_data,
    6.23 +        size_t size,
    6.24 +        identity_list **private_keys
    6.25 +    );
    6.26  
    6.27  
    6.28  // export_key() - export ascii armored key
     7.1 --- a/src/pgp_gpg.c	Sun Jun 19 15:25:25 2016 +0200
     7.2 +++ b/src/pgp_gpg.c	Mon Jun 20 13:10:01 2016 +0200
     7.3 @@ -257,6 +257,11 @@
     7.4              dlsym(gpgme, "gpgme_op_import");
     7.5          assert(gpg.gpgme_op_import);
     7.6  
     7.7 +        gpg.gpgme_op_import_result
     7.8 +            = (gpgme_op_import_result_t) (intptr_t) dlsym(gpgme,
     7.9 +            "gpgme_op_import_result");
    7.10 +        assert(gpg.gpgme_op_import_result);
    7.11 +
    7.12          gpg.gpgme_op_export = (gpgme_op_export_t) (intptr_t)
    7.13              dlsym(gpgme, "gpgme_op_export");
    7.14          assert(gpg.gpgme_op_export);
    7.15 @@ -456,8 +461,7 @@
    7.16                              // This is meant to get signer's primary 
    7.17                              // key fingerprint, using subkey's.
    7.18  
    7.19 -                            gpgme_key_t key;
    7.20 -                            memset(&key,0,sizeof(key));
    7.21 +                            gpgme_key_t key = NULL;
    7.22  
    7.23                              gpgme_error = gpg.gpgme_get_key(session->ctx,
    7.24                                  gpgme_signature->fpr, &key, 0);
    7.25 @@ -1013,13 +1017,17 @@
    7.26      return PEP_STATUS_OK;
    7.27  }
    7.28  
    7.29 -PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
    7.30 +PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
    7.31 +                              size_t size, identity_list **private_idents)
    7.32  {
    7.33      gpgme_error_t gpgme_error;
    7.34      gpgme_data_t dh;
    7.35  
    7.36      assert(session);
    7.37      assert(key_data);
    7.38 +   
    7.39 +    if(private_idents) 
    7.40 +        *private_idents = NULL;
    7.41  
    7.42      gpgme_error = gpg.gpgme_data_new_from_mem(&dh, key_data, size, 0);
    7.43      gpgme_error = _GPGERR(gpgme_error);
    7.44 @@ -1037,10 +1045,67 @@
    7.45          return PEP_UNKNOWN_ERROR;
    7.46      }
    7.47  
    7.48 +    gpgme_import_result_t gpgme_import_result;
    7.49 +
    7.50      gpgme_error = gpg.gpgme_op_import(session->ctx, dh);
    7.51      gpgme_error = _GPGERR(gpgme_error);
    7.52      switch (gpgme_error) {
    7.53      case GPG_ERR_NO_ERROR:
    7.54 +        if(private_idents) 
    7.55 +        {
    7.56 +            gpgme_import_result =
    7.57 +                gpg.gpgme_op_import_result(session->ctx);
    7.58 +            assert(gpgme_import_result);
    7.59 +            gpgme_import_status_t import;
    7.60 +            for (import = gpgme_import_result->imports; 
    7.61 +                 import; 
    7.62 +                 import = import->next)
    7.63 +             {
    7.64 +                if (import &&
    7.65 +                    import->result == GPG_ERR_NO_ERROR &&
    7.66 +                    import->status & GPGME_IMPORT_SECRET )
    7.67 +                {
    7.68 +                    gpgme_key_t key = NULL;
    7.69 +
    7.70 +                    gpgme_error = gpg.gpgme_get_key(session->ctx,
    7.71 +                        import->fpr, &key, 0);
    7.72 +                    gpgme_error = _GPGERR(gpgme_error);
    7.73 +                    assert(gpgme_error != GPG_ERR_ENOMEM);
    7.74 +                    if (gpgme_error == GPG_ERR_ENOMEM) {
    7.75 +                        gpg.gpgme_data_release(dh);
    7.76 +                        return PEP_OUT_OF_MEMORY;
    7.77 +                    }
    7.78 +                    
    7.79 +                    if (gpgme_error == GPG_ERR_NO_ERROR &&  
    7.80 +                        key && key->uids && 
    7.81 +                        key->uids->email && key->uids->name)
    7.82 +                    {
    7.83 +                        pEp_identity *ident = new_identity(
    7.84 +                             key->uids->email, import->fpr, NULL, key->uids->name);
    7.85 +
    7.86 +                        gpg.gpgme_key_unref(key);
    7.87 +
    7.88 +                        if (ident == NULL) {
    7.89 +                            gpg.gpgme_data_release(dh);
    7.90 +                            return PEP_OUT_OF_MEMORY;
    7.91 +                        }
    7.92 +
    7.93 +                        *private_idents = identity_list_add(*private_idents, ident);
    7.94 +
    7.95 +                        if (*private_idents == NULL) {
    7.96 +                            gpg.gpgme_data_release(dh);
    7.97 +                            return PEP_OUT_OF_MEMORY;
    7.98 +                        }
    7.99 +                    }
   7.100 +                    else 
   7.101 +                    {
   7.102 +                        gpg.gpgme_key_unref(key);
   7.103 +                        gpg.gpgme_data_release(dh);
   7.104 +                        return PEP_UNKNOWN_ERROR;
   7.105 +                    }
   7.106 +                }
   7.107 +            }
   7.108 +        }
   7.109          break;
   7.110      case GPG_ERR_INV_VALUE:
   7.111          assert(0);
     8.1 --- a/src/pgp_gpg.h	Sun Jun 19 15:25:25 2016 +0200
     8.2 +++ b/src/pgp_gpg.h	Mon Jun 20 13:10:01 2016 +0200
     8.3 @@ -41,7 +41,10 @@
     8.4      );
     8.5  
     8.6  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
     8.7 -        size_t size);
     8.8 +                              size_t size, identity_list **private_idents);
     8.9 +
    8.10 +PEP_STATUS pgp_import_private_keydata(PEP_SESSION session, const char *key_data,
    8.11 +                                      size_t size, identity_list **private_idents);
    8.12  
    8.13  PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern);
    8.14  PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern);
     9.1 --- a/src/pgp_gpg_internal.h	Sun Jun 19 15:25:25 2016 +0200
     9.2 +++ b/src/pgp_gpg_internal.h	Mon Jun 20 13:10:01 2016 +0200
     9.3 @@ -55,6 +55,7 @@
     9.4      const gpgme_key_t KEY, int ALLOW_SECRET);
     9.5  typedef gpgme_error_t(*gpgme_op_import_t)(gpgme_ctx_t CTX,
     9.6      gpgme_data_t KEYDATA);
     9.7 +typedef gpgme_import_result_t(*gpgme_op_import_result_t)(gpgme_ctx_t CTX);
     9.8  typedef gpgme_error_t(*gpgme_op_export_t)(gpgme_ctx_t CTX,
     9.9      const char *PATTERN, gpgme_export_mode_t MODE, gpgme_data_t KEYDATA);
    9.10  typedef gpgme_error_t(*gpgme_set_keylist_mode_t)(gpgme_ctx_t CTX,
    9.11 @@ -106,6 +107,7 @@
    9.12      gpgme_op_genkey_result_t gpgme_op_genkey_result;
    9.13      gpgme_op_delete_t gpgme_op_delete;
    9.14      gpgme_op_import_t gpgme_op_import;
    9.15 +    gpgme_op_import_result_t gpgme_op_import_result;
    9.16      gpgme_op_export_t gpgme_op_export;
    9.17      gpgme_set_keylist_mode_t gpgme_set_keylist_mode;
    9.18      gpgme_get_keylist_mode_t gpgme_get_keylist_mode;
    10.1 --- a/test/message_api_test.cc	Sun Jun 19 15:25:25 2016 +0200
    10.2 +++ b/test/message_api_test.cc	Mon Jun 20 13:10:01 2016 +0200
    10.3 @@ -74,7 +74,9 @@
    10.4      message *msg4;
    10.5      stringlist_t *keylist4;
    10.6      PEP_color color;
    10.7 -    PEP_STATUS status4 = decrypt_message(session, enc_msg2, &msg4, &keylist4, &color);
    10.8 +    PEP_decrypt_flags_t flags;
    10.9 +    
   10.10 +    PEP_STATUS status4 = decrypt_message(session, enc_msg2, &msg4, &keylist4, &color, &flags);
   10.11      assert(status4 == PEP_STATUS_OK);
   10.12      assert(msg4);
   10.13      assert(keylist4);
   10.14 @@ -109,7 +111,8 @@
   10.15      message *msg6;
   10.16      stringlist_t *keylist5;
   10.17      PEP_color color2;
   10.18 -    PEP_STATUS status6 = decrypt_message(session, msg5, &msg6, &keylist5, &color2);
   10.19 +    PEP_decrypt_flags_t flags2;
   10.20 +    PEP_STATUS status6 = decrypt_message(session, msg5, &msg6, &keylist5, &color2, &flags2);
   10.21      assert(status6 == PEP_DECRYPT_NO_KEY);
   10.22      assert(msg6 == NULL);
   10.23      assert(keylist5 == NULL);
    11.1 --- a/test/pEpEngineTest.cc	Sun Jun 19 15:25:25 2016 +0200
    11.2 +++ b/test/pEpEngineTest.cc	Mon Jun 20 13:10:01 2016 +0200
    11.3 @@ -88,7 +88,7 @@
    11.4          size_t k_user_length = 0;
    11.5          ReadFileIntoMem(*kf, k_user_buffer, k_user_length);
    11.6          cout << "import_key(" << *kf << ")\n";
    11.7 -        PEP_STATUS import_status = import_key(session, k_user_buffer, k_user_length);
    11.8 +        PEP_STATUS import_status = import_key(session, k_user_buffer, k_user_length, NULL);
    11.9          assert(import_status == PEP_STATUS_OK);
   11.10          cout << "successfully imported key\n";
   11.11          delete[] k_user_buffer;
   11.12 @@ -244,7 +244,7 @@
   11.13      assert(delete_status == PEP_STATUS_OK);
   11.14      
   11.15      cout << "import_key()\n";
   11.16 -    PEP_STATUS import_status = import_key(session, key_data, size);
   11.17 +    PEP_STATUS import_status = import_key(session, key_data, size, NULL);
   11.18      assert(import_status == PEP_STATUS_OK);
   11.19      cout << "successfully imported key\n";
   11.20