ENGINE-398: Moved key_reset into its own files ENGINE-398
authorKrista Bennett <krista@pep-project.org>
Fri, 14 Sep 2018 20:18:53 +0200
branchENGINE-398
changeset 29474b525ec0f95c
parent 2943 dd40810a7490
child 2948 3f66f366dc5f
ENGINE-398: Moved key_reset into its own files
src/key_reset.c
src/key_reset.h
src/message_api.c
src/pEpEngine.c
src/pEpEngine.h
src/pEp_internal.h
test/test_files/398_gabrielle_to_alice.eml
test/test_files/398_reset_from_alice_to_bob.eml
test/test_files/398_reset_from_alice_to_fenris.eml
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/key_reset.c	Fri Sep 14 20:18:53 2018 +0200
     1.3 @@ -0,0 +1,478 @@
     1.4 +// This file is under GNU General Public License 3.0
     1.5 +// see LICENSE.txt
     1.6 +
     1.7 +#include "pEp_internal.h"
     1.8 +#include "dynamic_api.h"
     1.9 +#include "message_api.h"
    1.10 +
    1.11 +#include <string.h>
    1.12 +#include <stdlib.h>
    1.13 +
    1.14 +PEP_STATUS has_key_reset_been_sent(
    1.15 +        PEP_SESSION session, 
    1.16 +        const char* user_id, 
    1.17 +        const char* revoked_fpr,
    1.18 +        bool* contacted)
    1.19 +{
    1.20 +    assert(session);
    1.21 +    assert(contacted);
    1.22 +    assert(user_id);
    1.23 +    assert(revoked_fpr);
    1.24 +    assert(!EMPTYSTR(user_id));
    1.25 +
    1.26 +    if (!session || !contacted || EMPTYSTR(revoked_fpr) || EMPTYSTR(user_id))
    1.27 +        return PEP_ILLEGAL_VALUE;
    1.28 +    
    1.29 +    *contacted = false;
    1.30 +                    
    1.31 +    char* alias_default = NULL;
    1.32 +    
    1.33 +    PEP_STATUS status = get_userid_alias_default(session, user_id, &alias_default);
    1.34 +    
    1.35 +    if (status == PEP_CANNOT_FIND_ALIAS || EMPTYSTR(alias_default)) {
    1.36 +        free(alias_default);
    1.37 +        alias_default = strdup(user_id);
    1.38 +    }
    1.39 +    
    1.40 +    sqlite3_reset(session->was_id_for_revoke_contacted);
    1.41 +    sqlite3_bind_text(session->was_id_for_revoke_contacted, 1, revoked_fpr, -1,
    1.42 +            SQLITE_STATIC);
    1.43 +    sqlite3_bind_text(session->was_id_for_revoke_contacted, 2, user_id, -1,
    1.44 +            SQLITE_STATIC);        
    1.45 +    int result = sqlite3_step(session->was_id_for_revoke_contacted);
    1.46 +    switch (result) {
    1.47 +        case SQLITE_ROW: {
    1.48 +            *contacted = (sqlite3_column_int(session->was_id_for_revoke_contacted, 0) != 0);
    1.49 +            break;
    1.50 +        }
    1.51 +        default:
    1.52 +            sqlite3_reset(session->was_id_for_revoke_contacted);
    1.53 +            free(alias_default);
    1.54 +            return PEP_UNKNOWN_DB_ERROR;
    1.55 +    }
    1.56 +
    1.57 +    sqlite3_reset(session->was_id_for_revoke_contacted);
    1.58 +    return PEP_STATUS_OK;
    1.59 +}
    1.60 +
    1.61 +//static const char *sql_set_revoke_contact_as_notified =
    1.62 +//    "insert or replace into revocation_contact_list(fpr, contact_id) values (?1, ?2) ;";
    1.63 +
    1.64 +PEP_STATUS set_reset_contact_notified(
    1.65 +        PEP_SESSION session,
    1.66 +        const char* revoke_fpr,
    1.67 +        const char* contact_id
    1.68 +    )
    1.69 +{
    1.70 +    PEP_STATUS status = PEP_STATUS_OK;
    1.71 +    
    1.72 +    assert(session && !EMPTYSTR(revoke_fpr) && !EMPTYSTR(contact_id));
    1.73 +    
    1.74 +    if (!session || EMPTYSTR(revoke_fpr) || EMPTYSTR(contact_id))
    1.75 +        return PEP_ILLEGAL_VALUE;
    1.76 +    
    1.77 +    sqlite3_reset(session->set_revoke_contact_as_notified);
    1.78 +    sqlite3_bind_text(session->set_revoke_contact_as_notified, 1, revoke_fpr, -1, 
    1.79 +            SQLITE_STATIC);
    1.80 +    sqlite3_bind_text(session->set_revoke_contact_as_notified, 2, contact_id, -1,
    1.81 +            SQLITE_STATIC);
    1.82 +
    1.83 +    int result;
    1.84 +    
    1.85 +    result = sqlite3_step(session->set_revoke_contact_as_notified);
    1.86 +    switch (result) {
    1.87 +        case SQLITE_DONE:
    1.88 +            status = PEP_STATUS_OK;
    1.89 +            break;
    1.90 +            
    1.91 +        default:
    1.92 +            status = PEP_UNKNOWN_DB_ERROR;
    1.93 +    }
    1.94 +    
    1.95 +    sqlite3_reset(session->set_revoke_contact_as_notified);
    1.96 +    return status;    
    1.97 +}
    1.98 +
    1.99 +
   1.100 +PEP_STATUS receive_key_reset(PEP_SESSION session,
   1.101 +                             message* reset_msg) {
   1.102 +
   1.103 +    if (!session || !reset_msg)
   1.104 +        return PEP_ILLEGAL_VALUE;
   1.105 +
   1.106 +    pEp_identity* sender_id = reset_msg->from;
   1.107 +                
   1.108 +    if (!sender_id)
   1.109 +        return PEP_MALFORMED_KEY_RESET_MSG;
   1.110 +        
   1.111 +    PEP_STATUS status = update_identity(session, sender_id);
   1.112 +    if (!sender_id->user_id)
   1.113 +        return PEP_UNKNOWN_ERROR;
   1.114 +        
   1.115 +    if (is_me(session, sender_id))
   1.116 +        return PEP_ILLEGAL_VALUE;    
   1.117 +        
   1.118 +    if (!reset_msg->longmsg || strncmp(reset_msg->longmsg, "OLD: ", 5) != 0) 
   1.119 +        return PEP_MALFORMED_KEY_RESET_MSG;
   1.120 +
   1.121 +    status = PEP_STATUS_OK;
   1.122 +    char* old_fpr = NULL;
   1.123 +    char* new_fpr = NULL;
   1.124 +    
   1.125 +    stringlist_t* keylist = NULL;
   1.126 +    pEp_identity* temp_ident = identity_dup(sender_id);
   1.127 +    if (!temp_ident) {
   1.128 +        status = PEP_OUT_OF_MEMORY;
   1.129 +        goto pep_free;
   1.130 +    }        
   1.131 +            
   1.132 +    char* rest = NULL;
   1.133 +    char* p = strtok_r(reset_msg->longmsg, "\r\n", &rest);
   1.134 +    if (!EMPTYSTR(p + 5))
   1.135 +        old_fpr = strdup(p + 5);
   1.136 +    else {
   1.137 +        status = PEP_MALFORMED_KEY_RESET_MSG;
   1.138 +        goto pep_free;
   1.139 +    }
   1.140 +    
   1.141 +    bool own_key = false;
   1.142 +    status = is_own_key(session, old_fpr, &own_key);
   1.143 +    
   1.144 +    if (own_key) {
   1.145 +        // Nope, no one can make us our own default. If we want to do that,
   1.146 +        // that's keysync, NOT key reset.
   1.147 +        status = PEP_ILLEGAL_VALUE;
   1.148 +        goto pep_free;
   1.149 +    }
   1.150 +            
   1.151 +    p = strtok_r(NULL, "\r\n", &rest); 
   1.152 +    if (strncmp(p, "NEW: ", 5) != 0  || EMPTYSTR(p + 5)) {
   1.153 +        status = PEP_MALFORMED_KEY_RESET_MSG;
   1.154 +        goto pep_free;
   1.155 +    }
   1.156 +
   1.157 +    new_fpr = strdup(p + 5);
   1.158 +        
   1.159 +    // Reset the original key
   1.160 +    status = key_reset(session, old_fpr, temp_ident);
   1.161 +    if (status != PEP_STATUS_OK)
   1.162 +        goto pep_free;
   1.163 +        
   1.164 +    status = find_keys(session, new_fpr, &keylist);
   1.165 +    if (status != PEP_STATUS_OK)
   1.166 +        goto pep_free;
   1.167 +        
   1.168 +    if (!keylist) {
   1.169 +        status = PEP_KEY_NOT_FOUND;
   1.170 +        goto pep_free;
   1.171 +    }
   1.172 +
   1.173 +    // alright, we've checked as best we can. Let's set that baby.
   1.174 +    sender_id->fpr = new_fpr;
   1.175 +    
   1.176 +    // This only sets as the default, does NOT TRUST IN ANY WAY
   1.177 +    sender_id->comm_type = sender_id->comm_type & (~PEP_ct_confirmed);
   1.178 +    status = set_identity(session, sender_id);
   1.179 +    
   1.180 +    sender_id->fpr = NULL; // ownership for free
   1.181 +pep_free:    
   1.182 +    free_stringlist(keylist);    
   1.183 +    free(old_fpr);
   1.184 +    free(new_fpr);
   1.185 +    free_identity(temp_ident);
   1.186 +    return status;
   1.187 +}
   1.188 +
   1.189 +PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
   1.190 +                                               message** dst, 
   1.191 +                                               pEp_identity* recip,
   1.192 +                                               const char* old_fpr,
   1.193 +                                               const char* new_fpr) {
   1.194 +                                                   
   1.195 +    if (!dst || !recip->user_id || !recip->address)
   1.196 +        return PEP_ILLEGAL_VALUE;
   1.197 +
   1.198 +    if (!old_fpr || !new_fpr)
   1.199 +        return PEP_ILLEGAL_VALUE;
   1.200 +        
   1.201 +    *dst = NULL;
   1.202 +    // Get own identity user has corresponded with
   1.203 +    pEp_identity* own_identity = NULL;
   1.204 +    
   1.205 +    PEP_STATUS status = get_own_ident_for_contact_id(session,
   1.206 +                                                     recip,
   1.207 +                                                     &own_identity);                                                       
   1.208 +    if (status != PEP_STATUS_OK)
   1.209 +        return status;
   1.210 +        
   1.211 +    message* reset_message = new_message(PEP_dir_outgoing);
   1.212 +    reset_message->from = own_identity;
   1.213 +    reset_message->to = new_identity_list(identity_dup(recip)); // ?
   1.214 +    
   1.215 +    const char* oldtag = "OLD: ";
   1.216 +    const char* newtag = "\nNEW: ";
   1.217 +    const size_t taglens = 11;
   1.218 +    size_t full_len = taglens + strlen(old_fpr) + strlen(new_fpr) + 2; // \n and \0
   1.219 +    char* longmsg = calloc(full_len, 1);
   1.220 +    strlcpy(longmsg, oldtag, full_len);
   1.221 +    strlcat(longmsg, old_fpr, full_len);
   1.222 +    strlcat(longmsg, newtag, full_len);
   1.223 +    strlcat(longmsg, new_fpr, full_len);
   1.224 +    strlcat(longmsg, "\n", full_len);
   1.225 +    reset_message->longmsg = longmsg; 
   1.226 +    reset_message->shortmsg = strdup("Key reset");    
   1.227 +    
   1.228 +    message* output_msg = NULL;
   1.229 +    
   1.230 +    status = encrypt_message(session, reset_message, NULL,
   1.231 +                             &output_msg, PEP_enc_PGP_MIME,
   1.232 +                             PEP_encrypt_flag_key_reset_only);
   1.233 +
   1.234 +    if (status == PEP_STATUS_OK)
   1.235 +        *dst = output_msg;
   1.236 +        
   1.237 +    free_message(reset_message);
   1.238 +    return status;
   1.239 +}
   1.240 +
   1.241 +PEP_STATUS send_key_reset_to_recents(PEP_SESSION session,
   1.242 +                                     const char* old_fpr, 
   1.243 +                                     const char* new_fpr) {
   1.244 +    assert(old_fpr);
   1.245 +    assert(new_fpr);
   1.246 +    assert(session);
   1.247 +    assert(session->messageToSend || session->sync_session->messageToSend);
   1.248 +    
   1.249 +    if (!session || !old_fpr || !new_fpr)
   1.250 +        return PEP_ILLEGAL_VALUE;
   1.251 +
   1.252 +    messageToSend_t send_cb = send_cb = session->messageToSend;
   1.253 +    void* sync_obj = session->sync_obj;
   1.254 +    if (!send_cb) {
   1.255 +        send_cb = session->sync_session->messageToSend;
   1.256 +        sync_obj = session->sync_session->sync_obj;
   1.257 +    }
   1.258 +    if (!send_cb)
   1.259 +        return PEP_SYNC_NO_MESSAGE_SEND_CALLBACK;
   1.260 +        
   1.261 +    identity_list* recent_contacts = NULL;
   1.262 +    message* reset_msg = NULL;
   1.263 +
   1.264 +    PEP_STATUS status = get_last_contacted(session, &recent_contacts);
   1.265 +    
   1.266 +    if (status != PEP_STATUS_OK)
   1.267 +        goto pep_free;
   1.268 +                    
   1.269 +    identity_list* curr_id_ptr = recent_contacts;
   1.270 +
   1.271 +    for (curr_id_ptr = recent_contacts; curr_id_ptr; curr_id_ptr = curr_id_ptr->next) {
   1.272 +        pEp_identity* curr_id = curr_id_ptr->ident;
   1.273 +        
   1.274 +        if (!curr_id)
   1.275 +            break;
   1.276 +    
   1.277 +        const char* user_id = curr_id->user_id;
   1.278 +        
   1.279 +        // Should be impossible, but?
   1.280 +        if (!user_id)
   1.281 +            continue;
   1.282 +        
   1.283 +        // Check if it's us - if so, pointless...
   1.284 +        if (is_me(session, curr_id))
   1.285 +            continue;
   1.286 +            
   1.287 +        // Check if they've already been told - this shouldn't be the case, but...
   1.288 +        bool contacted = false;
   1.289 +        status = has_key_reset_been_sent(session, user_id, old_fpr, &contacted);
   1.290 +        if (status != PEP_STATUS_OK)
   1.291 +            goto pep_free;
   1.292 +    
   1.293 +        if (contacted)
   1.294 +            continue;
   1.295 +            
   1.296 +        // if not, make em a message    
   1.297 +        reset_msg = NULL;
   1.298 +        
   1.299 +        status = create_standalone_key_reset_message(session,
   1.300 +                                                     &reset_msg,
   1.301 +                                                     curr_id,
   1.302 +                                                     old_fpr,
   1.303 +                                                     new_fpr);
   1.304 +
   1.305 +        if (status == PEP_CANNOT_FIND_IDENTITY) { // this is ok, just means we never mailed them 
   1.306 +            status = PEP_STATUS_OK;
   1.307 +            continue; 
   1.308 +        }
   1.309 +            
   1.310 +        if (status != PEP_STATUS_OK) {
   1.311 +            free(reset_msg);
   1.312 +            goto pep_free;
   1.313 +        }
   1.314 +        
   1.315 +        // insert into queue
   1.316 +        status = send_cb(sync_obj, reset_msg);
   1.317 +
   1.318 +        if (status != PEP_STATUS_OK) {
   1.319 +            free(reset_msg);
   1.320 +            goto pep_free;            
   1.321 +        }
   1.322 +            
   1.323 +        // Put into notified DB
   1.324 +        status = set_reset_contact_notified(session, old_fpr, user_id);
   1.325 +        if (status != PEP_STATUS_OK)
   1.326 +            goto pep_free;            
   1.327 +    }
   1.328 +    
   1.329 +pep_free:
   1.330 +    free_identity_list(recent_contacts);
   1.331 +    return status;
   1.332 +}
   1.333 +
   1.334 +DYNAMIC_API PEP_STATUS key_reset(
   1.335 +        PEP_SESSION session,
   1.336 +        const char* key_id,
   1.337 +        pEp_identity* ident
   1.338 +    )
   1.339 +{
   1.340 +    if (!session)
   1.341 +        return PEP_ILLEGAL_VALUE;
   1.342 +        
   1.343 +    PEP_STATUS status = PEP_STATUS_OK;
   1.344 +        
   1.345 +    char* fpr_copy = NULL;
   1.346 +    char* own_id = NULL;
   1.347 +    char* new_key = NULL;
   1.348 +    identity_list* key_idents = NULL;
   1.349 +    stringlist_t* keys = NULL;
   1.350 +    
   1.351 +    if (!EMPTYSTR(key_id)) {
   1.352 +        fpr_copy = strdup(key_id);
   1.353 +        if (!fpr_copy)
   1.354 +            return PEP_OUT_OF_MEMORY;
   1.355 +    }
   1.356 +        
   1.357 +    if (!ident) {
   1.358 +        // Get list of own identities
   1.359 +        status = get_default_own_userid(session, &own_id);
   1.360 +        if (status != PEP_STATUS_OK)
   1.361 +            goto pep_free;
   1.362 +            
   1.363 +        if (EMPTYSTR(fpr_copy)) {
   1.364 +            status = get_all_keys_for_user(session, own_id, &keys);
   1.365 +            if (status == PEP_STATUS_OK) {
   1.366 +                stringlist_t* curr_key;
   1.367 +                for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
   1.368 +                    status = key_reset(session, curr_key->value, NULL);
   1.369 +                    if (status != PEP_STATUS_OK)
   1.370 +                        break;
   1.371 +                }
   1.372 +            }
   1.373 +            goto pep_free;
   1.374 +        } // otherwise, we have a specific fpr to process
   1.375 +
   1.376 +        // fpr_copy exists, so... let's go.
   1.377 +        // Process own identities with this fpr
   1.378 +        status = get_identities_by_main_key_id(session, fpr_copy, &key_idents);
   1.379 +        
   1.380 +        if (status == PEP_STATUS_OK) {
   1.381 +            // have ident list, or should
   1.382 +            identity_list* curr_ident;
   1.383 +            for (curr_ident = key_idents; curr_ident && curr_ident->ident; 
   1.384 +                 curr_ident = curr_ident->next) {
   1.385 +                pEp_identity* this_identity = curr_ident->ident;
   1.386 +                status = key_reset(session, fpr_copy, this_identity);
   1.387 +                if (status != PEP_STATUS_OK)
   1.388 +                    break;                    
   1.389 +            }
   1.390 +        }
   1.391 +        goto pep_free;
   1.392 +    }
   1.393 +    else { // an identity was specified.       
   1.394 +        if (is_me(session, ident)) {            
   1.395 +            // FIXME: make sure this IS our fpr?
   1.396 +            
   1.397 +            // If it got sent in with an empty fpr...
   1.398 +            if (EMPTYSTR(fpr_copy)) {
   1.399 +                //
   1.400 +                // if (!EMPTYSTR(ident->fpr))
   1.401 +                //     fpr_copy = strdup(ident->fpr);
   1.402 +                status = _myself(session, ident, false, true);
   1.403 +                if (status == PEP_STATUS_OK && ident->fpr)
   1.404 +                    fpr_copy = strdup(ident->fpr);
   1.405 +                else {
   1.406 +                    // last resort?
   1.407 +                    // Get list of own identities
   1.408 +                    char* own_id = NULL;
   1.409 +                    status = get_default_own_userid(session, &own_id);
   1.410 +                    if (status == PEP_STATUS_OK)
   1.411 +                        status = get_user_default_key(session, own_id, &fpr_copy);
   1.412 +                    if (status != PEP_STATUS_OK || EMPTYSTR(fpr_copy))  {
   1.413 +                        free(own_id);
   1.414 +                        return (status == PEP_STATUS_OK ? PEP_KEY_NOT_FOUND : status);
   1.415 +                    }
   1.416 +                }
   1.417 +            }
   1.418 +                        
   1.419 +            free(ident->fpr);
   1.420 +            ident->fpr = fpr_copy;            
   1.421 +            // Create revocation
   1.422 +            status = revoke_key(session, fpr_copy, NULL);
   1.423 +            // generate new key
   1.424 +            if (status == PEP_STATUS_OK) {
   1.425 +                ident->fpr = NULL;
   1.426 +                status = generate_keypair(session, ident);
   1.427 +            }
   1.428 +            if (status == PEP_STATUS_OK) {
   1.429 +                new_key = strdup(ident->fpr);
   1.430 +                status = set_own_key(session, ident, new_key);
   1.431 +            }
   1.432 +            // mistrust fpr from trust
   1.433 +            ident->fpr = fpr_copy;
   1.434 +            
   1.435 +            ident->comm_type = PEP_ct_mistrusted;
   1.436 +            status = set_trust(session, ident);
   1.437 +            ident->fpr = NULL;
   1.438 +            
   1.439 +            // Done with old use of ident.
   1.440 +            if (status == PEP_STATUS_OK) {
   1.441 +                // Update fpr for outgoing
   1.442 +                status = myself(session, ident);
   1.443 +            }
   1.444 +            
   1.445 +            if (status == PEP_STATUS_OK)
   1.446 +                // cascade that mistrust for anyone using this key
   1.447 +                status = mark_as_compromised(session, fpr_copy);
   1.448 +            if (status == PEP_STATUS_OK)
   1.449 +                status = remove_fpr_as_default(session, fpr_copy);
   1.450 +            if (status == PEP_STATUS_OK)
   1.451 +                status = add_mistrusted_key(session, fpr_copy);
   1.452 +            // add to revocation list 
   1.453 +            if (status == PEP_STATUS_OK) 
   1.454 +                status = set_revoked(session, fpr_copy, new_key, time(NULL));            
   1.455 +            // for all active communication partners:
   1.456 +            //      active_send revocation
   1.457 +            if (status == PEP_STATUS_OK)
   1.458 +                status = send_key_reset_to_recents(session, fpr_copy, new_key);
   1.459 +                
   1.460 +        }
   1.461 +        else { // not is_me
   1.462 +            // remove fpr from all identities
   1.463 +            // remove fpr from all users
   1.464 +            if (status == PEP_STATUS_OK)
   1.465 +                status = remove_fpr_as_default(session, fpr_copy);
   1.466 +            // delete key from DB
   1.467 +            if (status == PEP_STATUS_OK) {};
   1.468 +//                status = delete_keypair(session, fpr_copy);
   1.469 +            // N.B. If this key is being replaced by something else, it
   1.470 +            // is done outside of this function.    
   1.471 +        }
   1.472 +    }
   1.473 +    
   1.474 +pep_free:
   1.475 +    free(fpr_copy);
   1.476 +    free(own_id);
   1.477 +    free_identity_list(key_idents);
   1.478 +    free_stringlist(keys);
   1.479 +    free(new_key);    
   1.480 +    return status;
   1.481 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/key_reset.h	Fri Sep 14 20:18:53 2018 +0200
     2.3 @@ -0,0 +1,93 @@
     2.4 +// This file is under GNU General Public License 3.0
     2.5 +// see LICENSE.txt
     2.6 +
     2.7 +#pragma once
     2.8 +
     2.9 +#include "key_reset.h"
    2.10 +
    2.11 +#include "pEpEngine.h"
    2.12 +#include "keymanagement.h"
    2.13 +#include "message.h"
    2.14 +#include "message_api.h"
    2.15 +#include "cryptotech.h"
    2.16 +
    2.17 +#ifdef __cplusplus
    2.18 +extern "C" {
    2.19 +#endif
    2.20 +
    2.21 +// FIXME: Proper docs!
    2.22 +//  Algorithm:
    2.23 +// 
    2.24 +//     Key Reset trigger; either manually or in another protocol, parameter key (optional)
    2.25 +// 
    2.26 +//     if identity given:
    2.27 +// 
    2.28 +//     key reset for one identity
    2.29 +// 
    2.30 +//     else
    2.31 +// 
    2.32 +//     For identity in own identities
    2.33 +// 
    2.34 +//     key reset for one identitiy
    2.35 +// 
    2.36 +//     Key Reset for identity:
    2.37 +// 
    2.38 +//     if own identity:
    2.39 +// 
    2.40 +//     Create revocation
    2.41 +// 
    2.42 +//     add to revocation list
    2.43 +// 
    2.44 +//     mistrust fpr from trust
    2.45 +// 
    2.46 +//     Remove fpr from ALL identities
    2.47 +// 
    2.48 +//     Remove fpr from ALL users
    2.49 +// 
    2.50 +//     generate new key
    2.51 +// 
    2.52 +//     for all active communication partners:
    2.53 +// 
    2.54 +//     active_send revocation
    2.55 +// 
    2.56 +//     else
    2.57 +// 
    2.58 +//     remove fpr from all identities
    2.59 +// 
    2.60 +//     remove fpr from all users
    2.61 +// 
    2.62 +//     delete key from key ring
    2.63 +DYNAMIC_API PEP_STATUS key_reset(
    2.64 +        PEP_SESSION session,
    2.65 +        const char* fpr,
    2.66 +        pEp_identity* ident
    2.67 +    );
    2.68 +
    2.69 +PEP_STATUS has_key_reset_been_sent(
    2.70 +        PEP_SESSION session, 
    2.71 +        const char* user_id, 
    2.72 +        const char* revoked_fpr,
    2.73 +        bool* contacted);
    2.74 +
    2.75 +PEP_STATUS set_reset_contact_notified(
    2.76 +        PEP_SESSION session,
    2.77 +        const char* revoke_fpr,
    2.78 +        const char* contact_id
    2.79 +    );
    2.80 +
    2.81 +PEP_STATUS receive_key_reset(PEP_SESSION session,
    2.82 +                             message* reset_msg);
    2.83 +
    2.84 +PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
    2.85 +                                               message** dst, 
    2.86 +                                               pEp_identity* recip,
    2.87 +                                               const char* old_fpr,
    2.88 +                                               const char* new_fpr);
    2.89 +                                               
    2.90 +PEP_STATUS send_key_reset_to_recents(PEP_SESSION session,
    2.91 +                                     const char* old_fpr, 
    2.92 +                                     const char* new_fpr);
    2.93 +    
    2.94 +#ifdef __cplusplus
    2.95 +}
    2.96 +#endif
     3.1 --- a/src/message_api.c	Thu Sep 13 13:59:53 2018 +0200
     3.2 +++ b/src/message_api.c	Fri Sep 14 20:18:53 2018 +0200
     3.3 @@ -1547,153 +1547,6 @@
     3.4      free(revoked_fpr);
     3.5  }
     3.6  
     3.7 -PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
     3.8 -                                               message** dst, 
     3.9 -                                               pEp_identity* recip,
    3.10 -                                               const char* old_fpr,
    3.11 -                                               const char* new_fpr) {
    3.12 -                                                   
    3.13 -    if (!dst || !recip->user_id || !recip->address)
    3.14 -        return PEP_ILLEGAL_VALUE;
    3.15 -
    3.16 -    if (!old_fpr || !new_fpr)
    3.17 -        return PEP_ILLEGAL_VALUE;
    3.18 -        
    3.19 -    *dst = NULL;
    3.20 -    // Get own identity user has corresponded with
    3.21 -    pEp_identity* own_identity = NULL;
    3.22 -    
    3.23 -    PEP_STATUS status = get_own_ident_for_contact_id(session,
    3.24 -                                                     recip,
    3.25 -                                                     &own_identity);                                                       
    3.26 -    if (status != PEP_STATUS_OK)
    3.27 -        return status;
    3.28 -        
    3.29 -    message* reset_message = new_message(PEP_dir_outgoing);
    3.30 -    reset_message->from = own_identity;
    3.31 -    reset_message->to = new_identity_list(identity_dup(recip)); // ?
    3.32 -    
    3.33 -    const char* oldtag = "OLD: ";
    3.34 -    const char* newtag = "\nNEW: ";
    3.35 -    const size_t taglens = 11;
    3.36 -    size_t full_len = taglens + strlen(old_fpr) + strlen(new_fpr) + 2; // \n and \0
    3.37 -    char* longmsg = calloc(full_len, 1);
    3.38 -    strlcpy(longmsg, oldtag, full_len);
    3.39 -    strlcat(longmsg, old_fpr, full_len);
    3.40 -    strlcat(longmsg, newtag, full_len);
    3.41 -    strlcat(longmsg, new_fpr, full_len);
    3.42 -    strlcat(longmsg, "\n", full_len);
    3.43 -    reset_message->longmsg = longmsg; 
    3.44 -    reset_message->shortmsg = strdup("Key reset");    
    3.45 -    
    3.46 -    message* output_msg = NULL;
    3.47 -    
    3.48 -    status = encrypt_message(session, reset_message, NULL,
    3.49 -                             &output_msg, PEP_enc_PGP_MIME,
    3.50 -                             PEP_encrypt_flag_key_reset_only);
    3.51 -
    3.52 -    if (status == PEP_STATUS_OK)
    3.53 -        *dst = output_msg;
    3.54 -        
    3.55 -    free_message(reset_message);
    3.56 -    return status;
    3.57 -}
    3.58 -
    3.59 -
    3.60 -PEP_STATUS send_key_reset_to_recents(PEP_SESSION session,
    3.61 -                                     const char* old_fpr, 
    3.62 -                                     const char* new_fpr) {
    3.63 -    assert(old_fpr);
    3.64 -    assert(new_fpr);
    3.65 -    assert(session);
    3.66 -    assert(session->messageToSend || session->sync_session->messageToSend);
    3.67 -    
    3.68 -    if (!session || !old_fpr || !new_fpr)
    3.69 -        return PEP_ILLEGAL_VALUE;
    3.70 -
    3.71 -    messageToSend_t send_cb = send_cb = session->messageToSend;
    3.72 -    void* sync_obj = session->sync_obj;
    3.73 -    if (!send_cb) {
    3.74 -        send_cb = session->sync_session->messageToSend;
    3.75 -        sync_obj = session->sync_session->sync_obj;
    3.76 -    }
    3.77 -    if (!send_cb)
    3.78 -        return PEP_SYNC_NO_MESSAGE_SEND_CALLBACK;
    3.79 -        
    3.80 -    identity_list* recent_contacts = NULL;
    3.81 -    message* reset_msg = NULL;
    3.82 -
    3.83 -    PEP_STATUS status = get_last_contacted(session, &recent_contacts);
    3.84 -    
    3.85 -    if (status != PEP_STATUS_OK)
    3.86 -        goto pep_free;
    3.87 -                    
    3.88 -    identity_list* curr_id_ptr = recent_contacts;
    3.89 -
    3.90 -    for (curr_id_ptr = recent_contacts; curr_id_ptr; curr_id_ptr = curr_id_ptr->next) {
    3.91 -        pEp_identity* curr_id = curr_id_ptr->ident;
    3.92 -        
    3.93 -        if (!curr_id)
    3.94 -            break;
    3.95 -    
    3.96 -        const char* user_id = curr_id->user_id;
    3.97 -        
    3.98 -        // Should be impossible, but?
    3.99 -        if (!user_id)
   3.100 -            continue;
   3.101 -        
   3.102 -        // Check if it's us - if so, pointless...
   3.103 -        if (is_me(session, curr_id))
   3.104 -            continue;
   3.105 -            
   3.106 -        // Check if they've already been told - this shouldn't be the case, but...
   3.107 -        bool contacted = false;
   3.108 -        status = has_key_reset_been_sent(session, user_id, old_fpr, &contacted);
   3.109 -        if (status != PEP_STATUS_OK)
   3.110 -            goto pep_free;
   3.111 -    
   3.112 -        if (contacted)
   3.113 -            continue;
   3.114 -            
   3.115 -        // if not, make em a message    
   3.116 -        reset_msg = NULL;
   3.117 -        
   3.118 -        status = create_standalone_key_reset_message(session,
   3.119 -                                                     &reset_msg,
   3.120 -                                                     curr_id,
   3.121 -                                                     old_fpr,
   3.122 -                                                     new_fpr);
   3.123 -
   3.124 -        if (status == PEP_CANNOT_FIND_IDENTITY) { // this is ok, just means we never mailed them 
   3.125 -            status = PEP_STATUS_OK;
   3.126 -            continue; 
   3.127 -        }
   3.128 -            
   3.129 -        if (status != PEP_STATUS_OK) {
   3.130 -            free(reset_msg);
   3.131 -            goto pep_free;
   3.132 -        }
   3.133 -        
   3.134 -        // insert into queue
   3.135 -        status = send_cb(sync_obj, reset_msg);
   3.136 -
   3.137 -        if (status != PEP_STATUS_OK) {
   3.138 -            free(reset_msg);
   3.139 -            goto pep_free;            
   3.140 -        }
   3.141 -            
   3.142 -        // Put into notified DB
   3.143 -        status = set_reset_contact_notified(session, old_fpr, user_id);
   3.144 -        if (status != PEP_STATUS_OK)
   3.145 -            goto pep_free;            
   3.146 -    }
   3.147 -    
   3.148 -pep_free:
   3.149 -    free_identity_list(recent_contacts);
   3.150 -    return status;
   3.151 -}
   3.152 -
   3.153 -
   3.154  PEP_cryptotech determine_encryption_format(message *msg)
   3.155  {
   3.156      assert(msg);
   3.157 @@ -3290,86 +3143,6 @@
   3.158  
   3.159  }
   3.160  
   3.161 -PEP_STATUS receive_key_reset(PEP_SESSION session,
   3.162 -                             message* reset_msg) {
   3.163 -
   3.164 -    if (!session || !reset_msg)
   3.165 -        return PEP_ILLEGAL_VALUE;
   3.166 -
   3.167 -    pEp_identity* sender_id = reset_msg->from;
   3.168 -                
   3.169 -    if (!sender_id)
   3.170 -        return PEP_MALFORMED_KEY_RESET_MSG;
   3.171 -        
   3.172 -    PEP_STATUS status = update_identity(session, sender_id);
   3.173 -    if (!sender_id->user_id)
   3.174 -        return PEP_UNKNOWN_ERROR;
   3.175 -        
   3.176 -    // FIXME: We'll have to change this for lists!!!    
   3.177 -    if (is_me(session, sender_id)) // hrm...
   3.178 -        return PEP_ILLEGAL_VALUE;
   3.179 -        
   3.180 -    if (!reset_msg->longmsg || strncmp(reset_msg->longmsg, "OLD: ", 5) != 0) 
   3.181 -        return PEP_MALFORMED_KEY_RESET_MSG;
   3.182 -
   3.183 -    status = PEP_STATUS_OK;
   3.184 -    char* old_fpr = NULL;
   3.185 -    char* new_fpr = NULL;
   3.186 -    
   3.187 -    stringlist_t* keylist = NULL;
   3.188 -    pEp_identity* temp_ident = identity_dup(sender_id);
   3.189 -    if (!temp_ident) {
   3.190 -        status = PEP_OUT_OF_MEMORY;
   3.191 -        goto pep_free;
   3.192 -    }        
   3.193 -            
   3.194 -    char* rest = NULL;
   3.195 -    char* p = strtok_r(reset_msg->longmsg, "\r\n", &rest);
   3.196 -    if (!EMPTYSTR(p + 5))
   3.197 -        old_fpr = strdup(p + 5);
   3.198 -    else {
   3.199 -        status = PEP_MALFORMED_KEY_RESET_MSG;
   3.200 -        goto pep_free;
   3.201 -    }
   3.202 -            
   3.203 -    p = strtok_r(NULL, "\r\n", &rest); 
   3.204 -    if (strncmp(p, "NEW: ", 5) != 0  || EMPTYSTR(p + 5)) {
   3.205 -        status = PEP_MALFORMED_KEY_RESET_MSG;
   3.206 -        goto pep_free;
   3.207 -    }
   3.208 -
   3.209 -    new_fpr = strdup(p + 5);
   3.210 -        
   3.211 -    // Reset the original key
   3.212 -    status = key_reset(session, old_fpr, temp_ident);
   3.213 -    if (status != PEP_STATUS_OK)
   3.214 -        goto pep_free;
   3.215 -        
   3.216 -    status = find_keys(session, new_fpr, &keylist);
   3.217 -    if (status != PEP_STATUS_OK)
   3.218 -        goto pep_free;
   3.219 -        
   3.220 -    if (!keylist) {
   3.221 -        status = PEP_KEY_NOT_FOUND;
   3.222 -        goto pep_free;
   3.223 -    }
   3.224 -
   3.225 -    // alright, we've checked as best we can. Let's set that baby.
   3.226 -    sender_id->fpr = new_fpr;
   3.227 -    
   3.228 -    // This only sets as the default, does NOT TRUST IN ANY WAY
   3.229 -    sender_id->comm_type = sender_id->comm_type & (~PEP_ct_confirmed);
   3.230 -    status = set_identity(session, sender_id);
   3.231 -    
   3.232 -    sender_id->fpr = NULL; // ownership for free
   3.233 -pep_free:    
   3.234 -    free_stringlist(keylist);    
   3.235 -    free(old_fpr);
   3.236 -    free(new_fpr);
   3.237 -    free_identity(temp_ident);
   3.238 -    return status;
   3.239 -}
   3.240 -
   3.241  DYNAMIC_API PEP_STATUS _decrypt_message(
   3.242          PEP_SESSION session,
   3.243          message *src,
   3.244 @@ -3957,156 +3730,6 @@
   3.245      return status;
   3.246  }
   3.247  
   3.248 -DYNAMIC_API PEP_STATUS key_reset(
   3.249 -        PEP_SESSION session,
   3.250 -        const char* key_id,
   3.251 -        pEp_identity* ident
   3.252 -    )
   3.253 -{
   3.254 -    if (!session)
   3.255 -        return PEP_ILLEGAL_VALUE;
   3.256 -        
   3.257 -    PEP_STATUS status = PEP_STATUS_OK;
   3.258 -        
   3.259 -    char* fpr_copy = NULL;
   3.260 -    char* own_id = NULL;
   3.261 -    char* new_key = NULL;
   3.262 -    identity_list* key_idents = NULL;
   3.263 -    stringlist_t* keys = NULL;
   3.264 -    
   3.265 -    if (!EMPTYSTR(key_id)) {
   3.266 -        fpr_copy = strdup(key_id);
   3.267 -        if (!fpr_copy)
   3.268 -            return PEP_OUT_OF_MEMORY;
   3.269 -    }
   3.270 -        
   3.271 -    if (!ident) {
   3.272 -        // Get list of own identities
   3.273 -        status = get_default_own_userid(session, &own_id);
   3.274 -        if (status != PEP_STATUS_OK)
   3.275 -            goto pep_free;
   3.276 -            
   3.277 -        if (EMPTYSTR(fpr_copy)) {
   3.278 -            status = get_all_keys_for_user(session, own_id, &keys);
   3.279 -            if (status == PEP_STATUS_OK) {
   3.280 -                stringlist_t* curr_key;
   3.281 -                for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
   3.282 -                    status = key_reset(session, curr_key->value, NULL);
   3.283 -                    if (status != PEP_STATUS_OK)
   3.284 -                        break;
   3.285 -                }
   3.286 -            }
   3.287 -            goto pep_free;
   3.288 -        } // otherwise, we have a specific fpr to process
   3.289 -
   3.290 -        // fpr_copy exists, so... let's go.
   3.291 -        // Process own identities with this fpr
   3.292 -        status = get_identities_by_main_key_id(session, fpr_copy, &key_idents);
   3.293 -        
   3.294 -        if (status == PEP_STATUS_OK) {
   3.295 -            // have ident list, or should
   3.296 -            identity_list* curr_ident;
   3.297 -            for (curr_ident = key_idents; curr_ident && curr_ident->ident; 
   3.298 -                 curr_ident = curr_ident->next) {
   3.299 -                pEp_identity* this_identity = curr_ident->ident;
   3.300 -                status = key_reset(session, fpr_copy, this_identity);
   3.301 -                if (status != PEP_STATUS_OK)
   3.302 -                    break;                    
   3.303 -            }
   3.304 -        }
   3.305 -        goto pep_free;
   3.306 -    }
   3.307 -    else { // an identity was specified.       
   3.308 -        if (is_me(session, ident)) {            
   3.309 -            // FIXME: make sure this IS our fpr?
   3.310 -            
   3.311 -            // If it got sent in with an empty fpr...
   3.312 -            if (EMPTYSTR(fpr_copy)) {
   3.313 -                //
   3.314 -                // if (!EMPTYSTR(ident->fpr))
   3.315 -                //     fpr_copy = strdup(ident->fpr);
   3.316 -                status = _myself(session, ident, false, true);
   3.317 -                if (status == PEP_STATUS_OK && ident->fpr)
   3.318 -                    fpr_copy = strdup(ident->fpr);
   3.319 -                else {
   3.320 -                    // last resort?
   3.321 -                    // Get list of own identities
   3.322 -                    char* own_id = NULL;
   3.323 -                    status = get_default_own_userid(session, &own_id);
   3.324 -                    if (status == PEP_STATUS_OK)
   3.325 -                        status = get_user_default_key(session, own_id, &fpr_copy);
   3.326 -                    if (status != PEP_STATUS_OK || EMPTYSTR(fpr_copy))  {
   3.327 -                        free(own_id);
   3.328 -                        return (status == PEP_STATUS_OK ? PEP_KEY_NOT_FOUND : status);
   3.329 -                    }
   3.330 -                }
   3.331 -            }
   3.332 -                        
   3.333 -            free(ident->fpr);
   3.334 -            ident->fpr = fpr_copy;            
   3.335 -            // Create revocation
   3.336 -            status = revoke_key(session, fpr_copy, NULL);
   3.337 -            // generate new key
   3.338 -            if (status == PEP_STATUS_OK) {
   3.339 -                ident->fpr = NULL;
   3.340 -                status = generate_keypair(session, ident);
   3.341 -            }
   3.342 -            if (status == PEP_STATUS_OK) {
   3.343 -                new_key = strdup(ident->fpr);
   3.344 -                status = set_own_key(session, ident, new_key);
   3.345 -            }
   3.346 -            // mistrust fpr from trust
   3.347 -            ident->fpr = fpr_copy;
   3.348 -            
   3.349 -            ident->comm_type = PEP_ct_mistrusted;
   3.350 -            status = set_trust(session, ident);
   3.351 -            ident->fpr = NULL;
   3.352 -            
   3.353 -            // Done with old use of ident.
   3.354 -            if (status == PEP_STATUS_OK) {
   3.355 -                // Update fpr for outgoing
   3.356 -                status = myself(session, ident);
   3.357 -            }
   3.358 -            
   3.359 -            if (status == PEP_STATUS_OK)
   3.360 -                // cascade that mistrust for anyone using this key
   3.361 -                status = mark_as_compromised(session, fpr_copy);
   3.362 -            if (status == PEP_STATUS_OK)
   3.363 -                status = remove_fpr_as_default(session, fpr_copy);
   3.364 -            if (status == PEP_STATUS_OK)
   3.365 -                status = add_mistrusted_key(session, fpr_copy);
   3.366 -            // add to revocation list 
   3.367 -            if (status == PEP_STATUS_OK) 
   3.368 -                status = set_revoked(session, fpr_copy, new_key, time(NULL));            
   3.369 -            // for all active communication partners:
   3.370 -            //      active_send revocation
   3.371 -            if (status == PEP_STATUS_OK)
   3.372 -                status = send_key_reset_to_recents(session, fpr_copy, new_key);
   3.373 -                
   3.374 -        }
   3.375 -        else { // not is_me
   3.376 -            // remove fpr from all identities
   3.377 -            // remove fpr from all users
   3.378 -            if (status == PEP_STATUS_OK)
   3.379 -                status = remove_fpr_as_default(session, fpr_copy);
   3.380 -            // delete key from DB
   3.381 -            if (status == PEP_STATUS_OK) {};
   3.382 -//                status = delete_keypair(session, fpr_copy);
   3.383 -            // N.B. If this key is being replaced by something else, it
   3.384 -            // is done outside of this function.    
   3.385 -        }
   3.386 -    }
   3.387 -    
   3.388 -pep_free:
   3.389 -    free(fpr_copy);
   3.390 -    free(own_id);
   3.391 -    free_identity_list(key_idents);
   3.392 -    free_stringlist(keys);
   3.393 -    free(new_key);    
   3.394 -    return status;
   3.395 -}
   3.396 -
   3.397 -
   3.398  // Note: if comm_type_determine is false, it generally means that
   3.399  // we were unable to get key information for anyone in the list,
   3.400  // likely because a key is missing.
     4.1 --- a/src/pEpEngine.c	Thu Sep 13 13:59:53 2018 +0200
     4.2 +++ b/src/pEpEngine.c	Fri Sep 14 20:18:53 2018 +0200
     4.3 @@ -4366,92 +4366,6 @@
     4.4  }
     4.5  
     4.6  
     4.7 -PEP_STATUS has_key_reset_been_sent(
     4.8 -        PEP_SESSION session, 
     4.9 -        const char* user_id, 
    4.10 -        const char* revoked_fpr,
    4.11 -        bool* contacted)
    4.12 -{
    4.13 -    assert(session);
    4.14 -    assert(contacted);
    4.15 -    assert(user_id);
    4.16 -    assert(revoked_fpr);
    4.17 -    assert(!EMPTYSTR(user_id));
    4.18 -
    4.19 -    if (!session || !contacted || EMPTYSTR(revoked_fpr) || EMPTYSTR(user_id))
    4.20 -        return PEP_ILLEGAL_VALUE;
    4.21 -    
    4.22 -    *contacted = false;
    4.23 -                    
    4.24 -    char* alias_default = NULL;
    4.25 -    
    4.26 -    PEP_STATUS status = get_userid_alias_default(session, user_id, &alias_default);
    4.27 -    
    4.28 -    if (status == PEP_CANNOT_FIND_ALIAS || EMPTYSTR(alias_default)) {
    4.29 -        free(alias_default);
    4.30 -        alias_default = strdup(user_id);
    4.31 -    }
    4.32 -    
    4.33 -    sqlite3_reset(session->was_id_for_revoke_contacted);
    4.34 -    sqlite3_bind_text(session->was_id_for_revoke_contacted, 1, revoked_fpr, -1,
    4.35 -            SQLITE_STATIC);
    4.36 -    sqlite3_bind_text(session->was_id_for_revoke_contacted, 2, user_id, -1,
    4.37 -            SQLITE_STATIC);        
    4.38 -    int result = sqlite3_step(session->was_id_for_revoke_contacted);
    4.39 -    switch (result) {
    4.40 -        case SQLITE_ROW: {
    4.41 -            *contacted = (sqlite3_column_int(session->was_id_for_revoke_contacted, 0) != 0);
    4.42 -            break;
    4.43 -        }
    4.44 -        default:
    4.45 -            sqlite3_reset(session->was_id_for_revoke_contacted);
    4.46 -            free(alias_default);
    4.47 -            return PEP_UNKNOWN_DB_ERROR;
    4.48 -    }
    4.49 -
    4.50 -    sqlite3_reset(session->was_id_for_revoke_contacted);
    4.51 -    return PEP_STATUS_OK;
    4.52 -}
    4.53 -
    4.54 -//static const char *sql_set_revoke_contact_as_notified =
    4.55 -//    "insert or replace into revocation_contact_list(fpr, contact_id) values (?1, ?2) ;";
    4.56 -
    4.57 -PEP_STATUS set_reset_contact_notified(
    4.58 -        PEP_SESSION session,
    4.59 -        const char* revoke_fpr,
    4.60 -        const char* contact_id
    4.61 -    )
    4.62 -{
    4.63 -    PEP_STATUS status = PEP_STATUS_OK;
    4.64 -    
    4.65 -    assert(session && !EMPTYSTR(revoke_fpr) && !EMPTYSTR(contact_id));
    4.66 -    
    4.67 -    if (!session || EMPTYSTR(revoke_fpr) || EMPTYSTR(contact_id))
    4.68 -        return PEP_ILLEGAL_VALUE;
    4.69 -    
    4.70 -    sqlite3_reset(session->set_revoke_contact_as_notified);
    4.71 -    sqlite3_bind_text(session->set_revoke_contact_as_notified, 1, revoke_fpr, -1, 
    4.72 -            SQLITE_STATIC);
    4.73 -    sqlite3_bind_text(session->set_revoke_contact_as_notified, 2, contact_id, -1,
    4.74 -            SQLITE_STATIC);
    4.75 -
    4.76 -    int result;
    4.77 -    
    4.78 -    result = sqlite3_step(session->set_revoke_contact_as_notified);
    4.79 -    switch (result) {
    4.80 -        case SQLITE_DONE:
    4.81 -            status = PEP_STATUS_OK;
    4.82 -            break;
    4.83 -            
    4.84 -        default:
    4.85 -            status = PEP_UNKNOWN_DB_ERROR;
    4.86 -    }
    4.87 -    
    4.88 -    sqlite3_reset(session->set_revoke_contact_as_notified);
    4.89 -    return status;    
    4.90 -}
    4.91 -
    4.92 -
    4.93  PEP_STATUS key_created(
    4.94          PEP_SESSION session,
    4.95          const char *fpr,
     5.1 --- a/src/pEpEngine.h	Thu Sep 13 13:59:53 2018 +0200
     5.2 +++ b/src/pEpEngine.h	Fri Sep 14 20:18:53 2018 +0200
     5.3 @@ -1177,54 +1177,6 @@
     5.4          uint64_t *revocation_date
     5.5      );
     5.6  
     5.7 -// Algorithm:
     5.8 -// 
     5.9 -//     Key Reset trigger; either manually or in another protocol, parameter key (optional)
    5.10 -// 
    5.11 -//     if identity given:
    5.12 -// 
    5.13 -//     key reset for one identity
    5.14 -// 
    5.15 -//     else
    5.16 -// 
    5.17 -//     For identity in own identities
    5.18 -// 
    5.19 -//     key reset for one identitiy
    5.20 -// 
    5.21 -//     Key Reset for identity:
    5.22 -// 
    5.23 -//     if own identity:
    5.24 -// 
    5.25 -//     Create revocation
    5.26 -// 
    5.27 -//     add to revocation list
    5.28 -// 
    5.29 -//     mistrust fpr from trust
    5.30 -// 
    5.31 -//     Remove fpr from ALL identities
    5.32 -// 
    5.33 -//     Remove fpr from ALL users
    5.34 -// 
    5.35 -//     generate new key
    5.36 -// 
    5.37 -//     for all active communication partners:
    5.38 -// 
    5.39 -//     active_send revocation
    5.40 -// 
    5.41 -//     else
    5.42 -// 
    5.43 -//     remove fpr from all identities
    5.44 -// 
    5.45 -//     remove fpr from all users
    5.46 -// 
    5.47 -//     delete key from key ring
    5.48 -DYNAMIC_API PEP_STATUS key_reset(
    5.49 -        PEP_SESSION session,
    5.50 -        const char* fpr,
    5.51 -        pEp_identity* ident
    5.52 -    );
    5.53 -
    5.54 -
    5.55  // key_created() - get creation date of a key
    5.56  //
    5.57  //  parameters:
    5.58 @@ -1349,19 +1301,6 @@
    5.59          identity_list** id_list
    5.60      );
    5.61  
    5.62 -
    5.63 -PEP_STATUS has_key_reset_been_sent(
    5.64 -        PEP_SESSION session, 
    5.65 -        const char* user_id, 
    5.66 -        const char* revoked_fpr,
    5.67 -        bool* contacted);
    5.68 -
    5.69 -PEP_STATUS set_reset_contact_notified(
    5.70 -        PEP_SESSION session,
    5.71 -        const char* revoke_fpr,
    5.72 -        const char* contact_id
    5.73 -    );
    5.74 -
    5.75  PEP_STATUS get_own_ident_for_contact_id(PEP_SESSION session,
    5.76                                            const pEp_identity* contact,
    5.77                                            pEp_identity** own_ident);
     6.1 --- a/src/pEp_internal.h	Thu Sep 13 13:59:53 2018 +0200
     6.2 +++ b/src/pEp_internal.h	Fri Sep 14 20:18:53 2018 +0200
     6.3 @@ -108,6 +108,8 @@
     6.4  #include "transport.h"
     6.5  #include "sync.h"
     6.6  
     6.7 +#include "key_reset.h"
     6.8 +
     6.9  #define NOT_IMPLEMENTED assert(0); return PEP_UNKNOWN_ERROR;
    6.10  
    6.11  struct _pEpSession;
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/test_files/398_gabrielle_to_alice.eml	Fri Sep 14 20:18:53 2018 +0200
     7.3 @@ -0,0 +1,87 @@
     7.4 +Message-ID: <pEp.PEW827.18NQTABD97IHX.3E6116A3-906D-4DAD-8BDD-3381606B4302@pep-project.org>
     7.5 +From: Gabi <pep-test-gabrielle@pep-project.org>
     7.6 +To: Alice is tired of Bob <pep.test.alice@pep-project.org>
     7.7 +Subject: =?utf-8?Q?p=E2=89=A1p?=
     7.8 +X-pEp-Version: 2.0
     7.9 +MIME-Version: 1.0
    7.10 +Content-Type: multipart/encrypted; boundary="d39e5287be3847623f45c9767504e45"; 
    7.11 + protocol="application/pgp-encrypted"
    7.12 +
    7.13 +--d39e5287be3847623f45c9767504e45
    7.14 +Content-Type: application/pgp-encrypted
    7.15 +
    7.16 +Version: 1
    7.17 +--d39e5287be3847623f45c9767504e45
    7.18 +Content-Type: application/octet-stream
    7.19 +Content-Transfer-Encoding: 7bit
    7.20 +Content-Disposition: inline; filename="msg.asc"
    7.21 +
    7.22 +-----BEGIN PGP MESSAGE-----
    7.23 +
    7.24 +hQEMAyZOqBcoGwQcAQf/QDYBUnJ8ASNE+aEOr/gKS1My4WXVbyCMtjLDHu2Ag0Rt
    7.25 +a7OKZNfJePc0DzNDAkj8Fj2OXVEBLAnpoE0E+Rs3V/rKsFjkQ0JXpK8LdstR+yC0
    7.26 +rqvRj8ga5lDkJMUGezk/bEJvsvdWTRiCsNqDOgR7FKo05Ize9Ce9NfxYjMDQrYfA
    7.27 +QaHcgb9naKe7VV8PJn4dtRHxHz0ZalyT2cTx3tge4MPv775I6ZUnLv8po3FUjx23
    7.28 +PFbjQv3lsV5BrzdBwYhZDbYUY8L7J3FJcHsJB0xQtlCPShfq++pEmuccl7KdV8fv
    7.29 +1Y6sv/hQstyAeAaI7g/QHcpYoOLqZq5isxjhTjsIP4UBDANaAgXZcwg/TQEIAKRc
    7.30 +MRhs9M0X4pZKd/q0K1/A7ey7AwbtjiBKV96hUS7rl/kpxtQrdzUJimpfylhDInUw
    7.31 +JRjJcsMXWrupcEwKr5UoXGgS7XfP6+by9qQYSJ9tKNiH0Mtu1BSXtLtx0b4Qoo7t
    7.32 +1i8qAGli4F96swXfgGQYtJAvG8RmSZHLNPe64WEaXoag9llKBHxzaNs6jAd4uTvg
    7.33 +iON4fv/YCUqv4ZS8VWVAw79xJDFIGSUFS6y+Zew01NOrIqQgRf6JmgGzcTTOmvlu
    7.34 +AyB2hTu8clTvGj9ux1GylspIAjQmDKbOmcbD7W2OYlUNJwfWlHu5HQoVOhvd3RnY
    7.35 +LBZnUGs3DTJYj5lUeg7S6wF+eM5HSqkBXvaUF1Xt2TdKEGPf1w57L8U1DXut5Sc8
    7.36 +GGtSXVFis2oV6thluZk3qCcAOyzBEf+Dl+yfRmguOAYsSCdSW9RYrkDZPV+arvGa
    7.37 +8jlsgANzpGPxoqHwUZUqYaAYseO3he4zYUmfWn62YFdeJryuqH7Gme4PxojVsgZr
    7.38 +TQBiLndaoI/aWlgDpXHnhKYsIRGGQbuxHOaLkAxZtzxE0ikhyeHIuY9TLMCrbnlJ
    7.39 +LhFmvidn2m0KB4KqLgv7m8vycaLGxOS0hgNKQPitOLYgV37QL44gZ+H6AwW6pV6r
    7.40 +e+V+FXh68h5AACJ/Ehk65Fl2MLt2XIg1IHopu2a3d6RjKlDnVWGoAZ8N0BkgVt79
    7.41 +2eSZ0I7FNIqmzKTNF94uUOvnFG93y8Dy9yr1bK8GQnHx6SxISfR1cl2c/KvPlVVe
    7.42 +7PO5hlVWvWbEyY89UcvTPn9lr22HXa5Ra2tAcUrw2xvjd83bxeBXigyjyAuzeDEZ
    7.43 +ycl7Jx+/ByrDpbjwUOoTfFUOkG5cHbFqGD1spO29iCUtnizA0oKawr74IvljnapY
    7.44 +cG2Kmbnoh2y+01aOv/BD0rzy6xO77HBUbH9VaKlnpyhgVu9dtDFYQCVYYimpY0aA
    7.45 +VQcLo18zMAsLOhVnWlFicrP1ghEq85bti9CopfkUnNxVIPIzzmXXUFb7tQQglfE6
    7.46 +2+xcC1yqwNp/Pa1EECCEJgfQMg9EhKk5F6AGAkrDuGIIWGWXCgHtbKOmOVUByVuP
    7.47 +pRVJmbNuq9t/qhp/PMrBXPOizcP1h4uLcGA97IbjDXkxOGQG7Tv1pPw/76se8wd9
    7.48 +JtUSd4a1UkwkjTzlGuToO0L0re0yYuLgloDpPftV47aa6JGITXoZ2FU0xk4C0bwM
    7.49 +D0+lVaUBHDcIbSGK0hw+s9RFOe+TG3zqNJF50f6wOy5s+M0CRhYC3ivk6CBmkGBu
    7.50 +hh/PMs4BXcSbyRxIIWYOPRKwa8XnRZRtsbh7FZpySkBITD2KfcNo3u3GV1R7aju3
    7.51 +7/NjF5nLScqNJ1cCcftXD42G7Ifm0VzqJvOwzTI9Dg8y8lxrQpYKGjxKAJGHfs2V
    7.52 +AcjBYcGinGeLZzxlV/YSXZ5rmTyVw6uELuCKSEltyqcdn1rOgQDLBLrbuVSkUJBd
    7.53 +emmHzIvlcSdvx1ObworrbTx1LH063u0fEcP8g9mLq5hL5y7uK54h9OO0mbcNvhAA
    7.54 +x8HrkKge8FXtb24T4s9qgn5Zt8elv9EqtNo0rSg1s5zc+Axy84lxqSCxBONv2uQG
    7.55 +bIQLO0CQHjehD7ALMlyeQnkgOP1VnvOxF/4L5RF8Giz6rmq+Q+UWGTEjS6BE3jyX
    7.56 +cZXVmbBT0HP36jToiJ6VqkO/oGPIDJxqBQXZYXeQRHr4P0WST2axoRRJ8Oq1ZImU
    7.57 +V8dbsHmfYQLXg2xf3ano8polC6Bovfl/15Wvhok5Dk4bNdwuNbEUIPUORfYw5+O2
    7.58 +QIXDDE3D0EcJJkS19sOqcSSfzqHNR2h9eEEKoKCLdjrehK6NHfwSbjHfi0C+J6D2
    7.59 +P6jGCvLbng7TgXpJk3z6/wJuZZkCTqP9xgPUpkrHuRaT4YISXxHWS5BgU852O7rm
    7.60 +gtQJF1mSIe5yrh/Ge7PdqjavMzDiLGmi89K013WpABy/0i8MyrhjYoI+3Xm4qX5a
    7.61 +cPzRgDcP0x6jxG3MCd3UxSnUpesnTcNqHtXTmvwBbVg+7c2WNyA/PUP8cYgpn7IN
    7.62 +VVAnzKN5tFCbmKoeVmycdqfiOq09RJ6hYp3qAJPcytSLxQXmxUdRt48yLzCBoqG5
    7.63 +N3kjFe62uMkx/foXEepAm6xFy0/H1n6q/pWeYehzcXtk0+AQaruM72ujMdEN3Ztc
    7.64 +ewBbsjwpj7mxkJqLb7OkCvXuVnk5GUtadweflyxbBkSh9dBZxpvPfAXbdI27VrPY
    7.65 +aUqr+x31rxq6E9mUfLfWLXEf+jXOpOyxI9E9JNIHPn8rbhPDykzin/4w/DcETjHd
    7.66 +6HmMYi0xu5++HLAf2gDk5V1oqfdmOgJTj6bZYCuSqpeWcUQ+PfflgfYOm4KcMcw4
    7.67 +gnHYQYLDFh/N5npLB0Q8gorHCNttZMjFHZWAwScgbum9VNb/P7bndUntPR1Rujb/
    7.68 +VwfAU7wRt2DaY2AP38XDcNVdKPL3aohnWItsH3P09rxaLfSt/gSQcfMsL2+TNi6A
    7.69 +OH/s+2m/M1B7bwjcPOg8bYYDrJwYATs/H8VKWy4uwpjvfll/CJijdJhPv/8uOzRq
    7.70 +0UFsfFYnhsh0CAL8sq2YHx/02nSiE9O2zdSMq5poqWUObzBXiRjGpPDaPoIYnDw2
    7.71 +/vDAFJmfvN7WMKQ9ipkktQAumalbf1nugzw5E9QjBLa0ZVAbreYW79KRFkQ9rJri
    7.72 +qtJHruemulHmYcw7JsCZacw2nfB/rm1TV+pt+l3rtWZpHVXuWAV7OxBf/OuYkZcZ
    7.73 +A4SGItArxaAuDD14GI7O+PiZLUml8hesfrQLwnn3a2bmt4wRE7yt0S1O6kkfb3kY
    7.74 +As2Zaauxt0lZF5Sm8WwSI/7L1gemox7cLErqlSZ83brqrB7AO/wc4rUsX9FQXKvl
    7.75 +AuTnUGJBw475+IRMy4cM5fmLHqbD/E/nbaXjhMEXpgni9yC9HnTvmF152Z/BzwhT
    7.76 +LJ1xmxcMuf7TDEe1YNq2uu+V7LlfkMsyuGLbErLU5KzHBTfh2drIISgB8XJPRcx/
    7.77 +QLAlI4pYre0pwxbW5RNq5X5C/drD0CKr0LYqmcP3rkpyzo3y7DpimwNSW4qfY1I1
    7.78 +wJG6X2LO0dUmiFHnGVZlFiA6XGO1kq6ElQAJICbztCJHBoXzEXXW8opkOTSTz510
    7.79 +1IKI1XbWONGX+XJptzRJPIEBJ4Pno0TcXmEKWiUuIK1MUxdvxH9mXvc9IZZhGu+z
    7.80 +zandg98QxTB0tyNW/htc7frdRKxRi7y/sY/Z9rhTXoEI1Y9DN+A1JsO8Mflk3s/A
    7.81 +alNpx31dbH71s3nvq8vjMEBQkMlhgyKz9vq/ZMf8lXHrkRd+3gUklbMDfy9YwabX
    7.82 +jq1+nbB6QCYZNcE2BEuwE2qv11PEoIjuRpP5oafg6ECjoRpyyH3vTUPYsKBSl/VD
    7.83 +JrzxvdRlrXPBOzkhug6WwlKnBnazuuQ135aiXT3NajiY2ftLG2y4IutrG/ttX39o
    7.84 +RH5IaaK+/fJMDMpc6BDueO27C4A1FfnF6SNLymh1b2hg8zVKeVUPctxiYNoHWC6F
    7.85 +6ihY
    7.86 +=/YtR
    7.87 +-----END PGP MESSAGE-----
    7.88 +
    7.89 +--d39e5287be3847623f45c9767504e45--
    7.90 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/test_files/398_reset_from_alice_to_bob.eml	Fri Sep 14 20:18:53 2018 +0200
     8.3 @@ -0,0 +1,115 @@
     8.4 +From: Alice in Wonderland <pep.test.alice@pep-project.org>
     8.5 +To: Bob's Burgers <pep.test.bob@pep-project.org>
     8.6 +Subject: =?utf-8?Q?p=E2=89=A1p?=
     8.7 +X-pEp-Version: 2.0
     8.8 +MIME-Version: 1.0
     8.9 +Content-Type: multipart/encrypted; boundary="41fb875950ea35e61360a605caa7977"; 
    8.10 + protocol="application/pgp-encrypted"
    8.11 +
    8.12 +--41fb875950ea35e61360a605caa7977
    8.13 +Content-Type: application/pgp-encrypted
    8.14 +
    8.15 +Version: 1
    8.16 +--41fb875950ea35e61360a605caa7977
    8.17 +Content-Type: application/octet-stream
    8.18 +Content-Transfer-Encoding: 7bit
    8.19 +Content-Disposition: inline; filename="msg.asc"
    8.20 +
    8.21 +-----BEGIN PGP MESSAGE-----
    8.22 +
    8.23 +hQEMA5Jd4qLmEMkZAQf+OnDf3f/QjoHqkMz/WdWwu0Trr4uN1k1QpNXgZEl8VpAk
    8.24 +Jlj1Akv3ksKMgNVRkdPGOSu14PE/xG7YxDDtzu4e0ruw3uFPl462i0WNz7fOmEdZ
    8.25 +YnMpfn4fNMf+H7/sG5BvaUs/Vdto7uhZ1+ebgeIcwVfKwiOs7NEvGghiJUMOteo/
    8.26 +Jqki9TMytX9sb58tL8x5d/dKbXEewNs1jqt28DKjAP+TCa+F2APN3z86GWBqaRse
    8.27 +JMnw5kOqDXEuyQ2XKA+nlLbThxMZ/5y0+4r4YeKmDqJdcqmSwggLet0LROhZajlV
    8.28 +O+UgkmIEpqKkj5yjG1Aobl8i+RbDSgcN2EcPjG+dHoUBDAOK25E37BudTgEH/1aK
    8.29 +OKh53th8VkK0XSnWqb3Th30X6/4pJNTi+gPM6jHGxRJmlcDgETw3oPii6Q9unWGF
    8.30 +LxFidBJLy91nfO+hxLwb/xVttQ8Gm8JO0ErjTPqdLC13sEN30nD6pBLl19CFPuYX
    8.31 +cq05KtFlSoip9T4Ie9Z9RfI3iX0FKYcOBUImXd41WD9VUMRghPKUyxILspkT5Lzr
    8.32 +hHHsAoDLMjAClwrJi+jFQ0tiBZXxA5E7g2uBvEWkI6zXlahR8LqFtczZRUKtkaUW
    8.33 +4B6SUhe/lhEysZ+OQeyicLN+UypYjHKOWRhZQ/c5ZCQ9WYQ8/fuvAW68vVauCVQz
    8.34 +Yi/Q+zUFYHuI0grCvCvS6wH1lh7lW+O6N6Q6yZEiuWkrKY/vPPsujSLSNV0rnhek
    8.35 +YIy/Dv6smWbmTmT0J4pu4LBOFeSxmoMPRqKvgGuxderlNd846y7y4UIcvHdZ7iit
    8.36 +bWQlTVvZiAUs3fZDRDGIHc55woaTaShHuQKsWq8Bz85gyZQyhf4OmqBKVdiV4Owx
    8.37 +5jdsFey96y+pK6hjMZxzBLDj5uLPtv9qpUAEw+2/GvX44RXf9gD+UEwo4KLx7iA2
    8.38 +lfktUa/93Ib3oFLFt0daej1bQVS6X+hREwt5djd2ufLitSzYQXGhDEKQ8PXnxT4G
    8.39 +oEaLuGS70CbQGk2WoWc5Lpb99K8Q6jCowh8YtcN+OKmjTvpeJlo0+bcTq1UJcbah
    8.40 +8vAmV9hnyJsOelCwKZnLGgx9q7ti86qtTHxtyRsvw0Pw0IFsUQBW9ZkIybOZrUfz
    8.41 +bPxt+de+jkbAsHK8gRhug2SWmb2XtEfhEoU6EMGZvaRwLF8GNvL1N5EOXFXKJ/dK
    8.42 +YR4mGDLBFjahq42wUlL0TADulj3E2vE89bLaUD23SI3yK2+Bva5JegI0YOg0cgKq
    8.43 +IZEpb29VeAxzae9/Gkmusp06GNsgjBqXgkLeO2rpPhzfrqgeKcD6I4UpTleSAP0U
    8.44 +ApdxisSnZlFjmOyxIqxbNV3JjYtApaeUi+B8nGmHnHE/lE/flSc8SdZne7MTq2iw
    8.45 +1pJMLDZNhWB+S2Ch6bhgYbnmiwBMJq+b/yEWOev8aL+ZGgWTAsWr2Kc//mdH0htH
    8.46 +Rk2Eckz/pyTJ7q0d/Tk9aOXVc5/Q5mWzrttrfoo40oJlR8IN3wcq5eKT+ZU3SygP
    8.47 +KRVt1iLWdj9/9TgeixtMlRUX7kXaBWRV/x0kX1mV9INEulzDvtwqcJiTRSX/pqPY
    8.48 +rTm+9FdpsPv+Rp1ep+iKkoPZRlzJh6z932+gZ6jam1eQz/UdBS4ttKMLvhxdaBgG
    8.49 +Rb29XKjIVRXdItq48n9UaBk91rGUT0Ol3i0NtiBIj5Z87tph+dq4XSLmhr720Imn
    8.50 +QvEl627xGbhb4xOE/MBxh0HYhSi1F2arxsIv+7c0YK5agbCqnl2+b+8L4Hlljlr3
    8.51 +FUu/GbkzOfkGDBYHYBfY48/VwEbDqoCDTef9uBJ7XQDFvwfhGwvKBOBnv5WW3j8i
    8.52 +pUVKby2x9oWTjH+7Tdn1oL4DiNcnyOGhmDOisWYhIDxFrWH02fHI5Ag9jvbY3mah
    8.53 +nrdWm8PNqnKRaS/fe++LYW3zKyo08+5TDGzQJqrOJ3wPK8UK51pXsMG1N/J3wxXr
    8.54 +saEBTzwhlPdc7bd734Grn0mmc/lBbBKK9VzgjwxS8lGRr0FOIdDTRdMJU42Zq5dC
    8.55 +vJ4fRDDx+0QlAos6+srlgYcmK6KFcp/9OpU+cNztQYolp4HNdZRPaG2TSdnl3SBi
    8.56 +e/DhE5JsVPVvlHXYPwPE1s4voxEQqce8BsbvNPBSCdN+UKd9/NAL3yCxqgQa+MPV
    8.57 +Cx7fJoIVD0Rpu4jBhga6ePxntuA16nNDefHh0BNKoptkbD3Ls0fWBAf0RC/kQbU8
    8.58 +wEeFwQfjIYES/OHKex51qhdxG+6yF3w5yehzbPoUPUM+Rmriwiq6lDEYDVfnJrK+
    8.59 +TqTxyHcDhLtgsCEo1DgS1wUMbbY7RbLXqfHUj+0VSpD65mkG6+0gu3gQLYGtTYDu
    8.60 +ssX/vYD63kuj2r2dYbN7muQrfPpOX4SGoh8Ao5e39A/G91+pD5MTrw4JUQ49EV6l
    8.61 +1KeewEivDBJ2inFPzg1ijRuQG5Zj/mDYCu2wkks0V2kqtikSIUAao/DK7UZ7fC1p
    8.62 +1NIYZcRjgL54P3fqize+0FW+a6FheLtBlzrcRXR9JXjpQHh/9zRw4PkGJOJsXv1L
    8.63 +GXcuPOL60wo5YF8SVrsmd6xzcrt1CB8egcQGFzdxOXrMC6sBCJ+xyWySZShotGvG
    8.64 +6/rwv1s7/Hl6ls5Pb1ii4FuxKSdrz70Fz01z066RszL7W0xqtgGcPw49/pBp1gCr
    8.65 +tqj/gD9/xM9j1N8gKtc9ABZVGS+fldUVxQ01S2Cg2riU0JpDAG6hVJyT/qWl6myQ
    8.66 +owLWdJOWcczyEa/aOiH+ls5yO7NT7hwT+EGWDx5B7VKA1JsouTBOK5BZbWLGI23G
    8.67 +SVVqVaRHiAeoqhIxmIHrzZK3hERohOG9T+IyMfOlMiGCfqPUUf/q7+LS3djTjQ2t
    8.68 +dEKfCpEdKmUOMQpb+I/lrbxP3dV+wEhmM7aSrRKke6PjiUXjfZMiGR/02evumhKi
    8.69 +aRqtwXy0s/QagTzo6z5Jp6ZqiALqZ2jopb390X+6Hz1GNvDZ1GSDX4KASlI7dnGA
    8.70 +8JzbKRwA1+H6Z+tgKFzl+96/56gtXTz6E1ynRF6tIp00j8sukBpTdi3lpZPAte/K
    8.71 +E3Ke7Ts0AyMHD5K35QJ0+zcunPrQ1AVfa7lBmUkBBE9Vf6jIgtAou+jWDMXZr5O9
    8.72 +u+qC4kSNoMglD3P2RO/XiqIdBCpcQigaVd+CTL+3vLUzm7swn36bRX+LYaHLDSUi
    8.73 +AKuhJ0UzRwetuxnUBQP3h7L8BzkfceixpUX97itmm6ZBZP3vl24eWPL8UKQwFboS
    8.74 +UuYzd4LOhv3G4nKSgFQcPj4isQlCJZyKsPZ95UHsA7SEuTgXQM/WXzWz7LtO2zOW
    8.75 +0tTVkBOyVADjqgXpihhA0hXYMJJAqhV99XRhiCc9LNOHqwPb72GZai3qQa8TC4gY
    8.76 +WXAzLM2oLI/DzhQNF1CRrGfj/tKfqrG6b9wH+NuW0fD2TapgsGF8Xgu8fMP0lcMs
    8.77 +6n5yJNm2Ocgu+j5nXMT4ovK10a/+ndI/oAB3a/YE7Z6pgnp7X6/fIkHLlwrAA3/W
    8.78 +jlH76PEFeVSBSWZy/1FwKYRHW33Dgync4SjK0UfTJdzU+N0CYetNYKGLvLV0Ffws
    8.79 +1CEqeXTNT0FUoeTNhdaUsgwJWmdRcIXZq5wduRFTWjJ69sRyHTGrFemg3WzUCpdm
    8.80 +AL/Ozbs2kC11bBjHovc6dne9SAXTQR9nZtf/+Zvu8Yyoswi/yG4WeRCIsEk1XVBj
    8.81 +SzyXRHCVMJC/HMGFTwNc4Iff/rcQnbFiTPvhjTsLC1vLgr5eLitF7QQW6Q9KPugH
    8.82 +VHmpNxlejj5nYIqUBal4w0TE5OvS+P9HPatwJCNcMjOh/NYdAIYv2lYRS+EepeC+
    8.83 +46EKB4s0o8hur5e1AHfhlsbrVZ6fyPPvNT0QTdAH6hgpHEZ/AUzxoJ6pTaN1smsJ
    8.84 +GIyqCPPy5Pq1VTv1fAx1wVZ7Xh3XZYDwv49qFO4swoYRspAAB47bW1sUGkI/gcSo
    8.85 +gtYWDYceP+GjsPKbLlfSfFUWirw4xMsbRH5BEmh0IGSGdycFv81PC1ii5VpWULFz
    8.86 +8M5qt9omY99EOppe6xVhw8gHRV09pT+ewizvJ4kQNyMs8/YqP3HUrPYSTaRnVZmG
    8.87 +AxJBQubYQyYx8r7sZnZRnorhlhBbl/0hY66eBbdU9kQpXDDE/S+Nt2iJ0I5c3hFt
    8.88 +Cs8sgIB0rsErIxjlefEo0nkfNgriF6ZGIIs2/NPjkxN5YDRLP6Ksbsq8SR+FFWCI
    8.89 +yhpd9478VilUfhd6c1uz8sLm5w7nQMTyBkjSS6rW+4XYa7uPu31EaVfm9bfodO8e
    8.90 +vKSZpvfcGsgZTuDx+CQkEpo/tAUsglnglvienoyoqFt33VZr3DaqQj6HZNsR/cZu
    8.91 +xt/72vHwhaPcFJyOn+qbbJ/P2rgsvbdszQhBJTfn4j63GPdHV7tVAChUFtX3fseR
    8.92 +PgpPcZea6JlaR+0CprUKRCsOQ7WZHNJIHjthavxegXi7qFJjfHN+/zrT1GUdyos/
    8.93 +NvEmO5ahXrmWVxfUjn5CTsByAkqzxInBsM+WS5iI4fq1oCsTsOyiVlCQi97+dAIi
    8.94 +3OIC+GDEsQbi+id2FJsMfKQuKwjmPCUrF6FYqpEUzwv8DKb+9Nb8OlKdFxayetGC
    8.95 +zkMvbuVsdEt7/Fale9RbiWkRqpSmgDFovFWEjJ73Ri/QZFP8Li3XjjnNt4cndc2Z
    8.96 +BoB+hAzv+FrpTInxGhrrCKGyBrEnKxRiCD9DDR0tKfiIbe3ZAXOo1MeZDDpCgr0Z
    8.97 +rAwb4AOkoAakS65sJ6ADtmTE4Jv4U2ulZABk8QG7yl5vxVSQcyJ+ZeVWXhW9S4rA
    8.98 +Kf+lB8I8T+rE69PKA3Y+ehPpFaRTx3rtktHfKfM3HUXz6OEcSrsqXreKE5am5qBM
    8.99 +QQ//vD9sHmkb9TTyrBYl0an/4DdxGDTxh+8lnhI/4bLrSrMluhkw6mRjow5yjA/+
   8.100 +zOYAwP15E5Xq+d7OHJomqTSnUtdFVLNs5ljIQQEXIsVDGU/UifQW6MycLREntHCW
   8.101 ++TZNRWk+H8JwVEPOnOEQCNzdCTwRhlhJkykxY8swaQezsdkG3ryNTqfT3ITRPOoA
   8.102 +l/huOyjHnWLo8496QciMLg6oBPieQhk9Ti93Mi2a5o8zDnOFvPc2etFWhYh3FdHQ
   8.103 +bMCESq6IqjVwz4u/terRQ+tZN751pGjhR5eS3/qJL8hvNHuRO2SoD7qI2SFo5d2H
   8.104 +8LtgQBMWWYQkF/WFieaLqvS+h/yrvXntfpv5+5O0Ceqk3rXWlC9Unjmvib4AUqPX
   8.105 +PUgbCJ06seSUS93Oy1VV+WTMxqi+5vvQ2stpudhos2BDQbpCIQL6wjcO/mQ3OAdr
   8.106 +SgRT1DJvq+n9JoRouyJHpnQuFpBZF5fMXy2sAoDsGqksy3sHvSjlKgZzwSetwiRk
   8.107 +Kixdan1Wbz5yp0VIcebyxQORTQqYHSicdTHmSzM8VrmgjeSxl+WWrn/uW36yJFP2
   8.108 +uCPoNKtF9BfgFu6sWgAOxXd5jTDR8LVFzi5oA9C2RCL5sZo4vZuQtPE1bSJYiKuW
   8.109 +QwnAFaNs9zV79FAmvvxjgoUWyjwB83yVtrrVaAyh/7KGzhF3tlGry/XN+kqWk2lW
   8.110 +bTpcLhSgzABkv0X12caWgV5uIMCDXxJv0h+x+P7C99+t/6xAGf0rR+5xmbN/EZjK
   8.111 +zJgnl/XNS18P7vciphoEcUSdQ7fTQmUyJIqBlSKlBbmtld7bph8nht9kEZdsfN+G
   8.112 +aSmWYw7HRaCXoq+IqVJeFoykvC35dBX/X30BV1d0HrO3kgTS87Fdl/7nF0boO528
   8.113 +ICgsOg1vvjXDZLqEyHrjxMCHpZiCNBksnQ==
   8.114 +=0apO
   8.115 +-----END PGP MESSAGE-----
   8.116 +
   8.117 +--41fb875950ea35e61360a605caa7977--
   8.118 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/test_files/398_reset_from_alice_to_fenris.eml	Fri Sep 14 20:18:53 2018 +0200
     9.3 @@ -0,0 +1,121 @@
     9.4 +Message-ID: <pEp.PEW17L.0RC7XPI9ZPB8X.97B39B40-10C2-404B-B8CC-54B79229F8FD@pep-project.org>
     9.5 +From: Alice in Wonderland <pep.test.alice@pep-project.org>
     9.6 +To: Fenris Leto Hawke <pep.test.fenris@thisstilldoesntwork.lu>
     9.7 +Subject: =?utf-8?Q?p=E2=89=A1p?=
     9.8 +X-pEp-Version: 2.0
     9.9 +MIME-Version: 1.0
    9.10 +Content-Type: multipart/encrypted; boundary="7e23a74c7397f0666f31d87d17b86a89"; 
    9.11 + protocol="application/pgp-encrypted"
    9.12 +
    9.13 +--7e23a74c7397f0666f31d87d17b86a89
    9.14 +Content-Type: application/pgp-encrypted
    9.15 +
    9.16 +Version: 1
    9.17 +--7e23a74c7397f0666f31d87d17b86a89
    9.18 +Content-Type: application/octet-stream
    9.19 +Content-Transfer-Encoding: 7bit
    9.20 +Content-Disposition: inline; filename="msg.asc"
    9.21 +
    9.22 +-----BEGIN PGP MESSAGE-----
    9.23 +
    9.24 +hQEMA5Jd4qLmEMkZAQgAj8cxagENLesYZm9tPxJWZv70pPUxrVbFG8U0of9V7Q+i
    9.25 +mypRO+/WoKg/fU7f1+JniBGb62ijwn8YuuZyxEch4TFQQrQ2u4BoJesy2nXr/JFM
    9.26 +wFLt+QcMwWbgAe9rmaPZ6E0TXpKFphz3Gz6wa6+21JNQiAlcUqv3UL7aNI8C7t0d
    9.27 +Oh0J9JxboAdJ2pi3AfDtaSb0vie6EcmEN+AeU3P+LnQlYyT9NK4AqaYGOgKa515e
    9.28 +NpCuogpAbnoRChlcRJGFlEBOJR1fuFKnY9VVpUppVQLSUm34BtIAIexsAfiiexXV
    9.29 +A/5XlqN4fzA/erFknlo/zl2jZGnsd5MVHZ5XClVeZIUBDAMSIv439cLEHAEH/RK1
    9.30 +OJ8G+vI+X9b4SZbcNrE6P1rnC6iZMqlIn+13fmnf0HE4ctLaAPhsazBB26mE+/pn
    9.31 +anby34JepDVvdplZHwKBML/053WeAo2luflrF5cZKoX6BE5P4/L5gTRWbYPWgPz9
    9.32 +uGiE8udceViK2PQyrPRXSGmoVxQ13mWVvIRK3hxB9HvK4YSAWf2Dd5ydMr8xUWUy
    9.33 +Mu6elZNT7fUGuFyfla4X0Jskc/dLr+zRhn4Nw2OdUwQ6ya0KPjeKwFLamyPa5Bat
    9.34 +u3q9d0YQJ+4GRRA7r++d/5EJvb8iT+YybU0IKgeaEkIGaUD51GNa/nUTHIn0Gdd2
    9.35 +o1AugkXRMyJIpsSRsi/S6wG/NW4D+ZfEevTFHnXea61aqwPeoQTwOScdjjpfRW9c
    9.36 +BQCEsygUP69n3Y0Ote+xuAsBnDw2oZh2OsRWbI6enedZhaNq3sbOj56KsE1lsHvz
    9.37 +kp9Ox9e519a4vE/kaQyHVQTcllDNttzLoLluWufs4kjZuyZ1Q97rTK5Fi4JJUyFk
    9.38 +stXdFLa9IkYxIJLg8iT3nls/het8BCHRJIsK3GU7sKPQJvcKOBmQvDfwpfYfXYOb
    9.39 +y1UhzNH31TlLyHLnfBex0RG909HmdFQC1lQ6cqE4cLjT2pC15aKjeTcP2igt6V7A
    9.40 +z2lGwZmtVqlCc0uyVKXNCe6jBrac+GTGyJjcWWYrkGY2MAC45893YwEIrqf93eGf
    9.41 +Wu1HPoV67B2X6xHDvvcehi3xldSZMsjd/HbcQ3w3HHH8meffsF27h/wmei1dSTj6
    9.42 +xsV0M0AnP/Ck0qm19XGindW8rgVP7khPG7yjI2ETsHKeEOdebgICFcoQY3lPv3F2
    9.43 +/26+i2AmF+SGfGW/t/I5Vpx3XuUFAKaP5fIQSZf1FRq4bZ3ctud5kT3/UC+pXedc
    9.44 +ItbFZIK4W+GFN5QfnyZ7qGOm0fO0mSFuhZHXzjLHIZB4NxW7SnCbBA7/MBM9QdyO
    9.45 +L/lXNLzW+f8JJyBRa/ro6ANv5euTzT20F4XNRZu026U2qmsDS0UrqMMkd1q6w0jn
    9.46 +fZggBNMgKw3k4S4VPGgICTDx7o9NkkuEP9LmOST1N9XhbIrGJXYj9ot05BwXp4aK
    9.47 +1saVD5v0OxSgQu5rqseT0ToElLD0te1kPjaFsxWSXqxgd6M612elm8T2gt2pcbOA
    9.48 +blJbqixncctuwWcmdh5Sq391gE+Ut38Wj/mJuJwlXbedgvMRGbVNjPMNg/wWWP4Z
    9.49 +awRk5b7rtAJ1F8bV3nJMQHUHJOG63mfRAOd0hpwA3VgVZpuVBwH3R9lW3t6b4RaH
    9.50 +hPF+J7CZyoi6FjgcuDob5F9T6BWzCx/gR8yVat/FNQu6mHc8JtiF5y8CYHyM7oLa
    9.51 +rNBM4Oaoc39N3wJx9bO+S7bc2A1whhtQom4o2VrLe1W0vxXMsW+v+mS3FAeG3QP1
    9.52 +88Mc3lQvXdQCAGiWBTUQ+CMcfFYaGVpIhQPZ2jW63CTkhX6adtHD0bBupfwxTz9p
    9.53 +KJcqhqDk29f52PPFb0HROvd04aVIhTUAlf6j9f8+1txP/6frRHOxwLKmI0OhEJBj
    9.54 +VsX5tB9K787fA4rd1vBScFi1pZ4k7HCKnTheeXxSp6DeE7dslgc4dQoyXPeny3ol
    9.55 +JugW8hB8lmZrEmYTJPcsglHbv6toUaTufkE2KFfkjpogwYLxMDLShIXgLAiQ5SX6
    9.56 +q/RWpFBr9o5un+z2D5FCwuhW9a3HVcWWWuxZ8YkWU736sKaLmZ8Lp7SsJKguUhpb
    9.57 +N/R8UddrfpbCCmIzAo8g2+XhcnfpPVw62yROFKkM3fNHOBgfeY0z3FY281V0/ytd
    9.58 +RH8E3CnGm7yBwn0XCx3uC9HtvOQL3Te5f88fCfSyEZJmg5EiXqBhf3uNw2QIj2x6
    9.59 +VwNGoVNd3QDJu0JeSAzzYfGcGkTQyEKgEs5zNr5YA7NeraJdv+CRzUu/kc7GNl94
    9.60 +8MWgb4oDgk6Mv6+uVxO0njyDQiIDTVnGItCxnsnllvvEW6zRyVsrm4viZmMSkVVf
    9.61 +X/kYDPIpmR//lJjjhYcJqFSieDYurkWs2BvZT5Di8xWZhllcGc/yB02BtK/uLkFT
    9.62 +RM3PsaLIef7OK2WZ/7Y4XuwIwFYCGK1gCv4TAiYkrrN+gzySMz2oId1BJLlA8CRL
    9.63 +DPAEW2QTucDXLOEpl0XFXSosiLUAf0pbZgVimWS1FdFV5M3SRxymoRFHUvJmaFKR
    9.64 +p7FjHmGxR4PhDrMOveDWa5331LYU8Ycvdbh2q7Cg4ZTt1UrqlPyZwbwxdSamPFrI
    9.65 +MhsTjUW6FuCmJ2AmmTbIafL+HohLAMG/gGMSK6qa8hjV9S3QEOmv0ieOce5Tlzka
    9.66 ++Jim//j+X1AGYFIb1Ho5YwBMY35GHTmRFQFeobAuFdmlKI6eziLi6gB0GFMGoViJ
    9.67 +yxEoLO0HN5iXnMPJ8jKw0dUg+qTNDAqS+8BS2CI1u0Ez7BtVuOqdCNCCT3qaBu6x
    9.68 +eFYJfs8eqQIwPmyDeShvYX1+klPvoKaut0HY8JOY2waI86wvfI6IKJKHcdCsIau/
    9.69 +EuHkoK9xAAx5YsvMXAiLBHQn+sdnrJ+iBweaLdBN5cmg6TAMlcE2gv5OTkL+mkz/
    9.70 +nHvBOR7qdbh5yxvlJd+SlI+hJrFuiM/MIwRmhTFefQxscOj16sDnIz7IHBEPhDoi
    9.71 +RGsJAwbj/pV5Sgjk2gFjgIQ+QvPzb5WYioY1GMOJKXJuea1ATrk35Fufg4y0aQZf
    9.72 +JtlrTrYz16jq7v+iFFD70zBuwIWAvvkNR2jyYT+meLkKmYugOVtlONJiwPqBQf9p
    9.73 +Xy5vsD3By/k2HFPEubVIS7w6kj21dPvbhugdAU8MT2oQZtPSyFUV/MCZRc6zu309
    9.74 +jZp84E2JWmF5hlDRXH6fiOiVaIJVdLaQ0aJA+75YzF1ilOJM2TSFXKyFOAYr6yQN
    9.75 +foOdXJ4ZPapCFKrIKmxEwhBMtN17cc7r0OOpxQMbhu6OOAup01UIc1d99qWWUKLm
    9.76 +2c+etOskQU7WMZisLtlfoVZtxalVjHmaCM18Zz0RxrjMnRnupYSH2WqXDC0xNpK0
    9.77 +6tHsBhct8vPMlWNB7gKtn6dB7tHFkeNUbR5a9wiM8VN9Sxck0F+RGr/Jr1A/s/jC
    9.78 +6todAmkDqenqun/3b5P35PMU2N4KzaOvlp9oDU6I+aGuhG4Q055aRXfHL5pmj6XD
    9.79 +t08D8HbRzXBxEqHn+b3vtlq+CyHX24Zf87HRCJTzNaG2vZt7xmIRfagImR9y8UzN
    9.80 +S3pNw9yCOL8e4VsJIAHQJ+nt2Gs1VhNb+El0CjYb6Uvpa+AkmLU4T5V1bKswiFO1
    9.81 +Q0SedRcBxmH+/UzkfT1eyG1RreSvhWZohOrLShu7kw+GKseDzXQrepBg1TLPcxgA
    9.82 +BVzf+1lQVqPCFTur4mt1bUGvcwgJ7ydFhZqp98JyFNRKH6Dp0FHOlBG9dEitKCG8
    9.83 +4SIiWO0o3Qor2OXK1f4hMrhnPuW1GHMuDQKLgdOv99C+C3DzbtOVDzUiFRG/qYmD
    9.84 +MM8Y9bWELwW0ofI/0N4J6cqZmIXv3qY9hgiWWZKvSnOTfgQ31T0ErSZ3LTM04UUo
    9.85 +OaxON34Z1X3O2vZW9nPgNagY/Nt8YhZL3rOgVKwDM1eLD++CNJUIjZFafBT4otv8
    9.86 +EX11LgJxIzz4UvezobqUjXQvYKdSz2sHvz+NXPcvfqUf8SwG+Cfm6lmAr/ZBskNw
    9.87 +M0mDCaRQbcOJ6mxNsOh3uf3VlzZeDpML11D1OskcnHC5aZw/0f6xzzGkYtvLSZmM
    9.88 +UsLoP62sANMgWdLRXALorFNp54gypkmFTi6FPI+8TK52pS+p63i3n21LZgSFY43r
    9.89 +2Rs/JiUZkfQ4CTHIhhUNtEU9G3W4b713zNAa47coaKW8DkxScnUgUNR6Jai/CLnP
    9.90 +lBt3MTs28aV/HEG3efguUzVZhUnrSsU3tTVy4Ok2P3+a88wN8bj30aFSsGq+v6Mc
    9.91 +M2eT6jK30uUpz144BSGMuOobauQI0JI2QgDu2UeuNdk5wQbsGuTs6/p8upFNg863
    9.92 +9a0PsEnpf0LteJB5voY9uy7FMNRF6kgoj/axa38VpWNx4WD2xAWI35/za287Vgm9
    9.93 +nS2r1TXiOnX1xHcD2gID3onVJrzD8VPYJcJjsfPzUfBsRp4KLl3gxdS4xg0YEVvG
    9.94 +utnOIPsKDK77kWWf1hmuI48xfALnN9EcBCJ4Cv4gQGQlaiIaAWMJJio562if3Nzw
    9.95 +sOcqqGn71kLw90v/xMl871vZtGFeNWBh8qFPO48w+5rci8KO5f8ya2dGsquMvuIw
    9.96 +7lEjLlpaQdKui/Fh68zWSmf5LzqjRCr0HiMFg53P46YEVHpDnyvPBPgzPrr9WKOA
    9.97 +CA2hB2Raf5bUgBPQnGor87w9QRcETlctFmgROSsysr9YBVQYYrqe69W6bq8kYfXN
    9.98 +G2gSOCItYJfSJiAgjZDlUpHwPdd4JaY6WwtfvcJbQJswAL6LRi+Yr7VHY0RyPX0c
    9.99 +rVSs8dtcelWTkl27IQ6OKw7pikDT2jfUOlQWGSatTOxGu5qsfR5yJQ8BY5wKHAkF
   9.100 +bpeg8nRHSF1wdbwssS6wJWFrn7vbTmZYavU3yLuQYAc4+wfGFwfv+BULfLBbyD0w
   9.101 +Hy+1aahhFg+aWs/0162xOKAO4d9+T6Woroy89Sr07Mn+wFROiPvskmkTEt3plJZl
   9.102 +mv/HWbOIY6PofKRXPsXZGpVgmmpnhiEvuvmbXagGpna65E5B5dJrFPhRccZi36k5
   9.103 +tNgpVEHz5Fn9l/hgEOs8j7Rw9yUiE862RD/LaiOwlOu/RqQbIf3yM4SUkFQ8Ef5Q
   9.104 +hi/rpmggBJD/Wc/2FJW3CHamXAoUdz72lKUSHf8sq0LGIqrIo+fP3NOr/7dywWPk
   9.105 +JBC0gODOKZGD3ZVfhWigcd6BQFMnkq7vFun67bz21x3n4u3m3eCDGMy5dS5cxx+C
   9.106 +kp2nq8p4qlsavklJPX72euPqli4oBNMb9EAVuzURsFPDAaXFxhNssTe20bU8FCic
   9.107 +/ghLgfv3Wot9yUcbZeVlikVANJeQ94Y1qphmGZ8UMJYfeoU61coj1W0fLwlbbkzO
   9.108 +otPBhe5GKRhe9dN0jTrXDXmBc+jVh02nc59LdJEyCsyIrjW5ypresxIJZf7M0HEx
   9.109 +JEfZ+Po/N8L9B/8h2I6xad7NUk0wrjROHsNUbHzOnYFQRQmlShZc8nV5A+YHSlzk
   9.110 +FP3A9grsvolwjkF71xbCNmsiH0tVosF6R0qteHeNHfdfLSluSRYC40BJqzq+sc7v
   9.111 +j6rdzjjS4AAsSwdvnz94BKUuSpD/0+ebiGcoQNg/8rwiZOXASNZqnoP1jX7A/cP8
   9.112 +e8OaBk1enYyQdNv4dq8G377rO5D3r9Vu3yX0D0UoYsvFX6LSniAl4385gyHw/1g8
   9.113 +T6EVLR5NOes+3L2HmEa454uQo6yOnYg9FaybX954dLWou3WgR/2p/K/0yWMGuCN8
   9.114 +XigjIc2E5Mt/VyrVImheLQ44i4u8x6KutcINzFbSjiJG0hIThCUOl5RKjzgKqrGj
   9.115 +dBbjq76p7FR+sJoTZVZ4qfd70Nmdi4ccQWfRXICLZGxnmYymMjfCc9A7JfEDl4E6
   9.116 +wGqDf7AKfsW6EhFNuT6a6d69OTAAYdL3ZhixbEOiNxOzrS1PS4T+g9/TMbTkCzHR
   9.117 +48ZJZb0/HS/idd9WXmUj02tSWYVtewxBSgbfes+fk0pM/zbiOjOqXgNMnPo0yngH
   9.118 +HBPs+/tkZX63EY8fk23UHm6U/6qpuMWFs62JR6kF1sb0MYCYY0rVxygrbVabFp5W
   9.119 +Gbdayy1g6mwuZA==
   9.120 +=ncTl
   9.121 +-----END PGP MESSAGE-----
   9.122 +
   9.123 +--7e23a74c7397f0666f31d87d17b86a89--
   9.124 +