... keysync
authorVolker Birk <vb@pep.foundation>
Sun, 31 Jul 2016 19:38:23 +0200
branchkeysync
changeset 951dec407deb10e
parent 949 779219e99833
child 952 986fd7b2eb8f
...
asn.1/devicegroup.asn1
asn.1/pEp.asn1
src/message_api.c
src/pEpEngine.c
src/pEpEngine.h
src/sync.c
src/sync_actions.c
src/sync_driver.c
src/sync_fsm.c
src/sync_fsm.h
src/sync_send_actions.c
sync/devicegroup.fsm
sync/fsm.yml2
sync/gen_actions_skeleton.ysl2
sync/gen_statemachine.ysl2
     1.1 --- a/asn.1/devicegroup.asn1	Sun Jul 31 09:04:42 2016 +0200
     1.2 +++ b/asn.1/devicegroup.asn1	Sun Jul 31 19:38:23 2016 +0200
     1.3 @@ -9,31 +9,24 @@
     1.4  IMPORTS Identity, IdentityList, Header FROM PEP;
     1.5  
     1.6  Beacon ::= SEQUENCE {
     1.7 -    header Header,
     1.8 -    state INTEGER,
     1.9 -    me Identity
    1.10 +    header Header
    1.11  }
    1.12  
    1.13  HandshakeRequest ::= SEQUENCE {
    1.14 -    header Header,
    1.15 -    state INTEGER,
    1.16 -    me Identity,
    1.17 -    partner Identity
    1.18 +    header Header
    1.19  }
    1.20  
    1.21  GroupKeys ::= SEQUENCE {
    1.22      header Header,
    1.23 -    state INTEGER,
    1.24 -    me Identity,
    1.25      ownIdentities IdentityList
    1.26  }
    1.27  
    1.28  /* for the tags see end of sync.fsm */
    1.29  
    1.30  DeviceGroup-Protocol ::= CHOICE {
    1.31 -    beacon [APPLICATION 1] Beacon,
    1.32 -    handshakeRequest [APPLICATION 2] HandshakeRequest,
    1.33 -    groupKeys [APPLICATION 3] GroupKeys
    1.34 +    beacon [APPLICATION 2] Beacon,
    1.35 +    handshakeRequest [APPLICATION 3] HandshakeRequest,
    1.36 +    groupKeys [APPLICATION 4] GroupKeys
    1.37  }
    1.38  
    1.39  END
     2.1 --- a/asn.1/pEp.asn1	Sun Jul 31 09:04:42 2016 +0200
     2.2 +++ b/asn.1/pEp.asn1	Sun Jul 31 19:38:23 2016 +0200
     2.3 @@ -32,7 +32,11 @@
     2.4  
     2.5  Header ::= SEQUENCE {
     2.6      version     Version,
     2.7 -    sequence    INTEGER
     2.8 +    sequence    INTEGER,  /* always increases */
     2.9 +    me          Identity, /* identity of the sender */
    2.10 +    state       INTEGER,  /* state the sender is in */
    2.11 +    devicegroup BOOLEAN DEFAULT FALSE
    2.12 +        /* signals if this message is coming from a device group member */
    2.13  }
    2.14  
    2.15  END
     3.1 --- a/src/message_api.c	Sun Jul 31 09:04:42 2016 +0200
     3.2 +++ b/src/message_api.c	Sun Jul 31 19:38:23 2016 +0200
     3.3 @@ -9,11 +9,11 @@
     3.4  #include <stdlib.h>
     3.5  
     3.6  
     3.7 -#ifndef MIN
     3.8 -#define MIN(A, B) ((B) > (A) ? (A) : (B))
     3.9 +#ifndef _MIN
    3.10 +#define _MIN(A, B) ((B) > (A) ? (A) : (B))
    3.11  #endif
    3.12 -#ifndef MAX
    3.13 -#define MAX(A, B) ((B) > (A) ? (B) : (A))
    3.14 +#ifndef _MAX
    3.15 +#define _MAX(A, B) ((B) > (A) ? (B) : (A))
    3.16  #endif
    3.17  
    3.18  
    3.19 @@ -851,7 +851,7 @@
    3.20          else if (ident->comm_type == PEP_ct_mistrusted)
    3.21              return PEP_ct_mistrusted;
    3.22          else
    3.23 -            return MIN(max_comm_type, ident->comm_type);
    3.24 +            return _MIN(max_comm_type, ident->comm_type);
    3.25      }
    3.26      else {
    3.27          return PEP_ct_unknown;
    3.28 @@ -1686,7 +1686,7 @@
    3.29      if (comm_type_determined == false)
    3.30          *color = PEP_rating_undefined;
    3.31      else
    3.32 -        *color = MAX(_rating(max_comm_type, PEP_rating_undefined),
    3.33 +        *color = _MAX(_rating(max_comm_type, PEP_rating_undefined),
    3.34                  PEP_rating_unencrypted);
    3.35  
    3.36      return PEP_STATUS_OK;
     4.1 --- a/src/pEpEngine.c	Sun Jul 31 09:04:42 2016 +0200
     4.2 +++ b/src/pEpEngine.c	Sun Jul 31 19:38:23 2016 +0200
     4.3 @@ -188,7 +188,8 @@
     4.4                  "       references pgp_keypair (fpr)\n"
     4.5                  "       on delete set null,\n"
     4.6                  "   lang text,\n"
     4.7 -                "   comment text\n"
     4.8 +                "   comment text,\n"
     4.9 +                "   device_group text\n"
    4.10                  ");\n"
    4.11                  "create table if not exists identity (\n"
    4.12                  "   address text,\n"
    4.13 @@ -250,7 +251,7 @@
    4.14              int_result = sqlite3_exec(
    4.15                  _session->db,
    4.16                  "alter table identity\n"
    4.17 -                "   add column flags integer default (0);",
    4.18 +                "   add column flags integer default (0);\n",
    4.19                  NULL,
    4.20                  NULL,
    4.21                  NULL
    4.22 @@ -261,9 +262,10 @@
    4.23          if (version < 2) {
    4.24              int_result = sqlite3_exec(
    4.25                  _session->db,
    4.26 -                "PRAGMA application_id = 0x23423423;\n"
    4.27                  "alter table pgp_keypair\n"
    4.28 -                "   add column flags integer default (0);",
    4.29 +                "   add column flags integer default (0);\n"
    4.30 +                "alter table person\n"
    4.31 +                "   add column device_group text;\n",
    4.32                  NULL,
    4.33                  NULL,
    4.34                  NULL
    4.35 @@ -382,8 +384,8 @@
    4.36                                "    where replacement_fpr = upper(replace(?1,' ','')) ;";
    4.37      }
    4.38  
    4.39 -    int_result = sqlite3_prepare_v2(_session->db, sql_log, (int)strlen(sql_log),
    4.40 -            &_session->log, NULL);
    4.41 +    int_result = sqlite3_prepare_v2(_session->db, sql_log,
    4.42 +            (int)strlen(sql_log), &_session->log, NULL);
    4.43      assert(int_result == SQLITE_OK);
    4.44  
    4.45      int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
    4.46 @@ -399,7 +401,8 @@
    4.47      assert(int_result == SQLITE_OK);
    4.48  
    4.49      int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
    4.50 -            (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
    4.51 +            (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair,
    4.52 +            NULL);
    4.53      assert(int_result == SQLITE_OK);
    4.54  
    4.55      int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
    4.56 @@ -407,7 +410,8 @@
    4.57      assert(int_result == SQLITE_OK);
    4.58  
    4.59      int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags,
    4.60 -            (int)strlen(sql_set_identity_flags), &_session->set_identity_flags, NULL);
    4.61 +            (int)strlen(sql_set_identity_flags), &_session->set_identity_flags,
    4.62 +            NULL);
    4.63      assert(int_result == SQLITE_OK);
    4.64  
    4.65      int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
    4.66 @@ -423,7 +427,8 @@
    4.67      assert(int_result == SQLITE_OK);
    4.68  
    4.69      int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
    4.70 -            (int)strlen(sql_mark_as_compromized), &_session->mark_compromized, NULL);
    4.71 +            (int)strlen(sql_mark_as_compromized), &_session->mark_compromized,
    4.72 +            NULL);
    4.73      assert(int_result == SQLITE_OK);
    4.74  
    4.75      int_result = sqlite3_prepare_v2(_session->db, sql_crashdump,
    4.76 @@ -445,45 +450,52 @@
    4.77      assert(int_result == SQLITE_OK);
    4.78  
    4.79      int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete,
    4.80 -            (int)strlen(sql_blacklist_delete), &_session->blacklist_delete, NULL);
    4.81 +            (int)strlen(sql_blacklist_delete), &_session->blacklist_delete,
    4.82 +            NULL);
    4.83      assert(int_result == SQLITE_OK);
    4.84  
    4.85      int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed,
    4.86 -            (int)strlen(sql_blacklist_is_listed), &_session->blacklist_is_listed, NULL);
    4.87 +            (int)strlen(sql_blacklist_is_listed),
    4.88 +            &_session->blacklist_is_listed, NULL);
    4.89      assert(int_result == SQLITE_OK);
    4.90  
    4.91      int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve,
    4.92 -            (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve, NULL);
    4.93 +            (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve,
    4.94 +            NULL);
    4.95      assert(int_result == SQLITE_OK);
    4.96  
    4.97      // Own keys
    4.98      
    4.99      int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
   4.100 -            (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed, NULL);
   4.101 +            (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed,
   4.102 +            NULL);
   4.103      assert(int_result == SQLITE_OK);
   4.104      
   4.105      int_result = sqlite3_prepare_v2(_session->db, sql_own_key_retrieve,
   4.106 -            (int)strlen(sql_own_key_retrieve), &_session->own_key_retrieve, NULL);
   4.107 +            (int)strlen(sql_own_key_retrieve), &_session->own_key_retrieve,
   4.108 +            NULL);
   4.109      assert(int_result == SQLITE_OK);
   4.110   
   4.111      // Sequence
   4.112  
   4.113      int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1,
   4.114 -            (int)strlen(sql_sequence_value1), &_session->sequence_value1, NULL);
   4.115 +            (int)strlen(sql_sequence_value1), &_session->sequence_value1,
   4.116 +            NULL);
   4.117      assert(int_result == SQLITE_OK);
   4.118  
   4.119      int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2,
   4.120 -            (int)strlen(sql_sequence_value2), &_session->sequence_value2, NULL);
   4.121 +            (int)strlen(sql_sequence_value2), &_session->sequence_value2,
   4.122 +            NULL);
   4.123      assert(int_result == SQLITE_OK);
   4.124  
   4.125      // Revocation tracking
   4.126      
   4.127      int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
   4.128 -                                    (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
   4.129 +            (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
   4.130      assert(int_result == SQLITE_OK);
   4.131      
   4.132      int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
   4.133 -                                    (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
   4.134 +            (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
   4.135      assert(int_result == SQLITE_OK);
   4.136      
   4.137      status = init_cryptotech(_session, in_first);
   4.138 @@ -602,7 +614,8 @@
   4.139      session->unencrypted_subject = enable;
   4.140  }
   4.141  
   4.142 -DYNAMIC_API void config_use_only_own_private_keys(PEP_SESSION session, bool enable)
   4.143 +DYNAMIC_API void config_use_only_own_private_keys(PEP_SESSION session,
   4.144 +        bool enable)
   4.145  {
   4.146      assert(session);
   4.147      session->use_only_own_private_keys = enable;
   4.148 @@ -833,7 +846,8 @@
   4.149  {
   4.150      assert(src);
   4.151  
   4.152 -    pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
   4.153 +    pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id,
   4.154 +            src->username);
   4.155      assert(dup);
   4.156      if (dup == NULL)
   4.157          return NULL;
   4.158 @@ -896,8 +910,10 @@
   4.159          if (_identity == NULL)
   4.160              return PEP_OUT_OF_MEMORY;
   4.161  
   4.162 -        _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 2);
   4.163 -        const char* const _lang = (const char *) sqlite3_column_text(session->get_identity, 3);
   4.164 +        _identity->comm_type = (PEP_comm_type)
   4.165 +            sqlite3_column_int(session->get_identity, 2);
   4.166 +        const char* const _lang = (const char *)
   4.167 +            sqlite3_column_text(session->get_identity, 3);
   4.168          if (_lang && _lang[0]) {
   4.169              assert(_lang[0] >= 'a' && _lang[0] <= 'z');
   4.170              assert(_lang[1] >= 'a' && _lang[1] <= 'z');
   4.171 @@ -906,7 +922,8 @@
   4.172              _identity->lang[1] = _lang[1];
   4.173              _identity->lang[2] = 0;
   4.174          }
   4.175 -        _identity->flags = (unsigned int) sqlite3_column_int(session->get_identity, 4);
   4.176 +        _identity->flags = (unsigned int)
   4.177 +            sqlite3_column_int(session->get_identity, 4);
   4.178          *identity = _identity;
   4.179          break;
   4.180      default:
   4.181 @@ -1090,13 +1107,15 @@
   4.182      identity->comm_type = PEP_ct_unknown;
   4.183  
   4.184      sqlite3_reset(session->get_trust);
   4.185 -    sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
   4.186 +    sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
   4.187 +            SQLITE_STATIC);
   4.188      sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
   4.189  
   4.190      result = sqlite3_step(session->get_trust);
   4.191      switch (result) {
   4.192      case SQLITE_ROW: {
   4.193 -        int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust, 0);
   4.194 +        int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
   4.195 +                0);
   4.196          identity->comm_type = comm_type;
   4.197          break;
   4.198      }
   4.199 @@ -1179,7 +1198,8 @@
   4.200      if (!(session && keylist && ptext && psize && ctext && csize))
   4.201          return PEP_ILLEGAL_VALUE;
   4.202  
   4.203 -    return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
   4.204 +    return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session,
   4.205 +            keylist, ptext, psize, ctext, csize);
   4.206  }
   4.207  
   4.208  DYNAMIC_API PEP_STATUS verify_text(
   4.209 @@ -1197,7 +1217,8 @@
   4.210      if (!(session && text && size && signature && sig_size && keylist))
   4.211          return PEP_ILLEGAL_VALUE;
   4.212  
   4.213 -    return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
   4.214 +    return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text,
   4.215 +            size, signature, sig_size, keylist);
   4.216  }
   4.217  
   4.218  DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
   4.219 @@ -1223,7 +1244,8 @@
   4.220      if (!(session && fpr && key_data && size))
   4.221          return PEP_ILLEGAL_VALUE;
   4.222  
   4.223 -    return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
   4.224 +    return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
   4.225 +            key_data, size);
   4.226  }
   4.227  
   4.228  DYNAMIC_API PEP_STATUS find_keys(
   4.229 @@ -1237,7 +1259,8 @@
   4.230      if (!(session && pattern && keylist))
   4.231          return PEP_ILLEGAL_VALUE;
   4.232  
   4.233 -    return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
   4.234 +    return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern,
   4.235 +            keylist);
   4.236  }
   4.237  
   4.238  DYNAMIC_API PEP_STATUS generate_keypair(
   4.239 @@ -1251,7 +1274,8 @@
   4.240      assert(identity->username);
   4.241  
   4.242      if (!(session && identity && identity->address &&
   4.243 -        (identity->fpr == NULL || identity->fpr[0] == 0) && identity->username))
   4.244 +            (identity->fpr == NULL || identity->fpr[0] == 0) &&
   4.245 +            identity->username))
   4.246          return PEP_ILLEGAL_VALUE;
   4.247  
   4.248      PEP_STATUS status =
   4.249 @@ -1262,8 +1286,7 @@
   4.250  
   4.251      // if a state machine for keysync is in place, inject notify
   4.252      if (session->sync_state != DeviceState_state_NONE)
   4.253 -        status = fsm_DeviceState_inject(session, KeyGen, NULL,
   4.254 -                DeviceState_state_NONE);
   4.255 +        status = fsm_DeviceState_inject(session, KeyGen, NULL, NULL);
   4.256  
   4.257      return status;
   4.258  }
   4.259 @@ -1281,7 +1304,8 @@
   4.260      if (!(session && fpr && comm_type))
   4.261          return PEP_ILLEGAL_VALUE;
   4.262  
   4.263 -    return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
   4.264 +    return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr,
   4.265 +            comm_type);
   4.266  }
   4.267  
   4.268  DYNAMIC_API PEP_STATUS import_key(
   4.269 @@ -1297,7 +1321,8 @@
   4.270      if (!(session && key_data))
   4.271          return PEP_ILLEGAL_VALUE;
   4.272  
   4.273 -    return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size, private_keys);
   4.274 +    return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
   4.275 +            size, private_keys);
   4.276  }
   4.277  
   4.278  DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
   4.279 @@ -1372,10 +1397,10 @@
   4.280  }
   4.281  
   4.282  DYNAMIC_API PEP_STATUS key_revoked(
   4.283 -                                   PEP_SESSION session,
   4.284 -                                   const char *fpr,
   4.285 -                                   bool *revoked
   4.286 -                                   )
   4.287 +       PEP_SESSION session,
   4.288 +       const char *fpr,
   4.289 +       bool *revoked
   4.290 +   )
   4.291  {
   4.292      assert(session);
   4.293      assert(fpr);
   4.294 @@ -1385,7 +1410,7 @@
   4.295          return PEP_ILLEGAL_VALUE;
   4.296      
   4.297      return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
   4.298 -                                                              revoked);
   4.299 +            revoked);
   4.300  }
   4.301  
   4.302  static void _clean_log_value(char *text)
   4.303 @@ -1457,11 +1482,16 @@
   4.304          result = sqlite3_step(session->crashdump);
   4.305          switch (result) {
   4.306          case SQLITE_ROW:
   4.307 -            timestamp = (const char *) sqlite3_column_text(session->crashdump, 0);
   4.308 -            title   = (const char *) sqlite3_column_text(session->crashdump, 1);
   4.309 -            entity  = (const char *) sqlite3_column_text(session->crashdump, 2);
   4.310 -            desc    = (const char *) sqlite3_column_text(session->crashdump, 3);
   4.311 -            comment = (const char *) sqlite3_column_text(session->crashdump, 4);
   4.312 +            timestamp = (const char *) sqlite3_column_text(session->crashdump,
   4.313 +                    0);
   4.314 +            title   = (const char *) sqlite3_column_text(session->crashdump,
   4.315 +                    1);
   4.316 +            entity  = (const char *) sqlite3_column_text(session->crashdump,
   4.317 +                    2);
   4.318 +            desc    = (const char *) sqlite3_column_text(session->crashdump,
   4.319 +                    3);
   4.320 +            comment = (const char *) sqlite3_column_text(session->crashdump,
   4.321 +                    4);
   4.322  
   4.323              _logdata = _concat_string(_logdata, timestamp, ',');
   4.324              if (_logdata == NULL)
   4.325 @@ -1536,9 +1566,12 @@
   4.326          result = sqlite3_step(session->languagelist);
   4.327          switch (result) {
   4.328          case SQLITE_ROW:
   4.329 -            lang = (const char *) sqlite3_column_text(session->languagelist, 0);
   4.330 -            name = (const char *) sqlite3_column_text(session->languagelist, 1);
   4.331 -            phrase = (const char *) sqlite3_column_text(session->languagelist, 2);
   4.332 +            lang = (const char *) sqlite3_column_text(session->languagelist,
   4.333 +                    0);
   4.334 +            name = (const char *) sqlite3_column_text(session->languagelist,
   4.335 +                    1);
   4.336 +            phrase = (const char *) sqlite3_column_text(session->languagelist,
   4.337 +                    2);
   4.338  
   4.339              _languages = _concat_string(_languages, lang, ',');
   4.340              if (_languages == NULL)
   4.341 @@ -1656,7 +1689,8 @@
   4.342      }
   4.343      else {
   4.344          sqlite3_reset(session->sequence_value2);
   4.345 -        sqlite3_bind_text(session->sequence_value2, 1, name, -1, SQLITE_STATIC);
   4.346 +        sqlite3_bind_text(session->sequence_value2, 1, name, -1,
   4.347 +                SQLITE_STATIC);
   4.348          result = sqlite3_step(session->sequence_value2);
   4.349          switch (result) {
   4.350              case SQLITE_ROW: {
   4.351 @@ -1695,7 +1729,8 @@
   4.352      
   4.353      sqlite3_reset(session->set_revoked);
   4.354      sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
   4.355 -    sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1, SQLITE_STATIC);
   4.356 +    sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1,
   4.357 +            SQLITE_STATIC);
   4.358      sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
   4.359  
   4.360      int result;
   4.361 @@ -1745,9 +1780,11 @@
   4.362      result = sqlite3_step(session->get_revoked);
   4.363      switch (result) {
   4.364          case SQLITE_ROW: {
   4.365 -            *revoked_fpr = strdup((const char *) sqlite3_column_text(session->get_revoked, 0));
   4.366 +            *revoked_fpr = strdup((const char *)
   4.367 +                    sqlite3_column_text(session->get_revoked, 0));
   4.368              if(*revoked_fpr)
   4.369 -                *revocation_date = sqlite3_column_int64(session->get_revoked, 1);
   4.370 +                *revocation_date = sqlite3_column_int64(session->get_revoked,
   4.371 +                        1);
   4.372              else
   4.373                  status = PEP_OUT_OF_MEMORY;
   4.374  
     5.1 --- a/src/pEpEngine.h	Sun Jul 31 09:04:42 2016 +0200
     5.2 +++ b/src/pEpEngine.h	Sun Jul 31 19:38:23 2016 +0200
     5.3 @@ -72,6 +72,7 @@
     5.4      PEP_CANNOT_ENCODE                               = 0x0803,
     5.5  
     5.6      PEP_SYNC_NO_TRUSTWORDS_CALLBACK                 = 0x0901,
     5.7 +    PEP_SYNC_ILLEGAL_MESSAGE                        = 0x0902,
     5.8  
     5.9      PEP_COMMIT_FAILED                               = 0xff01,
    5.10  
    5.11 @@ -319,6 +320,8 @@
    5.12      );
    5.13  
    5.14  
    5.15 +// TODO: increase versions in pEp.asn1 if rating changes
    5.16 +
    5.17  typedef enum _PEP_comm_type {
    5.18      PEP_ct_unknown = 0,
    5.19  
    5.20 @@ -380,12 +383,12 @@
    5.21  } PEP_comm_type;
    5.22  
    5.23  typedef enum _identity_flags {
    5.24 -    // first octet is flags set by application
    5.25 +    // the first octet flags are app defined settings
    5.26      PEP_idf_not_for_sync = 1,   // don't use this identity for sync
    5.27 -    PEP_idf_group = 2,          // identity of group of persons
    5.28 +    PEP_idf_list = 2,           // identity of list of persons
    5.29  
    5.30 -    // second octet is flags set by key sync implementation
    5.31 -    PEP_idf_device_group = 256  // own identity member of device group
    5.32 +    // the second octet flags are calculated
    5.33 +    PEP_idf_devicegroup = 256   // identity of a device group member
    5.34  } identity_flags;
    5.35  
    5.36  typedef unsigned int identity_flags_t;
    5.37 @@ -467,8 +470,8 @@
    5.38  //                            NULL if failure
    5.39  //
    5.40  //    caveat:
    5.41 -//        the address string is being copied; the original string remains in the
    5.42 -//        ownership of the caller
    5.43 +//        address and user_id are being copied; the original strings remains in
    5.44 +//        the ownership of the caller
    5.45  //        the resulting pEp_identity structure goes to the ownership of the
    5.46  //        caller and has to be freed with free_identity() when not in use any
    5.47  //        more
     6.1 --- a/src/sync.c	Sun Jul 31 09:04:42 2016 +0200
     6.2 +++ b/src/sync.c	Sun Jul 31 19:38:23 2016 +0200
     6.3 @@ -3,6 +3,8 @@
     6.4  #include <memory.h>
     6.5  #include <assert.h>
     6.6  
     6.7 +#include "../asn.1/DeviceGroup-Protocol.h"
     6.8 +
     6.9  
    6.10  DYNAMIC_API PEP_STATUS register_sync_callbacks(
    6.11          PEP_SESSION session,
     7.1 --- a/src/sync_actions.c	Sun Jul 31 09:04:42 2016 +0200
     7.2 +++ b/src/sync_actions.c	Sun Jul 31 19:38:23 2016 +0200
     7.3 @@ -4,7 +4,74 @@
     7.4  #include "pEp_internal.h"
     7.5  #include "message.h"
     7.6  #include "sync_fsm.h"
     7.7 +#include "map_asn1.h"
     7.8  
     7.9 +// conditions
    7.10 +
    7.11 +static const char *sql_stored_group_keys =
    7.12 +        "select count(device_group) from person where id = "PEP_OWN_USERID";"; 
    7.13 +
    7.14 +static int _stored_group_keys(void *_gc, int count, char **text, char **name)
    7.15 +{
    7.16 +    assert(_gc);
    7.17 +    assert(count == 1);
    7.18 +    assert(text && text[0]);
    7.19 +    if (!(_gc && count == 1 && text && text[0]))
    7.20 +        return -1;
    7.21 +
    7.22 +    bool *gc = (bool *) _gc;
    7.23 +    *gc = atoi(text[0]) != 0;
    7.24 +    return 0;
    7.25 +}
    7.26 +
    7.27 +bool storedGroupKeys(PEP_SESSION session)
    7.28 +{
    7.29 +    assert(session);
    7.30 +    if (!session)
    7.31 +        return false;
    7.32 +
    7.33 +    bool gc = false;
    7.34 +    int int_result = sqlite3_exec(
    7.35 +        session->db,
    7.36 +        sql_stored_group_keys,
    7.37 +        _stored_group_keys,
    7.38 +        &gc,
    7.39 +        NULL
    7.40 +    );
    7.41 +    assert(int_result == SQLITE_OK);
    7.42 +    return gc;
    7.43 +}
    7.44 +
    7.45 +bool keyElectionWon(PEP_SESSION session, Identity partner)
    7.46 +{
    7.47 +    assert(session);
    7.48 +    assert(partner);
    7.49 +    if (!(session && partner))
    7.50 +        return false;
    7.51 +
    7.52 +    // an already existing group always wins
    7.53 +
    7.54 +    if (storedGroupKeys(session)) {
    7.55 +        assert(!(partner->flags & PEP_idf_devicegroup));
    7.56 +        return true;
    7.57 +    }
    7.58 +
    7.59 +    if (partner->flags & PEP_idf_devicegroup)
    7.60 +        return false;
    7.61 +
    7.62 +    Identity me = NULL;
    7.63 +    PEP_STATUS status = get_identity(session, partner->address, PEP_OWN_USERID,
    7.64 +            &me);
    7.65 +    if (status != PEP_STATUS_OK)
    7.66 +        return false;
    7.67 +
    7.68 +    bool result = false;
    7.69 +
    7.70 +
    7.71 +the_end:
    7.72 +    free_identity(me);
    7.73 +    return result;
    7.74 +}
    7.75  
    7.76  // showHandshake() - trigger the handshake dialog of the application
    7.77  //
    7.78 @@ -46,12 +113,14 @@
    7.79          goto error;
    7.80  
    7.81      free_identity(me);
    7.82 +    free_identity(partner);
    7.83      return status;
    7.84  
    7.85  enomem:
    7.86      status = PEP_OUT_OF_MEMORY;
    7.87  error:
    7.88      free_identity(me);
    7.89 +    free_identity(partner);
    7.90      return status;
    7.91  }
    7.92  
    7.93 @@ -84,11 +153,13 @@
    7.94      status = set_identity_flags(session, partner,
    7.95              partner->flags | PEP_idf_not_for_sync);
    7.96  
    7.97 +    free_identity(partner);
    7.98      return status;
    7.99  
   7.100  enomem:
   7.101      status = PEP_OUT_OF_MEMORY;
   7.102  error:
   7.103 +    free_identity(partner);
   7.104      // free...
   7.105      return status;
   7.106  }
   7.107 @@ -120,15 +191,66 @@
   7.108      if (!(session && partner && _group_keys))
   7.109          return PEP_ILLEGAL_VALUE;
   7.110  
   7.111 -    Stringlist group_keys = (Stringlist) _group_keys;
   7.112 +    identity_list *group_keys = (identity_list *) _group_keys;
   7.113 +    if (!group_keys)
   7.114 +        goto enomem;
   7.115  
   7.116 -
   7.117 +    free_identity(partner);
   7.118 +    free_identity_list(group_keys);
   7.119      return status;
   7.120  
   7.121  enomem:
   7.122      status = PEP_OUT_OF_MEMORY;
   7.123  error:
   7.124      // free...
   7.125 +    free_identity(partner);
   7.126 +    free_identity_list(group_keys);
   7.127      return status;
   7.128  }
   7.129  
   7.130 +PEP_STATUS receive_sync_msg(PEP_SESSION session, DeviceGroup_Protocol_t *msg)
   7.131 +{
   7.132 +    assert(session && msg && msg->present != DeviceGroup_Protocol_PR_NOTHING);
   7.133 +    if (!(session && msg && msg->present != DeviceGroup_Protocol_PR_NOTHING))
   7.134 +        return PEP_ILLEGAL_VALUE;
   7.135 +
   7.136 +    void *extra = NULL;
   7.137 +    Identity partner = NULL;
   7.138 +    DeviceState_event event = DeviceState_event_NONE;
   7.139 +
   7.140 +    switch (msg->present) {
   7.141 +        case DeviceGroup_Protocol_PR_beacon:
   7.142 +            partner = Identity_to_Struct(&msg->choice.beacon.header.me, NULL);
   7.143 +            if (!partner)
   7.144 +                return PEP_OUT_OF_MEMORY;
   7.145 +            event = Beacon;
   7.146 +            break;
   7.147 +
   7.148 +        case DeviceGroup_Protocol_PR_handshakeRequest:
   7.149 +            partner = Identity_to_Struct(&msg->choice.handshakeRequest.header.me, NULL);
   7.150 +            if (!partner)
   7.151 +                return PEP_OUT_OF_MEMORY;
   7.152 +            event = HandshakeRequest;
   7.153 +            break;
   7.154 +
   7.155 +        case DeviceGroup_Protocol_PR_groupKeys:
   7.156 +            partner = Identity_to_Struct(&msg->choice.groupKeys.header.me, NULL);
   7.157 +            if (!partner)
   7.158 +                return PEP_OUT_OF_MEMORY;
   7.159 +            identity_list *group_keys = IdentityList_to_identity_list(
   7.160 +                    &msg->choice.groupKeys.ownIdentities, NULL);
   7.161 +            if (!group_keys) {
   7.162 +                free_identity(partner);
   7.163 +                return PEP_OUT_OF_MEMORY;
   7.164 +            }
   7.165 +            extra = (void *) group_keys;
   7.166 +            event = GroupKeys;
   7.167 +            break;
   7.168 +
   7.169 +        default:
   7.170 +            return PEP_SYNC_ILLEGAL_MESSAGE;
   7.171 +    }
   7.172 +
   7.173 +    return fsm_DeviceState_inject(session, event, partner, extra);
   7.174 +}
   7.175 +
     8.1 --- a/src/sync_driver.c	Sun Jul 31 09:04:42 2016 +0200
     8.2 +++ b/src/sync_driver.c	Sun Jul 31 19:38:23 2016 +0200
     8.3 @@ -8,14 +8,16 @@
     8.4          PEP_SESSION session,
     8.5          DeviceState_event event,
     8.6          Identity partner,
     8.7 -        DeviceState_state state_partner
     8.8 +        void *extra
     8.9      )
    8.10  {
    8.11 -    PEP_STATUS status = PEP_STATUS_OK;
    8.12 +    assert(session);
    8.13 +    if (!session)
    8.14 +        return PEP_ILLEGAL_VALUE;
    8.15  
    8.16      session->sync_state = fsm_DeviceState(session, session->sync_state,
    8.17 -            event, partner, state_partner);
    8.18 +            event, partner, extra);
    8.19  
    8.20 -    return status;
    8.21 +    return PEP_STATUS_OK;
    8.22  }
    8.23  
     9.1 --- a/src/sync_fsm.c	Sun Jul 31 09:04:42 2016 +0200
     9.2 +++ b/src/sync_fsm.c	Sun Jul 31 19:38:23 2016 +0200
     9.3 @@ -7,90 +7,96 @@
     9.4          DeviceState_state state,
     9.5          DeviceState_event event,
     9.6          Identity partner,
     9.7 -        DeviceState_state state_partner
     9.8 +        void *extra
     9.9      )
    9.10  {
    9.11      switch (state) {
    9.12 -    case InitState:
    9.13 -        switch (event) {
    9.14 -            case Init:
    9.15 -                return Sole;
    9.16 -        default:
    9.17 -            return (DeviceState_state) invalid_event;
    9.18 -        }
    9.19 -        break;
    9.20 -    
    9.21 -    case Sole:
    9.22 -        switch (event) {
    9.23 -            case KeyGen:
    9.24 -                sendBeacon(session, state, NULL, NULL);
    9.25 -                break;
    9.26 -            case CannotDecrypt:
    9.27 -                sendBeacon(session, state, NULL, NULL);
    9.28 -                break;
    9.29 -            case Beacon:
    9.30 -                sendHandshakeRequest(session, state, partner, NULL);
    9.31 -                break;
    9.32 -            case HandshakeRequest:
    9.33 -                sendHandshakeRequest(session, state, partner, NULL);
    9.34 -                return HandshakingSole;
    9.35 -        default:
    9.36 -            return (DeviceState_state) invalid_event;
    9.37 -        }
    9.38 -        break;
    9.39 -    
    9.40 -    case HandshakingSole:
    9.41 -        switch (event) {
    9.42 -            case Init:
    9.43 -                showHandshake(session, state, partner, NULL);
    9.44 -                break;
    9.45 -            case HandshakeRejected:
    9.46 -                reject(session, state, partner, NULL);
    9.47 -                return Sole;
    9.48 -            case HandshakeAccepted:
    9.49 -                return WaitForGroupKeys;
    9.50 -        default:
    9.51 -            return (DeviceState_state) invalid_event;
    9.52 -        }
    9.53 -        break;
    9.54 -    
    9.55 -    case WaitForGroupKeys:
    9.56 -        switch (event) {
    9.57 -            case GroupKeys:
    9.58 -                storeGroupKeys(session, state, partner, NULL);
    9.59 -                return Grouped;
    9.60 -            case Cancel:
    9.61 -                return Sole;
    9.62 -            case Reject:
    9.63 -                reject(session, state, partner, NULL);
    9.64 -                return Sole;
    9.65 -        default:
    9.66 -            return (DeviceState_state) invalid_event;
    9.67 -        }
    9.68 -        break;
    9.69 -    
    9.70 -    case Grouped:
    9.71 -        switch (event) {
    9.72 -            case KeyGen:
    9.73 -                sendGroupKeys(session, state, NULL, NULL);
    9.74 -                break;
    9.75 -            case HandshakeRequest:
    9.76 -                sendHandshakeRequest(session, state, partner, NULL);
    9.77 -                showHandshake(session, state, partner, NULL);
    9.78 -                break;
    9.79 -            case HandshakeRejected:
    9.80 -                reject(session, state, partner, NULL);
    9.81 -                break;
    9.82 -            case Hand:
    9.83 -                break;
    9.84 -            case Reject:
    9.85 -                reject(session, state, NULL, NULL);
    9.86 -                break;
    9.87 -        default:
    9.88 -            return (DeviceState_state) invalid_event;
    9.89 -        }
    9.90 -        break;
    9.91 -    
    9.92 +        case InitState:
    9.93 +            switch (event) {
    9.94 +                case Init:
    9.95 +                    if (storedGroupKeys(session)) {
    9.96 +                        return Grouped;
    9.97 +                    }
    9.98 +                    return Sole;
    9.99 +                default:
   9.100 +                    return (DeviceState_state) invalid_event;
   9.101 +            }
   9.102 +            break;
   9.103 +        
   9.104 +        case Sole:
   9.105 +            switch (event) {
   9.106 +                case KeyGen:
   9.107 +                    sendBeacon(session, state, NULL, NULL);
   9.108 +                    break;
   9.109 +                case CannotDecrypt:
   9.110 +                    sendBeacon(session, state, NULL, NULL);
   9.111 +                    break;
   9.112 +                case Beacon:
   9.113 +                    sendHandshakeRequest(session, state, partner, NULL);
   9.114 +                    break;
   9.115 +                case HandshakeRequest:
   9.116 +                    sendHandshakeRequest(session, state, partner, NULL);
   9.117 +                    return HandshakingSole;
   9.118 +                default:
   9.119 +                    return (DeviceState_state) invalid_event;
   9.120 +            }
   9.121 +            break;
   9.122 +        
   9.123 +        case HandshakingSole:
   9.124 +            switch (event) {
   9.125 +                case Init:
   9.126 +                    showHandshake(session, state, partner, NULL);
   9.127 +                    break;
   9.128 +                case HandshakeRejected:
   9.129 +                    reject(session, state, partner, NULL);
   9.130 +                    return Sole;
   9.131 +                case HandshakeAccepted:
   9.132 +                    if (keyElectionWon(session, partner)) {
   9.133 +                        return Grouped;
   9.134 +                    }
   9.135 +                    return WaitForGroupKeys;
   9.136 +                default:
   9.137 +                    return (DeviceState_state) invalid_event;
   9.138 +            }
   9.139 +            break;
   9.140 +        
   9.141 +        case WaitForGroupKeys:
   9.142 +            switch (event) {
   9.143 +                case GroupKeys:
   9.144 +                    storeGroupKeys(session, state, partner, NULL);
   9.145 +                    return Grouped;
   9.146 +                case Cancel:
   9.147 +                    return Sole;
   9.148 +                case Reject:
   9.149 +                    reject(session, state, partner, NULL);
   9.150 +                    return Sole;
   9.151 +                default:
   9.152 +                    return (DeviceState_state) invalid_event;
   9.153 +            }
   9.154 +            break;
   9.155 +        
   9.156 +        case Grouped:
   9.157 +            switch (event) {
   9.158 +                case KeyGen:
   9.159 +                    sendGroupKeys(session, state, NULL, NULL);
   9.160 +                    break;
   9.161 +                case HandshakeRequest:
   9.162 +                    sendHandshakeRequest(session, state, partner, NULL);
   9.163 +                    showHandshake(session, state, partner, NULL);
   9.164 +                    break;
   9.165 +                case HandshakeRejected:
   9.166 +                    reject(session, state, partner, NULL);
   9.167 +                    break;
   9.168 +                case Hand:
   9.169 +                    break;
   9.170 +                case Reject:
   9.171 +                    reject(session, state, NULL, NULL);
   9.172 +                    break;
   9.173 +                default:
   9.174 +                    return (DeviceState_state) invalid_event;
   9.175 +            }
   9.176 +            break;
   9.177 +        
   9.178          default:
   9.179              return (DeviceState_state) invalid_state;
   9.180      }
    10.1 --- a/src/sync_fsm.h	Sun Jul 31 09:04:42 2016 +0200
    10.2 +++ b/src/sync_fsm.h	Sun Jul 31 19:38:23 2016 +0200
    10.3 @@ -3,6 +3,7 @@
    10.4  // state machine for DeviceState
    10.5  
    10.6  #include "pEpEngine.h"
    10.7 +#include "../asn.1/DeviceGroup-Protocol.h"
    10.8  
    10.9  #ifdef __cplusplus
   10.10  extern "C" {
   10.11 @@ -21,10 +22,15 @@
   10.12      invalid_event = -3
   10.13  } fsm_error;
   10.14  
   10.15 +// conditions
   10.16 +
   10.17 +bool storedGroupKeys(PEP_SESSION session);
   10.18 +bool keyElectionWon(PEP_SESSION session, Identity partner);
   10.19 +
   10.20  // states
   10.21  
   10.22  typedef enum _DeviceState_state {
   10.23 -    DeviceState_state_NONE = -1,
   10.24 +    DeviceState_state_NONE = 0,
   10.25      InitState, 
   10.26      Sole, 
   10.27      HandshakingSole, 
   10.28 @@ -35,11 +41,11 @@
   10.29  // events
   10.30  
   10.31  typedef enum _DeviceState_event {
   10.32 -    DeviceState_event_NONE = -1,
   10.33 -    Beacon = 1,
   10.34 -    HandshakeRequest = 2,
   10.35 -    GroupKeys = 3,
   10.36 -    Init, 
   10.37 +    DeviceState_event_NONE = 0,
   10.38 +    Init = 1,
   10.39 +    Beacon = 2,
   10.40 +    HandshakeRequest = 3,
   10.41 +    GroupKeys = 4,
   10.42      KeyGen, 
   10.43      CannotDecrypt, 
   10.44      HandshakeRejected, 
   10.45 @@ -58,6 +64,10 @@
   10.46  PEP_STATUS storeGroupKeys(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.47  PEP_STATUS sendGroupKeys(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.48  
   10.49 +// message receiver
   10.50 +
   10.51 +PEP_STATUS receive_DeviceState_msg(PEP_SESSION session, DeviceGroup_Protocol_t *msg);
   10.52 +
   10.53  // state machine
   10.54  
   10.55  DeviceState_state fsm_DeviceState(
   10.56 @@ -65,7 +75,7 @@
   10.57          DeviceState_state state,
   10.58          DeviceState_event event,
   10.59          Identity partner,
   10.60 -        DeviceState_state state_partner
   10.61 +        void *extra
   10.62      );
   10.63  
   10.64  // driver
   10.65 @@ -74,7 +84,7 @@
   10.66          PEP_SESSION session,
   10.67          DeviceState_event event,
   10.68          Identity partner,
   10.69 -        DeviceState_state state_partner
   10.70 +        void *extra
   10.71      );
   10.72  
   10.73  #ifdef __cplusplus
    11.1 --- a/src/sync_send_actions.c	Sun Jul 31 09:04:42 2016 +0200
    11.2 +++ b/src/sync_send_actions.c	Sun Jul 31 19:38:23 2016 +0200
    11.3 @@ -41,8 +41,10 @@
    11.4          return PEP_ILLEGAL_VALUE;
    11.5  
    11.6      assert(session->messageToSend);
    11.7 -    if (!session->messageToSend)
    11.8 -        return PEP_SEND_FUNCTION_NOT_REGISTERED;
    11.9 +    if (!session->messageToSend) {
   11.10 +        status = PEP_SEND_FUNCTION_NOT_REGISTERED;
   11.11 +        goto error;
   11.12 +    }
   11.13  
   11.14      msg = (Beacon_t *) calloc(1, sizeof(Beacon_t));
   11.15      assert(msg);
   11.16 @@ -55,7 +57,18 @@
   11.17          goto error;
   11.18      msg->header.sequence = (long) seq;
   11.19  
   11.20 -    msg->state = (long) state;
   11.21 +    bool devicegroup = storedGroupKeys(session);
   11.22 +    if (devicegroup) { // default is FALSE
   11.23 +        BOOLEAN_t *dg = malloc(sizeof(BOOLEAN_t));
   11.24 +        assert(dg);
   11.25 +        if (!dg)
   11.26 +            goto enomem;
   11.27 +
   11.28 +        *dg = 1;
   11.29 +        msg->header.devicegroup = dg;
   11.30 +    }
   11.31 +
   11.32 +    msg->header.state = (long) state;
   11.33  
   11.34      me = new_identity(NULL, NULL, NULL, NULL);
   11.35      if (!me)
   11.36 @@ -63,7 +76,7 @@
   11.37      status = myself(session, me);
   11.38      if (status != PEP_STATUS_OK)
   11.39          goto error;
   11.40 -    if (Identity_from_Struct(me, &msg->me) == NULL)
   11.41 +    if (Identity_from_Struct(me, &msg->header.me) == NULL)
   11.42          goto enomem;
   11.43  
   11.44      if (asn_check_constraints(&asn_DEF_Beacon, msg, NULL, NULL)) {
   11.45 @@ -90,7 +103,7 @@
   11.46  
   11.47      free_message(_message);
   11.48      ASN_STRUCT_FREE(asn_DEF_Beacon, msg);
   11.49 -
   11.50 +    free_identity(partner);
   11.51      return status;
   11.52  
   11.53  enomem:
   11.54 @@ -133,8 +146,10 @@
   11.55          return PEP_ILLEGAL_VALUE;
   11.56  
   11.57      assert(session->messageToSend);
   11.58 -    if (!session->messageToSend)
   11.59 -        return PEP_SEND_FUNCTION_NOT_REGISTERED;
   11.60 +    if (!session->messageToSend) {
   11.61 +        status = PEP_SEND_FUNCTION_NOT_REGISTERED;
   11.62 +        goto error;
   11.63 +    }
   11.64  
   11.65      msg = (HandshakeRequest_t *) calloc(1, sizeof(HandshakeRequest_t));
   11.66      assert(msg);
   11.67 @@ -147,7 +162,18 @@
   11.68          goto error;
   11.69      msg->header.sequence = (long) seq;
   11.70  
   11.71 -    msg->state = (long) state;
   11.72 +    bool devicegroup = storedGroupKeys(session);
   11.73 +    if (devicegroup) { // default is FALSE
   11.74 +        BOOLEAN_t *dg = malloc(sizeof(BOOLEAN_t));
   11.75 +        assert(dg);
   11.76 +        if (!dg)
   11.77 +            goto enomem;
   11.78 +
   11.79 +        *dg = 1;
   11.80 +        msg->header.devicegroup = dg;
   11.81 +    }
   11.82 +
   11.83 +    msg->header.state = (long) state;
   11.84  
   11.85      me = new_identity(NULL, NULL, NULL, NULL);
   11.86      if (!me)
   11.87 @@ -155,10 +181,7 @@
   11.88      status = myself(session, me);
   11.89      if (status != PEP_STATUS_OK)
   11.90          goto error;
   11.91 -    if (Identity_from_Struct(me, &msg->me) == NULL)
   11.92 -        goto enomem;
   11.93 -
   11.94 -    if (Identity_from_Struct(partner, &msg->partner) == NULL)
   11.95 +    if (Identity_from_Struct(me, &msg->header.me) == NULL)
   11.96          goto enomem;
   11.97  
   11.98      if (asn_check_constraints(&asn_DEF_HandshakeRequest, msg, NULL, NULL)) {
   11.99 @@ -185,7 +208,7 @@
  11.100  
  11.101      free_message(_message);
  11.102      ASN_STRUCT_FREE(asn_DEF_HandshakeRequest, msg);
  11.103 -
  11.104 +    free_identity(partner);
  11.105      return status;
  11.106  
  11.107  enomem:
  11.108 @@ -228,8 +251,10 @@
  11.109          return PEP_ILLEGAL_VALUE;
  11.110  
  11.111      assert(session->messageToSend);
  11.112 -    if (!session->messageToSend)
  11.113 -        return PEP_SEND_FUNCTION_NOT_REGISTERED;
  11.114 +    if (!session->messageToSend) {
  11.115 +        status = PEP_SEND_FUNCTION_NOT_REGISTERED;
  11.116 +        goto error;
  11.117 +    }
  11.118  
  11.119      msg = (GroupKeys_t *) calloc(1, sizeof(GroupKeys_t));
  11.120      assert(msg);
  11.121 @@ -242,7 +267,18 @@
  11.122          goto error;
  11.123      msg->header.sequence = (long) seq;
  11.124  
  11.125 -    msg->state = (long) state;
  11.126 +    bool devicegroup = storedGroupKeys(session);
  11.127 +    if (devicegroup) { // default is FALSE
  11.128 +        BOOLEAN_t *dg = malloc(sizeof(BOOLEAN_t));
  11.129 +        assert(dg);
  11.130 +        if (!dg)
  11.131 +            goto enomem;
  11.132 +
  11.133 +        *dg = 1;
  11.134 +        msg->header.devicegroup = dg;
  11.135 +    }
  11.136 +
  11.137 +    msg->header.state = (long) state;
  11.138  
  11.139      me = new_identity(NULL, NULL, NULL, NULL);
  11.140      if (!me)
  11.141 @@ -250,7 +286,7 @@
  11.142      status = myself(session, me);
  11.143      if (status != PEP_STATUS_OK)
  11.144          goto error;
  11.145 -    if (Identity_from_Struct(me, &msg->me) == NULL)
  11.146 +    if (Identity_from_Struct(me, &msg->header.me) == NULL)
  11.147          goto enomem;
  11.148  
  11.149      if (asn_check_constraints(&asn_DEF_GroupKeys, msg, NULL, NULL)) {
  11.150 @@ -277,7 +313,7 @@
  11.151  
  11.152      free_message(_message);
  11.153      ASN_STRUCT_FREE(asn_DEF_GroupKeys, msg);
  11.154 -
  11.155 +    free_identity(partner);
  11.156      return status;
  11.157  
  11.158  enomem:
    12.1 --- a/sync/devicegroup.fsm	Sun Jul 31 09:04:42 2016 +0200
    12.2 +++ b/sync/devicegroup.fsm	Sun Jul 31 19:38:23 2016 +0200
    12.3 @@ -10,9 +10,12 @@
    12.4      // all messages have a timestamp, time out and are removed after timeout
    12.5  
    12.6      fsm DeviceState filename=sync {
    12.7 +        condition storedGroupKeys();
    12.8 +        condition keyElectionWon(Identity partner);
    12.9 +
   12.10          state InitState {
   12.11              on Init {
   12.12 -                if (storedGroupKeys)
   12.13 +                if storedGroupKeys()
   12.14                      go Grouped;
   12.15                  go Sole;
   12.16              }
   12.17 @@ -78,10 +81,10 @@
   12.18                  do reject partner;
   12.19          }
   12.20  
   12.21 -        tag InitState 0;
   12.22 -        tag Beacon 1;
   12.23 -        tag HandshakeRequest 2;
   12.24 -        tag GroupKeys 3;
   12.25 +        tag Init 1;
   12.26 +        tag Beacon 2;
   12.27 +        tag HandshakeRequest 3;
   12.28 +        tag GroupKeys 4;
   12.29      }
   12.30  }
   12.31  
    13.1 --- a/sync/fsm.yml2	Sun Jul 31 09:04:42 2016 +0200
    13.2 +++ b/sync/fsm.yml2	Sun Jul 31 19:38:23 2016 +0200
    13.3 @@ -10,6 +10,6 @@
    13.4  decl event @name, on is event;
    13.5  decl transition @target, go is transition;
    13.6  decl action @name, do is action;
    13.7 -decl condition @flag, if is condition;
    13.8 +decl condition @name, if is condition;
    13.9  decl interface @name;
   13.10  decl tag @name (id);
    14.1 --- a/sync/gen_actions_skeleton.ysl2	Sun Jul 31 09:04:42 2016 +0200
    14.2 +++ b/sync/gen_actions_skeleton.ysl2	Sun Jul 31 19:38:23 2016 +0200
    14.3 @@ -111,13 +111,15 @@
    14.4  
    14.5              // working code
    14.6  
    14.7 -
    14.8 +            free_identity(partner);
    14.9 +            // free extra
   14.10              return status;
   14.11  
   14.12          enomem:
   14.13              status = PEP_OUT_OF_MEMORY;
   14.14          error:
   14.15 -            // free...
   14.16 +            free_identity(partner);
   14.17 +            // free extra
   14.18              return status;
   14.19          }
   14.20  
   14.21 @@ -159,8 +161,10 @@
   14.22              `` call "paramcheck" with "partner", "parm/partner";
   14.23  
   14.24              assert(session->messageToSend);
   14.25 -            if (!session->messageToSend)
   14.26 -                return PEP_SEND_FUNCTION_NOT_REGISTERED;
   14.27 +            if (!session->messageToSend) {
   14.28 +                status = PEP_SEND_FUNCTION_NOT_REGISTERED;
   14.29 +                goto error;
   14.30 +            }
   14.31  
   14.32              msg = («$name»_t *) calloc(1, sizeof(«$name»_t));
   14.33              assert(msg);
   14.34 @@ -173,7 +177,18 @@
   14.35                  goto error;
   14.36              msg->header.sequence = (long) seq;
   14.37  
   14.38 -            msg->state = (long) state;
   14.39 +            bool devicegroup = storedGroupKeys(session);
   14.40 +            if (devicegroup) { // default is FALSE
   14.41 +                BOOLEAN_t *dg = malloc(sizeof(BOOLEAN_t));
   14.42 +                assert(dg);
   14.43 +                if (!dg)
   14.44 +                    goto enomem;
   14.45 +
   14.46 +                *dg = 1;
   14.47 +                msg->header.devicegroup = dg;
   14.48 +            }
   14.49 +
   14.50 +            msg->header.state = (long) state;
   14.51  
   14.52              me = new_identity(NULL, NULL, NULL, NULL);
   14.53              if (!me)
   14.54 @@ -181,18 +196,18 @@
   14.55              status = myself(session, me);
   14.56              if (status != PEP_STATUS_OK)
   14.57                  goto error;
   14.58 -            if (Identity_from_Struct(me, &msg->me) == NULL)
   14.59 +            if (Identity_from_Struct(me, &msg->header.me) == NULL)
   14.60                  goto enomem;
   14.61          ||
   14.62 -        if "parm or $name='OwnKeys'" |
   14.63 -        if "parm/partner"   |> if (Identity_from_Struct(partner, &msg->partner) == NULL)
   14.64 -        if "parm/partner"   |>> goto enomem;
   14.65 -        if "$name='OwnKeys'"|> stringlist_t *sl;
   14.66 -        if "$name='OwnKeys'"|> status = own_key_retrieve(session, &sl);
   14.67 -        if "$name='OwnKeys'"|> if (status != PEP_STATUS_OK)
   14.68 -        if "$name='OwnKeys'"|>> goto error;
   14.69 -        if "$name='OwnKeys'"|> if (KeyList_from_stringlist(sl, &msg->keylist) == NULL)
   14.70 -        if "$name='OwnKeys'"|>> goto enomem;
   14.71 +        if "$name='OwnKeys'" {
   14.72 +            |
   14.73 +            |> identity_list *kl;
   14.74 +            |> status = own_key_retrieve(session, &kl);
   14.75 +            |> if (status != PEP_STATUS_OK)
   14.76 +            |>> goto error;
   14.77 +            |> if (KeyList_from_stringlist(kl, &msg->keylist) == NULL)
   14.78 +            |>> goto enomem;
   14.79 +        }
   14.80          ||
   14.81  
   14.82              if (asn_check_constraints(&asn_DEF_«$name», msg, NULL, NULL)) {
   14.83 @@ -219,7 +234,8 @@
   14.84  
   14.85              free_message(_message);
   14.86              ASN_STRUCT_FREE(asn_DEF_«$name», msg);
   14.87 -
   14.88 +            free_identity(partner);
   14.89 +            `` if "$name='OwnKeys'" |> free_identity_list(kl);
   14.90              return status;
   14.91  
   14.92          enomem:
   14.93 @@ -229,6 +245,7 @@
   14.94              free(payload);
   14.95              free_message(_message);
   14.96              free_identity(me);
   14.97 +            `` if "$name='OwnKeys'" |> free_identity_list(kl);
   14.98              return status;
   14.99          }
  14.100  
    15.1 --- a/sync/gen_statemachine.ysl2	Sun Jul 31 09:04:42 2016 +0200
    15.2 +++ b/sync/gen_statemachine.ysl2	Sun Jul 31 19:38:23 2016 +0200
    15.3 @@ -29,6 +29,7 @@
    15.4          // state machine for «@name»
    15.5  
    15.6          #include "pEpEngine.h"
    15.7 +        #include "../asn.1/«../@name»-Protocol.h"
    15.8          
    15.9          #ifdef __cplusplus
   15.10          extern "C" {
   15.11 @@ -47,17 +48,21 @@
   15.12              invalid_event = -3
   15.13          } fsm_error;
   15.14  
   15.15 +        // conditions
   15.16 +
   15.17 +        `` for "func:distinctName(condition)" | bool «@name»(PEP_SESSION session`apply "parm", 0`);
   15.18 +
   15.19          // states
   15.20  
   15.21          typedef enum _«@name»_state {
   15.22 -            «@name»_state_NONE = -1,
   15.23 +            «@name»_state_NONE = 0,
   15.24          `` for "func:distinctName(state)" |> «@name»`if "position()!=last()" > , `
   15.25          } «@name»_state;
   15.26  
   15.27          // events
   15.28  
   15.29          typedef enum _«@name»_event {
   15.30 -            «@name»_event_NONE = -1,
   15.31 +            «@name»_event_NONE = 0,
   15.32          ||
   15.33          for "func:distinctName(state/event[not(not(/protocol/fsm/tag/@name=@name))])" {
   15.34              const "name", "@name";
   15.35 @@ -73,6 +78,10 @@
   15.36          `` const "name", "@name"
   15.37          `` for "func:distinctName(//action)" | PEP_STATUS «@name»(PEP_SESSION session, «$name»_state state, Identity partner, void *extra);
   15.38  
   15.39 +        // message receiver
   15.40 +        
   15.41 +        PEP_STATUS receive_«@name»_msg(PEP_SESSION session, «../@name»_Protocol_t *msg);
   15.42 +
   15.43          // state machine
   15.44  
   15.45          «@name»_state fsm_«@name»(
   15.46 @@ -80,7 +89,7 @@
   15.47                  «@name»_state state,
   15.48                  «@name»_event event,
   15.49                  Identity partner,
   15.50 -                «@name»_state state_partner
   15.51 +                void *extra
   15.52              );
   15.53  
   15.54          // driver
   15.55 @@ -89,7 +98,7 @@
   15.56                  PEP_SESSION session,
   15.57                  «@name»_event event,
   15.58                  Identity partner,
   15.59 -                «@name»_state state_partner
   15.60 +                void *extra
   15.61              );
   15.62  
   15.63          #ifdef __cplusplus
   15.64 @@ -110,15 +119,17 @@
   15.65                  PEP_SESSION session,
   15.66                  «@name»_event event,
   15.67                  Identity partner,
   15.68 -                «@name»_state state_partner
   15.69 +                void *extra
   15.70              )
   15.71          {
   15.72 -            PEP_STATUS status = PEP_STATUS_OK;
   15.73 +            assert(session);
   15.74 +            if (!session)
   15.75 +                return PEP_ILLEGAL_VALUE;
   15.76  
   15.77              session->«@filename»_state = fsm_«@name»(session, session->«@filename»_state,
   15.78 -                    event, partner, state_partner);
   15.79 +                    event, partner, extra);
   15.80  
   15.81 -            return status;
   15.82 +            return PEP_STATUS_OK;
   15.83          }
   15.84  
   15.85          ||
   15.86 @@ -133,11 +144,11 @@
   15.87                  «@name»_state state,
   15.88                  «@name»_event event,
   15.89                  Identity partner,
   15.90 -                «@name»_state state_partner
   15.91 +                void *extra
   15.92              )
   15.93          {
   15.94              switch (state) {
   15.95 -                `` apply "state"
   15.96 +            `` apply "state", 2
   15.97                  default:
   15.98                      return («@name»_state) invalid_state;
   15.99              }
  15.100 @@ -153,8 +164,8 @@
  15.101      case «@name»:
  15.102          switch (event) {
  15.103          `` apply "event", 2
  15.104 -        default:
  15.105 -            return («../@name»_state) invalid_event;
  15.106 +            default:
  15.107 +                return («../@name»_state) invalid_event;
  15.108          }
  15.109          break;
  15.110  
  15.111 @@ -163,7 +174,7 @@
  15.112      template "event"
  15.113      ||
  15.114      case «@name»:
  15.115 -    `` apply "action|transition";
  15.116 +    `` apply "action|transition|condition";
  15.117      `` if "name(*[position()=last()]) != 'transition'" |> break;
  15.118      ||
  15.119  
  15.120 @@ -177,6 +188,19 @@
  15.121          > , NULL);\n
  15.122      }
  15.123  
  15.124 +    template "condition" {
  15.125 +        | if («@name»(session`apply "parm", 0`)) {
  15.126 +        apply "action|transition|condition";
  15.127 +        | }
  15.128 +    }
  15.129 +
  15.130 +    template "parm" choose {
  15.131 +        when "count(*) = 1"
  15.132 +            > , «name(*)»
  15.133 +        otherwise
  15.134 +            > , «name(*[1])» «name(*[2])»
  15.135 +    }
  15.136 +
  15.137      template "transition" | return «@target»;
  15.138  }
  15.139