...
authorvb
Mon, 01 Sep 2014 17:44:19 +0200
changeset 2450887c6ab78f
parent 23 dba569e54163
child 25 5af1602f5c66
...
pEpEngine.vcxproj
pEpEngine.vcxproj.filters
src/cryptotech.c
src/cryptotech.h
src/gpgme.exp
src/gpgme.lib
src/keymanagement.c
src/pEpEngine.c
src/pEp_internal.h
src/pgp_gpg.c
src/pgp_gpg.h
src/pgp_gpg_internal.h
src/platform_windows.h
     1.1 --- a/pEpEngine.vcxproj	Mon Sep 01 13:02:23 2014 +0200
     1.2 +++ b/pEpEngine.vcxproj	Mon Sep 01 17:44:19 2014 +0200
     1.3 @@ -84,6 +84,7 @@
     1.4      <ClCompile Include="src\cryptotech.c" />
     1.5      <ClCompile Include="src\keymanagement.c" />
     1.6      <ClCompile Include="src\pEpEngine.c" />
     1.7 +    <ClCompile Include="src\pgp_gpg.c" />
     1.8      <ClCompile Include="src\platform_windows.cpp" />
     1.9      <ClCompile Include="src\sqlite3.c" />
    1.10      <ClCompile Include="src\transport.c" />
    1.11 @@ -92,6 +93,9 @@
    1.12      <ClInclude Include="src\cryptotech.h" />
    1.13      <ClInclude Include="src\keymanagement.h" />
    1.14      <ClInclude Include="src\pEpEngine.h" />
    1.15 +    <ClInclude Include="src\pEp_internal.h" />
    1.16 +    <ClInclude Include="src\pgp_gpg.h" />
    1.17 +    <ClInclude Include="src\pgp_gpg_internal.h" />
    1.18      <ClInclude Include="src\platform_windows.h" />
    1.19      <ClInclude Include="src\sqlite3.h" />
    1.20      <ClInclude Include="src\transport.h" />
     2.1 --- a/pEpEngine.vcxproj.filters	Mon Sep 01 13:02:23 2014 +0200
     2.2 +++ b/pEpEngine.vcxproj.filters	Mon Sep 01 17:44:19 2014 +0200
     2.3 @@ -33,6 +33,9 @@
     2.4      <ClCompile Include="src\cryptotech.c">
     2.5        <Filter>Quelldateien</Filter>
     2.6      </ClCompile>
     2.7 +    <ClCompile Include="src\pgp_gpg.c">
     2.8 +      <Filter>Quelldateien</Filter>
     2.9 +    </ClCompile>
    2.10    </ItemGroup>
    2.11    <ItemGroup>
    2.12      <ClInclude Include="src\keymanagement.h">
    2.13 @@ -53,5 +56,14 @@
    2.14      <ClInclude Include="src\cryptotech.h">
    2.15        <Filter>Headerdateien</Filter>
    2.16      </ClInclude>
    2.17 +    <ClInclude Include="src\pgp_gpg.h">
    2.18 +      <Filter>Headerdateien</Filter>
    2.19 +    </ClInclude>
    2.20 +    <ClInclude Include="src\pEp_internal.h">
    2.21 +      <Filter>Headerdateien</Filter>
    2.22 +    </ClInclude>
    2.23 +    <ClInclude Include="src\pgp_gpg_internal.h">
    2.24 +      <Filter>Headerdateien</Filter>
    2.25 +    </ClInclude>
    2.26    </ItemGroup>
    2.27  </Project>
    2.28 \ No newline at end of file
     3.1 --- a/src/cryptotech.c	Mon Sep 01 13:02:23 2014 +0200
     3.2 +++ b/src/cryptotech.c	Mon Sep 01 17:44:19 2014 +0200
     3.3 @@ -1,5 +1,11 @@
     3.4  #include "cryptotech.h"
     3.5  
     3.6 +#ifdef NO_GPG
     3.7 +#include "pgp_netpgp.h"
     3.8 +#else
     3.9 +#include "pgp_gpg.h"
    3.10 +#endif
    3.11 +
    3.12  #include <stdlib.h>
    3.13  #include <memory.h>
    3.14  #include <assert.h>
    3.15 @@ -10,11 +16,23 @@
    3.16      memset(cryptotech, 0, sizeof(PEP_cryptotech_t) * PEP_crypt__count);
    3.17  
    3.18      cryptotech[0].id = PEP_crypt_none;
    3.19 +    cryptotech[0].unconfirmed_comm_type = PEP_ct_no_encryption;
    3.20 +    cryptotech[0].confirmed_comm_type = PEP_ct_no_encryption;
    3.21  
    3.22      cryptotech[1].id = PEP_crypt_OpenPGP;
    3.23 -    cryptotech[1].decrypt_and_verify = decrypt_and_verify;
    3.24 -    cryptotech[1].encrypt_and_sign = encrypt_and_sign;
    3.25 -    cryptotech[1].verify_text = verify_text;
    3.26 +    cryptotech[1].unconfirmed_comm_type = PEP_ct_OpenPGP_unconfirmed;
    3.27 +    cryptotech[1].confirmed_comm_type = PEP_ct_OpenPGP;
    3.28 +    cryptotech[1].decrypt_and_verify = pgp_decrypt_and_verify;
    3.29 +    cryptotech[1].encrypt_and_sign = pgp_encrypt_and_sign;
    3.30 +    cryptotech[1].verify_text = pgp_verify_text;
    3.31 +    cryptotech[1].delete_keypair = pgp_delete_keypair;
    3.32 +    cryptotech[1].export_key = pgp_export_key;
    3.33 +    cryptotech[1].find_keys = pgp_find_keys;
    3.34 +    cryptotech[1].generate_keypair = pgp_generate_keypair;
    3.35 +    cryptotech[1].get_key_rating = pgp_get_key_rating;
    3.36 +    cryptotech[1].import_key = pgp_import_key;
    3.37 +    cryptotech[1].recv_key = pgp_recv_key;
    3.38 +    cryptotech[1].send_key = pgp_send_key;
    3.39  
    3.40      return PEP_STATUS_OK;
    3.41  }
     4.1 --- a/src/cryptotech.h	Mon Sep 01 13:02:23 2014 +0200
     4.2 +++ b/src/cryptotech.h	Mon Sep 01 17:44:19 2014 +0200
     4.3 @@ -4,10 +4,10 @@
     4.4  
     4.5  typedef enum _PEP_cryptotech {
     4.6      PEP_crypt_none = 0,
     4.7 -    PEP_crypt_OpenPGP = 0x2f,
     4.8 -//    PEP_ctypt_PEP = 0x6f,
     4.9 -//    PEP_crypt_SMIME = 0x10,
    4.10 -//    PEP_crypt_CMS = 0x20,
    4.11 +    PEP_crypt_OpenPGP,
    4.12 +    //    PEP_ctypt_PEP,
    4.13 +    //    PEP_crypt_SMIME,
    4.14 +    //    PEP_crypt_CMS,
    4.15  
    4.16      PEP_crypt__count
    4.17  };
    4.18 @@ -27,11 +27,48 @@
    4.19      size_t psize, char **ctext, size_t *csize
    4.20      );
    4.21  
    4.22 +typedef PEP_STATUS (*delete_keypair_t)(PEP_SESSION session, const char *fpr);
    4.23 +
    4.24 +typedef PEP_STATUS (*export_key_t)(
    4.25 +    PEP_SESSION session, const char *fpr, char **key_data, size_t *size
    4.26 +    );
    4.27 +
    4.28 +typedef PEP_STATUS (*find_keys_t)(
    4.29 +    PEP_SESSION session, const char *pattern, stringlist_t **keylist
    4.30 +    );
    4.31 +
    4.32 +typedef PEP_STATUS (*generate_keypair_t)(
    4.33 +    PEP_SESSION session, pEp_identity *identity
    4.34 +    );
    4.35 +
    4.36 +typedef PEP_STATUS (*get_key_rating_t)(
    4.37 +    PEP_SESSION session,
    4.38 +    const char *fpr,
    4.39 +    PEP_comm_type *comm_type
    4.40 +    );
    4.41 +
    4.42 +typedef PEP_STATUS (*import_key_t)(PEP_SESSION session, const char *key_data, size_t size);
    4.43 +
    4.44 +typedef PEP_STATUS (*recv_key_t)(PEP_SESSION session, const char *pattern);
    4.45 +
    4.46 +typedef PEP_STATUS (*send_key_t)(PEP_SESSION session, const char *pattern);
    4.47 +
    4.48  typedef struct _PEP_cryptotech_t {
    4.49      uint8_t id;
    4.50 +    // the following are default values; comm_type may vary with key length or b0rken crypto
    4.51 +    uint8_t unconfirmed_comm_type;
    4.52 +    uint8_t confirmed_comm_type;
    4.53      decrypt_and_verify_t decrypt_and_verify;
    4.54      verify_text_t verify_text;
    4.55      encrypt_and_sign_t encrypt_and_sign;
    4.56 +    delete_keypair_t delete_keypair;
    4.57 +    export_key_t export_key;
    4.58 +    find_keys_t find_keys;
    4.59 +    generate_keypair_t generate_keypair;
    4.60 +    get_key_rating_t get_key_rating;
    4.61 +    import_key_t import_key;
    4.62 +    recv_key_t recv_key;
    4.63 +    send_key_t send_key;
    4.64  } PEP_cryptotech_t;
    4.65  
    4.66  typedef uint64_t cryptotech_mask;
     5.1 Binary file src/gpgme.exp has changed
     6.1 Binary file src/gpgme.lib has changed
     7.1 --- a/src/keymanagement.c	Mon Sep 01 13:02:23 2014 +0200
     7.2 +++ b/src/keymanagement.c	Mon Sep 01 17:44:19 2014 +0200
     7.3 @@ -257,6 +257,9 @@
     7.4      if (status != PEP_STATUS_OK)
     7.5          return status;
     7.6  
     7.7 +    assert(retrieve_next_identity);
     7.8 +    assert(management);
     7.9 +
    7.10      log_event(session, "keymanagement thread started", "pEp engine", NULL, NULL);
    7.11  
    7.12      while (identity = retrieve_next_identity(management)) {
     8.1 --- a/src/pEpEngine.c	Mon Sep 01 13:02:23 2014 +0200
     8.2 +++ b/src/pEpEngine.c	Mon Sep 01 17:44:19 2014 +0200
     8.3 @@ -1,216 +1,13 @@
     8.4 -#define PEP_ENGINE_VERSION "0.4.0"
     8.5 -
     8.6 -// this is 20 safewords with 79 chars max
     8.7 -#define MAX_SAFEWORDS_SPACE (20 * 80)
     8.8 -
     8.9 -// XML parameters string
    8.10 -#define PARMS_MAX 32768
    8.11 -
    8.12 -// maximum busy wait time in ms
    8.13 -#define BUSY_WAIT_TIME 5000
    8.14 -
    8.15 -// maximum line length for reading gpg.conf
    8.16 -#define MAX_LINELENGTH 1024
    8.17 -
    8.18 -// default keyserver
    8.19 -#define DEFAULT_KEYSERVER "hkp://keys.gnupg.net"
    8.20 -
    8.21 -#ifdef WIN32
    8.22 -#include "platform_windows.h"
    8.23 -#define LOCAL_DB windoze_local_db()
    8.24 -#define SYSTEM_DB windoze_system_db()
    8.25 -#define LIBGPGME "libgpgme-11.dll"
    8.26 -#else // UNIX
    8.27 -#define _POSIX_C_SOURCE 200809L
    8.28 -#include <dlfcn.h>
    8.29 -#include "platform_unix.h"
    8.30 -#define LOCAL_DB unix_local_db()
    8.31 -#ifndef SYSTEM_DB
    8.32 -#define SYSTEM_DB "/usr/share/pEp/system.db"
    8.33 +#include "pEp_internal.h"
    8.34 +#ifndef NO_GPG
    8.35 +#include "pgp_gpg.h"
    8.36 +#else
    8.37 +#include "pgp_netpgp.h"
    8.38  #endif
    8.39 -#ifndef LIBGPGME
    8.40 -#define LIBGPGME "libgpgme-pthread.so"
    8.41 -#endif
    8.42 -#endif
    8.43 -
    8.44 -#include <locale.h>
    8.45 -#include <stdlib.h>
    8.46 -#include <string.h>
    8.47 -#include <assert.h>
    8.48 -#include <stdio.h>
    8.49 -
    8.50 -#ifndef NDEBUG
    8.51 -#include <stdio.h>
    8.52 -#endif
    8.53 -
    8.54 -#include <gpgme.h>
    8.55 -#include "sqlite3.h"
    8.56 -
    8.57 -#define _EXPORT_PEP_ENGINE_DLL
    8.58 -#include "pEpEngine.h"
    8.59 -
    8.60 -#define NOT_IMPLEMENTED assert(0)
    8.61 -
    8.62 -// init
    8.63 -
    8.64 -typedef const char * (*gpgme_check_version_t)(const char*);
    8.65 -typedef gpgme_error_t (*gpgme_set_locale_t)(gpgme_ctx_t CTX, int CATEGORY,
    8.66 -        const char *VALUE);
    8.67 -typedef gpgme_error_t (*gpgme_new_t)(gpgme_ctx_t *CTX);
    8.68 -typedef void (*gpgme_release_t)(gpgme_ctx_t CTX);
    8.69 -typedef gpgme_error_t (*gpgme_set_protocol_t)(gpgme_ctx_t CTX,
    8.70 -        gpgme_protocol_t PROTO);
    8.71 -typedef void (*gpgme_set_armor_t)(gpgme_ctx_t CTX, int YES);
    8.72 -
    8.73 -// data
    8.74 -
    8.75 -typedef gpgme_error_t (*gpgme_data_new_t)(gpgme_data_t *DH);
    8.76 -typedef gpgme_error_t (*gpgme_data_new_from_mem_t)(gpgme_data_t *DH,
    8.77 -        const char *BUFFER, size_t SIZE, int COPY);
    8.78 -typedef void (*gpgme_data_release_t)(gpgme_data_t DH);
    8.79 -typedef gpgme_data_type_t (*gpgme_data_identify_t)(gpgme_data_t DH);
    8.80 -typedef size_t (*gpgme_data_seek_t)(gpgme_data_t DH, size_t OFFSET,
    8.81 -        int WHENCE);
    8.82 -typedef size_t (*gpgme_data_read_t)(gpgme_data_t DH, void *BUFFER,
    8.83 -        size_t LENGTH);
    8.84 -
    8.85 -// encrypt and decrypt
    8.86 -
    8.87 -typedef gpgme_error_t (*gpgme_op_decrypt_t)(gpgme_ctx_t CTX,
    8.88 -        gpgme_data_t CIPHER, gpgme_data_t PLAIN);
    8.89 -typedef gpgme_error_t (*gpgme_op_verify_t)(gpgme_ctx_t CTX, gpgme_data_t SIG,
    8.90 -        gpgme_data_t SIGNED_TEXT, gpgme_data_t PLAIN);
    8.91 -typedef gpgme_error_t (*gpgme_op_decrypt_verify_t)(gpgme_ctx_t CTX,
    8.92 -        gpgme_data_t CIPHER, gpgme_data_t PLAIN);
    8.93 -typedef gpgme_decrypt_result_t (*gpgme_op_decrypt_result_t)(gpgme_ctx_t CTX);
    8.94 -typedef gpgme_error_t (*gpgme_op_encrypt_sign_t)(gpgme_ctx_t CTX,
    8.95 -        gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
    8.96 -        gpgme_data_t CIPHER);
    8.97 -typedef gpgme_verify_result_t (*gpgme_op_verify_result_t)(gpgme_ctx_t CTX);
    8.98 -typedef void (*gpgme_signers_clear_t)(gpgme_ctx_t CTX);
    8.99 -typedef gpgme_error_t (*gpgme_signers_add_t)(gpgme_ctx_t CTX, const gpgme_key_t KEY);
   8.100 -
   8.101 -// keys
   8.102 -
   8.103 -typedef gpgme_error_t (*gpgme_get_key_t)(gpgme_ctx_t CTX, const char *FPR,
   8.104 -        gpgme_key_t *R_KEY, int SECRET);
   8.105 -typedef gpgme_error_t (*gpgme_op_genkey_t)(gpgme_ctx_t CTX, const char *PARMS,
   8.106 -        gpgme_data_t PUBLIC, gpgme_data_t SECRET);
   8.107 -typedef gpgme_genkey_result_t (*gpgme_op_genkey_result_t)(gpgme_ctx_t CTX);
   8.108 -typedef gpgme_error_t (*gpgme_op_delete_t)(gpgme_ctx_t CTX,
   8.109 -        const gpgme_key_t KEY, int ALLOW_SECRET);
   8.110 -typedef gpgme_error_t (*gpgme_op_import_t)(gpgme_ctx_t CTX,
   8.111 -        gpgme_data_t KEYDATA);
   8.112 -typedef gpgme_error_t (*gpgme_op_export_t)(gpgme_ctx_t CTX,
   8.113 -        const char *PATTERN, gpgme_export_mode_t MODE, gpgme_data_t KEYDATA);
   8.114 -typedef gpgme_error_t (*gpgme_set_keylist_mode_t)(gpgme_ctx_t CTX,
   8.115 -        gpgme_keylist_mode_t MODE);
   8.116 -typedef gpgme_keylist_mode_t (*gpgme_get_keylist_mode_t)(gpgme_ctx_t CTX);
   8.117 -typedef gpgme_error_t (*gpgme_op_keylist_start_t)(gpgme_ctx_t CTX,
   8.118 -        const char *PATTERN, int SECRET_ONLY);
   8.119 -typedef gpgme_error_t (*gpgme_op_keylist_next_t)(gpgme_ctx_t CTX,
   8.120 -        gpgme_key_t *R_KEY);
   8.121 -typedef gpgme_error_t (*gpgme_op_keylist_end_t)(gpgme_ctx_t CTX);
   8.122 -typedef gpgme_error_t (*gpgme_op_import_keys_t)(gpgme_ctx_t CTX,
   8.123 -        gpgme_key_t *KEYS);
   8.124 -typedef void (*gpgme_key_ref_t)(gpgme_key_t KEY);
   8.125 -typedef void (*gpgme_key_unref_t)(gpgme_key_t KEY);
   8.126 -
   8.127 -typedef struct {
   8.128 -	const char *version;
   8.129 -    const char *passphrase;
   8.130 -	void * gpgme;
   8.131 -	gpgme_ctx_t ctx;
   8.132 -
   8.133 -	sqlite3 *db;
   8.134 -	sqlite3 *system_db;
   8.135 -
   8.136 -	sqlite3_stmt *log;
   8.137 -	sqlite3_stmt *safeword;
   8.138 -	sqlite3_stmt *get_identity;
   8.139 -	sqlite3_stmt *set_person;
   8.140 -	sqlite3_stmt *set_pgp_keypair;
   8.141 -	sqlite3_stmt *set_identity;
   8.142 -	sqlite3_stmt *set_trust;
   8.143 -    sqlite3_stmt *get_trust;
   8.144 -
   8.145 -	gpgme_check_version_t gpgme_check;
   8.146 -	gpgme_set_locale_t gpgme_set_locale;
   8.147 -	gpgme_new_t gpgme_new;
   8.148 -	gpgme_release_t gpgme_release;
   8.149 -	gpgme_set_protocol_t gpgme_set_protocol;
   8.150 -	gpgme_set_armor_t gpgme_set_armor;
   8.151 -
   8.152 -	gpgme_data_new_t gpgme_data_new;
   8.153 -	gpgme_data_new_from_mem_t gpgme_data_new_from_mem;
   8.154 -	gpgme_data_release_t gpgme_data_release;
   8.155 -	gpgme_data_identify_t gpgme_data_identify;
   8.156 -	gpgme_data_seek_t gpgme_data_seek;
   8.157 -	gpgme_data_read_t gpgme_data_read;
   8.158 -
   8.159 -	gpgme_op_decrypt_t gpgme_op_decrypt;
   8.160 -	gpgme_op_verify_t gpgme_op_verify;
   8.161 -	gpgme_op_decrypt_verify_t gpgme_op_decrypt_verify;
   8.162 -	gpgme_op_decrypt_result_t gpgme_op_decrypt_result;
   8.163 -	gpgme_op_encrypt_sign_t gpgme_op_encrypt_sign;
   8.164 -	gpgme_op_verify_result_t gpgme_op_verify_result;
   8.165 -    gpgme_signers_clear_t gpgme_signers_clear;
   8.166 -    gpgme_signers_add_t gpgme_signers_add;
   8.167 -
   8.168 -	gpgme_get_key_t gpgme_get_key;
   8.169 -	gpgme_op_genkey_t gpgme_op_genkey;
   8.170 -    gpgme_op_genkey_result_t gpgme_op_genkey_result;
   8.171 -    gpgme_op_delete_t gpgme_op_delete;
   8.172 -    gpgme_op_import_t gpgme_op_import;
   8.173 -    gpgme_op_export_t gpgme_op_export;
   8.174 -    gpgme_set_keylist_mode_t gpgme_set_keylist_mode;
   8.175 -    gpgme_get_keylist_mode_t gpgme_get_keylist_mode;
   8.176 -    gpgme_op_keylist_start_t gpgme_op_keylist_start;
   8.177 -    gpgme_op_keylist_next_t gpgme_op_keylist_next;
   8.178 -    gpgme_op_keylist_end_t gpgme_op_keylist_end;
   8.179 -    gpgme_op_import_keys_t gpgme_op_import_keys;
   8.180 -    gpgme_key_ref_t gpgme_key_ref;
   8.181 -    gpgme_key_unref_t gpgme_key_unref;
   8.182 -} pEpSession;
   8.183 -
   8.184 -static bool ensure_keyserver()
   8.185 -{
   8.186 -    static char buf[MAX_LINELENGTH];
   8.187 -    int n;
   8.188 -    FILE *f = fopen(gpg_conf(), "r");
   8.189 -
   8.190 -    if (f != NULL) {
   8.191 -        while (!feof(f)) {
   8.192 -            char * s = fgets(buf, MAX_LINELENGTH, f);
   8.193 -            if (s && !feof(f)) {
   8.194 -                char * t = strtok(s, " ");
   8.195 -                if (t && strcmp(t, "keyserver") == 0)
   8.196 -                {
   8.197 -                    fclose(f);
   8.198 -                    return true;
   8.199 -                }
   8.200 -            }
   8.201 -        }
   8.202 -        f = freopen(gpg_conf(), "a", f);
   8.203 -    }
   8.204 -    else {
   8.205 -        f = fopen(gpg_conf(), "w");
   8.206 -    }
   8.207 -
   8.208 -    assert(f);
   8.209 -    if (f == NULL)
   8.210 -        return false;
   8.211 -
   8.212 -    n = fprintf(f, "keyserver %s\n", DEFAULT_KEYSERVER);
   8.213 -    assert(n >= 0);
   8.214 -    fclose(f);
   8.215 -
   8.216 -    return true;
   8.217 -}
   8.218  
   8.219  DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
   8.220  {
   8.221 -	gpgme_error_t gpgme_error;
   8.222 +    PEP_STATUS status_result;
   8.223  	int int_result;
   8.224  	const char *sql_log;
   8.225  	const char *sql_safeword;
   8.226 @@ -221,8 +18,6 @@
   8.227  	const char *sql_set_trust;
   8.228      const char *sql_get_trust;
   8.229  
   8.230 -    bool bResult;
   8.231 -
   8.232  	assert(sqlite3_threadsafe());
   8.233  	if (!sqlite3_threadsafe())
   8.234  		return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
   8.235 @@ -237,195 +32,16 @@
   8.236  	
   8.237  	_session->version = PEP_ENGINE_VERSION;
   8.238  
   8.239 -    bResult = ensure_keyserver();
   8.240 -    assert(bResult);
   8.241 -
   8.242 -    // to do: implement something useful
   8.243 -    _session->passphrase = "";
   8.244 -
   8.245 -	_session->gpgme = dlopen(LIBGPGME, RTLD_LAZY);
   8.246 -	if (_session->gpgme == NULL) {
   8.247 -		free(_session);
   8.248 -		return PEP_INIT_CANNOT_LOAD_GPGME;
   8.249 -	}
   8.250 -
   8.251 -	_session->gpgme_set_locale
   8.252 -        = (gpgme_set_locale_t) (intptr_t) dlsym(_session->gpgme,
   8.253 -                "gpgme_set_locale");
   8.254 -	assert(_session->gpgme_set_locale);
   8.255 -
   8.256 -	_session->gpgme_check
   8.257 -        = (gpgme_check_version_t) (intptr_t) dlsym(_session->gpgme,
   8.258 -                "gpgme_check_version");
   8.259 -	assert(_session->gpgme_check);
   8.260 -
   8.261 -	_session->gpgme_new
   8.262 -        = (gpgme_new_t) (intptr_t) dlsym(_session->gpgme, "gpgme_new");
   8.263 -	assert(_session->gpgme_new);
   8.264 -
   8.265 -	_session->gpgme_release
   8.266 -        = (gpgme_release_t) (intptr_t) dlsym(_session->gpgme, "gpgme_release");
   8.267 -	assert(_session->gpgme_release);
   8.268 -
   8.269 -	_session->gpgme_set_protocol
   8.270 -        = (gpgme_set_protocol_t) (intptr_t) dlsym(_session->gpgme,
   8.271 -                "gpgme_set_protocol");
   8.272 -	assert(_session->gpgme_set_protocol);
   8.273 -
   8.274 -	_session->gpgme_set_armor
   8.275 -        = (gpgme_set_armor_t) (intptr_t) dlsym(_session->gpgme,
   8.276 -                "gpgme_set_armor");
   8.277 -	assert(_session->gpgme_set_armor);
   8.278 -
   8.279 -	_session->gpgme_data_new
   8.280 -        = (gpgme_data_new_t) (intptr_t) dlsym(_session->gpgme,
   8.281 -                "gpgme_data_new");
   8.282 -	assert(_session->gpgme_data_new);
   8.283 -
   8.284 -	_session->gpgme_data_new_from_mem
   8.285 -        = (gpgme_data_new_from_mem_t) (intptr_t) dlsym(_session->gpgme,
   8.286 -                "gpgme_data_new_from_mem");
   8.287 -	assert(_session->gpgme_data_new_from_mem);
   8.288 -
   8.289 -	_session->gpgme_data_release
   8.290 -        = (gpgme_data_release_t) (intptr_t) dlsym(_session->gpgme,
   8.291 -                "gpgme_data_release");
   8.292 -	assert(_session->gpgme_data_release);
   8.293 -
   8.294 -	_session->gpgme_data_identify
   8.295 -        = (gpgme_data_identify_t) (intptr_t) dlsym(_session->gpgme,
   8.296 -                "gpgme_data_identify");
   8.297 -	assert(_session->gpgme_data_identify);
   8.298 -
   8.299 -	_session->gpgme_data_seek
   8.300 -        = (gpgme_data_seek_t) (intptr_t) dlsym(_session->gpgme,
   8.301 -                "gpgme_data_seek");
   8.302 -	assert(_session->gpgme_data_seek);
   8.303 -
   8.304 -	_session->gpgme_data_read
   8.305 -        = (gpgme_data_read_t) (intptr_t) dlsym(_session->gpgme,
   8.306 -                "gpgme_data_read");
   8.307 -	assert(_session->gpgme_data_read);
   8.308 -
   8.309 -	_session->gpgme_op_decrypt
   8.310 -        = (gpgme_op_decrypt_t) (intptr_t) dlsym(_session->gpgme,
   8.311 -                "gpgme_op_decrypt");
   8.312 -	assert(_session->gpgme_op_decrypt);
   8.313 -
   8.314 -	_session->gpgme_op_verify
   8.315 -        = (gpgme_op_verify_t) (intptr_t) dlsym(_session->gpgme,
   8.316 -                "gpgme_op_verify");
   8.317 -	assert(_session->gpgme_op_verify);
   8.318 -
   8.319 -	_session->gpgme_op_decrypt_verify
   8.320 -        = (gpgme_op_decrypt_verify_t) (intptr_t) dlsym(_session->gpgme,
   8.321 -                "gpgme_op_decrypt_verify");
   8.322 -	assert(_session->gpgme_op_decrypt_verify);
   8.323 -
   8.324 -	_session->gpgme_op_decrypt_result
   8.325 -        = (gpgme_op_decrypt_result_t) (intptr_t) dlsym(_session->gpgme,
   8.326 -                "gpgme_op_decrypt_result");
   8.327 -	assert(_session->gpgme_op_decrypt_result);
   8.328 -
   8.329 -	_session->gpgme_op_encrypt_sign
   8.330 -        = (gpgme_op_encrypt_sign_t) (intptr_t) dlsym(_session->gpgme,
   8.331 -                "gpgme_op_encrypt_sign");
   8.332 -	assert(_session->gpgme_op_encrypt_sign);
   8.333 -
   8.334 -	_session->gpgme_op_verify_result
   8.335 -        = (gpgme_op_verify_result_t) (intptr_t) dlsym(_session->gpgme,
   8.336 -                "gpgme_op_verify_result");
   8.337 -	assert(_session->gpgme_op_verify_result);
   8.338 -
   8.339 -    _session->gpgme_signers_clear
   8.340 -        = (gpgme_signers_clear_t) (intptr_t) dlsym(_session->gpgme,
   8.341 -        "gpgme_signers_clear");
   8.342 -    assert(_session->gpgme_signers_clear);
   8.343 -
   8.344 -    _session->gpgme_signers_add
   8.345 -        = (gpgme_signers_add_t) (intptr_t) dlsym(_session->gpgme,
   8.346 -        "gpgme_signers_add");
   8.347 -    assert(_session->gpgme_signers_add);
   8.348 -
   8.349 -	_session->gpgme_get_key
   8.350 -        = (gpgme_get_key_t) (intptr_t) dlsym(_session->gpgme, "gpgme_get_key");
   8.351 -	assert(_session->gpgme_get_key);
   8.352 -
   8.353 -	_session->gpgme_op_genkey
   8.354 -        = (gpgme_op_genkey_t) (intptr_t) dlsym(_session->gpgme,
   8.355 -                "gpgme_op_genkey");
   8.356 -	assert(_session->gpgme_op_genkey);
   8.357 -
   8.358 -	_session->gpgme_op_genkey_result
   8.359 -        = (gpgme_op_genkey_result_t) (intptr_t) dlsym(_session->gpgme,
   8.360 -                "gpgme_op_genkey_result");
   8.361 -	assert(_session->gpgme_op_genkey_result);
   8.362 -
   8.363 -    _session->gpgme_op_delete = (gpgme_op_delete_t) (intptr_t)
   8.364 -        dlsym(_session->gpgme, "gpgme_op_delete");
   8.365 -	assert(_session->gpgme_op_delete);
   8.366 -
   8.367 -    _session->gpgme_op_import = (gpgme_op_import_t) (intptr_t)
   8.368 -        dlsym(_session->gpgme, "gpgme_op_import");
   8.369 -	assert(_session->gpgme_op_import);
   8.370 -
   8.371 -    _session->gpgme_op_export = (gpgme_op_export_t) (intptr_t)
   8.372 -        dlsym(_session->gpgme, "gpgme_op_export");
   8.373 -	assert(_session->gpgme_op_export);
   8.374 -
   8.375 -    _session->gpgme_set_keylist_mode = (gpgme_set_keylist_mode_t) (intptr_t)
   8.376 -        dlsym(_session->gpgme, "gpgme_set_keylist_mode");
   8.377 -	assert(_session->gpgme_set_keylist_mode);
   8.378 -
   8.379 -    _session->gpgme_get_keylist_mode = (gpgme_get_keylist_mode_t) (intptr_t)
   8.380 -        dlsym(_session->gpgme, "gpgme_get_keylist_mode");
   8.381 -	assert(_session->gpgme_get_keylist_mode);
   8.382 -
   8.383 -    _session->gpgme_op_keylist_start = (gpgme_op_keylist_start_t) (intptr_t)
   8.384 -        dlsym(_session->gpgme, "gpgme_op_keylist_start");
   8.385 -	assert(_session->gpgme_op_keylist_start);
   8.386 -
   8.387 -    _session->gpgme_op_keylist_next = (gpgme_op_keylist_next_t) (intptr_t)
   8.388 -        dlsym(_session->gpgme, "gpgme_op_keylist_next");
   8.389 -	assert(_session->gpgme_op_keylist_next);
   8.390 -
   8.391 -    _session->gpgme_op_keylist_end = (gpgme_op_keylist_end_t) (intptr_t)
   8.392 -        dlsym(_session->gpgme, "gpgme_op_keylist_end");
   8.393 -	assert(_session->gpgme_op_keylist_end);
   8.394 -
   8.395 -    _session->gpgme_op_import_keys = (gpgme_op_import_keys_t) (intptr_t)
   8.396 -        dlsym(_session->gpgme, "gpgme_op_import_keys");
   8.397 -	assert(_session->gpgme_op_import_keys);
   8.398 -
   8.399 -    _session->gpgme_key_ref = (gpgme_key_ref_t) (intptr_t)
   8.400 -        dlsym(_session->gpgme, "gpgme_key_ref");
   8.401 -	assert(_session->gpgme_key_ref);
   8.402 -
   8.403 -    _session->gpgme_key_unref = (gpgme_key_unref_t) (intptr_t)
   8.404 -        dlsym(_session->gpgme, "gpgme_key_unref");
   8.405 -	assert(_session->gpgme_key_unref);
   8.406 -
   8.407 -	setlocale(LC_ALL, "");
   8.408 -	_session->version = _session->gpgme_check(NULL);
   8.409 -	_session->gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
   8.410 -
   8.411 -	gpgme_error = _session->gpgme_new(&_session->ctx);
   8.412 -	if (gpgme_error != GPG_ERR_NO_ERROR) {
   8.413 -		dlclose(_session->gpgme);
   8.414 -		free(_session);
   8.415 -		return PEP_INIT_GPGME_INIT_FAILED;
   8.416 -	}
   8.417 -
   8.418 -    gpgme_error = _session->gpgme_set_protocol(_session->ctx,
   8.419 -            GPGME_PROTOCOL_OpenPGP);
   8.420 -	assert(gpgme_error == GPG_ERR_NO_ERROR);
   8.421 -
   8.422 -	_session->gpgme_set_armor(_session->ctx, 1);
   8.423 +    status_result = pgp_init(session);
   8.424 +    assert(status_result == PEP_STATUS_OK);
   8.425 +    if (status_result != PEP_STATUS_OK) {
   8.426 +        free(_session);
   8.427 +        return status_result;
   8.428 +    }
   8.429  
   8.430      assert(LOCAL_DB);
   8.431      if (LOCAL_DB == NULL) {
   8.432 -		_session->gpgme_release(_session->ctx);
   8.433 -		dlclose(_session->gpgme);
   8.434 +        pgp_release(session);
   8.435          free(_session);
   8.436          return PEP_INIT_CANNOT_OPEN_DB;
   8.437      }
   8.438 @@ -442,9 +58,8 @@
   8.439  
   8.440  	if (int_result != SQLITE_OK) {
   8.441  		sqlite3_close_v2(_session->db);
   8.442 -		_session->gpgme_release(_session->ctx);
   8.443 -		dlclose(_session->gpgme);
   8.444 -		free(_session);
   8.445 +        pgp_release(session);
   8.446 +        free(_session);
   8.447  		return PEP_INIT_CANNOT_OPEN_DB;
   8.448  	}
   8.449  
   8.450 @@ -453,9 +68,8 @@
   8.451      assert(SYSTEM_DB);
   8.452      if (SYSTEM_DB == NULL) {
   8.453  		sqlite3_close_v2(_session->db);
   8.454 -		_session->gpgme_release(_session->ctx);
   8.455 -		dlclose(_session->gpgme);
   8.456 -		free(_session);
   8.457 +        pgp_release(session);
   8.458 +        free(_session);
   8.459  		return PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   8.460      }
   8.461  
   8.462 @@ -470,9 +84,8 @@
   8.463  	if (int_result != SQLITE_OK) {
   8.464  		sqlite3_close_v2(_session->system_db);
   8.465  		sqlite3_close_v2(_session->db);
   8.466 -		_session->gpgme_release(_session->ctx);
   8.467 -		dlclose(_session->gpgme);
   8.468 -		free(_session);
   8.469 +        pgp_release(session);
   8.470 +        free(_session);
   8.471  		return PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   8.472  	}
   8.473  
   8.474 @@ -634,10 +247,8 @@
   8.475  			sqlite3_close_v2(_session->db);
   8.476  			sqlite3_close_v2(_session->system_db);
   8.477  		}
   8.478 -		if (_session->ctx)
   8.479 -			_session->gpgme_release(_session->ctx);
   8.480 -		dlclose(_session->gpgme);
   8.481 -	}
   8.482 +        pgp_release(session);
   8.483 +    }
   8.484  	free(_session);
   8.485  }
   8.486  
   8.487 @@ -706,471 +317,6 @@
   8.488      }
   8.489  }
   8.490  
   8.491 -DYNAMIC_API PEP_STATUS decrypt_and_verify(
   8.492 -        PEP_SESSION session, const char *ctext, size_t csize,
   8.493 -        char **ptext, size_t *psize, stringlist_t **keylist
   8.494 -    )
   8.495 -{
   8.496 -	pEpSession *_session = (pEpSession *) session;
   8.497 -
   8.498 -	PEP_STATUS result;
   8.499 -	gpgme_error_t gpgme_error;
   8.500 -	gpgme_data_t cipher, plain;
   8.501 -	gpgme_data_type_t dt;
   8.502 -
   8.503 -	stringlist_t *_keylist = NULL;
   8.504 -	int i_key = 0;
   8.505 -
   8.506 -	assert(_session);
   8.507 -	assert(ctext);
   8.508 -	assert(csize);
   8.509 -	assert(ptext);
   8.510 -	assert(psize);
   8.511 -	assert(keylist);
   8.512 -
   8.513 -	*ptext = NULL;
   8.514 -	*psize = 0;
   8.515 -	*keylist = NULL;
   8.516 -
   8.517 -    gpgme_error = _session->gpgme_data_new_from_mem(&cipher, ctext, csize, 0);
   8.518 -	assert(gpgme_error == GPG_ERR_NO_ERROR);
   8.519 -	if (gpgme_error != GPG_ERR_NO_ERROR) {
   8.520 -		if (gpgme_error == GPG_ERR_ENOMEM)
   8.521 -			return PEP_OUT_OF_MEMORY;
   8.522 -		else
   8.523 -			return PEP_UNKNOWN_ERROR;
   8.524 -	}
   8.525 -
   8.526 -	gpgme_error = _session->gpgme_data_new(&plain);
   8.527 -	assert(gpgme_error == GPG_ERR_NO_ERROR);
   8.528 -	if (gpgme_error != GPG_ERR_NO_ERROR) {
   8.529 -		_session->gpgme_data_release(cipher);
   8.530 -		if (gpgme_error == GPG_ERR_ENOMEM)
   8.531 -			return PEP_OUT_OF_MEMORY;
   8.532 -		else
   8.533 -			return PEP_UNKNOWN_ERROR;
   8.534 -	}
   8.535 -
   8.536 -	dt = _session->gpgme_data_identify(cipher);
   8.537 -	switch (dt) {
   8.538 -	case GPGME_DATA_TYPE_PGP_SIGNED:
   8.539 -	case GPGME_DATA_TYPE_PGP_OTHER:
   8.540 -        gpgme_error = _session->gpgme_op_decrypt_verify(_session->ctx, cipher,
   8.541 -                plain);
   8.542 -		assert(gpgme_error != GPG_ERR_INV_VALUE);
   8.543 -		assert(gpgme_error != GPG_ERR_NO_DATA);
   8.544 -
   8.545 -		switch (gpgme_error) {
   8.546 -		case GPG_ERR_NO_ERROR:
   8.547 -			{
   8.548 -                gpgme_verify_result_t gpgme_verify_result;
   8.549 -                char *_buffer = NULL;
   8.550 -				size_t reading;
   8.551 -                size_t length = _session->gpgme_data_seek(plain, 0, SEEK_END);
   8.552 -                gpgme_signature_t gpgme_signature;
   8.553 -
   8.554 -				assert(length != -1);
   8.555 -				_session->gpgme_data_seek(plain, 0, SEEK_SET);
   8.556 -
   8.557 -				// TODO: make things less memory consuming
   8.558 -                // the following algorithm allocates memory for the complete
   8.559 -                // text
   8.560 -
   8.561 -                _buffer = malloc(length + 1);
   8.562 -                assert(_buffer);
   8.563 -                if (_buffer == NULL) {
   8.564 -                    _session->gpgme_data_release(plain);
   8.565 -                    _session->gpgme_data_release(cipher);
   8.566 -                    return PEP_OUT_OF_MEMORY;
   8.567 -                }
   8.568 -
   8.569 -                reading = _session->gpgme_data_read(plain, _buffer, length);
   8.570 -				assert(length == reading);
   8.571 -
   8.572 -                gpgme_verify_result =
   8.573 -                    _session->gpgme_op_verify_result(_session->ctx);
   8.574 -				assert(gpgme_verify_result);
   8.575 -                gpgme_signature = gpgme_verify_result->signatures;
   8.576 -
   8.577 -				if (gpgme_signature) {
   8.578 -                    stringlist_t *k;
   8.579 -                    _keylist = new_stringlist(NULL);
   8.580 -                    assert(_keylist);
   8.581 -                    if (_keylist == NULL) {
   8.582 -						_session->gpgme_data_release(plain);
   8.583 -						_session->gpgme_data_release(cipher);
   8.584 -                        free(_buffer);
   8.585 -                        return PEP_OUT_OF_MEMORY;
   8.586 -                    }
   8.587 -                    k = _keylist;
   8.588 -
   8.589 -                    result = PEP_DECRYPTED_AND_VERIFIED;
   8.590 -					do {
   8.591 -                        switch (gpgme_signature->status) {
   8.592 -                        case GPG_ERR_NO_ERROR:
   8.593 -                            k = stringlist_add(k, gpgme_signature->fpr);
   8.594 -                            break;
   8.595 -                        case GPG_ERR_CERT_REVOKED:
   8.596 -                        case GPG_ERR_BAD_SIGNATURE:
   8.597 -                            result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   8.598 -                            break;
   8.599 -                        case GPG_ERR_SIG_EXPIRED:
   8.600 -                        case GPG_ERR_KEY_EXPIRED:
   8.601 -                        case GPG_ERR_NO_PUBKEY:
   8.602 -                            k = stringlist_add(k, gpgme_signature->fpr);
   8.603 -                            if (result == PEP_DECRYPTED_AND_VERIFIED)
   8.604 -                                result = PEP_DECRYPTED;
   8.605 -                            break;
   8.606 -                        case GPG_ERR_GENERAL:
   8.607 -                            break;
   8.608 -                        default:
   8.609 -                            if (result == PEP_DECRYPTED_AND_VERIFIED)
   8.610 -                                result = PEP_DECRYPTED;
   8.611 -                            break;
   8.612 -                        }
   8.613 -					} while ((gpgme_signature = gpgme_signature->next));
   8.614 -				} else {
   8.615 -					result = PEP_DECRYPTED;
   8.616 -				}
   8.617 -
   8.618 -				if (result == PEP_DECRYPTED_AND_VERIFIED
   8.619 -                        || result == PEP_DECRYPTED) {
   8.620 -					*ptext = _buffer;
   8.621 -					*psize = reading;
   8.622 -                    (*ptext)[*psize] = 0; // safeguard for naive users
   8.623 -					*keylist = _keylist;
   8.624 -				}
   8.625 -                else {
   8.626 -                    free_stringlist(_keylist);
   8.627 -                    free(_buffer);
   8.628 -	            }
   8.629 -				break;
   8.630 -			}
   8.631 -		case GPG_ERR_DECRYPT_FAILED:
   8.632 -			result = PEP_DECRYPT_WRONG_FORMAT;
   8.633 -			break;
   8.634 -		case GPG_ERR_BAD_PASSPHRASE:
   8.635 -			NOT_IMPLEMENTED;
   8.636 -        default:
   8.637 -            {
   8.638 -                gpgme_decrypt_result_t gpgme_decrypt_result = _session->gpgme_op_decrypt_result(_session->ctx);
   8.639 -                result = PEP_DECRYPT_NO_KEY;
   8.640 -
   8.641 -                if (gpgme_decrypt_result != NULL) {
   8.642 -                    if (gpgme_decrypt_result->unsupported_algorithm)
   8.643 -                        *keylist = new_stringlist(gpgme_decrypt_result->unsupported_algorithm);
   8.644 -                    else
   8.645 -                        *keylist = new_stringlist("");
   8.646 -                    assert(*keylist);
   8.647 -                    if (*keylist == NULL) {
   8.648 -                        result = PEP_OUT_OF_MEMORY;
   8.649 -                        break;
   8.650 -                    }
   8.651 -                    stringlist_t *_keylist = *keylist;
   8.652 -                    for (gpgme_recipient_t r = gpgme_decrypt_result->recipients; r != NULL; r = r->next) {
   8.653 -                        _keylist = stringlist_add(_keylist, r->keyid);
   8.654 -                        assert(_keylist);
   8.655 -                        if (_keylist == NULL) {
   8.656 -                            free_stringlist(*keylist);
   8.657 -                            *keylist = NULL;
   8.658 -                            result = PEP_OUT_OF_MEMORY;
   8.659 -                            break;
   8.660 -                        }
   8.661 -                    }
   8.662 -                    if (result == PEP_OUT_OF_MEMORY)
   8.663 -                        break;
   8.664 -                }
   8.665 -            }
   8.666 -		}
   8.667 -		break;
   8.668 -
   8.669 -	default:
   8.670 -		result = PEP_DECRYPT_WRONG_FORMAT;
   8.671 -	}
   8.672 -
   8.673 -	_session->gpgme_data_release(plain);
   8.674 -	_session->gpgme_data_release(cipher);
   8.675 -	return result;
   8.676 -}
   8.677 -
   8.678 -DYNAMIC_API PEP_STATUS verify_text(
   8.679 -        PEP_SESSION session, const char *text, size_t size,
   8.680 -        const char *signature, size_t sig_size, stringlist_t **keylist
   8.681 -    )
   8.682 -{
   8.683 -	pEpSession *_session = (pEpSession *) session;
   8.684 -
   8.685 -	PEP_STATUS result;
   8.686 -	gpgme_error_t gpgme_error;
   8.687 -	gpgme_data_t d_text, d_sig;
   8.688 -    stringlist_t *_keylist;
   8.689 -
   8.690 -    assert(session);
   8.691 -    assert(text);
   8.692 -    assert(size);
   8.693 -    assert(signature);
   8.694 -    assert(sig_size);
   8.695 -    assert(keylist);
   8.696 -
   8.697 -    *keylist = NULL;
   8.698 -
   8.699 -    gpgme_error = _session->gpgme_data_new_from_mem(&d_text, text, size, 0);
   8.700 -	assert(gpgme_error == GPG_ERR_NO_ERROR);
   8.701 -	if (gpgme_error != GPG_ERR_NO_ERROR) {
   8.702 -		if (gpgme_error == GPG_ERR_ENOMEM)
   8.703 -			return PEP_OUT_OF_MEMORY;
   8.704 -		else
   8.705 -			return PEP_UNKNOWN_ERROR;
   8.706 -	}
   8.707 -
   8.708 -    gpgme_error = _session->gpgme_data_new_from_mem(&d_sig, signature, sig_size, 0);
   8.709 -	assert(gpgme_error == GPG_ERR_NO_ERROR);
   8.710 -	if (gpgme_error != GPG_ERR_NO_ERROR) {
   8.711 -		_session->gpgme_data_release(d_text);
   8.712 -		if (gpgme_error == GPG_ERR_ENOMEM)
   8.713 -			return PEP_OUT_OF_MEMORY;
   8.714 -		else
   8.715 -			return PEP_UNKNOWN_ERROR;
   8.716 -	}
   8.717 -
   8.718 -    gpgme_error = _session->gpgme_op_verify(_session->ctx, d_sig, d_text, NULL);
   8.719 -    assert(gpgme_error != GPG_ERR_INV_VALUE);
   8.720 -
   8.721 -    switch (gpgme_error) {
   8.722 -    case GPG_ERR_NO_ERROR:
   8.723 -        {
   8.724 -            gpgme_verify_result_t gpgme_verify_result;
   8.725 -            gpgme_signature_t gpgme_signature;
   8.726 -
   8.727 -            gpgme_verify_result =
   8.728 -                _session->gpgme_op_verify_result(_session->ctx);
   8.729 -            assert(gpgme_verify_result);
   8.730 -            gpgme_signature = gpgme_verify_result->signatures;
   8.731 -
   8.732 -            if (gpgme_signature) {
   8.733 -                stringlist_t *k;
   8.734 -                _keylist = new_stringlist(NULL);
   8.735 -                assert(_keylist);
   8.736 -                if (_keylist == NULL) {
   8.737 -                    _session->gpgme_data_release(d_text);
   8.738 -                    _session->gpgme_data_release(d_sig);
   8.739 -                    return PEP_OUT_OF_MEMORY;
   8.740 -                }
   8.741 -                k = _keylist;
   8.742 -
   8.743 -                result = PEP_VERIFIED;
   8.744 -                do {
   8.745 -                    k = stringlist_add(k, gpgme_signature->fpr);
   8.746 -                    if (k == NULL) {
   8.747 -                        free_stringlist(_keylist);
   8.748 -                        _session->gpgme_data_release(d_text);
   8.749 -                        _session->gpgme_data_release(d_sig);
   8.750 -                        return PEP_OUT_OF_MEMORY;
   8.751 -                    }
   8.752 -                    if (gpgme_signature->summary & GPGME_SIGSUM_RED) {
   8.753 -                        if (gpgme_signature->summary & GPGME_SIGSUM_KEY_EXPIRED
   8.754 -                                || gpgme_signature->summary & GPGME_SIGSUM_SIG_EXPIRED) {
   8.755 -                            if (result == PEP_VERIFIED
   8.756 -                                    || result == PEP_VERIFIED_AND_TRUSTED)
   8.757 -                                result = PEP_UNENCRYPTED;
   8.758 -                        }
   8.759 -                        else {
   8.760 -                            result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   8.761 -                            break;
   8.762 -                        }
   8.763 -                    }
   8.764 -                    else {
   8.765 -                        if (gpgme_signature->summary & GPGME_SIGSUM_VALID) {
   8.766 -                            if (result == PEP_VERIFIED)
   8.767 -                                result = PEP_VERIFIED_AND_TRUSTED;
   8.768 -                        }
   8.769 -                        if (gpgme_signature->summary & GPGME_SIGSUM_GREEN) {
   8.770 -                            // good
   8.771 -                        }
   8.772 -                        else if (gpgme_signature->summary & GPGME_SIGSUM_KEY_MISSING) {
   8.773 -                            result = PEP_VERIFY_NO_KEY;
   8.774 -                        }
   8.775 -                        else if (gpgme_signature->summary & GPGME_SIGSUM_SYS_ERROR) {
   8.776 -                            if (result == PEP_VERIFIED
   8.777 -                                    || result == PEP_VERIFIED_AND_TRUSTED)
   8.778 -                                result = PEP_UNENCRYPTED;
   8.779 -                        }
   8.780 -                        else {
   8.781 -                            // do nothing
   8.782 -                        }
   8.783 -                    }
   8.784 -                } while ((gpgme_signature = gpgme_signature->next));
   8.785 -                *keylist = _keylist;
   8.786 -            } else {
   8.787 -                result = PEP_UNENCRYPTED;
   8.788 -            }
   8.789 -            break;
   8.790 -        }
   8.791 -        break;
   8.792 -    case GPG_ERR_NO_DATA:
   8.793 -        result = PEP_DECRYPT_WRONG_FORMAT;
   8.794 -        break;
   8.795 -    case GPG_ERR_INV_VALUE:
   8.796 -    default:
   8.797 -        result = PEP_UNKNOWN_ERROR;
   8.798 -        break;
   8.799 -    }
   8.800 -
   8.801 -    _session->gpgme_data_release(d_text);
   8.802 -    _session->gpgme_data_release(d_sig);
   8.803 -
   8.804 -    return result;
   8.805 -}
   8.806 -
   8.807 -DYNAMIC_API PEP_STATUS encrypt_and_sign(
   8.808 -        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   8.809 -        size_t psize, char **ctext, size_t *csize
   8.810 -    )
   8.811 -{
   8.812 -	pEpSession *_session = (pEpSession *) session;
   8.813 -
   8.814 -	PEP_STATUS result;
   8.815 -	gpgme_error_t gpgme_error;
   8.816 -	gpgme_data_t plain, cipher;
   8.817 -	gpgme_key_t *rcpt;
   8.818 -	gpgme_encrypt_flags_t flags;
   8.819 -	const stringlist_t *_keylist;
   8.820 -    int i, j;
   8.821 -
   8.822 -	assert(_session);
   8.823 -	assert(keylist);
   8.824 -	assert(ptext);
   8.825 -	assert(psize);
   8.826 -	assert(ctext);
   8.827 -	assert(csize);
   8.828 -
   8.829 -	*ctext = NULL;
   8.830 -	*csize = 0;
   8.831 -
   8.832 -    gpgme_error = _session->gpgme_data_new_from_mem(&plain, ptext, psize, 0);
   8.833 -	assert(gpgme_error == GPG_ERR_NO_ERROR);
   8.834 -	if (gpgme_error != GPG_ERR_NO_ERROR) {
   8.835 -		if (gpgme_error == GPG_ERR_ENOMEM)
   8.836 -			return PEP_OUT_OF_MEMORY;
   8.837 -		else
   8.838 -			return PEP_UNKNOWN_ERROR;
   8.839 -	}
   8.840 -
   8.841 -	gpgme_error = _session->gpgme_data_new(&cipher);
   8.842 -	assert(gpgme_error == GPG_ERR_NO_ERROR);
   8.843 -	if (gpgme_error != GPG_ERR_NO_ERROR) {
   8.844 -		_session->gpgme_data_release(plain);
   8.845 -		if (gpgme_error == GPG_ERR_ENOMEM)
   8.846 -			return PEP_OUT_OF_MEMORY;
   8.847 -		else
   8.848 -			return PEP_UNKNOWN_ERROR;
   8.849 -	}
   8.850 -
   8.851 -    rcpt = (gpgme_key_t *) calloc(stringlist_length(keylist) + 1,
   8.852 -            sizeof(gpgme_key_t));
   8.853 -	assert(rcpt);
   8.854 -	if (rcpt == NULL) {
   8.855 -		_session->gpgme_data_release(plain);
   8.856 -		_session->gpgme_data_release(cipher);
   8.857 -		return PEP_OUT_OF_MEMORY;
   8.858 -	}
   8.859 -
   8.860 -    _session->gpgme_signers_clear(_session->ctx);
   8.861 -
   8.862 -    for (_keylist=keylist, i=0; _keylist!=NULL; _keylist=_keylist->next, i++) {
   8.863 -		assert(_keylist->value);
   8.864 -        gpgme_error = _session->gpgme_get_key(_session->ctx, _keylist->value,
   8.865 -                &rcpt[i], 0);
   8.866 -		assert(gpgme_error != GPG_ERR_ENOMEM);
   8.867 -
   8.868 -		switch (gpgme_error) {
   8.869 -		case GPG_ERR_ENOMEM:
   8.870 -            for (j=0; j<i; j++)
   8.871 -                _session->gpgme_key_unref(rcpt[j]);
   8.872 -			free(rcpt);
   8.873 -			_session->gpgme_data_release(plain);
   8.874 -			_session->gpgme_data_release(cipher);
   8.875 -			return PEP_OUT_OF_MEMORY;
   8.876 -		case GPG_ERR_NO_ERROR:
   8.877 -            if (i == 0) {
   8.878 -                gpgme_error_t _gpgme_error = _session->gpgme_signers_add(_session->ctx, rcpt[0]);
   8.879 -                assert(_gpgme_error == GPG_ERR_NO_ERROR);
   8.880 -            }
   8.881 -			break;
   8.882 -		case GPG_ERR_EOF:
   8.883 -            for (j=0; j<i; j++)
   8.884 -                _session->gpgme_key_unref(rcpt[j]);
   8.885 -			free(rcpt);
   8.886 -			_session->gpgme_data_release(plain);
   8.887 -			_session->gpgme_data_release(cipher);
   8.888 -			return PEP_KEY_NOT_FOUND;
   8.889 -		case GPG_ERR_AMBIGUOUS_NAME:
   8.890 -            for (j=0; j<i; j++)
   8.891 -                _session->gpgme_key_unref(rcpt[j]);
   8.892 -			free(rcpt);
   8.893 -			_session->gpgme_data_release(plain);
   8.894 -			_session->gpgme_data_release(cipher);
   8.895 -			return PEP_KEY_HAS_AMBIG_NAME;
   8.896 -        default: // GPG_ERR_INV_VALUE if CTX or R_KEY is not a valid pointer or
   8.897 -                 // FPR is not a fingerprint or key ID
   8.898 -            for (j=0; j<i; j++)
   8.899 -                _session->gpgme_key_unref(rcpt[j]);
   8.900 -			free(rcpt);
   8.901 -			_session->gpgme_data_release(plain);
   8.902 -			_session->gpgme_data_release(cipher);
   8.903 -			return PEP_GET_KEY_FAILED;
   8.904 -		}
   8.905 -	}
   8.906 -
   8.907 -	// TODO: remove that and replace with proper key management
   8.908 -	flags  = GPGME_ENCRYPT_ALWAYS_TRUST;
   8.909 -
   8.910 -    gpgme_error = _session->gpgme_op_encrypt_sign(_session->ctx, rcpt, flags,
   8.911 -            plain, cipher);
   8.912 -	switch (gpgme_error) {
   8.913 -	case GPG_ERR_NO_ERROR:
   8.914 -		{
   8.915 -            char *_buffer = NULL;
   8.916 -			size_t reading;
   8.917 -            size_t length = _session->gpgme_data_seek(cipher, 0, SEEK_END);
   8.918 -            assert(length != -1);
   8.919 -			_session->gpgme_data_seek(cipher, 0, SEEK_SET);
   8.920 -
   8.921 -			// TODO: make things less memory consuming
   8.922 -            // the following algorithm allocates a buffer for the complete text
   8.923 -
   8.924 -            _buffer = (char *) malloc(length + 1);
   8.925 -            assert(_buffer);
   8.926 -            if (_buffer == NULL) {
   8.927 -                for (j=0; j<stringlist_length(keylist); j++)
   8.928 -                    _session->gpgme_key_unref(rcpt[j]);
   8.929 -                free(rcpt);
   8.930 -                _session->gpgme_data_release(plain);
   8.931 -                _session->gpgme_data_release(cipher);
   8.932 -                return PEP_OUT_OF_MEMORY;
   8.933 -            }
   8.934 -
   8.935 -            reading = _session->gpgme_data_read(cipher, _buffer, length);
   8.936 -			assert(length == reading);
   8.937 -
   8.938 -			*ctext = _buffer;
   8.939 -			*csize = reading;
   8.940 -			(*ctext)[*csize] = 0; // safeguard for naive users
   8.941 -			result = PEP_STATUS_OK;
   8.942 -			break;
   8.943 -		}
   8.944 -	default:
   8.945 -		result = PEP_UNKNOWN_ERROR;
   8.946 -	}
   8.947 -
   8.948 -    for (j=0; j<stringlist_length(keylist); j++)
   8.949 -        _session->gpgme_key_unref(rcpt[j]);
   8.950 -	free(rcpt);
   8.951 -	_session->gpgme_data_release(plain);
   8.952 -	_session->gpgme_data_release(cipher);
   8.953 -	return result;
   8.954 -}
   8.955 -
   8.956  DYNAMIC_API PEP_STATUS log_event(
   8.957          PEP_SESSION session, const char *title, const char *entity,
   8.958          const char *description, const char *comment
   8.959 @@ -1526,402 +672,6 @@
   8.960  		return PEP_COMMIT_FAILED;
   8.961  }
   8.962  
   8.963 -DYNAMIC_API PEP_STATUS generate_keypair(
   8.964 -        PEP_SESSION session, pEp_identity *identity
   8.965 -    )
   8.966 -{
   8.967 -	pEpSession *_session = (pEpSession *) session;
   8.968 -	gpgme_error_t gpgme_error;
   8.969 -    char *parms;
   8.970 -    const char *template =
   8.971 -        "<GnupgKeyParms format=\"internal\">\n"
   8.972 -        "Key-Type: RSA\n"
   8.973 -        "Key-Length: 4096\n"
   8.974 -        "Name-Real: %s\n"
   8.975 -        "Name-Email: %s\n"
   8.976 -        /* "Passphrase: %s\n" */
   8.977 -        "Expire-Date: 1y\n"
   8.978 -        "</GnupgKeyParms>\n";
   8.979 -    int result;
   8.980 -    gpgme_genkey_result_t gpgme_genkey_result;
   8.981 -
   8.982 -    assert(session);
   8.983 -    assert(identity);
   8.984 -    assert(identity->address);
   8.985 -    assert(identity->fpr == NULL);
   8.986 -    assert(identity->username);
   8.987 -    
   8.988 -    parms = calloc(1, PARMS_MAX);
   8.989 -    assert(parms);
   8.990 -    if (parms == NULL)
   8.991 -        return PEP_OUT_OF_MEMORY;
   8.992 -
   8.993 -    result = snprintf(parms, PARMS_MAX, template, identity->username,
   8.994 -            identity->address); // , _session->passphrase);
   8.995 -    assert(result < PARMS_MAX);
   8.996 -    if (result >= PARMS_MAX) {
   8.997 -        free(parms);
   8.998 -        return PEP_BUFFER_TOO_SMALL;
   8.999 -    }
  8.1000 -
  8.1001 -    gpgme_error = _session->gpgme_op_genkey(_session->ctx, parms, NULL, NULL);
  8.1002 -    free(parms);
  8.1003 -
  8.1004 -    switch (gpgme_error) {
  8.1005 -    case GPG_ERR_NO_ERROR:
  8.1006 -        break;
  8.1007 -    case GPG_ERR_INV_VALUE:
  8.1008 -        return PEP_ILLEGAL_VALUE;
  8.1009 -    case GPG_ERR_GENERAL:
  8.1010 -        return PEP_CANNOT_CREATE_KEY;
  8.1011 -    default:
  8.1012 -        assert(0);
  8.1013 -        return PEP_UNKNOWN_ERROR;
  8.1014 -    }
  8.1015 -
  8.1016 -    gpgme_genkey_result = _session->gpgme_op_genkey_result(_session->ctx);
  8.1017 -    assert(gpgme_genkey_result);
  8.1018 -    assert(gpgme_genkey_result->fpr);
  8.1019 -
  8.1020 -    identity->fpr = strdup(gpgme_genkey_result->fpr);
  8.1021 -
  8.1022 -    return PEP_STATUS_OK;
  8.1023 -}
  8.1024 -
  8.1025 -PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  8.1026 -{
  8.1027 -	pEpSession *_session = (pEpSession *) session;
  8.1028 -	gpgme_error_t gpgme_error;
  8.1029 -    gpgme_key_t key;
  8.1030 -
  8.1031 -    assert(session);
  8.1032 -    assert(fpr);
  8.1033 -
  8.1034 -    gpgme_error = _session->gpgme_get_key(_session->ctx, fpr, &key, 0);
  8.1035 -    assert(gpgme_error != GPG_ERR_ENOMEM);
  8.1036 -    switch (gpgme_error) {
  8.1037 -    case GPG_ERR_NO_ERROR:
  8.1038 -        break;
  8.1039 -    case GPG_ERR_EOF:
  8.1040 -        return PEP_KEY_NOT_FOUND;
  8.1041 -    case GPG_ERR_INV_VALUE:
  8.1042 -        return PEP_ILLEGAL_VALUE;
  8.1043 -    case GPG_ERR_AMBIGUOUS_NAME:
  8.1044 -        return PEP_KEY_HAS_AMBIG_NAME;
  8.1045 -    case GPG_ERR_ENOMEM:
  8.1046 -        return PEP_OUT_OF_MEMORY;
  8.1047 -    default:
  8.1048 -        assert(0);
  8.1049 -        return PEP_UNKNOWN_ERROR;
  8.1050 -    }
  8.1051 -
  8.1052 -    gpgme_error = _session->gpgme_op_delete(_session->ctx, key, 1);
  8.1053 -    _session->gpgme_key_unref(key);
  8.1054 -    switch (gpgme_error) {
  8.1055 -    case GPG_ERR_NO_ERROR:
  8.1056 -        break;
  8.1057 -    case GPG_ERR_INV_VALUE:
  8.1058 -        assert(0);
  8.1059 -        return PEP_UNKNOWN_ERROR;
  8.1060 -    case GPG_ERR_NO_PUBKEY:
  8.1061 -        assert(0);
  8.1062 -        return PEP_KEY_NOT_FOUND;
  8.1063 -    case GPG_ERR_AMBIGUOUS_NAME:
  8.1064 -        assert(0);
  8.1065 -        return PEP_KEY_HAS_AMBIG_NAME;
  8.1066 -    default:
  8.1067 -        assert(0);
  8.1068 -        return PEP_UNKNOWN_ERROR;
  8.1069 -    }
  8.1070 -
  8.1071 -    return PEP_STATUS_OK;
  8.1072 -}
  8.1073 -
  8.1074 -PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
  8.1075 -{
  8.1076 -	pEpSession *_session = (pEpSession *) session;
  8.1077 -	gpgme_error_t gpgme_error;
  8.1078 -    gpgme_data_t dh;
  8.1079 -
  8.1080 -    assert(session);
  8.1081 -    assert(key_data);
  8.1082 -
  8.1083 -    gpgme_error = _session->gpgme_data_new_from_mem(&dh, key_data, size, 0);
  8.1084 -    assert(gpgme_error != GPG_ERR_ENOMEM);
  8.1085 -    switch (gpgme_error) {
  8.1086 -    case GPG_ERR_NO_ERROR:
  8.1087 -        break;
  8.1088 -    case GPG_ERR_ENOMEM:
  8.1089 -        return PEP_OUT_OF_MEMORY;
  8.1090 -    case GPG_ERR_INV_VALUE:
  8.1091 -        assert(0);
  8.1092 -        return PEP_UNKNOWN_ERROR;
  8.1093 -    default:
  8.1094 -        assert(0);
  8.1095 -        return PEP_UNKNOWN_ERROR;
  8.1096 -    }
  8.1097 -
  8.1098 -    gpgme_error = _session->gpgme_op_import(_session->ctx, dh);
  8.1099 -    switch (gpgme_error) {
  8.1100 -    case GPG_ERR_NO_ERROR:
  8.1101 -        break;
  8.1102 -    case GPG_ERR_INV_VALUE:
  8.1103 -        assert(0);
  8.1104 -        _session->gpgme_data_release(dh);
  8.1105 -        return PEP_UNKNOWN_ERROR;
  8.1106 -    case GPG_ERR_NO_DATA:
  8.1107 -        _session->gpgme_data_release(dh);
  8.1108 -        return PEP_ILLEGAL_VALUE;
  8.1109 -    default:
  8.1110 -        assert(0);
  8.1111 -        _session->gpgme_data_release(dh);
  8.1112 -        return PEP_UNKNOWN_ERROR;
  8.1113 -    }
  8.1114 -
  8.1115 -    _session->gpgme_data_release(dh);
  8.1116 -    return PEP_STATUS_OK;
  8.1117 -}
  8.1118 -
  8.1119 -PEP_STATUS export_key(
  8.1120 -        PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  8.1121 -    )
  8.1122 -{
  8.1123 -	pEpSession *_session = (pEpSession *) session;
  8.1124 -	gpgme_error_t gpgme_error;
  8.1125 -    gpgme_data_t dh;
  8.1126 -    size_t _size;
  8.1127 -    char *buffer;
  8.1128 -    int reading;
  8.1129 -
  8.1130 -    assert(session);
  8.1131 -    assert(fpr);
  8.1132 -    assert(key_data);
  8.1133 -    assert(size);
  8.1134 -
  8.1135 -    gpgme_error = _session->gpgme_data_new(&dh);
  8.1136 -    assert(gpgme_error != GPG_ERR_ENOMEM);
  8.1137 -    switch (gpgme_error) {
  8.1138 -    case GPG_ERR_NO_ERROR:
  8.1139 -        break;
  8.1140 -    case GPG_ERR_ENOMEM:
  8.1141 -        return PEP_OUT_OF_MEMORY;
  8.1142 -    case GPG_ERR_INV_VALUE:
  8.1143 -        assert(0);
  8.1144 -        return PEP_UNKNOWN_ERROR;
  8.1145 -    default:
  8.1146 -        assert(0);
  8.1147 -        return PEP_UNKNOWN_ERROR;
  8.1148 -    }
  8.1149 -
  8.1150 -    gpgme_error = _session->gpgme_op_export(_session->ctx, fpr,
  8.1151 -            GPGME_EXPORT_MODE_MINIMAL, dh);
  8.1152 -    switch (gpgme_error) {
  8.1153 -    case GPG_ERR_NO_ERROR:
  8.1154 -        break;
  8.1155 -    case GPG_ERR_EOF:
  8.1156 -        _session->gpgme_data_release(dh);
  8.1157 -        return PEP_KEY_NOT_FOUND;
  8.1158 -    case GPG_ERR_INV_VALUE:
  8.1159 -        assert(0);
  8.1160 -        _session->gpgme_data_release(dh);
  8.1161 -        return PEP_UNKNOWN_ERROR;
  8.1162 -    default:
  8.1163 -        assert(0);
  8.1164 -        _session->gpgme_data_release(dh);
  8.1165 -        return PEP_UNKNOWN_ERROR;
  8.1166 -    };
  8.1167 -
  8.1168 -    _size = _session->gpgme_data_seek(dh, 0, SEEK_END);
  8.1169 -    assert(_size != -1);
  8.1170 -    _session->gpgme_data_seek(dh, 0, SEEK_SET);
  8.1171 -
  8.1172 -    buffer = malloc(_size + 1);
  8.1173 -    assert(buffer);
  8.1174 -    if (buffer == NULL) {
  8.1175 -        _session->gpgme_data_release(dh);
  8.1176 -        return PEP_OUT_OF_MEMORY;
  8.1177 -    }
  8.1178 -
  8.1179 -    reading = _session->gpgme_data_read(dh, buffer, _size);
  8.1180 -    assert(_size == reading);
  8.1181 -
  8.1182 -    // safeguard for the naive user
  8.1183 -    buffer[_size] = 0;
  8.1184 -
  8.1185 -    *key_data = buffer;
  8.1186 -    *size = _size;
  8.1187 -
  8.1188 -    _session->gpgme_data_release(dh);
  8.1189 -    return PEP_STATUS_OK;
  8.1190 -}
  8.1191 -
  8.1192 -static void _switch_mode(pEpSession *_session, gpgme_keylist_mode_t remove_mode,
  8.1193 -        gpgme_keylist_mode_t add_mode)
  8.1194 -{
  8.1195 -	gpgme_error_t gpgme_error;
  8.1196 -    gpgme_keylist_mode_t mode;
  8.1197 -
  8.1198 -    mode = _session->gpgme_get_keylist_mode(_session->ctx);
  8.1199 -
  8.1200 -    mode &= ~remove_mode;
  8.1201 -    mode |= add_mode;
  8.1202 -
  8.1203 -    gpgme_error = _session->gpgme_set_keylist_mode(_session->ctx, mode);
  8.1204 -    assert(gpgme_error == GPG_ERR_NO_ERROR);
  8.1205 -}
  8.1206 -
  8.1207 -PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  8.1208 -{
  8.1209 -	pEpSession *_session = (pEpSession *) session;
  8.1210 -	gpgme_error_t gpgme_error;
  8.1211 -    gpgme_key_t key;
  8.1212 -
  8.1213 -    assert(session);
  8.1214 -    assert(pattern);
  8.1215 -
  8.1216 -    _switch_mode(_session, GPGME_KEYLIST_MODE_LOCAL, GPGME_KEYLIST_MODE_EXTERN);
  8.1217 -
  8.1218 -    gpgme_error = _session->gpgme_op_keylist_start(_session->ctx, pattern, 0);
  8.1219 -    switch (gpgme_error) {
  8.1220 -    case GPG_ERR_NO_ERROR:
  8.1221 -        break;
  8.1222 -    case GPG_ERR_INV_VALUE:
  8.1223 -        assert(0);
  8.1224 -        _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
  8.1225 -                GPGME_KEYLIST_MODE_LOCAL);
  8.1226 -        return PEP_UNKNOWN_ERROR;
  8.1227 -    default:
  8.1228 -        _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
  8.1229 -                GPGME_KEYLIST_MODE_LOCAL);
  8.1230 -        return PEP_GET_KEY_FAILED;
  8.1231 -    };
  8.1232 -
  8.1233 -    do {
  8.1234 -        gpgme_error = _session->gpgme_op_keylist_next(_session->ctx, &key);
  8.1235 -        assert(gpgme_error != GPG_ERR_INV_VALUE);
  8.1236 -        switch (gpgme_error) {
  8.1237 -        case GPG_ERR_EOF:
  8.1238 -            break;
  8.1239 -        case GPG_ERR_NO_ERROR:
  8.1240 -            {
  8.1241 -                gpgme_error_t gpgme_error;
  8.1242 -                gpgme_key_t keys[2];
  8.1243 -
  8.1244 -                keys[0] = key;
  8.1245 -                keys[1] = NULL;
  8.1246 -
  8.1247 -                gpgme_error = _session->gpgme_op_import_keys(_session->ctx, keys);
  8.1248 -                _session->gpgme_key_unref(key);
  8.1249 -                assert(gpgme_error != GPG_ERR_INV_VALUE);
  8.1250 -                assert(gpgme_error != GPG_ERR_CONFLICT);
  8.1251 -            }
  8.1252 -            break;
  8.1253 -        case GPG_ERR_ENOMEM:
  8.1254 -            _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
  8.1255 -                    GPGME_KEYLIST_MODE_LOCAL);
  8.1256 -            _session->gpgme_op_keylist_end(_session->ctx);
  8.1257 -            return PEP_OUT_OF_MEMORY;
  8.1258 -        default:
  8.1259 -            // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
  8.1260 -            // reading first key
  8.1261 -#ifndef NDEBUG
  8.1262 -            fprintf(stderr, "warning: unknown result 0x%x of"
  8.1263 -                    " gpgme_op_keylist_next()\n", gpgme_error);
  8.1264 -#endif
  8.1265 -            gpgme_error = GPG_ERR_EOF;
  8.1266 -            break;
  8.1267 -        };
  8.1268 -    } while (gpgme_error != GPG_ERR_EOF);
  8.1269 -
  8.1270 -    _session->gpgme_op_keylist_end(_session->ctx);
  8.1271 -    _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
  8.1272 -            GPGME_KEYLIST_MODE_LOCAL);
  8.1273 -    return PEP_STATUS_OK;
  8.1274 -}
  8.1275 -
  8.1276 -DYNAMIC_API PEP_STATUS find_keys(
  8.1277 -        PEP_SESSION session, const char *pattern, stringlist_t **keylist
  8.1278 -    )
  8.1279 -{
  8.1280 -	pEpSession *_session = (pEpSession *) session;
  8.1281 -	gpgme_error_t gpgme_error;
  8.1282 -    gpgme_key_t key;
  8.1283 -    stringlist_t *_keylist;
  8.1284 -    char *fpr;
  8.1285 -
  8.1286 -    assert(session);
  8.1287 -    assert(pattern);
  8.1288 -    assert(keylist);
  8.1289 -
  8.1290 -    *keylist = NULL;
  8.1291 -
  8.1292 -    gpgme_error = _session->gpgme_op_keylist_start(_session->ctx, pattern, 0);
  8.1293 -    switch (gpgme_error) {
  8.1294 -    case GPG_ERR_NO_ERROR:
  8.1295 -        break;
  8.1296 -    case GPG_ERR_INV_VALUE:
  8.1297 -        assert(0);
  8.1298 -        return PEP_UNKNOWN_ERROR;
  8.1299 -    default:
  8.1300 -        return PEP_GET_KEY_FAILED;
  8.1301 -    };
  8.1302 -
  8.1303 -    _keylist = new_stringlist(NULL);
  8.1304 -    stringlist_t *_k = _keylist;
  8.1305 -
  8.1306 -    do {
  8.1307 -        gpgme_error = _session->gpgme_op_keylist_next(_session->ctx, &key);
  8.1308 -        assert(gpgme_error != GPG_ERR_INV_VALUE);
  8.1309 -        switch (gpgme_error) {
  8.1310 -        case GPG_ERR_EOF:
  8.1311 -            break;
  8.1312 -        case GPG_ERR_NO_ERROR:
  8.1313 -            assert(key);
  8.1314 -            assert(key->subkeys);
  8.1315 -            fpr = key->subkeys->fpr;
  8.1316 -            assert(fpr);
  8.1317 -            _k = stringlist_add(_k, fpr);
  8.1318 -            assert(_k);
  8.1319 -            if (_k != NULL)
  8.1320 -                break;
  8.1321 -        case GPG_ERR_ENOMEM:
  8.1322 -            free_stringlist(_keylist);
  8.1323 -            _session->gpgme_op_keylist_end(_session->ctx);
  8.1324 -            return PEP_OUT_OF_MEMORY;
  8.1325 -        default:
  8.1326 -            // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
  8.1327 -            // reading first key
  8.1328 -#ifndef NDEBUG
  8.1329 -            fprintf(stderr, "warning: unknown result 0x%x of"
  8.1330 -                    " gpgme_op_keylist_next()\n", gpgme_error);
  8.1331 -#endif
  8.1332 -            gpgme_error = GPG_ERR_EOF;
  8.1333 -            break;
  8.1334 -        };
  8.1335 -    } while (gpgme_error != GPG_ERR_EOF);
  8.1336 -
  8.1337 -    _session->gpgme_op_keylist_end(_session->ctx);
  8.1338 -    *keylist = _keylist;
  8.1339 -    return PEP_STATUS_OK;
  8.1340 -}
  8.1341 -
  8.1342 -PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  8.1343 -{
  8.1344 -	pEpSession *_session = (pEpSession *) session;
  8.1345 -	gpgme_error_t gpgme_error;
  8.1346 -
  8.1347 -    assert(session);
  8.1348 -    assert(pattern);
  8.1349 -
  8.1350 -    gpgme_error = _session->gpgme_op_export(_session->ctx, pattern,
  8.1351 -            GPGME_EXPORT_MODE_EXTERN, NULL);
  8.1352 -    assert(gpgme_error != GPG_ERR_INV_VALUE);
  8.1353 -    if (gpgme_error == GPG_ERR_NO_ERROR)
  8.1354 -        return PEP_STATUS_OK;
  8.1355 -    else
  8.1356 -        return PEP_CANNOT_SEND_KEY;
  8.1357 -}
  8.1358 -
  8.1359  void pEp_free(void *p)
  8.1360  {
  8.1361      free(p);
  8.1362 @@ -1971,105 +721,76 @@
  8.1363      return status;
  8.1364  }
  8.1365  
  8.1366 +DYNAMIC_API PEP_STATUS decrypt_and_verify(
  8.1367 +    PEP_SESSION session, const char *ctext, size_t csize,
  8.1368 +    char **ptext, size_t *psize, stringlist_t **keylist
  8.1369 +    )
  8.1370 +{
  8.1371 +    return pgp_decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
  8.1372 +}
  8.1373 +
  8.1374 +DYNAMIC_API PEP_STATUS encrypt_and_sign(
  8.1375 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  8.1376 +    size_t psize, char **ctext, size_t *csize
  8.1377 +    )
  8.1378 +{
  8.1379 +    return pgp_encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
  8.1380 +}
  8.1381 +
  8.1382 +DYNAMIC_API PEP_STATUS verify_text(
  8.1383 +    PEP_SESSION session, const char *text, size_t size,
  8.1384 +    const char *signature, size_t sig_size, stringlist_t **keylist
  8.1385 +    )
  8.1386 +{
  8.1387 +    return pgp_verify_text(session, text, size, signature, sig_size, keylist);
  8.1388 +}
  8.1389 +
  8.1390 +DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  8.1391 +{
  8.1392 +    return pgp_delete_keypair(session, fpr);
  8.1393 +}
  8.1394 +
  8.1395 +DYNAMIC_API PEP_STATUS export_key(
  8.1396 +    PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  8.1397 +    )
  8.1398 +{
  8.1399 +    return pgp_export_key(session, fpr, key_data, size);
  8.1400 +}
  8.1401 +
  8.1402 +DYNAMIC_API PEP_STATUS find_keys(
  8.1403 +    PEP_SESSION session, const char *pattern, stringlist_t **keylist
  8.1404 +    )
  8.1405 +{
  8.1406 +    return pgp_find_keys(session, pattern, keylist);
  8.1407 +}
  8.1408 +
  8.1409 +DYNAMIC_API PEP_STATUS generate_keypair(
  8.1410 +    PEP_SESSION session, pEp_identity *identity
  8.1411 +    )
  8.1412 +{
  8.1413 +    return pgp_generate_keypair(session, identity);
  8.1414 +}
  8.1415 +
  8.1416  DYNAMIC_API PEP_STATUS get_key_rating(
  8.1417      PEP_SESSION session,
  8.1418      const char *fpr,
  8.1419      PEP_comm_type *comm_type
  8.1420      )
  8.1421  {
  8.1422 -    pEpSession *_session = (pEpSession *) session;
  8.1423 -    PEP_STATUS status = PEP_STATUS_OK;
  8.1424 -    gpgme_error_t gpgme_error;
  8.1425 -    gpgme_key_t key;
  8.1426 +    return pgp_get_key_rating(session, fpr, comm_type);
  8.1427 +}
  8.1428  
  8.1429 -    assert(session);
  8.1430 -    assert(fpr);
  8.1431 -    assert(comm_type);
  8.1432 -    
  8.1433 -    *comm_type = PEP_ct_unknown;
  8.1434 +DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
  8.1435 +{
  8.1436 +    return pgp_import_key(session, key_data, size);
  8.1437 +}
  8.1438  
  8.1439 -    gpgme_error = _session->gpgme_op_keylist_start(_session->ctx, fpr, 0);
  8.1440 -    switch (gpgme_error) {
  8.1441 -    case GPG_ERR_NO_ERROR:
  8.1442 -        break;
  8.1443 -    case GPG_ERR_INV_VALUE:
  8.1444 -        assert(0);
  8.1445 -        return PEP_UNKNOWN_ERROR;
  8.1446 -    default:
  8.1447 -        return PEP_GET_KEY_FAILED;
  8.1448 -    };
  8.1449 +DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  8.1450 +{
  8.1451 +    return pgp_recv_key(session, pattern);
  8.1452 +}
  8.1453  
  8.1454 -    gpgme_error = _session->gpgme_op_keylist_next(_session->ctx, &key);
  8.1455 -    assert(gpgme_error != GPG_ERR_INV_VALUE);
  8.1456 -
  8.1457 -    if (key == NULL) {
  8.1458 -        _session->gpgme_op_keylist_end(_session->ctx);
  8.1459 -        return PEP_KEY_NOT_FOUND;
  8.1460 -    }
  8.1461 -
  8.1462 -    switch (key->protocol) {
  8.1463 -    case GPGME_PROTOCOL_OpenPGP:
  8.1464 -    case GPGME_PROTOCOL_DEFAULT:
  8.1465 -        *comm_type = PEP_ct_OpenPGP_unconfirmed;
  8.1466 -        break;
  8.1467 -    case GPGME_PROTOCOL_CMS:
  8.1468 -        *comm_type = PEP_ct_CMS_unconfirmed;
  8.1469 -        break;
  8.1470 -    default:
  8.1471 -        *comm_type = PEP_ct_unknown;
  8.1472 -        _session->gpgme_op_keylist_end(_session->ctx);
  8.1473 -        return PEP_STATUS_OK;
  8.1474 -    }
  8.1475 -
  8.1476 -    switch (gpgme_error) {
  8.1477 -    case GPG_ERR_EOF:
  8.1478 -        break;
  8.1479 -    case GPG_ERR_NO_ERROR:
  8.1480 -        assert(key);
  8.1481 -        assert(key->subkeys);
  8.1482 -        for (gpgme_subkey_t sk = key->subkeys; sk != NULL; sk = sk->next) {
  8.1483 -            if (sk->length < 1024)
  8.1484 -                *comm_type = PEP_ct_key_too_short;
  8.1485 -            else if (
  8.1486 -                (
  8.1487 -                       (sk->pubkey_algo == GPGME_PK_RSA)
  8.1488 -                    || (sk->pubkey_algo == GPGME_PK_RSA_E)
  8.1489 -                    || (sk->pubkey_algo == GPGME_PK_RSA_S)
  8.1490 -                )
  8.1491 -                && sk->length == 1024
  8.1492 -            )
  8.1493 -                *comm_type = PEP_ct_OpenPGP_1024_RSA_unconfirmed;
  8.1494 -
  8.1495 -            if (sk->invalid) {
  8.1496 -                *comm_type = PEP_ct_key_b0rken;
  8.1497 -                break;
  8.1498 -            }
  8.1499 -            if (sk->expired) {
  8.1500 -                *comm_type = PEP_ct_key_expired;
  8.1501 -                break;
  8.1502 -            }
  8.1503 -            if (sk->revoked) {
  8.1504 -                *comm_type = PEP_ct_key_revoked;
  8.1505 -                break;
  8.1506 -            }
  8.1507 -        }
  8.1508 -        break;
  8.1509 -    case GPG_ERR_ENOMEM:
  8.1510 -        _session->gpgme_op_keylist_end(_session->ctx);
  8.1511 -        *comm_type = PEP_ct_unknown;
  8.1512 -        return PEP_OUT_OF_MEMORY;
  8.1513 -    default:
  8.1514 -        // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
  8.1515 -        // reading first key
  8.1516 -#ifndef NDEBUG
  8.1517 -        fprintf(stderr, "warning: unknown result 0x%x of"
  8.1518 -            " gpgme_op_keylist_next()\n", gpgme_error);
  8.1519 -#endif
  8.1520 -        gpgme_error = GPG_ERR_EOF;
  8.1521 -        break;
  8.1522 -    };
  8.1523 -
  8.1524 -    _session->gpgme_op_keylist_end(_session->ctx);
  8.1525 -
  8.1526 -    return status;
  8.1527 +DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  8.1528 +{
  8.1529 +    return pgp_send_key(session, pattern);
  8.1530  }
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/pEp_internal.h	Mon Sep 01 17:44:19 2014 +0200
     9.3 @@ -0,0 +1,80 @@
     9.4 +#define PEP_ENGINE_VERSION "0.5.0"
     9.5 +
     9.6 +// this is 20 safewords with 79 chars max
     9.7 +#define MAX_SAFEWORDS_SPACE (20 * 80)
     9.8 +
     9.9 +// XML parameters string
    9.10 +#define PARMS_MAX 32768
    9.11 +
    9.12 +// maximum busy wait time in ms
    9.13 +#define BUSY_WAIT_TIME 5000
    9.14 +
    9.15 +// maximum line length for reading gpg.conf
    9.16 +#define MAX_LINELENGTH 1024
    9.17 +
    9.18 +// default keyserver
    9.19 +#define DEFAULT_KEYSERVER "hkp://keys.gnupg.net"
    9.20 +
    9.21 +#ifdef WIN32
    9.22 +#include "platform_windows.h"
    9.23 +#define LOCAL_DB windoze_local_db()
    9.24 +#define SYSTEM_DB windoze_system_db()
    9.25 +#define LIBGPGME "libgpgme-11.dll"
    9.26 +#else // UNIX
    9.27 +#define _POSIX_C_SOURCE 200809L
    9.28 +#include <dlfcn.h>
    9.29 +#include "platform_unix.h"
    9.30 +#define LOCAL_DB unix_local_db()
    9.31 +#ifndef SYSTEM_DB
    9.32 +#define SYSTEM_DB "/usr/share/pEp/system.db"
    9.33 +#endif
    9.34 +#ifndef LIBGPGME
    9.35 +#define LIBGPGME "libgpgme-pthread.so"
    9.36 +#endif
    9.37 +#endif
    9.38 +
    9.39 +#include <locale.h>
    9.40 +#include <stdlib.h>
    9.41 +#include <string.h>
    9.42 +#include <assert.h>
    9.43 +#include <stdio.h>
    9.44 +
    9.45 +#ifndef NDEBUG
    9.46 +#include <stdio.h>
    9.47 +#endif
    9.48 +
    9.49 +#ifndef NO_GPG
    9.50 +#include <gpgme.h>
    9.51 +#endif
    9.52 +
    9.53 +#include "sqlite3.h"
    9.54 +
    9.55 +#define _EXPORT_PEP_ENGINE_DLL
    9.56 +#include "pEpEngine.h"
    9.57 +#ifndef NO_GPG
    9.58 +#include "pgp_gpg_internal.h"
    9.59 +#endif
    9.60 +
    9.61 +#define NOT_IMPLEMENTED assert(0)
    9.62 +
    9.63 +typedef struct {
    9.64 +    const char *version;
    9.65 +
    9.66 +#ifndef NO_GPG
    9.67 +    void *gpgme;
    9.68 +    struct gpg_s gpg;
    9.69 +    gpgme_ctx_t ctx;
    9.70 +#endif
    9.71 +
    9.72 +    sqlite3 *db;
    9.73 +    sqlite3 *system_db;
    9.74 +
    9.75 +    sqlite3_stmt *log;
    9.76 +    sqlite3_stmt *safeword;
    9.77 +    sqlite3_stmt *get_identity;
    9.78 +    sqlite3_stmt *set_person;
    9.79 +    sqlite3_stmt *set_pgp_keypair;
    9.80 +    sqlite3_stmt *set_identity;
    9.81 +    sqlite3_stmt *set_trust;
    9.82 +    sqlite3_stmt *get_trust;
    9.83 +} pEpSession;
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/pgp_gpg.c	Mon Sep 01 17:44:19 2014 +0200
    10.3 @@ -0,0 +1,1202 @@
    10.4 +#include "pgp_gpg.h"
    10.5 +#include "pEp_internal.h"
    10.6 +
    10.7 +static bool ensure_keyserver()
    10.8 +{
    10.9 +    static char buf[MAX_LINELENGTH];
   10.10 +    int n;
   10.11 +    FILE *f = fopen(gpg_conf(), "r");
   10.12 +
   10.13 +    if (f != NULL) {
   10.14 +        while (!feof(f)) {
   10.15 +            char * s = fgets(buf, MAX_LINELENGTH, f);
   10.16 +            if (s && !feof(f)) {
   10.17 +                char * t = strtok(s, " ");
   10.18 +                if (t && strcmp(t, "keyserver") == 0) {
   10.19 +                    fclose(f);
   10.20 +                    return true;
   10.21 +                }
   10.22 +            }
   10.23 +        }
   10.24 +        f = freopen(gpg_conf(), "a", f);
   10.25 +    }
   10.26 +    else {
   10.27 +        f = fopen(gpg_conf(), "w");
   10.28 +    }
   10.29 +
   10.30 +    assert(f);
   10.31 +    if (f == NULL)
   10.32 +        return false;
   10.33 +
   10.34 +    n = fprintf(f, "keyserver %s\n", DEFAULT_KEYSERVER);
   10.35 +    assert(n >= 0);
   10.36 +    fclose(f);
   10.37 +
   10.38 +    return true;
   10.39 +}
   10.40 +
   10.41 +PEP_STATUS pgp_init(PEP_SESSION session)
   10.42 +{
   10.43 +    pEpSession *_session = (pEpSession *) session;
   10.44 +    gpgme_error_t gpgme_error;
   10.45 +    bool bResult = ensure_keyserver();
   10.46 +    assert(bResult);
   10.47 +
   10.48 +    _session->gpgme = dlopen(LIBGPGME, RTLD_LAZY);
   10.49 +    if (_session->gpgme == NULL) {
   10.50 +        free(_session);
   10.51 +        return PEP_INIT_CANNOT_LOAD_GPGME;
   10.52 +    }
   10.53 +
   10.54 +    memset(&(_session->gpg), 0, sizeof(struct gpg_s));
   10.55 +
   10.56 +    _session->gpg.gpgme_set_locale
   10.57 +        = (gpgme_set_locale_t) (intptr_t) dlsym(_session->gpgme,
   10.58 +        "gpgme_set_locale");
   10.59 +    assert(_session->gpg.gpgme_set_locale);
   10.60 +
   10.61 +    _session->gpg.gpgme_check
   10.62 +        = (gpgme_check_version_t) (intptr_t) dlsym(_session->gpgme,
   10.63 +        "gpgme_check_version");
   10.64 +    assert(_session->gpg.gpgme_check);
   10.65 +
   10.66 +    _session->gpg.gpgme_new
   10.67 +        = (gpgme_new_t) (intptr_t) dlsym(_session->gpgme, "gpgme_new");
   10.68 +    assert(_session->gpg.gpgme_new);
   10.69 +
   10.70 +    _session->gpg.gpgme_release
   10.71 +        = (gpgme_release_t) (intptr_t) dlsym(_session->gpgme, "gpgme_release");
   10.72 +    assert(_session->gpg.gpgme_release);
   10.73 +
   10.74 +    _session->gpg.gpgme_set_protocol
   10.75 +        = (gpgme_set_protocol_t) (intptr_t) dlsym(_session->gpgme,
   10.76 +        "gpgme_set_protocol");
   10.77 +    assert(_session->gpg.gpgme_set_protocol);
   10.78 +
   10.79 +    _session->gpg.gpgme_set_armor
   10.80 +        = (gpgme_set_armor_t) (intptr_t) dlsym(_session->gpgme,
   10.81 +        "gpgme_set_armor");
   10.82 +    assert(_session->gpg.gpgme_set_armor);
   10.83 +
   10.84 +    _session->gpg.gpgme_data_new
   10.85 +        = (gpgme_data_new_t) (intptr_t) dlsym(_session->gpgme,
   10.86 +        "gpgme_data_new");
   10.87 +    assert(_session->gpg.gpgme_data_new);
   10.88 +
   10.89 +    _session->gpg.gpgme_data_new_from_mem
   10.90 +        = (gpgme_data_new_from_mem_t) (intptr_t) dlsym(_session->gpgme,
   10.91 +        "gpgme_data_new_from_mem");
   10.92 +    assert(_session->gpg.gpgme_data_new_from_mem);
   10.93 +
   10.94 +    _session->gpg.gpgme_data_release
   10.95 +        = (gpgme_data_release_t) (intptr_t) dlsym(_session->gpgme,
   10.96 +        "gpgme_data_release");
   10.97 +    assert(_session->gpg.gpgme_data_release);
   10.98 +
   10.99 +    _session->gpg.gpgme_data_identify
  10.100 +        = (gpgme_data_identify_t) (intptr_t) dlsym(_session->gpgme,
  10.101 +        "gpgme_data_identify");
  10.102 +    assert(_session->gpg.gpgme_data_identify);
  10.103 +    _session->gpg.gpgme_data_seek
  10.104 +        = (gpgme_data_seek_t) (intptr_t) dlsym(_session->gpgme,
  10.105 +        "gpgme_data_seek");
  10.106 +    assert(_session->gpg.gpgme_data_seek);
  10.107 +
  10.108 +    _session->gpg.gpgme_data_read
  10.109 +        = (gpgme_data_read_t) (intptr_t) dlsym(_session->gpgme,
  10.110 +        "gpgme_data_read");
  10.111 +    assert(_session->gpg.gpgme_data_read);
  10.112 +
  10.113 +    _session->gpg.gpgme_op_decrypt
  10.114 +        = (gpgme_op_decrypt_t) (intptr_t) dlsym(_session->gpgme,
  10.115 +        "gpgme_op_decrypt");
  10.116 +    assert(_session->gpg.gpgme_op_decrypt);
  10.117 +
  10.118 +    _session->gpg.gpgme_op_verify
  10.119 +        = (gpgme_op_verify_t) (intptr_t) dlsym(_session->gpgme,
  10.120 +        "gpgme_op_verify");
  10.121 +    assert(_session->gpg.gpgme_op_verify);
  10.122 +
  10.123 +    _session->gpg.gpgme_op_decrypt_verify
  10.124 +        = (gpgme_op_decrypt_verify_t) (intptr_t) dlsym(_session->gpgme,
  10.125 +        "gpgme_op_decrypt_verify");
  10.126 +    assert(_session->gpg.gpgme_op_decrypt_verify);
  10.127 +
  10.128 +    _session->gpg.gpgme_op_decrypt_result
  10.129 +        = (gpgme_op_decrypt_result_t) (intptr_t) dlsym(_session->gpgme,
  10.130 +        "gpgme_op_decrypt_result");
  10.131 +    assert(_session->gpg.gpgme_op_decrypt_result);
  10.132 +
  10.133 +    _session->gpg.gpgme_op_encrypt_sign
  10.134 +        = (gpgme_op_encrypt_sign_t) (intptr_t) dlsym(_session->gpgme,
  10.135 +        "gpgme_op_encrypt_sign");
  10.136 +    assert(_session->gpg.gpgme_op_encrypt_sign);
  10.137 +
  10.138 +    _session->gpg.gpgme_op_verify_result
  10.139 +        = (gpgme_op_verify_result_t) (intptr_t) dlsym(_session->gpgme,
  10.140 +        "gpgme_op_verify_result");
  10.141 +    assert(_session->gpg.gpgme_op_verify_result);
  10.142 +
  10.143 +    _session->gpg.gpgme_signers_clear
  10.144 +        = (gpgme_signers_clear_t) (intptr_t) dlsym(_session->gpgme,
  10.145 +        "gpgme_signers_clear");
  10.146 +    assert(_session->gpg.gpgme_signers_clear);
  10.147 +
  10.148 +    _session->gpg.gpgme_signers_add
  10.149 +        = (gpgme_signers_add_t) (intptr_t) dlsym(_session->gpgme,
  10.150 +        "gpgme_signers_add");
  10.151 +    assert(_session->gpg.gpgme_signers_add);
  10.152 +    _session->gpg.gpgme_get_key
  10.153 +        = (gpgme_get_key_t) (intptr_t) dlsym(_session->gpgme, "gpgme_get_key");
  10.154 +    assert(_session->gpg.gpgme_get_key);
  10.155 +
  10.156 +    _session->gpg.gpgme_op_genkey
  10.157 +        = (gpgme_op_genkey_t) (intptr_t) dlsym(_session->gpgme,
  10.158 +        "gpgme_op_genkey");
  10.159 +    assert(_session->gpg.gpgme_op_genkey);
  10.160 +
  10.161 +    _session->gpg.gpgme_op_genkey_result
  10.162 +        = (gpgme_op_genkey_result_t) (intptr_t) dlsym(_session->gpgme,
  10.163 +        "gpgme_op_genkey_result");
  10.164 +    assert(_session->gpg.gpgme_op_genkey_result);
  10.165 +
  10.166 +    _session->gpg.gpgme_op_delete = (gpgme_op_delete_t) (intptr_t)
  10.167 +        dlsym(_session->gpgme, "gpgme_op_delete");
  10.168 +    assert(_session->gpg.gpgme_op_delete);
  10.169 +
  10.170 +    _session->gpg.gpgme_op_import = (gpgme_op_import_t) (intptr_t)
  10.171 +        dlsym(_session->gpgme, "gpgme_op_import");
  10.172 +    assert(_session->gpg.gpgme_op_import);
  10.173 +
  10.174 +    _session->gpg.gpgme_op_export = (gpgme_op_export_t) (intptr_t)
  10.175 +        dlsym(_session->gpgme, "gpgme_op_export");
  10.176 +    assert(_session->gpg.gpgme_op_export);
  10.177 +
  10.178 +    _session->gpg.gpgme_set_keylist_mode = (gpgme_set_keylist_mode_t) (intptr_t)
  10.179 +        dlsym(_session->gpgme, "gpgme_set_keylist_mode");
  10.180 +    assert(_session->gpg.gpgme_set_keylist_mode);
  10.181 +
  10.182 +    _session->gpg.gpgme_get_keylist_mode = (gpgme_get_keylist_mode_t) (intptr_t)
  10.183 +        dlsym(_session->gpgme, "gpgme_get_keylist_mode");
  10.184 +    assert(_session->gpg.gpgme_get_keylist_mode);
  10.185 +
  10.186 +    _session->gpg.gpgme_op_keylist_start = (gpgme_op_keylist_start_t) (intptr_t)
  10.187 +        dlsym(_session->gpgme, "gpgme_op_keylist_start");
  10.188 +    assert(_session->gpg.gpgme_op_keylist_start);
  10.189 +
  10.190 +    _session->gpg.gpgme_op_keylist_next = (gpgme_op_keylist_next_t) (intptr_t)
  10.191 +        dlsym(_session->gpgme, "gpgme_op_keylist_next");
  10.192 +    assert(_session->gpg.gpgme_op_keylist_next);
  10.193 +
  10.194 +    _session->gpg.gpgme_op_keylist_end = (gpgme_op_keylist_end_t) (intptr_t)
  10.195 +        dlsym(_session->gpgme, "gpgme_op_keylist_end");
  10.196 +    assert(_session->gpg.gpgme_op_keylist_end);
  10.197 +
  10.198 +    _session->gpg.gpgme_op_import_keys = (gpgme_op_import_keys_t) (intptr_t)
  10.199 +        dlsym(_session->gpgme, "gpgme_op_import_keys");
  10.200 +    assert(_session->gpg.gpgme_op_import_keys);
  10.201 +
  10.202 +    _session->gpg.gpgme_key_ref = (gpgme_key_ref_t) (intptr_t)
  10.203 +        dlsym(_session->gpgme, "gpgme_key_ref");
  10.204 +    assert(_session->gpg.gpgme_key_ref);
  10.205 +
  10.206 +    _session->gpg.gpgme_key_unref = (gpgme_key_unref_t) (intptr_t)
  10.207 +        dlsym(_session->gpgme, "gpgme_key_unref");
  10.208 +    assert(_session->gpg.gpgme_key_unref);
  10.209 +
  10.210 +    setlocale(LC_ALL, "");
  10.211 +    _session->version = _session->gpg.gpgme_check(NULL);
  10.212 +    _session->gpg.gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
  10.213 +
  10.214 +    gpgme_error = _session->gpg.gpgme_new(&_session->ctx);
  10.215 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
  10.216 +        dlclose(_session->gpgme);
  10.217 +        free(_session);
  10.218 +        return PEP_INIT_GPGME_INIT_FAILED;
  10.219 +    }
  10.220 +
  10.221 +    gpgme_error = _session->gpg.gpgme_set_protocol(_session->ctx,
  10.222 +        GPGME_PROTOCOL_OpenPGP);
  10.223 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.224 +
  10.225 +    _session->gpg.gpgme_set_armor(_session->ctx, 1);
  10.226 +
  10.227 +    return PEP_STATUS_OK;
  10.228 +}
  10.229 +
  10.230 +void pgp_release(PEP_SESSION session)
  10.231 +{
  10.232 +    pEpSession *_session = (pEpSession *) session;
  10.233 +    if (_session->ctx)
  10.234 +        _session->gpg.gpgme_release(_session->ctx);
  10.235 +    _session->ctx = NULL;
  10.236 +    memset(&(_session->gpg), 0, sizeof(struct gpg_s));
  10.237 +    dlclose(_session->gpgme);
  10.238 +}
  10.239 +
  10.240 +PEP_STATUS pgp_decrypt_and_verify(
  10.241 +    PEP_SESSION session, const char *ctext, size_t csize,
  10.242 +    char **ptext, size_t *psize, stringlist_t **keylist
  10.243 +    )
  10.244 +{
  10.245 +    pEpSession *_session = (pEpSession *) session;
  10.246 +
  10.247 +    PEP_STATUS result;
  10.248 +    gpgme_error_t gpgme_error;
  10.249 +    gpgme_data_t cipher, plain;
  10.250 +    gpgme_data_type_t dt;
  10.251 +
  10.252 +    stringlist_t *_keylist = NULL;
  10.253 +    int i_key = 0;
  10.254 +
  10.255 +    assert(_session);
  10.256 +    assert(ctext);
  10.257 +    assert(csize);
  10.258 +    assert(ptext);
  10.259 +    assert(psize);
  10.260 +    assert(keylist);
  10.261 +
  10.262 +    *ptext = NULL;
  10.263 +    *psize = 0;
  10.264 +    *keylist = NULL;
  10.265 +
  10.266 +    gpgme_error = _session->gpg.gpgme_data_new_from_mem(&cipher, ctext, csize, 0);
  10.267 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.268 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
  10.269 +        if (gpgme_error == GPG_ERR_ENOMEM)
  10.270 +            return PEP_OUT_OF_MEMORY;
  10.271 +        else
  10.272 +            return PEP_UNKNOWN_ERROR;
  10.273 +    }
  10.274 +
  10.275 +    gpgme_error = _session->gpg.gpgme_data_new(&plain);
  10.276 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.277 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
  10.278 +        _session->gpg.gpgme_data_release(cipher);
  10.279 +        if (gpgme_error == GPG_ERR_ENOMEM)
  10.280 +            return PEP_OUT_OF_MEMORY;
  10.281 +        else
  10.282 +            return PEP_UNKNOWN_ERROR;
  10.283 +    }
  10.284 +
  10.285 +    dt = _session->gpg.gpgme_data_identify(cipher);
  10.286 +    switch (dt) {
  10.287 +    case GPGME_DATA_TYPE_PGP_SIGNED:
  10.288 +    case GPGME_DATA_TYPE_PGP_OTHER:
  10.289 +        gpgme_error = _session->gpg.gpgme_op_decrypt_verify(_session->ctx, cipher,
  10.290 +            plain);
  10.291 +        assert(gpgme_error != GPG_ERR_INV_VALUE);
  10.292 +        assert(gpgme_error != GPG_ERR_NO_DATA);
  10.293 +
  10.294 +        switch (gpgme_error) {
  10.295 +        case GPG_ERR_NO_ERROR:
  10.296 +        {
  10.297 +            gpgme_verify_result_t gpgme_verify_result;
  10.298 +            char *_buffer = NULL;
  10.299 +            size_t reading;
  10.300 +            size_t length = _session->gpg.gpgme_data_seek(plain, 0, SEEK_END);
  10.301 +            gpgme_signature_t gpgme_signature;
  10.302 +
  10.303 +            assert(length != -1);
  10.304 +            _session->gpg.gpgme_data_seek(plain, 0, SEEK_SET);
  10.305 +
  10.306 +            // TODO: make things less memory consuming
  10.307 +            // the following algorithm allocates memory for the complete
  10.308 +            // text
  10.309 +
  10.310 +            _buffer = malloc(length + 1);
  10.311 +            assert(_buffer);
  10.312 +            if (_buffer == NULL) {
  10.313 +                _session->gpg.gpgme_data_release(plain);
  10.314 +                _session->gpg.gpgme_data_release(cipher);
  10.315 +                return PEP_OUT_OF_MEMORY;
  10.316 +            }
  10.317 +
  10.318 +            reading = _session->gpg.gpgme_data_read(plain, _buffer, length);
  10.319 +            assert(length == reading);
  10.320 +
  10.321 +            gpgme_verify_result =
  10.322 +                _session->gpg.gpgme_op_verify_result(_session->ctx);
  10.323 +            assert(gpgme_verify_result);
  10.324 +            gpgme_signature = gpgme_verify_result->signatures;
  10.325 +
  10.326 +            if (gpgme_signature) {
  10.327 +                stringlist_t *k;
  10.328 +                _keylist = new_stringlist(NULL);
  10.329 +                assert(_keylist);
  10.330 +                if (_keylist == NULL) {
  10.331 +                    _session->gpg.gpgme_data_release(plain);
  10.332 +                    _session->gpg.gpgme_data_release(cipher);
  10.333 +                    free(_buffer);
  10.334 +                    return PEP_OUT_OF_MEMORY;
  10.335 +                }
  10.336 +                k = _keylist;
  10.337 +
  10.338 +                result = PEP_DECRYPTED_AND_VERIFIED;
  10.339 +                do {
  10.340 +                    switch (gpgme_signature->status) {
  10.341 +                    case GPG_ERR_NO_ERROR:
  10.342 +                        k = stringlist_add(k, gpgme_signature->fpr);
  10.343 +                        break;
  10.344 +                    case GPG_ERR_CERT_REVOKED:
  10.345 +                    case GPG_ERR_BAD_SIGNATURE:
  10.346 +                        result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
  10.347 +                        break;
  10.348 +                    case GPG_ERR_SIG_EXPIRED:
  10.349 +                    case GPG_ERR_KEY_EXPIRED:
  10.350 +                    case GPG_ERR_NO_PUBKEY:
  10.351 +                        k = stringlist_add(k, gpgme_signature->fpr);
  10.352 +                        if (result == PEP_DECRYPTED_AND_VERIFIED)
  10.353 +                            result = PEP_DECRYPTED;
  10.354 +                        break;
  10.355 +                    case GPG_ERR_GENERAL:
  10.356 +                        break;
  10.357 +                    default:
  10.358 +                        if (result == PEP_DECRYPTED_AND_VERIFIED)
  10.359 +                            result = PEP_DECRYPTED;
  10.360 +                        break;
  10.361 +                    }
  10.362 +                } while ((gpgme_signature = gpgme_signature->next));
  10.363 +            }
  10.364 +            else {
  10.365 +                result = PEP_DECRYPTED;
  10.366 +            }
  10.367 +
  10.368 +            if (result == PEP_DECRYPTED_AND_VERIFIED
  10.369 +                || result == PEP_DECRYPTED) {
  10.370 +                *ptext = _buffer;
  10.371 +                *psize = reading;
  10.372 +                (*ptext)[*psize] = 0; // safeguard for naive users
  10.373 +                *keylist = _keylist;
  10.374 +            }
  10.375 +            else {
  10.376 +                free_stringlist(_keylist);
  10.377 +                free(_buffer);
  10.378 +            }
  10.379 +            break;
  10.380 +        }
  10.381 +        case GPG_ERR_DECRYPT_FAILED:
  10.382 +            result = PEP_DECRYPT_WRONG_FORMAT;
  10.383 +            break;
  10.384 +        case GPG_ERR_BAD_PASSPHRASE:
  10.385 +            NOT_IMPLEMENTED;
  10.386 +        default:
  10.387 +        {
  10.388 +            gpgme_decrypt_result_t gpgme_decrypt_result = _session->gpg.gpgme_op_decrypt_result(_session->ctx);
  10.389 +            result = PEP_DECRYPT_NO_KEY;
  10.390 +
  10.391 +            if (gpgme_decrypt_result != NULL) {
  10.392 +                if (gpgme_decrypt_result->unsupported_algorithm)
  10.393 +                    *keylist = new_stringlist(gpgme_decrypt_result->unsupported_algorithm);
  10.394 +                else
  10.395 +                    *keylist = new_stringlist("");
  10.396 +                assert(*keylist);
  10.397 +                if (*keylist == NULL) {
  10.398 +                    result = PEP_OUT_OF_MEMORY;
  10.399 +                    break;
  10.400 +                }
  10.401 +                stringlist_t *_keylist = *keylist;
  10.402 +                for (gpgme_recipient_t r = gpgme_decrypt_result->recipients; r != NULL; r = r->next) {
  10.403 +                    _keylist = stringlist_add(_keylist, r->keyid);
  10.404 +                    assert(_keylist);
  10.405 +                    if (_keylist == NULL) {
  10.406 +                        free_stringlist(*keylist);
  10.407 +                        *keylist = NULL;
  10.408 +                        result = PEP_OUT_OF_MEMORY;
  10.409 +                        break;
  10.410 +                    }
  10.411 +                }
  10.412 +                if (result == PEP_OUT_OF_MEMORY)
  10.413 +                    break;
  10.414 +            }
  10.415 +        }
  10.416 +        }
  10.417 +        break;
  10.418 +
  10.419 +    default:
  10.420 +        result = PEP_DECRYPT_WRONG_FORMAT;
  10.421 +    }
  10.422 +
  10.423 +    _session->gpg.gpgme_data_release(plain);
  10.424 +    _session->gpg.gpgme_data_release(cipher);
  10.425 +    return result;
  10.426 +}
  10.427 +
  10.428 +PEP_STATUS pgp_verify_text(
  10.429 +    PEP_SESSION session, const char *text, size_t size,
  10.430 +    const char *signature, size_t sig_size, stringlist_t **keylist
  10.431 +    )
  10.432 +{
  10.433 +    pEpSession *_session = (pEpSession *) session;
  10.434 +
  10.435 +    PEP_STATUS result;
  10.436 +    gpgme_error_t gpgme_error;
  10.437 +    gpgme_data_t d_text, d_sig;
  10.438 +    stringlist_t *_keylist;
  10.439 +
  10.440 +    assert(session);
  10.441 +    assert(text);
  10.442 +    assert(size);
  10.443 +    assert(signature);
  10.444 +    assert(sig_size);
  10.445 +    assert(keylist);
  10.446 +
  10.447 +    *keylist = NULL;
  10.448 +
  10.449 +    gpgme_error = _session->gpg.gpgme_data_new_from_mem(&d_text, text, size, 0);
  10.450 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.451 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
  10.452 +        if (gpgme_error == GPG_ERR_ENOMEM)
  10.453 +            return PEP_OUT_OF_MEMORY;
  10.454 +        else
  10.455 +            return PEP_UNKNOWN_ERROR;
  10.456 +    }
  10.457 +
  10.458 +    gpgme_error = _session->gpg.gpgme_data_new_from_mem(&d_sig, signature, sig_size, 0);
  10.459 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.460 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
  10.461 +        _session->gpg.gpgme_data_release(d_text);
  10.462 +        if (gpgme_error == GPG_ERR_ENOMEM)
  10.463 +            return PEP_OUT_OF_MEMORY;
  10.464 +        else
  10.465 +            return PEP_UNKNOWN_ERROR;
  10.466 +    }
  10.467 +
  10.468 +    gpgme_error = _session->gpg.gpgme_op_verify(_session->ctx, d_sig, d_text, NULL);
  10.469 +    assert(gpgme_error != GPG_ERR_INV_VALUE);
  10.470 +
  10.471 +    switch (gpgme_error) {
  10.472 +    case GPG_ERR_NO_ERROR:
  10.473 +    {
  10.474 +        gpgme_verify_result_t gpgme_verify_result;
  10.475 +        gpgme_signature_t gpgme_signature;
  10.476 +
  10.477 +        gpgme_verify_result =
  10.478 +            _session->gpg.gpgme_op_verify_result(_session->ctx);
  10.479 +        assert(gpgme_verify_result);
  10.480 +        gpgme_signature = gpgme_verify_result->signatures;
  10.481 +
  10.482 +        if (gpgme_signature) {
  10.483 +            stringlist_t *k;
  10.484 +            _keylist = new_stringlist(NULL);
  10.485 +            assert(_keylist);
  10.486 +            if (_keylist == NULL) {
  10.487 +                _session->gpg.gpgme_data_release(d_text);
  10.488 +                _session->gpg.gpgme_data_release(d_sig);
  10.489 +                return PEP_OUT_OF_MEMORY;
  10.490 +            }
  10.491 +            k = _keylist;
  10.492 +
  10.493 +            result = PEP_VERIFIED;
  10.494 +            do {
  10.495 +                k = stringlist_add(k, gpgme_signature->fpr);
  10.496 +                if (k == NULL) {
  10.497 +                    free_stringlist(_keylist);
  10.498 +                    _session->gpg.gpgme_data_release(d_text);
  10.499 +                    _session->gpg.gpgme_data_release(d_sig);
  10.500 +                    return PEP_OUT_OF_MEMORY;
  10.501 +                }
  10.502 +                if (gpgme_signature->summary & GPGME_SIGSUM_RED) {
  10.503 +                    if (gpgme_signature->summary & GPGME_SIGSUM_KEY_EXPIRED
  10.504 +                        || gpgme_signature->summary & GPGME_SIGSUM_SIG_EXPIRED) {
  10.505 +                        if (result == PEP_VERIFIED
  10.506 +                            || result == PEP_VERIFIED_AND_TRUSTED)
  10.507 +                            result = PEP_UNENCRYPTED;
  10.508 +                    }
  10.509 +                    else {
  10.510 +                        result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
  10.511 +                        break;
  10.512 +                    }
  10.513 +                }
  10.514 +                else {
  10.515 +                    if (gpgme_signature->summary & GPGME_SIGSUM_VALID) {
  10.516 +                        if (result == PEP_VERIFIED)
  10.517 +                            result = PEP_VERIFIED_AND_TRUSTED;
  10.518 +                    }
  10.519 +                    if (gpgme_signature->summary & GPGME_SIGSUM_GREEN) {
  10.520 +                        // good
  10.521 +                    }
  10.522 +                    else if (gpgme_signature->summary & GPGME_SIGSUM_KEY_MISSING) {
  10.523 +                        result = PEP_VERIFY_NO_KEY;
  10.524 +                    }
  10.525 +                    else if (gpgme_signature->summary & GPGME_SIGSUM_SYS_ERROR) {
  10.526 +                        if (result == PEP_VERIFIED
  10.527 +                            || result == PEP_VERIFIED_AND_TRUSTED)
  10.528 +                            result = PEP_UNENCRYPTED;
  10.529 +                    }
  10.530 +                    else {
  10.531 +                        // do nothing
  10.532 +                    }
  10.533 +                }
  10.534 +            } while ((gpgme_signature = gpgme_signature->next));
  10.535 +            *keylist = _keylist;
  10.536 +        }
  10.537 +        else {
  10.538 +            result = PEP_UNENCRYPTED;
  10.539 +        }
  10.540 +        break;
  10.541 +    }
  10.542 +        break;
  10.543 +    case GPG_ERR_NO_DATA:
  10.544 +        result = PEP_DECRYPT_WRONG_FORMAT;
  10.545 +        break;
  10.546 +    case GPG_ERR_INV_VALUE:
  10.547 +    default:
  10.548 +        result = PEP_UNKNOWN_ERROR;
  10.549 +        break;
  10.550 +    }
  10.551 +
  10.552 +    _session->gpg.gpgme_data_release(d_text);
  10.553 +    _session->gpg.gpgme_data_release(d_sig);
  10.554 +
  10.555 +    return result;
  10.556 +}
  10.557 +
  10.558 +PEP_STATUS pgp_encrypt_and_sign(
  10.559 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  10.560 +    size_t psize, char **ctext, size_t *csize
  10.561 +    )
  10.562 +{
  10.563 +    pEpSession *_session = (pEpSession *) session;
  10.564 +
  10.565 +    PEP_STATUS result;
  10.566 +    gpgme_error_t gpgme_error;
  10.567 +    gpgme_data_t plain, cipher;
  10.568 +    gpgme_key_t *rcpt;
  10.569 +    gpgme_encrypt_flags_t flags;
  10.570 +    const stringlist_t *_keylist;
  10.571 +    int i, j;
  10.572 +
  10.573 +    assert(_session);
  10.574 +    assert(keylist);
  10.575 +    assert(ptext);
  10.576 +    assert(psize);
  10.577 +    assert(ctext);
  10.578 +    assert(csize);
  10.579 +
  10.580 +    *ctext = NULL;
  10.581 +    *csize = 0;
  10.582 +
  10.583 +    gpgme_error = _session->gpg.gpgme_data_new_from_mem(&plain, ptext, psize, 0);
  10.584 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.585 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
  10.586 +        if (gpgme_error == GPG_ERR_ENOMEM)
  10.587 +            return PEP_OUT_OF_MEMORY;
  10.588 +        else
  10.589 +            return PEP_UNKNOWN_ERROR;
  10.590 +    }
  10.591 +
  10.592 +    gpgme_error = _session->gpg.gpgme_data_new(&cipher);
  10.593 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.594 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
  10.595 +        _session->gpg.gpgme_data_release(plain);
  10.596 +        if (gpgme_error == GPG_ERR_ENOMEM)
  10.597 +            return PEP_OUT_OF_MEMORY;
  10.598 +        else
  10.599 +            return PEP_UNKNOWN_ERROR;
  10.600 +    }
  10.601 +
  10.602 +    rcpt = (gpgme_key_t *) calloc(stringlist_length(keylist) + 1,
  10.603 +        sizeof(gpgme_key_t));
  10.604 +    assert(rcpt);
  10.605 +    if (rcpt == NULL) {
  10.606 +        _session->gpg.gpgme_data_release(plain);
  10.607 +        _session->gpg.gpgme_data_release(cipher);
  10.608 +        return PEP_OUT_OF_MEMORY;
  10.609 +    }
  10.610 +
  10.611 +    _session->gpg.gpgme_signers_clear(_session->ctx);
  10.612 +
  10.613 +    for (_keylist = keylist, i = 0; _keylist != NULL; _keylist = _keylist->next, i++) {
  10.614 +        assert(_keylist->value);
  10.615 +        gpgme_error = _session->gpg.gpgme_get_key(_session->ctx, _keylist->value,
  10.616 +            &rcpt[i], 0);
  10.617 +        assert(gpgme_error != GPG_ERR_ENOMEM);
  10.618 +
  10.619 +        switch (gpgme_error) {
  10.620 +        case GPG_ERR_ENOMEM:
  10.621 +            for (j = 0; j<i; j++)
  10.622 +                _session->gpg.gpgme_key_unref(rcpt[j]);
  10.623 +            free(rcpt);
  10.624 +            _session->gpg.gpgme_data_release(plain);
  10.625 +            _session->gpg.gpgme_data_release(cipher);
  10.626 +            return PEP_OUT_OF_MEMORY;
  10.627 +        case GPG_ERR_NO_ERROR:
  10.628 +            if (i == 0) {
  10.629 +                gpgme_error_t _gpgme_error = _session->gpg.gpgme_signers_add(_session->ctx, rcpt[0]);
  10.630 +                assert(_gpgme_error == GPG_ERR_NO_ERROR);
  10.631 +            }
  10.632 +            break;
  10.633 +        case GPG_ERR_EOF:
  10.634 +            for (j = 0; j<i; j++)
  10.635 +                _session->gpg.gpgme_key_unref(rcpt[j]);
  10.636 +            free(rcpt);
  10.637 +            _session->gpg.gpgme_data_release(plain);
  10.638 +            _session->gpg.gpgme_data_release(cipher);
  10.639 +            return PEP_KEY_NOT_FOUND;
  10.640 +        case GPG_ERR_AMBIGUOUS_NAME:
  10.641 +            for (j = 0; j<i; j++)
  10.642 +                _session->gpg.gpgme_key_unref(rcpt[j]);
  10.643 +            free(rcpt);
  10.644 +            _session->gpg.gpgme_data_release(plain);
  10.645 +            _session->gpg.gpgme_data_release(cipher);
  10.646 +            return PEP_KEY_HAS_AMBIG_NAME;
  10.647 +        default: // GPG_ERR_INV_VALUE if CTX or R_KEY is not a valid pointer or
  10.648 +            // FPR is not a fingerprint or key ID
  10.649 +            for (j = 0; j<i; j++)
  10.650 +                _session->gpg.gpgme_key_unref(rcpt[j]);
  10.651 +            free(rcpt);
  10.652 +            _session->gpg.gpgme_data_release(plain);
  10.653 +            _session->gpg.gpgme_data_release(cipher);
  10.654 +            return PEP_GET_KEY_FAILED;
  10.655 +        }
  10.656 +    }
  10.657 +
  10.658 +    // TODO: remove that and replace with proper key management
  10.659 +    flags = GPGME_ENCRYPT_ALWAYS_TRUST;
  10.660 +
  10.661 +    gpgme_error = _session->gpg.gpgme_op_encrypt_sign(_session->ctx, rcpt, flags,
  10.662 +        plain, cipher);
  10.663 +    switch (gpgme_error) {
  10.664 +    case GPG_ERR_NO_ERROR:
  10.665 +    {
  10.666 +        char *_buffer = NULL;
  10.667 +        size_t reading;
  10.668 +        size_t length = _session->gpg.gpgme_data_seek(cipher, 0, SEEK_END);
  10.669 +        assert(length != -1);
  10.670 +        _session->gpg.gpgme_data_seek(cipher, 0, SEEK_SET);
  10.671 +
  10.672 +        // TODO: make things less memory consuming
  10.673 +        // the following algorithm allocates a buffer for the complete text
  10.674 +
  10.675 +        _buffer = (char *) malloc(length + 1);
  10.676 +        assert(_buffer);
  10.677 +        if (_buffer == NULL) {
  10.678 +            for (j = 0; j<stringlist_length(keylist); j++)
  10.679 +                _session->gpg.gpgme_key_unref(rcpt[j]);
  10.680 +            free(rcpt);
  10.681 +            _session->gpg.gpgme_data_release(plain);
  10.682 +            _session->gpg.gpgme_data_release(cipher);
  10.683 +            return PEP_OUT_OF_MEMORY;
  10.684 +        }
  10.685 +
  10.686 +        reading = _session->gpg.gpgme_data_read(cipher, _buffer, length);
  10.687 +        assert(length == reading);
  10.688 +
  10.689 +        *ctext = _buffer;
  10.690 +        *csize = reading;
  10.691 +        (*ctext)[*csize] = 0; // safeguard for naive users
  10.692 +        result = PEP_STATUS_OK;
  10.693 +        break;
  10.694 +    }
  10.695 +    default:
  10.696 +        result = PEP_UNKNOWN_ERROR;
  10.697 +    }
  10.698 +
  10.699 +    for (j = 0; j<stringlist_length(keylist); j++)
  10.700 +        _session->gpg.gpgme_key_unref(rcpt[j]);
  10.701 +    free(rcpt);
  10.702 +    _session->gpg.gpgme_data_release(plain);
  10.703 +    _session->gpg.gpgme_data_release(cipher);
  10.704 +    return result;
  10.705 +}
  10.706 +
  10.707 +PEP_STATUS pgp_generate_keypair(
  10.708 +    PEP_SESSION session, pEp_identity *identity
  10.709 +    )
  10.710 +{
  10.711 +    pEpSession *_session = (pEpSession *) session;
  10.712 +    gpgme_error_t gpgme_error;
  10.713 +    char *parms;
  10.714 +    const char *template =
  10.715 +        "<GnupgKeyParms format=\"internal\">\n"
  10.716 +        "Key-Type: RSA\n"
  10.717 +        "Key-Length: 4096\n"
  10.718 +        "Name-Real: %s\n"
  10.719 +        "Name-Email: %s\n"
  10.720 +        /* "Passphrase: %s\n" */
  10.721 +        "Expire-Date: 1y\n"
  10.722 +        "</GnupgKeyParms>\n";
  10.723 +    int result;
  10.724 +    gpgme_genkey_result_t gpgme_genkey_result;
  10.725 +
  10.726 +    assert(session);
  10.727 +    assert(identity);
  10.728 +    assert(identity->address);
  10.729 +    assert(identity->fpr == NULL);
  10.730 +    assert(identity->username);
  10.731 +
  10.732 +    parms = calloc(1, PARMS_MAX);
  10.733 +    assert(parms);
  10.734 +    if (parms == NULL)
  10.735 +        return PEP_OUT_OF_MEMORY;
  10.736 +
  10.737 +    result = snprintf(parms, PARMS_MAX, template, identity->username,
  10.738 +        identity->address); // , _session->passphrase);
  10.739 +    assert(result < PARMS_MAX);
  10.740 +    if (result >= PARMS_MAX) {
  10.741 +        free(parms);
  10.742 +        return PEP_BUFFER_TOO_SMALL;
  10.743 +    }
  10.744 +
  10.745 +    gpgme_error = _session->gpg.gpgme_op_genkey(_session->ctx, parms, NULL, NULL);
  10.746 +    free(parms);
  10.747 +
  10.748 +    switch (gpgme_error) {
  10.749 +    case GPG_ERR_NO_ERROR:
  10.750 +        break;
  10.751 +    case GPG_ERR_INV_VALUE:
  10.752 +        return PEP_ILLEGAL_VALUE;
  10.753 +    case GPG_ERR_GENERAL:
  10.754 +        return PEP_CANNOT_CREATE_KEY;
  10.755 +    default:
  10.756 +        assert(0);
  10.757 +        return PEP_UNKNOWN_ERROR;
  10.758 +    }
  10.759 +
  10.760 +    gpgme_genkey_result = _session->gpg.gpgme_op_genkey_result(_session->ctx);
  10.761 +    assert(gpgme_genkey_result);
  10.762 +    assert(gpgme_genkey_result->fpr);
  10.763 +
  10.764 +    identity->fpr = strdup(gpgme_genkey_result->fpr);
  10.765 +
  10.766 +    return PEP_STATUS_OK;
  10.767 +}
  10.768 +
  10.769 +PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
  10.770 +{
  10.771 +    pEpSession *_session = (pEpSession *) session;
  10.772 +    gpgme_error_t gpgme_error;
  10.773 +    gpgme_key_t key;
  10.774 +
  10.775 +    assert(session);
  10.776 +    assert(fpr);
  10.777 +
  10.778 +    gpgme_error = _session->gpg.gpgme_get_key(_session->ctx, fpr, &key, 0);
  10.779 +    assert(gpgme_error != GPG_ERR_ENOMEM);
  10.780 +    switch (gpgme_error) {
  10.781 +    case GPG_ERR_NO_ERROR:
  10.782 +        break;
  10.783 +    case GPG_ERR_EOF:
  10.784 +        return PEP_KEY_NOT_FOUND;
  10.785 +    case GPG_ERR_INV_VALUE:
  10.786 +        return PEP_ILLEGAL_VALUE;
  10.787 +    case GPG_ERR_AMBIGUOUS_NAME:
  10.788 +        return PEP_KEY_HAS_AMBIG_NAME;
  10.789 +    case GPG_ERR_ENOMEM:
  10.790 +        return PEP_OUT_OF_MEMORY;
  10.791 +    default:
  10.792 +        assert(0);
  10.793 +        return PEP_UNKNOWN_ERROR;
  10.794 +    }
  10.795 +
  10.796 +    gpgme_error = _session->gpg.gpgme_op_delete(_session->ctx, key, 1);
  10.797 +    _session->gpg.gpgme_key_unref(key);
  10.798 +    switch (gpgme_error) {
  10.799 +    case GPG_ERR_NO_ERROR:
  10.800 +        break;
  10.801 +    case GPG_ERR_INV_VALUE:
  10.802 +        assert(0);
  10.803 +        return PEP_UNKNOWN_ERROR;
  10.804 +    case GPG_ERR_NO_PUBKEY:
  10.805 +        assert(0);
  10.806 +        return PEP_KEY_NOT_FOUND;
  10.807 +    case GPG_ERR_AMBIGUOUS_NAME:
  10.808 +        assert(0);
  10.809 +        return PEP_KEY_HAS_AMBIG_NAME;
  10.810 +    default:
  10.811 +        assert(0);
  10.812 +        return PEP_UNKNOWN_ERROR;
  10.813 +    }
  10.814 +
  10.815 +    return PEP_STATUS_OK;
  10.816 +}
  10.817 +
  10.818 +PEP_STATUS pgp_import_key(PEP_SESSION session, const char *key_data, size_t size)
  10.819 +{
  10.820 +    pEpSession *_session = (pEpSession *) session;
  10.821 +    gpgme_error_t gpgme_error;
  10.822 +    gpgme_data_t dh;
  10.823 +
  10.824 +    assert(session);
  10.825 +    assert(key_data);
  10.826 +
  10.827 +    gpgme_error = _session->gpg.gpgme_data_new_from_mem(&dh, key_data, size, 0);
  10.828 +    assert(gpgme_error != GPG_ERR_ENOMEM);
  10.829 +    switch (gpgme_error) {
  10.830 +    case GPG_ERR_NO_ERROR:
  10.831 +        break;
  10.832 +    case GPG_ERR_ENOMEM:
  10.833 +        return PEP_OUT_OF_MEMORY;
  10.834 +    case GPG_ERR_INV_VALUE:
  10.835 +        assert(0);
  10.836 +        return PEP_UNKNOWN_ERROR;
  10.837 +    default:
  10.838 +        assert(0);
  10.839 +        return PEP_UNKNOWN_ERROR;
  10.840 +    }
  10.841 +
  10.842 +    gpgme_error = _session->gpg.gpgme_op_import(_session->ctx, dh);
  10.843 +    switch (gpgme_error) {
  10.844 +    case GPG_ERR_NO_ERROR:
  10.845 +        break;
  10.846 +    case GPG_ERR_INV_VALUE:
  10.847 +        assert(0);
  10.848 +        _session->gpg.gpgme_data_release(dh);
  10.849 +        return PEP_UNKNOWN_ERROR;
  10.850 +    case GPG_ERR_NO_DATA:
  10.851 +        _session->gpg.gpgme_data_release(dh);
  10.852 +        return PEP_ILLEGAL_VALUE;
  10.853 +    default:
  10.854 +        assert(0);
  10.855 +        _session->gpg.gpgme_data_release(dh);
  10.856 +        return PEP_UNKNOWN_ERROR;
  10.857 +    }
  10.858 +
  10.859 +    _session->gpg.gpgme_data_release(dh);
  10.860 +    return PEP_STATUS_OK;
  10.861 +}
  10.862 +
  10.863 +PEP_STATUS pgp_export_key(
  10.864 +    PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  10.865 +    )
  10.866 +{
  10.867 +    pEpSession *_session = (pEpSession *) session;
  10.868 +    gpgme_error_t gpgme_error;
  10.869 +    gpgme_data_t dh;
  10.870 +    size_t _size;
  10.871 +    char *buffer;
  10.872 +    int reading;
  10.873 +
  10.874 +    assert(session);
  10.875 +    assert(fpr);
  10.876 +    assert(key_data);
  10.877 +    assert(size);
  10.878 +
  10.879 +    gpgme_error = _session->gpg.gpgme_data_new(&dh);
  10.880 +    assert(gpgme_error != GPG_ERR_ENOMEM);
  10.881 +    switch (gpgme_error) {
  10.882 +    case GPG_ERR_NO_ERROR:
  10.883 +        break;
  10.884 +    case GPG_ERR_ENOMEM:
  10.885 +        return PEP_OUT_OF_MEMORY;
  10.886 +    case GPG_ERR_INV_VALUE:
  10.887 +        assert(0);
  10.888 +        return PEP_UNKNOWN_ERROR;
  10.889 +    default:
  10.890 +        assert(0);
  10.891 +        return PEP_UNKNOWN_ERROR;
  10.892 +    }
  10.893 +
  10.894 +    gpgme_error = _session->gpg.gpgme_op_export(_session->ctx, fpr,
  10.895 +        GPGME_EXPORT_MODE_MINIMAL, dh);
  10.896 +    switch (gpgme_error) {
  10.897 +    case GPG_ERR_NO_ERROR:
  10.898 +        break;
  10.899 +    case GPG_ERR_EOF:
  10.900 +        _session->gpg.gpgme_data_release(dh);
  10.901 +        return PEP_KEY_NOT_FOUND;
  10.902 +    case GPG_ERR_INV_VALUE:
  10.903 +        assert(0);
  10.904 +        _session->gpg.gpgme_data_release(dh);
  10.905 +        return PEP_UNKNOWN_ERROR;
  10.906 +    default:
  10.907 +        assert(0);
  10.908 +        _session->gpg.gpgme_data_release(dh);
  10.909 +        return PEP_UNKNOWN_ERROR;
  10.910 +    };
  10.911 +
  10.912 +    _size = _session->gpg.gpgme_data_seek(dh, 0, SEEK_END);
  10.913 +    assert(_size != -1);
  10.914 +    _session->gpg.gpgme_data_seek(dh, 0, SEEK_SET);
  10.915 +
  10.916 +    buffer = malloc(_size + 1);
  10.917 +    assert(buffer);
  10.918 +    if (buffer == NULL) {
  10.919 +        _session->gpg.gpgme_data_release(dh);
  10.920 +        return PEP_OUT_OF_MEMORY;
  10.921 +    }
  10.922 +
  10.923 +    reading = _session->gpg.gpgme_data_read(dh, buffer, _size);
  10.924 +    assert(_size == reading);
  10.925 +
  10.926 +    // safeguard for the naive user
  10.927 +    buffer[_size] = 0;
  10.928 +
  10.929 +    *key_data = buffer;
  10.930 +    *size = _size;
  10.931 +
  10.932 +    _session->gpg.gpgme_data_release(dh);
  10.933 +    return PEP_STATUS_OK;
  10.934 +}
  10.935 +
  10.936 +static void _switch_mode(pEpSession *_session, gpgme_keylist_mode_t remove_mode,
  10.937 +    gpgme_keylist_mode_t add_mode)
  10.938 +{
  10.939 +    gpgme_error_t gpgme_error;
  10.940 +    gpgme_keylist_mode_t mode;
  10.941 +
  10.942 +    mode = _session->gpg.gpgme_get_keylist_mode(_session->ctx);
  10.943 +
  10.944 +    mode &= ~remove_mode;
  10.945 +    mode |= add_mode;
  10.946 +
  10.947 +    gpgme_error = _session->gpg.gpgme_set_keylist_mode(_session->ctx, mode);
  10.948 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.949 +}
  10.950 +
  10.951 +PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
  10.952 +{
  10.953 +    pEpSession *_session = (pEpSession *) session;
  10.954 +    gpgme_error_t gpgme_error;
  10.955 +    gpgme_key_t key;
  10.956 +
  10.957 +    assert(session);
  10.958 +    assert(pattern);
  10.959 +
  10.960 +    _switch_mode(_session, GPGME_KEYLIST_MODE_LOCAL, GPGME_KEYLIST_MODE_EXTERN);
  10.961 +
  10.962 +    gpgme_error = _session->gpg.gpgme_op_keylist_start(_session->ctx, pattern, 0);
  10.963 +    switch (gpgme_error) {
  10.964 +    case GPG_ERR_NO_ERROR:
  10.965 +        break;
  10.966 +    case GPG_ERR_INV_VALUE:
  10.967 +        assert(0);
  10.968 +        _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
  10.969 +            GPGME_KEYLIST_MODE_LOCAL);
  10.970 +        return PEP_UNKNOWN_ERROR;
  10.971 +    default:
  10.972 +        _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
  10.973 +            GPGME_KEYLIST_MODE_LOCAL);
  10.974 +        return PEP_GET_KEY_FAILED;
  10.975 +    };
  10.976 +
  10.977 +    do {
  10.978 +        gpgme_error = _session->gpg.gpgme_op_keylist_next(_session->ctx, &key);
  10.979 +        assert(gpgme_error != GPG_ERR_INV_VALUE);
  10.980 +        switch (gpgme_error) {
  10.981 +        case GPG_ERR_EOF:
  10.982 +            break;
  10.983 +        case GPG_ERR_NO_ERROR:
  10.984 +        {
  10.985 +            gpgme_error_t gpgme_error;
  10.986 +            gpgme_key_t keys[2];
  10.987 +
  10.988 +            keys[0] = key;
  10.989 +            keys[1] = NULL;
  10.990 +
  10.991 +            gpgme_error = _session->gpg.gpgme_op_import_keys(_session->ctx, keys);
  10.992 +            _session->gpg.gpgme_key_unref(key);
  10.993 +            assert(gpgme_error != GPG_ERR_INV_VALUE);
  10.994 +            assert(gpgme_error != GPG_ERR_CONFLICT);
  10.995 +        }
  10.996 +            break;
  10.997 +        case GPG_ERR_ENOMEM:
  10.998 +            _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
  10.999 +                GPGME_KEYLIST_MODE_LOCAL);
 10.1000 +            _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1001 +            return PEP_OUT_OF_MEMORY;
 10.1002 +        default:
 10.1003 +            // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
 10.1004 +            // reading first key
 10.1005 +#ifndef NDEBUG
 10.1006 +            fprintf(stderr, "warning: unknown result 0x%x of"
 10.1007 +                " gpgme_op_keylist_next()\n", gpgme_error);
 10.1008 +#endif
 10.1009 +            gpgme_error = GPG_ERR_EOF;
 10.1010 +            break;
 10.1011 +        };
 10.1012 +    } while (gpgme_error != GPG_ERR_EOF);
 10.1013 +
 10.1014 +    _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1015 +    _switch_mode(_session, GPGME_KEYLIST_MODE_EXTERN,
 10.1016 +        GPGME_KEYLIST_MODE_LOCAL);
 10.1017 +    return PEP_STATUS_OK;
 10.1018 +}
 10.1019 +
 10.1020 +PEP_STATUS pgp_find_keys(
 10.1021 +    PEP_SESSION session, const char *pattern, stringlist_t **keylist
 10.1022 +    )
 10.1023 +{
 10.1024 +    pEpSession *_session = (pEpSession *) session;
 10.1025 +    gpgme_error_t gpgme_error;
 10.1026 +    gpgme_key_t key;
 10.1027 +    stringlist_t *_keylist;
 10.1028 +    char *fpr;
 10.1029 +
 10.1030 +    assert(session);
 10.1031 +    assert(pattern);
 10.1032 +    assert(keylist);
 10.1033 +
 10.1034 +    *keylist = NULL;
 10.1035 +
 10.1036 +    gpgme_error = _session->gpg.gpgme_op_keylist_start(_session->ctx, pattern, 0);
 10.1037 +    switch (gpgme_error) {
 10.1038 +    case GPG_ERR_NO_ERROR:
 10.1039 +        break;
 10.1040 +    case GPG_ERR_INV_VALUE:
 10.1041 +        assert(0);
 10.1042 +        return PEP_UNKNOWN_ERROR;
 10.1043 +    default:
 10.1044 +        return PEP_GET_KEY_FAILED;
 10.1045 +    };
 10.1046 +
 10.1047 +    _keylist = new_stringlist(NULL);
 10.1048 +    stringlist_t *_k = _keylist;
 10.1049 +
 10.1050 +    do {
 10.1051 +        gpgme_error = _session->gpg.gpgme_op_keylist_next(_session->ctx, &key);
 10.1052 +        assert(gpgme_error != GPG_ERR_INV_VALUE);
 10.1053 +        switch (gpgme_error) {
 10.1054 +        case GPG_ERR_EOF:
 10.1055 +            break;
 10.1056 +        case GPG_ERR_NO_ERROR:
 10.1057 +            assert(key);
 10.1058 +            assert(key->subkeys);
 10.1059 +            fpr = key->subkeys->fpr;
 10.1060 +            assert(fpr);
 10.1061 +            _k = stringlist_add(_k, fpr);
 10.1062 +            assert(_k);
 10.1063 +            if (_k != NULL)
 10.1064 +                break;
 10.1065 +        case GPG_ERR_ENOMEM:
 10.1066 +            free_stringlist(_keylist);
 10.1067 +            _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1068 +            return PEP_OUT_OF_MEMORY;
 10.1069 +        default:
 10.1070 +            // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
 10.1071 +            // reading first key
 10.1072 +#ifndef NDEBUG
 10.1073 +            fprintf(stderr, "warning: unknown result 0x%x of"
 10.1074 +                " gpgme_op_keylist_next()\n", gpgme_error);
 10.1075 +#endif
 10.1076 +            gpgme_error = GPG_ERR_EOF;
 10.1077 +            break;
 10.1078 +        };
 10.1079 +    } while (gpgme_error != GPG_ERR_EOF);
 10.1080 +
 10.1081 +    _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1082 +    *keylist = _keylist;
 10.1083 +    return PEP_STATUS_OK;
 10.1084 +}
 10.1085 +
 10.1086 +PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
 10.1087 +{
 10.1088 +    pEpSession *_session = (pEpSession *) session;
 10.1089 +    gpgme_error_t gpgme_error;
 10.1090 +
 10.1091 +    assert(session);
 10.1092 +    assert(pattern);
 10.1093 +
 10.1094 +    gpgme_error = _session->gpg.gpgme_op_export(_session->ctx, pattern,
 10.1095 +        GPGME_EXPORT_MODE_EXTERN, NULL);
 10.1096 +    assert(gpgme_error != GPG_ERR_INV_VALUE);
 10.1097 +    if (gpgme_error == GPG_ERR_NO_ERROR)
 10.1098 +        return PEP_STATUS_OK;
 10.1099 +    else
 10.1100 +        return PEP_CANNOT_SEND_KEY;
 10.1101 +}
 10.1102 +
 10.1103 +
 10.1104 +PEP_STATUS pgp_get_key_rating(
 10.1105 +    PEP_SESSION session,
 10.1106 +    const char *fpr,
 10.1107 +    PEP_comm_type *comm_type
 10.1108 +    )
 10.1109 +{
 10.1110 +    pEpSession *_session = (pEpSession *) session;
 10.1111 +    PEP_STATUS status = PEP_STATUS_OK;
 10.1112 +    gpgme_error_t gpgme_error;
 10.1113 +    gpgme_key_t key;
 10.1114 +
 10.1115 +    assert(session);
 10.1116 +    assert(fpr);
 10.1117 +    assert(comm_type);
 10.1118 +
 10.1119 +    *comm_type = PEP_ct_unknown;
 10.1120 +
 10.1121 +    gpgme_error = _session->gpg.gpgme_op_keylist_start(_session->ctx, fpr, 0);
 10.1122 +    switch (gpgme_error) {
 10.1123 +    case GPG_ERR_NO_ERROR:
 10.1124 +        break;
 10.1125 +    case GPG_ERR_INV_VALUE:
 10.1126 +        assert(0);
 10.1127 +        return PEP_UNKNOWN_ERROR;
 10.1128 +    default:
 10.1129 +        return PEP_GET_KEY_FAILED;
 10.1130 +    };
 10.1131 +
 10.1132 +    gpgme_error = _session->gpg.gpgme_op_keylist_next(_session->ctx, &key);
 10.1133 +    assert(gpgme_error != GPG_ERR_INV_VALUE);
 10.1134 +
 10.1135 +    if (key == NULL) {
 10.1136 +        _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1137 +        return PEP_KEY_NOT_FOUND;
 10.1138 +    }
 10.1139 +
 10.1140 +    switch (key->protocol) {
 10.1141 +    case GPGME_PROTOCOL_OpenPGP:
 10.1142 +    case GPGME_PROTOCOL_DEFAULT:
 10.1143 +        *comm_type = PEP_ct_OpenPGP_unconfirmed;
 10.1144 +        break;
 10.1145 +    case GPGME_PROTOCOL_CMS:
 10.1146 +        *comm_type = PEP_ct_CMS_unconfirmed;
 10.1147 +        break;
 10.1148 +    default:
 10.1149 +        *comm_type = PEP_ct_unknown;
 10.1150 +        _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1151 +        return PEP_STATUS_OK;
 10.1152 +    }
 10.1153 +
 10.1154 +    switch (gpgme_error) {
 10.1155 +    case GPG_ERR_EOF:
 10.1156 +        break;
 10.1157 +    case GPG_ERR_NO_ERROR:
 10.1158 +        assert(key);
 10.1159 +        assert(key->subkeys);
 10.1160 +        for (gpgme_subkey_t sk = key->subkeys; sk != NULL; sk = sk->next) {
 10.1161 +            if (sk->length < 1024)
 10.1162 +                *comm_type = PEP_ct_key_too_short;
 10.1163 +            else if (
 10.1164 +                (
 10.1165 +                (sk->pubkey_algo == GPGME_PK_RSA)
 10.1166 +                || (sk->pubkey_algo == GPGME_PK_RSA_E)
 10.1167 +                || (sk->pubkey_algo == GPGME_PK_RSA_S)
 10.1168 +                )
 10.1169 +                && sk->length == 1024
 10.1170 +                )
 10.1171 +                *comm_type = PEP_ct_OpenPGP_1024_RSA_unconfirmed;
 10.1172 +
 10.1173 +            if (sk->invalid) {
 10.1174 +                *comm_type = PEP_ct_key_b0rken;
 10.1175 +                break;
 10.1176 +            }
 10.1177 +            if (sk->expired) {
 10.1178 +                *comm_type = PEP_ct_key_expired;
 10.1179 +                break;
 10.1180 +            }
 10.1181 +            if (sk->revoked) {
 10.1182 +                *comm_type = PEP_ct_key_revoked;
 10.1183 +                break;
 10.1184 +            }
 10.1185 +        }
 10.1186 +        break;
 10.1187 +    case GPG_ERR_ENOMEM:
 10.1188 +        _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1189 +        *comm_type = PEP_ct_unknown;
 10.1190 +        return PEP_OUT_OF_MEMORY;
 10.1191 +    default:
 10.1192 +        // BUG: GPGME returns an illegal value instead of GPG_ERR_EOF after
 10.1193 +        // reading first key
 10.1194 +#ifndef NDEBUG
 10.1195 +        fprintf(stderr, "warning: unknown result 0x%x of"
 10.1196 +            " gpgme_op_keylist_next()\n", gpgme_error);
 10.1197 +#endif
 10.1198 +        gpgme_error = GPG_ERR_EOF;
 10.1199 +        break;
 10.1200 +    };
 10.1201 +
 10.1202 +    _session->gpg.gpgme_op_keylist_end(_session->ctx);
 10.1203 +
 10.1204 +    return status;
 10.1205 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/pgp_gpg.h	Mon Sep 01 17:44:19 2014 +0200
    11.3 @@ -0,0 +1,47 @@
    11.4 +#pragma once
    11.5 +
    11.6 +#include "pEpEngine.h"
    11.7 +
    11.8 +PEP_STATUS pgp_init(PEP_SESSION session);
    11.9 +void pgp_release(PEP_SESSION session);
   11.10 +
   11.11 +PEP_STATUS pgp_decrypt_and_verify(
   11.12 +    PEP_SESSION session, const char *ctext, size_t csize,
   11.13 +    char **ptext, size_t *psize, stringlist_t **keylist
   11.14 +    );
   11.15 +
   11.16 +PEP_STATUS pgp_encrypt_and_sign(
   11.17 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   11.18 +    size_t psize, char **ctext, size_t *csize
   11.19 +    );
   11.20 +
   11.21 +PEP_STATUS pgp_verify_text(
   11.22 +    PEP_SESSION session, const char *text, size_t size,
   11.23 +    const char *signature, size_t sig_size, stringlist_t **keylist
   11.24 +    );
   11.25 +
   11.26 +PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr);
   11.27 +
   11.28 +PEP_STATUS pgp_export_key(
   11.29 +    PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   11.30 +    );
   11.31 +
   11.32 +PEP_STATUS pgp_find_keys(
   11.33 +    PEP_SESSION session, const char *pattern, stringlist_t **keylist
   11.34 +    );
   11.35 +
   11.36 +PEP_STATUS pgp_generate_keypair(
   11.37 +    PEP_SESSION session, pEp_identity *identity
   11.38 +    );
   11.39 +
   11.40 +PEP_STATUS pgp_get_key_rating(
   11.41 +    PEP_SESSION session,
   11.42 +    const char *fpr,
   11.43 +    PEP_comm_type *comm_type
   11.44 +    );
   11.45 +
   11.46 +PEP_STATUS pgp_import_key(PEP_SESSION session, const char *key_data, size_t size);
   11.47 +
   11.48 +PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern);
   11.49 +
   11.50 +PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern);
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/pgp_gpg_internal.h	Mon Sep 01 17:44:19 2014 +0200
    12.3 @@ -0,0 +1,106 @@
    12.4 +#include <gpgme.h>
    12.5 +
    12.6 +// init
    12.7 +
    12.8 +typedef const char * (*gpgme_check_version_t)(const char*);
    12.9 +typedef gpgme_error_t(*gpgme_set_locale_t)(gpgme_ctx_t CTX, int CATEGORY,
   12.10 +    const char *VALUE);
   12.11 +typedef gpgme_error_t(*gpgme_new_t)(gpgme_ctx_t *CTX);
   12.12 +typedef void(*gpgme_release_t)(gpgme_ctx_t CTX);
   12.13 +typedef gpgme_error_t(*gpgme_set_protocol_t)(gpgme_ctx_t CTX,
   12.14 +    gpgme_protocol_t PROTO);
   12.15 +typedef void(*gpgme_set_armor_t)(gpgme_ctx_t CTX, int YES);
   12.16 +
   12.17 +// data
   12.18 +
   12.19 +typedef gpgme_error_t(*gpgme_data_new_t)(gpgme_data_t *DH);
   12.20 +typedef gpgme_error_t(*gpgme_data_new_from_mem_t)(gpgme_data_t *DH,
   12.21 +    const char *BUFFER, size_t SIZE, int COPY);
   12.22 +typedef void(*gpgme_data_release_t)(gpgme_data_t DH);
   12.23 +typedef gpgme_data_type_t(*gpgme_data_identify_t)(gpgme_data_t DH);
   12.24 +typedef size_t(*gpgme_data_seek_t)(gpgme_data_t DH, size_t OFFSET,
   12.25 +    int WHENCE);
   12.26 +typedef size_t(*gpgme_data_read_t)(gpgme_data_t DH, void *BUFFER,
   12.27 +    size_t LENGTH);
   12.28 +
   12.29 +// encrypt and decrypt
   12.30 +
   12.31 +typedef gpgme_error_t(*gpgme_op_decrypt_t)(gpgme_ctx_t CTX,
   12.32 +    gpgme_data_t CIPHER, gpgme_data_t PLAIN);
   12.33 +typedef gpgme_error_t(*gpgme_op_verify_t)(gpgme_ctx_t CTX, gpgme_data_t SIG,
   12.34 +    gpgme_data_t SIGNED_TEXT, gpgme_data_t PLAIN);
   12.35 +typedef gpgme_error_t(*gpgme_op_decrypt_verify_t)(gpgme_ctx_t CTX,
   12.36 +    gpgme_data_t CIPHER, gpgme_data_t PLAIN);
   12.37 +typedef gpgme_decrypt_result_t(*gpgme_op_decrypt_result_t)(gpgme_ctx_t CTX);
   12.38 +typedef gpgme_error_t(*gpgme_op_encrypt_sign_t)(gpgme_ctx_t CTX,
   12.39 +    gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
   12.40 +    gpgme_data_t CIPHER);
   12.41 +typedef gpgme_verify_result_t(*gpgme_op_verify_result_t)(gpgme_ctx_t CTX);
   12.42 +typedef void(*gpgme_signers_clear_t)(gpgme_ctx_t CTX);
   12.43 +typedef gpgme_error_t(*gpgme_signers_add_t)(gpgme_ctx_t CTX, const gpgme_key_t KEY);
   12.44 +
   12.45 +// keys
   12.46 +
   12.47 +typedef gpgme_error_t(*gpgme_get_key_t)(gpgme_ctx_t CTX, const char *FPR,
   12.48 +    gpgme_key_t *R_KEY, int SECRET);
   12.49 +typedef gpgme_error_t(*gpgme_op_genkey_t)(gpgme_ctx_t CTX, const char *PARMS,
   12.50 +    gpgme_data_t PUBLIC, gpgme_data_t SECRET);
   12.51 +typedef gpgme_genkey_result_t(*gpgme_op_genkey_result_t)(gpgme_ctx_t CTX);
   12.52 +typedef gpgme_error_t(*gpgme_op_delete_t)(gpgme_ctx_t CTX,
   12.53 +    const gpgme_key_t KEY, int ALLOW_SECRET);
   12.54 +typedef gpgme_error_t(*gpgme_op_import_t)(gpgme_ctx_t CTX,
   12.55 +    gpgme_data_t KEYDATA);
   12.56 +typedef gpgme_error_t(*gpgme_op_export_t)(gpgme_ctx_t CTX,
   12.57 +    const char *PATTERN, gpgme_export_mode_t MODE, gpgme_data_t KEYDATA);
   12.58 +typedef gpgme_error_t(*gpgme_set_keylist_mode_t)(gpgme_ctx_t CTX,
   12.59 +    gpgme_keylist_mode_t MODE);
   12.60 +typedef gpgme_keylist_mode_t(*gpgme_get_keylist_mode_t)(gpgme_ctx_t CTX);
   12.61 +typedef gpgme_error_t(*gpgme_op_keylist_start_t)(gpgme_ctx_t CTX,
   12.62 +    const char *PATTERN, int SECRET_ONLY);
   12.63 +typedef gpgme_error_t(*gpgme_op_keylist_next_t)(gpgme_ctx_t CTX,
   12.64 +    gpgme_key_t *R_KEY);
   12.65 +typedef gpgme_error_t(*gpgme_op_keylist_end_t)(gpgme_ctx_t CTX);
   12.66 +typedef gpgme_error_t(*gpgme_op_import_keys_t)(gpgme_ctx_t CTX,
   12.67 +    gpgme_key_t *KEYS);
   12.68 +typedef void(*gpgme_key_ref_t)(gpgme_key_t KEY);
   12.69 +typedef void(*gpgme_key_unref_t)(gpgme_key_t KEY);
   12.70 +
   12.71 +struct gpg_s {
   12.72 +    gpgme_check_version_t gpgme_check;
   12.73 +    gpgme_set_locale_t gpgme_set_locale;
   12.74 +    gpgme_new_t gpgme_new;
   12.75 +    gpgme_release_t gpgme_release;
   12.76 +    gpgme_set_protocol_t gpgme_set_protocol;
   12.77 +    gpgme_set_armor_t gpgme_set_armor;
   12.78 +
   12.79 +    gpgme_data_new_t gpgme_data_new;
   12.80 +    gpgme_data_new_from_mem_t gpgme_data_new_from_mem;
   12.81 +    gpgme_data_release_t gpgme_data_release;
   12.82 +    gpgme_data_identify_t gpgme_data_identify;
   12.83 +    gpgme_data_seek_t gpgme_data_seek;
   12.84 +    gpgme_data_read_t gpgme_data_read;
   12.85 +
   12.86 +    gpgme_op_decrypt_t gpgme_op_decrypt;
   12.87 +    gpgme_op_verify_t gpgme_op_verify;
   12.88 +    gpgme_op_decrypt_verify_t gpgme_op_decrypt_verify;
   12.89 +    gpgme_op_decrypt_result_t gpgme_op_decrypt_result;
   12.90 +    gpgme_op_encrypt_sign_t gpgme_op_encrypt_sign;
   12.91 +    gpgme_op_verify_result_t gpgme_op_verify_result;
   12.92 +    gpgme_signers_clear_t gpgme_signers_clear;
   12.93 +    gpgme_signers_add_t gpgme_signers_add;
   12.94 +
   12.95 +    gpgme_get_key_t gpgme_get_key;
   12.96 +    gpgme_op_genkey_t gpgme_op_genkey;
   12.97 +    gpgme_op_genkey_result_t gpgme_op_genkey_result;
   12.98 +    gpgme_op_delete_t gpgme_op_delete;
   12.99 +    gpgme_op_import_t gpgme_op_import;
  12.100 +    gpgme_op_export_t gpgme_op_export;
  12.101 +    gpgme_set_keylist_mode_t gpgme_set_keylist_mode;
  12.102 +    gpgme_get_keylist_mode_t gpgme_get_keylist_mode;
  12.103 +    gpgme_op_keylist_start_t gpgme_op_keylist_start;
  12.104 +    gpgme_op_keylist_next_t gpgme_op_keylist_next;
  12.105 +    gpgme_op_keylist_end_t gpgme_op_keylist_end;
  12.106 +    gpgme_op_import_keys_t gpgme_op_import_keys;
  12.107 +    gpgme_key_ref_t gpgme_key_ref;
  12.108 +    gpgme_key_unref_t gpgme_key_unref;
  12.109 +};
    13.1 --- a/src/platform_windows.h	Mon Sep 01 13:02:23 2014 +0200
    13.2 +++ b/src/platform_windows.h	Mon Sep 01 17:44:19 2014 +0200
    13.3 @@ -9,8 +9,7 @@
    13.4  #ifndef snprintf
    13.5  #define snprintf _snprintf
    13.6  #endif
    13.7 -#define _CRT_NONSTDC_NO_DEPRECATE
    13.8 -#define _CRT_SECURE_NO_WARNINGS
    13.9 +#pragma warning(disable : 4996)
   13.10  
   13.11  #ifdef __cplusplus
   13.12  extern "C" {