merge "default" into "ENGINE-199" ENGINE-199
authorRoker <roker@pep-project.org>
Mon, 08 May 2017 08:18:47 +0200
branchENGINE-199
changeset 175301faac16cec6
parent 1736 18b244fa4710
parent 1750 33b2fa2368e6
child 1754 a9e54ca6c043
merge "default" into "ENGINE-199"
src/keymanagement.c
src/message_api.c
src/pEp_internal.h
     1.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Fri Apr 21 21:39:42 2017 +0200
     1.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Mon May 08 08:18:47 2017 +0200
     1.3 @@ -292,7 +292,7 @@
     1.4  		646C414C1D510D8800C63EFF /* baseprotocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = baseprotocol.c; path = ../src/baseprotocol.c; sourceTree = "<group>"; };
     1.5  		646C414D1D510D8800C63EFF /* baseprotocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = baseprotocol.h; path = ../src/baseprotocol.h; sourceTree = "<group>"; };
     1.6  		64796A3F1B455AA5004B1C24 /* libpEpEngine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpEpEngine.a; sourceTree = BUILT_PRODUCTS_DIR; };
     1.7 -		64951A1B1BE0FCD800B10E71 /* system.db */ = {isa = PBXFileReference; lastKnownFileType = file; name = system.db; path = ../db/system.db; sourceTree = "<group>"; };
     1.8 +		64951A1B1BE0FCD800B10E71 /* system.db */ = {isa = PBXFileReference; lastKnownFileType = text; name = system.db; path = ../db/system.db; sourceTree = "<group>"; };
     1.9  		649DE08A1B45C19100912F72 /* libcurl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libcurl.a; sourceTree = "<group>"; };
    1.10  		64A8264C1B455D0800EECAF0 /* bloblist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bloblist.c; path = ../src/bloblist.c; sourceTree = "<group>"; };
    1.11  		64A8264D1B455D0800EECAF0 /* bloblist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bloblist.h; path = ../src/bloblist.h; sourceTree = "<group>"; };
    1.12 @@ -947,7 +947,7 @@
    1.13  					"$(SRCROOT)",
    1.14  					"$(SRCROOT)/../../netpgp-et/include/",
    1.15  					"$(SRCROOT)/../../netpgp-et/src/",
    1.16 -					"$(SRCROOT)/../../netpgp-et/netpgp-xcode/openssl/include/",
    1.17 +					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
    1.18  					"$(SRCROOT)/../asn.1/",
    1.19  				);
    1.20  				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
    1.21 @@ -994,7 +994,7 @@
    1.22  					"$(SRCROOT)",
    1.23  					"$(SRCROOT)/../../netpgp-et/include/",
    1.24  					"$(SRCROOT)/../../netpgp-et/src/",
    1.25 -					"$(SRCROOT)/../../netpgp-et/netpgp-xcode/openssl/include/",
    1.26 +					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
    1.27  					"$(SRCROOT)/../asn.1/",
    1.28  				);
    1.29  				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
     2.1 --- a/src/keymanagement.c	Fri Apr 21 21:39:42 2017 +0200
     2.2 +++ b/src/keymanagement.c	Mon May 08 08:18:47 2017 +0200
     2.3 @@ -179,10 +179,11 @@
     2.4                         downgrade eventually trusted comm_type */
     2.5                      temp_id->comm_type = _comm_type_key;
     2.6                  } else {
     2.7 -                    /* otherwise take stored comm_type as-is */
     2.8 +                    /* otherwise take stored comm_type as-is except if 
     2.9 +                       is unknown or is expired (but key not expired anymore) */
    2.10                      temp_id->comm_type = stored_identity->comm_type;
    2.11 -                    if (temp_id->comm_type == PEP_ct_unknown) {
    2.12 -                        /* except if unknown */
    2.13 +                    if (temp_id->comm_type == PEP_ct_unknown ||
    2.14 +                        temp_id->comm_type == PEP_ct_key_expired) {
    2.15                          temp_id->comm_type = _comm_type_key;
    2.16                      }
    2.17                  }
     3.1 --- a/src/message_api.c	Fri Apr 21 21:39:42 2017 +0200
     3.2 +++ b/src/message_api.c	Mon May 08 08:18:47 2017 +0200
     3.3 @@ -794,6 +794,7 @@
     3.4          return PEP_rating_unencrypted;
     3.5  
     3.6      case PEP_DECRYPTED:
     3.7 +    case PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH:
     3.8          return PEP_rating_unreliable;
     3.9  
    3.10      case PEP_DECRYPTED_AND_VERIFIED:
    3.11 @@ -2251,88 +2252,6 @@
    3.12      return PEP_color_no_color;
    3.13  }
    3.14  
    3.15 -static bool _is_valid_hex(const char* hexstr) {
    3.16 -    if (!hexstr)
    3.17 -        return false;
    3.18 -
    3.19 -    const char* curr = hexstr;
    3.20 -    char currchar;
    3.21 -
    3.22 -    for (currchar = *curr; currchar != '\0'; currchar = *(++curr)) {
    3.23 -        if ((currchar >= '0' && currchar <= '9') ||
    3.24 -            (currchar >= 'a' && currchar <= 'f') ||
    3.25 -            (currchar >= 'A' && currchar <= 'F'))
    3.26 -        {
    3.27 -            continue;
    3.28 -        }
    3.29 -        return false;
    3.30 -    }
    3.31 -    return true;
    3.32 -}
    3.33 -
    3.34 -// Returns, in comparison: 1 if fpr1 > fpr2, 0 if equal, -1 if fpr1 < fpr2
    3.35 -static PEP_STATUS _compare_fprs(const char* fpr1, const char* fpr2, int* comparison) {
    3.36 -
    3.37 -    const int _FULL_FINGERPRINT_LENGTH = 40;
    3.38 -    const int _ASCII_LOWERCASE_OFFSET = 32;
    3.39 -
    3.40 -    size_t fpr1_len = strlen(fpr1);
    3.41 -    size_t fpr2_len = strlen(fpr2);
    3.42 -
    3.43 -    if (fpr1_len != _FULL_FINGERPRINT_LENGTH || fpr2_len != _FULL_FINGERPRINT_LENGTH)
    3.44 -        return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
    3.45 -
    3.46 -    if (!_is_valid_hex(fpr1) || !_is_valid_hex(fpr2))
    3.47 -        return PEP_ILLEGAL_VALUE;
    3.48 -
    3.49 -    const char* fpr1_curr = fpr1;
    3.50 -    const char* fpr2_curr = fpr2;
    3.51 -
    3.52 -    char current;
    3.53 -
    3.54 -    // Advance past leading zeros.
    3.55 -    for (current = *fpr1_curr; current != '0' && current != '\0'; current = *(++fpr1_curr), fpr1_len--);
    3.56 -    for (current = *fpr2_curr; current != '0' && current != '\0'; current = *(++fpr2_curr), fpr2_len--);
    3.57 -
    3.58 -    if (fpr1_len == fpr2_len) {
    3.59 -        char digit1;
    3.60 -        char digit2;
    3.61 -
    3.62 -        while (fpr1_curr && *fpr1_curr != '\0') {
    3.63 -            digit1 = *fpr1_curr++;
    3.64 -            digit2 = *fpr2_curr++;
    3.65 -
    3.66 -            // Adjust for case-insensitive compare
    3.67 -            if (digit1 >= 'a' && digit1 <= 'f')
    3.68 -                digit1 -= _ASCII_LOWERCASE_OFFSET;
    3.69 -            if (digit2 >= 'a' && digit2 <= 'f')
    3.70 -                digit2 -= _ASCII_LOWERCASE_OFFSET;
    3.71 -
    3.72 -            // We take advantage of the fact that 'a'-'f' are larger
    3.73 -            // integer values in the ASCII table than '0'-'9'.
    3.74 -            // This allows us to compare digits directly.
    3.75 -            if (digit1 > digit2) {
    3.76 -                *comparison = 1;
    3.77 -                return PEP_STATUS_OK;
    3.78 -            } else if (digit1 < digit2) {
    3.79 -                *comparison = -1;
    3.80 -                return PEP_STATUS_OK;
    3.81 -            }
    3.82 -
    3.83 -            // pointers already advanced above. Keep going.
    3.84 -        }
    3.85 -        *comparison = 0;
    3.86 -        return PEP_STATUS_OK;
    3.87 -    }
    3.88 -    else if (fpr1_len > fpr2_len) {
    3.89 -        *comparison = 1;
    3.90 -        return PEP_STATUS_OK;
    3.91 -    }
    3.92 -    // Otherwise, fpr1_len < fpr2_len
    3.93 -    *comparison = -1;
    3.94 -    return PEP_STATUS_OK;
    3.95 -}
    3.96 -
    3.97  DYNAMIC_API PEP_STATUS get_trustwords(
    3.98      PEP_SESSION session, const pEp_identity* id1, const pEp_identity* id2,
    3.99      const char* lang, char **words, size_t *wsize, bool full
   3.100 @@ -2368,7 +2287,7 @@
   3.101      size_t second_wsize = 0;
   3.102  
   3.103      int fpr_comparison = -255;
   3.104 -    PEP_STATUS status = _compare_fprs(source1, source2, &fpr_comparison);
   3.105 +    PEP_STATUS status = _compare_fprs(source1, strlen(source1), source2, strlen(source2), &fpr_comparison);
   3.106      if (status != PEP_STATUS_OK)
   3.107          return status;
   3.108  
   3.109 @@ -2556,6 +2475,12 @@
   3.110      PEP_decrypt_flags_t *flags
   3.111  )
   3.112  {
   3.113 +    assert(mimetext);
   3.114 +    assert(mime_plaintext);
   3.115 +    assert(keylist);
   3.116 +    assert(rating);
   3.117 +    assert(flags);
   3.118 +
   3.119      PEP_STATUS status = PEP_STATUS_OK;
   3.120      message* tmp_msg = NULL;
   3.121      message* dec_msg = NULL;
   3.122 @@ -2570,12 +2495,24 @@
   3.123                                                  keylist,
   3.124                                                  rating,
   3.125                                                  flags);
   3.126 +                                                
   3.127 +    if (!dec_msg && (decrypt_status == PEP_UNENCRYPTED || decrypt_status == PEP_VERIFIED)) {
   3.128 +        dec_msg = message_dup(tmp_msg);
   3.129 +    }
   3.130 +        
   3.131      if (decrypt_status > PEP_CANNOT_DECRYPT_UNKNOWN)
   3.132      {
   3.133          status = decrypt_status;
   3.134          goto pep_error;
   3.135      }
   3.136  
   3.137 +    assert(dec_msg);
   3.138 +    
   3.139 +    if (!dec_msg) {
   3.140 +        status = PEP_UNKNOWN_ERROR;
   3.141 +        goto pep_error;
   3.142 +    }
   3.143 +
   3.144      status = mime_encode_message(dec_msg, false, mime_plaintext);
   3.145  
   3.146      if (status == PEP_STATUS_OK)
   3.147 @@ -2621,6 +2558,12 @@
   3.148      if (status != PEP_STATUS_OK)
   3.149          GOTO(pep_error);
   3.150  
   3.151 +
   3.152 +    if (!enc_msg) {
   3.153 +        status = PEP_UNKNOWN_ERROR;
   3.154 +        goto pep_error;
   3.155 +    }
   3.156 +
   3.157      status = mime_encode_message(enc_msg, false, mime_ciphertext);
   3.158  
   3.159  pep_error:
   3.160 @@ -2659,6 +2602,11 @@
   3.161                                        flags);
   3.162      if (status != PEP_STATUS_OK)
   3.163          goto pep_error;
   3.164 + 
   3.165 +    if (!enc_msg) {
   3.166 +        status = PEP_UNKNOWN_ERROR;
   3.167 +        goto pep_error;
   3.168 +    }
   3.169  
   3.170      status = mime_encode_message(enc_msg, false, mime_ciphertext);
   3.171  
     4.1 --- a/src/pEp_internal.h	Fri Apr 21 21:39:42 2017 +0200
     4.2 +++ b/src/pEp_internal.h	Mon May 08 08:18:47 2017 +0200
     4.3 @@ -193,7 +193,109 @@
     4.4  }
     4.5  #endif
     4.6  
     4.7 +typedef enum _normalize_hex_rest_t {
     4.8 +    accept_hex,
     4.9 +    ignore_hex,
    4.10 +    reject_hex
    4.11 +} normalize_hex_res_t;
    4.12 +
    4.13 +static inline normalize_hex_res_t _normalize_hex(char *hex) 
    4.14 +{
    4.15 +    if (*hex >= '0' && *hex <= '9')
    4.16 +        return accept_hex;
    4.17 +
    4.18 +    if (*hex >= 'A' && *hex <= 'F') {
    4.19 +        *hex += 'a' - 'A';
    4.20 +        return accept_hex;
    4.21 +    }
    4.22 +
    4.23 +    if (*hex >= 'a' && *hex <= 'f') 
    4.24 +        return accept_hex;
    4.25 +
    4.26 +    if (*hex == ' ') 
    4.27 +        return ignore_hex;
    4.28 +
    4.29 +    return reject_hex;
    4.30 +}
    4.31 +
    4.32  // Space tolerant and case insensitive fingerprint string compare
    4.33 +static inline PEP_STATUS _compare_fprs(
    4.34 +        const char* fpra,
    4.35 +        size_t fpras,
    4.36 +        const char* fprb,
    4.37 +        size_t fprbs,
    4.38 +        int* comparison)
    4.39 +{
    4.40 +
    4.41 +    size_t ai = 0;
    4.42 +    size_t bi = 0;
    4.43 +    size_t significant = 0;
    4.44 +    int _comparison = 0;
    4.45 +    const int _FULL_FINGERPRINT_LENGTH = 40;
    4.46 +   
    4.47 +    // First compare every non-ignored chars until an end is reached
    4.48 +    while(ai < fpras && bi < fprbs)
    4.49 +    {
    4.50 +        char fprac = fpra[ai];
    4.51 +        char fprbc = fprb[bi];
    4.52 +        normalize_hex_res_t fprah = _normalize_hex(&fprac);
    4.53 +        normalize_hex_res_t fprbh = _normalize_hex(&fprbc);
    4.54 +
    4.55 +        if(fprah == reject_hex || fprbh == reject_hex)
    4.56 +            return PEP_ILLEGAL_VALUE;
    4.57 +
    4.58 +        if ( fprah == ignore_hex )
    4.59 +        {
    4.60 +            ai++;
    4.61 +        }
    4.62 +        else if ( fprbh == ignore_hex )
    4.63 +        {
    4.64 +            bi++;
    4.65 +        }
    4.66 +        else
    4.67 +        {
    4.68 +            if(fprac != fprbc && _comparison == 0 )
    4.69 +            {
    4.70 +                _comparison = fprac > fprbc ? 1 : -1;
    4.71 +            }
    4.72 +
    4.73 +            significant++;
    4.74 +            ai++;
    4.75 +            bi++;
    4.76 +
    4.77 +        } 
    4.78 +    }
    4.79 +
    4.80 +    // Bail out if we didn't got enough significnt chars
    4.81 +    if (significant != _FULL_FINGERPRINT_LENGTH )
    4.82 +        return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
    4.83 +
    4.84 +    // Then purge remaining chars, all must be ignored chars
    4.85 +    while ( ai < fpras )
    4.86 +    {
    4.87 +        char fprac = fpra[ai];
    4.88 +        normalize_hex_res_t fprah = _normalize_hex(&fprac);
    4.89 +        if( fprah == reject_hex )
    4.90 +            return PEP_ILLEGAL_VALUE;
    4.91 +        if ( fprah != ignore_hex )
    4.92 +            return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
    4.93 +        ai++;
    4.94 +    }
    4.95 +    while ( bi < fprbs )
    4.96 +    {
    4.97 +        char fprbc = fprb[bi];
    4.98 +        normalize_hex_res_t fprbh = _normalize_hex(&fprbc);
    4.99 +        if( fprbh == reject_hex )
   4.100 +            return PEP_ILLEGAL_VALUE;
   4.101 +        if ( fprbh != ignore_hex )
   4.102 +            return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
   4.103 +        bi++;
   4.104 +    }
   4.105 +
   4.106 +    *comparison = _comparison;
   4.107 +    return PEP_STATUS_OK;
   4.108 +}
   4.109 +
   4.110  static inline int _same_fpr(
   4.111          const char* fpra,
   4.112          size_t fpras,
   4.113 @@ -201,37 +303,12 @@
   4.114          size_t fprbs
   4.115      )
   4.116  {
   4.117 -    size_t ai = 0;
   4.118 -    size_t bi = 0;
   4.119 -    
   4.120 -    do
   4.121 -    {
   4.122 -        if(fpra[ai] == 0 || fprb[bi] == 0)
   4.123 -        {
   4.124 -            return 0;
   4.125 -        }
   4.126 -        else if(fpra[ai] == ' ')
   4.127 -        {
   4.128 -            ai++;
   4.129 -        }
   4.130 -        else if(fprb[bi] == ' ')
   4.131 -        {
   4.132 -            bi++;
   4.133 -        }
   4.134 -        else if(toupper(fpra[ai]) == toupper(fprb[bi]))
   4.135 -        {
   4.136 -            ai++;
   4.137 -            bi++;
   4.138 -        }
   4.139 -        else
   4.140 -        {
   4.141 -            return 0;
   4.142 -        }
   4.143 -        
   4.144 -    }
   4.145 -    while(ai < fpras && bi < fprbs);
   4.146 -    
   4.147 -    return ai == fpras && bi == fprbs;
   4.148 +    // illegal values are ignored, and considered not same.
   4.149 +    int comparison = 1;
   4.150 +
   4.151 +    _compare_fprs(fpra, fpras, fprb, fprbs, &comparison);
   4.152 +
   4.153 +    return comparison == 0;
   4.154  }
   4.155  
   4.156  
     5.1 --- a/src/sync_impl.c	Fri Apr 21 21:39:42 2017 +0200
     5.2 +++ b/src/sync_impl.c	Mon May 08 08:18:47 2017 +0200
     5.3 @@ -727,7 +727,7 @@
     5.4  }
     5.5  
     5.6  
     5.7 -#ifndef NDEBUG
     5.8 +#ifdef DEBUG_SYNC_XER_IN_MESSAGE_BODY
     5.9  static int _append(const void *buffer, size_t size, void *appkey)
    5.10  {
    5.11      char **dest_ptr = (char **)appkey;
    5.12 @@ -823,7 +823,7 @@
    5.13      free_identity(me);
    5.14      me = NULL;
    5.15  
    5.16 -#ifndef NDEBUG
    5.17 +#ifdef DEBUG_SYNC_XER_IN_MESSAGE_BODY
    5.18      asn_enc_rval_t er;
    5.19      er = xer_encode(&asn_DEF_DeviceGroup_Protocol, msg, 
    5.20                      XER_F_BASIC, _append, &_message->longmsg);
     6.1 --- a/sync/devicegroup.fsm	Fri Apr 21 21:39:42 2017 +0200
     6.2 +++ b/sync/devicegroup.fsm	Mon May 08 08:18:47 2017 +0200
     6.3 @@ -32,10 +32,14 @@
     6.4          }
     6.5  
     6.6          state Sole end=1 {
     6.7 -            on KeyGen
     6.8 +            on KeyGen {
     6.9                  do sendBeacon;
    6.10 -            on CannotDecrypt
    6.11 +                go SoleWaiting;
    6.12 +            }
    6.13 +            on CannotDecrypt {
    6.14                  do sendBeacon;
    6.15 +                go SoleWaiting;
    6.16 +            }
    6.17              on Beacon(Identity partner){
    6.18                  do sendHandshakeRequest(partner);
    6.19                  go SoleBeaconed(partner);
    6.20 @@ -46,6 +50,26 @@
    6.21              }
    6.22          }
    6.23  
    6.24 +        // copy of sole state with a timeout to enable fast polling for a second
    6.25 +        // TODO use more YSLT power here (substates ?) 
    6.26 +        state SoleWaiting timeout=60 {
    6.27 +            on KeyGen {
    6.28 +                do sendBeacon;
    6.29 +            }
    6.30 +            on CannotDecrypt {
    6.31 +                do sendBeacon;
    6.32 +            }
    6.33 +            on Beacon(Identity partner){
    6.34 +                do sendHandshakeRequest(partner);
    6.35 +                go SoleBeaconed(partner);
    6.36 +            }
    6.37 +            on HandshakeRequest(Identity partner) {
    6.38 +                do sendHandshakeRequest(partner);
    6.39 +                go HandshakingSole(partner);
    6.40 +            }
    6.41 +            on Timeout go Sole;
    6.42 +        }
    6.43 +
    6.44          state SoleBeaconed timeout=600 (Identity expected) {
    6.45              on KeyGen{
    6.46                  do sendBeacon;
    6.47 @@ -161,6 +185,7 @@
    6.48              on CannotDecrypt {
    6.49                  do sendUpdateRequest;
    6.50                  do sendBeacon;
    6.51 +                go GroupWaiting;
    6.52              }
    6.53              on UpdateRequest
    6.54                  do sendGroupUpdate;
    6.55 @@ -176,6 +201,29 @@
    6.56                  do storeGroupUpdate(partner, keys);
    6.57          }
    6.58  
    6.59 +        // copy of grouped state, with a timeout to enable fast poling for a minut
    6.60 +        state GroupWaiting timeout=60 {
    6.61 +            on KeyGen
    6.62 +                do sendGroupUpdate;
    6.63 +            on CannotDecrypt {
    6.64 +                do sendUpdateRequest;
    6.65 +                do sendBeacon;
    6.66 +            }
    6.67 +            on UpdateRequest
    6.68 +                do sendGroupUpdate;
    6.69 +            on Beacon(Identity partner){
    6.70 +                do sendHandshakeRequest(partner);
    6.71 +                go GroupedBeaconed(partner);
    6.72 +            }
    6.73 +            on HandshakeRequest(Identity partner) {
    6.74 +                do sendHandshakeRequest(partner);
    6.75 +                go HandshakingGrouped(partner);
    6.76 +            }
    6.77 +            on GroupUpdate(Identity partner, IdentityList keys)
    6.78 +                do storeGroupUpdate(partner, keys);
    6.79 +            on Timeout go Grouped;
    6.80 +        }
    6.81 +
    6.82          state GroupedBeaconed timeout=600 (Identity expected){
    6.83              on KeyGen
    6.84                  do sendGroupUpdate;
     7.1 --- a/sync/generated/sync_fsm.c	Fri Apr 21 21:39:42 2017 +0200
     7.2 +++ b/sync/generated/sync_fsm.c	Mon May 08 08:18:47 2017 +0200
     7.3 @@ -100,7 +100,8 @@
     7.4                          return (int) invalid_out_of_memory;
     7.5                      if (status != PEP_STATUS_OK)
     7.6                          return (int) invalid_action;
     7.7 -                    break;
     7.8 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=KeyGen", "target=SoleWaiting")
     7.9 +                    return SoleWaiting;
    7.10                  }
    7.11                  case CannotDecrypt:
    7.12                  {
    7.13 @@ -111,7 +112,8 @@
    7.14                          return (int) invalid_out_of_memory;
    7.15                      if (status != PEP_STATUS_OK)
    7.16                          return (int) invalid_action;
    7.17 -                    break;
    7.18 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=CannotDecrypt", "target=SoleWaiting")
    7.19 +                    return SoleWaiting;
    7.20                  }
    7.21                  case Beacon:
    7.22                  {
    7.23 @@ -152,6 +154,81 @@
    7.24              }
    7.25              break;
    7.26          }
    7.27 +        case SoleWaiting:
    7.28 +        {
    7.29 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=SoleWaiting")
    7.30 +            switch (event) {
    7.31 +                case Init: 
    7.32 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Init") 
    7.33 +                    *timeout = 60;
    7.34 +                    break;
    7.35 +                case KeyGen:
    7.36 +                {
    7.37 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=KeyGen")
    7.38 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=KeyGen", "action=sendBeacon")
    7.39 +                    status = sendBeacon(session, state, NULL, NULL);
    7.40 +                    if (status == PEP_OUT_OF_MEMORY)
    7.41 +                        return (int) invalid_out_of_memory;
    7.42 +                    if (status != PEP_STATUS_OK)
    7.43 +                        return (int) invalid_action;
    7.44 +                    break;
    7.45 +                }
    7.46 +                case CannotDecrypt:
    7.47 +                {
    7.48 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=CannotDecrypt")
    7.49 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=CannotDecrypt", "action=sendBeacon")
    7.50 +                    status = sendBeacon(session, state, NULL, NULL);
    7.51 +                    if (status == PEP_OUT_OF_MEMORY)
    7.52 +                        return (int) invalid_out_of_memory;
    7.53 +                    if (status != PEP_STATUS_OK)
    7.54 +                        return (int) invalid_action;
    7.55 +                    break;
    7.56 +                }
    7.57 +                case Beacon:
    7.58 +                {
    7.59 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Beacon")
    7.60 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=Beacon", "action=sendHandshakeRequest")
    7.61 +                    status = sendHandshakeRequest(session, state, partner, NULL);
    7.62 +                    if (status == PEP_OUT_OF_MEMORY)
    7.63 +                        return (int) invalid_out_of_memory;
    7.64 +                    if (status != PEP_STATUS_OK)
    7.65 +                        return (int) invalid_action;
    7.66 +                    session->sync_state_payload = malloc(sizeof(SoleBeaconed_state_payload_t));
    7.67 +                    assert(session->sync_state_payload);
    7.68 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
    7.69 +                    ((SoleBeaconed_state_payload_t*)session->sync_state_payload)->expected =
    7.70 +                        identity_dup(partner);
    7.71 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=Beacon", "target=SoleBeaconed")
    7.72 +                    return SoleBeaconed;
    7.73 +                }
    7.74 +                case HandshakeRequest:
    7.75 +                {
    7.76 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=HandshakeRequest")
    7.77 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleWaiting, event=HandshakeRequest", "action=sendHandshakeRequest")
    7.78 +                    status = sendHandshakeRequest(session, state, partner, NULL);
    7.79 +                    if (status == PEP_OUT_OF_MEMORY)
    7.80 +                        return (int) invalid_out_of_memory;
    7.81 +                    if (status != PEP_STATUS_OK)
    7.82 +                        return (int) invalid_action;
    7.83 +                    session->sync_state_payload = malloc(sizeof(HandshakingSole_state_payload_t));
    7.84 +                    assert(session->sync_state_payload);
    7.85 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
    7.86 +                    ((HandshakingSole_state_payload_t*)session->sync_state_payload)->expected =
    7.87 +                        identity_dup(partner);
    7.88 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=HandshakeRequest", "target=HandshakingSole")
    7.89 +                    return HandshakingSole;
    7.90 +                }
    7.91 +                case Timeout:
    7.92 +                {
    7.93 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleWaiting", "event=Timeout")
    7.94 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleWaiting, event=Timeout", "target=Sole")
    7.95 +                    return Sole;
    7.96 +                }
    7.97 +                default:
    7.98 +                    return (DeviceState_state) invalid_event;
    7.99 +            }
   7.100 +            break;
   7.101 +        }
   7.102          case SoleBeaconed:
   7.103          {
   7.104              DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=SoleBeaconed")
   7.105 @@ -739,7 +816,8 @@
   7.106                          return (int) invalid_out_of_memory;
   7.107                      if (status != PEP_STATUS_OK)
   7.108                          return (int) invalid_action;
   7.109 -                    break;
   7.110 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Grouped, event=CannotDecrypt", "target=GroupWaiting")
   7.111 +                    return GroupWaiting;
   7.112                  }
   7.113                  case UpdateRequest:
   7.114                  {
   7.115 @@ -803,6 +881,110 @@
   7.116              }
   7.117              break;
   7.118          }
   7.119 +        case GroupWaiting:
   7.120 +        {
   7.121 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=GroupWaiting")
   7.122 +            switch (event) {
   7.123 +                case Init: 
   7.124 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Init") 
   7.125 +                    *timeout = 60;
   7.126 +                    break;
   7.127 +                case KeyGen:
   7.128 +                {
   7.129 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=KeyGen")
   7.130 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=KeyGen", "action=sendGroupUpdate")
   7.131 +                    status = sendGroupUpdate(session, state, NULL, NULL);
   7.132 +                    if (status == PEP_OUT_OF_MEMORY)
   7.133 +                        return (int) invalid_out_of_memory;
   7.134 +                    if (status != PEP_STATUS_OK)
   7.135 +                        return (int) invalid_action;
   7.136 +                    break;
   7.137 +                }
   7.138 +                case CannotDecrypt:
   7.139 +                {
   7.140 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=CannotDecrypt")
   7.141 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=CannotDecrypt", "action=sendUpdateRequest")
   7.142 +                    status = sendUpdateRequest(session, state, NULL, NULL);
   7.143 +                    if (status == PEP_OUT_OF_MEMORY)
   7.144 +                        return (int) invalid_out_of_memory;
   7.145 +                    if (status != PEP_STATUS_OK)
   7.146 +                        return (int) invalid_action;
   7.147 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=CannotDecrypt", "action=sendBeacon")
   7.148 +                    status = sendBeacon(session, state, NULL, NULL);
   7.149 +                    if (status == PEP_OUT_OF_MEMORY)
   7.150 +                        return (int) invalid_out_of_memory;
   7.151 +                    if (status != PEP_STATUS_OK)
   7.152 +                        return (int) invalid_action;
   7.153 +                    break;
   7.154 +                }
   7.155 +                case UpdateRequest:
   7.156 +                {
   7.157 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=UpdateRequest")
   7.158 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=UpdateRequest", "action=sendGroupUpdate")
   7.159 +                    status = sendGroupUpdate(session, state, NULL, NULL);
   7.160 +                    if (status == PEP_OUT_OF_MEMORY)
   7.161 +                        return (int) invalid_out_of_memory;
   7.162 +                    if (status != PEP_STATUS_OK)
   7.163 +                        return (int) invalid_action;
   7.164 +                    break;
   7.165 +                }
   7.166 +                case Beacon:
   7.167 +                {
   7.168 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Beacon")
   7.169 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=Beacon", "action=sendHandshakeRequest")
   7.170 +                    status = sendHandshakeRequest(session, state, partner, NULL);
   7.171 +                    if (status == PEP_OUT_OF_MEMORY)
   7.172 +                        return (int) invalid_out_of_memory;
   7.173 +                    if (status != PEP_STATUS_OK)
   7.174 +                        return (int) invalid_action;
   7.175 +                    session->sync_state_payload = malloc(sizeof(GroupedBeaconed_state_payload_t));
   7.176 +                    assert(session->sync_state_payload);
   7.177 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
   7.178 +                    ((GroupedBeaconed_state_payload_t*)session->sync_state_payload)->expected =
   7.179 +                        identity_dup(partner);
   7.180 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=Beacon", "target=GroupedBeaconed")
   7.181 +                    return GroupedBeaconed;
   7.182 +                }
   7.183 +                case HandshakeRequest:
   7.184 +                {
   7.185 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=HandshakeRequest")
   7.186 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=HandshakeRequest", "action=sendHandshakeRequest")
   7.187 +                    status = sendHandshakeRequest(session, state, partner, NULL);
   7.188 +                    if (status == PEP_OUT_OF_MEMORY)
   7.189 +                        return (int) invalid_out_of_memory;
   7.190 +                    if (status != PEP_STATUS_OK)
   7.191 +                        return (int) invalid_action;
   7.192 +                    session->sync_state_payload = malloc(sizeof(HandshakingGrouped_state_payload_t));
   7.193 +                    assert(session->sync_state_payload);
   7.194 +                    if(!session->sync_state_payload) return (DeviceState_state) invalid_out_of_memory;
   7.195 +                    ((HandshakingGrouped_state_payload_t*)session->sync_state_payload)->expected =
   7.196 +                        identity_dup(partner);
   7.197 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=HandshakeRequest", "target=HandshakingGrouped")
   7.198 +                    return HandshakingGrouped;
   7.199 +                }
   7.200 +                case GroupUpdate:
   7.201 +                {
   7.202 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=GroupUpdate")
   7.203 +                    identity_list* keys = (identity_list*)extra;
   7.204 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupWaiting, event=GroupUpdate", "action=storeGroupUpdate")
   7.205 +                    status = storeGroupUpdate(session, state, partner, keys);
   7.206 +                    if (status == PEP_OUT_OF_MEMORY)
   7.207 +                        return (int) invalid_out_of_memory;
   7.208 +                    if (status != PEP_STATUS_OK)
   7.209 +                        return (int) invalid_action;
   7.210 +                    break;
   7.211 +                }
   7.212 +                case Timeout:
   7.213 +                {
   7.214 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupWaiting", "event=Timeout")
   7.215 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupWaiting, event=Timeout", "target=Grouped")
   7.216 +                    return Grouped;
   7.217 +                }
   7.218 +                default:
   7.219 +                    return (DeviceState_state) invalid_event;
   7.220 +            }
   7.221 +            break;
   7.222 +        }
   7.223          case GroupedBeaconed:
   7.224          {
   7.225              DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=GroupedBeaconed")
     8.1 --- a/sync/generated/sync_fsm.h	Fri Apr 21 21:39:42 2017 +0200
     8.2 +++ b/sync/generated/sync_fsm.h	Mon May 08 08:18:47 2017 +0200
     8.3 @@ -47,11 +47,13 @@
     8.4      DeviceState_state_NONE = 0,
     8.5      InitState, 
     8.6      Sole, 
     8.7 +    SoleWaiting, 
     8.8      SoleBeaconed, 
     8.9      HandshakingSole, 
    8.10      WaitForGroupKeysSole, 
    8.11      WaitForAcceptSole, 
    8.12      Grouped, 
    8.13 +    GroupWaiting, 
    8.14      GroupedBeaconed, 
    8.15      HandshakingGrouped, 
    8.16      WaitForGroupKeysGrouped, 
     9.1 --- a/test/trustwords_test.cc	Fri Apr 21 21:39:42 2017 +0200
     9.2 +++ b/test/trustwords_test.cc	Mon May 08 08:18:47 2017 +0200
     9.3 @@ -33,6 +33,12 @@
     9.4          "blargh",
     9.5          "Krista Grothoff");
     9.6      
     9.7 +    pEp_identity* identity2_with_spaces = new_identity(
     9.8 +        "krista@kgrothoff.org",
     9.9 +        " 62D4932086185C159 17B72D30571A FBCA    5493553   ",
    9.10 +        "blargh",
    9.11 +        "Krista Grothoff");
    9.12 +    
    9.13      string fingerprint1 = identity1->fpr;
    9.14      string fingerprint2 = identity2->fpr;
    9.15      char* words1 = nullptr;
    9.16 @@ -58,6 +64,11 @@
    9.17      get_trustwords(session, identity1, identity2, "de", &full_wordlist, &wsize_full, false);
    9.18      assert(full_wordlist);
    9.19      cout << full_wordlist << "\n";
    9.20 +
    9.21 +    cout << "\nfinding Englis trustwords for " << identity1->address << " and " << identity2->address << "... with spaces\n";
    9.22 +    get_trustwords(session, identity1, identity2_with_spaces, "en", &full_wordlist, &wsize_full, false);
    9.23 +    assert(full_wordlist);
    9.24 +    cout << full_wordlist << "\n";
    9.25      
    9.26      
    9.27      pEp_free(words1);
    9.28 @@ -79,6 +90,11 @@
    9.29      assert(full_wordlist);
    9.30      cout << full_wordlist << "\n";
    9.31  
    9.32 +    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "... with spaces\n";
    9.33 +    get_trustwords(session, identity2, identity2_with_spaces, "en", &full_wordlist, &wsize_full, false);
    9.34 +    assert(full_wordlist);
    9.35 +    cout << full_wordlist << "\n";
    9.36 +
    9.37      pEp_free(words1);
    9.38      words1 = nullptr;
    9.39      pEp_free(full_wordlist);
    9.40 @@ -101,6 +117,11 @@
    9.41      assert(full_wordlist);
    9.42      cout << full_wordlist << "\n";
    9.43      
    9.44 +    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "... with spaces\n";
    9.45 +    get_trustwords(session, identity2_with_spaces, identity1, "en", &full_wordlist, &wsize_full, false);
    9.46 +    assert(full_wordlist);
    9.47 +    cout << full_wordlist << "\n";
    9.48 +    
    9.49      pEp_free(words1);
    9.50      words1 = nullptr;
    9.51      pEp_free(words2);