merged default into ENGINE-178 ENGINE-178
authorKrista Grothoff <krista@pep-project.org>
Mon, 20 Feb 2017 15:29:07 +0100
branchENGINE-178
changeset 159337d5334bbb66
parent 1592 cc35fb239fce
parent 1589 c6dbfcea6e5a
child 1594 03ee060519ff
child 2705 2f29a3afff62
merged default into ENGINE-178
     1.1 --- a/asn.1/devicegroup.asn1	Mon Feb 20 15:22:58 2017 +0100
     1.2 +++ b/asn.1/devicegroup.asn1	Mon Feb 20 15:29:07 2017 +0100
     1.3 @@ -14,11 +14,13 @@
     1.4  Beacon ::= NULL
     1.5  
     1.6  HandshakeRequest ::= SEQUENCE {
     1.7 -    partner Identity /* identity of the receiver */
     1.8 +    partner-id     UTF8String  (SIZE(1..1024)) OPTIONAL,
     1.9 +    group-id       UTF8String  (SIZE(1..1024)) OPTIONAL
    1.10  }
    1.11  
    1.12  GroupKeys ::= SEQUENCE {
    1.13 -    partner Identity, /* identity of the receiver */
    1.14 +    partner-id     UTF8String  (SIZE(1..1024)) OPTIONAL,
    1.15 +    group-id       UTF8String  (SIZE(1..1024)) OPTIONAL,
    1.16      ownIdentities IdentityList
    1.17  }
    1.18  
     2.1 --- a/src/sync.h	Mon Feb 20 15:22:58 2017 +0100
     2.2 +++ b/src/sync.h	Mon Feb 20 15:29:07 2017 +0100
     2.3 @@ -160,6 +160,13 @@
     2.4          App displays trustwords, and requests user accept or reject
     2.5          App calls deliverHandshakeResult with user's answer
     2.6  
     2.7 +    SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE
     2.8 +        Device (me) is grouped and will leave current group to join another
     2.9 +        device's (partner) group.
    2.10 +        App displays trustwords, and requests user accept or reject
    2.11 +        App calls deliverHandshakeResult with user's answer
    2.12 +
    2.13 +
    2.14      SYNC_NOTIFY_TIMEOUT :
    2.15          KeySync operation timed out.
    2.16          Identities are set reflecting peers involved in aborted operation.
    2.17 @@ -173,6 +180,10 @@
    2.18          New group created.
    2.19          App displays message. No feedback to engine.
    2.20  
    2.21 +    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED
    2.22 +        New device was moved from one group to another.
    2.23 +        App displays message. No feedback to engine.
    2.24 +
    2.25     To deliver handshake result back to engine once user reacted,
    2.26     deliver_handshake_result is used. Result can be :
    2.27  
    2.28 @@ -224,13 +235,15 @@
    2.29      SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
    2.30      SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
    2.31      SYNC_NOTIFY_INIT_FORM_GROUP,
    2.32 +    SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE,
    2.33  
    2.34      // handshake process timed out
    2.35      SYNC_NOTIFY_TIMEOUT,
    2.36  
    2.37      // handshake accepted by user
    2.38      SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED,
    2.39 -    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED
    2.40 +    SYNC_NOTIFY_ACCEPTED_GROUP_CREATED,
    2.41 +    SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED
    2.42  
    2.43  } sync_handshake_signal;
    2.44  
     3.1 --- a/src/sync_actions.c	Mon Feb 20 15:22:58 2017 +0100
     3.2 +++ b/src/sync_actions.c	Mon Feb 20 15:29:07 2017 +0100
     3.3 @@ -7,6 +7,7 @@
     3.4  #include "pEp_internal.h"
     3.5  #include "message.h"
     3.6  #include "sync_fsm.h"
     3.7 +#include "sync_impl.h"
     3.8  #include "map_asn1.h"
     3.9  #include "baseprotocol.h"
    3.10  
    3.11 @@ -39,15 +40,20 @@
    3.12      if (!(session && partner))
    3.13          return invalid_condition; // error
    3.14  
    3.15 -    // an already existing group always wins
    3.16 +    int partner_is_group = partner->flags & PEP_idf_devicegroup;
    3.17  
    3.18 -    if (deviceGrouped(session)) {
    3.19 -        assert(!(partner->flags & PEP_idf_devicegroup));
    3.20 -        return 1;
    3.21 +    if (deviceGrouped(session)){
    3.22 +        // existing group always wins against sole device
    3.23 +        if(!partner_is_group)
    3.24 +            return 1;
    3.25 +    } else {
    3.26 +        // sole device always loses against group
    3.27 +        if(partner_is_group)
    3.28 +            return 0;
    3.29      }
    3.30  
    3.31 -    if (partner->flags & PEP_idf_devicegroup)
    3.32 -        return 0;
    3.33 +    // two groups or two sole are elected based on key age
    3.34 +    // key created first wins
    3.35  
    3.36      Identity me = NULL;
    3.37      PEP_STATUS status = get_identity(session, partner->address, PEP_OWN_USERID,
    3.38 @@ -205,6 +211,39 @@
    3.39      return status;
    3.40  }
    3.41  
    3.42 +PEP_STATUS _storeGroupKeys(
    3.43 +        PEP_SESSION session,
    3.44 +        identity_list *group_keys
    3.45 +    )
    3.46 +{
    3.47 +    PEP_STATUS status = PEP_STATUS_OK;
    3.48 +
    3.49 +    for (identity_list *il = group_keys; il && il->ident; il = il->next) {
    3.50 +
    3.51 +        if (strcmp(il->ident->user_id, PEP_OWN_USERID)!=0) {
    3.52 +            assert(0);
    3.53 +            continue;
    3.54 +        }
    3.55 +        // Check that identity isn't excluded from sync.
    3.56 +        pEp_identity *stored_identity = NULL;
    3.57 +        status = get_identity(session, il->ident->address, PEP_OWN_USERID,
    3.58 +                &stored_identity);
    3.59 +        if (status == PEP_STATUS_OK) {
    3.60 +            if(stored_identity->flags & PEP_idf_not_for_sync){
    3.61 +                free_identity(stored_identity);
    3.62 +                continue;
    3.63 +            }
    3.64 +            free_identity(stored_identity);
    3.65 +        }
    3.66 +
    3.67 +        status = set_identity(session, il->ident);
    3.68 +        if (status != PEP_STATUS_OK)
    3.69 +            break;
    3.70 +    }
    3.71 +
    3.72 +    return status;
    3.73 +}
    3.74 +    
    3.75  
    3.76  // storeGroupKeys() - 
    3.77  //
    3.78 @@ -221,54 +260,75 @@
    3.79          PEP_SESSION session,
    3.80          DeviceState_state state,
    3.81          Identity partner,
    3.82 -        void *_group_keys
    3.83 +        void *group_keys_extra_
    3.84      )
    3.85  {
    3.86      PEP_STATUS status = PEP_STATUS_OK;
    3.87  
    3.88      assert(session);
    3.89      assert(partner);
    3.90 -    assert(_group_keys);
    3.91 -    if (!(session && partner && _group_keys))
    3.92 +    assert(group_keys_extra_);
    3.93 +    if (!(session && partner && group_keys_extra_))
    3.94          return PEP_ILLEGAL_VALUE;
    3.95  
    3.96 -    identity_list *group_keys = (identity_list *) _group_keys;
    3.97 +    group_keys_extra_t *group_keys_extra = 
    3.98 +        (group_keys_extra_t*) group_keys_extra_;
    3.99 +    identity_list *group_keys = group_keys_extra->group_keys;
   3.100 +    char *group_id = group_keys_extra->group_id;
   3.101  
   3.102 -    for (identity_list *il = group_keys; il && il->ident; il = il->next) {
   3.103 +    status = _storeGroupKeys(session, group_keys);
   3.104 +    if (status != PEP_STATUS_OK)
   3.105 +        return status;
   3.106  
   3.107 -        // Check that identity isn't excluded from sync.
   3.108 -        pEp_identity *stored_identity = NULL;
   3.109 -        status = get_identity(session, il->ident->address, PEP_OWN_USERID,
   3.110 -                &stored_identity);
   3.111 -        if (status == PEP_STATUS_OK) {
   3.112 -            if(stored_identity->flags & PEP_idf_not_for_sync){
   3.113 -                free_identity(stored_identity);
   3.114 -                continue;
   3.115 -            }
   3.116 -            free_identity(stored_identity);
   3.117 -        }
   3.118 +    // set group id according to given group-id
   3.119 +    status = set_device_group(session, group_id);
   3.120 +    if (status != PEP_STATUS_OK)
   3.121 +        return status;
   3.122 +    
   3.123 +    // change sync_uuid when entering group 
   3.124 +    // thus ignoring unprocessed handshakes
   3.125 +    // addressed to previous self (sole) once in.
   3.126 +    pEpUUID uuid;
   3.127 +    uuid_generate_random(uuid);
   3.128 +    uuid_unparse_upper(uuid, session->sync_uuid);
   3.129  
   3.130 -        free(il->ident->user_id);
   3.131 -        il->ident->user_id = strdup(PEP_OWN_USERID);
   3.132 -        assert(il->ident->user_id);
   3.133 -        if (!il->ident->user_id)
   3.134 -            goto enomem;
   3.135 -        status = set_identity(session, il->ident);
   3.136 -        if (status != PEP_STATUS_OK)
   3.137 -            break;
   3.138 -    }
   3.139 -
   3.140 -    free_identity_list(group_keys);
   3.141 -    
   3.142 -    return status;
   3.143 -
   3.144 -enomem:
   3.145 -    status = PEP_OUT_OF_MEMORY;
   3.146 -    free_identity_list(group_keys);
   3.147      return status;
   3.148  }
   3.149  
   3.150 -// enterGroup() - 
   3.151 +// storeGroupUpdate() - 
   3.152 +//
   3.153 +//  params:
   3.154 +//      session (in)        session handle
   3.155 +//      state (in)          state the state machine is in
   3.156 +//      partner (in)        partner to communicate with
   3.157 +//      _group_keys (in)    group keys received from partner
   3.158 +//
   3.159 +//  returns:
   3.160 +//      PEP_STATUS_OK or any other value on error
   3.161 +
   3.162 +PEP_STATUS storeGroupUpdate(
   3.163 +        PEP_SESSION session,
   3.164 +        DeviceState_state state,
   3.165 +        Identity partner,
   3.166 +        void *group_keys_
   3.167 +    )
   3.168 +{
   3.169 +    PEP_STATUS status = PEP_STATUS_OK;
   3.170 +
   3.171 +    assert(session);
   3.172 +    assert(partner);
   3.173 +    assert(group_keys_);
   3.174 +    if (!(session && partner && group_keys_))
   3.175 +        return PEP_ILLEGAL_VALUE;
   3.176 +
   3.177 +    identity_list *group_keys = (identity_list*) group_keys_;
   3.178 +
   3.179 +    status = _storeGroupKeys(session, group_keys);
   3.180 +
   3.181 +
   3.182 +    return status;
   3.183 +}
   3.184 +// makeGroup() - 
   3.185  //
   3.186  //  params:
   3.187  //      session (in)        session handle
   3.188 @@ -279,7 +339,7 @@
   3.189  //  returns:
   3.190  //      PEP_STATUS_OK or any other value on error
   3.191  
   3.192 -PEP_STATUS enterGroup(
   3.193 +PEP_STATUS makeGroup(
   3.194          PEP_SESSION session,
   3.195          DeviceState_state state,
   3.196          Identity partner,
   3.197 @@ -290,9 +350,6 @@
   3.198  
   3.199      assert(session);
   3.200  
   3.201 -    // groups have no uuid for now
   3.202 -    status = set_device_group(session, "1");
   3.203 -
   3.204      // change sync_uuid when entering group 
   3.205      // thus ignoring unprocessed handshakes
   3.206      // addressed to previous self (sole) once in.
   3.207 @@ -300,6 +357,9 @@
   3.208      uuid_generate_random(uuid);
   3.209      uuid_unparse_upper(uuid, session->sync_uuid);
   3.210      
   3.211 +    // take that new uuid as group-id
   3.212 +    status = set_device_group(session, session->sync_uuid);
   3.213 +
   3.214      return status;
   3.215  }
   3.216  
     4.1 --- a/src/sync_impl.c	Mon Feb 20 15:22:58 2017 +0100
     4.2 +++ b/src/sync_impl.c	Mon Feb 20 15:29:07 2017 +0100
     4.3 @@ -7,7 +7,6 @@
     4.4  // #define for the dllimport / dllexport DYNAMIC_API stuff.
     4.5  #include "pEp_internal.h"
     4.6  
     4.7 -#include "../asn.1/DeviceGroup-Protocol.h"
     4.8  #include "sync_impl.h"
     4.9  #include "keymanagement.h"
    4.10  #include "message_api.h"
    4.11 @@ -65,11 +64,28 @@
    4.12              case DeviceGroup_Protocol__payload_PR_handshakeRequest:
    4.13                  // re-check uuid in case sync_uuid changed while in the queue
    4.14                  if (strncmp(session->sync_uuid,
    4.15 -                            (const char *)msg->payload.choice.handshakeRequest.partner.user_id->buf,
    4.16 -                            msg->payload.choice.handshakeRequest.partner.user_id->size) != 0){
    4.17 +                            (const char *)msg->payload.choice.handshakeRequest.partner_id->buf,
    4.18 +                            msg->payload.choice.handshakeRequest.partner_id->size) != 0){
    4.19                      status = PEP_SYNC_ILLEGAL_MESSAGE;
    4.20                      goto error;
    4.21                  }
    4.22 +
    4.23 +                if(msgIsFromGroup) {
    4.24 +                    char *devgrp = NULL;
    4.25 +                    status = get_device_group(session, &devgrp);
    4.26 +
    4.27 +                    // if handshake request comes from same group ignore, ignore it
    4.28 +                    if (status == PEP_STATUS_OK && devgrp && devgrp[0] &&
    4.29 +                        strncmp(devgrp,
    4.30 +                                (const char *)msg->payload.choice.handshakeRequest.group_id->buf,
    4.31 +                                msg->payload.choice.handshakeRequest.group_id->size) != 0){
    4.32 +                        status = PEP_SYNC_ILLEGAL_MESSAGE;
    4.33 +                        goto error;
    4.34 +                    }
    4.35 +                    free(devgrp);
    4.36 +                    // if it comes from another group, then this is groupmerge
    4.37 +                }
    4.38 +
    4.39                  event = HandshakeRequest;
    4.40                  break;
    4.41  
    4.42 @@ -78,31 +94,62 @@
    4.43                  break;
    4.44  
    4.45              case DeviceGroup_Protocol__payload_PR_groupKeys:
    4.46 +            {
    4.47                  // re-check uuid in case sync_uuid changed while in the queue
    4.48                  if (strncmp(session->sync_uuid,
    4.49 -                            (const char *)msg->payload.choice.groupKeys.partner.user_id->buf,
    4.50 -                            msg->payload.choice.groupKeys.partner.user_id->size) != 0){
    4.51 +                            (const char *)msg->payload.choice.groupKeys.partner_id->buf,
    4.52 +                            msg->payload.choice.groupKeys.partner_id->size) != 0){
    4.53                      status = PEP_SYNC_ILLEGAL_MESSAGE;
    4.54                      goto error;
    4.55                  }
    4.56 -                // no break
    4.57 +                group_keys_extra_t *group_keys_extra;
    4.58 +                group_keys_extra = malloc(sizeof(group_keys_extra_t));
    4.59 +                if(group_keys_extra == NULL){
    4.60 +                    status = PEP_OUT_OF_MEMORY;
    4.61 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    4.62 +                    goto error;
    4.63 +                }
    4.64 +
    4.65 +                char *group_id = strndup(
    4.66 +                        (char*)msg->payload.choice.groupKeys.group_id->buf,
    4.67 +                        msg->payload.choice.groupKeys.group_id->size);
    4.68 +
    4.69 +                if (msg->payload.choice.groupKeys.group_id && !group_id){
    4.70 +                    status = PEP_OUT_OF_MEMORY;
    4.71 +                    free(group_keys_extra);
    4.72 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    4.73 +                    goto error;
    4.74 +                }
    4.75 +                group_keys_extra->group_id = group_id;
    4.76 +
    4.77 +                identity_list *group_keys = IdentityList_to_identity_list(
    4.78 +                        &msg->payload.choice.groupKeys.ownIdentities,
    4.79 +                        NULL);
    4.80 +                if (!group_keys) {
    4.81 +                    status = PEP_OUT_OF_MEMORY;
    4.82 +                    free(group_id);
    4.83 +                    free(group_keys_extra);
    4.84 +                    ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
    4.85 +                    goto error;
    4.86 +                }
    4.87 +                group_keys_extra->group_keys = group_keys;
    4.88 +
    4.89 +                extra = (void *) group_keys_extra;
    4.90 +                event = GroupKeys;
    4.91 +
    4.92 +                break;
    4.93 +            }
    4.94              case DeviceGroup_Protocol__payload_PR_groupUpdate:
    4.95              {
    4.96                  identity_list *group_keys = IdentityList_to_identity_list(
    4.97 -                        msg->payload.present == 
    4.98 -                          DeviceGroup_Protocol__payload_PR_groupKeys ?
    4.99 -                            &msg->payload.choice.groupKeys.ownIdentities :
   4.100 -                            &msg->payload.choice.groupUpdate.ownIdentities,
   4.101 -                        NULL);
   4.102 +                        &msg->payload.choice.groupUpdate.ownIdentities, NULL);
   4.103                  if (!group_keys) {
   4.104                      status = PEP_OUT_OF_MEMORY;
   4.105                      ASN_STRUCT_FREE(asn_DEF_DeviceGroup_Protocol, msg);
   4.106                      goto error;
   4.107                  }
   4.108                  extra = (void *) group_keys;
   4.109 -                event = msg->payload.present == 
   4.110 -                          DeviceGroup_Protocol__payload_PR_groupKeys ?
   4.111 -                            GroupKeys : GroupUpdate;
   4.112 +                event = GroupUpdate;
   4.113                  break;
   4.114              }
   4.115  
   4.116 @@ -143,7 +190,6 @@
   4.117      if(last != NULL){
   4.118          time_t now = time(NULL);
   4.119          if(*last != 0 && (*last + SYNC_INHIBIT_TIME) > now ){
   4.120 -            free_identity(partner);
   4.121              status = PEP_STATEMACHINE_INHIBITED_EVENT;
   4.122              goto error;
   4.123          }
   4.124 @@ -205,9 +251,32 @@
   4.125  
   4.126      status = fsm_DeviceState_inject(session, event, partner, extra, timeout);
   4.127  
   4.128 +error:
   4.129 +
   4.130      free_identity(partner);
   4.131  
   4.132 -error:
   4.133 +    switch(event){
   4.134 +        case GroupKeys:
   4.135 +        {
   4.136 +            group_keys_extra_t *group_keys_extra = (group_keys_extra_t*) extra;
   4.137 +            identity_list *group_keys = group_keys_extra->group_keys;
   4.138 +            char *group_id = group_keys_extra->group_id;
   4.139 +            free_identity_list(group_keys);
   4.140 +            free(group_id);
   4.141 +            free(group_keys_extra);
   4.142 +            break;
   4.143 +        }
   4.144 +        case GroupUpdate:
   4.145 +        {
   4.146 +            identity_list *group_keys = (identity_list*) extra;
   4.147 +            free_identity_list(group_keys);
   4.148 +            break;
   4.149 +        }
   4.150 +        default:
   4.151 +            assert(extra==NULL);
   4.152 +            break;
   4.153 +    }
   4.154 +
   4.155      free(sync_msg);
   4.156  
   4.157      return status;
   4.158 @@ -374,8 +443,8 @@
   4.159                          case DeviceGroup_Protocol__payload_PR_handshakeRequest:
   4.160                              if (rating < PEP_rating_reliable ||
   4.161                                  strncmp(session->sync_uuid,
   4.162 -                                        (const char *)msg->payload.choice.handshakeRequest.partner.user_id->buf,
   4.163 -                                        msg->payload.choice.handshakeRequest.partner.user_id->size) != 0){
   4.164 +                                        (const char *)msg->payload.choice.handshakeRequest.partner_id->buf,
   4.165 +                                        msg->payload.choice.handshakeRequest.partner_id->size) != 0){
   4.166                                  discard = true;
   4.167                                  goto free_all;
   4.168                              }
   4.169 @@ -387,8 +456,8 @@
   4.170                              if (!keylist || rating < PEP_rating_reliable ||
   4.171                                  // message is only consumed by instance it is addressed to
   4.172                                  (strncmp(session->sync_uuid,
   4.173 -                                        (const char *)msg->payload.choice.groupKeys.partner.user_id->buf,
   4.174 -                                        msg->payload.choice.groupKeys.partner.user_id->size) != 0)){
   4.175 +                                        (const char *)msg->payload.choice.groupKeys.partner_id->buf,
   4.176 +                                        msg->payload.choice.groupKeys.partner_id->size) != 0)){
   4.177                                  discard = true;
   4.178                                  goto free_all;
   4.179                              }
     5.1 --- a/src/sync_impl.h	Mon Feb 20 15:22:58 2017 +0100
     5.2 +++ b/src/sync_impl.h	Mon Feb 20 15:29:07 2017 +0100
     5.3 @@ -3,6 +3,7 @@
     5.4  
     5.5  #pragma once
     5.6  
     5.7 +#include "../asn.1/DeviceGroup-Protocol.h"
     5.8  #include "message.h"
     5.9  #include "sync.h"
    5.10  #include "sync_fsm.h"
    5.11 @@ -11,6 +12,11 @@
    5.12  extern "C" {
    5.13  #endif
    5.14  
    5.15 +typedef struct _group_keys_extra {
    5.16 +    identity_list *group_keys;
    5.17 +    char *group_id;
    5.18 +} group_keys_extra_t;
    5.19 +
    5.20  PEP_STATUS receive_sync_msg(
    5.21          PEP_SESSION session,
    5.22          sync_msg_t *sync_msg,
     6.1 --- a/sync/devicegroup.fsm	Mon Feb 20 15:22:58 2017 +0100
     6.2 +++ b/sync/devicegroup.fsm	Mon Feb 20 15:29:07 2017 +0100
     6.3 @@ -82,14 +82,17 @@
     6.4                  go Sole;
     6.5              }
     6.6              on HandshakeAccepted(Identity partner) {
     6.7 -                do acceptHandshake(partner); 
     6.8 -                if keyElectionWon(partner) {
     6.9 -                    do enterGroup;
    6.10 -                    do sendGroupKeys(partner);
    6.11 -                    do notifyAcceptedGroupCreated(partner);
    6.12 -                    go Grouped;
    6.13 +                if sameIdentities(partner, expected) {
    6.14 +                    do acceptHandshake(partner); 
    6.15 +                    if keyElectionWon(partner) {
    6.16 +                        do makeGroup;
    6.17 +                        do sendGroupKeys(partner);
    6.18 +                        do notifyAcceptedGroupCreated(partner);
    6.19 +                        go Grouped;
    6.20 +                    }
    6.21 +                    go WaitForGroupKeysSole(partner);
    6.22                  }
    6.23 -                go WaitForGroupKeysSole(partner);
    6.24 +                go Sole;
    6.25              }
    6.26              on Cancel go Sole;
    6.27              on Timeout {
    6.28 @@ -100,10 +103,9 @@
    6.29          }
    6.30      
    6.31          state WaitForGroupKeysSole timeout=600 (Identity expected) {
    6.32 -            on GroupKeys(Identity partner, Stringlist keys) {
    6.33 +            on GroupKeys(Identity partner, identity_list keys) {
    6.34                  if sameIdentities(partner, expected) {
    6.35                      do storeGroupKeys(partner, keys);
    6.36 -                    do enterGroup;
    6.37                      do sendGroupUpdate;
    6.38                      do notifyAcceptedDeviceAdded(partner);
    6.39                      go Grouped;
    6.40 @@ -118,8 +120,10 @@
    6.41          state Grouped end=1 {
    6.42              on KeyGen
    6.43                  do sendGroupUpdate;
    6.44 -            on CannotDecrypt
    6.45 +            on CannotDecrypt {
    6.46                  do sendUpdateRequest;
    6.47 +                do sendBeacon;
    6.48 +            }
    6.49              on UpdateRequest
    6.50                  do sendGroupUpdate;
    6.51              on Beacon(Identity partner){
    6.52 @@ -130,15 +134,17 @@
    6.53                  do sendHandshakeRequest(partner);
    6.54                  go HandshakingGrouped(partner);
    6.55              }
    6.56 -            on GroupUpdate(Identity partner, Stringlist keys)
    6.57 -                do storeGroupKeys(partner, keys);
    6.58 +            on GroupUpdate(Identity partner, identity_list keys)
    6.59 +                do storeGroupUpdate(partner, keys);
    6.60          }
    6.61  
    6.62          state GroupedBeaconed timeout=600 (Identity expected){
    6.63              on KeyGen
    6.64                  do sendGroupUpdate;
    6.65 -            on CannotDecrypt
    6.66 +            on CannotDecrypt {
    6.67                  do sendUpdateRequest;
    6.68 +                do sendBeacon;
    6.69 +            }
    6.70              on UpdateRequest
    6.71                  do sendGroupUpdate;
    6.72              on Beacon(Identity partner){
    6.73 @@ -153,27 +159,49 @@
    6.74                  }
    6.75                  go HandshakingGrouped(partner);
    6.76              }
    6.77 -            on GroupUpdate(Identity partner, Stringlist keys)
    6.78 -                do storeGroupKeys(partner, keys);
    6.79 +            on GroupUpdate(Identity partner, identity_list keys)
    6.80 +                do storeGroupUpdate(partner, keys);
    6.81              on Timeout go Grouped;
    6.82          }
    6.83  
    6.84          state HandshakingGrouped timeout=600 (Identity expected) {
    6.85 -            on Init
    6.86 -                do notifyInitAddOurDevice(partner);
    6.87 +            // HandshakeRequest from same group are filtered in receive_sync_msg
    6.88 +            on Init{
    6.89 +                if keyElectionWon(partner) {
    6.90 +                    do notifyInitAddOtherDevice(partner);
    6.91 +                } else {
    6.92 +                    do notifyInitMoveOurDevice(partner);
    6.93 +                }
    6.94 +            }
    6.95              on HandshakeRejected(Identity partner) {
    6.96                  do rejectHandshake(partner);             // stores rejection of partner
    6.97                  go Grouped;
    6.98              }
    6.99              on HandshakeAccepted(Identity partner) {
   6.100                  do acceptHandshake(partner); 
   6.101 -
   6.102 -                // an already existing group always wins
   6.103 -                do sendGroupKeys(partner);
   6.104 -
   6.105 +                if keyElectionWon(partner) {
   6.106 +                    do sendGroupKeys(partner);
   6.107 +                    do notifyAcceptedDeviceAdded(partner);
   6.108 +                    go Grouped;
   6.109 +                }
   6.110 +                go WaitForGroupKeysGrouped(partner);
   6.111 +            }
   6.112 +            on Cancel go Grouped;
   6.113 +            on Timeout {
   6.114 +                do notifyTimeout(expected);
   6.115                  go Grouped;
   6.116              }
   6.117 -            on Cancel go Grouped;
   6.118 +        }
   6.119 +
   6.120 +        state WaitForGroupKeysGrouped timeout=600 (Identity expected) {
   6.121 +            on GroupKeys(Identity partner, identity_list keys) {
   6.122 +                if sameIdentities(partner, expected) {
   6.123 +                    do storeGroupKeys(partner, keys);
   6.124 +                    do sendGroupUpdate;
   6.125 +                    do notifyAcceptedDeviceMoved(partner);
   6.126 +                    go Grouped;
   6.127 +                }
   6.128 +            }
   6.129              on Timeout {
   6.130                  do notifyTimeout(expected);
   6.131                  go Grouped;
     7.1 --- a/sync/gen_actions.ysl2	Mon Feb 20 15:22:58 2017 +0100
     7.2 +++ b/sync/gen_actions.ysl2	Mon Feb 20 15:29:07 2017 +0100
     7.3 @@ -198,9 +198,21 @@
     7.4          choose {
     7.5              when "$name='GroupKeys' or $name='HandshakeRequest'" {
     7.6                  |
     7.7 -                |> if (Identity_from_Struct(partner,
     7.8 -                |>                          &msg->payload.choice.«$lname».partner) == NULL)
     7.9 -                |>> goto enomem;
    7.10 +                |> msg->payload.choice.«$lname».partner_id = 
    7.11 +                |>     OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
    7.12 +                |>                              partner->user_id, -1);
    7.13 +                |> if (partner->user_id && !msg->payload.choice.«$lname».partner_id)
    7.14 +                |>    goto enomem;
    7.15 +                |
    7.16 +                |> char *devgrp = NULL;
    7.17 +                |> status = get_device_group(session, &devgrp);
    7.18 +                |> if (status == PEP_STATUS_OK && devgrp && devgrp[0])
    7.19 +                |> msg->payload.choice.«$lname».group_id = 
    7.20 +                |>     OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
    7.21 +                |>                              devgrp, -1);
    7.22 +                |> free(devgrp);
    7.23 +                |> if (devgrp && !msg->payload.choice.«$lname».partner_id)
    7.24 +                |>    goto enomem;
    7.25              }
    7.26          }
    7.27          ||
     8.1 --- a/sync/gen_statemachine.ysl2	Mon Feb 20 15:22:58 2017 +0100
     8.2 +++ b/sync/gen_statemachine.ysl2	Mon Feb 20 15:29:07 2017 +0100
     8.3 @@ -42,7 +42,6 @@
     8.4  
     8.5          typedef pEp_identity * Identity;
     8.6          typedef stringlist_t * Stringlist;
     8.7 -        typedef union _param { Identity partner; stringlist_t *keylist; } param_t;
     8.8  
     8.9          // error values
    8.10  
     9.1 --- a/sync/generated/sync_fsm.c	Mon Feb 20 15:22:58 2017 +0100
     9.2 +++ b/sync/generated/sync_fsm.c	Mon Feb 20 15:29:07 2017 +0100
     9.3 @@ -257,53 +257,69 @@
     9.4                  case HandshakeAccepted:
     9.5                  {
     9.6                      DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingSole", "event=HandshakeAccepted")
     9.7 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=acceptHandshake")
     9.8 -                    status = acceptHandshake(session, state, partner, NULL);
     9.9 -                    if (status == PEP_OUT_OF_MEMORY)
    9.10 -                        return (int) invalid_out_of_memory;
    9.11 -                    if (status != PEP_STATUS_OK)
    9.12 -                        return (int) invalid_action;
    9.13 -                    cond_result = keyElectionWon(session, partner);
    9.14 +                    cond_result = sameIdentities(session, partner, expected);
    9.15                      #ifndef NDEBUG
    9.16                      char resstr[11] = {0,};
    9.17                      snprintf(resstr,10,"result=%d",cond_result);
    9.18                      #endif
    9.19 -                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted, condition=keyElectionWon", resstr)
    9.20 +                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted, condition=sameIdentities", resstr)
    9.21                      if (cond_result < 0)
    9.22                          return cond_result;
    9.23                      if (cond_result) {
    9.24 -                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=enterGroup")
    9.25 -                        status = enterGroup(session, state, NULL, NULL);
    9.26 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=acceptHandshake")
    9.27 +                        status = acceptHandshake(session, state, partner, NULL);
    9.28                          if (status == PEP_OUT_OF_MEMORY)
    9.29                              return (int) invalid_out_of_memory;
    9.30                          if (status != PEP_STATUS_OK)
    9.31                              return (int) invalid_action;
    9.32 -                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=sendGroupKeys")
    9.33 -                        status = sendGroupKeys(session, state, partner, NULL);
    9.34 -                        if (status == PEP_OUT_OF_MEMORY)
    9.35 -                            return (int) invalid_out_of_memory;
    9.36 -                        if (status != PEP_STATUS_OK)
    9.37 -                            return (int) invalid_action;
    9.38 -                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=notifyAcceptedGroupCreated")
    9.39 -                        status = notifyAcceptedGroupCreated(session, state, partner, NULL);
    9.40 -                        if (status == PEP_OUT_OF_MEMORY)
    9.41 -                            return (int) invalid_out_of_memory;
    9.42 -                        if (status != PEP_STATUS_OK)
    9.43 -                            return (int) invalid_action;
    9.44 +                        cond_result = keyElectionWon(session, partner);
    9.45 +                        #ifndef NDEBUG
    9.46 +                        char resstr[11] = {0,};
    9.47 +                        snprintf(resstr,10,"result=%d",cond_result);
    9.48 +                        #endif
    9.49 +                        DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted, condition=keyElectionWon", resstr)
    9.50 +                        if (cond_result < 0)
    9.51 +                            return cond_result;
    9.52 +                        if (cond_result) {
    9.53 +                            DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=makeGroup")
    9.54 +                            status = makeGroup(session, state, NULL, NULL);
    9.55 +                            if (status == PEP_OUT_OF_MEMORY)
    9.56 +                                return (int) invalid_out_of_memory;
    9.57 +                            if (status != PEP_STATUS_OK)
    9.58 +                                return (int) invalid_action;
    9.59 +                            DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=sendGroupKeys")
    9.60 +                            status = sendGroupKeys(session, state, partner, NULL);
    9.61 +                            if (status == PEP_OUT_OF_MEMORY)
    9.62 +                                return (int) invalid_out_of_memory;
    9.63 +                            if (status != PEP_STATUS_OK)
    9.64 +                                return (int) invalid_action;
    9.65 +                            DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "action=notifyAcceptedGroupCreated")
    9.66 +                            status = notifyAcceptedGroupCreated(session, state, partner, NULL);
    9.67 +                            if (status == PEP_OUT_OF_MEMORY)
    9.68 +                                return (int) invalid_out_of_memory;
    9.69 +                            if (status != PEP_STATUS_OK)
    9.70 +                                return (int) invalid_action;
    9.71 +                            if(session->sync_state_payload){
    9.72 +                                free_identity((Identity)session->sync_state_payload);
    9.73 +                                session->sync_state_payload = NULL;
    9.74 +                            }
    9.75 +                            DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=Grouped")
    9.76 +                            return Grouped;
    9.77 +                        }
    9.78                          if(session->sync_state_payload){
    9.79                              free_identity((Identity)session->sync_state_payload);
    9.80                              session->sync_state_payload = NULL;
    9.81                          }
    9.82 -                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=Grouped")
    9.83 -                        return Grouped;
    9.84 +                        session->sync_state_payload = identity_dup(partner);
    9.85 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=WaitForGroupKeysSole")
    9.86 +                        return WaitForGroupKeysSole;
    9.87                      }
    9.88                      if(session->sync_state_payload){
    9.89                          free_identity((Identity)session->sync_state_payload);
    9.90                          session->sync_state_payload = NULL;
    9.91                      }
    9.92 -                    session->sync_state_payload = identity_dup(partner);
    9.93 -                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=WaitForGroupKeysSole")
    9.94 -                    return WaitForGroupKeysSole;
    9.95 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingSole, event=HandshakeAccepted", "target=Sole")
    9.96 +                    return Sole;
    9.97                  }
    9.98                  case Cancel:
    9.99                  {
   9.100 @@ -367,12 +383,6 @@
   9.101                              return (int) invalid_out_of_memory;
   9.102                          if (status != PEP_STATUS_OK)
   9.103                              return (int) invalid_action;
   9.104 -                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=enterGroup")
   9.105 -                        status = enterGroup(session, state, NULL, NULL);
   9.106 -                        if (status == PEP_OUT_OF_MEMORY)
   9.107 -                            return (int) invalid_out_of_memory;
   9.108 -                        if (status != PEP_STATUS_OK)
   9.109 -                            return (int) invalid_action;
   9.110                          DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=sendGroupUpdate")
   9.111                          status = sendGroupUpdate(session, state, NULL, NULL);
   9.112                          if (status == PEP_OUT_OF_MEMORY)
   9.113 @@ -441,6 +451,12 @@
   9.114                          return (int) invalid_out_of_memory;
   9.115                      if (status != PEP_STATUS_OK)
   9.116                          return (int) invalid_action;
   9.117 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=CannotDecrypt", "action=sendBeacon")
   9.118 +                    status = sendBeacon(session, state, NULL, NULL);
   9.119 +                    if (status == PEP_OUT_OF_MEMORY)
   9.120 +                        return (int) invalid_out_of_memory;
   9.121 +                    if (status != PEP_STATUS_OK)
   9.122 +                        return (int) invalid_action;
   9.123                      break;
   9.124                  }
   9.125                  case UpdateRequest:
   9.126 @@ -483,8 +499,8 @@
   9.127                  case GroupUpdate:
   9.128                  {
   9.129                      DEBUG_LOG("FSM event", "sync_fsm.c, state=Grouped", "event=GroupUpdate")
   9.130 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=GroupUpdate", "action=storeGroupKeys")
   9.131 -                    status = storeGroupKeys(session, state, partner, extra /*keys*/);
   9.132 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=Grouped, event=GroupUpdate", "action=storeGroupUpdate")
   9.133 +                    status = storeGroupUpdate(session, state, partner, extra /*keys*/);
   9.134                      if (status == PEP_OUT_OF_MEMORY)
   9.135                          return (int) invalid_out_of_memory;
   9.136                      if (status != PEP_STATUS_OK)
   9.137 @@ -523,6 +539,12 @@
   9.138                          return (int) invalid_out_of_memory;
   9.139                      if (status != PEP_STATUS_OK)
   9.140                          return (int) invalid_action;
   9.141 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=CannotDecrypt", "action=sendBeacon")
   9.142 +                    status = sendBeacon(session, state, NULL, NULL);
   9.143 +                    if (status == PEP_OUT_OF_MEMORY)
   9.144 +                        return (int) invalid_out_of_memory;
   9.145 +                    if (status != PEP_STATUS_OK)
   9.146 +                        return (int) invalid_action;
   9.147                      break;
   9.148                  }
   9.149                  case UpdateRequest:
   9.150 @@ -585,8 +607,8 @@
   9.151                  case GroupUpdate:
   9.152                  {
   9.153                      DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=GroupUpdate")
   9.154 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=GroupUpdate", "action=storeGroupKeys")
   9.155 -                    status = storeGroupKeys(session, state, partner, extra /*keys*/);
   9.156 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=GroupUpdate", "action=storeGroupUpdate")
   9.157 +                    status = storeGroupUpdate(session, state, partner, extra /*keys*/);
   9.158                      if (status == PEP_OUT_OF_MEMORY)
   9.159                          return (int) invalid_out_of_memory;
   9.160                      if (status != PEP_STATUS_OK)
   9.161 @@ -617,12 +639,30 @@
   9.162                  case Init:
   9.163                  {
   9.164                      DEBUG_LOG("FSM event", "sync_fsm.c, state=HandshakingGrouped", "event=Init")
   9.165 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=Init", "action=notifyInitAddOurDevice")
   9.166 -                    status = notifyInitAddOurDevice(session, state, partner, NULL);
   9.167 -                    if (status == PEP_OUT_OF_MEMORY)
   9.168 -                        return (int) invalid_out_of_memory;
   9.169 -                    if (status != PEP_STATUS_OK)
   9.170 -                        return (int) invalid_action;
   9.171 +                    cond_result = keyElectionWon(session, partner);
   9.172 +                    #ifndef NDEBUG
   9.173 +                    char resstr[11] = {0,};
   9.174 +                    snprintf(resstr,10,"result=%d",cond_result);
   9.175 +                    #endif
   9.176 +                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=Init, condition=keyElectionWon", resstr)
   9.177 +                    if (cond_result < 0)
   9.178 +                        return cond_result;
   9.179 +                    if (cond_result) {
   9.180 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=Init", "action=notifyInitAddOtherDevice")
   9.181 +                        status = notifyInitAddOtherDevice(session, state, partner, NULL);
   9.182 +                        if (status == PEP_OUT_OF_MEMORY)
   9.183 +                            return (int) invalid_out_of_memory;
   9.184 +                        if (status != PEP_STATUS_OK)
   9.185 +                            return (int) invalid_action;
   9.186 +                    }
   9.187 +                    else {
   9.188 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=Init", "action=notifyInitMoveOurDevice")
   9.189 +                        status = notifyInitMoveOurDevice(session, state, partner, NULL);
   9.190 +                        if (status == PEP_OUT_OF_MEMORY)
   9.191 +                            return (int) invalid_out_of_memory;
   9.192 +                        if (status != PEP_STATUS_OK)
   9.193 +                            return (int) invalid_action;
   9.194 +                    }
   9.195                      break;
   9.196                  }
   9.197                  case HandshakeRejected:
   9.198 @@ -650,18 +690,41 @@
   9.199                          return (int) invalid_out_of_memory;
   9.200                      if (status != PEP_STATUS_OK)
   9.201                          return (int) invalid_action;
   9.202 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=sendGroupKeys")
   9.203 -                    status = sendGroupKeys(session, state, partner, NULL);
   9.204 -                    if (status == PEP_OUT_OF_MEMORY)
   9.205 -                        return (int) invalid_out_of_memory;
   9.206 -                    if (status != PEP_STATUS_OK)
   9.207 -                        return (int) invalid_action;
   9.208 +                    cond_result = keyElectionWon(session, partner);
   9.209 +                    #ifndef NDEBUG
   9.210 +                    char resstr[11] = {0,};
   9.211 +                    snprintf(resstr,10,"result=%d",cond_result);
   9.212 +                    #endif
   9.213 +                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted, condition=keyElectionWon", resstr)
   9.214 +                    if (cond_result < 0)
   9.215 +                        return cond_result;
   9.216 +                    if (cond_result) {
   9.217 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=sendGroupKeys")
   9.218 +                        status = sendGroupKeys(session, state, partner, NULL);
   9.219 +                        if (status == PEP_OUT_OF_MEMORY)
   9.220 +                            return (int) invalid_out_of_memory;
   9.221 +                        if (status != PEP_STATUS_OK)
   9.222 +                            return (int) invalid_action;
   9.223 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "action=notifyAcceptedDeviceAdded")
   9.224 +                        status = notifyAcceptedDeviceAdded(session, state, partner, NULL);
   9.225 +                        if (status == PEP_OUT_OF_MEMORY)
   9.226 +                            return (int) invalid_out_of_memory;
   9.227 +                        if (status != PEP_STATUS_OK)
   9.228 +                            return (int) invalid_action;
   9.229 +                        if(session->sync_state_payload){
   9.230 +                            free_identity((Identity)session->sync_state_payload);
   9.231 +                            session->sync_state_payload = NULL;
   9.232 +                        }
   9.233 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "target=Grouped")
   9.234 +                        return Grouped;
   9.235 +                    }
   9.236                      if(session->sync_state_payload){
   9.237                          free_identity((Identity)session->sync_state_payload);
   9.238                          session->sync_state_payload = NULL;
   9.239                      }
   9.240 -                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "target=Grouped")
   9.241 -                    return Grouped;
   9.242 +                    session->sync_state_payload = identity_dup(partner);
   9.243 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=HandshakingGrouped, event=HandshakeAccepted", "target=WaitForGroupKeysGrouped")
   9.244 +                    return WaitForGroupKeysGrouped;
   9.245                  }
   9.246                  case Cancel:
   9.247                  {
   9.248 @@ -694,6 +757,73 @@
   9.249              }
   9.250              break;
   9.251          }
   9.252 +        case WaitForGroupKeysGrouped:
   9.253 +        {
   9.254 +            Identity expected = (Identity)session->sync_state_payload;
   9.255 +            *timeout = 600;
   9.256 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=WaitForGroupKeysGrouped")
   9.257 +            switch (event) {
   9.258 +                case Init: DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=Init") break;
   9.259 +                case GroupKeys:
   9.260 +                {
   9.261 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=GroupKeys")
   9.262 +                    cond_result = sameIdentities(session, partner, expected);
   9.263 +                    #ifndef NDEBUG
   9.264 +                    char resstr[11] = {0,};
   9.265 +                    snprintf(resstr,10,"result=%d",cond_result);
   9.266 +                    #endif
   9.267 +                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys, condition=sameIdentities", resstr)
   9.268 +                    if (cond_result < 0)
   9.269 +                        return cond_result;
   9.270 +                    if (cond_result) {
   9.271 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "action=storeGroupKeys")
   9.272 +                        status = storeGroupKeys(session, state, partner, extra /*keys*/);
   9.273 +                        if (status == PEP_OUT_OF_MEMORY)
   9.274 +                            return (int) invalid_out_of_memory;
   9.275 +                        if (status != PEP_STATUS_OK)
   9.276 +                            return (int) invalid_action;
   9.277 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "action=sendGroupUpdate")
   9.278 +                        status = sendGroupUpdate(session, state, NULL, NULL);
   9.279 +                        if (status == PEP_OUT_OF_MEMORY)
   9.280 +                            return (int) invalid_out_of_memory;
   9.281 +                        if (status != PEP_STATUS_OK)
   9.282 +                            return (int) invalid_action;
   9.283 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "action=notifyAcceptedDeviceMoved")
   9.284 +                        status = notifyAcceptedDeviceMoved(session, state, partner, NULL);
   9.285 +                        if (status == PEP_OUT_OF_MEMORY)
   9.286 +                            return (int) invalid_out_of_memory;
   9.287 +                        if (status != PEP_STATUS_OK)
   9.288 +                            return (int) invalid_action;
   9.289 +                        if(session->sync_state_payload){
   9.290 +                            free_identity((Identity)session->sync_state_payload);
   9.291 +                            session->sync_state_payload = NULL;
   9.292 +                        }
   9.293 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=GroupKeys", "target=Grouped")
   9.294 +                        return Grouped;
   9.295 +                    }
   9.296 +                    break;
   9.297 +                }
   9.298 +                case Timeout:
   9.299 +                {
   9.300 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysGrouped", "event=Timeout")
   9.301 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=Timeout", "action=notifyTimeout")
   9.302 +                    status = notifyTimeout(session, state, expected, NULL);
   9.303 +                    if (status == PEP_OUT_OF_MEMORY)
   9.304 +                        return (int) invalid_out_of_memory;
   9.305 +                    if (status != PEP_STATUS_OK)
   9.306 +                        return (int) invalid_action;
   9.307 +                    if(session->sync_state_payload){
   9.308 +                        free_identity((Identity)session->sync_state_payload);
   9.309 +                        session->sync_state_payload = NULL;
   9.310 +                    }
   9.311 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysGrouped, event=Timeout", "target=Grouped")
   9.312 +                    return Grouped;
   9.313 +                }
   9.314 +                default:
   9.315 +                    return (DeviceState_state) invalid_event;
   9.316 +            }
   9.317 +            break;
   9.318 +        }
   9.319          default:
   9.320              return (DeviceState_state) invalid_state;
   9.321      }
    10.1 --- a/sync/generated/sync_fsm.h	Mon Feb 20 15:22:58 2017 +0100
    10.2 +++ b/sync/generated/sync_fsm.h	Mon Feb 20 15:29:07 2017 +0100
    10.3 @@ -12,7 +12,6 @@
    10.4  
    10.5  typedef pEp_identity * Identity;
    10.6  typedef stringlist_t * Stringlist;
    10.7 -typedef union _param { Identity partner; stringlist_t *keylist; } param_t;
    10.8  
    10.9  // error values
   10.10  
   10.11 @@ -52,7 +51,8 @@
   10.12      WaitForGroupKeysSole, 
   10.13      Grouped, 
   10.14      GroupedBeaconed, 
   10.15 -    HandshakingGrouped
   10.16 +    HandshakingGrouped, 
   10.17 +    WaitForGroupKeysGrouped
   10.18  } DeviceState_state;
   10.19  
   10.20  // events
   10.21 @@ -81,7 +81,7 @@
   10.22  PEP_STATUS notifyInitAddOurDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.23  PEP_STATUS rejectHandshake(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.24  PEP_STATUS acceptHandshake(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.25 -PEP_STATUS enterGroup(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.26 +PEP_STATUS makeGroup(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.27  PEP_STATUS sendGroupKeys(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.28  PEP_STATUS notifyAcceptedGroupCreated(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.29  PEP_STATUS notifyTimeout(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.30 @@ -89,6 +89,10 @@
   10.31  PEP_STATUS sendGroupUpdate(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.32  PEP_STATUS notifyAcceptedDeviceAdded(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.33  PEP_STATUS sendUpdateRequest(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.34 +PEP_STATUS storeGroupUpdate(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.35 +PEP_STATUS notifyInitAddOtherDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.36 +PEP_STATUS notifyInitMoveOurDevice(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.37 +PEP_STATUS notifyAcceptedDeviceMoved(PEP_SESSION session, DeviceState_state state, Identity partner, void *extra);
   10.38  
   10.39  // event injector
   10.40  
    11.1 --- a/sync/generated/sync_send_actions.c	Mon Feb 20 15:22:58 2017 +0100
    11.2 +++ b/sync/generated/sync_send_actions.c	Mon Feb 20 15:29:07 2017 +0100
    11.3 @@ -86,9 +86,21 @@
    11.4      if (!msg)
    11.5          goto enomem;
    11.6  
    11.7 -    if (Identity_from_Struct(partner,
    11.8 -                             &msg->payload.choice.handshakeRequest.partner) == NULL)
    11.9 -        goto enomem;
   11.10 +    msg->payload.choice.handshakeRequest.partner_id = 
   11.11 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
   11.12 +                                 partner->user_id, -1);
   11.13 +    if (partner->user_id && !msg->payload.choice.handshakeRequest.partner_id)
   11.14 +       goto enomem;
   11.15 +
   11.16 +    char *devgrp = NULL;
   11.17 +    status = get_device_group(session, &devgrp);
   11.18 +    if (status == PEP_STATUS_OK && devgrp && devgrp[0])
   11.19 +    msg->payload.choice.handshakeRequest.group_id = 
   11.20 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
   11.21 +                                 devgrp, -1);
   11.22 +    free(devgrp);
   11.23 +    if (devgrp && !msg->payload.choice.handshakeRequest.partner_id)
   11.24 +       goto enomem;
   11.25  
   11.26      bool encrypted = true;
   11.27      status = unicast_msg(session, partner, state, msg, encrypted);
   11.28 @@ -140,9 +152,21 @@
   11.29      if (IdentityList_from_identity_list(kl, &msg->payload.choice.groupKeys.ownIdentities) == NULL)
   11.30          goto enomem;
   11.31  
   11.32 -    if (Identity_from_Struct(partner,
   11.33 -                             &msg->payload.choice.groupKeys.partner) == NULL)
   11.34 -        goto enomem;
   11.35 +    msg->payload.choice.groupKeys.partner_id = 
   11.36 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
   11.37 +                                 partner->user_id, -1);
   11.38 +    if (partner->user_id && !msg->payload.choice.groupKeys.partner_id)
   11.39 +       goto enomem;
   11.40 +
   11.41 +    char *devgrp = NULL;
   11.42 +    status = get_device_group(session, &devgrp);
   11.43 +    if (status == PEP_STATUS_OK && devgrp && devgrp[0])
   11.44 +    msg->payload.choice.groupKeys.group_id = 
   11.45 +        OCTET_STRING_new_fromBuf(&asn_DEF_UTF8String,
   11.46 +                                 devgrp, -1);
   11.47 +    free(devgrp);
   11.48 +    if (devgrp && !msg->payload.choice.groupKeys.partner_id)
   11.49 +       goto enomem;
   11.50  
   11.51      bool encrypted = true;
   11.52      status = unicast_msg(session, partner, state, msg, encrypted);
   11.53 @@ -391,3 +415,81 @@
   11.54      return _notifyHandshake(session, partner, SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED);
   11.55  }
   11.56  
   11.57 +
   11.58 +// notifyInitAddOtherDevice() - notify InitAddOtherDevice to app
   11.59 +//
   11.60 +//  params:
   11.61 +//      session (in)        session handle
   11.62 +//      state (in)          state the state machine is in
   11.63 +//      partner (in)        partner to communicate with
   11.64 +//
   11.65 +//  returns:
   11.66 +//      PEP_STATUS_OK or any other value on error
   11.67 +
   11.68 +PEP_STATUS notifyInitAddOtherDevice(
   11.69 +        PEP_SESSION session,
   11.70 +        DeviceState_state state,
   11.71 +        Identity partner,
   11.72 +        void *extra
   11.73 +    )
   11.74 +{
   11.75 +    assert(session && state);
   11.76 +    assert(extra == NULL);
   11.77 +    if (!(session && state && extra == NULL))
   11.78 +        return PEP_ILLEGAL_VALUE;
   11.79 +
   11.80 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE);
   11.81 +}
   11.82 +
   11.83 +
   11.84 +// notifyInitMoveOurDevice() - notify InitMoveOurDevice to app
   11.85 +//
   11.86 +//  params:
   11.87 +//      session (in)        session handle
   11.88 +//      state (in)          state the state machine is in
   11.89 +//      partner (in)        partner to communicate with
   11.90 +//
   11.91 +//  returns:
   11.92 +//      PEP_STATUS_OK or any other value on error
   11.93 +
   11.94 +PEP_STATUS notifyInitMoveOurDevice(
   11.95 +        PEP_SESSION session,
   11.96 +        DeviceState_state state,
   11.97 +        Identity partner,
   11.98 +        void *extra
   11.99 +    )
  11.100 +{
  11.101 +    assert(session && state);
  11.102 +    assert(extra == NULL);
  11.103 +    if (!(session && state && extra == NULL))
  11.104 +        return PEP_ILLEGAL_VALUE;
  11.105 +
  11.106 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_INIT_MOVE_OUR_DEVICE);
  11.107 +}
  11.108 +
  11.109 +
  11.110 +// notifyAcceptedDeviceMoved() - notify AcceptedDeviceMoved to app
  11.111 +//
  11.112 +//  params:
  11.113 +//      session (in)        session handle
  11.114 +//      state (in)          state the state machine is in
  11.115 +//      partner (in)        partner to communicate with
  11.116 +//
  11.117 +//  returns:
  11.118 +//      PEP_STATUS_OK or any other value on error
  11.119 +
  11.120 +PEP_STATUS notifyAcceptedDeviceMoved(
  11.121 +        PEP_SESSION session,
  11.122 +        DeviceState_state state,
  11.123 +        Identity partner,
  11.124 +        void *extra
  11.125 +    )
  11.126 +{
  11.127 +    assert(session && state);
  11.128 +    assert(extra == NULL);
  11.129 +    if (!(session && state && extra == NULL))
  11.130 +        return PEP_ILLEGAL_VALUE;
  11.131 +
  11.132 +    return _notifyHandshake(session, partner, SYNC_NOTIFY_ACCEPTED_DEVICE_MOVED);
  11.133 +}
  11.134 +
    12.1 --- a/sync/skeletons/sync_actions.c	Mon Feb 20 15:22:58 2017 +0100
    12.2 +++ b/sync/skeletons/sync_actions.c	Mon Feb 20 15:29:07 2017 +0100
    12.3 @@ -156,7 +156,7 @@
    12.4  }
    12.5  
    12.6  
    12.7 -// enterGroup() - 
    12.8 +// makeGroup() - 
    12.9  //
   12.10  //  params:
   12.11  //      session (in)        session handle
   12.12 @@ -166,7 +166,7 @@
   12.13  //  returns:
   12.14  //      PEP_STATUS_OK or any other value on error
   12.15  
   12.16 -PEP_STATUS enterGroup(
   12.17 +PEP_STATUS makeGroup(
   12.18          PEP_SESSION session,
   12.19          DeviceState_state state,
   12.20          Identity partner,
   12.21 @@ -340,3 +340,151 @@
   12.22      return status;
   12.23  }
   12.24  
   12.25 +
   12.26 +// storeGroupUpdate() - 
   12.27 +//
   12.28 +//  params:
   12.29 +//      session (in)        session handle
   12.30 +//      state (in)          state the state machine is in
   12.31 +//      partner (in)        partner to communicate with
   12.32 +//
   12.33 +//  returns:
   12.34 +//      PEP_STATUS_OK or any other value on error
   12.35 +
   12.36 +PEP_STATUS storeGroupUpdate(
   12.37 +        PEP_SESSION session,
   12.38 +        DeviceState_state state,
   12.39 +        Identity partner,
   12.40 +        void *extra
   12.41 +    )
   12.42 +{
   12.43 +    PEP_STATUS status = PEP_STATUS_OK;
   12.44 +
   12.45 +    assert(session);
   12.46 +    assert(partner);
   12.47 +    if (!(session && partner))
   12.48 +        return PEP_ILLEGAL_VALUE;
   12.49 +
   12.50 +    // working code
   12.51 +
   12.52 +    // free extra
   12.53 +    return status;
   12.54 +
   12.55 +enomem:
   12.56 +    status = PEP_OUT_OF_MEMORY;
   12.57 +error:
   12.58 +    // free extra
   12.59 +    return status;
   12.60 +}
   12.61 +
   12.62 +
   12.63 +// notifyInitAddOtherDevice() - 
   12.64 +//
   12.65 +//  params:
   12.66 +//      session (in)        session handle
   12.67 +//      state (in)          state the state machine is in
   12.68 +//      partner (in)        partner to communicate with
   12.69 +//
   12.70 +//  returns:
   12.71 +//      PEP_STATUS_OK or any other value on error
   12.72 +
   12.73 +PEP_STATUS notifyInitAddOtherDevice(
   12.74 +        PEP_SESSION session,
   12.75 +        DeviceState_state state,
   12.76 +        Identity partner,
   12.77 +        void *extra
   12.78 +    )
   12.79 +{
   12.80 +    PEP_STATUS status = PEP_STATUS_OK;
   12.81 +
   12.82 +    assert(session);
   12.83 +    assert(partner);
   12.84 +    if (!(session && partner))
   12.85 +        return PEP_ILLEGAL_VALUE;
   12.86 +
   12.87 +    // working code
   12.88 +
   12.89 +    // free extra
   12.90 +    return status;
   12.91 +
   12.92 +enomem:
   12.93 +    status = PEP_OUT_OF_MEMORY;
   12.94 +error:
   12.95 +    // free extra
   12.96 +    return status;
   12.97 +}
   12.98 +
   12.99 +
  12.100 +// notifyInitMoveOurDevice() - 
  12.101 +//
  12.102 +//  params:
  12.103 +//      session (in)        session handle
  12.104 +//      state (in)          state the state machine is in
  12.105 +//      partner (in)        partner to communicate with
  12.106 +//
  12.107 +//  returns:
  12.108 +//      PEP_STATUS_OK or any other value on error
  12.109 +
  12.110 +PEP_STATUS notifyInitMoveOurDevice(
  12.111 +        PEP_SESSION session,
  12.112 +        DeviceState_state state,
  12.113 +        Identity partner,
  12.114 +        void *extra
  12.115 +    )
  12.116 +{
  12.117 +    PEP_STATUS status = PEP_STATUS_OK;
  12.118 +
  12.119 +    assert(session);
  12.120 +    assert(partner);
  12.121 +    if (!(session && partner))
  12.122 +        return PEP_ILLEGAL_VALUE;
  12.123 +
  12.124 +    // working code
  12.125 +
  12.126 +    // free extra
  12.127 +    return status;
  12.128 +
  12.129 +enomem:
  12.130 +    status = PEP_OUT_OF_MEMORY;
  12.131 +error:
  12.132 +    // free extra
  12.133 +    return status;
  12.134 +}
  12.135 +
  12.136 +
  12.137 +// notifyAcceptedDeviceMoved() - 
  12.138 +//
  12.139 +//  params:
  12.140 +//      session (in)        session handle
  12.141 +//      state (in)          state the state machine is in
  12.142 +//      partner (in)        partner to communicate with
  12.143 +//
  12.144 +//  returns:
  12.145 +//      PEP_STATUS_OK or any other value on error
  12.146 +
  12.147 +PEP_STATUS notifyAcceptedDeviceMoved(
  12.148 +        PEP_SESSION session,
  12.149 +        DeviceState_state state,
  12.150 +        Identity partner,
  12.151 +        void *extra
  12.152 +    )
  12.153 +{
  12.154 +    PEP_STATUS status = PEP_STATUS_OK;
  12.155 +
  12.156 +    assert(session);
  12.157 +    assert(partner);
  12.158 +    if (!(session && partner))
  12.159 +        return PEP_ILLEGAL_VALUE;
  12.160 +
  12.161 +    // working code
  12.162 +
  12.163 +    // free extra
  12.164 +    return status;
  12.165 +
  12.166 +enomem:
  12.167 +    status = PEP_OUT_OF_MEMORY;
  12.168 +error:
  12.169 +    // free extra
  12.170 +    return status;
  12.171 +}
  12.172 +