Merged
authorEdouard Tisserant
Mon, 20 Apr 2015 23:26:20 +0200
changeset 210f599bb1ebb90
parent 209 8572f358fb61
parent 205 69abe9ef3be2
child 212 6207061ddd14
child 225 ed16ea1bece7
Merged
src/pgp_netpgp.c
src/pgp_netpgp.h
     1.1 --- a/src/Makefile	Mon Apr 20 22:58:53 2015 +0200
     1.2 +++ b/src/Makefile	Mon Apr 20 23:26:20 2015 +0200
     1.3 @@ -85,7 +85,7 @@
     1.4  install: $(TARGET)
     1.5  	cp $< $(PREFIX)/lib/
     1.6  	mkdir -p $(PREFIX)/include/pEp
     1.7 -	cp pEpEngine.h keymanagement.h message_api.h $(PREFIX)/include/pEp/
     1.8 +	cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h $(PREFIX)/include/pEp/
     1.9  
    1.10  uninstall:
    1.11  	rm -f $(PREFIX)/lib/$(TARGET)
     2.1 --- a/src/cryptotech.c	Mon Apr 20 22:58:53 2015 +0200
     2.2 +++ b/src/cryptotech.c	Mon Apr 20 23:26:20 2015 +0200
     2.3 @@ -38,6 +38,8 @@
     2.4          cryptotech[PEP_crypt_OpenPGP].import_key = pgp_import_keydata;
     2.5          cryptotech[PEP_crypt_OpenPGP].recv_key = pgp_recv_key;
     2.6          cryptotech[PEP_crypt_OpenPGP].send_key = pgp_send_key;
     2.7 +        cryptotech[PEP_crypt_OpenPGP].renew_key = pgp_renew_key;
     2.8 +        cryptotech[PEP_crypt_OpenPGP].revoke_key = pgp_revoke_key;
     2.9      }
    2.10  
    2.11      session->cryptotech = cryptotech;
     3.1 --- a/src/cryptotech.h	Mon Apr 20 22:58:53 2015 +0200
     3.2 +++ b/src/cryptotech.h	Mon Apr 20 23:26:20 2015 +0200
     3.3 @@ -47,12 +47,18 @@
     3.4          PEP_comm_type *comm_type
     3.5      );
     3.6  
     3.7 -typedef PEP_STATUS (*import_key_t)(PEP_SESSION session, const char *key_data, size_t size);
     3.8 +typedef PEP_STATUS (*import_key_t)(PEP_SESSION session, const char *key_data,
     3.9 +        size_t size);
    3.10  
    3.11  typedef PEP_STATUS (*recv_key_t)(PEP_SESSION session, const char *pattern);
    3.12  
    3.13  typedef PEP_STATUS (*send_key_t)(PEP_SESSION session, const char *pattern);
    3.14  
    3.15 +typedef PEP_STATUS (*renew_key_t)(PEP_SESSION session, const char *key_id,
    3.16 +        const timestamp *ts);
    3.17 +
    3.18 +typedef PEP_STATUS (*revoke_key_t)(PEP_SESSION session, const char *key_id);
    3.19 +
    3.20  typedef struct _PEP_cryptotech_t {
    3.21      uint8_t id;
    3.22      // the following are default values; comm_type may vary with key length or b0rken crypto
    3.23 @@ -69,6 +75,8 @@
    3.24      import_key_t import_key;
    3.25      recv_key_t recv_key;
    3.26      send_key_t send_key;
    3.27 +    renew_key_t renew_key;
    3.28 +    revoke_key_t revoke_key;
    3.29  } PEP_cryptotech_t;
    3.30  
    3.31  typedef uint64_t cryptotech_mask;
     4.1 --- a/src/keymanagement.c	Mon Apr 20 22:58:53 2015 +0200
     4.2 +++ b/src/keymanagement.c	Mon Apr 20 23:26:20 2015 +0200
     4.3 @@ -28,6 +28,9 @@
     4.4      assert(identity);
     4.5      assert(!EMPTY(identity->address));
     4.6  
     4.7 +    if (!(session && identity && !EMPTY(identity->address)))
     4.8 +        return PEP_ILLEGAL_VALUE;
     4.9 +
    4.10      status = get_identity(session, identity->address, &stored_identity);
    4.11      assert(status != PEP_OUT_OF_MEMORY);
    4.12      if (status == PEP_OUT_OF_MEMORY)
    4.13 @@ -190,6 +193,10 @@
    4.14      assert(identity->username);
    4.15      assert(identity->user_id);
    4.16  
    4.17 +    if (!(session && identity && identity->address && identity->username &&
    4.18 +                identity->user_id))
    4.19 +        return PEP_ILLEGAL_VALUE;
    4.20 +
    4.21      identity->comm_type = PEP_ct_pEp;
    4.22      identity->me = true;
    4.23  
     5.1 --- a/src/message_api.c	Mon Apr 20 22:58:53 2015 +0200
     5.2 +++ b/src/message_api.c	Mon Apr 20 23:26:20 2015 +0200
     5.3 @@ -7,6 +7,10 @@
     5.4  #include <string.h>
     5.5  #include <stdlib.h>
     5.6  
     5.7 +#ifndef MIN
     5.8 +#define MIN(A, B) ((B) > (A) ? (A) : (B))
     5.9 +#endif
    5.10 +
    5.11  static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
    5.12  {
    5.13      char * ptext;
    5.14 @@ -241,6 +245,9 @@
    5.15      assert(dst);
    5.16      assert(enc_format >= PEP_enc_pieces);
    5.17  
    5.18 +    if (!(session && src && dst && (enc_format >= PEP_enc_pieces)))
    5.19 +        return PEP_ILLEGAL_VALUE;
    5.20 +
    5.21      *dst = NULL;
    5.22  
    5.23      if (src->enc_format >= PEP_enc_pieces) {
    5.24 @@ -559,6 +566,9 @@
    5.25      assert(src);
    5.26      assert(dst);
    5.27  
    5.28 +    if (!(session && src && dst))
    5.29 +        return PEP_ILLEGAL_VALUE;
    5.30 +
    5.31      *dst = NULL;
    5.32   
    5.33      if (src->mime == PEP_MIME_fields_omitted || src->mime == PEP_MIME) {
    5.34 @@ -740,3 +750,121 @@
    5.35      return status;
    5.36  }
    5.37  
    5.38 +static PEP_comm_type _get_comm_type(
    5.39 +        PEP_SESSION session,
    5.40 +        PEP_comm_type max_comm_type,
    5.41 +        pEp_identity *ident
    5.42 +    )
    5.43 +{
    5.44 +    PEP_STATUS status = update_identity(session, ident);
    5.45 +
    5.46 +    if (max_comm_type == PEP_ct_compromized)
    5.47 +        return PEP_ct_compromized;
    5.48 +
    5.49 +    if (status == PEP_STATUS_OK) {
    5.50 +        if (ident->comm_type == PEP_ct_compromized)
    5.51 +            return PEP_ct_compromized;
    5.52 +        else
    5.53 +            return MIN(max_comm_type, ident->comm_type);
    5.54 +    }
    5.55 +    else {
    5.56 +        return PEP_ct_unknown;
    5.57 +    }
    5.58 +}
    5.59 +
    5.60 +DYNAMIC_API PEP_STATUS get_message_color(
    5.61 +        PEP_SESSION session,
    5.62 +        message *msg,
    5.63 +        pEp_color *color
    5.64 +    )
    5.65 +{
    5.66 +    PEP_STATUS status = PEP_STATUS_OK;
    5.67 +    PEP_comm_type max_comm_type = PEP_ct_pEp;
    5.68 +    bool comm_type_determined = false;
    5.69 +    identity_list * il;
    5.70 +
    5.71 +    assert(session);
    5.72 +    assert(msg);
    5.73 +    assert(color);
    5.74 +
    5.75 +    if (!(session && msg && color))
    5.76 +        return PEP_ILLEGAL_VALUE;
    5.77 +
    5.78 +    *color = pEp_undefined;
    5.79 +
    5.80 +    assert(msg->from);
    5.81 +    if (msg->from == NULL)
    5.82 +        return PEP_ILLEGAL_VALUE;
    5.83 +
    5.84 +    switch (msg->dir) {
    5.85 +        case PEP_dir_incoming:
    5.86 +            status = update_identity(session, msg->from);
    5.87 +            if (status != PEP_STATUS_OK)
    5.88 +                return status;
    5.89 +            max_comm_type = msg->from->comm_type;
    5.90 +            comm_type_determined = true;
    5.91 +            break;
    5.92 +        
    5.93 +        case PEP_dir_outgoing:
    5.94 +            status = myself(session, msg->from);
    5.95 +            if (status != PEP_STATUS_OK)
    5.96 +                return status;
    5.97 +
    5.98 +            for (il = msg->to; il != NULL; il = il->next) {
    5.99 +                if (il->ident) {
   5.100 +                    max_comm_type = _get_comm_type(session, max_comm_type,
   5.101 +                            il->ident);
   5.102 +                    comm_type_determined = true;
   5.103 +                }
   5.104 +            }
   5.105 +
   5.106 +            for (il = msg->cc; il != NULL; il = il->next) {
   5.107 +                if (il->ident) {
   5.108 +                    max_comm_type = _get_comm_type(session, max_comm_type,
   5.109 +                            il->ident);
   5.110 +                    comm_type_determined = true;
   5.111 +                }
   5.112 +            }
   5.113 +
   5.114 +            for (il = msg->bcc; il != NULL; il = il->next) {
   5.115 +                if (il->ident) {
   5.116 +                    max_comm_type = _get_comm_type(session, max_comm_type,
   5.117 +                            il->ident);
   5.118 +                    comm_type_determined = true;
   5.119 +                }
   5.120 +            }
   5.121 +            break;
   5.122 +
   5.123 +        default:
   5.124 +            return PEP_ILLEGAL_VALUE;
   5.125 +    }
   5.126 +
   5.127 +    if (comm_type_determined == false)
   5.128 +        *color = pEp_undefined;
   5.129 +
   5.130 +    else if (max_comm_type == PEP_ct_compromized)
   5.131 +        *color = pEp_under_attack;
   5.132 +
   5.133 +    else if (max_comm_type >= PEP_ct_confirmed_enc_anon)
   5.134 +        *color = pEp_trusted_and_anonymized;
   5.135 +
   5.136 +    else if (max_comm_type >= PEP_ct_strong_encryption)
   5.137 +        *color = pEp_trusted;
   5.138 +
   5.139 +    else if (max_comm_type >= PEP_ct_strong_but_unconfirmed &&
   5.140 +            max_comm_type < PEP_ct_confirmed)
   5.141 +        *color = pEp_reliable;
   5.142 +    
   5.143 +    else if (max_comm_type == PEP_ct_no_encryption ||
   5.144 +            max_comm_type == PEP_ct_no_encrypted_channel)
   5.145 +        *color = pEp_unencrypted;
   5.146 +
   5.147 +    else if (max_comm_type == PEP_ct_unknown)
   5.148 +        *color = pEp_undefined;
   5.149 +
   5.150 +    else
   5.151 +        *color = pEp_unreliable;
   5.152 +
   5.153 +    return PEP_STATUS_OK;
   5.154 +}
   5.155 +
     6.1 --- a/src/message_api.h	Mon Apr 20 22:58:53 2015 +0200
     6.2 +++ b/src/message_api.h	Mon Apr 20 23:26:20 2015 +0200
     6.3 @@ -62,6 +62,42 @@
     6.4          message **dst
     6.5      );
     6.6  
     6.7 +
     6.8 +typedef enum _pEp_color {
     6.9 +    pEp_undefined = 0,
    6.10 +    pEp_unencrypted,
    6.11 +    pEp_unreliable,
    6.12 +    pEp_reliable,
    6.13 +    pEp_yellow = pEp_reliable,
    6.14 +    pEp_trusted,
    6.15 +    pEp_green = pEp_trusted,
    6.16 +    pEp_trusted_and_anonymized,
    6.17 +    pEp_fully_anonymous,   
    6.18 +
    6.19 +    pEp_under_attack = -1,
    6.20 +    pEp_red = pEp_under_attack,
    6.21 +    pEp_b0rken = -2
    6.22 +} pEp_color;
    6.23 +
    6.24 +// get_message_color() - get color for a message
    6.25 +//
    6.26 +//  parameters:
    6.27 +//      session (in)        session handle
    6.28 +//      msg (in)            message to get the color for
    6.29 +//      color (out)         color for the message
    6.30 +//
    6.31 +//  return value:
    6.32 +//      error status or PEP_STATUS_OK on success
    6.33 +//
    6.34 +//  caveat:
    6.35 +//      msg->from must point to a valid pEp_identity
    6.36 +
    6.37 +DYNAMIC_API PEP_STATUS get_message_color(
    6.38 +        PEP_SESSION session,
    6.39 +        message *msg,
    6.40 +        pEp_color *color
    6.41 +    );
    6.42 +
    6.43  #ifdef __cplusplus
    6.44  }
    6.45  #endif
     7.1 --- a/src/mime.c	Mon Apr 20 22:58:53 2015 +0200
     7.2 +++ b/src/mime.c	Mon Apr 20 23:26:20 2015 +0200
     7.3 @@ -771,6 +771,9 @@
     7.4      assert(msg->mime == PEP_MIME_none);
     7.5      assert(mimetext);
     7.6  
     7.7 +    if (!(msg && msg->mime == PEP_MIME_none && mimetext))
     7.8 +        return PEP_ILLEGAL_VALUE;
     7.9 +
    7.10      *mimetext = NULL;
    7.11  
    7.12      switch (msg->enc_format) {
    7.13 @@ -1423,6 +1426,9 @@
    7.14      assert(mimetext);
    7.15      assert(msg);
    7.16  
    7.17 +    if (!(mimetext && msg))
    7.18 +        return PEP_ILLEGAL_VALUE;
    7.19 +
    7.20      *msg = NULL;
    7.21  
    7.22      index = 0;
     8.1 --- a/src/pEpEngine.c	Mon Apr 20 22:58:53 2015 +0200
     8.2 +++ b/src/pEpEngine.c	Mon Apr 20 23:26:20 2015 +0200
     8.3 @@ -31,6 +31,9 @@
     8.4          in_first = true;
     8.5  
     8.6  	assert(session);
     8.7 +    if (session == NULL)
     8.8 +        return PEP_ILLEGAL_VALUE;
     8.9 +
    8.10  	*session = NULL;
    8.11  
    8.12      pEpSession *_session = calloc(1, sizeof(pEpSession));
    8.13 @@ -254,6 +257,9 @@
    8.14      assert(init_count >= 0);
    8.15  	assert(session);
    8.16  
    8.17 +    if (!(init_count && session))
    8.18 +        return;
    8.19 +
    8.20      // a small race condition but still a race condition
    8.21      // mitigated by calling caveat (see documentation)
    8.22  
    8.23 @@ -305,6 +311,9 @@
    8.24  	assert(title);
    8.25  	assert(entity);
    8.26  
    8.27 +    if (!(session && title && entity))
    8.28 +        return PEP_ILLEGAL_VALUE;
    8.29 +
    8.30  	sqlite3_reset(session->log);
    8.31  	sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
    8.32  	sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
    8.33 @@ -339,6 +348,9 @@
    8.34  	assert(word);
    8.35  	assert(wsize);
    8.36  
    8.37 +    if (!(session && word && wsize))
    8.38 +        return PEP_ILLEGAL_VALUE;
    8.39 +
    8.40  	*word = NULL;
    8.41  	*wsize = 0;
    8.42  
    8.43 @@ -387,6 +399,9 @@
    8.44  	assert(wsize);
    8.45  	assert(max_words >= 0);
    8.46  
    8.47 +    if (!(session && fingerprint && words && wsize && max_words >= 0))
    8.48 +        return PEP_ILLEGAL_VALUE;
    8.49 +
    8.50  	*words = NULL;
    8.51  	*wsize = 0;
    8.52  
    8.53 @@ -551,6 +566,9 @@
    8.54  	assert(address);
    8.55      assert(address[0]);
    8.56  
    8.57 +    if (!(session && address && address[0]))
    8.58 +        return PEP_ILLEGAL_VALUE;
    8.59 +
    8.60      sqlite3_reset(session->get_identity);
    8.61      sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
    8.62  
    8.63 @@ -601,6 +619,10 @@
    8.64  	assert(identity->user_id);
    8.65  	assert(identity->username);
    8.66  
    8.67 +    if (!(session && identity && identity->address && identity->fpr &&
    8.68 +                identity->user_id && identity->username))
    8.69 +        return PEP_ILLEGAL_VALUE;
    8.70 +
    8.71  	sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
    8.72  
    8.73  	sqlite3_reset(session->set_person);
    8.74 @@ -681,6 +703,10 @@
    8.75      assert(identity->fpr);
    8.76      assert(identity->fpr[0]);
    8.77  
    8.78 +    if (!(session && identity && identity->user_id && identity->user_id[0] &&
    8.79 +                identity->fpr && identity->fpr[0]))
    8.80 +        return PEP_ILLEGAL_VALUE;
    8.81 +
    8.82      identity->comm_type = PEP_ct_unknown;
    8.83  
    8.84      sqlite3_reset(session->get_trust);
    8.85 @@ -717,6 +743,16 @@
    8.86      char **ptext, size_t *psize, stringlist_t **keylist
    8.87      )
    8.88  {
    8.89 +    assert(session);
    8.90 +    assert(ctext);
    8.91 +    assert(csize);
    8.92 +    assert(ptext);
    8.93 +    assert(psize);
    8.94 +    assert(keylist);
    8.95 +
    8.96 +    if (!(session && ctext && csize && ptext && psize && keylist && keylist))
    8.97 +        return PEP_ILLEGAL_VALUE;
    8.98 +
    8.99      return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
   8.100  }
   8.101  
   8.102 @@ -725,6 +761,16 @@
   8.103      size_t psize, char **ctext, size_t *csize
   8.104      )
   8.105  {
   8.106 +    assert(session);
   8.107 +    assert(keylist);
   8.108 +    assert(ptext);
   8.109 +    assert(psize);
   8.110 +    assert(ctext);
   8.111 +    assert(csize);
   8.112 +
   8.113 +    if (!(session && keylist && ptext && psize && ctext && csize))
   8.114 +        return PEP_ILLEGAL_VALUE;
   8.115 +
   8.116      return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
   8.117  }
   8.118  
   8.119 @@ -733,11 +779,27 @@
   8.120      const char *signature, size_t sig_size, stringlist_t **keylist
   8.121      )
   8.122  {
   8.123 +    assert(session);
   8.124 +    assert(text);
   8.125 +    assert(size);
   8.126 +    assert(signature);
   8.127 +    assert(sig_size);
   8.128 +    assert(keylist);
   8.129 +
   8.130 +    if (!(session && text && size && signature && sig_size && keylist))
   8.131 +        return PEP_ILLEGAL_VALUE;
   8.132 +
   8.133      return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
   8.134  }
   8.135  
   8.136  DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
   8.137  {
   8.138 +    assert(session);
   8.139 +    assert(fpr);
   8.140 +
   8.141 +    if (!(session && fpr))
   8.142 +        return PEP_ILLEGAL_VALUE;
   8.143 +
   8.144      return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
   8.145  }
   8.146  
   8.147 @@ -745,6 +807,14 @@
   8.148          PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   8.149      )
   8.150  {
   8.151 +    assert(session);
   8.152 +    assert(fpr);
   8.153 +    assert(key_data);
   8.154 +    assert(size);
   8.155 +
   8.156 +    if (!(session && fpr && key_data && size))
   8.157 +        return PEP_ILLEGAL_VALUE;
   8.158 +
   8.159      return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
   8.160  }
   8.161  
   8.162 @@ -752,6 +822,13 @@
   8.163          PEP_SESSION session, const char *pattern, stringlist_t **keylist
   8.164      )
   8.165  {
   8.166 +    assert(session);
   8.167 +    assert(pattern);
   8.168 +    assert(keylist);
   8.169 +
   8.170 +    if (!(session && pattern && keylist))
   8.171 +        return PEP_ILLEGAL_VALUE;
   8.172 +
   8.173      return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
   8.174  }
   8.175  
   8.176 @@ -759,6 +836,16 @@
   8.177          PEP_SESSION session, pEp_identity *identity
   8.178      )
   8.179  {
   8.180 +    assert(session);
   8.181 +    assert(identity);
   8.182 +    assert(identity->address);
   8.183 +    assert(identity->fpr == NULL);
   8.184 +    assert(identity->username);
   8.185 +
   8.186 +    if (!(session && identity && identity->address && identity->fpr == NULL &&
   8.187 +                identity->username))
   8.188 +        return PEP_ILLEGAL_VALUE;
   8.189 +
   8.190      return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
   8.191  }
   8.192  
   8.193 @@ -768,20 +855,72 @@
   8.194          PEP_comm_type *comm_type
   8.195      )
   8.196  {
   8.197 +    assert(session);
   8.198 +    assert(fpr);
   8.199 +    assert(comm_type);
   8.200 +
   8.201 +    if (!(session && fpr && comm_type))
   8.202 +        return PEP_ILLEGAL_VALUE;
   8.203 +
   8.204      return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
   8.205  }
   8.206  
   8.207  DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
   8.208  {
   8.209 +    assert(session);
   8.210 +    assert(key_data);
   8.211 +
   8.212 +    if (!(session && key_data))
   8.213 +        return PEP_ILLEGAL_VALUE;
   8.214 +
   8.215      return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
   8.216  }
   8.217  
   8.218  DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
   8.219  {
   8.220 +    assert(session);
   8.221 +    assert(pattern);
   8.222 +
   8.223 +    if (!(session && pattern))
   8.224 +        return PEP_ILLEGAL_VALUE;
   8.225 +
   8.226      return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
   8.227  }
   8.228  
   8.229  DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
   8.230  {
   8.231 +    assert(session);
   8.232 +    assert(pattern);
   8.233 +
   8.234 +    if (!(session && pattern))
   8.235 +        return PEP_ILLEGAL_VALUE;
   8.236 +
   8.237      return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
   8.238  }
   8.239 +
   8.240 +DYNAMIC_API PEP_STATUS renew_key(
   8.241 +        PEP_SESSION session,
   8.242 +        const char *fpr,
   8.243 +        const timestamp *ts
   8.244 +    )
   8.245 +{
   8.246 +    assert(session);
   8.247 +    assert(fpr);
   8.248 +
   8.249 +    if (!(session && fpr))
   8.250 +        return PEP_ILLEGAL_VALUE;
   8.251 +
   8.252 +    return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
   8.253 +}
   8.254 +
   8.255 +DYNAMIC_API PEP_STATUS revoke_key(PEP_SESSION session, const char *fpr)
   8.256 +{
   8.257 +    assert(session);
   8.258 +    assert(fpr);
   8.259 +
   8.260 +    if (!(session && fpr))
   8.261 +        return PEP_ILLEGAL_VALUE;
   8.262 +
   8.263 +    return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr);
   8.264 +}
   8.265 +
     9.1 --- a/src/pEpEngine.h	Mon Apr 20 22:58:53 2015 +0200
     9.2 +++ b/src/pEpEngine.h	Mon Apr 20 23:26:20 2015 +0200
     9.3 @@ -10,6 +10,7 @@
     9.4  
     9.5  #include "dynamic_api.h"
     9.6  #include "stringlist.h"
     9.7 +#include "timestamp.h"
     9.8  
     9.9  #define PEP_VERSION "1.0"
    9.10  
    9.11 @@ -299,8 +300,12 @@
    9.12  
    9.13      PEP_ct_unconfirmed_encryption = 0x10,       // generic
    9.14      PEP_ct_OpenPGP_weak_unconfirmed = 0x11,	    // RSA 1024 is weak
    9.15 -    PEP_ct_SMIME_unconfirmed = 0x20,
    9.16 -    PEP_ct_CMS_unconfirmed = 0x30,
    9.17 +
    9.18 +    PEP_ct_to_be_checked = 0x20,                // generic
    9.19 +    PEP_ct_SMIME_unconfirmed = 0x21,
    9.20 +    PEP_ct_CMS_unconfirmed = 0x22,
    9.21 +
    9.22 +    PEP_ct_strong_but_unconfirmed = 0x30,       // generic
    9.23      PEP_ct_OpenPGP_unconfirmed = 0x38,          // key at least 2048 bit RSA or EC
    9.24      PEP_ct_OTR_unconfirmed = 0x3a,
    9.25  
    9.26 @@ -316,8 +321,12 @@
    9.27  
    9.28      PEP_ct_confirmed_encryption = 0x90,         // generic
    9.29  	PEP_ct_OpenPGP_weak = 0x91,                 // RSA 1024 is weak
    9.30 -    PEP_ct_SMIME = 0xa0,
    9.31 -    PEP_ct_CMS = 0xb0,
    9.32 +
    9.33 +    PEP_ct_to_be_checked_confirmed = 0xa0,      //generic
    9.34 +    PEP_ct_SMIME = 0xa1,
    9.35 +    PEP_ct_CMS = 0xa2,
    9.36 +
    9.37 +    PEP_ct_strong_encryption = 0xb0,            // generic
    9.38  	PEP_ct_OpenPGP = 0xb8,                      // key at least 2048 bit RSA or EC
    9.39  	PEP_ct_OTR = 0xba,
    9.40  
    9.41 @@ -598,6 +607,30 @@
    9.42      );
    9.43  
    9.44  
    9.45 +// renew_key() - renew an expired key
    9.46 +//
    9.47 +//  parameters:
    9.48 +//      session (in)            session handle
    9.49 +//      key_id (in)             ID of key to renew as UTF-8 string
    9.50 +//      ts (in)                 timestamp when key should expire or NULL for
    9.51 +//                              default
    9.52 +
    9.53 +DYNAMIC_API PEP_STATUS renew_key(
    9.54 +        PEP_SESSION session,
    9.55 +        const char *fpr,
    9.56 +        const timestamp *ts
    9.57 +    );
    9.58 +
    9.59 +
    9.60 +// revoke_key() - revoke an expired key
    9.61 +//
    9.62 +//  parameters:
    9.63 +//      session (in)            session handle
    9.64 +//      key_id (in)             ID of key to revoke as UTF-8 string
    9.65 +
    9.66 +DYNAMIC_API PEP_STATUS revoke_key(PEP_SESSION session, const char *fpr);
    9.67 +
    9.68 +
    9.69  #ifdef __cplusplus
    9.70  }
    9.71  #endif
    10.1 --- a/src/pgp_gpg.c	Mon Apr 20 22:58:53 2015 +0200
    10.2 +++ b/src/pgp_gpg.c	Mon Apr 20 23:26:20 2015 +0200
    10.3 @@ -1193,7 +1193,6 @@
    10.4          return PEP_CANNOT_SEND_KEY;
    10.5  }
    10.6  
    10.7 -
    10.8  PEP_STATUS pgp_get_key_rating(
    10.9      PEP_SESSION session,
   10.10      const char *fpr,
   10.11 @@ -1291,3 +1290,218 @@
   10.12  
   10.13      return status;
   10.14  }
   10.15 +
   10.16 +static PEP_STATUS find_single_key(
   10.17 +        PEP_SESSION session,
   10.18 +        const char *fpr,
   10.19 +        gpgme_key_t *key
   10.20 +    )
   10.21 +{
   10.22 +    gpgme_error_t gpgme_error;
   10.23 +
   10.24 +    *key = NULL;
   10.25 +
   10.26 +    gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
   10.27 +    gpgme_error = _GPGERR(gpgme_error);
   10.28 +    switch (gpgme_error) {
   10.29 +    case GPG_ERR_NO_ERROR:
   10.30 +        break;
   10.31 +    case GPG_ERR_INV_VALUE:
   10.32 +        assert(0);
   10.33 +        return PEP_UNKNOWN_ERROR;
   10.34 +    default:
   10.35 +        return PEP_GET_KEY_FAILED;
   10.36 +    };
   10.37 +
   10.38 +    gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, key);
   10.39 +    gpgme_error = _GPGERR(gpgme_error);
   10.40 +    assert(gpgme_error != GPG_ERR_INV_VALUE);
   10.41 +
   10.42 +    gpg.gpgme_op_keylist_end(session->ctx);
   10.43 +
   10.44 +    return PEP_STATUS_OK;
   10.45 +}
   10.46 +
   10.47 +typedef struct _renew_state {
   10.48 +    enum state_t {
   10.49 +        renew_command = 0,
   10.50 +        renew_date,
   10.51 +        renew_secret_key,
   10.52 +        renew_command2,
   10.53 +        renew_date2,
   10.54 +        renew_quit,
   10.55 +        renew_save,
   10.56 +        renew_exit,
   10.57 +        renew_error = -1
   10.58 +    } state;
   10.59 +    const char *date_ref;
   10.60 +} renew_state;
   10.61 +
   10.62 +static gpgme_error_t renew_fsm(
   10.63 +        void *_handle,
   10.64 +        gpgme_status_code_t statuscode,
   10.65 +        const char *args,
   10.66 +        int fd
   10.67 +    )
   10.68 +{
   10.69 +    renew_state *handle = _handle;
   10.70 +
   10.71 +    switch (handle->state) {
   10.72 +        case renew_command:
   10.73 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   10.74 +                assert(strcmp(args, "keyedit.prompt") == 0);
   10.75 +                if (strcmp(args, "keyedit.prompt")) {
   10.76 +                    handle->state = renew_error;
   10.77 +                    return GPG_ERR_GENERAL;
   10.78 +                }
   10.79 +                write(fd, "expire\n", 7);
   10.80 +                handle->state = renew_date;
   10.81 +            }
   10.82 +            break;
   10.83 +
   10.84 +        case renew_date:
   10.85 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   10.86 +                assert(strcmp(args, "keygen.valid") == 0);
   10.87 +                if (strcmp(args, "keygen.valid")) {
   10.88 +                    handle->state = renew_error;
   10.89 +                    return GPG_ERR_GENERAL;
   10.90 +                }
   10.91 +                write(fd, handle->date_ref, 11);
   10.92 +                handle->state = renew_secret_key;
   10.93 +            }
   10.94 +            break;
   10.95 +
   10.96 +        case renew_secret_key:
   10.97 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   10.98 +                assert(strcmp(args, "keyedit.prompt") == 0);
   10.99 +                if (strcmp(args, "keyedit.prompt")) {
  10.100 +                    handle->state = renew_error;
  10.101 +                    return GPG_ERR_GENERAL;
  10.102 +                }
  10.103 +                write(fd, "key 1\n", 6);
  10.104 +                handle->state = renew_command2;
  10.105 +            }
  10.106 +            break;
  10.107 +
  10.108 +        case renew_command2:
  10.109 +            if (statuscode == GPGME_STATUS_GET_LINE) {
  10.110 +                assert(strcmp(args, "keyedit.prompt") == 0);
  10.111 +                if (strcmp(args, "keyedit.prompt")) {
  10.112 +                    handle->state = renew_error;
  10.113 +                    return GPG_ERR_GENERAL;
  10.114 +                }
  10.115 +                write(fd, "expire\n", 7);
  10.116 +                handle->state = renew_date2;
  10.117 +            }
  10.118 +            break;
  10.119 +
  10.120 +        case renew_date2:
  10.121 +            if (statuscode == GPGME_STATUS_GET_LINE) {
  10.122 +                assert(strcmp(args, "keygen.valid") == 0);
  10.123 +                if (strcmp(args, "keygen.valid")) {
  10.124 +                    handle->state = renew_error;
  10.125 +                    return GPG_ERR_GENERAL;
  10.126 +                }
  10.127 +                write(fd, handle->date_ref, 11);
  10.128 +                handle->state = renew_quit;
  10.129 +            }
  10.130 +            break;
  10.131 +
  10.132 +        case renew_quit:
  10.133 +            if (statuscode == GPGME_STATUS_GET_LINE) {
  10.134 +                assert(strcmp(args, "keyedit.prompt") == 0);
  10.135 +                if (strcmp(args, "keyedit.prompt")) {
  10.136 +                    handle->state = renew_error;
  10.137 +                    return GPG_ERR_GENERAL;
  10.138 +                }
  10.139 +                write(fd, "quit\n", 5);
  10.140 +                handle->state = renew_save;
  10.141 +            }
  10.142 +            break;
  10.143 +
  10.144 +        case renew_save:
  10.145 +            if (statuscode == GPGME_STATUS_GET_BOOL) {
  10.146 +                assert(strcmp(args, "keyedit.save.okay") == 0);
  10.147 +                if (strcmp(args, "keyedit.save.okay")) {
  10.148 +                    handle->state = renew_error;
  10.149 +                    return GPG_ERR_GENERAL;
  10.150 +                }
  10.151 +                write(fd, "Y\n", 2);
  10.152 +                handle->state = renew_exit;
  10.153 +            }
  10.154 +            break;
  10.155 +
  10.156 +        case renew_exit:
  10.157 +            break;
  10.158 +
  10.159 +        case renew_error:
  10.160 +            return GPG_ERR_GENERAL;
  10.161 +    }
  10.162 +
  10.163 +    return GPG_ERR_NO_ERROR;
  10.164 +}
  10.165 +
  10.166 +static ssize_t _nullwriter(
  10.167 +        void *_handle,
  10.168 +        const void *buffer,
  10.169 +        size_t size
  10.170 +    )
  10.171 +{
  10.172 +    return size;
  10.173 +}
  10.174 +
  10.175 +PEP_STATUS pgp_renew_key(
  10.176 +        PEP_SESSION session,
  10.177 +        const char *fpr,
  10.178 +        const timestamp *ts
  10.179 +    )
  10.180 +{
  10.181 +    PEP_STATUS status = PEP_STATUS_OK;
  10.182 +    gpgme_error_t gpgme_error;
  10.183 +    gpgme_key_t key;
  10.184 +    gpgme_data_t output;
  10.185 +    renew_state handle;
  10.186 +    char date_text[12];
  10.187 +
  10.188 +    assert(session);
  10.189 +    assert(fpr);
  10.190 +
  10.191 +    memset(&handle, 0, sizeof(renew_state));
  10.192 +    snprintf(date_text, 12, "%.4d-%.2d-%.2d\n", ts->tm_year + 1900,
  10.193 +            ts->tm_mon + 1, ts->tm_mday);
  10.194 +    handle.date_ref = date_text;
  10.195 +
  10.196 +    status = find_single_key(session, fpr, &key);
  10.197 +    if (status != PEP_STATUS_OK)
  10.198 +        return status;
  10.199 +
  10.200 +    struct gpgme_data_cbs data_cbs;
  10.201 +    memset(&data_cbs, 0, sizeof(struct gpgme_data_cbs));
  10.202 +    data_cbs.write = _nullwriter;
  10.203 +    gpgme_data_new_from_cbs(&output, &data_cbs, &handle);
  10.204 +
  10.205 +    gpgme_error = gpgme_op_edit(session->ctx, key, renew_fsm, &handle,
  10.206 +            output);
  10.207 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
  10.208 +
  10.209 +    gpg.gpgme_data_release(output);
  10.210 +    gpg.gpgme_key_unref(key);
  10.211 +
  10.212 +    return PEP_STATUS_OK;
  10.213 +}
  10.214 +
  10.215 +PEP_STATUS pgp_revoke_key(PEP_SESSION session, const char *fpr)
  10.216 +{
  10.217 +    PEP_STATUS status = PEP_STATUS_OK;
  10.218 +    gpgme_key_t key;
  10.219 +    
  10.220 +    assert(session);
  10.221 +    assert(fpr);
  10.222 +
  10.223 +    status = find_single_key(session, fpr, &key);
  10.224 +    if (status != PEP_STATUS_OK)
  10.225 +        return status;
  10.226 +
  10.227 +    return PEP_STATUS_OK;
  10.228 +}
  10.229 +
    11.1 --- a/src/pgp_gpg.h	Mon Apr 20 22:58:53 2015 +0200
    11.2 +++ b/src/pgp_gpg.h	Mon Apr 20 23:26:20 2015 +0200
    11.3 @@ -44,6 +44,13 @@
    11.4          size_t size);
    11.5  
    11.6  PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern);
    11.7 -
    11.8  PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern);
    11.9  
   11.10 +PEP_STATUS pgp_renew_key(
   11.11 +        PEP_SESSION session,
   11.12 +        const char *fpr,
   11.13 +        const timestamp *ts
   11.14 +    );
   11.15 +
   11.16 +PEP_STATUS pgp_revoke_key(PEP_SESSION session, const char *fpr);
   11.17 +
    12.1 --- a/src/pgp_netpgp.c	Mon Apr 20 22:58:53 2015 +0200
    12.2 +++ b/src/pgp_netpgp.c	Mon Apr 20 23:26:20 2015 +0200
    12.3 @@ -753,3 +753,36 @@
    12.4  
    12.5      return status;
    12.6  }
    12.7 +
    12.8 +PEP_STATUS pgp_renew_key(
    12.9 +        PEP_SESSION session,
   12.10 +        const char *fpr,
   12.11 +        const timestamp *ts
   12.12 +    )
   12.13 +{
   12.14 +    PEP_STATUS status = PEP_STATUS_OK;
   12.15 +    char date_text[12];
   12.16 +
   12.17 +    assert(session);
   12.18 +    assert(fpr);
   12.19 +
   12.20 +    snprintf(date_text, 12, "%.4d-%.2d-%.2d\n", ts->tm_year + 1900,
   12.21 +            ts->tm_mon + 1, ts->tm_mday);
   12.22 +
   12.23 +
   12.24 +        return PEP_UNKNOWN_ERROR;
   12.25 +    return PEP_STATUS_OK;
   12.26 +}
   12.27 +
   12.28 +PEP_STATUS pgp_revoke_key(PEP_SESSION session, const char *fpr)
   12.29 +{
   12.30 +    PEP_STATUS status = PEP_STATUS_OK;
   12.31 +    
   12.32 +    assert(session);
   12.33 +    assert(fpr);
   12.34 +
   12.35 +        return PEP_UNKNOWN_ERROR;
   12.36 +
   12.37 +    return PEP_STATUS_OK;
   12.38 +}
   12.39 +
    13.1 --- a/src/pgp_netpgp.h	Mon Apr 20 22:58:53 2015 +0200
    13.2 +++ b/src/pgp_netpgp.h	Mon Apr 20 23:26:20 2015 +0200
    13.3 @@ -47,3 +47,10 @@
    13.4  
    13.5  PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern);
    13.6  
    13.7 +PEP_STATUS pgp_renew_key(
    13.8 +        PEP_SESSION session,
    13.9 +        const char *fpr,
   13.10 +        const timestamp *ts
   13.11 +    );
   13.12 +
   13.13 +PEP_STATUS pgp_revoke_key(PEP_SESSION session, const char *fpr);
    14.1 --- a/test/Makefile	Mon Apr 20 22:58:53 2015 +0200
    14.2 +++ b/test/Makefile	Mon Apr 20 23:26:20 2015 +0200
    14.3 @@ -29,7 +29,7 @@
    14.4  
    14.5  unit_tests: $(UNIT_TESTS)
    14.6  	for t in ./*_test ; do \
    14.7 -		LD_LIBRARY_PATH=~/lib:../src $$t ; \
    14.8 +		if LD_LIBRARY_PATH=~/lib:../src $$t ; then true; else break; fi \
    14.9  	done
   14.10  
   14.11  install:
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/keyedit_test.cc	Mon Apr 20 23:26:20 2015 +0200
    15.3 @@ -0,0 +1,64 @@
    15.4 +#include "platform.h"
    15.5 +
    15.6 +#include <iostream>
    15.7 +#include <fstream>
    15.8 +#include <string>
    15.9 +#include <assert.h>
   15.10 +
   15.11 +#include "pEpEngine.h"
   15.12 +
   15.13 +using namespace std;
   15.14 +
   15.15 +int main() {
   15.16 +    cout << "\n*** keyedit_test ***\n\n";
   15.17 +
   15.18 +    PEP_SESSION session;
   15.19 +    
   15.20 +    cout << "calling init()\n";
   15.21 +    PEP_STATUS status1 = init(&session);   
   15.22 +    assert(status1 == PEP_STATUS_OK);
   15.23 +    assert(session);
   15.24 +    cout << "init() completed.\n";
   15.25 +
   15.26 +    // generate test key
   15.27 +
   15.28 +    cout << "\ngenerating key for expire test\n";
   15.29 +    pEp_identity *identity = new_identity(
   15.30 +            "expire@dingens.org",
   15.31 +            NULL,
   15.32 +            "423",
   15.33 +            "expire test key"
   15.34 +        );
   15.35 +    assert(identity);
   15.36 +    PEP_STATUS generate_status = generate_keypair(session, identity);
   15.37 +    cout << "generate_keypair() exits with " << generate_status << "\n";
   15.38 +    assert(generate_status == PEP_STATUS_OK);
   15.39 +    cout << "generated key is " << identity->fpr << "\n";
   15.40 +
   15.41 +    string key(identity->fpr);
   15.42 +    free_identity(identity);
   15.43 +
   15.44 +    // keyedit test code
   15.45 +
   15.46 +    timestamp *ts = new_timestamp(time(0));
   15.47 +    ts->tm_year += 2;
   15.48 +
   15.49 +    cout << "key shell expire on " << asctime(ts) << "\n";
   15.50 +
   15.51 +    PEP_STATUS status2 = renew_key(session, key.c_str(), ts);
   15.52 +    cout << "renew_key() exited with " << status2 << "\n";
   15.53 +    assert(status2 == PEP_STATUS_OK);
   15.54 +    free_timestamp(ts);
   15.55 +
   15.56 +    cout << "key renewed.\n";
   15.57 +
   15.58 +    cout << "deleting key pair " << key.c_str() << "\n";
   15.59 +    PEP_STATUS delete_status = delete_keypair(session, key.c_str());
   15.60 +    cout << "delete_keypair() exits with " << delete_status << "\n";
   15.61 +    assert(delete_status == PEP_STATUS_OK);
   15.62 +
   15.63 +    cout << "calling release()\n";
   15.64 +    release(session);
   15.65 +    return 0;
   15.66 +}
   15.67 +