merged
authorEdouard Tisserant <edouard@pep-project.org>
Mon, 13 Mar 2017 15:03:14 +0100
changeset 1648158e65c83311
parent 1645 5f5d81b05b0e
parent 1647 f089d9e32e60
child 1651 180d93b2a4b1
child 1653 949eca2414b7
merged
src/message_api.c
src/pEpEngine.c
src/pEp_internal.h
test/apple_mail_test.cc
     1.1 --- a/asn.1/devicegroup.asn1	Mon Mar 13 09:51:53 2017 +0100
     1.2 +++ b/asn.1/devicegroup.asn1	Mon Mar 13 15:03:14 2017 +0100
     1.3 @@ -14,12 +14,16 @@
     1.4  Beacon ::= NULL
     1.5  
     1.6  HandshakeRequest ::= SEQUENCE {
     1.7 +    /* UUID of receiver, group UUID if grouped */
     1.8      partner-id     UTF8String  (SIZE(1..1024)) OPTIONAL,
     1.9 +    /* Group UUID of sender, if grouped */
    1.10      group-id       UTF8String  (SIZE(1..1024)) OPTIONAL
    1.11  }
    1.12  
    1.13  GroupKeys ::= SEQUENCE {
    1.14 +    /* UUID of receiver */
    1.15      partner-id     UTF8String  (SIZE(1..1024)) OPTIONAL,
    1.16 +    /* Group UUID of sender */
    1.17      group-id       UTF8String  (SIZE(1..1024)) OPTIONAL,
    1.18      ownIdentities IdentityList
    1.19  }
     2.1 --- a/src/message_api.c	Mon Mar 13 09:51:53 2017 +0100
     2.2 +++ b/src/message_api.c	Mon Mar 13 15:03:14 2017 +0100
     2.3 @@ -813,7 +813,6 @@
     2.4  
     2.5  static PEP_rating key_rating(PEP_SESSION session, const char *fpr)
     2.6  {
     2.7 -    PEP_comm_type comm_type = PEP_ct_unknown;
     2.8  
     2.9      assert(session);
    2.10      assert(fpr);
    2.11 @@ -821,11 +820,20 @@
    2.12      if (session == NULL || fpr == NULL)
    2.13          return PEP_rating_undefined;
    2.14  
    2.15 -    PEP_STATUS status = get_key_rating(session, fpr, &comm_type);
    2.16 +
    2.17 +    PEP_comm_type bare_comm_type = PEP_ct_unknown;
    2.18 +    PEP_STATUS status = get_key_rating(session, fpr, &bare_comm_type);
    2.19      if (status != PEP_STATUS_OK)
    2.20          return PEP_rating_undefined;
    2.21  
    2.22 -    return _rating(comm_type, PEP_rating_undefined);
    2.23 +    PEP_comm_type least_trust_type = PEP_ct_unknown;
    2.24 +    least_trust(session, fpr, &least_trust_type);
    2.25 +
    2.26 +    if (least_trust_type == PEP_ct_unknown) {
    2.27 +        return _rating(bare_comm_type, PEP_rating_undefined);
    2.28 +    } else {
    2.29 +        return _rating(least_trust_type, PEP_rating_undefined);
    2.30 +    }
    2.31  }
    2.32  
    2.33  static PEP_rating worst_rating(PEP_rating rating1, PEP_rating rating2) {
    2.34 @@ -834,13 +842,14 @@
    2.35  
    2.36  static PEP_rating keylist_rating(PEP_SESSION session, stringlist_t *keylist)
    2.37  {
    2.38 -    PEP_rating rating = PEP_rating_reliable;
    2.39 +    PEP_rating rating = PEP_rating_undefined;
    2.40  
    2.41      assert(keylist && keylist->value);
    2.42      if (keylist == NULL || keylist->value == NULL)
    2.43          return PEP_rating_undefined;
    2.44  
    2.45      stringlist_t *_kl;
    2.46 +    bool first = true;
    2.47      for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
    2.48          PEP_comm_type ct;
    2.49          PEP_STATUS status;
    2.50 @@ -849,8 +858,12 @@
    2.51           
    2.52          if (_rating_ <= PEP_rating_mistrust)
    2.53              return _rating_;
    2.54 -
    2.55 -        if (rating == PEP_rating_undefined)
    2.56 +            
    2.57 +        if (first) {
    2.58 +            rating = _rating_;
    2.59 +            first = false;
    2.60 +        }
    2.61 +        else if (rating == PEP_rating_undefined)
    2.62              rating = worst_rating(rating, _rating_);
    2.63  
    2.64          if (_rating_ >= PEP_rating_reliable) {
    2.65 @@ -858,8 +871,10 @@
    2.66              if (status != PEP_STATUS_OK)
    2.67                  return PEP_rating_undefined;
    2.68              if (ct == PEP_ct_unknown){
    2.69 +                /* per edouard, we reduce reliable+ ratings to reliable because
    2.70 +                   ct unknown */
    2.71                  if (rating >= PEP_rating_reliable){
    2.72 -                    rating = worst_rating(rating, PEP_rating_reliable);
    2.73 +                    rating = PEP_rating_reliable; 
    2.74                  }
    2.75              }
    2.76              else{
    2.77 @@ -1537,6 +1552,20 @@
    2.78          while (*tail_pp) {
    2.79              tail_pp = &((*tail_pp)->next);
    2.80          }
    2.81 +        stringlist_t* second_list = *keylist_in_out;
    2.82 +        if (second_list) {
    2.83 +            char* listhead_val = second_list->value;
    2.84 +            if (!listhead_val || listhead_val[0] == '\0') {
    2.85 +                /* remove head, basically. This can happen when,
    2.86 +                   for example, the signature is detached and
    2.87 +                   verification is not seen directly after
    2.88 +                   decryption, so no signer is presumed in
    2.89 +                   the first construction of the keylist */
    2.90 +                *keylist_in_out = (*keylist_in_out)->next;
    2.91 +                second_list->next = NULL;
    2.92 +                free_stringlist(second_list);
    2.93 +            }
    2.94 +        }
    2.95          *tail_pp = *keylist_in_out;
    2.96      }
    2.97      
    2.98 @@ -1958,8 +1987,10 @@
    2.99                      if (_from == NULL)
   2.100                          goto enomem;
   2.101                      status = get_trust(session, _from);
   2.102 -                    if (_from->comm_type != PEP_ct_unknown)
   2.103 -                        *rating = _rating(_from->comm_type, PEP_rating_undefined);
   2.104 +                    if (_from->comm_type != PEP_ct_unknown) {
   2.105 +                        *rating = worst_rating(_rating(_from->comm_type, PEP_rating_undefined),
   2.106 +                                  kl_rating);
   2.107 +                    }
   2.108                      free_identity(_from);
   2.109                      if (status == PEP_CANNOT_FIND_IDENTITY)
   2.110                         status = PEP_STATUS_OK;
     3.1 --- a/src/pEpEngine.c	Mon Mar 13 09:51:53 2017 +0100
     3.2 +++ b/src/pEpEngine.c	Mon Mar 13 15:03:14 2017 +0100
     3.3 @@ -90,7 +90,10 @@
     3.4      "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
     3.5  
     3.6  static const char *sql_least_trust = 
     3.7 -    "select min(comm_type) from trust where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
     3.8 +    "select min(comm_type) from trust where"
     3.9 +    " pgp_keypair_fpr = upper(replace(?1,' ',''))"
    3.10 +    " and comm_type != 0;"; // ignores PEP_ct_unknown
    3.11 +    // returns PEP_ct_unknown only when no known trust is recorded
    3.12  
    3.13  static const char *sql_mark_as_compromized = 
    3.14      "update trust not indexed set comm_type = 15"
    3.15 @@ -169,7 +172,11 @@
    3.16      "select value, own from sequences where name = ?1 ;";
    3.17  
    3.18  static const char *sql_sequence_value3 = 
    3.19 -    "update sequences set value = ?2, own = (select own or ?3 from sequences where name = ?1) where name = ?1 ;";
    3.20 +    "insert or replace into sequences (name, value, own) "
    3.21 +    "values (?1, "
    3.22 +    "        ?2, "
    3.23 +    "       (select coalesce((select own or ?3 from sequences "
    3.24 +    "           where name = ?1), ?3))) ; ";
    3.25          
    3.26  // Revocation tracking
    3.27  static const char *sql_set_revoked =
    3.28 @@ -786,12 +793,6 @@
    3.29      assert(title);
    3.30      assert(entity);
    3.31  
    3.32 -    #ifndef NDEBUG
    3.33 -    #ifdef ANDROID
    3.34 -    LOGD(" %s :: %s :: %s ", title, entity, description);
    3.35 -    #endif
    3.36 -    #endif
    3.37 -
    3.38      if (!(session && title && entity))
    3.39          return PEP_ILLEGAL_VALUE;
    3.40  
    3.41 @@ -1431,6 +1432,7 @@
    3.42              break;
    3.43          }
    3.44          default:
    3.45 +            // never reached because of sql min()
    3.46              status = PEP_CANNOT_FIND_IDENTITY;
    3.47      }
    3.48  
     4.1 --- a/src/pEpEngine.h	Mon Mar 13 09:51:53 2017 +0100
     4.2 +++ b/src/pEpEngine.h	Mon Mar 13 15:03:14 2017 +0100
     4.3 @@ -402,7 +402,7 @@
     4.4      // range 0x90 to 0xbf: confirmed encryption
     4.5  
     4.6      PEP_ct_confirmed_encryption = 0x90,         // generic
     4.7 -    PEP_ct_OpenPGP_weak = 0x91,                 // RSA 1024 is weak
     4.8 +    PEP_ct_OpenPGP_weak = 0x91,                 // RSA 1024 is weak (unused)
     4.9  
    4.10      PEP_ct_to_be_checked_confirmed = 0xa0,      //generic
    4.11      PEP_ct_SMIME = 0xa1,
     5.1 --- a/src/pEp_internal.h	Mon Mar 13 09:51:53 2017 +0100
     5.2 +++ b/src/pEp_internal.h	Mon Mar 13 15:03:14 2017 +0100
     5.3 @@ -175,16 +175,18 @@
     5.4  
     5.5  #ifdef NDEBUG
     5.6  #define DEBUG_LOG(TITLE, ENTITY, DESC)
     5.7 -#define  LOGD(...)
     5.8  #else
     5.9 -#define DEBUG_LOG(TITLE, ENTITY, DESC) \
    5.10 -    log_event(session, (TITLE), (ENTITY), (DESC), "debug");
    5.11  #ifdef ANDROID
    5.12  #include <android/log.h>
    5.13 -#define  LOG_TAG    "pEpEngine"
    5.14 -#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
    5.15 +#define  LOG_MORE(...)  __android_log_print(ANDROID_LOG_DEBUG, "pEpEngine", " %s :: %s :: %s ", __VA_ARGS__);
    5.16 +#else
    5.17 +#include <stdio.h>
    5.18 +#define  LOG_MORE(...)  printf("pEpEngine DEBUG_LOG('%s','%s','%s')\n", __VA_ARGS__);
    5.19  #endif
    5.20 -
    5.21 +#define DEBUG_LOG(TITLE, ENTITY, DESC) {\
    5.22 +    log_event(session, (TITLE), (ENTITY), (DESC), "debug");\
    5.23 +    LOG_MORE((TITLE), (ENTITY), (DESC))\
    5.24 +}
    5.25  #endif
    5.26  
    5.27  // Space tolerant and case insensitive fingerprint string compare
     6.1 --- a/src/stringlist.c	Mon Mar 13 09:51:53 2017 +0100
     6.2 +++ b/src/stringlist.c	Mon Mar 13 15:03:14 2017 +0100
     6.3 @@ -163,13 +163,13 @@
     6.4  
     6.5  DYNAMIC_API void free_stringlist(stringlist_t *stringlist)
     6.6  {
     6.7 -    stringlist_t *curr = stringlist;;
     6.8 +    stringlist_t *curr = stringlist;
     6.9      
    6.10      while (curr) {
    6.11          stringlist_t *next = curr->next;
    6.12          free(curr->value);
    6.13 +        curr->value = NULL;
    6.14          free(curr);
    6.15          curr = next;
    6.16      }
    6.17  }
    6.18 -
     7.1 --- a/src/sync.c	Mon Mar 13 09:51:53 2017 +0100
     7.2 +++ b/src/sync.c	Mon Mar 13 15:03:14 2017 +0100
     7.3 @@ -185,13 +185,16 @@
     7.4              continue;
     7.5  #endif
     7.6          }
     7.7 -        else if ((status = receive_sync_msg(session, msg, &timeout) != PEP_STATUS_OK)) {
     7.8 +        else {
     7.9 +            status = receive_sync_msg(session, msg, &timeout);
    7.10 +            if (status != PEP_STATUS_OK && status != PEP_MESSAGE_IGNORE) {
    7.11  #ifndef NDEBUG
    7.12 -            char buffer[MAX_LINELENGTH];
    7.13 -            memset(buffer, 0, MAX_LINELENGTH);
    7.14 -            snprintf(buffer, MAX_LINELENGTH, "problem with msg received: %d\n", (int) status);
    7.15 -            log_event(session, buffer, "pEp sync protocol", NULL, NULL);
    7.16 +                char buffer[MAX_LINELENGTH];
    7.17 +                memset(buffer, 0, MAX_LINELENGTH);
    7.18 +                snprintf(buffer, MAX_LINELENGTH, "problem with msg received: %d\n", (int) status);
    7.19 +                log_event(session, buffer, "pEp sync protocol", NULL, NULL);
    7.20  #endif
    7.21 +            }
    7.22          }
    7.23      }
    7.24  
     8.1 --- a/src/sync.h	Mon Mar 13 09:51:53 2017 +0100
     8.2 +++ b/src/sync.h	Mon Mar 13 15:03:14 2017 +0100
     8.3 @@ -243,8 +243,10 @@
     8.4      // handshake accepted by user
     8.5      SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
     8.6      SYNC_NOTIFY_ACCEPTED_GROUP_CREATED,
     8.7 -    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED
     8.8 +    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED,
     8.9  
    8.10 +    // handshake dialog must be closed
    8.11 +    SYNC_NOTIFY_OVERTAKEN
    8.12  } sync_handshake_signal;
    8.13  
    8.14  // notifyHandshake() - notify UI about sync handshaking process
     9.1 --- a/src/sync_actions.c	Mon Mar 13 09:51:53 2017 +0100
     9.2 +++ b/src/sync_actions.c	Mon Mar 13 15:03:14 2017 +0100
     9.3 @@ -205,6 +205,7 @@
     9.4      if (!(session && partner))
     9.5          return PEP_ILLEGAL_VALUE;
     9.6  
     9.7 +    // TODO : disable sync globally if not in a group
     9.8      status = set_identity_flags(session, partner,
     9.9              partner->flags | PEP_idf_not_for_sync);
    9.10  
    9.11 @@ -343,9 +344,15 @@
    9.12      PEP_STATUS status = PEP_STATUS_OK;
    9.13  
    9.14      assert(session);
    9.15 -    
    9.16 +   
    9.17 +    // make a new uuid 
    9.18 +    char new_uuid[37];
    9.19 +    pEpUUID uuid;
    9.20 +    uuid_generate_random(uuid);
    9.21 +    uuid_unparse_upper(uuid, new_uuid);
    9.22 +
    9.23      // take that new uuid as group-id
    9.24 -    status = set_device_group(session, session->sync_uuid);
    9.25 +    status = set_device_group(session, new_uuid);
    9.26  
    9.27      return status;
    9.28  }
    10.1 --- a/src/sync_impl.c	Mon Mar 13 09:51:53 2017 +0100
    10.2 +++ b/src/sync_impl.c	Mon Mar 13 15:03:14 2017 +0100
    10.3 @@ -31,6 +31,33 @@
    10.4      } u;
    10.5  };
    10.6  
    10.7 +static bool _is_own_uuid( PEP_SESSION session, UTF8String_t *uuid)
    10.8 +{
    10.9 +    return strncmp(session->sync_session->sync_uuid,
   10.10 +                   (const char*)uuid->buf, uuid->size) == 0;
   10.11 +}
   10.12 +
   10.13 +static bool _is_own_group_uuid( PEP_SESSION session, UTF8String_t *uuid, char** our_group)
   10.14 +{
   10.15 +    PEP_STATUS status = PEP_STATUS_OK;
   10.16 +    char *devgrp = NULL;
   10.17 +
   10.18 +    if(our_group == NULL || *our_group == NULL)
   10.19 +        status = get_device_group(session, &devgrp);
   10.20 +    else
   10.21 +        devgrp = *our_group;
   10.22 +
   10.23 +    bool res = (status == PEP_STATUS_OK && devgrp && devgrp[0] &&
   10.24 +        strncmp(devgrp,(const char*)uuid->buf, uuid->size) == 0);
   10.25 +
   10.26 +    if(our_group == NULL)
   10.27 +        free(devgrp);
   10.28 +    else if(*our_group == NULL)
   10.29 +        *our_group = devgrp;
   10.30 +
   10.31 +    return res;
   10.32 +}
   10.33 +
   10.34  PEP_STATUS receive_sync_msg(
   10.35          PEP_SESSION session,
   10.36          sync_msg_t *sync_msg,
   10.37 @@ -54,6 +81,13 @@
   10.38              goto error;
   10.39          }
   10.40  
   10.41 +        partner = Identity_to_Struct(&msg->header.me, NULL);
   10.42 +        if (!partner){
   10.43 +            status = PEP_OUT_OF_MEMORY;
   10.44 +            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   10.45 +            goto error;
   10.46 +        }
   10.47 +
   10.48          msgIsFromGroup = msg->header.devicegroup;
   10.49  
   10.50          switch (msg->payload.present) {
   10.51 @@ -62,46 +96,96 @@
   10.52                  break;
   10.53  
   10.54              case DeviceGroup_Protocol__payload_PR_handshakeRequest:
   10.55 -                // re-check uuid in case sync_uuid changed while in the queue
   10.56 -                if (strncmp(session->sync_session->sync_uuid,
   10.57 -                            (const char *)msg->payload.choice.handshakeRequest.partner_id->buf,
   10.58 -                            msg->payload.choice.handshakeRequest.partner_id->size) != 0){
   10.59 -                    status = PEP_SYNC_ILLEGAL_MESSAGE;
   10.60 +            {
   10.61 +                // re-check uuid in case sync_uuid or group changed while in the queue
   10.62 +                char *own_group_id = NULL;
   10.63 +                bool is_for_me = _is_own_uuid(session, 
   10.64 +                    msg->payload.choice.handshakeRequest.partner_id);
   10.65 +                bool is_for_group = !is_for_me && _is_own_group_uuid(session, 
   10.66 +                    msg->payload.choice.handshakeRequest.partner_id, &own_group_id);
   10.67 +                if (!(is_for_me || is_for_group)){
   10.68 +                    status = PEP_MESSAGE_IGNORE;
   10.69                      goto error;
   10.70                  }
   10.71  
   10.72 -                if(msgIsFromGroup) {
   10.73 -                    char *devgrp = NULL;
   10.74 -                    status = get_device_group(session, &devgrp);
   10.75 +                UTF8String_t *guuid = msg->payload.choice.handshakeRequest.group_id;
   10.76 +                if(msgIsFromGroup && guuid && guuid->buf && guuid->size) {
   10.77 +                    bool is_from_own_group = _is_own_group_uuid(session, 
   10.78 +                                                                guuid, &own_group_id);
   10.79  
   10.80 -                    // if handshake request comes from same group ignore, ignore it
   10.81 -                    if (status == PEP_STATUS_OK && devgrp && devgrp[0] &&
   10.82 -                        strncmp(devgrp,
   10.83 -                                (const char *)msg->payload.choice.handshakeRequest.group_id->buf,
   10.84 -                                msg->payload.choice.handshakeRequest.group_id->size) != 0){
   10.85 -                        status = PEP_SYNC_ILLEGAL_MESSAGE;
   10.86 +                    // Filter handshake requests from own group
   10.87 +                    if(is_from_own_group) {
   10.88 +                        status = PEP_MESSAGE_IGNORE;
   10.89                          goto error;
   10.90                      }
   10.91 -                    free(devgrp);
   10.92 -                    // if it comes from another group, then this is groupmerge
   10.93 +
   10.94 +                    // if it comes from another group, 
   10.95 +                    // we want to communicate with that group
   10.96 +                    // insert group_id given in handshake request 
   10.97 +                    // into partner's id
   10.98 +
   10.99 +                    free(partner->user_id);
  10.100 +                    partner->user_id = strndup((const char*)guuid->buf, guuid->size);
  10.101 +                    if(partner->user_id == NULL){
  10.102 +                        status = PEP_OUT_OF_MEMORY;
  10.103 +                        goto error;
  10.104 +                    }
  10.105 +
  10.106 +                    // if it comes from another group, and we are grouped,
  10.107 +                    // then this is groupmerge
  10.108                  }
  10.109  
  10.110                  event = HandshakeRequest;
  10.111                  break;
  10.112  
  10.113 +            }
  10.114              case DeviceGroup_Protocol__payload_PR_updateRequest:
  10.115                  event = UpdateRequest;
  10.116                  break;
  10.117  
  10.118              case DeviceGroup_Protocol__payload_PR_groupKeys:
  10.119              {
  10.120 -                // re-check uuid in case sync_uuid changed while in the queue
  10.121 -                if (strncmp(session->sync_session->sync_uuid,
  10.122 -                            (const char *)msg->payload.choice.groupKeys.partner_id->buf,
  10.123 -                            msg->payload.choice.groupKeys.partner_id->size) != 0){
  10.124 +                // re-check uuid in case sync_uuid or group_uuid changed while in the queue
  10.125 +                char *own_group_id = NULL;
  10.126 +                UTF8String_t *puuid = msg->payload.choice.groupKeys.partner_id;
  10.127 +                bool is_for_me = _is_own_uuid(session, puuid);
  10.128 +                bool is_for_group = !is_for_me &&
  10.129 +                                    _is_own_group_uuid(session, 
  10.130 +                                        puuid, &own_group_id);
  10.131 +                if (!(is_for_me || is_for_group)){
  10.132 +                    status = PEP_MESSAGE_IGNORE;
  10.133 +                    goto error;
  10.134 +                }
  10.135 +
  10.136 +                UTF8String_t *guuid = msg->payload.choice.groupKeys.group_id;
  10.137 +
  10.138 +                // GroupKeys come from groups, no choice
  10.139 +                if(!(msgIsFromGroup && guuid && guuid->buf && guuid->size)) {
  10.140                      status = PEP_SYNC_ILLEGAL_MESSAGE;
  10.141                      goto error;
  10.142                  }
  10.143 +
  10.144 +                // Filter groupKeys from own group
  10.145 +                bool is_from_own_group = _is_own_group_uuid(session, 
  10.146 +                                                            guuid, 
  10.147 +                                                            &own_group_id);
  10.148 +                if(is_from_own_group) {
  10.149 +                    // FixMe : protocol shouldn't allow this
  10.150 +                    status = PEP_SYNC_ILLEGAL_MESSAGE;
  10.151 +                    goto error;
  10.152 +                }
  10.153 +
  10.154 +                // insert group_id given in groupKeys into partner's id
  10.155 +                free(partner->user_id);
  10.156 +                partner->user_id = strndup((const char*)guuid->buf, guuid->size);
  10.157 +                if(partner->user_id == NULL){
  10.158 +                    status = PEP_OUT_OF_MEMORY;
  10.159 +                    goto error;
  10.160 +                }
  10.161 +
  10.162 +                // if it comes from another group, and we are grouped,
  10.163 +                // then this is groupmerge's groupKeys
  10.164 +
  10.165                  group_keys_extra_t *group_keys_extra;
  10.166                  group_keys_extra = malloc(sizeof(group_keys_extra_t));
  10.167                  if(group_keys_extra == NULL){
  10.168 @@ -110,11 +194,9 @@
  10.169                      goto error;
  10.170                  }
  10.171  
  10.172 -                char *group_id = strndup(
  10.173 -                        (char*)msg->payload.choice.groupKeys.group_id->buf,
  10.174 -                        msg->payload.choice.groupKeys.group_id->size);
  10.175 +                char *group_id = strndup((char*)guuid->buf, guuid->size);
  10.176  
  10.177 -                if (msg->payload.choice.groupKeys.group_id && !group_id){
  10.178 +                if (!group_id){
  10.179                      status = PEP_OUT_OF_MEMORY;
  10.180                      free(group_keys_extra);
  10.181                      ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
  10.182 @@ -159,12 +241,6 @@
  10.183                  goto error;
  10.184          }
  10.185  
  10.186 -        partner = Identity_to_Struct(&msg->header.me, NULL);
  10.187 -        if (!partner){
  10.188 -            status = PEP_OUT_OF_MEMORY;
  10.189 -            ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
  10.190 -            goto error;
  10.191 -        }
  10.192      }
  10.193      else{
  10.194          partner = sync_msg->u.event.partner;
  10.195 @@ -436,46 +512,86 @@
  10.196                      switch (msg->payload.present) {
  10.197                          // HandshakeRequest needs encryption
  10.198                          case DeviceGroup_Protocol__payload_PR_handshakeRequest:
  10.199 +                        {
  10.200 +                            UTF8String_t *puuid = 
  10.201 +                              msg->payload.choice.handshakeRequest.partner_id;
  10.202 +                            bool is_for_me = _is_own_uuid(session, puuid);
  10.203 +                            bool is_for_group = !is_for_me && 
  10.204 +                                                _is_own_group_uuid(
  10.205 +                                                    session, puuid, NULL);
  10.206 +
  10.207 +                            // Reject handshake requests not addressed to us
  10.208                              if (rating < PEP_rating_reliable ||
  10.209 -                                strncmp(session->sync_session->sync_uuid,
  10.210 -                                        (const char *)msg->payload.choice.handshakeRequest.partner_id->buf,
  10.211 -                                        msg->payload.choice.handshakeRequest.partner_id->size) != 0){
  10.212 -                                discard = true;
  10.213 -                                goto free_all;
  10.214 -                            }
  10.215 -                            
  10.216 -                            break;
  10.217 -                        // accepting GroupKeys needs encryption and trust of peer device
  10.218 -                        case DeviceGroup_Protocol__payload_PR_groupKeys:
  10.219 -                        {
  10.220 -                            if (!keylist || rating < PEP_rating_reliable ||
  10.221 -                                // message is only consumed by instance it is addressed to
  10.222 -                                (strncmp(session->sync_session->sync_uuid,
  10.223 -                                        (const char *)msg->payload.choice.groupKeys.partner_id->buf,
  10.224 -                                        msg->payload.choice.groupKeys.partner_id->size) != 0)){
  10.225 +                                !(is_for_me || is_for_group)){
  10.226                                  discard = true;
  10.227                                  goto free_all;
  10.228                              }
  10.229  
  10.230 -                            // check trust of identity using user_id given in msg.header.me
  10.231 -                            // to exacly match identity of device, the one trusted in
  10.232 -                            // case of accepted handshake
  10.233 -                            pEp_identity *_from = new_identity(NULL, 
  10.234 -                                                               keylist->value,
  10.235 -                                                               user_id,
  10.236 -                                                               NULL);
  10.237 -                            if (_from == NULL){
  10.238 -                                status = PEP_OUT_OF_MEMORY;
  10.239 -                                goto free_all;
  10.240 +                            // do not consume handshake request for group
  10.241 +                            if(is_for_group){ 
  10.242 +                                force_keep_msg = true;
  10.243                              }
  10.244 -                            status = get_trust(session, _from);
  10.245 -                            if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_strong_encryption) {
  10.246 -                                status = PEP_STATUS_OK;
  10.247 -                                free_identity(_from);
  10.248 +                            break;
  10.249 +                        }
  10.250 +                        // accepting GroupKeys needs encryption and trust of peer device
  10.251 +                        case DeviceGroup_Protocol__payload_PR_groupKeys:
  10.252 +                        {
  10.253 +                            UTF8String_t *puuid = msg->payload.choice.groupKeys.partner_id;
  10.254 +                            bool is_for_me = _is_own_uuid(session, puuid);
  10.255 +                            bool is_for_group = !is_for_me &&
  10.256 +                                                _is_own_group_uuid(session, 
  10.257 +                                                    puuid, NULL);
  10.258 +                            if (!keylist || rating < PEP_rating_reliable ||
  10.259 +                                // message is only consumed by instance it is addressed to
  10.260 +                                !(is_for_me || is_for_group)){
  10.261                                  discard = true;
  10.262                                  goto free_all;
  10.263                              }
  10.264 -                            free_identity(_from);
  10.265 +
  10.266 +                            // do not consume groupKeys for group
  10.267 +                            if(is_for_group){ 
  10.268 +                                // This happens in case case of groupmerge
  10.269 +                                force_keep_msg = true;
  10.270 +                            }
  10.271 +
  10.272 +                            // Trust check disabled here but it still it should be safe.
  10.273 +                            // SameIdentity checks in state machine ensures that we only
  10.274 +                            // store groupkeys signed by device or group that have been 
  10.275 +                            // previously accepted in handshake.
  10.276 +                            //
  10.277 +                            // // check trust of identity using user_id given in msg.header.me
  10.278 +                            // // to exacly match identity of device, the one trusted in
  10.279 +                            // // case of accepted handshake from a sole device
  10.280 +                            // pEp_identity *_from = new_identity(NULL, 
  10.281 +                            //                                    keylist->value,
  10.282 +                            //                                    user_id,
  10.283 +                            //                                    NULL);
  10.284 +                            // if (_from == NULL){
  10.285 +                            //     status = PEP_OUT_OF_MEMORY;
  10.286 +                            //     goto free_all;
  10.287 +                            // }
  10.288 +                            // status = get_trust(session, _from);
  10.289 +                            // if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_strong_encryption) {
  10.290 +
  10.291 +                            //     // re-try with group_id instead, in case of handshake with pre-existing group
  10.292 +                            //     UTF8String_t *guuid = msg->payload.choice.groupKeys.group_id;
  10.293 +                            //     free(_from->user_id);
  10.294 +                            //     if ((_from->user_id = strndup((const char*)guuid->buf, guuid->size)) == NULL){
  10.295 +                            //         free_identity(_from);
  10.296 +                            //         status = PEP_OUT_OF_MEMORY;
  10.297 +                            //         goto free_all;
  10.298 +                            //     }
  10.299 +                            //     _from->comm_type = PEP_ct_unknown;
  10.300 +
  10.301 +                            //     status = get_trust(session, _from);
  10.302 +                            //     if (status != PEP_STATUS_OK || _from->comm_type < PEP_ct_strong_encryption) {
  10.303 +                            //         status = PEP_STATUS_OK;
  10.304 +                            //         free_identity(_from);
  10.305 +                            //         discard = true;
  10.306 +                            //         goto free_all;
  10.307 +                            //     }
  10.308 +                            // }
  10.309 +                            // free_identity(_from);
  10.310                              break;
  10.311                          }
  10.312                          case DeviceGroup_Protocol__payload_PR_groupUpdate:
  10.313 @@ -532,7 +648,7 @@
  10.314                      // don't free message now that it is in the queue
  10.315                      goto free_userid;
  10.316                  }
  10.317 -                else if (status == PEP_OWN_SEQUENCE) {
  10.318 +                else if (status == PEP_OWN_SEQUENCE || status == PEP_SEQUENCE_VIOLATED) {
  10.319                      status = PEP_STATUS_OK;
  10.320                      discard = true;
  10.321                      goto free_all;
  10.322 @@ -827,30 +943,30 @@
  10.323      free(group_keys_extra);
  10.324  }
  10.325  
  10.326 -group_keys_extra_t* group_keys_extra_dup(group_keys_extra_t* groupkeys)
  10.327 +group_keys_extra_t* group_keys_extra_dup(group_keys_extra_t* group_key_extra_src)
  10.328  {
  10.329 -    group_keys_extra_t *group_keys_extra;
  10.330 -    group_keys_extra = malloc(sizeof(group_keys_extra_t));
  10.331 -    if(group_keys_extra == NULL){
  10.332 +    group_keys_extra_t *group_key_extra_dst;
  10.333 +    group_key_extra_dst = calloc(1,sizeof(group_keys_extra_t));
  10.334 +    if(group_key_extra_dst == NULL){
  10.335          return NULL;
  10.336      }
  10.337  
  10.338 -    char *group_id = strdup(group_keys_extra->group_id);
  10.339 +    char *group_id = strdup(group_key_extra_src->group_id);
  10.340  
  10.341 -    if (group_keys_extra->group_id && !group_id){
  10.342 -        free(group_keys_extra);
  10.343 +    if (group_key_extra_dst->group_id && !group_id){
  10.344 +        free(group_key_extra_dst);
  10.345          return NULL;
  10.346      }
  10.347 -    group_keys_extra->group_id = group_id;
  10.348 +    group_key_extra_dst->group_id = group_id;
  10.349  
  10.350 -    identity_list *group_keys = identity_list_dup(group_keys_extra->group_keys);;
  10.351 +    identity_list *group_keys = identity_list_dup(group_key_extra_src->group_keys);;
  10.352      if (!group_keys) {
  10.353          free(group_id);
  10.354 -        free(group_keys_extra);
  10.355 +        free(group_key_extra_dst);
  10.356          return NULL;
  10.357      }
  10.358 -    group_keys_extra->group_keys = group_keys;
  10.359 +    group_key_extra_dst->group_keys = group_keys;
  10.360  
  10.361 -    return group_keys_extra;
  10.362 +    return group_key_extra_dst;
  10.363  }
  10.364  
    11.1 --- a/sync/devicegroup.fsm	Mon Mar 13 09:51:53 2017 +0100
    11.2 +++ b/sync/devicegroup.fsm	Mon Mar 13 15:03:14 2017 +0100
    11.3 @@ -142,6 +142,7 @@
    11.4                      do notifyAcceptedDeviceAdded(partner);
    11.5                      go Grouped;
    11.6                  }
    11.7 +                go Sole;
    11.8              }
    11.9              on Cancel go Sole;
   11.10              on Timeout {
   11.11 @@ -208,10 +209,12 @@
   11.12              }
   11.13              on HandshakeRejected(Identity partner) {
   11.14                  do rejectHandshake(partner);             // stores rejection of partner
   11.15 +                do sendGroupUpdate;
   11.16                  go Grouped;
   11.17              }
   11.18              on HandshakeAccepted(Identity partner) {
   11.19                  do acceptHandshake(partner); 
   11.20 +                do sendGroupUpdate;
   11.21                  if keyElectionWon(partner) {
   11.22                      do sendGroupKeys(partner);
   11.23                      do notifyAcceptedDeviceAdded(partner);
   11.24 @@ -225,6 +228,11 @@
   11.25                      go WaitForAcceptGrouped(partner, groupkeys);
   11.26                  }
   11.27              }
   11.28 +            on GroupUpdate(Identity partner, IdentityList keys) {
   11.29 +                do notifyOvertaken(partner);
   11.30 +                do storeGroupUpdate(partner, keys);
   11.31 +                go Grouped;
   11.32 +            }
   11.33              on Timeout {
   11.34                  do notifyTimeout(expected);
   11.35                  go Grouped;
   11.36 @@ -241,6 +249,11 @@
   11.37                      go Grouped;
   11.38                  }
   11.39              }
   11.40 +            on GroupUpdate(Identity partner, IdentityList keys) {
   11.41 +                do notifyOvertaken(partner);
   11.42 +                do storeGroupUpdate(partner, keys);
   11.43 +                go Grouped;
   11.44 +            }
   11.45              on Timeout {
   11.46                  do notifyTimeout(expected);
   11.47                  go Grouped;
   11.48 @@ -250,17 +263,25 @@
   11.49          state WaitForAcceptGrouped timeout=600 (Identity expected, GroupKeys groupkeys) {
   11.50              on HandshakeRejected(Identity partner) {
   11.51                  do rejectHandshake(partner);
   11.52 +                do sendGroupUpdate;
   11.53                  go Grouped;
   11.54              }
   11.55              on HandshakeAccepted(Identity partner) {
   11.56 -                do acceptHandshake(partner); 
   11.57 -                do storeGroupKeys(partner, groupkeys);
   11.58 -                do sendGroupUpdate;
   11.59 -                do renewUUID;
   11.60 -                do notifyAcceptedDeviceMoved(partner);
   11.61 +                if sameIdentities(partner, expected) {
   11.62 +                    do acceptHandshake(partner); 
   11.63 +                    do storeGroupKeys(partner, groupkeys);
   11.64 +                    do sendGroupUpdate;
   11.65 +                    do renewUUID;
   11.66 +                    do notifyAcceptedDeviceMoved(partner);
   11.67 +                }
   11.68                  go Grouped;
   11.69              }
   11.70              on Cancel go Grouped;
   11.71 +            on GroupUpdate(Identity partner, IdentityList keys) {
   11.72 +                do notifyOvertaken(partner);
   11.73 +                do storeGroupUpdate(partner, keys);
   11.74 +                go Grouped;
   11.75 +            }
   11.76              on Timeout {
   11.77                  do notifyTimeout(expected);
   11.78                  go Grouped;
    12.1 --- a/sync/generated/sync_fsm.c	Mon Mar 13 09:51:53 2017 +0100
    12.2 +++ b/sync/generated/sync_fsm.c	Mon Mar 13 15:03:14 2017 +0100
    12.3 @@ -661,7 +661,14 @@
    12.4                          return Grouped;
    12.5                          }
    12.6                      }
    12.7 -                    break;
    12.8 +                    assert(session->sync_state_payload);
    12.9 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
   12.10 +                    free_identity(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->expected);
   12.11 +                    free_group_keys_extra(((WaitForAcceptSole_state_payload_t*)session->sync_state_payload)->groupkeys);
   12.12 +                    free(session->sync_state_payload);
   12.13 +                    session->sync_state_payload = NULL;
   12.14 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptSole, event=HandshakeAccepted", "target=Sole")
   12.15 +                    return Sole;
   12.16                  }
   12.17                  case Cancel:
   12.18                  {
   12.19 @@ -980,6 +987,12 @@
   12.20                          return (int) invalid_out_of_memory;
   12.21                      if (status != PEP_STATUS_OK)
   12.22                          return (int) invalid_action;
   12.23 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeRejected", "action=sendGroupUpdate")
   12.24 +                    status = sendGroupUpdate(session, state, NULL, NULL);
   12.25 +                    if (status == PEP_OUT_OF_MEMORY)
   12.26 +                        return (int) invalid_out_of_memory;
   12.27 +                    if (status != PEP_STATUS_OK)
   12.28 +                        return (int) invalid_action;
   12.29                      assert(session->sync_state_payload);
   12.30                      if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
   12.31                      free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
   12.32 @@ -997,6 +1010,12 @@
   12.33                          return (int) invalid_out_of_memory;
   12.34                      if (status != PEP_STATUS_OK)
   12.35                          return (int) invalid_action;
   12.36 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=sendGroupUpdate")
   12.37 +                    status = sendGroupUpdate(session, state, NULL, NULL);
   12.38 +                    if (status == PEP_OUT_OF_MEMORY)
   12.39 +                        return (int) invalid_out_of_memory;
   12.40 +                    if (status != PEP_STATUS_OK)
   12.41 +                        return (int) invalid_action;
   12.42                      {
   12.43                          int cond_result = keyElectionWon(session, partner);
   12.44                          #ifndef NDEBUG
   12.45 @@ -1084,6 +1103,30 @@
   12.46                      }
   12.47                      break;
   12.48                  }
   12.49 +                case GroupUpdate:
   12.50 +                {
   12.51 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=GroupUpdate")
   12.52 +                    identity_list* keys = (identity_list*)extra;
   12.53 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=GroupUpdate", "action=notifyOvertaken")
   12.54 +                    status = notifyOvertaken(session, state, partner, NULL);
   12.55 +                    if (status == PEP_OUT_OF_MEMORY)
   12.56 +                        return (int) invalid_out_of_memory;
   12.57 +                    if (status != PEP_STATUS_OK)
   12.58 +                        return (int) invalid_action;
   12.59 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=GroupUpdate", "action=storeGroupUpdate")
   12.60 +                    status = storeGroupUpdate(session, state, partner, keys);
   12.61 +                    if (status == PEP_OUT_OF_MEMORY)
   12.62 +                        return (int) invalid_out_of_memory;
   12.63 +                    if (status != PEP_STATUS_OK)
   12.64 +                        return (int) invalid_action;
   12.65 +                    assert(session->sync_state_payload);
   12.66 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
   12.67 +                    free_identity(((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected);
   12.68 +                    free(session->sync_state_payload);
   12.69 +                    session->sync_state_payload = NULL;
   12.70 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=GroupUpdate", "target=Grouped")
   12.71 +                    return Grouped;
   12.72 +                }
   12.73                  case Timeout:
   12.74                  {
   12.75                      DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=Timeout")
   12.76 @@ -1166,6 +1209,30 @@
   12.77                      }
   12.78                      break;
   12.79                  }
   12.80 +                case GroupUpdate:
   12.81 +                {
   12.82 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=GroupUpdate")
   12.83 +                    identity_list* keys = (identity_list*)extra;
   12.84 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupUpdate", "action=notifyOvertaken")
   12.85 +                    status = notifyOvertaken(session, state, partner, NULL);
   12.86 +                    if (status == PEP_OUT_OF_MEMORY)
   12.87 +                        return (int) invalid_out_of_memory;
   12.88 +                    if (status != PEP_STATUS_OK)
   12.89 +                        return (int) invalid_action;
   12.90 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupUpdate", "action=storeGroupUpdate")
   12.91 +                    status = storeGroupUpdate(session, state, partner, keys);
   12.92 +                    if (status == PEP_OUT_OF_MEMORY)
   12.93 +                        return (int) invalid_out_of_memory;
   12.94 +                    if (status != PEP_STATUS_OK)
   12.95 +                        return (int) invalid_action;
   12.96 +                    assert(session->sync_state_payload);
   12.97 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
   12.98 +                    free_identity(((WaitForGroupKeysGrouped_state_payload_t*)session->sync_state_payload)->expected);
   12.99 +                    free(session->sync_state_payload);
  12.100 +                    session->sync_state_payload = NULL;
  12.101 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupUpdate", "target=Grouped")
  12.102 +                    return Grouped;
  12.103 +                }
  12.104                  case Timeout:
  12.105                  {
  12.106                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=Timeout")
  12.107 @@ -1209,6 +1276,12 @@
  12.108                          return (int) invalid_out_of_memory;
  12.109                      if (status != PEP_STATUS_OK)
  12.110                          return (int) invalid_action;
  12.111 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeRejected", "action=sendGroupUpdate")
  12.112 +                    status = sendGroupUpdate(session, state, NULL, NULL);
  12.113 +                    if (status == PEP_OUT_OF_MEMORY)
  12.114 +                        return (int) invalid_out_of_memory;
  12.115 +                    if (status != PEP_STATUS_OK)
  12.116 +                        return (int) invalid_action;
  12.117                      assert(session->sync_state_payload);
  12.118                      if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  12.119                      free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
  12.120 @@ -1221,36 +1294,48 @@
  12.121                  case HandshakeAccepted:
  12.122                  {
  12.123                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=HandshakeAccepted")
  12.124 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=acceptHandshake")
  12.125 -                    status = acceptHandshake(session, state, partner, NULL);
  12.126 -                    if (status == PEP_OUT_OF_MEMORY)
  12.127 -                        return (int) invalid_out_of_memory;
  12.128 -                    if (status != PEP_STATUS_OK)
  12.129 -                        return (int) invalid_action;
  12.130 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=storeGroupKeys")
  12.131 -                    status = storeGroupKeys(session, state, partner, groupkeys);
  12.132 -                    if (status == PEP_OUT_OF_MEMORY)
  12.133 -                        return (int) invalid_out_of_memory;
  12.134 -                    if (status != PEP_STATUS_OK)
  12.135 -                        return (int) invalid_action;
  12.136 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=sendGroupUpdate")
  12.137 -                    status = sendGroupUpdate(session, state, NULL, NULL);
  12.138 -                    if (status == PEP_OUT_OF_MEMORY)
  12.139 -                        return (int) invalid_out_of_memory;
  12.140 -                    if (status != PEP_STATUS_OK)
  12.141 -                        return (int) invalid_action;
  12.142 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=renewUUID")
  12.143 -                    status = renewUUID(session, state, NULL, NULL);
  12.144 -                    if (status == PEP_OUT_OF_MEMORY)
  12.145 -                        return (int) invalid_out_of_memory;
  12.146 -                    if (status != PEP_STATUS_OK)
  12.147 -                        return (int) invalid_action;
  12.148 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=notifyAcceptedDeviceMoved")
  12.149 -                    status = notifyAcceptedDeviceMoved(session, state, partner, NULL);
  12.150 -                    if (status == PEP_OUT_OF_MEMORY)
  12.151 -                        return (int) invalid_out_of_memory;
  12.152 -                    if (status != PEP_STATUS_OK)
  12.153 -                        return (int) invalid_action;
  12.154 +                    {
  12.155 +                        int cond_result = sameIdentities(session, partner, expected);
  12.156 +                        #ifndef NDEBUG
  12.157 +                        char resstr[11] = {0,};
  12.158 +                        snprintf(resstr,10,"result=%d",cond_result);
  12.159 +                        #endif
  12.160 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted, condition=sameIdentities", resstr)
  12.161 +                        if (cond_result < 0)
  12.162 +                            return cond_result;
  12.163 +                        if (cond_result) {
  12.164 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=acceptHandshake")
  12.165 +                        status = acceptHandshake(session, state, partner, NULL);
  12.166 +                        if (status == PEP_OUT_OF_MEMORY)
  12.167 +                            return (int) invalid_out_of_memory;
  12.168 +                        if (status != PEP_STATUS_OK)
  12.169 +                            return (int) invalid_action;
  12.170 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=storeGroupKeys")
  12.171 +                        status = storeGroupKeys(session, state, partner, groupkeys);
  12.172 +                        if (status == PEP_OUT_OF_MEMORY)
  12.173 +                            return (int) invalid_out_of_memory;
  12.174 +                        if (status != PEP_STATUS_OK)
  12.175 +                            return (int) invalid_action;
  12.176 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=sendGroupUpdate")
  12.177 +                        status = sendGroupUpdate(session, state, NULL, NULL);
  12.178 +                        if (status == PEP_OUT_OF_MEMORY)
  12.179 +                            return (int) invalid_out_of_memory;
  12.180 +                        if (status != PEP_STATUS_OK)
  12.181 +                            return (int) invalid_action;
  12.182 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=renewUUID")
  12.183 +                        status = renewUUID(session, state, NULL, NULL);
  12.184 +                        if (status == PEP_OUT_OF_MEMORY)
  12.185 +                            return (int) invalid_out_of_memory;
  12.186 +                        if (status != PEP_STATUS_OK)
  12.187 +                            return (int) invalid_action;
  12.188 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=HandshakeAccepted", "action=notifyAcceptedDeviceMoved")
  12.189 +                        status = notifyAcceptedDeviceMoved(session, state, partner, NULL);
  12.190 +                        if (status == PEP_OUT_OF_MEMORY)
  12.191 +                            return (int) invalid_out_of_memory;
  12.192 +                        if (status != PEP_STATUS_OK)
  12.193 +                            return (int) invalid_action;
  12.194 +                        }
  12.195 +                    }
  12.196                      assert(session->sync_state_payload);
  12.197                      if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  12.198                      free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
  12.199 @@ -1272,6 +1357,31 @@
  12.200                      DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptGrouped, event=Cancel", "target=Grouped")
  12.201                      return Grouped;
  12.202                  }
  12.203 +                case GroupUpdate:
  12.204 +                {
  12.205 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=GroupUpdate")
  12.206 +                    identity_list* keys = (identity_list*)extra;
  12.207 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=GroupUpdate", "action=notifyOvertaken")
  12.208 +                    status = notifyOvertaken(session, state, partner, NULL);
  12.209 +                    if (status == PEP_OUT_OF_MEMORY)
  12.210 +                        return (int) invalid_out_of_memory;
  12.211 +                    if (status != PEP_STATUS_OK)
  12.212 +                        return (int) invalid_action;
  12.213 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForAcceptGrouped, event=GroupUpdate", "action=storeGroupUpdate")
  12.214 +                    status = storeGroupUpdate(session, state, partner, keys);
  12.215 +                    if (status == PEP_OUT_OF_MEMORY)
  12.216 +                        return (int) invalid_out_of_memory;
  12.217 +                    if (status != PEP_STATUS_OK)
  12.218 +                        return (int) invalid_action;
  12.219 +                    assert(session->sync_state_payload);
  12.220 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_state;
  12.221 +                    free_identity(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->expected);
  12.222 +                    free_group_keys_extra(((WaitForAcceptGrouped_state_payload_t*)session->sync_state_payload)->groupkeys);
  12.223 +                    free(session->sync_state_payload);
  12.224 +                    session->sync_state_payload = NULL;
  12.225 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForAcceptGrouped, event=GroupUpdate", "target=Grouped")
  12.226 +                    return Grouped;
  12.227 +                }
  12.228                  case Timeout:
  12.229                  {
  12.230                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForAcceptGrouped", "event=Timeout")
    13.1 --- a/sync/generated/sync_fsm.h	Mon Mar 13 09:51:53 2017 +0100
    13.2 +++ b/sync/generated/sync_fsm.h	Mon Mar 13 15:03:14 2017 +0100
    13.3 @@ -95,6 +95,7 @@
    13.4  PEP_STATUS storeGroupUpdate(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
    13.5  PEP_STATUS notifyInitAddOtherDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
    13.6  PEP_STATUS notifyInitMoveOurDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
    13.7 +PEP_STATUS notifyOvertaken(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
    13.8  PEP_STATUS notifyAcceptedDeviceMoved(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
    13.9  
   13.10  // event injector
    14.1 --- a/sync/generated/sync_send_actions.c	Mon Mar 13 09:51:53 2017 +0100
    14.2 +++ b/sync/generated/sync_send_actions.c	Mon Mar 13 15:03:14 2017 +0100
    14.3 @@ -468,6 +468,32 @@
    14.4  }
    14.5  
    14.6  
    14.7 +// notifyOvertaken() - notify Overtaken to app
    14.8 +//
    14.9 +//  params:
   14.10 +//      session (in)        session handle
   14.11 +//      state (in)          state the state machine is in
   14.12 +//      partner (in)        partner to communicate with
   14.13 +//
   14.14 +//  returns:
   14.15 +//      PEP_STATUS_OK or any other value on error
   14.16 +
   14.17 +PEP_STATUS notifyOvertaken(
   14.18 +        PEP_SESSION session,
   14.19 +        DeviceState_state state,
   14.20 +        Identity partner,
   14.21 +        void *extra
   14.22 +    )
   14.23 +{
   14.24 +    assert(session && state);
   14.25 +    assert(extra == NULL);
   14.26 +    if (!(session && state && extra == NULL))
   14.27 +        return PEP_ILLEGAL_VALUE;
   14.28 +
   14.29 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_OVERTAKEN);
   14.30 +}
   14.31 +
   14.32 +
   14.33  // notifyAcceptedDeviceMoved() - notify AcceptedDeviceMoved to app
   14.34  //
   14.35  //  params:
    15.1 --- a/sync/skeletons/sync_actions.c	Mon Mar 13 09:51:53 2017 +0100
    15.2 +++ b/sync/skeletons/sync_actions.c	Mon Mar 13 15:03:14 2017 +0100
    15.3 @@ -489,6 +489,43 @@
    15.4  }
    15.5  
    15.6  
    15.7 +// notifyOvertaken() - 
    15.8 +//
    15.9 +//  params:
   15.10 +//      session (in)        session handle
   15.11 +//      state (in)          state the state machine is in
   15.12 +//      partner (in)        partner to communicate with
   15.13 +//
   15.14 +//  returns:
   15.15 +//      PEP_STATUS_OK or any other value on error
   15.16 +
   15.17 +PEP_STATUS notifyOvertaken(
   15.18 +        PEP_SESSION session,
   15.19 +        DeviceState_state state,
   15.20 +        Identity partner,
   15.21 +        void *extra
   15.22 +    )
   15.23 +{
   15.24 +    PEP_STATUS status = PEP_STATUS_OK;
   15.25 +
   15.26 +    assert(session);
   15.27 +    assert(partner);
   15.28 +    if (!(session && partner))
   15.29 +        return PEP_ILLEGAL_VALUE;
   15.30 +
   15.31 +    // working code
   15.32 +
   15.33 +    // free extra
   15.34 +    return status;
   15.35 +
   15.36 +enomem:
   15.37 +    status = PEP_OUT_OF_MEMORY;
   15.38 +error:
   15.39 +    // free extra
   15.40 +    return status;
   15.41 +}
   15.42 +
   15.43 +
   15.44  // notifyAcceptedDeviceMoved() - 
   15.45  //
   15.46  //  params:
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/least_color_group_test.cc	Mon Mar 13 15:03:14 2017 +0100
    16.3 @@ -0,0 +1,113 @@
    16.4 +#include <iostream>
    16.5 +#include <iostream>
    16.6 +#include <fstream>
    16.7 +#include <string>
    16.8 +#include <cstring> // for strcmp()
    16.9 +#include <assert.h>
   16.10 +#include "blacklist.h"
   16.11 +#include "keymanagement.h"
   16.12 +#include "message_api.h"
   16.13 +#include "mime.h"
   16.14 +
   16.15 +using namespace std;
   16.16 +
   16.17 +int main(int argc, char** argv) {
   16.18 +    cout << "\n*** least_color_group_test.cc ***\n\n";
   16.19 +    
   16.20 +    const char* mailfile = "test_mails/color_test.eml";
   16.21 +    
   16.22 +    const char* keynames[] = {"test_keys/priv/pep.color.test.P-0x3EBE215C_priv.asc",
   16.23 +                              "test_keys/pub/pep.color.test.H-0xD17E598E_pub.asc",
   16.24 +                              "test_keys/pub/pep.color.test.L-0xE9CDB4CE_pub.asc",
   16.25 +                              "test_keys/pub/pep.color.test.P-0x3EBE215C_pub.asc",
   16.26 +                              "test_keys/pub/pep.color.test.V-0x71FC6D28_pub.asc"
   16.27 +                          };
   16.28 +    
   16.29 +    const int num_keyfiles = 5;
   16.30 +        
   16.31 +    PEP_SESSION session;
   16.32 +    
   16.33 +    cout << "calling init()\n";
   16.34 +    PEP_STATUS status1 = init(&session);   
   16.35 +    assert(status1 == PEP_STATUS_OK);
   16.36 +    assert(session);
   16.37 +    cout << "init() completed.\n";
   16.38 +    
   16.39 +    int i = 0;
   16.40 +    
   16.41 +    for ( ; i < num_keyfiles; i++) {
   16.42 +        ifstream infilekey(keynames[i]);
   16.43 +        string keytextkey;
   16.44 +        while (!infilekey.eof()) {
   16.45 +            static string line;
   16.46 +            getline(infilekey, line);
   16.47 +            keytextkey += line + "\n";
   16.48 +        }
   16.49 +        infilekey.close(); 
   16.50 +        PEP_STATUS statuskey = import_key(session, keytextkey.c_str(), keytextkey.length(), NULL);
   16.51 +        assert(statuskey == PEP_STATUS_OK);
   16.52 +    }        
   16.53 +        
   16.54 +    ifstream infile(mailfile);
   16.55 +    string mailtext;
   16.56 +    while (!infile.eof()) {
   16.57 +        static string line;
   16.58 +        getline(infile, line);
   16.59 +        mailtext += line + "\n";
   16.60 +    }
   16.61 +    infile.close(); 
   16.62 +
   16.63 +    pEp_identity * me1 = new_identity("pep.color.test.P@kgrothoff.org", NULL, 
   16.64 +                                      PEP_OWN_USERID, "Pep Color Test P (recip)");    
   16.65 +    me1->me = true;    
   16.66 +    PEP_STATUS status = update_identity(session, me1);
   16.67 +    trust_personal_key(session, me1);
   16.68 +    status = update_identity(session, me1);        
   16.69 +    
   16.70 +    pEp_identity * sender1 = new_identity("pep.color.test.V@kgrothoff.org",
   16.71 +                                          NULL, "TOFU_pep.color.test.V@kgrothoff.org",
   16.72 +                                          "Pep Color Test V (sender)");
   16.73 +                                          
   16.74 +    sender1->me = false;
   16.75 +    status = update_identity(session, sender1);
   16.76 +    trust_personal_key(session, sender1);
   16.77 +    status = update_identity(session, sender1);    
   16.78 +    
   16.79 +    message* msg_ptr = nullptr;
   16.80 +    message* dest_msg = nullptr;
   16.81 +    message* final_ptr = nullptr;
   16.82 +    stringlist_t* keylist = nullptr;
   16.83 +    PEP_rating rating;
   16.84 +    PEP_decrypt_flags_t flags;
   16.85 +    
   16.86 +    status = mime_decode_message(mailtext.c_str(), mailtext.length(), &msg_ptr);
   16.87 +    assert(status == PEP_STATUS_OK);
   16.88 +    assert(msg_ptr);
   16.89 +    final_ptr = msg_ptr;
   16.90 +    status = decrypt_message(session, msg_ptr, &dest_msg, &keylist, &rating, &flags);
   16.91 +    final_ptr = dest_msg ? dest_msg : msg_ptr;
   16.92 +  
   16.93 +    cout << "shortmsg: " << final_ptr->shortmsg << endl << endl;
   16.94 +    cout << "longmsg: " << final_ptr->longmsg << endl << endl;
   16.95 +    cout << "longmsg_formatted: " << (final_ptr->longmsg_formatted ? final_ptr->longmsg_formatted : "(empty)") << endl << endl;
   16.96 +    cout << "rating: " << rating << endl << endl;
   16.97 +    cout << "keys used: " << endl;
   16.98 +    i = 0;
   16.99 +    for (stringlist_t* k = keylist; k; k = k->next) {
  16.100 +        if (i == 0)
  16.101 +       	    cout << "\t Signer (key 0):\t" << k->value << endl;
  16.102 +        else
  16.103 +            cout << "\t #" << i << ":\t" << k->value << endl;
  16.104 +        i++;
  16.105 +    }
  16.106 +    
  16.107 +//    free_identity(me1);
  16.108 +    if (final_ptr == dest_msg)
  16.109 +    	free_message(dest_msg);
  16.110 +    free_message(msg_ptr);
  16.111 +    free_stringlist(keylist);
  16.112 +    
  16.113 +    cout << "calling release()\n";
  16.114 +    release(session);
  16.115 +    return 0;
  16.116 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/test/test_keys/priv/pep.color.test.H-0xD17E598E_priv.asc	Mon Mar 13 15:03:14 2017 +0100
    17.3 @@ -0,0 +1,58 @@
    17.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
    17.5 +
    17.6 +lQOYBFi0Nl8BCADSZSP/I35zpiaShZ9bn96AWFsQnD32stjEuQxYLO+T5krbot0x
    17.7 +eqHPI5jHs4tF9j/DwQ4qaI2v6Tj5csHgSYfsFvIst5xmVEsOXUYZBXSSzei29XQx
    17.8 +XISQZwHcaY0znXGN5Dnj4oeJq/Ok3G0TZ2ddx5pmEu5j9+VA3NLC65hKXnbeY7+A
    17.9 +uNo6UYDqo6FPqBff6IO4ibKPLZ09kZbF6xh77dOAJfWbeNS8oifaqQ2NIfork/Uz
   17.10 +dq67xO7V28RlJKhFQo95EJyjw2Juu0p4UYMt9c5Dte+Lxz47iSqIzHJH9Odd5klP
   17.11 +isrCWq2U6ALAFIKp6ykNg9d3SW2J7LWIfJq/ABEBAAEAB/0ZnROJS55o4OjgPKE+
   17.12 +a9OQJ3GKr6LBhltqc6bDk1DlXgtt+sFX9Th+ubQvV7XUYhq4L6gUVJ8vM8LqZ2Sf
   17.13 +9AO2o8J+3CmPsaJjkMpoYGglOSkkIPSwz7UZyViKJ1V326qH3imICzt58LOcNfOX
   17.14 +gaatXY/37kUUaYkA4QFNlpX3M5lJzBf1qwADRddjBD+aiLhdeyaONdIoZN7SPG2D
   17.15 ++VU5D9c2Rb8QwG1yrEOjnJ1ybezYC7V25N6lgB7BcIIBnbr6VaesbesepvKbb+LY
   17.16 +cfq5zrTEwft5Fl4WwTlBI7grx4qe1f9GSYkHcNKEfHYUvcAnB+xU2cM35lxGWrK6
   17.17 +NnzFBADcHw30P2gGnJHvMnjR2GBiO2Z5aich6ZIze8Qqj7ghCkbSx6I12V38ighM
   17.18 +UQdKufsmaTB/hiAjYIuJ3XAzukAr5yrSKYzKFUzr1M5CMhBOp5VXDRBvHYffGb6s
   17.19 +yHQXgU1i9ScuWMb1vKwNNxd2hHC9huJ8zckJos1hnRiywVGt9QQA9LA+Crq3HJqH
   17.20 +QLTLOL9ynLBpVSr3PaYitr6aE5/xsmXTmAkqK2Q8n/q3TX7wYu8FzTsQKdqiEvT5
   17.21 +DaVTDY8plJtK/zqjz5YUwJyjLUJcoieEHG03lThlWyY9rjS5BTvwUvfdBa5/MIRQ
   17.22 +sgEFncL4BBChR4V/id29KPTNbji64WMD/3wJdaKJfJ4GjqGlbPu5nByssV5BUY9w
   17.23 +ysDOkunq8joHbcHK9x2FUB4Bqs3kLwwTpTH6Kycf4Pn9Tooxa1qTdzzz0FxUqu86
   17.24 +RXBws2D3BVRwlj4mYaNEbPwyQhoghEuWw7K0ApiL8PNcxOQ4Ran8BMrVApNjfLrj
   17.25 +0Bsh2Tc0Imd7Pbq0b1BlcCBDb2xvciBUZXN0IEggKG90aGVyIHJlY2lwKSAodGVz
   17.26 +dCBrZXkgZm9yIGNvbG9yIHRlc3RzLiBkb24ndCBtZXNzIHdpdGggbWUuKSA8cGVw
   17.27 +LmNvbG9yLnRlc3QuSEBrZ3JvdGhvZmYub3JnPokBOQQTAQgAIwUCWLQ2XwIbAwcL
   17.28 +CQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEL5pp6DRflmOlVAH/iH6KhXLAN90
   17.29 +vyUEfPxITWsSO/IN6XN4mjUxhY7QyGJg2P77ljkAYup4ukIwEPx/XaKeb/Ofeoch
   17.30 +pkhhS9uW7TBqnn5B8Xd80UV+WdY3knv0ba6U1HnUq2CE+QkVkVfLWxIwSHPCnvDz
   17.31 +3rNcp9j70oyoMqKvezCB+hxn1+jHJOmugQ44Q/AWJraeuGNbrMOwUWwscBg7ikYE
   17.32 +bbIT7RNdG4QpCYQxIQNRTEXJ9bLChNs4Daai2S5qMInsAA4NWc8OvJNBhixWVmoa
   17.33 +Hfuy4GdxjUhDkZR79butWw+/2DcUEbkmUXxu4TIPQEi3IfsHHwMopiJfALU0Zqq4
   17.34 +BNGWjhzgldudA5gEWLQ2XwEIAOIZwJVXR2Rvcoz3FnwDaTvww5LztQKskZd7Tszd
   17.35 +Mvv/c3QxPJbk4B0w1nZPcXu4UohRl2dAcxVTgXVB7cM1K1ush1/QJQWuxDvJK+MN
   17.36 ++WynkpMuQmaiEKTnXqc3N7U8Ejf6oRbt7K/+8dmXX7zOFvThFAEA9cnK4ot5jMFL
   17.37 +M6lYbHBj5tP1Al0E9kZV4SzYS5mLcl3ulCoSZufz8MVrEOrS1llUwpiVhsHTs81k
   17.38 +zAIsdOKdb9QmbOctLmHiWg7O/97I9/CK3nC/2IYOyhAccRd08lopbvEfdgBQaKT8
   17.39 +R4+npL+YGGh7l5IJHlNbZHAsa8RJDNwCEPKIMRwN1eO8YZkAEQEAAQAH+gLDjBM/
   17.40 +RYIEqz6uJA4YyBPpn+hnVoB9fcufYCGYuB90ulNyqSISkutEbjC0zKc1o/ui3LIQ
   17.41 +S3/YnRni+A41c43btG1vSM6Smfc9oK3WPUTu4Pev3nOs+j1bzzBF2GZcoT/iLk8u
   17.42 +kiC+IfR2GV9gWQ8+A522BmskseOA1T/FJLDmnA3nvzBhbZOx2NfRu3nBBhooQVpA
   17.43 +HhR/L3wtAqYlV5+dWdDjY/rGrc4znAiU0KhK1Tks2d3Jymc9TKBFODx+xmEOQkhx
   17.44 +LtCzpP+nH2haRWo2MjjuYKpnh6z2tG99mUFDfudIE7NRXS5q9WystMGME+ygAQE6
   17.45 +bBYFpa2mVv8k9yEEAO6KM76g5Jk8BjJRm6SD9CW7VZSytS/hGapX1mou1pVoROPD
   17.46 +SocObvFpiJUPhI/tHdcldcrFqAycVLkEJ8BX3yguVyX9e0BLpVojOIE9WmnA2swN
   17.47 +kllUhSD1FrPFyLhBTHuHHCrCdXQSSGrY9t/i2sdA2lCuZtnl0+G0f35uSAW5BADy
   17.48 +pnYbxrL0p0VLT/mdDG5wgU6CE2hCk2wFL2msuX5jKHMMMY4hH5wcrD4aaB/9GLHx
   17.49 +BOj/4mKsft4X9Ia2Ff/mcVRF9kR2Cct18VuY/5kAMZ5dYYdbBhyksaExeV+owR1Q
   17.50 +hEOIi1xgrs1A/xWSK/0rqJA02qqSqJxHo/H+oPcq4QP+PxAvd8AwNXhUOfXPwHDJ
   17.51 +/Oa7/tZXM4hW9TRMju6cXCVVqAxbrB+829579mIlIQWRgpWkuChXCEdSb6FRYHcg
   17.52 +Oc0NFIwEIIAI+30nyUqs1JYDQy9gA5h1Re5tyiN23uUHAiykPBfFz8bGIi2dxv78
   17.53 +7Icy+66+hDOFm3i33F11Jo06TYkBHwQYAQgACQUCWLQ2XwIbDAAKCRC+aaeg0X5Z
   17.54 +jjT6B/9T2HneZqBhUhcJI+/j94MXoYIJHZkODo5MP30ynlXc6+kJiYyXbuK+K0Z6
   17.55 +4bpRpO7cKPvdQCkcQ75LDqXGgT7/wH8rzP2Q7G+gsh2JBzGyaPPF6w9eEK8gML3G
   17.56 +8gAFo6BV+bXR8vNO7n9XjvambNkqDobZECr3TmaUjWBkkV0r3Vhb36a5XRY2uO1E
   17.57 +1GB9ihF3+9pljpFiHeTBT3dDQBeVq7WGmO84lHdPb14nwm94Zn7N/nJMa5NBDDph
   17.58 +8dGtf5j1Rg5R1rn+ABl3/N+7pmcEFMJbjtJdYuLC6PLfhw1nO6BhuTW2hcHRUe4l
   17.59 +t7xAWEVGLUkrI+IvjaiKmOvYCwl0
   17.60 +=fjcC
   17.61 +-----END PGP PRIVATE KEY BLOCK-----
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/test/test_keys/priv/pep.color.test.L-0xE9CDB4CE_priv.asc	Mon Mar 13 15:03:14 2017 +0100
    18.3 @@ -0,0 +1,58 @@
    18.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
    18.5 +
    18.6 +lQOYBFi0NaUBCAC3TwbxovyU/zUFDG0d+m55UF9zmxjfnwhTnoPCOtSDK2eVZFOv
    18.7 +ZCSatpsIZzJ5BWDC7hn+sgbELhgckVvfEzAz8GKow9tCiRuyW5XThDdtujGChlbY
    18.8 +Jnsto91v8hwdXa9DEYz+XSary7DJp0VsSLnxJglxH+r4H688iT6f/w11RLAEcESF
    18.9 +BsZLTQx769YCPZw9rHN5pPpyJrkkNJINPUzIYIgQ4fKdPe3ECOL2NilA5IhFkuLA
   18.10 +3FZdeE4F/Jsb4GAu+nb8wJxBZbPZxBs/Hw+PTI/ACpUnj2Y1nUPRzRAFYuompZcw
   18.11 +GxvC0Y2Oy5HJumLW5e5Y3r2b5hE8x8rQnX65ABEBAAEAB/0TLjw6RYUrbAbWt+Wl
   18.12 +COLNY9kRBi4UnBXpdgEwbip1bTHCAoT1KcPgwnG3b+Dqo+LrkrF6opMtrOsN9jHI
   18.13 +RkA5dxJDuXa0YBdbUtT7FG8eVqi+kSL+LAyginBtucYyVm6z1F7N8N5OhJpDh3Ku
   18.14 +sW9vabz8LsxN2TbjXTMF19DHL9LQqmd7WDIjT4gxdXjCHLgI8kpR9RxFgkQxTkrF
   18.15 +fZMY1Xd4oxcgsJexE8hHURI9MdFr8shaDXePuOEJFvghgAdgpYhbes9oiO8Divgp
   18.16 +sFirFGuCwtvb3Stf4ClHM7huj187dHtQXWy0jNKkTPS2XBSeWI22BvmMZ5gAXOMO
   18.17 +Mq1ZBADKXhig4/umvetRvL3zwPVCQ9OW9Mh+lkL0f13KCFNzXT1u0QsJPwWAp0uW
   18.18 +uqD+xWlFtga4qxtkxrch+io9kHTlUod8vF80b8QKZmDZDwiF+BI/T7OCizSRxAwA
   18.19 +vK+J3O276S3oyrRXYayIHuCC9P3R3UmDWEiCmPIZuKuSQObnpQQA5+PbNUlwT4Xa
   18.20 +Zy5KOpi7dRKHmYTAegs+QHzzcu4vNS62wGWUSKok7MxFyWa0vwheNjs+4JEkBFdB
   18.21 +kFHH1GitUYKTwR2Gf5rQ9X7i7JmHu0gU+rzknDS4yLhKWGdgBmGB5lPghDLdT3CZ
   18.22 +SF4lEgebu/I7TFmnEGvBbHVQAKxRroUD/2sV5JZ4BFBHeEqOPkb1jPXSfXIMzEOW
   18.23 +5pJIhkmF/ulXMnw7ZDunSwXWfWwIcYQdAOFoePLsbj+EGWcMUmjD5pr+QbjSbOAR
   18.24 +IfEJnR6gR10vzqkfMuqOJBLKtb/au6CydbN4V7nM0WCGjl/zWtsQ/TVqiqSQ+3Hy
   18.25 +jBnymgEYfWtnPxW0b1BlcCBDb2xvciBUZXN0IEwgKG90aGVyIHJlY2lwKSAodGVz
   18.26 +dCBrZXkgZm9yIGNvbG9yIHRlc3RzLiBkb24ndCBtZXNzIHdpdGggbWUuKSA8cGVw
   18.27 +LmNvbG9yLnRlc3QuTEBrZ3JvdGhvZmYub3JnPokBOQQTAQgAIwUCWLQ1pQIbAwcL
   18.28 +CQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEC3ZgKjpzbTOePgH/0URElHoQJIM
   18.29 +T246FF/j2RUka+rAUSHfgCoEAQIROUETEWZXtLwyA9UdKq4+abg6Y7x9QTazUxwa
   18.30 +YlCD0rmI0caraZBEcw8KefugNG+uFo5CZxp8U6v3Gkp/u26o6RLelgq2wpCPE2NU
   18.31 +pKNwzL1Q64szHez8Bv14tMxBR2minERnGQoPWVj9yesuA/4oTE8gHzrvwM5pu0Kd
   18.32 +WNvLmFWC6KJSGcNo7S4CCOe307/EyFXTNy/Ibnj6vr3t0fC10RScH2gxTj5+1JKU
   18.33 +erNlDnNC7V7wMiyzOh0X7BQSFmESCgIo03d+KFZvj/b5kyOlnn93PLCA83zhNA+5
   18.34 +TpsYmToehpWdA5gEWLQ1pQEIALmvIDyG2wEy9eWC37aczgNOxnELOH9Zq9iEQWaQ
   18.35 +ypjbGCaWWTgjo+cNR/ibKAyHCaYReKULylawQVVDTgVp4/CrU2nXP0ozjvHb5MoB
   18.36 ++Whp+bYlZpQ7jQIYwblaM9CMfZ/ROhkTYvsjf+LGJUXwRHAJTSUnxT+PP9p30Nfp
   18.37 +8yISres+ihz+BF7rKJwNiJhvPWyqAeEMnJWxrc8ZjKSy4JUAryn2IlxsOleNhT4N
   18.38 +XFyzYdg33rtLWQ4jxiT0RYqHecFhBX9kLclL4wYwvh7DcaFkSPY5vk+3csZhs74U
   18.39 +2+PgQkaVqAXQlX4fGoDqOWU/s+VTbVEEduwZgGpDIax1Kz0AEQEAAQAH/imrmwTq
   18.40 +ULDCsntYtQLiyrrkTVVmKr4trgqPl6vAV68ZECDswcX+/ZPnH50zmLfDAE/UAOqt
   18.41 +LDHrKSZMzfAaFOzYTgZlJ09sJaqyafRJoCKmEcOmPhCLEriDPMpva0xkkvawOiUR
   18.42 +fDeW/mayh//bjUhFVho+BB6g87gABo7F8mnVPHPivgn+dyoFnhRjEyA+/2nh37wb
   18.43 +UAtFiwBq7p6Rbqv2mQq+kwOvtvw4i5scZcmi0tfvHoDf7g8vv3UZF57pgG01DigB
   18.44 +dJqKNPP4yS4UGZHHCusWzdQp5AigF8FnF+CLMRR5ZyxtRZGQCfdScAmb4HdI4zL3
   18.45 +C9CkRLuox1xvvkMEANc7szXRVikylhirduK+dV1bYl5RRYahX1uf1786mfIkonuL
   18.46 +k8Au1zFd83Z0Y6QPcVXKOsbutEpTNZmvGHr/xKllBqtl0gPDAf2hmm+6W6zEVbyV
   18.47 +4sA80P/LCd2jqKreCJG3mYjrh3ETvg2mAsZDiJ/FA19Z193YxnIeYWqrOLC3BADc
   18.48 +2qNpctG9uyK2oQx18cApoLE44UxaUvK/h8JqUlQXK8ZMc4LXYtc+rIS2U8n1MAx0
   18.49 +QG6gEBVUxS+XiV6y03+3XKqj0EfbDaDtNr56EQIHIW9HfUy3MmJMeHbs+ZI+ukyG
   18.50 +n9fK3DU2XTWjkW9H0xWrshLmB6LXYJauQDpmBO7nqwQAqWjPt7qBmY67tcRFP7RD
   18.51 +H7ZXHvdPfCWRlfxcOunqtEgwt0hziA2w9ognSI1ND36SBJBtatt4cdTjHa+dNaQJ
   18.52 +UWc20DP98pILMPi6EjqQ/yNX15mnc+neq8nVVac5xbMZBQyccpn406j3Fe+88waN
   18.53 +I7/9vRUVOZYihz5FfbOsf2I/zYkBHwQYAQgACQUCWLQ1pQIbDAAKCRAt2YCo6c20
   18.54 +znQQB/47kyeQIrz1CxijZ8uKyLSXxrOBuEL/ximZlfyQHYxHMYWGqor662DdXZcv
   18.55 +g2qSr+skdtkUfKeC5kshiJAH1c1AzCm6jXt6fB0T4sARo7FRbQJJv5/5C5uz4KsK
   18.56 +F9qD+89w22QSKyQLXNBxQQG3mMvfSFXBiNg/AaIeoXateppblRhbJDmBGIqkDryj
   18.57 +liURU8W10LdD3kYaQ8TLj6HDIssLgA0FbtdEiJkiFhMAYU/ObmnhgQJrJku6VMVs
   18.58 +Q0LlWgcZyp15p5w3b9iqseJCdejkz8xlKA/IUN7YS48jrlfJRmEjz++EO3sWD5jY
   18.59 +uHDrG9ggwen0UoY4IGhF+PgFVCRF
   18.60 +=gB35
   18.61 +-----END PGP PRIVATE KEY BLOCK-----
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/test_keys/priv/pep.color.test.P-0x3EBE215C_priv.asc	Mon Mar 13 15:03:14 2017 +0100
    19.3 @@ -0,0 +1,58 @@
    19.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
    19.5 +
    19.6 +lQOYBFi0NWIBCADfZwQP5IWDe5K+LohvaZgyeqCnA8tA3wmFmDCSrSTg596LJAj/
    19.7 ++NCO+cXABRbiihAOfCQ4vZZu+nBOXrGt6iAxsEZrbQg0MUx0vvbeuVeuF2ItHobE
    19.8 +BSwQVGArqDlU+Ts+Ew3+nenJZBg+4KTq4i3L2RTq+AIxV/DLLQat4Qc2tdfDiuBA
    19.9 +dI3Ro2d6va+6Dd/z37V7FZEPG+oAiKeLEl7Alr8iyrBLWyiIKWFjOIK9N094NifY
   19.10 +6UayN7AAiFBWv7dAIRRL9WtSfRIap7Iv3LrjIVLDdeIZfbrhEOC/a3D4rQQ0gkqS
   19.11 +MZWSUlRUuZ/AlFYNzyFoIEZmG2dnh5FhzU/DABEBAAEAB/9Tmxt/kR/QXZpE12hS
   19.12 +/bsqRQ9Dgd16qR3Io/Slp+uxycTU4McHeMgggeRaYO04GcA5k4cAvx8B6HLIOZMY
   19.13 +SZMD1Xr9MCBOXBbHaEI+hzGDoxeoWBDKYj8j21fkbsAKB33+1KW7oMCCEJYsTeka
   19.14 +SEwoSlUUPH2hls40U2T5BMqs07y9aLmpWSCzwXwkdN0RooVH+a7KKJwCCXDAf/rN
   19.15 +kdi+vvJ5fAtw8UmCWfAwXRnli23qRU/c3/9iTL7BZQ6xBwlRhe+G/DyhJoD3p0YW
   19.16 +8VNJnvqseZYev9s2i46FjPDeRNMijYaFup2fPRgjwhjD1kcHdbOLKf4T5MtDdnLK
   19.17 +t3AJBADkhXeFGGCfQvmcEmUTivMhqic8WINzyjuRG9JwGnduEYexhH9qhp65cY0N
   19.18 +7IS+8nEEzsxEfbTAPK6WddvJKzUHMDFxYM8DJ/FlMnl9cXWplaGIHqwyrInRzs5s
   19.19 +RJM5RGISFeqc9oyWqFhJI+bXnWzyGF0SlXi7tFVmESUOH9lUCQQA+kP5KCA8c1DC
   19.20 +tdwO7MoBCpe+IgNnpZgcvJhHhY4VvdSXOelQkggX47UKJ/zQJGWH4pc35o8GSJeC
   19.21 +Rd/TmcDlwhkTrAgPRpmJ4lX6LUSjLQPueu55pz0rVb/kmT2DXCqIu5F1JO8pBg4M
   19.22 +EM7HmPmt5FWsZOS6GPNtiKIhAMzpsGsD/jvjvqY74hmiTjb6w1x6Kl1VW/lxQ8kz
   19.23 +qVmJhCSJOijhuY3ZzKk5rbN1+8I3OA6XhT9upVQ/ZCgYtQvUzH++VtFNTo/iLntK
   19.24 +yu4qqA5C9HEsJT6Smnu13UQt3LzTO3UBuzmyFIn6bVYkZxPPUSmtJah5qyURXyKK
   19.25 +eiB4gR31gmdxODC0aVBlcCBDb2xvciBUZXN0IFAgKHJlY2lwKSAodGVzdCBrZXkg
   19.26 +Zm9yIGNvbG9yIHRlc3RzLiBkb24ndCBtZXNzIHdpdGggbWUuKSA8cGVwLmNvbG9y
   19.27 +LnRlc3QuUEBrZ3JvdGhvZmYub3JnPokBOQQTAQgAIwUCWLQ1YgIbAwcLCQgHAwIB
   19.28 +BhUIAgkKCwQWAgMBAh4BAheAAAoJEOpZcV4+viFcu0IH/AsCpzsRv/adLiGy979m
   19.29 +LZriFWxYhW2zUUA2sWXvlX9FibH32ve5cG+k5DqwctqWmA+EkcvVER7GzvQrEJLv
   19.30 +mzJnjq19CGzg8rm7HgNp6EKIHMH70gVUEikawjstZ5eMO5raD+5qFZhQzTDsT9DI
   19.31 +XYGnqUOGUaoelreZpadT4ZqF4WHxux2JJbojShUSfo9lUY3iIH4YInAmYdaoODKj
   19.32 +DTzNVMKfujyMFz6TrpjQUQFazi7JtbeTQfluFTR8rp8CwKOgwDVUMgfie6kLYwnc
   19.33 +ZDkAsIMVs1Vc3uHRwa8arHavRSxN0rnXGty/oNuErGX0aiYBOtaUjRsU9C5x69jm
   19.34 +V66dA5gEWLQ1YgEIAMMysh2rCBvNtirkHt5kYKDCBfpRANzWl7z9z8LVg8KI0bt8
   19.35 +KaR7+zyWfNKdf3c7Qi8MhI7EGBzQiu62CqlRcP9I61rAH2yxoNn4+JOVTObtGjJp
   19.36 +zwoYO+umrJZ6h1JrV8SMEkrUp51xDsEr9RKtdmGvDNjZRD0Jlh7gGMlH+1LwkUOe
   19.37 +0OoZkfQz7b/TWnvkZfveVyTZI4SnxpeEVzIbTx7qceTByJeNoHnd4DIHH4sZHkEA
   19.38 +xxkE6VQf7BXykV4xh+G76o3JVytE3bDIrCpPwaswlpZ9++8Jr5bB5o+JN8po9pxS
   19.39 +4rKE7ngzwqvpCLzCZV3t2+YlVKSkI9kqo4z7DV0AEQEAAQAH+gMPYqZJ6zQ1DE0j
   19.40 +AI6NJXb9C7HHVCY3fASpDaPY4TpVwZn47JXeTAuWCAoXkNW/mVOaVI1WFX2wJu7D
   19.41 +7lSws5Q2TQWXcPatLd/KQiqyzWmVCn3YqverdmxaPibpcAEoBdB4P1oqeB/k/kL4
   19.42 +1jGkhAWshEegV6xFn/OcdkRY4J+wdvFaagQcjmTgZtYnjXKdWpl6EG8GE6PTsd/r
   19.43 +HZJ63wJY4JPcmUnXFVak8tElYlTzrBOI5PCnNgXi2Hdd/vECS1oZvt1hmANASFxG
   19.44 +0QPE9IB0cikDMfI/eGyOCVnXcjCXhF9iGhcXWXxknIZyQapE3d91GL8ecE68qSSm
   19.45 +f6JSA9EEANZy6vGhBhxICNW4k8vYDgyLQwKNRpYaTS9GlDaa2TVcRgMC+5Gp4Vzk
   19.46 +UzCVrkRpOXdCw+Kh9fd7pp/LGA873AOukRH4b5T9Dj5S7pqgF+/4tKEr+4Zv/V8d
   19.47 +mz9lgkvyxQxl2uOJXK4Lf7vUoIDN+dnPihNPKraGNTEB5N8aAElNBADpBOXHsOt3
   19.48 +eZiyGrYIO/Efh5KRzakFFPjDTsfuMYdKBhy8787wiGBTro2fk/3KVWNkqacGF0xn
   19.49 +aIFZh0P+8hT5kE+1+ssYKV0x8jAKyn2Ez0FlaC2127fS+BIZaucqSondZ8oqrPYw
   19.50 +6m0TWOfIxcQ2LT4LxSIBLpMw47IVuSVMUQP/SNiPkUIfh+I9p85wlP490LDCEpim
   19.51 +Lk+kL7wTDTc34o2MY8YCZq48AwkhATwvI/MIIJfoL84JrFoZkyjK15inLXfC1ozr
   19.52 +riVu2Ds7gIHXORNUiiTryhEHr+Uqso1zl8iyBYkR/2LCyydsvBZPCVuP3MARWlOg
   19.53 +ccm0tb2/Lmqb7Xg234kBHwQYAQgACQUCWLQ1YgIbDAAKCRDqWXFePr4hXJU8CACD
   19.54 +r98ShkdT6KMHvRCqfKCRKwgFm6G4zeJGfww9sGtykhG9bECydHv+mFxUtMT2PzBI
   19.55 +Vz4cNcCv/ODdkJq6/yyKi2ZYWQ65nykmBiWi0SudcHsTMfmyQHzC07NMRGz+ZgnF
   19.56 +9ipeQ41I8rOLzoIcxHZGVUzrGtQ3G9NGUnb2fa8i78dtme9/gY9f0LhIpwiP3CMz
   19.57 +HzXUV8uEsDGhzLVRYJBcwHP017C+0I7gVfM3IWwjjNRjhelgKnFE+pvo6agDhqi7
   19.58 +7d/GEOBUZCj16UqIj8pPc+iAWHeYqdIve7vOWP0t7bJ5tuvqsNFvPJJgzgEw9CNa
   19.59 +P2e8hCozSJhlhi9r7x0R
   19.60 +=+PRn
   19.61 +-----END PGP PRIVATE KEY BLOCK-----
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/test_keys/priv/pep.color.test.V-0x71FC6D28_priv.asc	Mon Mar 13 15:03:14 2017 +0100
    20.3 @@ -0,0 +1,58 @@
    20.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
    20.5 +
    20.6 +lQOYBFi0NhwBCADA/h48Na8AJ/8gjonAxxJLboQBM5utqcMLN4QQNXtZC77xvUlj
    20.7 +LT2xIo+FRBjQ4eh8IxBH9zXfEIDlT3Xk7++HAcepsprf7Fg87IhH/XDEcz3Lq3x4
    20.8 +XNyBNeYL5MjLKfiIlyFtB/z7nMkNTRzSR+Iwz2tmsEh6EeRXYDPIzObwJCaSgJBf
    20.9 +KvsNRzcFrfDAU4KwZhBtpIGkN3fzrt/jgePybjnD0dFBzIQOy2lT6mwaaCBu1S4T
   20.10 +w5WtPKmfwOWBpeNeELBD/2++HpqtVKlq3+BjIEQoP+QOvQLte9d5oZP9XOhKQu95
   20.11 +M4YLaKWLlDFF5AMEogCnotmRj7XH7B1f1quTABEBAAEAB/wMOUxC9geClAX10vFo
   20.12 +s3M2MebMiK9InaML99U2jZyldDgA6cNXM8tfh9fdUgXcXSKzkij61e6klVAEtja6
   20.13 +bHQYcgVqezSSEE86dKThIm1dFAuK9e6pVQBmcrqCcFhDfgIO7LuiQ0pDyZd2bzbv
   20.14 +Hrx16P1dgLbmfHGhEyfUhR3vgc5+f7QyQWouHvnrRv5csFeJ8rN4gYEDcUkvqcTj
   20.15 +2qNLQU3B4V09S6VNdugBJZU1Sc4eG0HyP8OfHP/GPJELjgt7gTzcyhM+EZtFIIju
   20.16 +qaQFogJKUWqAcZ8zE0B1cU1NjMesSxQPdkNY9vWeIEnJ8himHP5Wa6X6M0Lh+vch
   20.17 +ZkaBBADWSGNZs5ayy7hHk+UiF+ysHQdeuOMP6sv9hv5GaLwIwaBwwORdohbwMdJn
   20.18 +vrkiIPOmCGQ0KUbwlZhfhazz4AUEnVC/YrhVRoM+3KtFmVvZ73tUMvbkigW8Y9ht
   20.19 +NM7TXVXJgAcDn9HfQz/xiQHx1FkpoKBsBLphgYMvd6HakhGYwQQA5pCnj/k/hKlX
   20.20 +rMLzMrWOWxc1qBKPZXRzw+EBepru2+ApbcmQsJOg8TpE9P+aG/mjodBe12j+aRfZ
   20.21 +pH+RnSIlpbv05PnD7OIADEZX+rejzkB0aANdTJ3ungHPG4heZK50ND9NedifFqQA
   20.22 +Fk9MAkAmeOxC7M03QtlklkWRi/xeZVMD/2wELEeXJlSDrb8KeqjfyMp4VZyGXir1
   20.23 +lzBhsdeIfKPJsmswslzv29TuKATmnaMaIVW8JsQj/A10qygRrLoiYttQG6JA7XSS
   20.24 +PY9a3YjzemawqpCKXA1pDWK7Q0re8nbUZTV9QcKHV2UK3rMnIT1TfeebSM5r11eM
   20.25 +4dQsv8sdErwIP+20alBlcCBDb2xvciBUZXN0IFYgKHNlbmRlcikgKHRlc3Qga2V5
   20.26 +IGZvciBjb2xvciB0ZXN0cy4gZG9uJ3QgbWVzcyB3aXRoIG1lLikgPHBlcC5jb2xv
   20.27 +ci50ZXN0LlZAa2dyb3Rob2ZmLm9yZz6JATkEEwEIACMFAli0NhwCGwMHCwkIBwMC
   20.28 +AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRAXm53ycfxtKEinCAC93W5VEJ9oUs/+dhiK
   20.29 +j4xG1H5SC/Jy9ChtIMEUprsZyHELILYKWOUSWeFD8LOBbgRNYcNQMCa4HhCVHnHc
   20.30 +wk6ZHnc2A2zH5qT+9cPx8oLP+/xo4AjHooIq4a2qPVKoLHaJA5ADZc9im6a2LNfK
   20.31 +I5jlM7JLif2ctcde8JqN/l8tKZMU1+uAT5+3Mr5Lo6TBXNMGQ/OfXHovJQ9xV9pl
   20.32 +9PzQRa4PbD/qUDlvyEMTcoNBbMUr+7DE/BjKPEv547weZamxCsJPInbSbeUcBSuF
   20.33 +C1rMDOvnfwyeW9SrDEPGuXDfKemDS4ji+FwqFD0L9BGfahdYMaSWigH4OowZrO5l
   20.34 +2jMTnQOYBFi0NhwBCADGvl5mNBuiHPEL7fX97pc/CdoUebziAcWrHMAKwdPN/LKm
   20.35 +7+sJ8GH41gd7gDf2IQb93EAj5QID0Auf9Q39d2tbxQTiK7Zkfcf+yh44KIHrTuen
   20.36 +ykQ6cfbnSNkOwQksbOp7MDiW0x1HK0y4XTFjENL2LEDgLIFus3jqZVAlZcQ/DonQ
   20.37 +kVM0m3HPHSCnLDvme/JCDuq0qz25e35ywLUpx9319TCVP+XXZ02dMCg/1R08Eb2C
   20.38 +cAmvtvPMzV5jQCxdscvRyG3eHoAFUOpo2h4IKfUlRAMOUdTQnuCGHzeWLRkwhL2V
   20.39 +6rXyT90eUly864K8LPOjZ2ils92AmqmM8DlRGHUhABEBAAEAB/4zyWUlsoxEyM/S
   20.40 +sPX5bhNBHNsTnMkoBxgvxzUPWIRNV3xh3YBcPaP5yCN4/ecXHnII8jxQXhsRTUPK
   20.41 +MXuswVJbPlJQcN18//1+GcKYFY4M96mLYjw3En0otSXCH3C5f8P1x5HnUyl84v6B
   20.42 +x97XlomyFcPt5grwApoOUcn5hLQHTdea5tVgozp/RNvL+8aiJDepEA3j9my1Cy5j
   20.43 +b76K8s/IqoMVX5vtQpDcvhN+a6ZInqiQVZ5pUMXlqm+Fi0Vq8+NMO1Qd4Zr2xakM
   20.44 +zHWewy3Im5OrywhTFR4d230xZBnRUvLS8rWO194PskCGQmA7B3d/tE71RyYOLoHM
   20.45 +3sgrSUilBADQ2AFb8++nJnjyivoR5gpDk1+7JnfnQSWXknd/VsfN6f0qXUYH5FLz
   20.46 +YCnR9NingKk5ZZcampnPGZ0SOUkhygvntqO3S6EggpbeLxhClK8s9F86jZU4gaDR
   20.47 +nV+JcftTyL0xrmY1ibLyPB4Up9uJ7nX/PnTidQnLyNdxWMimELDnEwQA856JCSy5
   20.48 +Wz0e//DCN7RluPoXywqD+plB3hUJe/D95JxjEDB4XvLJi8OGNMQJJYqkxt4MNOlD
   20.49 +O2tsEEKwKjBy0C5pj67AdbTghGLPTD1OMNiIIpfAlNdjYP/16qlauSLt/vnrHzL/
   20.50 +wQzsdO1tibMj6nAS0dcquzcaH0h9EV6DtXsEAKsqAoVWTzpFXfqlGzMatEXYFDre
   20.51 +yFH5bN+J4f7/rKf2fRWny99hipT9viOqOlo7696JvYMdwkevxCvYdvoljJAX7xy5
   20.52 +RBHhUvosNWDHn/GtKeO7laTQeXfQ6xtpjOqvksGfjZDjpxLa0QJidCGG+sncmI/s
   20.53 +RrfTfXbmVUYWdteYTWuJAR8EGAEIAAkFAli0NhwCGwwACgkQF5ud8nH8bSjACgf8
   20.54 +CYPaqU9AmeCfGj2djOqAC/qrSGdRbzEwLsB6uEgSch8Wj7nFleJ/PIgaTxBiHl2k
   20.55 +TMp7k3eTbNsHZjfDFQAxfRXbNAYzZFOCnocqPdabzg5GaBmPoC5SmnHFATSRtMDv
   20.56 +seXySqgV6b4nM+Omfz8ZFUpuDzzllhRo4j+VV/lN4BIC9O+R27LL8xQiCERJd3HK
   20.57 +7jI2qpYyC2TrvqKjpDekO76xPCtW+K71YbStUGNV3CE5tZHzxBqimzRj0DTWqwP2
   20.58 +gRDQgc6NvF8yro/Tje6FNh+Hy3ZSXI+xlP2Rx17S0FbvussNbNQx1KEShXLfH2DI
   20.59 +n6LP+on7cpRMDCJYivFJIA==
   20.60 +=flWf
   20.61 +-----END PGP PRIVATE KEY BLOCK-----
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/test_keys/pub/pep.color.test.H-0xD17E598E_pub.asc	Mon Mar 13 15:03:14 2017 +0100
    21.3 @@ -0,0 +1,31 @@
    21.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    21.5 +
    21.6 +mQENBFi0Nl8BCADSZSP/I35zpiaShZ9bn96AWFsQnD32stjEuQxYLO+T5krbot0x
    21.7 +eqHPI5jHs4tF9j/DwQ4qaI2v6Tj5csHgSYfsFvIst5xmVEsOXUYZBXSSzei29XQx
    21.8 +XISQZwHcaY0znXGN5Dnj4oeJq/Ok3G0TZ2ddx5pmEu5j9+VA3NLC65hKXnbeY7+A
    21.9 +uNo6UYDqo6FPqBff6IO4ibKPLZ09kZbF6xh77dOAJfWbeNS8oifaqQ2NIfork/Uz
   21.10 +dq67xO7V28RlJKhFQo95EJyjw2Juu0p4UYMt9c5Dte+Lxz47iSqIzHJH9Odd5klP
   21.11 +isrCWq2U6ALAFIKp6ykNg9d3SW2J7LWIfJq/ABEBAAG0b1BlcCBDb2xvciBUZXN0
   21.12 +IEggKG90aGVyIHJlY2lwKSAodGVzdCBrZXkgZm9yIGNvbG9yIHRlc3RzLiBkb24n
   21.13 +dCBtZXNzIHdpdGggbWUuKSA8cGVwLmNvbG9yLnRlc3QuSEBrZ3JvdGhvZmYub3Jn
   21.14 +PokBOQQTAQgAIwUCWLQ2XwIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJ
   21.15 +EL5pp6DRflmOlVAH/iH6KhXLAN90vyUEfPxITWsSO/IN6XN4mjUxhY7QyGJg2P77
   21.16 +ljkAYup4ukIwEPx/XaKeb/OfeochpkhhS9uW7TBqnn5B8Xd80UV+WdY3knv0ba6U
   21.17 +1HnUq2CE+QkVkVfLWxIwSHPCnvDz3rNcp9j70oyoMqKvezCB+hxn1+jHJOmugQ44
   21.18 +Q/AWJraeuGNbrMOwUWwscBg7ikYEbbIT7RNdG4QpCYQxIQNRTEXJ9bLChNs4Daai
   21.19 +2S5qMInsAA4NWc8OvJNBhixWVmoaHfuy4GdxjUhDkZR79butWw+/2DcUEbkmUXxu
   21.20 +4TIPQEi3IfsHHwMopiJfALU0Zqq4BNGWjhzgldu5AQ0EWLQ2XwEIAOIZwJVXR2Rv
   21.21 +coz3FnwDaTvww5LztQKskZd7TszdMvv/c3QxPJbk4B0w1nZPcXu4UohRl2dAcxVT
   21.22 +gXVB7cM1K1ush1/QJQWuxDvJK+MN+WynkpMuQmaiEKTnXqc3N7U8Ejf6oRbt7K/+
   21.23 +8dmXX7zOFvThFAEA9cnK4ot5jMFLM6lYbHBj5tP1Al0E9kZV4SzYS5mLcl3ulCoS
   21.24 +Zufz8MVrEOrS1llUwpiVhsHTs81kzAIsdOKdb9QmbOctLmHiWg7O/97I9/CK3nC/
   21.25 +2IYOyhAccRd08lopbvEfdgBQaKT8R4+npL+YGGh7l5IJHlNbZHAsa8RJDNwCEPKI
   21.26 +MRwN1eO8YZkAEQEAAYkBHwQYAQgACQUCWLQ2XwIbDAAKCRC+aaeg0X5ZjjT6B/9T
   21.27 +2HneZqBhUhcJI+/j94MXoYIJHZkODo5MP30ynlXc6+kJiYyXbuK+K0Z64bpRpO7c
   21.28 +KPvdQCkcQ75LDqXGgT7/wH8rzP2Q7G+gsh2JBzGyaPPF6w9eEK8gML3G8gAFo6BV
   21.29 ++bXR8vNO7n9XjvambNkqDobZECr3TmaUjWBkkV0r3Vhb36a5XRY2uO1E1GB9ihF3
   21.30 ++9pljpFiHeTBT3dDQBeVq7WGmO84lHdPb14nwm94Zn7N/nJMa5NBDDph8dGtf5j1
   21.31 +Rg5R1rn+ABl3/N+7pmcEFMJbjtJdYuLC6PLfhw1nO6BhuTW2hcHRUe4lt7xAWEVG
   21.32 +LUkrI+IvjaiKmOvYCwl0
   21.33 +=GR5N
   21.34 +-----END PGP PUBLIC KEY BLOCK-----
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/test/test_keys/pub/pep.color.test.L-0xE9CDB4CE_pub.asc	Mon Mar 13 15:03:14 2017 +0100
    22.3 @@ -0,0 +1,31 @@
    22.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    22.5 +
    22.6 +mQENBFi0NaUBCAC3TwbxovyU/zUFDG0d+m55UF9zmxjfnwhTnoPCOtSDK2eVZFOv
    22.7 +ZCSatpsIZzJ5BWDC7hn+sgbELhgckVvfEzAz8GKow9tCiRuyW5XThDdtujGChlbY
    22.8 +Jnsto91v8hwdXa9DEYz+XSary7DJp0VsSLnxJglxH+r4H688iT6f/w11RLAEcESF
    22.9 +BsZLTQx769YCPZw9rHN5pPpyJrkkNJINPUzIYIgQ4fKdPe3ECOL2NilA5IhFkuLA
   22.10 +3FZdeE4F/Jsb4GAu+nb8wJxBZbPZxBs/Hw+PTI/ACpUnj2Y1nUPRzRAFYuompZcw
   22.11 +GxvC0Y2Oy5HJumLW5e5Y3r2b5hE8x8rQnX65ABEBAAG0b1BlcCBDb2xvciBUZXN0
   22.12 +IEwgKG90aGVyIHJlY2lwKSAodGVzdCBrZXkgZm9yIGNvbG9yIHRlc3RzLiBkb24n
   22.13 +dCBtZXNzIHdpdGggbWUuKSA8cGVwLmNvbG9yLnRlc3QuTEBrZ3JvdGhvZmYub3Jn
   22.14 +PokBOQQTAQgAIwUCWLQ1pQIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJ
   22.15 +EC3ZgKjpzbTOePgH/0URElHoQJIMT246FF/j2RUka+rAUSHfgCoEAQIROUETEWZX
   22.16 +tLwyA9UdKq4+abg6Y7x9QTazUxwaYlCD0rmI0caraZBEcw8KefugNG+uFo5CZxp8
   22.17 +U6v3Gkp/u26o6RLelgq2wpCPE2NUpKNwzL1Q64szHez8Bv14tMxBR2minERnGQoP
   22.18 +WVj9yesuA/4oTE8gHzrvwM5pu0KdWNvLmFWC6KJSGcNo7S4CCOe307/EyFXTNy/I
   22.19 +bnj6vr3t0fC10RScH2gxTj5+1JKUerNlDnNC7V7wMiyzOh0X7BQSFmESCgIo03d+
   22.20 +KFZvj/b5kyOlnn93PLCA83zhNA+5TpsYmToehpW5AQ0EWLQ1pQEIALmvIDyG2wEy
   22.21 +9eWC37aczgNOxnELOH9Zq9iEQWaQypjbGCaWWTgjo+cNR/ibKAyHCaYReKULylaw
   22.22 +QVVDTgVp4/CrU2nXP0ozjvHb5MoB+Whp+bYlZpQ7jQIYwblaM9CMfZ/ROhkTYvsj
   22.23 +f+LGJUXwRHAJTSUnxT+PP9p30Nfp8yISres+ihz+BF7rKJwNiJhvPWyqAeEMnJWx
   22.24 +rc8ZjKSy4JUAryn2IlxsOleNhT4NXFyzYdg33rtLWQ4jxiT0RYqHecFhBX9kLclL
   22.25 +4wYwvh7DcaFkSPY5vk+3csZhs74U2+PgQkaVqAXQlX4fGoDqOWU/s+VTbVEEduwZ
   22.26 +gGpDIax1Kz0AEQEAAYkBHwQYAQgACQUCWLQ1pQIbDAAKCRAt2YCo6c20znQQB/47
   22.27 +kyeQIrz1CxijZ8uKyLSXxrOBuEL/ximZlfyQHYxHMYWGqor662DdXZcvg2qSr+sk
   22.28 +dtkUfKeC5kshiJAH1c1AzCm6jXt6fB0T4sARo7FRbQJJv5/5C5uz4KsKF9qD+89w
   22.29 +22QSKyQLXNBxQQG3mMvfSFXBiNg/AaIeoXateppblRhbJDmBGIqkDryjliURU8W1
   22.30 +0LdD3kYaQ8TLj6HDIssLgA0FbtdEiJkiFhMAYU/ObmnhgQJrJku6VMVsQ0LlWgcZ
   22.31 +yp15p5w3b9iqseJCdejkz8xlKA/IUN7YS48jrlfJRmEjz++EO3sWD5jYuHDrG9gg
   22.32 +wen0UoY4IGhF+PgFVCRF
   22.33 +=cLMc
   22.34 +-----END PGP PUBLIC KEY BLOCK-----
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/test/test_keys/pub/pep.color.test.P-0x3EBE215C_pub.asc	Mon Mar 13 15:03:14 2017 +0100
    23.3 @@ -0,0 +1,31 @@
    23.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    23.5 +
    23.6 +mQENBFi0NWIBCADfZwQP5IWDe5K+LohvaZgyeqCnA8tA3wmFmDCSrSTg596LJAj/
    23.7 ++NCO+cXABRbiihAOfCQ4vZZu+nBOXrGt6iAxsEZrbQg0MUx0vvbeuVeuF2ItHobE
    23.8 +BSwQVGArqDlU+Ts+Ew3+nenJZBg+4KTq4i3L2RTq+AIxV/DLLQat4Qc2tdfDiuBA
    23.9 +dI3Ro2d6va+6Dd/z37V7FZEPG+oAiKeLEl7Alr8iyrBLWyiIKWFjOIK9N094NifY
   23.10 +6UayN7AAiFBWv7dAIRRL9WtSfRIap7Iv3LrjIVLDdeIZfbrhEOC/a3D4rQQ0gkqS
   23.11 +MZWSUlRUuZ/AlFYNzyFoIEZmG2dnh5FhzU/DABEBAAG0aVBlcCBDb2xvciBUZXN0
   23.12 +IFAgKHJlY2lwKSAodGVzdCBrZXkgZm9yIGNvbG9yIHRlc3RzLiBkb24ndCBtZXNz
   23.13 +IHdpdGggbWUuKSA8cGVwLmNvbG9yLnRlc3QuUEBrZ3JvdGhvZmYub3JnPokBOQQT
   23.14 +AQgAIwUCWLQ1YgIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEOpZcV4+
   23.15 +viFcu0IH/AsCpzsRv/adLiGy979mLZriFWxYhW2zUUA2sWXvlX9FibH32ve5cG+k
   23.16 +5DqwctqWmA+EkcvVER7GzvQrEJLvmzJnjq19CGzg8rm7HgNp6EKIHMH70gVUEika
   23.17 +wjstZ5eMO5raD+5qFZhQzTDsT9DIXYGnqUOGUaoelreZpadT4ZqF4WHxux2JJboj
   23.18 +ShUSfo9lUY3iIH4YInAmYdaoODKjDTzNVMKfujyMFz6TrpjQUQFazi7JtbeTQflu
   23.19 +FTR8rp8CwKOgwDVUMgfie6kLYwncZDkAsIMVs1Vc3uHRwa8arHavRSxN0rnXGty/
   23.20 +oNuErGX0aiYBOtaUjRsU9C5x69jmV665AQ0EWLQ1YgEIAMMysh2rCBvNtirkHt5k
   23.21 +YKDCBfpRANzWl7z9z8LVg8KI0bt8KaR7+zyWfNKdf3c7Qi8MhI7EGBzQiu62CqlR
   23.22 +cP9I61rAH2yxoNn4+JOVTObtGjJpzwoYO+umrJZ6h1JrV8SMEkrUp51xDsEr9RKt
   23.23 +dmGvDNjZRD0Jlh7gGMlH+1LwkUOe0OoZkfQz7b/TWnvkZfveVyTZI4SnxpeEVzIb
   23.24 +Tx7qceTByJeNoHnd4DIHH4sZHkEAxxkE6VQf7BXykV4xh+G76o3JVytE3bDIrCpP
   23.25 +waswlpZ9++8Jr5bB5o+JN8po9pxS4rKE7ngzwqvpCLzCZV3t2+YlVKSkI9kqo4z7
   23.26 +DV0AEQEAAYkBHwQYAQgACQUCWLQ1YgIbDAAKCRDqWXFePr4hXJU8CACDr98ShkdT
   23.27 +6KMHvRCqfKCRKwgFm6G4zeJGfww9sGtykhG9bECydHv+mFxUtMT2PzBIVz4cNcCv
   23.28 +/ODdkJq6/yyKi2ZYWQ65nykmBiWi0SudcHsTMfmyQHzC07NMRGz+ZgnF9ipeQ41I
   23.29 +8rOLzoIcxHZGVUzrGtQ3G9NGUnb2fa8i78dtme9/gY9f0LhIpwiP3CMzHzXUV8uE
   23.30 +sDGhzLVRYJBcwHP017C+0I7gVfM3IWwjjNRjhelgKnFE+pvo6agDhqi77d/GEOBU
   23.31 +ZCj16UqIj8pPc+iAWHeYqdIve7vOWP0t7bJ5tuvqsNFvPJJgzgEw9CNaP2e8hCoz
   23.32 +SJhlhi9r7x0R
   23.33 +=BqBz
   23.34 +-----END PGP PUBLIC KEY BLOCK-----
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/test/test_keys/pub/pep.color.test.V-0x71FC6D28_pub.asc	Mon Mar 13 15:03:14 2017 +0100
    24.3 @@ -0,0 +1,31 @@
    24.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    24.5 +
    24.6 +mQENBFi0NhwBCADA/h48Na8AJ/8gjonAxxJLboQBM5utqcMLN4QQNXtZC77xvUlj
    24.7 +LT2xIo+FRBjQ4eh8IxBH9zXfEIDlT3Xk7++HAcepsprf7Fg87IhH/XDEcz3Lq3x4
    24.8 +XNyBNeYL5MjLKfiIlyFtB/z7nMkNTRzSR+Iwz2tmsEh6EeRXYDPIzObwJCaSgJBf
    24.9 +KvsNRzcFrfDAU4KwZhBtpIGkN3fzrt/jgePybjnD0dFBzIQOy2lT6mwaaCBu1S4T
   24.10 +w5WtPKmfwOWBpeNeELBD/2++HpqtVKlq3+BjIEQoP+QOvQLte9d5oZP9XOhKQu95
   24.11 +M4YLaKWLlDFF5AMEogCnotmRj7XH7B1f1quTABEBAAG0alBlcCBDb2xvciBUZXN0
   24.12 +IFYgKHNlbmRlcikgKHRlc3Qga2V5IGZvciBjb2xvciB0ZXN0cy4gZG9uJ3QgbWVz
   24.13 +cyB3aXRoIG1lLikgPHBlcC5jb2xvci50ZXN0LlZAa2dyb3Rob2ZmLm9yZz6JATkE
   24.14 +EwEIACMFAli0NhwCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRAXm53y
   24.15 +cfxtKEinCAC93W5VEJ9oUs/+dhiKj4xG1H5SC/Jy9ChtIMEUprsZyHELILYKWOUS
   24.16 +WeFD8LOBbgRNYcNQMCa4HhCVHnHcwk6ZHnc2A2zH5qT+9cPx8oLP+/xo4AjHooIq
   24.17 +4a2qPVKoLHaJA5ADZc9im6a2LNfKI5jlM7JLif2ctcde8JqN/l8tKZMU1+uAT5+3
   24.18 +Mr5Lo6TBXNMGQ/OfXHovJQ9xV9pl9PzQRa4PbD/qUDlvyEMTcoNBbMUr+7DE/BjK
   24.19 +PEv547weZamxCsJPInbSbeUcBSuFC1rMDOvnfwyeW9SrDEPGuXDfKemDS4ji+Fwq
   24.20 +FD0L9BGfahdYMaSWigH4OowZrO5l2jMTuQENBFi0NhwBCADGvl5mNBuiHPEL7fX9
   24.21 +7pc/CdoUebziAcWrHMAKwdPN/LKm7+sJ8GH41gd7gDf2IQb93EAj5QID0Auf9Q39
   24.22 +d2tbxQTiK7Zkfcf+yh44KIHrTuenykQ6cfbnSNkOwQksbOp7MDiW0x1HK0y4XTFj
   24.23 +ENL2LEDgLIFus3jqZVAlZcQ/DonQkVM0m3HPHSCnLDvme/JCDuq0qz25e35ywLUp
   24.24 +x9319TCVP+XXZ02dMCg/1R08Eb2CcAmvtvPMzV5jQCxdscvRyG3eHoAFUOpo2h4I
   24.25 +KfUlRAMOUdTQnuCGHzeWLRkwhL2V6rXyT90eUly864K8LPOjZ2ils92AmqmM8DlR
   24.26 +GHUhABEBAAGJAR8EGAEIAAkFAli0NhwCGwwACgkQF5ud8nH8bSjACgf8CYPaqU9A
   24.27 +meCfGj2djOqAC/qrSGdRbzEwLsB6uEgSch8Wj7nFleJ/PIgaTxBiHl2kTMp7k3eT
   24.28 +bNsHZjfDFQAxfRXbNAYzZFOCnocqPdabzg5GaBmPoC5SmnHFATSRtMDvseXySqgV
   24.29 +6b4nM+Omfz8ZFUpuDzzllhRo4j+VV/lN4BIC9O+R27LL8xQiCERJd3HK7jI2qpYy
   24.30 +C2TrvqKjpDekO76xPCtW+K71YbStUGNV3CE5tZHzxBqimzRj0DTWqwP2gRDQgc6N
   24.31 +vF8yro/Tje6FNh+Hy3ZSXI+xlP2Rx17S0FbvussNbNQx1KEShXLfH2DIn6LP+on7
   24.32 +cpRMDCJYivFJIA==
   24.33 +=i+0S
   24.34 +-----END PGP PUBLIC KEY BLOCK-----