Merged in sync/parent ENGINE-559
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Tue, 04 Jun 2019 15:08:54 +0200
branchENGINE-559
changeset 3829e1d53d19bb4d
parent 3805 2e7f89437eb8
parent 3828 8b28b328fd1b
child 3830 2fbdb002d301
Merged in sync/parent
src/message_api.c
src/pEpEngine.c
src/pEp_internal.h
test/src/SuiteMaker.cc
     1.1 --- a/src/map_asn1.c	Wed May 29 19:33:45 2019 +0200
     1.2 +++ b/src/map_asn1.c	Tue Jun 04 15:08:54 2019 +0200
     1.3 @@ -134,11 +134,15 @@
     1.4      if (!list)
     1.5          return NULL;
     1.6  
     1.7 -    if (allocated)
     1.8 +    if (allocated) {
     1.9          result = (IdentityList_t *) calloc(1, sizeof(IdentityList_t));
    1.10 -    assert(result);
    1.11 -    if (!result)
    1.12 -        return NULL;
    1.13 +        assert(result);
    1.14 +        if (!result)
    1.15 +            return NULL;
    1.16 +    }
    1.17 +    else {
    1.18 +        asn_sequence_empty(result);
    1.19 +    }
    1.20  
    1.21      for (const identity_list *l = list; l && l->ident; l=l->next) {
    1.22          Identity_t *ident = Identity_from_Struct(l->ident, NULL);
     2.1 --- a/src/message_api.c	Wed May 29 19:33:45 2019 +0200
     2.2 +++ b/src/message_api.c	Tue Jun 04 15:08:54 2019 +0200
     2.3 @@ -3996,15 +3996,16 @@
     2.4              !(*flags & PEP_decrypt_flag_dont_trigger_sync)) {
     2.5          size_t size;
     2.6          const char *data;
     2.7 -        char *sync_fpr = NULL;
     2.8 -        PEP_STATUS tmpstatus = base_extract_message(session, msg, &size, &data, &sync_fpr);
     2.9 +        char *sender_fpr = NULL;
    2.10 +        PEP_STATUS tmpstatus = base_extract_message(session, msg, &size, &data, &sender_fpr);
    2.11          if (!tmpstatus && size && data) {
    2.12 -            if (sync_fpr)
    2.13 -                signal_Sync_message(session, *rating, data, size, msg->from, sync_fpr);
    2.14 +            if (sender_fpr)
    2.15 +                signal_Sync_message(session, *rating, data, size, msg->from, sender_fpr);
    2.16 +            // FIXME: this must be changed to sender_fpr
    2.17              else if (*keylist)
    2.18                  signal_Sync_message(session, *rating, data, size, msg->from, (*keylist)->value);
    2.19          }
    2.20 -        free(sync_fpr);
    2.21 +        free(sender_fpr);
    2.22      }
    2.23  
    2.24      return status;
     3.1 --- a/src/pEpEngine.c	Wed May 29 19:33:45 2019 +0200
     3.2 +++ b/src/pEpEngine.c	Tue Jun 04 15:08:54 2019 +0200
     3.3 @@ -997,6 +997,7 @@
     3.4                  "   timestamp integer default (datetime('now')),\n"
     3.5                  "   primary key (address, user_id)\n"
     3.6                  ");\n"
     3.7 +                "create index if not exists identity_userid_addr on identity(address, user_id);\n"
     3.8                  "create table if not exists trust (\n"
     3.9                  "   user_id text not null\n"
    3.10                  "       references person (id)\n"
    3.11 @@ -1458,6 +1459,16 @@
    3.12              if (version < 12) {
    3.13                  int_result = sqlite3_exec(
    3.14                      _session->db,
    3.15 +                    "create index if not exists identity_userid_addr on identity(address, user_id);\n"
    3.16 +                    ,
    3.17 +                    NULL,
    3.18 +                    NULL,
    3.19 +                    NULL
    3.20 +                );
    3.21 +                assert(int_result == SQLITE_OK);
    3.22 +                
    3.23 +                int_result = sqlite3_exec(
    3.24 +                    _session->db,
    3.25                      "alter table identity\n"
    3.26                      "   add column pEp_version_major integer default 0;\n"
    3.27                      "alter table identity\n"
     4.1 --- a/src/pEp_internal.h	Wed May 29 19:33:45 2019 +0200
     4.2 +++ b/src/pEp_internal.h	Tue Jun 04 15:08:54 2019 +0200
     4.3 @@ -151,6 +151,7 @@
     4.4          sqlite3_stmt *tpk_save_insert_primary;
     4.5          sqlite3_stmt *tpk_save_insert_subkeys;
     4.6          sqlite3_stmt *tpk_save_insert_userids;
     4.7 +        sqlite3_stmt *delete_keypair;
     4.8      } sq_sql;
     4.9  #endif
    4.10  
    4.11 @@ -260,7 +261,6 @@
    4.12      void *sync_management;
    4.13      void *sync_obj;
    4.14      struct Sync_state_s sync_state;
    4.15 -    struct own_Sync_state_s own_sync_state;
    4.16  
    4.17  //     void* sync_state_payload;
    4.18  //     char sync_uuid[37];
     5.1 --- a/src/pgp_sequoia.c	Wed May 29 19:33:45 2019 +0200
     5.2 +++ b/src/pgp_sequoia.c	Tue Jun 04 15:08:54 2019 +0200
     5.3 @@ -141,9 +141,13 @@
     5.4  
     5.5      char *a_address = NULL;
     5.6      pgp_user_id_address_normalized(NULL, a_userid, &a_address);
     5.7 +    if (!a_address)
     5.8 +        pgp_user_id_other(NULL, a_userid, &a_address);
     5.9  
    5.10      char *b_address = NULL;
    5.11      pgp_user_id_address_normalized(NULL, b_userid, &b_address);
    5.12 +    if (!b_address)
    5.13 +        pgp_user_id_other(NULL, b_userid, &b_address);
    5.14  
    5.15      pgp_packet_free(a_userid);
    5.16      pgp_packet_free(b_userid);
    5.17 @@ -396,6 +400,12 @@
    5.18                               -1, &session->sq_sql.tpk_save_insert_userids, NULL);
    5.19      assert(sqlite_result == SQLITE_OK);
    5.20  
    5.21 +    sqlite_result
    5.22 +        = sqlite3_prepare_v2(session->key_db,
    5.23 +                             "DELETE FROM keys WHERE primary_key = ?",
    5.24 +                             -1, &session->sq_sql.delete_keypair, NULL);
    5.25 +    assert(sqlite_result == SQLITE_OK);
    5.26 +
    5.27   out:
    5.28      if (status != PEP_STATUS_OK)
    5.29          pgp_release(session, in_first);
    5.30 @@ -421,8 +431,6 @@
    5.31      }
    5.32  }
    5.33  
    5.34 -/* commented out to omit compiler warning about unused function
    5.35 -
    5.36  // Ensures that a fingerprint is in canonical form.  A canonical
    5.37  // fingerprint doesn't contain any white space.
    5.38  //
    5.39 @@ -437,8 +445,6 @@
    5.40      return fpr_canonicalized;
    5.41  }
    5.42  
    5.43 -*/
    5.44 -
    5.45  // step statement and load the tpk and secret.
    5.46  static PEP_STATUS key_load(PEP_SESSION, sqlite3_stmt *, pgp_tpk_t *, int *)
    5.47      __attribute__((nonnull(1, 2)));
    5.48 @@ -793,54 +799,7 @@
    5.49  
    5.50          pgp_packet_t userid = pgp_user_id_new (user_id_value);
    5.51          pgp_user_id_name(NULL, userid, &name);
    5.52 -        pgp_user_id_address(NULL, userid, &email);
    5.53 -                
    5.54 -        if (!email || email[0] == '\0') {
    5.55 -            size_t uid_value_len;
    5.56 -            const char* uid_value = (const char*)pgp_user_id_value(userid, &uid_value_len);
    5.57 -            if (!uid_value) {
    5.58 -                // We need some kind of an error here, maybe?
    5.59 -                 
    5.60 -            }
    5.61 -            else {
    5.62 -                // Ok, asan gets really pissed at us using this string directly, SO...
    5.63 -                char* uid_copy = calloc(uid_value_len + 1, 1);
    5.64 -                strlcpy(uid_copy, uid_value, uid_value_len);
    5.65 -                const char* split = strstr(uid_copy, "<");
    5.66 -                if (split != uid_copy) {       
    5.67 -                    while (split) {
    5.68 -                        if (isspace(*(split - 1)))
    5.69 -                            break;
    5.70 -                        split = strstr(split + 1, "<");
    5.71 -                    }
    5.72 -                }
    5.73 -                if (split) {
    5.74 -                    char* stopchr = strrchr(split, '>');
    5.75 -                    if (stopchr) {
    5.76 -                        int email_len = stopchr - split - 1;
    5.77 -                        email = calloc(email_len + 1, 1); 
    5.78 -                        strlcpy(email, split + 1, email_len + 1);
    5.79 -                        const char* last = NULL;
    5.80 -                        if (split != uid_value) {
    5.81 -                            for (last = split - 1; last > uid_value; last--) {
    5.82 -                                if (!isspace(*last))
    5.83 -                                    break;
    5.84 -                            }
    5.85 -                            int name_len = (last - uid_value) + 1;
    5.86 -                            name = calloc(name_len + 1, 1);
    5.87 -                            strlcpy(name, uid_value, name_len + 1);
    5.88 -                        }
    5.89 -                    }
    5.90 -                    else  
    5.91 -                        split = NULL;
    5.92 -                }
    5.93 -                if (split == NULL)
    5.94 -                    email = uid_copy;
    5.95 -                else 
    5.96 -                    free(uid_copy);
    5.97 -            }
    5.98 -        }
    5.99 -        
   5.100 +        pgp_user_id_address_or_other(NULL, userid, &email);
   5.101          pgp_packet_free(userid);
   5.102          free(user_id_value);
   5.103  
   5.104 @@ -897,15 +856,12 @@
   5.105  
   5.106      free(email);
   5.107      free(name);
   5.108 -    if (user_id_iter)
   5.109 -        pgp_user_id_binding_iter_free(user_id_iter);
   5.110 -    if (key_iter)
   5.111 -        pgp_tpk_key_iter_free(key_iter);
   5.112 +    pgp_user_id_binding_iter_free(user_id_iter);
   5.113 +    pgp_tpk_key_iter_free(key_iter);
   5.114      if (stmt)
   5.115        sqlite3_reset(stmt);
   5.116      free(tsk_buffer);
   5.117 -    if (tpk)
   5.118 -        pgp_tpk_free(tpk);
   5.119 +    pgp_tpk_free(tpk);
   5.120      free(fpr);
   5.121      pgp_fingerprint_free(pgp_fpr);
   5.122  
   5.123 @@ -1057,13 +1013,10 @@
   5.124          cookie->decrypted = 1;
   5.125  
   5.126      eol:
   5.127 -        if (sk)
   5.128 -            pgp_session_key_free (sk);
   5.129 +        pgp_session_key_free (sk);
   5.130          free(keyid_str);
   5.131 -        if (key_iter)
   5.132 -            pgp_tpk_key_iter_free(key_iter);
   5.133 -        if (tpk)
   5.134 -            pgp_tpk_free(tpk);
   5.135 +        pgp_tpk_key_iter_free(key_iter);
   5.136 +        pgp_tpk_free(tpk);
   5.137      }
   5.138  
   5.139      // Consider wildcard recipients.
   5.140 @@ -1136,11 +1089,9 @@
   5.141              key_iter = NULL;
   5.142          }
   5.143      eol2:
   5.144 -        if (sk)
   5.145 -            pgp_session_key_free (sk);
   5.146 +        pgp_session_key_free (sk);
   5.147          free(keyid_str);
   5.148 -        if (key_iter)
   5.149 -            pgp_tpk_key_iter_free(key_iter);
   5.150 +        pgp_tpk_key_iter_free(key_iter);
   5.151      }
   5.152  
   5.153      if (tsks) {
   5.154 @@ -1474,12 +1425,9 @@
   5.155          free(*ptext);
   5.156      }
   5.157  
   5.158 -    if (reader)
   5.159 -        pgp_reader_free(reader);
   5.160 -    if (decryptor)
   5.161 -        pgp_reader_free(decryptor);
   5.162 -    if (writer)
   5.163 -        pgp_writer_free(writer);
   5.164 +    pgp_reader_free(reader);
   5.165 +    pgp_reader_free(decryptor);
   5.166 +    pgp_writer_free(writer);
   5.167  
   5.168      T("-> %s", pEp_status_to_string(status));
   5.169      return status;
   5.170 @@ -1573,12 +1521,9 @@
   5.171          free_stringlist(cookie.signer_keylist);
   5.172      }
   5.173  
   5.174 -    if (verifier)
   5.175 -        pgp_reader_free(verifier);
   5.176 -    if (reader)
   5.177 -        pgp_reader_free(reader);
   5.178 -    if (dsig_reader)
   5.179 -        pgp_reader_free(dsig_reader);
   5.180 +    pgp_reader_free(verifier);
   5.181 +    pgp_reader_free(reader);
   5.182 +    pgp_reader_free(dsig_reader);
   5.183  
   5.184      T("-> %s", pEp_status_to_string(status));
   5.185      return status;
   5.186 @@ -1660,14 +1605,10 @@
   5.187      (*stext)[*ssize] = 0;
   5.188  
   5.189   out:
   5.190 -    if (signer)
   5.191 -        pgp_signer_free (signer);
   5.192 -    if (signing_keypair)
   5.193 -        pgp_key_pair_free (signing_keypair);
   5.194 -    if (iter)
   5.195 -        pgp_tpk_key_iter_free (iter);
   5.196 -    if (signer_tpk)
   5.197 -        pgp_tpk_free(signer_tpk);
   5.198 +    pgp_signer_free (signer);
   5.199 +    pgp_key_pair_free (signing_keypair);
   5.200 +    pgp_tpk_key_iter_free (iter);
   5.201 +    pgp_tpk_free(signer_tpk);
   5.202  
   5.203      T("(%s)-> %s", fpr, pEp_status_to_string(status));
   5.204      return status;
   5.205 @@ -1781,14 +1722,10 @@
   5.206      (*ctext)[*csize] = 0;
   5.207  
   5.208   out:
   5.209 -    if (signer)
   5.210 -        pgp_signer_free (signer);
   5.211 -    if (signing_keypair)
   5.212 -        pgp_key_pair_free (signing_keypair);
   5.213 -    if (iter)
   5.214 -        pgp_tpk_key_iter_free (iter);
   5.215 -    if (signer_tpk)
   5.216 -        pgp_tpk_free(signer_tpk);
   5.217 +    pgp_signer_free (signer);
   5.218 +    pgp_key_pair_free (signing_keypair);
   5.219 +    pgp_tpk_key_iter_free (iter);
   5.220 +    pgp_tpk_free(signer_tpk);
   5.221  
   5.222      for (int i = 0; i < keys_count; i ++)
   5.223          pgp_tpk_free(keys[i]);
   5.224 @@ -1819,6 +1756,7 @@
   5.225  {
   5.226      PEP_STATUS status = PEP_STATUS_OK;
   5.227      pgp_error_t err = NULL;
   5.228 +    pgp_packet_t userid_packet = NULL;
   5.229      char *userid = NULL;
   5.230      pgp_tpk_t tpk = NULL;
   5.231      pgp_fingerprint_t pgp_fpr = NULL;
   5.232 @@ -1830,16 +1768,22 @@
   5.233      assert(identity->fpr == NULL || identity->fpr[0] == 0);
   5.234      assert(identity->username);
   5.235  
   5.236 -    size_t userid_size = strlen(identity->username)+strlen(identity->address)+3+1;
   5.237 -    userid = (char *) calloc(1, userid_size);
   5.238 -    assert(userid);
   5.239 +    userid_packet = pgp_user_id_from_unchecked_address(&err,
   5.240 +                                                       identity->username, NULL,
   5.241 +                                                       identity->address);
   5.242 +    if (!userid_packet)
   5.243 +        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_user_id_from_other_address");
   5.244 +
   5.245 +    size_t userid_len = 0;
   5.246 +    const uint8_t *raw = pgp_user_id_value(userid_packet, &userid_len);
   5.247 +
   5.248 +    // NUL terminate it.
   5.249 +    userid = malloc(userid_len + 1);
   5.250      if (!userid)
   5.251          ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
   5.252  
   5.253 -    int r = snprintf(userid, userid_size, "%s <%s>", identity->username, identity->address);
   5.254 -    assert(r >= 0 && r < userid_size);
   5.255 -    if (r < 0)
   5.256 -        ERROR_OUT(NULL, PEP_UNKNOWN_ERROR, "snprintf");
   5.257 +    memcpy(userid, raw, userid_len);
   5.258 +    userid[userid_len] = 0;
   5.259  
   5.260      T("(%s)", userid);
   5.261  
   5.262 @@ -1867,51 +1811,47 @@
   5.263      fpr = NULL;
   5.264  
   5.265   out:
   5.266 -    if (pgp_fpr)
   5.267 -        pgp_fingerprint_free(pgp_fpr);
   5.268 +    pgp_fingerprint_free(pgp_fpr);
   5.269      free(fpr);
   5.270 -    if (tpk)
   5.271 -        pgp_tpk_free(tpk);
   5.272 +    pgp_tpk_free(tpk);
   5.273      free(userid);
   5.274 +    pgp_packet_free(userid_packet);
   5.275  
   5.276      T("-> %s", pEp_status_to_string(status));
   5.277      return status;
   5.278  }
   5.279  
   5.280 -#define SQL_DELETE "DELETE FROM keys WHERE primary_key = '%s' ;"
   5.281 -static const char *sql_delete = SQL_DELETE;
   5.282 -static const size_t sql_delete_size = sizeof(SQL_DELETE);
   5.283 -
   5.284 -// FIXME: this is deleting the key from the index but not the key data
   5.285 -
   5.286 -PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
   5.287 +PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr_raw)
   5.288  {
   5.289 -    assert(session && fpr && fpr[0]);
   5.290 -    if (!(session && fpr && fpr[0]))
   5.291 -        return PEP_ILLEGAL_VALUE;
   5.292 -
   5.293 -    size_t sql_size = sql_delete_size + strlen(fpr);
   5.294 -    char *sql = calloc(1, sql_size);
   5.295 -    assert(sql);
   5.296 -    if (!sql)
   5.297 -        return PEP_OUT_OF_MEMORY;
   5.298 -
   5.299 -    int r = snprintf(sql, sql_size, sql_delete, fpr);
   5.300 -    assert(r > 0 && r < sql_size);
   5.301 -    if (r < 0)
   5.302 -        return PEP_UNKNOWN_ERROR;
   5.303 -
   5.304 -    int sqlite_result = sqlite3_exec(session->key_db, sql, NULL, NULL, NULL);
   5.305 -    assert(sqlite_result == SQLITE_OK);
   5.306 -    if (sqlite_result != SQLITE_OK)
   5.307 -        return PEP_CANNOT_DELETE_KEY;
   5.308 +    PEP_STATUS status = PEP_STATUS_OK;
   5.309 +
   5.310 +    assert(session && fpr_raw && fpr_raw[0]);
   5.311 +    if (!(session && fpr_raw && fpr_raw[0]))
   5.312 +        ERROR_OUT(NULL, PEP_ILLEGAL_VALUE, "invalid arguments");
   5.313 +
   5.314 +    char *fpr = pgp_fingerprint_canonicalize(fpr_raw);
   5.315 +    if (! fpr)
   5.316 +        ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
   5.317 +
   5.318 +    T("Deleting %s", fpr);
   5.319 +
   5.320 +    sqlite3_stmt *stmt = session->sq_sql.delete_keypair;
   5.321 +    sqlite3_bind_text(stmt, 1, fpr, -1, free);
   5.322 +
   5.323 +    int sqlite_result = Sqlite3_step(stmt);
   5.324 +    sqlite3_reset(stmt);
   5.325 +    if (sqlite_result != SQLITE_DONE)
   5.326 +        ERROR_OUT(NULL, PEP_CANNOT_DELETE_KEY,
   5.327 +                  "deletion failed: %s", sqlite3_errmsg(session->key_db));
   5.328  
   5.329      sqlite_result = sqlite3_changes(session->key_db);
   5.330      assert(sqlite_result >= 0 && sqlite_result < 2);
   5.331      if (sqlite_result < 1)
   5.332 -        return PEP_KEY_NOT_FOUND;
   5.333 -
   5.334 -    return PEP_STATUS_OK;
   5.335 +        ERROR_OUT(NULL, PEP_KEY_NOT_FOUND,
   5.336 +                  "attempt to delete non-existent key: %s", fpr_raw);
   5.337 +
   5.338 + out:
   5.339 +    return status;
   5.340  }
   5.341  
   5.342  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
   5.343 @@ -2029,8 +1969,7 @@
   5.344      }
   5.345  
   5.346   out:
   5.347 -    if (parser)
   5.348 -        pgp_tpk_parser_free(parser);
   5.349 +    pgp_tpk_parser_free(parser);
   5.350  
   5.351      T("-> %s", pEp_status_to_string(status));
   5.352      return status;
   5.353 @@ -2102,12 +2041,12 @@
   5.354      return status;
   5.355  }
   5.356  
   5.357 -char* _undot_address(const char* address) {
   5.358 +static char *_undot_address(const char* address) {
   5.359      if (!address)
   5.360          return NULL;
   5.361  
   5.362      int addr_len = strlen(address);
   5.363 -    const char* at = strstr(address, "@");
   5.364 +    const char* at = memchr(address, '@', addr_len);
   5.365  
   5.366      if (!at)
   5.367          at = address + addr_len;
   5.368 @@ -2256,10 +2195,8 @@
   5.369      }
   5.370  
   5.371   out:
   5.372 -    if (tpk)
   5.373 -        pgp_tpk_free(tpk);
   5.374 -    if (fpr)
   5.375 -        pgp_fingerprint_free(fpr);
   5.376 +    pgp_tpk_free(tpk);
   5.377 +    pgp_fingerprint_free(fpr);
   5.378  
   5.379      if (status == PEP_KEY_NOT_FOUND)
   5.380          status = PEP_STATUS_OK;
   5.381 @@ -2404,8 +2341,7 @@
   5.382      }
   5.383  
   5.384   out:
   5.385 -    if (tpk)
   5.386 -        pgp_tpk_free(tpk);
   5.387 +    pgp_tpk_free(tpk);
   5.388  
   5.389      T("(%s) -> %s", fpr, pEp_comm_type_to_string(*comm_type));
   5.390      return status;
   5.391 @@ -2465,14 +2401,10 @@
   5.392      ERROR_OUT(NULL, status, "Saving %s", fpr);
   5.393  
   5.394   out:
   5.395 -    if (signer)
   5.396 -        pgp_signer_free (signer);
   5.397 -    if (keypair)
   5.398 -        pgp_key_pair_free (keypair);
   5.399 -    if (iter)
   5.400 -        pgp_tpk_key_iter_free (iter);
   5.401 -    if (tpk)
   5.402 -        pgp_tpk_free(tpk);
   5.403 +    pgp_signer_free (signer);
   5.404 +    pgp_key_pair_free (keypair);
   5.405 +    pgp_tpk_key_iter_free (iter);
   5.406 +    pgp_tpk_free(tpk);
   5.407  
   5.408      T("(%s) -> %s", fpr, pEp_status_to_string(status));
   5.409      return status;
   5.410 @@ -2526,14 +2458,10 @@
   5.411      ERROR_OUT(NULL, status, "Saving %s", fpr);
   5.412  
   5.413   out:
   5.414 -    if (signer)
   5.415 -        pgp_signer_free (signer);
   5.416 -    if (keypair)
   5.417 -        pgp_key_pair_free (keypair);
   5.418 -    if (iter)
   5.419 -        pgp_tpk_key_iter_free (iter);
   5.420 -    if (tpk)
   5.421 -        pgp_tpk_free(tpk);
   5.422 +    pgp_signer_free (signer);
   5.423 +    pgp_key_pair_free (keypair);
   5.424 +    pgp_tpk_key_iter_free (iter);
   5.425 +    pgp_tpk_free(tpk);
   5.426  
   5.427      T("(%s) -> %s", fpr, pEp_status_to_string(status));
   5.428      return status;
   5.429 @@ -2590,8 +2518,7 @@
   5.430      *expired = !(can_encrypt && can_sign && can_certify);
   5.431  
   5.432   out:
   5.433 -    if (tpk)
   5.434 -        pgp_tpk_free(tpk);
   5.435 +    pgp_tpk_free(tpk);
   5.436      T("(%s) -> %s", fpr, pEp_status_to_string(status));
   5.437      return status;
   5.438  }
     6.1 --- a/sync/cond_act_sync.yml2	Wed May 29 19:33:45 2019 +0200
     6.2 +++ b/sync/cond_act_sync.yml2	Tue Jun 04 15:08:54 2019 +0200
     6.3 @@ -21,7 +21,7 @@
     6.4  condition weAreFirst
     6.5  ||
     6.6      TID_t *t1 = &session->sync_state.keysync.challenge;
     6.7 -    TID_t *t2 = &session->own_sync_state.challenge;
     6.8 +    TID_t *t2 = &session->sync_state.own.challenge;
     6.9  
    6.10      *result = _TID_greater(t1, t2);
    6.11  ||
    6.12 @@ -29,38 +29,30 @@
    6.13  condition partnerIsGrouped
    6.14  |> *result = session->sync_state.keysync.is_group;
    6.15  
    6.16 -condition challengeAccepted
    6.17 +condition sameChallenge
    6.18  ||
    6.19      TID_t *t1 = &session->sync_state.keysync.challenge;
    6.20 -    TID_t *t2 = &session->own_sync_state.challenge;
    6.21 +    TID_t *t2 = &session->sync_state.own.challenge;
    6.22  
    6.23      *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    6.24  ||
    6.25  
    6.26 -condition sameChallenge
    6.27 -||
    6.28 -    TID_t *t1 = &session->sync_state.keysync.challenge;
    6.29 -    TID_t *t2 = &session->own_sync_state.challenge;
    6.30 -
    6.31 -    *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    6.32 -||
    6.33 -
    6.34 -condition sameTransaction
    6.35 +condition sameNegotiation
    6.36  ||
    6.37      TID_t *t1 = &session->sync_state.keysync.negotiation;
    6.38 -    TID_t *t2 = &session->own_sync_state.negotiation;
    6.39 +    TID_t *t2 = &session->sync_state.comm_partner.negotiation;
    6.40  
    6.41      // test if TID is identical
    6.42      *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
    6.43  ||
    6.44  
    6.45 -condition sameTransactionAndPartner
    6.46 +condition sameNegotiationAndPartner
    6.47  ||
    6.48      TID_t *t1 = &session->sync_state.keysync.negotiation;
    6.49 -    TID_t *t2 = &session->own_sync_state.negotiation;
    6.50 +    TID_t *t2 = &session->sync_state.comm_partner.negotiation;
    6.51  
    6.52 -    const char *s1 = session->sync_state.common.signature_fpr;
    6.53 -    const char *s2 = session->own_sync_state.signature_fpr;
    6.54 +    const char *s1 = session->sync_state.comm_partner.sender_fpr;
    6.55 +    const char *s2 = session->sync_state.transport.sender_fpr;
    6.56  
    6.57      // test if TID is identical
    6.58      *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0
    6.59 @@ -70,8 +62,8 @@
    6.60  
    6.61  condition keyElectionWon
    6.62  ||
    6.63 -    pEp_identity *from = session->sync_state.common.from;
    6.64 -    char *signature_fpr = session->sync_state.common.signature_fpr;
    6.65 +    pEp_identity *from = session->sync_state.transport.from;
    6.66 +    char *sender_fpr = session->sync_state.comm_partner.sender_fpr;
    6.67  
    6.68      assert(from && from->address && from->address[0] && from->user_id &&
    6.69              from->user_id[0]);
    6.70 @@ -91,8 +83,8 @@
    6.71          return PEP_ILLEGAL_VALUE;
    6.72      }
    6.73  
    6.74 -    size_t len = MIN(strlen(signature_fpr), strlen(me->fpr));
    6.75 -    *result = strncasecmp(signature_fpr, me->fpr, len) > 0;
    6.76 +    size_t len = MIN(strlen(sender_fpr), strlen(me->fpr));
    6.77 +    *result = strncasecmp(sender_fpr, me->fpr, len) > 0;
    6.78      free_identity(me);
    6.79  ||
    6.80  
    6.81 @@ -101,10 +93,12 @@
    6.82  function "new_UUID" {
    6.83      param "dst";
    6.84      ||
    6.85 -        pEpUUID c;
    6.86 -        uuid_generate_random(c);
    6.87 +        {
    6.88 +            pEpUUID c;
    6.89 +            uuid_generate_random(c);
    6.90  
    6.91 -        OCTET_STRING_fromBuf(«$dst», (char *) c, 16);
    6.92 +            OCTET_STRING_fromBuf(«$dst», (char *) c, 16);
    6.93 +        }
    6.94      ||
    6.95  }
    6.96  
    6.97 @@ -141,75 +135,98 @@
    6.98      ||
    6.99  }
   6.100  
   6.101 -action newChallenge {
   6.102 +action newChallengeAndNegotiationBase {
   6.103      // random new challenge
   6.104 -    call "new_UUID" with "dst" > &session->own_sync_state.challenge
   6.105 -    // store a copy of this challenge
   6.106 +    call "new_UUID" with "dst" > &session->sync_state.own.challenge
   6.107      call "copy_UUID" {
   6.108 -        with "src" > &session->own_sync_state.challenge
   6.109 -        with "dst" > &session->sync_state.common.challenge
   6.110 +        with "src" > &session->sync_state.own.challenge
   6.111 +        with "dst" > &session->sync_state.keysync.challenge
   6.112 +    }
   6.113 +
   6.114 +    // this is the random data we are using as a base
   6.115 +    call "new_UUID" with "dst" > &session->sync_state.own.negotiation
   6.116 +||
   6.117 +    memset(session->sync_state.keysync.negotiation.buf, 0,
   6.118 +            session->sync_state.keysync.negotiation.size);
   6.119 +    memset(session->sync_state.comm_partner.negotiation.buf, 0,
   6.120 +            session->sync_state.comm_partner.negotiation.size);
   6.121 +||
   6.122 +}
   6.123 +
   6.124 +action useOwnChallenge call "copy_UUID" {
   6.125 +    with "src" > &session->sync_state.own.challenge
   6.126 +    with "dst" > &session->sync_state.keysync.challenge
   6.127 +}
   6.128 +
   6.129 +action openNegotiation {
   6.130 +||
   6.131 +    // sender key must be stable while transaction
   6.132 +
   6.133 +    // we take the actual signature of the last message and store it in our
   6.134 +    // state for the comm partner
   6.135 +    assert(session->sync_state.transport.sender_fpr);
   6.136 +
   6.137 +    free(session->sync_state.comm_partner.sender_fpr);
   6.138 +
   6.139 +    session->sync_state.comm_partner.sender_fpr
   6.140 +            = strdup(session->sync_state.transport.sender_fpr);
   6.141 +    assert(session->sync_state.comm_partner.sender_fpr);
   6.142 +    if (!session->sync_state.comm_partner.sender_fpr)
   6.143 +        return PEP_OUT_OF_MEMORY;
   6.144 +
   6.145 +    // we need a unique TID for the Negotiation with each single comm_partner
   6.146 +    // we identify the comm_partners by their Challenge
   6.147 +    // we derive the actual Negotiation TID by having random data and XORing it
   6.148 +    // with comm_partner's Challenge
   6.149 +
   6.150 +    // copy Negotiation base into buffer
   6.151 +
   6.152 +||
   6.153 +    call "copy_UUID" {
   6.154 +        with "src" > &session->sync_state.own.negotiation
   6.155 +        with "dst" > &session->sync_state.keysync.negotiation
   6.156 +    }
   6.157 +||
   6.158 +
   6.159 +    // we're XORing this with the challenge of the comm_partner, which is in
   6.160 +    // the buffer already
   6.161 +
   6.162 +||
   6.163 +    call "xor_UUID" {
   6.164 +        with "src" > &session->sync_state.keysync.challenge
   6.165 +        with "dst" > &session->sync_state.keysync.negotiation
   6.166 +    }
   6.167 +||
   6.168 +
   6.169 +    // this is the Negotiation's TID for this comm_partner
   6.170 +
   6.171 +||
   6.172 +    call "copy_UUID" {
   6.173 +        with "src" > &session->sync_state.keysync.negotiation
   6.174 +        with "dst" > &session->sync_state.comm_partner.negotiation
   6.175      }
   6.176  }
   6.177  
   6.178 -action replyChallenge call "copy_UUID" {
   6.179 -    with "src" > &session->sync_state.keysync.challenge
   6.180 -    with "dst" > &session->own_sync_state.challenge
   6.181 -}
   6.182 -
   6.183 -action useOwnChallenge call "copy_UUID" {
   6.184 -    with "src" > &session->sync_state.common.challenge
   6.185 -    with "dst" > &session->own_sync_state.challenge
   6.186 -}
   6.187 -
   6.188 -action newTransaction {
   6.189 +action storeNegotiation {
   6.190  ||
   6.191      // sender key must be stable while transaction
   6.192 -    assert(session->sync_state.common.signature_fpr);
   6.193 -    free(session->own_sync_state.signature_fpr);
   6.194 -    session->own_sync_state.signature_fpr
   6.195 -            = strdup(session->sync_state.common.signature_fpr);
   6.196 -    assert(session->own_sync_state.signature_fpr);
   6.197 -    if (!session->own_sync_state.signature_fpr)
   6.198 -        return PEP_OUT_OF_MEMORY;
   6.199  
   6.200 -||
   6.201 -    call "copy_UUID" {
   6.202 -        with "src" > &session->sync_state.keysync.challenge
   6.203 -        with "dst" > &session->sync_state.keysync.negotiation
   6.204 -    }
   6.205 -    call "xor_UUID" {
   6.206 -        with "src" > &session->own_sync_state.challenge
   6.207 -        with "dst" > &session->sync_state.keysync.negotiation
   6.208 -    }
   6.209 -    call "copy_UUID" {
   6.210 -        with "src" > &session->sync_state.keysync.negotiation
   6.211 -        with "dst" > &session->own_sync_state.negotiation
   6.212 -    }
   6.213 -}
   6.214 +    // we take the actual signature of the last message and store it in our
   6.215 +    // state for the comm partner
   6.216 +    assert(session->sync_state.transport.sender_fpr);
   6.217  
   6.218 -action closeTransaction
   6.219 -||
   6.220 -    memset(session->sync_state.keysync.negotiation.buf, 0,
   6.221 -            session->sync_state.keysync.negotiation.size);
   6.222 -    memset(session->own_sync_state.negotiation.buf, 0,
   6.223 -            session->own_sync_state.negotiation.size);
   6.224 -||
   6.225 +    free(session->sync_state.comm_partner.sender_fpr);
   6.226  
   6.227 -action storeTransaction {
   6.228 -||
   6.229 -    // sender key must be stable while transaction
   6.230 -    assert(session->sync_state.common.signature_fpr);
   6.231 -    free(session->own_sync_state.signature_fpr);
   6.232 -    session->own_sync_state.signature_fpr
   6.233 -            = strdup(session->sync_state.common.signature_fpr);
   6.234 -    assert(session->own_sync_state.signature_fpr);
   6.235 -    if (!session->own_sync_state.signature_fpr)
   6.236 +    session->sync_state.comm_partner.sender_fpr
   6.237 +            = strdup(session->sync_state.transport.sender_fpr);
   6.238 +    assert(session->sync_state.comm_partner.sender_fpr);
   6.239 +    if (!session->sync_state.comm_partner.sender_fpr)
   6.240          return PEP_OUT_OF_MEMORY;
   6.241  
   6.242  ||
   6.243      call "copy_UUID" {
   6.244          with "src" > &session->sync_state.keysync.negotiation
   6.245 -        with "dst" > &session->own_sync_state.negotiation
   6.246 +        with "dst" > &session->sync_state.comm_partner.negotiation
   6.247      }
   6.248  }
   6.249  
   6.250 @@ -222,34 +239,20 @@
   6.251       
   6.252      ||
   6.253      choose {
   6.254 -    when "$type = 'SYNC_NOTIFY_TIMEOUT' or $type = 'SYNC_NOTIFY_SOLE' or $type = 'SYNC_NOTIFY_IN_GROUP'"
   6.255 +    when "$type = 'SYNC_NOTIFY_INIT_ADD_OUR_DEVICE' or $type = 'SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE' or $type = 'SYNC_NOTIFY_INIT_FORM_GROUP'"
   6.256      ||
   6.257 -        pEp_identity *me = new_identity(NULL, NULL, NULL, NULL);
   6.258 -        pEp_identity *partner = new_identity(NULL, NULL, NULL, NULL);
   6.259 -        assert(me && partner);
   6.260 -        if (!(me && partner)) {
   6.261 -            free_identity(me);
   6.262 -            free_identity(partner);
   6.263 -            return PEP_OUT_OF_MEMORY;
   6.264 -        }
   6.265 -
   6.266 -        PEP_STATUS status = session->notifyHandshake(me, partner, «$type»);
   6.267 -        if (status)
   6.268 -            return status;
   6.269 -    ||
   6.270 -    otherwise
   6.271 -    ||
   6.272 -        assert(session->sync_state.common.from);
   6.273 -        if (!session->sync_state.common.from)
   6.274 +        assert(session->sync_state.transport.from);
   6.275 +        if (!session->sync_state.transport.from)
   6.276              return PEP_ILLEGAL_VALUE;
   6.277  
   6.278 -        pEp_identity *from = session->sync_state.common.from;
   6.279 +        pEp_identity *from = session->sync_state.transport.from;
   6.280          pEp_identity *me = NULL;
   6.281          PEP_STATUS status = get_identity(session, from->address, from->user_id, &me);
   6.282          assert(status == PEP_STATUS_OK);
   6.283          if (status)
   6.284              return status;
   6.285 -
   6.286 +        assert(strcmp(me->fpr, session->sync_state.comm_partner.sender_fpr) != 0);
   6.287 +        
   6.288          assert(me->fpr && me->fpr[0]);
   6.289          if (!(me->fpr && me->fpr[0])) {
   6.290              free_identity(me);
   6.291 @@ -262,10 +265,11 @@
   6.292              return PEP_OUT_OF_MEMORY;
   6.293          }
   6.294  
   6.295 -        assert(session->sync_state.common.signature_fpr);
   6.296 -        if (session->sync_state.common.signature_fpr) {
   6.297 +        assert(session->sync_state.comm_partner.sender_fpr);
   6.298 +        if (session->sync_state.comm_partner.sender_fpr) {
   6.299              free(partner->fpr);
   6.300 -            partner->fpr = strdup(session->sync_state.common.signature_fpr);
   6.301 +            partner->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
   6.302 +            assert(partner->fpr);
   6.303              if (!partner->fpr) {
   6.304                  free_identity(me);
   6.305                  free_identity(partner);
   6.306 @@ -282,10 +286,26 @@
   6.307              return PEP_OUT_OF_MEMORY;
   6.308          }
   6.309  
   6.310 +        assert(strcmp(me->fpr, partner->fpr) != 0);
   6.311          status = session->notifyHandshake(me, partner, «$type»);
   6.312          if (status)
   6.313              return status;
   6.314      ||
   6.315 +    otherwise
   6.316 +    ||
   6.317 +        pEp_identity *me = new_identity(NULL, NULL, NULL, NULL);
   6.318 +        pEp_identity *partner = new_identity(NULL, NULL, NULL, NULL);
   6.319 +        assert(me && partner);
   6.320 +        if (!(me && partner)) {
   6.321 +            free_identity(me);
   6.322 +            free_identity(partner);
   6.323 +            return PEP_OUT_OF_MEMORY;
   6.324 +        }
   6.325 +
   6.326 +        PEP_STATUS status = session->notifyHandshake(me, partner, «$type»);
   6.327 +        if (status)
   6.328 +            return status;
   6.329 +    ||
   6.330      }
   6.331  }
   6.332  
   6.333 @@ -323,9 +343,9 @@
   6.334      if (status)
   6.335          return status;
   6.336  
   6.337 -    if (session->own_sync_state.own_keys)
   6.338 -        free_stringlist(session->own_sync_state.own_keys);
   6.339 -    session->own_sync_state.own_keys = own_keys;
   6.340 +    if (session->sync_state.own.keys)
   6.341 +        free_stringlist(session->sync_state.own.keys);
   6.342 +    session->sync_state.own.keys = own_keys;
   6.343  
   6.344      identity_list *il;
   6.345      status = _own_identities_retrieve(session, &il, PEP_idf_not_for_sync);
   6.346 @@ -338,19 +358,61 @@
   6.347  
   6.348  action saveGroupKeys
   6.349  ||
   6.350 +    char *user_id = NULL;
   6.351 +    PEP_STATUS status = get_default_own_userid(session, &user_id);
   6.352 +    if (status)
   6.353 +        return status;
   6.354 +
   6.355      identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   6.356 -    if (!il)
   6.357 +    if (!il) {
   6.358 +        free(user_id);
   6.359          return PEP_OUT_OF_MEMORY;
   6.360 +    }
   6.361      
   6.362 +    identity_list *oil = session->sync_state.own.identities;
   6.363 +
   6.364      // BUG: this should be a transaction and been rolled back completely on error
   6.365      for (identity_list *_il = il; _il && _il->ident; _il = _il->next) {
   6.366 -        PEP_STATUS status = set_identity(session, _il->ident);
   6.367 +        pEp_identity *ident = _il->ident;
   6.368 +        bool is_own_already = false;
   6.369 +
   6.370 +        status = is_own_address(session, ident->address, &is_own_already);
   6.371          if (status) {
   6.372              free_identity_list(il);
   6.373 +            free(user_id);
   6.374 +            return status;
   6.375 +        }
   6.376 +
   6.377 +        free(ident->user_id);
   6.378 +        ident->user_id = strdup(user_id);
   6.379 +        assert(ident->user_id);
   6.380 +        if (!ident->user_id) {
   6.381 +            free_identity_list(il);
   6.382 +            free(user_id);
   6.383 +            return PEP_OUT_OF_MEMORY;
   6.384 +        }
   6.385 +
   6.386 +        if (is_own_already) {
   6.387 +            ident->comm_type = PEP_ct_pEp;
   6.388 +            status = set_trust(session, ident);
   6.389 +        }
   6.390 +        else {
   6.391 +            oil = identity_list_add(oil, ident);
   6.392 +            if (!oil) {
   6.393 +                free_identity_list(il);
   6.394 +                free(user_id);
   6.395 +                return PEP_OUT_OF_MEMORY;
   6.396 +            }
   6.397 +            status = myself(session, ident);
   6.398 +        }
   6.399 +        if (status) {
   6.400 +            free_identity_list(il);
   6.401 +            free(user_id);
   6.402              return status;
   6.403          }
   6.404      }
   6.405  
   6.406 +    free(user_id);
   6.407      free_identity_list(il);
   6.408  ||
   6.409  
   6.410 @@ -358,8 +420,8 @@
   6.411  ||
   6.412      PEP_STATUS status = PEP_STATUS_OK;
   6.413  
   6.414 -    // set flag for current keys
   6.415 -    for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   6.416 +    // set flag for all keys; don't change anything else
   6.417 +    for (identity_list *il = session->sync_state.own.identities; il && il->ident ; il = il->next) {
   6.418          if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   6.419              status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   6.420              if (status)
   6.421 @@ -371,56 +433,61 @@
   6.422  action receivedKeysAreGroupKeys
   6.423  ||
   6.424      PEP_STATUS status = PEP_STATUS_OK;
   6.425 -
   6.426 -    // set flag for current keys
   6.427 -    for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   6.428 +    // set flag for all keys
   6.429 +    for (identity_list *il = session->sync_state.own.identities; il && il->ident ; il = il->next) {
   6.430          if (!(il->ident->flags && PEP_idf_not_for_sync)) {
   6.431 +            
   6.432              status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   6.433              if (status)
   6.434                  return status;
   6.435          }
   6.436      }
   6.437  
   6.438 +    char *user_id = NULL;
   6.439 +    status = get_default_own_userid(session, &user_id);
   6.440 +    if (status)
   6.441 +        return status;
   6.442 +
   6.443      identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
   6.444      if (!il)
   6.445          return PEP_OUT_OF_MEMORY;
   6.446  
   6.447 -    for (il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
   6.448 +    for (identity_list *_il = il; _il && _il->ident ; _il = _il->next) {
   6.449          // replace partner's user_id with own user_id
   6.450 -        free(il->ident->user_id);
   6.451 -        il->ident->user_id = strdup(session->sync_state.common.from->user_id);
   6.452 -        if (!il->ident->user_id) {
   6.453 +        free(_il->ident->user_id);
   6.454 +        _il->ident->user_id = strdup(user_id);
   6.455 +        assert(_il->ident->user_id);
   6.456 +        if (!_il->ident->user_id) {
   6.457              free_identity_list(il);
   6.458 +            free(user_id);
   6.459              return PEP_OUT_OF_MEMORY;
   6.460          }
   6.461 -
   6.462 -        status = myself(session, il->ident);
   6.463 +    
   6.464 +        const char *own_key = _il->ident->fpr;
   6.465 +        _il->ident->fpr = NULL;
   6.466 +        status = set_own_key(session, _il->ident, own_key);
   6.467          if (status) {
   6.468              free_identity_list(il);
   6.469 -            return status;
   6.470 -        }
   6.471 -
   6.472 -        status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
   6.473 -        if (status) {
   6.474 -            free_identity_list(il);
   6.475 +            free(user_id);
   6.476              return status;
   6.477          }
   6.478      }
   6.479  
   6.480      free_identity_list(il);
   6.481 +    free(user_id);
   6.482  ||
   6.483  
   6.484  action trustThisKey
   6.485  ||
   6.486 -    assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
   6.487 -    if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
   6.488 +    assert(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr);
   6.489 +    if (!(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr))
   6.490          return PEP_ILLEGAL_VALUE;
   6.491  
   6.492 -    pEp_identity *ident = identity_dup(session->sync_state.common.from);
   6.493 +    pEp_identity *ident = identity_dup(session->sync_state.transport.from);
   6.494      if (!ident)
   6.495          return PEP_OUT_OF_MEMORY;
   6.496      free(ident->fpr);
   6.497 -    ident->fpr = strdup(session->sync_state.common.signature_fpr);
   6.498 +    ident->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
   6.499      assert(ident->fpr);
   6.500      if (!ident->fpr) {
   6.501          free_identity(ident);
   6.502 @@ -439,13 +506,13 @@
   6.503  
   6.504  action untrustThisKey
   6.505  ||
   6.506 -    assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
   6.507 -    if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
   6.508 +    assert(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr);
   6.509 +    if (!(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr))
   6.510          return PEP_ILLEGAL_VALUE;
   6.511  
   6.512 -    pEp_identity *ident = session->sync_state.common.from;
   6.513 +    pEp_identity *ident = session->sync_state.transport.from;
   6.514      free(ident->fpr);
   6.515 -    ident->fpr = strdup(session->sync_state.common.signature_fpr);
   6.516 +    ident->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
   6.517      assert(ident->fpr);
   6.518      if (!ident->fpr)
   6.519          return PEP_OUT_OF_MEMORY;
     7.1 --- a/sync/gen_message_func.ysl2	Wed May 29 19:33:45 2019 +0200
     7.2 +++ b/sync/gen_message_func.ysl2	Tue Jun 04 15:08:54 2019 +0200
     7.3 @@ -39,32 +39,36 @@
     7.4  // state
     7.5  
     7.6  struct «@name»_state_s {
     7.7 -    // common buffer for all types of «@name» messages
     7.8 +    // own state
     7.9  
    7.10 -    struct common_state_s {
    7.11 -        // intermediate store own challenge
    7.12 -        TID_t challenge;
    7.13 +    struct own_«@name»_state_s {
    7.14 +        stringlist_t *keys;
    7.15 +        identity_list *identities;
    7.16  
    7.17 -        // transport data
    7.18 +        // TIDs we're using ourselves
    7.19 +        `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»;
    7.20 +    } own;
    7.21 +
    7.22 +    // state we learned about our communication partner
    7.23 +
    7.24 +    struct comm_partner_state_s {
    7.25 +        // transport data we expect
    7.26 +        char *sender_fpr;
    7.27 +
    7.28 +        // TIDs our comm partner wants to have
    7.29 +        `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»;
    7.30 +    } comm_partner;
    7.31 +
    7.32 +    // input buffer for actual transport data coming in
    7.33 +
    7.34 +    struct transport_data_s {
    7.35 +        // transport data we got
    7.36          pEp_identity *from;
    7.37 -        char *signature_fpr;
    7.38 -    } common;
    7.39 +        char *sender_fpr;
    7.40 +    } transport;
    7.41      `` apply "fsm", mode=state
    7.42  };
    7.43  
    7.44 -// own state
    7.45 -
    7.46 -struct own_«@name»_state_s {
    7.47 -    stringlist_t *own_keys;
    7.48 -    identity_list *own_identities;
    7.49 -
    7.50 -    `` if "func:distinctName(fsm/message/field[@type='TID'])" |> // active TIDs
    7.51 -    `` for "func:distinctName(fsm/message/field[@type='TID'])" |> «func:ctype()» «@name»;
    7.52 -
    7.53 -    // transport data
    7.54 -    char *signature_fpr;
    7.55 -};
    7.56 -
    7.57  void free_«@name»_state(PEP_SESSION session);
    7.58  
    7.59  // functions for protocol «@name»
    7.60 @@ -86,7 +90,7 @@
    7.61  template "fsm", mode=state
    7.62  ||
    7.63  
    7.64 -// buffer for «@name» messages
    7.65 +// input/output buffer for «@name» messages
    7.66  
    7.67  struct _«@name»_state_s {
    7.68      int state;
    7.69 @@ -113,21 +117,46 @@
    7.70      if (!session)
    7.71          return;
    7.72  
    7.73 -    free_identity(session->«yml:lcase(@name)»_state.common.from);
    7.74 -    free(session->«yml:lcase(@name)»_state.common.signature_fpr);
    7.75 -    free_stringlist(session->own_«yml:lcase(@name)»_state.own_keys);
    7.76 -    free_identity_list(session->own_«yml:lcase(@name)»_state.own_identities);
    7.77 -    session->own_«yml:lcase(@name)»_state.own_keys = NULL;
    7.78 -    session->own_«yml:lcase(@name)»_state.own_identities = NULL;
    7.79 +    // own state
    7.80 +
    7.81 +    free_stringlist(session->«yml:lcase(@name)»_state.own.keys);
    7.82 +    session->«yml:lcase(@name)»_state.own.keys = NULL;
    7.83 +    free_identity_list(session->«yml:lcase(@name)»_state.own.identities);
    7.84 +    session->«yml:lcase(@name)»_state.own.identities = NULL;
    7.85 +
    7.86 +    // TIDs we're using ourselves
    7.87 +||
    7.88 +    for "func:distinctName(fsm/message/field[@type='TID'])"
    7.89 +        |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.own.«@name»);
    7.90 +||
    7.91 +
    7.92 +    // state we learned about our communication partner
    7.93 +
    7.94 +    free(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
    7.95 +    session->«yml:lcase(@name)»_state.comm_partner.sender_fpr = NULL;
    7.96 +
    7.97 +    // TIDs our comm partner wants to have
    7.98 +||
    7.99 +    for "func:distinctName(fsm/message/field[@type='TID'])"
   7.100 +        |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.comm_partner.«@name»);
   7.101 +||
   7.102 +
   7.103 +    // buffer for transport data
   7.104 +
   7.105 +    free_identity(session->«yml:lcase(@name)»_state.transport.from);
   7.106 +    session->«yml:lcase(@name)»_state.transport.from = NULL;
   7.107 +    free(session->«yml:lcase(@name)»_state.transport.sender_fpr);
   7.108 +    session->«yml:lcase(@name)»_state.transport.sender_fpr = NULL;
   7.109 +
   7.110 +    // message buffers
   7.111  
   7.112  ||
   7.113 -for "fsm"
   7.114 -    for "func:distinctName(message/field[not(func:basicType())])"
   7.115 -        |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
   7.116 -for "func:distinctName(fsm/message/field[@type='TID'])"
   7.117 -    |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->own_«yml:lcase(../../../@name)»_state.«@name»);
   7.118 +    for "fsm" {
   7.119 +        for "func:distinctName(message/field[not(substring(@type,1,1)=yml:lcase(substring(@type,1,1)))])"
   7.120 +            |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
   7.121 +        |
   7.122 +    }
   7.123  ||
   7.124 -
   7.125      memset(&session->«yml:lcase(@name)»_state, 0, sizeof(session->«yml:lcase(@name)»_state));
   7.126  }
   7.127  
   7.128 @@ -259,12 +288,7 @@
   7.129  
   7.130  template "field", mode=update_message {
   7.131      const "message_name", "yml:mixedCase(../@name)";
   7.132 -    const "state" choose {
   7.133 -        when "@type='TID'"
   7.134 -            > own_«yml:lcase(ancestor::protocol/@name)»_state
   7.135 -        otherwise
   7.136 -            > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
   7.137 -    }
   7.138 +    const "state" > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
   7.139  
   7.140      choose {
   7.141          when "func:basicType()" // copyable
     8.1 --- a/sync/gen_statemachine.ysl2	Wed May 29 19:33:45 2019 +0200
     8.2 +++ b/sync/gen_statemachine.ysl2	Tue Jun 04 15:08:54 2019 +0200
     8.3 @@ -38,7 +38,7 @@
     8.4  
     8.5              // transport data
     8.6              pEp_identity *from;
     8.7 -            char *signature_fpr;
     8.8 +            char *sender_fpr;
     8.9  
    8.10              identity_list *own_identities;
    8.11          } «@name»_event_t;
    8.12 @@ -119,7 +119,7 @@
    8.13                  free_identity_list(ev->own_identities);
    8.14                  free_«@name»_message(ev->msg);
    8.15                  free_identity(ev->from);
    8.16 -                free(ev->signature_fpr);
    8.17 +                free(ev->sender_fpr);
    8.18                  free(ev);
    8.19              }
    8.20          }
    8.21 @@ -211,7 +211,7 @@
    8.22                      const char *data,
    8.23                      size_t size,
    8.24                      const pEp_identity *from,
    8.25 -                    const char *signature_fpr
    8.26 +                    const char *sender_fpr
    8.27                  );
    8.28  
    8.29              #ifdef __cplusplus
    8.30 @@ -328,7 +328,7 @@
    8.31                      const char *data,
    8.32                      size_t size,
    8.33                      const pEp_identity *from,
    8.34 -                    const char *signature_fpr
    8.35 +                    const char *sender_fpr
    8.36                  )
    8.37              {
    8.38                  assert(session && data && size);
    8.39 @@ -373,10 +373,10 @@
    8.40                      }
    8.41                  }
    8.42  
    8.43 -                if (signature_fpr) {
    8.44 -                    ev->signature_fpr = strdup(signature_fpr);
    8.45 -                    assert(ev->signature_fpr);
    8.46 -                    if (!ev->signature_fpr) {
    8.47 +                if (sender_fpr) {
    8.48 +                    ev->sender_fpr = strdup(sender_fpr);
    8.49 +                    assert(ev->sender_fpr);
    8.50 +                    if (!ev->sender_fpr) {
    8.51                          status = PEP_OUT_OF_MEMORY;
    8.52                          goto the_end;
    8.53                      }
    8.54 @@ -447,8 +447,8 @@
    8.55  
    8.56                      // these go anycast; previously used address is sticky (unicast)
    8.57                      `` for "fsm/message[@type='anycast']" |>> case «../@name»_PR_«yml:mixedCase(@name)»:
    8.58 -                        if (!session->«yml:lcase(@name)»_state.common.from `> |`|
    8.59 -                            (session->«yml:lcase(@name)»_state.common.from->flags &
    8.60 +                        if (!session->«yml:lcase(@name)»_state.transport.from `> |`|
    8.61 +                            (session->«yml:lcase(@name)»_state.transport.from->flags &
    8.62                              PEP_idf_not_for_«yml:lcase(@name)»)) {
    8.63  
    8.64                              // no address available yet, try to find one
    8.65 @@ -468,7 +468,7 @@
    8.66                              }
    8.67                          }
    8.68                          else {
    8.69 -                            pEp_identity *channel = identity_dup(session->«yml:lcase(@name)»_state.common.from);
    8.70 +                            pEp_identity *channel = identity_dup(session->«yml:lcase(@name)»_state.transport.from);
    8.71                              if (!channel) {
    8.72                                  status = PEP_OUT_OF_MEMORY;
    8.73                                  goto the_end;
    8.74 @@ -521,13 +521,13 @@
    8.75                      `` for "fsm/message[@security='untrusted']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
    8.76                              // add fpr of key of comm partner
    8.77  
    8.78 -                            assert(session->«yml:lcase(@name)»_state.common.signature_fpr);
    8.79 -                            if (!session->«yml:lcase(@name)»_state.common.signature_fpr) {
    8.80 +                            assert(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
    8.81 +                            if (!session->«yml:lcase(@name)»_state.comm_partner.sender_fpr) {
    8.82                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
    8.83                                  goto the_end;
    8.84                              }
    8.85  
    8.86 -                            extra = new_stringlist(session->«yml:lcase(@name)»_state.common.signature_fpr);
    8.87 +                            extra = new_stringlist(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
    8.88                              if (!extra) {
    8.89                                  status = PEP_OUT_OF_MEMORY;
    8.90                                  goto the_end;
    8.91 @@ -556,11 +556,11 @@
    8.92                              break;
    8.93  
    8.94                      `` for "fsm/message[@security='attach_own_keys']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
    8.95 -                            // check if this is the key of a former negotiation
    8.96 +                            // check if we had a former negotiation
    8.97  
    8.98                              transaction = false;
    8.99 -                            for (int i=0; i < session->own_«yml:lcase(@name)»_state.negotiation.size; i++) {
   8.100 -                                if (session->own_«yml:lcase(@name)»_state.negotiation.buf[i]) {
   8.101 +                            for (int i=0; i < session->«yml:lcase(@name)»_state.own.negotiation.size; i++) {
   8.102 +                                if (session->«yml:lcase(@name)»_state.own.negotiation.buf[i]) {
   8.103                                      transaction = true;
   8.104                                      break;
   8.105                                  }
   8.106 @@ -573,12 +573,12 @@
   8.107                              // secret keys
   8.108  
   8.109                              if (transaction) {
   8.110 -                                assert(session->own_«yml:lcase(@name)»_state.signature_fpr &&
   8.111 -                                    session->«yml:lcase(@name)»_state.common.from &&
   8.112 -                                    session->«yml:lcase(@name)»_state.common.from->user_id);
   8.113 -                                if (!(session->own_«yml:lcase(@name)»_state.signature_fpr &&
   8.114 -                                        session->«yml:lcase(@name)»_state.common.from &&
   8.115 -                                        session->«yml:lcase(@name)»_state.common.from->user_id))
   8.116 +                                assert(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr &&
   8.117 +                                    session->«yml:lcase(@name)»_state.transport.from &&
   8.118 +                                    session->«yml:lcase(@name)»_state.transport.from->user_id);
   8.119 +                                if (!(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr &&
   8.120 +                                        session->«yml:lcase(@name)»_state.transport.from &&
   8.121 +                                        session->«yml:lcase(@name)»_state.transport.from->user_id))
   8.122                                  {
   8.123                                      status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
   8.124                                      goto the_end;
   8.125 @@ -587,8 +587,8 @@
   8.126                                  // test if this is a green channel
   8.127  
   8.128                                  pEp_identity *ident = new_identity(NULL,
   8.129 -                                        session->own_«yml:lcase(@name)»_state.signature_fpr,
   8.130 -                                        session->«yml:lcase(@name)»_state.common.from->user_id,
   8.131 +                                        session->«yml:lcase(@name)»_state.comm_partner.sender_fpr,
   8.132 +                                        session->«yml:lcase(@name)»_state.transport.from->user_id,
   8.133                                          NULL
   8.134                                      );
   8.135                                  if (!ident) {
   8.136 @@ -612,7 +612,7 @@
   8.137  
   8.138                                  bool is_own_key = false;
   8.139                                  status = own_key_is_listed(session,
   8.140 -                                        session->own_«yml:lcase(@name)»_state.signature_fpr,
   8.141 +                                        session->«yml:lcase(@name)»_state.comm_partner.sender_fpr,
   8.142                                          &is_own_key);
   8.143                                  assert(!status);
   8.144                                  if (status)
   8.145 @@ -625,7 +625,7 @@
   8.146  
   8.147                                  // if so add key of comm partner to extra keys
   8.148  
   8.149 -                                extra = new_stringlist(session->own_«yml:lcase(@name)»_state.signature_fpr);
   8.150 +                                extra = new_stringlist(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
   8.151                                  if (!extra) {
   8.152                                      status = PEP_OUT_OF_MEMORY;
   8.153                                      goto the_end;
   8.154 @@ -660,7 +660,7 @@
   8.155                                                 // if we include this in the size, libetpan will null terminate and 
   8.156                                                 // go bananas. We can't have a NUL in the mime text.
   8.157  
   8.158 -                            for (stringlist_t *sl = session->own_«yml:lcase(@name)»_state.own_keys;
   8.159 +                            for (stringlist_t *sl = session->«yml:lcase(@name)»_state.own.keys;
   8.160                                      sl && sl->value ; sl = sl->next)
   8.161                              {
   8.162                                  char *_key_data = NULL;
   8.163 @@ -808,22 +808,22 @@
   8.164                  // update transport data
   8.165  
   8.166                  if (ev->from) {
   8.167 -                    free_identity(session->«yml:lcase(@name)»_state.common.from);
   8.168 -                    session->«yml:lcase(@name)»_state.common.from = ev->from;
   8.169 +                    free_identity(session->«yml:lcase(@name)»_state.transport.from);
   8.170 +                    session->«yml:lcase(@name)»_state.transport.from = ev->from;
   8.171                      ev->from = NULL;
   8.172                  }
   8.173  
   8.174 -                if (ev->signature_fpr) {
   8.175 -                    free(session->«yml:lcase(@name)»_state.common.signature_fpr);
   8.176 -                    session->«yml:lcase(@name)»_state.common.signature_fpr = ev->signature_fpr;
   8.177 -                    ev->signature_fpr = NULL;
   8.178 +                if (ev->sender_fpr) {
   8.179 +                    free(session->«yml:lcase(@name)»_state.transport.sender_fpr);
   8.180 +                    session->«yml:lcase(@name)»_state.transport.sender_fpr = ev->sender_fpr;
   8.181 +                    ev->sender_fpr = NULL;
   8.182                  }
   8.183  
   8.184                  // update own identities
   8.185  
   8.186                  if (ev->own_identities && ev->own_identities->ident) {
   8.187 -                    free_identity_list(session->own_«yml:lcase(@name)»_state.own_identities);
   8.188 -                    session->own_«yml:lcase(@name)»_state.own_identities = ev->own_identities;
   8.189 +                    free_identity_list(session->«yml:lcase(@name)»_state.own.identities);
   8.190 +                    session->«yml:lcase(@name)»_state.own.identities = ev->own_identities;
   8.191                      ev->own_identities = NULL;
   8.192                  }
   8.193  
   8.194 @@ -901,7 +901,7 @@
   8.195          if "position()=1" |>> // these messages require a detached signature
   8.196          ||
   8.197                  case «../@name»_PR_«yml:mixedCase(@name)»:
   8.198 -                    if (!signature_fpr) {
   8.199 +                    if (!sender_fpr) {
   8.200                          status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
   8.201                          goto the_end;
   8.202                      }
   8.203 @@ -931,7 +931,7 @@
   8.204                          status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
   8.205                          goto the_end;
   8.206                      }
   8.207 -                    status = own_key_is_listed(session, signature_fpr, &is_own_key);
   8.208 +                    status = own_key_is_listed(session, sender_fpr, &is_own_key);
   8.209                      if (status)
   8.210                          goto the_end;
   8.211                      if (!is_own_key) {
     9.1 --- a/sync/sync.fsm	Wed May 29 19:33:45 2019 +0200
     9.2 +++ b/sync/sync.fsm	Tue Jun 04 15:08:54 2019 +0200
     9.3 @@ -23,8 +23,7 @@
     9.4  
     9.5          state Sole timeout=off {
     9.6              on Init {
     9.7 -                do closeTransaction;
     9.8 -                do newChallenge;
     9.9 +                do newChallengeAndNegotiationBase;
    9.10                  do showBeingSole;
    9.11                  send Beacon;
    9.12              }
    9.13 @@ -43,13 +42,13 @@
    9.14                  }
    9.15                  else {
    9.16                      if weAreFirst {
    9.17 +                        do useOwnChallenge;
    9.18                          send Beacon;
    9.19                      }
    9.20                      else /* we are second */ {
    9.21 -                        do newTransaction;
    9.22 +                        do openNegotiation;
    9.23                          do tellWeAreNotGrouped;
    9.24                          // second is sending NegotiationRequest
    9.25 -                        do replyChallenge; // partner's challenge
    9.26                          send NegotiationRequest;
    9.27                          do useOwnChallenge;
    9.28                      }
    9.29 @@ -57,24 +56,25 @@
    9.30              }
    9.31  
    9.32              on NegotiationRequest {
    9.33 -                if challengeAccepted {
    9.34 -                    if sameTransaction {
    9.35 +                if sameChallenge { // challenge accepted
    9.36 +                    if sameNegotiation {
    9.37                          // this is our own NegotiationRequest; ignore
    9.38                      }
    9.39                      else {
    9.40 -                        // first is receiving NegotiationRequest
    9.41 -                        do storeTransaction;
    9.42 +                        do storeNegotiation;
    9.43                          // first is sending NegotiationOpen
    9.44                          send NegotiationOpen;
    9.45                          if partnerIsGrouped
    9.46                              go HandshakingWithGroup;
    9.47 -                        go HandshakingNewFirst;
    9.48 +                        else
    9.49 +                            go HandshakingNewFirst;
    9.50                      }
    9.51                  }
    9.52              }
    9.53  
    9.54 -            on NegotiationOpen if sameTransactionAndPartner {
    9.55 +            on NegotiationOpen if sameNegotiationAndPartner {
    9.56                  // second is receiving NegotiationOpen
    9.57 +                do storeNegotiation;
    9.58                  go HandshakingNewSecond;
    9.59              }
    9.60          }
    9.61 @@ -90,7 +90,7 @@
    9.62                  go Sole;
    9.63              }
    9.64  
    9.65 -            on Rollback if sameTransactionAndPartner
    9.66 +            on Rollback if sameNegotiationAndPartner
    9.67                  go Sole;
    9.68  
    9.69              // Reject is CommitReject
    9.70 @@ -100,7 +100,7 @@
    9.71                  go End;
    9.72              }
    9.73  
    9.74 -            on CommitReject if sameTransactionAndPartner {
    9.75 +            on CommitReject if sameNegotiationAndPartner {
    9.76                  do disable;
    9.77                  go End;
    9.78              }
    9.79 @@ -113,7 +113,7 @@
    9.80              }
    9.81  
    9.82              // got a CommitAccept from second
    9.83 -            on CommitAcceptSecond if sameTransactionAndPartner
    9.84 +            on CommitAcceptSecond if sameNegotiationAndPartner
    9.85                  go HandshakingNewPhase2First;
    9.86          }
    9.87  
    9.88 @@ -128,7 +128,7 @@
    9.89                  go Sole;
    9.90              }
    9.91  
    9.92 -            on Rollback if sameTransactionAndPartner
    9.93 +            on Rollback if sameNegotiationAndPartner
    9.94                  go Sole;
    9.95  
    9.96              // Reject is CommitReject
    9.97 @@ -138,7 +138,7 @@
    9.98                  go End;
    9.99              }
   9.100  
   9.101 -            on CommitReject if sameTransactionAndPartner {
   9.102 +            on CommitReject if sameNegotiationAndPartner {
   9.103                  do disable;
   9.104                  go End;
   9.105              }
   9.106 @@ -151,40 +151,40 @@
   9.107              }
   9.108  
   9.109              // got a CommitAccept from first
   9.110 -            on CommitAcceptFirst if sameTransactionAndPartner
   9.111 +            on CommitAcceptFirst if sameNegotiationAndPartner
   9.112                  go HandshakingNewPhase2Second;
   9.113          }
   9.114  
   9.115          state HandshakingNewPhase1First {
   9.116 -            on Rollback if sameTransactionAndPartner {
   9.117 +            on Rollback if sameNegotiationAndPartner {
   9.118                  do untrustThisKey;
   9.119                  go Sole;
   9.120              }
   9.121              
   9.122 -            on CommitReject if sameTransactionAndPartner {
   9.123 +            on CommitReject if sameNegotiationAndPartner {
   9.124                  do untrustThisKey;
   9.125                  do disable;
   9.126                  go End;
   9.127              }
   9.128  
   9.129 -            on CommitAcceptSecond if sameTransactionAndPartner {
   9.130 +            on CommitAcceptSecond if sameNegotiationAndPartner {
   9.131                  go NewGroupFirst;
   9.132              }
   9.133          }
   9.134  
   9.135          state HandshakingNewPhase1Second {
   9.136 -            on Rollback if sameTransactionAndPartner {
   9.137 +            on Rollback if sameNegotiationAndPartner {
   9.138                  do untrustThisKey;
   9.139                  go Sole;
   9.140              }
   9.141              
   9.142 -            on CommitReject if sameTransactionAndPartner {
   9.143 +            on CommitReject if sameNegotiationAndPartner {
   9.144                  do untrustThisKey;
   9.145                  do disable;
   9.146                  go End;
   9.147              }
   9.148  
   9.149 -            on CommitAcceptFirst if sameTransactionAndPartner {
   9.150 +            on CommitAcceptFirst if sameNegotiationAndPartner {
   9.151                  go NewGroupSecond;
   9.152              }
   9.153          }
   9.154 @@ -235,11 +235,7 @@
   9.155  
   9.156              on OwnKeysSecond {
   9.157                  do saveGroupKeys;
   9.158 -
   9.159 -                if keyElectionWon
   9.160 -                    do ownKeysAreGroupKeys;
   9.161 -                else
   9.162 -                    do receivedKeysAreGroupKeys;
   9.163 +                do receivedKeysAreGroupKeys;
   9.164                  do showGroupCreated;
   9.165                  go Grouped;
   9.166              }
   9.167 @@ -254,10 +250,7 @@
   9.168              on OwnKeysFirst {
   9.169                  do saveGroupKeys;
   9.170  
   9.171 -                if keyElectionWon
   9.172 -                    do ownKeysAreGroupKeys;
   9.173 -                else
   9.174 -                    do receivedKeysAreGroupKeys;
   9.175 +                do ownKeysAreGroupKeys;
   9.176                  do showGroupCreated;
   9.177                  go Grouped;
   9.178              }
   9.179 @@ -265,8 +258,7 @@
   9.180  
   9.181          state Grouped timeout=off {
   9.182              on Init {
   9.183 -                do closeTransaction;
   9.184 -                do newChallenge;
   9.185 +                do newChallengeAndNegotiationBase;
   9.186                  do showBeingInGroup;
   9.187              }
   9.188  
   9.189 @@ -279,15 +271,16 @@
   9.190              }
   9.191  
   9.192              on Beacon {
   9.193 -                do newTransaction;
   9.194 +                do openNegotiation;
   9.195                  do tellWeAreGrouped;
   9.196 -                do replyChallenge; // partner's challenge
   9.197                  send NegotiationRequest;
   9.198                  do useOwnChallenge;
   9.199              }
   9.200  
   9.201 -            on NegotiationOpen if sameTransactionAndPartner
   9.202 +            on NegotiationOpen if sameNegotiationAndPartner {
   9.203 +                do storeNegotiation;
   9.204                  go HandshakingGrouped;
   9.205 +            }
   9.206  
   9.207              on GroupTrustThisKey {
   9.208                  do trustThisKey;
   9.209 @@ -305,7 +298,7 @@
   9.210                  go Sole;
   9.211              }
   9.212  
   9.213 -            on Rollback if sameTransactionAndPartner
   9.214 +            on Rollback if sameNegotiationAndPartner
   9.215                  go Sole;
   9.216  
   9.217              // Reject is CommitReject
   9.218 @@ -315,7 +308,7 @@
   9.219                  go End;
   9.220              }
   9.221  
   9.222 -            on CommitReject if sameTransactionAndPartner {
   9.223 +            on CommitReject if sameNegotiationAndPartner {
   9.224                  do disable;
   9.225                  go End;
   9.226              }
   9.227 @@ -326,21 +319,18 @@
   9.228                  send CommitAccept;
   9.229                  go HandshakingJoinPhase1;
   9.230              }
   9.231 -
   9.232 -            on CommitAcceptForGroup if sameTransactionAndPartner
   9.233 -                go HandshakingJoinPhase2;
   9.234          }
   9.235  
   9.236          state HandshakingJoinPhase1 {
   9.237 -            on Rollback if sameTransactionAndPartner
   9.238 +            on Rollback if sameNegotiationAndPartner
   9.239                  go Sole;
   9.240              
   9.241 -            on CommitReject if sameTransactionAndPartner {
   9.242 +            on CommitReject if sameNegotiationAndPartner {
   9.243                  do disable;
   9.244                  go End;
   9.245              }
   9.246  
   9.247 -            on CommitAcceptForGroup if sameTransactionAndPartner {
   9.248 +            on CommitAcceptForGroup if sameNegotiationAndPartner {
   9.249                  go JoinGroup;
   9.250              }
   9.251          }
   9.252 @@ -387,7 +377,7 @@
   9.253                  go Grouped;
   9.254              }
   9.255  
   9.256 -            on Rollback if sameTransactionAndPartner
   9.257 +            on Rollback if sameNegotiationAndPartner
   9.258                  go Grouped;
   9.259  
   9.260              // Reject is CommitReject
   9.261 @@ -396,7 +386,7 @@
   9.262                  go Grouped;
   9.263              }
   9.264  
   9.265 -            on CommitReject if sameTransactionAndPartner
   9.266 +            on CommitReject if sameNegotiationAndPartner
   9.267                  go Grouped;
   9.268  
   9.269              // Accept is Phase1Commit
   9.270 @@ -407,7 +397,7 @@
   9.271                  go HandshakingGroupedPhase1;
   9.272              }
   9.273  
   9.274 -            on CommitAccept if sameTransactionAndPartner
   9.275 +            on CommitAccept if sameNegotiationAndPartner
   9.276                  go HandshakingGroupedPhase2;
   9.277  
   9.278              on GroupTrustThisKey {
   9.279 @@ -417,7 +407,7 @@
   9.280  
   9.281              on CommitAcceptForGroup {
   9.282                  do showDeviceAdded;
   9.283 -                if sameTransactionAndPartner {
   9.284 +                if sameNegotiationAndPartner {
   9.285                      do hideHandshakeDialog;
   9.286                      go Grouped;
   9.287                  }
   9.288 @@ -428,13 +418,14 @@
   9.289          }
   9.290  
   9.291          state HandshakingGroupedPhase1 {
   9.292 -            on Rollback if sameTransactionAndPartner
   9.293 +            on Rollback if sameNegotiationAndPartner
   9.294                  go Grouped;
   9.295  
   9.296 -            on CommitReject if sameTransactionAndPartner
   9.297 +            on CommitReject if sameNegotiationAndPartner
   9.298                  go Grouped;
   9.299  
   9.300 -            on CommitAccept if sameTransactionAndPartner {
   9.301 +            on CommitAccept if sameNegotiationAndPartner {
   9.302 +                do prepareOwnKeys;
   9.303                  send GroupKeys;
   9.304                  go Grouped;
   9.305              }
   9.306 @@ -443,12 +434,6 @@
   9.307                  do trustThisKey;
   9.308              }
   9.309  
   9.310 -            on CommitAcceptForGroup {
   9.311 -                do showDeviceAdded;
   9.312 -                if sameTransactionAndPartner
   9.313 -                    go Grouped;
   9.314 -            }
   9.315 -
   9.316              on GroupKeys
   9.317                  do saveGroupKeys;
   9.318          }
   9.319 @@ -467,6 +452,7 @@
   9.320              on Accept {
   9.321                  do trustThisKey;
   9.322                  send GroupTrustThisKey;
   9.323 +                do prepareOwnKeys;
   9.324                  send GroupKeys;
   9.325                  go Grouped;
   9.326              }
   9.327 @@ -475,14 +461,6 @@
   9.328                  do trustThisKey;
   9.329              }
   9.330  
   9.331 -            on CommitAcceptForGroup {
   9.332 -                do showDeviceAdded;
   9.333 -                if sameTransactionAndPartner {
   9.334 -                    do hideHandshakeDialog;
   9.335 -                    go Grouped;
   9.336 -                }
   9.337 -            }
   9.338 -
   9.339              on GroupKeys
   9.340                  do saveGroupKeys;
   9.341          }
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/include/LotsOfKeysTests.h	Tue Jun 04 15:08:54 2019 +0200
    10.3 @@ -0,0 +1,19 @@
    10.4 +// This file is under GNU General Public License 3.0
    10.5 +// see LICENSE.txt
    10.6 +
    10.7 +#ifndef LOTS_OF_KEYS_H
    10.8 +#define LOTS_OF_KEYS_H
    10.9 +
   10.10 +#include <string>
   10.11 +#include "EngineTestIndividualSuite.h"
   10.12 +
   10.13 +using namespace std;
   10.14 +
   10.15 +class LotsOfKeysTests : public EngineTestIndividualSuite {
   10.16 +    public:
   10.17 +        LotsOfKeysTests(string test_suite, string test_home_dir);
   10.18 +    private:
   10.19 +        void check();
   10.20 +};
   10.21 +
   10.22 +#endif
    11.1 --- a/test/src/SuiteMaker.cc	Wed May 29 19:33:45 2019 +0200
    11.2 +++ b/test/src/SuiteMaker.cc	Tue Jun 04 15:08:54 2019 +0200
    11.3 @@ -40,6 +40,7 @@
    11.4  #include "KeyringImportTests.h"
    11.5  #include "EnterLeaveDeviceGroupTests.h"
    11.6  #include "SignOnlyTests.h"
    11.7 +#include "LotsOfKeysTests.h"
    11.8  #include "BCCTests.h"
    11.9  #include "Engine358Tests.h"
   11.10  #include "BlacklistAcceptNewKeyTests.h"
   11.11 @@ -105,6 +106,7 @@
   11.12      "KeyringImportTests",
   11.13      "EnterLeaveDeviceGroupTests",
   11.14      "SignOnlyTests",
   11.15 +    "LotsOfKeysTests",
   11.16      "BCCTests",
   11.17      "Engine358Tests",
   11.18      "BlacklistAcceptNewKeyTests",
   11.19 @@ -142,7 +144,7 @@
   11.20  };
   11.21  
   11.22  // This file is generated, so magic constants are ok.
   11.23 -int SuiteMaker::num_suites = 62;
   11.24 +int SuiteMaker::num_suites = 63;
   11.25  
   11.26  void SuiteMaker::suitemaker_build(const char* test_class_name, const char* test_home, Test::Suite** test_suite) {
   11.27      if (strcmp(test_class_name, "URIAddressTests") == 0)
   11.28 @@ -201,6 +203,8 @@
   11.29          *test_suite = new EnterLeaveDeviceGroupTests(test_class_name, test_home);
   11.30      else if (strcmp(test_class_name, "SignOnlyTests") == 0)
   11.31          *test_suite = new SignOnlyTests(test_class_name, test_home);
   11.32 +    else if (strcmp(test_class_name, "LotsOfKeysTests") == 0)
   11.33 +        *test_suite = new LotsOfKeysTests(test_class_name, test_home);
   11.34      else if (strcmp(test_class_name, "BCCTests") == 0)
   11.35          *test_suite = new BCCTests(test_class_name, test_home);
   11.36      else if (strcmp(test_class_name, "Engine358Tests") == 0)
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/src/engine_tests/LotsOfKeysTests.cc	Tue Jun 04 15:08:54 2019 +0200
    12.3 @@ -0,0 +1,275 @@
    12.4 +// This file is under GNU General Public License 3.0
    12.5 +// see LICENSE.txt
    12.6 +
    12.7 +#include <stdlib.h>
    12.8 +#include <string>
    12.9 +#include <cstring>
   12.10 +#include <cpptest.h>
   12.11 +#include <fstream>
   12.12 +#include <sys/time.h>
   12.13 +#include <assert.h>
   12.14 +#include <sys/types.h>
   12.15 +#include <unistd.h>
   12.16 +#include <time.h>
   12.17 +
   12.18 +#include "pEpEngine.h"
   12.19 +
   12.20 +#include "test_util.h"
   12.21 +#include "EngineTestIndividualSuite.h"
   12.22 +#include "LotsOfKeysTests.h"
   12.23 +
   12.24 +// Whether to log to the file system (in /tmp).
   12.25 +#define LOG 0
   12.26 +// How to plot (in R).  You need to enable LOG above.
   12.27 +#if 0
   12.28 +
   12.29 +library(ggplot2);
   12.30 +
   12.31 +t = "2019XXXX-XXXXXX";
   12.32 +find_keys = read.csv(sprintf("/tmp/pep-benchmark-find-keys-%s.csv", t),
   12.33 +                     header=T, sep=",")
   12.34 +get_ids = read.csv(sprintf("/tmp/pep-benchmark-get-identity-%s.csv", t),
   12.35 +                   header=T, sep=",")
   12.36 +ggplot(find_keys, aes(x=Keys, y=run0_us_per_op), tag="FOO") +
   12.37 +    geom_point() +
   12.38 +    geom_point(data = get_ids, aes(Keys, run0_us_per_op), colour = 'red') +
   12.39 +    scale_x_log10() + guides(fill = guide_legend()) +
   12.40 +    labs(title="Microseconds/Op for a Key/Management DB with x keys",
   12.41 +         x="Keys in DB", y="usec")
   12.42 +
   12.43 +ggsave("/tmp/pep-benchmark.pdf", width = 4, height = 4)
   12.44 +#endif
   12.45 +
   12.46 +
   12.47 +using namespace std;
   12.48 +
   12.49 +LotsOfKeysTests::LotsOfKeysTests(string suitename, string test_home_dir) :
   12.50 +    EngineTestIndividualSuite::EngineTestIndividualSuite(suitename, test_home_dir) {
   12.51 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("LotsOfKeysTests::check"),
   12.52 +                                                                      static_cast<Func>(&LotsOfKeysTests::check)));
   12.53 +}
   12.54 +
   12.55 +// Only really run the bench mark if logging is enabled.
   12.56 +#if LOG > 0
   12.57 +// Maximum number of keys.
   12.58 +#  define N 31622
   12.59 +// Amount of time to run each benchmark, in usecs.
   12.60 +#  define TIME 2 * 1000000
   12.61 +#else
   12.62 +// Don't actually run the benchmark.
   12.63 +#  define N 3
   12.64 +#  define TIME 0
   12.65 +#endif
   12.66 +
   12.67 +// Number of times to run each benchmark.
   12.68 +#define REPITIONS 3
   12.69 +
   12.70 +// 10^x, x=0.5.. step 0.5.
   12.71 +const int exp[] = { 3, 10, 31, 100, 316, 1000, 3162, 10000, 31622,
   12.72 +                    100000, 316227, 1000000, 3162277, 10000000,
   12.73 +                    31622776, 100000000, 316227766, 1000000000 };
   12.74 +#define BENCHMARKS (sizeof(exp) / sizeof(exp[0]))
   12.75 +
   12.76 +struct stats {
   12.77 +    FILE *fp;
   12.78 +    const char *name;
   12.79 +    struct {
   12.80 +        // Number of keys in the db.
   12.81 +        int keys;
   12.82 +        unsigned long long time[REPITIONS];
   12.83 +        unsigned long long ops[REPITIONS];
   12.84 +    } benchmarks[BENCHMARKS];
   12.85 +};
   12.86 +
   12.87 +struct stats *stats_new(const char *name)
   12.88 +{
   12.89 +    struct stats *stats = (struct stats *) calloc(1, sizeof(*stats));
   12.90 +    stats->name = name;
   12.91 +    return stats;
   12.92 +}
   12.93 +
   12.94 +unsigned long long time() {
   12.95 +    struct timeval tv;
   12.96 +    int err = gettimeofday(&tv, NULL);
   12.97 +    assert(err == 0);
   12.98 +
   12.99 +    return (unsigned long long) (tv.tv_sec * 1000000 + tv.tv_usec);
  12.100 +}
  12.101 +
  12.102 +static char start_time[100];
  12.103 +
  12.104 +static void dump_stats(struct stats *stats, int benchmark) {
  12.105 +    if (LOG && ! stats->fp) {
  12.106 +        char fn[1024];
  12.107 +        sprintf(fn, "/tmp/pep-benchmark-%s-%s.csv", stats->name, start_time);
  12.108 +        stats->fp = fopen(fn , "w");
  12.109 +        if (! stats->fp) {
  12.110 +            printf("Opening %s failed.\n", fn);
  12.111 +            abort();
  12.112 +        }
  12.113 +
  12.114 +        fprintf(stats->fp, "Keys");
  12.115 +        for (int iter = 0; iter < REPITIONS; iter ++) {
  12.116 +            fprintf(stats->fp, ", run%d_us_per_op, run%d_ops_per_sec", iter, iter);
  12.117 +        }
  12.118 +        fprintf(stats->fp, "\n");
  12.119 +    }
  12.120 +
  12.121 +    printf("%-8d keys", stats->benchmarks[benchmark].keys);
  12.122 +    if (stats->fp)
  12.123 +        fprintf(stats->fp, "%d", stats->benchmarks[benchmark].keys);
  12.124 +
  12.125 +    for (int iter = 0; iter < REPITIONS; iter ++) {
  12.126 +        double us_per_lookup = (double) stats->benchmarks[benchmark].time[iter]
  12.127 +            / (double) stats->benchmarks[benchmark].ops[iter];
  12.128 +        double ops_per_second = (double) stats->benchmarks[benchmark].ops[iter]
  12.129 +            / ((double) stats->benchmarks[benchmark].time[iter] / 1000000);
  12.130 +
  12.131 +        printf("\t%.02f us/op (%.1f ops/s)", us_per_lookup, ops_per_second);
  12.132 +        if (stats->fp)
  12.133 +            fprintf(stats->fp, ", %f, %f", us_per_lookup, ops_per_second);
  12.134 +    }
  12.135 +
  12.136 +    printf("\n");
  12.137 +    if (stats->fp) {
  12.138 +        fprintf(stats->fp, "\n");
  12.139 +        fflush(stats->fp);
  12.140 +    }
  12.141 +}
  12.142 +
  12.143 +void LotsOfKeysTests::check() {
  12.144 +    struct tm tm;
  12.145 +    time_t t = time((time_t *) NULL);
  12.146 +    localtime_r(&t, &tm);
  12.147 +    strftime(start_time, sizeof(start_time), "%Y%m%d-%H%M%S", &tm);
  12.148 +
  12.149 +    struct stats *find_keys_stats = stats_new("find-keys");
  12.150 +    struct stats *get_identity_stats = stats_new("get-identity");
  12.151 +
  12.152 +    int benchmark = 0;
  12.153 +    PEP_STATUS status;
  12.154 +    pEp_identity **ids = (pEp_identity **) calloc(N, sizeof(*ids));
  12.155 +    assert(ids);
  12.156 +
  12.157 +    status = config_cipher_suite(session, PEP_CIPHER_SUITE_CV25519);
  12.158 +    TEST_ASSERT_MSG(status == PEP_STATUS_OK, tl_status_string(status));
  12.159 +
  12.160 +    for (int key = 0; key < N; key ++) {
  12.161 +        // Create key
  12.162 +        char email[1024];
  12.163 +        sprintf(email, "%09d@example.org", key);
  12.164 +
  12.165 +        ids[key] = new_identity(strdup(email), NULL, NULL, "Test User");
  12.166 +        status = update_identity(session, ids[key]);
  12.167 +        TEST_ASSERT_MSG(status == PEP_STATUS_OK, tl_status_string(status));
  12.168 +
  12.169 +        if (key == 0) {
  12.170 +            printf("\nRaw identity:\n");
  12.171 +            printf("   address = %s\n", ids[0]->address);
  12.172 +            printf("       fpr = %s\n", ids[0]->fpr);
  12.173 +            printf("   user_id = %s\n", ids[0]->user_id);
  12.174 +            printf("  username = %s\n", ids[0]->username);
  12.175 +        }
  12.176 +
  12.177 +        status = generate_keypair(session, ids[key]);
  12.178 +        TEST_ASSERT_MSG(status == PEP_STATUS_OK, tl_status_string(status));
  12.179 +
  12.180 +        if (key == 0) {
  12.181 +            printf("\nAfter generating a key:\n");
  12.182 +            printf("   address = %s\n", ids[0]->address);
  12.183 +            printf("       fpr = %s\n", ids[0]->fpr);
  12.184 +            printf("   user_id = %s\n", ids[0]->user_id);
  12.185 +            printf("  username = %s\n", ids[0]->username);
  12.186 +        }
  12.187 +
  12.188 +        status = set_identity(session, ids[key]);
  12.189 +        TEST_ASSERT_MSG(status == PEP_STATUS_OK, tl_status_string(status));
  12.190 +
  12.191 +        if (key == 0) {
  12.192 +            printf("\nSetting identity:\n");
  12.193 +            printf("   address = %s\n", ids[0]->address);
  12.194 +            printf("       fpr = %s\n", ids[0]->fpr);
  12.195 +            printf("   user_id = %s\n", ids[0]->user_id);
  12.196 +            printf("  username = %s\n", ids[0]->username);
  12.197 +        }
  12.198 +
  12.199 +        bool do_benchmark = false;
  12.200 +        for (int i = 0; i < sizeof(exp) / sizeof(exp[0]); i ++) {
  12.201 +            if (key + 1 == exp[i]) {
  12.202 +                do_benchmark = true;
  12.203 +            } else if (key + 1 < exp[i]) {
  12.204 +                break;
  12.205 +            }
  12.206 +        }
  12.207 +
  12.208 +        if (! do_benchmark)
  12.209 +            continue;
  12.210 +
  12.211 +
  12.212 +        // Look up a random key by its email address.
  12.213 +        //
  12.214 +        // This doesn't use the engine, only the pgp
  12.215 +        // implementation.  For Sequoia, this should run in O(log
  12.216 +        // N).
  12.217 +        find_keys_stats->benchmarks[benchmark].keys = key + 1;
  12.218 +        for (int iter = 0; iter < REPITIONS; iter ++) {
  12.219 +            unsigned long long start = time();
  12.220 +            unsigned long long elapsed;
  12.221 +            int ops = 0;
  12.222 +
  12.223 +            do {
  12.224 +                int i = random() % (key + 1);
  12.225 +                assert(i <= key);
  12.226 +
  12.227 +                stringlist_t* keylist = NULL;
  12.228 +                status = find_keys(session, ids[i]->address, &keylist);
  12.229 +                free_stringlist(keylist);
  12.230 +                TEST_ASSERT_MSG(status == PEP_STATUS_OK,
  12.231 +                                tl_status_string(status));
  12.232 +                ops ++;
  12.233 +                elapsed = time() - start;
  12.234 +            } while (elapsed < TIME);
  12.235 +
  12.236 +            find_keys_stats->benchmarks[benchmark].ops[iter] = ops;
  12.237 +            find_keys_stats->benchmarks[benchmark].time[iter] = elapsed;
  12.238 +        }
  12.239 +
  12.240 +        dump_stats(find_keys_stats, benchmark);
  12.241 +
  12.242 +
  12.243 +        // Look up a random key by its pep user id.
  12.244 +        //
  12.245 +        // This uses the engine's management databank and doesn't
  12.246 +        // touch the pgp engine's DB.
  12.247 +        get_identity_stats->benchmarks[benchmark].keys = key + 1;
  12.248 +        for (int iter = 0; iter < REPITIONS; iter ++) {
  12.249 +            unsigned long long start = time();
  12.250 +            unsigned long long elapsed;
  12.251 +            int ops = 0;
  12.252 +
  12.253 +            do {
  12.254 +                int i = random() % (key + 1);
  12.255 +                pEp_identity *id = NULL;
  12.256 +                status = get_identity(session, ids[i]->address,
  12.257 +                                      ids[i]->user_id, &id);
  12.258 +                TEST_ASSERT_MSG(status == PEP_STATUS_OK,
  12.259 +                                tl_status_string(status));
  12.260 +                TEST_ASSERT_MSG(id->fpr, "no fingerprint");
  12.261 +                TEST_ASSERT_MSG(strcmp(ids[i]->fpr, id->fpr) == 0,
  12.262 +                                "fingerprint mismatch");
  12.263 +                free_identity(id);
  12.264 +
  12.265 +                ops ++;
  12.266 +                elapsed = time() - start;
  12.267 +            } while (elapsed < TIME);
  12.268 +
  12.269 +            get_identity_stats->benchmarks[benchmark].ops[iter] = ops;
  12.270 +            get_identity_stats->benchmarks[benchmark].time[iter] = elapsed;
  12.271 +        }
  12.272 +
  12.273 +        dump_stats(get_identity_stats, benchmark);
  12.274 +
  12.275 +
  12.276 +        benchmark++;
  12.277 +    }
  12.278 +}