Merged latest default in test_diphoton test_diphoton
authorEdouard Tisserant <edouard@pep-project.org>
Wed, 21 Jun 2017 15:43:54 +0200
branchtest_diphoton
changeset 1883183848e382a2
parent 1860 1975a3b9bc37
parent 1877 e2f357447046
child 1903 c2a9a756b1f5
Merged latest default in test_diphoton
     1.1 --- a/src/message_api.c	Thu Jun 15 11:35:44 2017 +0200
     1.2 +++ b/src/message_api.c	Wed Jun 21 15:43:54 2017 +0200
     1.3 @@ -826,69 +826,61 @@
     1.4  
     1.5  
     1.6      PEP_comm_type bare_comm_type = PEP_ct_unknown;
     1.7 +    PEP_comm_type resulting_comm_type = PEP_ct_unknown;
     1.8      PEP_STATUS status = get_key_rating(session, fpr, &bare_comm_type);
     1.9      if (status != PEP_STATUS_OK)
    1.10          return PEP_rating_undefined;
    1.11  
    1.12 -    PEP_comm_type least_trust_type = PEP_ct_unknown;
    1.13 -    least_trust(session, fpr, &least_trust_type);
    1.14 -
    1.15 -    if (least_trust_type == PEP_ct_unknown) {
    1.16 -        return _rating(bare_comm_type, PEP_rating_undefined);
    1.17 +    PEP_comm_type least_comm_type = PEP_ct_unknown;
    1.18 +    least_trust(session, fpr, &least_comm_type);
    1.19 +
    1.20 +    if (least_comm_type == PEP_ct_unknown) {
    1.21 +        resulting_comm_type = bare_comm_type;
    1.22 +    } else if (least_comm_type < PEP_ct_strong_but_unconfirmed ||
    1.23 +               bare_comm_type < PEP_ct_strong_but_unconfirmed) {
    1.24 +        // take minimum if anything bad
    1.25 +        resulting_comm_type = least_comm_type < bare_comm_type ? 
    1.26 +                              least_comm_type : 
    1.27 +                              bare_comm_type;
    1.28      } else {
    1.29 -        return _rating(least_trust_type, PEP_rating_undefined);
    1.30 +        resulting_comm_type = least_comm_type;
    1.31      }
    1.32 +    return _rating(resulting_comm_type, PEP_rating_undefined);
    1.33  }
    1.34  
    1.35  static PEP_rating worst_rating(PEP_rating rating1, PEP_rating rating2) {
    1.36      return ((rating1 < rating2) ? rating1 : rating2);
    1.37  }
    1.38  
    1.39 -static PEP_rating keylist_rating(PEP_SESSION session, stringlist_t *keylist)
    1.40 +static PEP_rating keylist_rating(PEP_SESSION session, stringlist_t *keylist, char* sender_fpr, PEP_rating sender_rating)
    1.41  {
    1.42 -    PEP_rating rating = PEP_rating_undefined;
    1.43 +    PEP_rating rating = sender_rating;
    1.44  
    1.45      assert(keylist && keylist->value);
    1.46      if (keylist == NULL || keylist->value == NULL)
    1.47          return PEP_rating_undefined;
    1.48  
    1.49      stringlist_t *_kl;
    1.50 -    bool first = true;
    1.51      for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
    1.52 -        PEP_comm_type ct;
    1.53 -        PEP_STATUS status;
    1.54 +
    1.55 +        // Ignore own fpr
    1.56 +        if(_same_fpr(sender_fpr, strlen(sender_fpr), _kl->value, strlen(_kl->value)))
    1.57 +            continue;
    1.58  
    1.59          PEP_rating _rating_ = key_rating(session, _kl->value);
    1.60           
    1.61          if (_rating_ <= PEP_rating_mistrust)
    1.62              return _rating_;
    1.63              
    1.64 -        if (first) {
    1.65 -            rating = _rating_;
    1.66 -            first = false;
    1.67 -        }
    1.68 -        else if (rating == PEP_rating_undefined)
    1.69 -            rating = worst_rating(rating, _rating_);
    1.70 -
    1.71 -        if (_rating_ >= PEP_rating_reliable) {
    1.72 -            status = least_trust(session, _kl->value, &ct);
    1.73 -            if (status != PEP_STATUS_OK)
    1.74 -                return PEP_rating_undefined;
    1.75 -            if (ct == PEP_ct_unknown){
    1.76 -                /* per edouard, we reduce reliable+ ratings to reliable because
    1.77 -                   ct unknown */
    1.78 -                if (rating >= PEP_rating_reliable){
    1.79 -                    rating = PEP_rating_reliable; 
    1.80 -                }
    1.81 -            }
    1.82 -            else{
    1.83 -                rating = worst_rating(rating, _rating(ct, rating));
    1.84 -            }
    1.85 -        }
    1.86 -        else if (_rating_ == PEP_rating_unencrypted) {
    1.87 +        if (_rating_ == PEP_rating_unencrypted)
    1.88 +        {
    1.89              if (rating > PEP_rating_unencrypted_for_some)
    1.90                  rating = worst_rating(rating, PEP_rating_unencrypted_for_some);
    1.91          }
    1.92 +        else
    1.93 +        {
    1.94 +            rating = worst_rating(rating, _rating_);
    1.95 +        }
    1.96      }
    1.97  
    1.98      return rating;
    1.99 @@ -995,8 +987,13 @@
   1.100          if (bl && bl->value && bl->size && bl->size < MAX_KEY_SIZE
   1.101                  && is_key(bl))
   1.102          {
   1.103 -            import_key(session, bl->value, bl->size, private_idents);
   1.104 +            identity_list *local_private_idents = NULL;
   1.105 +            import_key(session, bl->value, bl->size, &local_private_idents);
   1.106              remove = true;
   1.107 +            if (private_idents && *private_idents == NULL && local_private_idents != NULL)
   1.108 +                *private_idents = local_private_idents;
   1.109 +            else
   1.110 +                free_identity_list(local_private_idents);
   1.111          }
   1.112      }
   1.113      return remove;
   1.114 @@ -1604,38 +1601,32 @@
   1.115      PEP_STATUS status = PEP_STATUS_OK;
   1.116  
   1.117      if (*rating > PEP_rating_mistrust) {
   1.118 -        PEP_rating kl_rating = PEP_rating_undefined;
   1.119 -
   1.120 -        if (recipients)
   1.121 -            kl_rating = keylist_rating(session, recipients);
   1.122 -
   1.123 -        if (kl_rating <= PEP_rating_mistrust) {
   1.124 -            *rating = kl_rating;
   1.125 +
   1.126 +        if (recipients == NULL) {
   1.127 +            *rating = PEP_rating_undefined;
   1.128 +            return PEP_STATUS_OK;
   1.129          }
   1.130 -        else if (*rating >= PEP_rating_reliable &&
   1.131 -                 kl_rating < PEP_rating_reliable) {
   1.132 +
   1.133 +        char *fpr = recipients->value;
   1.134 +
   1.135 +        if (!(sender && sender->user_id && sender->user_id[0] && fpr && fpr[0])) {
   1.136              *rating = PEP_rating_unreliable;
   1.137          }
   1.138 -        else if (*rating >= PEP_rating_reliable &&
   1.139 -                 kl_rating >= PEP_rating_reliable) {
   1.140 -            if (!(sender && sender->user_id && sender->user_id[0])) {
   1.141 -                *rating = PEP_rating_unreliable;
   1.142 +        else {
   1.143 +            pEp_identity *_sender = new_identity(sender->address, fpr,
   1.144 +                                               sender->user_id, sender->username);
   1.145 +            if (_sender == NULL)
   1.146 +                return PEP_OUT_OF_MEMORY;
   1.147 +
   1.148 +            status = get_trust(session, _sender);
   1.149 +            if (_sender->comm_type != PEP_ct_unknown) {
   1.150 +                *rating = keylist_rating(session, recipients, 
   1.151 +                            fpr, _rating(_sender->comm_type, 
   1.152 +                                          PEP_rating_undefined));
   1.153              }
   1.154 -            else {
   1.155 -                char *fpr = recipients->value;
   1.156 -                pEp_identity *_sender = new_identity(sender->address, fpr,
   1.157 -                                                   sender->user_id, sender->username);
   1.158 -                if (_sender == NULL)
   1.159 -                    return PEP_OUT_OF_MEMORY;
   1.160 -                status = get_trust(session, _sender);
   1.161 -                if (_sender->comm_type != PEP_ct_unknown) {
   1.162 -                    *rating = worst_rating(_rating(_sender->comm_type, PEP_rating_undefined),
   1.163 -                              kl_rating);
   1.164 -                }
   1.165 -                free_identity(_sender);
   1.166 -                if (status == PEP_CANNOT_FIND_IDENTITY)
   1.167 -                   status = PEP_STATUS_OK;
   1.168 -            }
   1.169 +            free_identity(_sender);
   1.170 +            if (status == PEP_CANNOT_FIND_IDENTITY)
   1.171 +               status = PEP_STATUS_OK;
   1.172          }
   1.173      }
   1.174      return status;
   1.175 @@ -2299,6 +2290,74 @@
   1.176      return PEP_color_no_color;
   1.177  }
   1.178  
   1.179 +/* [0-9]: 0x30 - 0x39; [A-F] = 0x41 - 0x46; [a-f] = 0x61 - 0x66 */
   1.180 +static short asciihex_to_num(char a) {
   1.181 +    short conv_num = -1;
   1.182 +    if (a >= 0x30 && a <= 0x39)
   1.183 +        conv_num = a - 0x30;
   1.184 +    else {
   1.185 +        // convert case, subtract offset, get number
   1.186 +        conv_num = ((a | 0x20) - 0x61) + 10;
   1.187 +        if (conv_num < 0xa || conv_num > 0xf)
   1.188 +            conv_num = -1;
   1.189 +    }
   1.190 +    return conv_num;
   1.191 +}
   1.192 +
   1.193 +static char num_to_asciihex(short h) {
   1.194 +    if (h < 0 || h > 16)
   1.195 +        return '\0';
   1.196 +    if (h < 10)
   1.197 +        return (char)(h + 0x30);
   1.198 +    return (char)((h - 10) + 0x41); // for readability
   1.199 +}
   1.200 +
   1.201 +static char xor_hex_chars(char a, char b) {
   1.202 +    short a_num = asciihex_to_num(a);
   1.203 +    short b_num = asciihex_to_num(b);
   1.204 +    if (a_num < 0 || b_num < 0)
   1.205 +        return '\0';
   1.206 +    short xor_num = a_num^b_num;
   1.207 +    return num_to_asciihex(xor_num);
   1.208 +}
   1.209 +
   1.210 +static char* skip_separators(char* current, char* begin) {
   1.211 +    while (current >= begin) {
   1.212 +        /* .:,;-_ ' ' - [2c-2e] [3a-3b] [20] [5f] */
   1.213 +        char check_char = *current;
   1.214 +        switch (check_char) {
   1.215 +            case '.':
   1.216 +            case ':':
   1.217 +            case ',':
   1.218 +            case ';':
   1.219 +            case '-':
   1.220 +            case '_':
   1.221 +            case ' ':
   1.222 +                current--;
   1.223 +                continue;
   1.224 +            default:
   1.225 +                break;
   1.226 +        }
   1.227 +        break;
   1.228 +    }
   1.229 +    return current;
   1.230 +}
   1.231 +
   1.232 +PEP_STATUS check_for_zero_fpr(char* fpr) {
   1.233 +    PEP_STATUS status = PEP_TRUSTWORDS_DUPLICATE_FPR;
   1.234 +    
   1.235 +    while (*fpr) {
   1.236 +        if (*fpr != '0') {
   1.237 +            status = PEP_STATUS_OK;
   1.238 +            break;
   1.239 +        }
   1.240 +        fpr++;    
   1.241 +    }
   1.242 +    
   1.243 +    return status;
   1.244 +    
   1.245 +}
   1.246 +
   1.247  DYNAMIC_API PEP_STATUS get_trustwords(
   1.248      PEP_SESSION session, const pEp_identity* id1, const pEp_identity* id2,
   1.249      const char* lang, char **words, size_t *wsize, bool full
   1.250 @@ -2312,95 +2371,113 @@
   1.251      assert(words);
   1.252      assert(wsize);
   1.253  
   1.254 +    int SHORT_NUM_TWORDS = 5; 
   1.255 +    
   1.256 +    PEP_STATUS status = PEP_STATUS_OK;
   1.257 +    
   1.258      if (!(session && id1 && id2 && words && wsize) ||
   1.259          !(id1->fpr) || (!id2->fpr))
   1.260          return PEP_ILLEGAL_VALUE;
   1.261  
   1.262 -    const char *source1 = id1->fpr;
   1.263 -    const char *source2 = id2->fpr;
   1.264 -
   1.265 -    *words = NULL;
   1.266 +    char *source1 = id1->fpr;
   1.267 +    char *source2 = id2->fpr;
   1.268 +
   1.269 +    int source1_len = strlen(source1);
   1.270 +    int source2_len = strlen(source2);
   1.271 +    int max_len;
   1.272 +        
   1.273 +    *words = NULL;    
   1.274      *wsize = 0;
   1.275  
   1.276 -    const size_t SHORT_NUM_TWORDS = 5;
   1.277 -
   1.278 -    // N.B. THIS will have to be changed once we start checking trustword entropy.
   1.279 -    // For now, full is ALL, and otherwise it's 5-per-id.
   1.280 -    size_t max_words_per_id = (full ? 0 : SHORT_NUM_TWORDS);
   1.281 -
   1.282 -    char* first_set = NULL;
   1.283 -    char* second_set = NULL;
   1.284 -    size_t first_wsize = 0;
   1.285 -    size_t second_wsize = 0;
   1.286 -
   1.287 -    int fpr_comparison = -255;
   1.288 -    PEP_STATUS status = _compare_fprs(source1, strlen(source1), source2, strlen(source2), &fpr_comparison);
   1.289 -    if (status != PEP_STATUS_OK)
   1.290 -        return status;
   1.291 -
   1.292 -    char* _retstr = NULL;
   1.293 -
   1.294 -    switch (fpr_comparison) {
   1.295 -        case 1: // source1 > source2
   1.296 -            status = trustwords(session, source2, lang, &first_set, &first_wsize, max_words_per_id);
   1.297 -            if (status != PEP_STATUS_OK)
   1.298 -                goto error_release;
   1.299 -            status = trustwords(session, source1, lang, &second_set, &second_wsize, max_words_per_id);
   1.300 -            if (status != PEP_STATUS_OK)
   1.301 -                goto error_release;
   1.302 +    max_len = (source1_len > source2_len ? source1_len : source2_len);
   1.303 +    
   1.304 +    char* XORed_fpr = (char*)(calloc(1,max_len + 1));
   1.305 +    *(XORed_fpr + max_len) = '\0';
   1.306 +    char* result_curr = XORed_fpr + max_len - 1;
   1.307 +    char* source1_curr = source1 + source1_len - 1;
   1.308 +    char* source2_curr = source2 + source2_len - 1;
   1.309 +
   1.310 +    while (source1 <= source1_curr && source2 <= source2_curr) {
   1.311 +        source1_curr = skip_separators(source1_curr, source1);
   1.312 +        source2_curr = skip_separators(source2_curr, source2);
   1.313 +        
   1.314 +        if (source1_curr < source1 || source2_curr < source2)
   1.315              break;
   1.316 -        case 0:
   1.317 -        case -1: // source1 <= source2
   1.318 -            status = trustwords(session, source1, lang, &first_set, &first_wsize, max_words_per_id);
   1.319 -            if (status != PEP_STATUS_OK)
   1.320 -                goto error_release;
   1.321 -            status = trustwords(session, source2, lang, &second_set, &second_wsize, max_words_per_id);
   1.322 -            if (status != PEP_STATUS_OK)
   1.323 -                goto error_release;
   1.324 -            break;
   1.325 -        default:
   1.326 -            return ADD_TO_LOG(PEP_UNKNOWN_ERROR); // shouldn't be possible
   1.327 -    }
   1.328 -
   1.329 -    size_t _wsize = first_wsize + second_wsize;
   1.330 -
   1.331 -    bool needs_space = (first_set[first_wsize - 1] != ' ');
   1.332 -
   1.333 -    if (needs_space)
   1.334 -        _wsize++;
   1.335 -
   1.336 -    _retstr = calloc(1, _wsize + 1);
   1.337 -
   1.338 -    size_t len = strlcpy(_retstr, first_set, _wsize);
   1.339 -    if (len >= _wsize) {
   1.340 -        status = PEP_UNKNOWN_ERROR;
   1.341 -        goto error_release;
   1.342 -    }
   1.343 -    if (needs_space) {
   1.344 -        strlcat(_retstr, " ", _wsize);
   1.345 -        if (len >= _wsize) {
   1.346 -            status = PEP_UNKNOWN_ERROR;
   1.347 +            
   1.348 +        char xor_hex = xor_hex_chars(*source1_curr, *source2_curr);
   1.349 +        if (xor_hex == '\0') {
   1.350 +            status = PEP_ILLEGAL_VALUE;
   1.351              goto error_release;
   1.352          }
   1.353 +        
   1.354 +        *result_curr = xor_hex;
   1.355 +        result_curr--; source1_curr--; source2_curr--;
   1.356      }
   1.357 -    strlcat(_retstr, second_set, _wsize);
   1.358 -    if (len >= _wsize){
   1.359 -        status = PEP_UNKNOWN_ERROR;
   1.360 +
   1.361 +    char* remainder_start = NULL;
   1.362 +    char* remainder_curr = NULL;
   1.363 +    
   1.364 +    if (source1 <= source1_curr) {
   1.365 +        remainder_start = source1;
   1.366 +        remainder_curr = source1_curr;
   1.367 +    }
   1.368 +    else if (source2 <= source2_curr) {
   1.369 +        remainder_start = source2;
   1.370 +        remainder_curr = source2_curr;
   1.371 +    }
   1.372 +    if (remainder_curr) {
   1.373 +        while (remainder_start <= remainder_curr) {
   1.374 +            remainder_curr = skip_separators(remainder_curr, remainder_start);
   1.375 +            
   1.376 +            if (remainder_curr < remainder_start)
   1.377 +                break;
   1.378 +            
   1.379 +            char the_char = *remainder_curr;
   1.380 +            
   1.381 +            if (asciihex_to_num(the_char) < 0) {
   1.382 +                status = PEP_ILLEGAL_VALUE;
   1.383 +                goto error_release;
   1.384 +            }
   1.385 +            
   1.386 +            *result_curr = the_char;                
   1.387 +            result_curr--;
   1.388 +            remainder_curr--;
   1.389 +        }
   1.390 +    }
   1.391 +    
   1.392 +    result_curr++;
   1.393 +
   1.394 +    if (result_curr > XORed_fpr) {
   1.395 +        char* tempstr = strdup(result_curr);
   1.396 +        free(XORed_fpr);
   1.397 +        XORed_fpr = tempstr;
   1.398 +    }
   1.399 +    
   1.400 +    status = check_for_zero_fpr(XORed_fpr);
   1.401 +    
   1.402 +    if (status != PEP_STATUS_OK)
   1.403          goto error_release;
   1.404 -    }
   1.405 -
   1.406 -    *words = _retstr;
   1.407 -    *wsize = _wsize;
   1.408 +    
   1.409 +    size_t max_words_per_id = (full ? 0 : SHORT_NUM_TWORDS);
   1.410 +
   1.411 +    char* the_words = NULL;
   1.412 +    size_t the_size = 0;
   1.413 +
   1.414 +    status = trustwords(session, XORed_fpr, lang, &the_words, &the_size, max_words_per_id);
   1.415 +    if (status != PEP_STATUS_OK)
   1.416 +        goto error_release;
   1.417 +
   1.418 +    *words = the_words;
   1.419 +    *wsize = the_size;
   1.420 +    
   1.421      status = PEP_STATUS_OK;
   1.422  
   1.423      goto the_end;
   1.424  
   1.425      error_release:
   1.426 -    free(_retstr);
   1.427 -
   1.428 +        free (XORed_fpr);
   1.429 +        
   1.430      the_end:
   1.431 -    free(first_set);
   1.432 -    free(second_set);
   1.433      return ADD_TO_LOG(status);
   1.434  }
   1.435  
     2.1 --- a/src/message_api.h	Thu Jun 15 11:35:44 2017 +0200
     2.2 +++ b/src/message_api.h	Wed Jun 21 15:43:54 2017 +0200
     2.3 @@ -18,8 +18,11 @@
     2.4          const message *msg,
     2.5          identity_list **private_idents
     2.6      );
     2.7 +
     2.8  void attach_own_key(PEP_SESSION session, message *msg);
     2.9 +
    2.10  PEP_cryptotech determine_encryption_format(message *msg);
    2.11 +
    2.12  void add_opt_field(message *msg, const char *name, const char *value);
    2.13  
    2.14  typedef enum _PEP_encrypt_flags {
    2.15 @@ -35,6 +38,7 @@
    2.16  
    2.17  typedef unsigned int PEP_encrypt_flags_t;
    2.18  
    2.19 +
    2.20  // encrypt_message() - encrypt message in memory
    2.21  //
    2.22  //  parameters:
    2.23 @@ -47,19 +51,18 @@
    2.24  //
    2.25  //  return value:
    2.26  //      PEP_STATUS_OK                   on success
    2.27 -//      PEP_KEY_NOT_FOUND	            at least one of the receipient keys
    2.28 +//      PEP_KEY_NOT_FOUND               at least one of the receipient keys
    2.29  //                                      could not be found
    2.30  //      PEP_KEY_HAS_AMBIG_NAME          at least one of the receipient keys has
    2.31  //                                      an ambiguous name
    2.32 -//      PEP_GET_KEY_FAILED		        cannot retrieve key
    2.33 +//      PEP_GET_KEY_FAILED              cannot retrieve key
    2.34  //      PEP_UNENCRYPTED                 no recipients with usable key, 
    2.35  //                                      message is left unencrypted,
    2.36  //                                      and key is attached to it
    2.37  //
    2.38 -//	caveat:
    2.39 -//	    the ownershop of src remains with the caller
    2.40 -//	    the ownership of dst goes to the caller
    2.41 -
    2.42 +//  caveat:
    2.43 +//      the ownershop of src remains with the caller
    2.44 +//      the ownership of dst goes to the caller
    2.45  DYNAMIC_API PEP_STATUS encrypt_message(
    2.46          PEP_SESSION session,
    2.47          message *src,
    2.48 @@ -69,6 +72,7 @@
    2.49          PEP_encrypt_flags_t flags
    2.50      );
    2.51  
    2.52 +
    2.53  // encrypt_message_for_self() - encrypt message in memory for user's identity only,
    2.54  //                              ignoring recipients and other identities from
    2.55  //                              the message
    2.56 @@ -81,20 +85,19 @@
    2.57  //      flags (in)          flags to set special encryption features
    2.58  //
    2.59  //  return value:       (FIXME: This may not be correct or complete)
    2.60 -//      PEP_STATUS_OK                   on success
    2.61 -//		PEP_KEY_NOT_FOUND	            at least one of the receipient keys
    2.62 -//		                                could not be found
    2.63 -//		PEP_KEY_HAS_AMBIG_NAME          at least one of the receipient keys has
    2.64 -//		                                an ambiguous name
    2.65 -//		PEP_GET_KEY_FAILED		        cannot retrieve key
    2.66 +//      PEP_STATUS_OK            on success
    2.67 +//      PEP_KEY_NOT_FOUND        at least one of the receipient keys
    2.68 +//                               could not be found
    2.69 +//      PEP_KEY_HAS_AMBIG_NAME   at least one of the receipient keys has
    2.70 +//                               an ambiguous name
    2.71 +//      PEP_GET_KEY_FAILED       cannot retrieve key
    2.72  //
    2.73 -//	caveat:
    2.74 -//	    the ownership of src remains with the caller
    2.75 +//  caveat:
    2.76 +//      the ownership of src remains with the caller
    2.77  //      the ownership of target_id remains w/ caller            
    2.78 -//	    the ownership of dst goes to the caller
    2.79 +//      the ownership of dst goes to the caller
    2.80  //      message is NOT encrypted for identities other than the target_id (and then,
    2.81 -//          only if the target_id refers to self!)
    2.82 -
    2.83 +//      only if the target_id refers to self!)
    2.84  DYNAMIC_API PEP_STATUS encrypt_message_for_self(
    2.85          PEP_SESSION session,
    2.86          pEp_identity* target_id,
    2.87 @@ -104,6 +107,7 @@
    2.88          PEP_encrypt_flags_t flags
    2.89      );
    2.90  
    2.91 +
    2.92  // MIME_encrypt_message() - encrypt a MIME message, with MIME output
    2.93  //
    2.94  //  parameters:
    2.95 @@ -127,7 +131,6 @@
    2.96  //  caveat:
    2.97  //      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
    2.98  //      will remain in the ownership of the caller
    2.99 -
   2.100  DYNAMIC_API PEP_STATUS MIME_encrypt_message(
   2.101      PEP_SESSION session,
   2.102      const char *mimetext,
   2.103 @@ -138,12 +141,13 @@
   2.104      PEP_encrypt_flags_t flags
   2.105  );
   2.106  
   2.107 +
   2.108  // MIME_encrypt_message_for_self() - encrypt MIME message for user's identity only,
   2.109  //                              ignoring recipients and other identities from
   2.110  //                              the message, with MIME output
   2.111  //  parameters:
   2.112  //      session (in)            session handle
   2.113 -//      target_id (in)      self identity this message should be encrypted for
   2.114 +//      target_id (in)          self identity this message should be encrypted for
   2.115  //      mimetext (in)           MIME encoded text to encrypt
   2.116  //      size (in)               size of input mime text
   2.117  //      mime_ciphertext (out)   encrypted, encoded message
   2.118 @@ -162,7 +166,6 @@
   2.119  //  caveat:
   2.120  //      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   2.121  //      will remain in the ownership of the caller
   2.122 -
   2.123  DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
   2.124      PEP_SESSION session,
   2.125      pEp_identity* target_id,
   2.126 @@ -174,7 +177,6 @@
   2.127  );
   2.128  
   2.129  
   2.130 -
   2.131  typedef enum _PEP_rating {
   2.132      PEP_rating_undefined = 0,
   2.133      PEP_rating_cannot_decrypt,
   2.134 @@ -199,13 +201,13 @@
   2.135      PEP_color_red = -1,
   2.136  } PEP_color;
   2.137  
   2.138 +
   2.139  // color_from_rating - calculate color from rating
   2.140  //
   2.141  //  parameters:
   2.142  //      rating (in)         rating
   2.143  //
   2.144  //  return value:           color representing that rating
   2.145 -
   2.146  DYNAMIC_API PEP_color color_from_rating(PEP_rating rating);
   2.147  
   2.148  typedef enum _PEP_decrypt_flags {
   2.149 @@ -216,6 +218,7 @@
   2.150  
   2.151  typedef unsigned int PEP_decrypt_flags_t;
   2.152  
   2.153 +
   2.154  // decrypt_message() - decrypt message in memory
   2.155  //
   2.156  //  parameters:
   2.157 @@ -231,13 +234,12 @@
   2.158  //      or PEP_DECRYPTED if message decrypted but not verified
   2.159  //      or PEP_STATUS_OK on success
   2.160  //
   2.161 -//	caveat:
   2.162 -//	    the ownership of src remains with the caller
   2.163 -//	    the ownership of dst goes to the caller
   2.164 -//	    the ownership of keylist goes to the caller
   2.165 -//	    if src is unencrypted this function returns PEP_UNENCRYPTED and sets
   2.166 -//	    dst to NULL
   2.167 -
   2.168 +// caveat:
   2.169 +//      the ownership of src remains with the caller
   2.170 +//      the ownership of dst goes to the caller
   2.171 +//      the ownership of keylist goes to the caller
   2.172 +//      if src is unencrypted this function returns PEP_UNENCRYPTED and sets
   2.173 +//      dst to NULL
   2.174  DYNAMIC_API PEP_STATUS decrypt_message(
   2.175          PEP_SESSION session,
   2.176          message *src,
   2.177 @@ -247,6 +249,7 @@
   2.178          PEP_decrypt_flags_t *flags
   2.179  );
   2.180  
   2.181 +
   2.182  // MIME_decrypt_message() - decrypt a MIME message, with MIME output
   2.183  //
   2.184  //  parameters:
   2.185 @@ -272,7 +275,6 @@
   2.186  //  caveat:
   2.187  //      the decrypted, encoded mime text will go to the ownership of the caller; mimetext
   2.188  //      will remain in the ownership of the caller
   2.189 -
   2.190  DYNAMIC_API PEP_STATUS MIME_decrypt_message(
   2.191      PEP_SESSION session,
   2.192      const char *mimetext,
   2.193 @@ -300,17 +302,17 @@
   2.194  //  return value:
   2.195  //      error status or PEP_STATUS_OK on success
   2.196  //
   2.197 -//	caveat:
   2.198 -//	    the ownership of msg remains with the caller
   2.199 -//	    the ownership of ident goes to the caller
   2.200 -//	    msg MUST be encrypted so that this function can check own signature
   2.201 -
   2.202 +//  caveat:
   2.203 +//      the ownership of msg remains with the caller
   2.204 +//      the ownership of ident goes to the caller
   2.205 +//      msg MUST be encrypted so that this function can check own signature
   2.206  DYNAMIC_API PEP_STATUS own_message_private_key_details(
   2.207          PEP_SESSION session,
   2.208          message *msg,
   2.209          pEp_identity **ident 
   2.210  );
   2.211  
   2.212 +
   2.213  // outgoing_message_rating() - get rating for an outgoing message
   2.214  //
   2.215  //  parameters:
   2.216 @@ -325,7 +327,6 @@
   2.217  //      msg->from must point to a valid pEp_identity
   2.218  //      msg->dir must be PEP_dir_outgoing
   2.219  //      the ownership of msg remains with the caller
   2.220 -
   2.221  DYNAMIC_API PEP_STATUS outgoing_message_rating(
   2.222          PEP_SESSION session,
   2.223          message *msg,
   2.224 @@ -345,7 +346,6 @@
   2.225  //
   2.226  //  caveat:
   2.227  //      the ownership of ident remains with the caller
   2.228 -
   2.229  DYNAMIC_API PEP_STATUS identity_rating(
   2.230          PEP_SESSION session,
   2.231          pEp_identity *ident,
   2.232 @@ -361,6 +361,7 @@
   2.233  //                          **path is owned by the library, do not change it!
   2.234  DYNAMIC_API PEP_STATUS get_binary_path(PEP_cryptotech tech, const char **path);
   2.235  
   2.236 +
   2.237  // get_trustwords() - get full trustwords string for a *pair* of identities
   2.238  //
   2.239  //    parameters:
   2.240 @@ -386,12 +387,12 @@
   2.241  //        the word pointer goes to the ownership of the caller
   2.242  //        the caller is responsible to free() it (on Windoze use pEp_free())
   2.243  //
   2.244 -
   2.245  DYNAMIC_API PEP_STATUS get_trustwords(
   2.246      PEP_SESSION session, const pEp_identity* id1, const pEp_identity* id2,
   2.247      const char* lang, char **words, size_t *wsize, bool full
   2.248  );
   2.249  
   2.250 +
   2.251  // get_message_trustwords() - get full trustwords string for message sender and reciever identities 
   2.252  //
   2.253  //    parameters:
     3.1 --- a/src/pEpEngine.h	Thu Jun 15 11:35:44 2017 +0200
     3.2 +++ b/src/pEpEngine.h	Wed Jun 21 15:43:54 2017 +0200
     3.3 @@ -68,6 +68,7 @@
     3.4  
     3.5      PEP_TRUSTWORD_NOT_FOUND                         = 0x0501,
     3.6      PEP_TRUSTWORDS_FPR_WRONG_LENGTH                 = 0x0502,
     3.7 +    PEP_TRUSTWORDS_DUPLICATE_FPR                    = 0x0503,
     3.8  
     3.9      PEP_CANNOT_CREATE_KEY                           = 0x0601,
    3.10      PEP_CANNOT_SEND_KEY                             = 0x0602,
     4.1 --- a/test/trustwords_test.cc	Thu Jun 15 11:35:44 2017 +0200
     4.2 +++ b/test/trustwords_test.cc	Wed Jun 21 15:43:54 2017 +0200
     4.3 @@ -14,6 +14,7 @@
     4.4      cout << "\n*** get_trustwords test ***\n\n";
     4.5  
     4.6      PEP_SESSION session = nullptr;
     4.7 +    PEP_STATUS status;
     4.8      
     4.9      cout << "calling init()\n";
    4.10      PEP_STATUS status1 = init(&session);
    4.11 @@ -55,29 +56,33 @@
    4.12      assert(words1);
    4.13      cout << words1 << "\n";
    4.14  
    4.15 +    free(words1);
    4.16 +    words1 = nullptr;
    4.17 +    
    4.18      cout << "\nfinding German trustwords for " << fingerprint2 << "...\n";
    4.19      trustwords(session, fingerprint2.c_str(), "de", &words2, &wsize2, 5);
    4.20      assert(words2);
    4.21      cout << words2 << "\n";
    4.22  
    4.23 +    free(words2);
    4.24 +    words1 = nullptr;
    4.25 +
    4.26      cout << "\nfinding German trustwords for " << identity1->address << " and " << identity2->address << "...\n";
    4.27      get_trustwords(session, identity1, identity2, "de", &full_wordlist, &wsize_full, false);
    4.28      assert(full_wordlist);
    4.29      cout << full_wordlist << "\n";
    4.30  
    4.31 -    cout << "\nfinding Englis trustwords for " << identity1->address << " and " << identity2->address << "... with spaces\n";
    4.32 +    free(full_wordlist);
    4.33 +    full_wordlist = nullptr;
    4.34 +
    4.35 +    cout << "\nfinding English trustwords for " << identity1->address << " and " << identity2->address << "... with spaces\n";
    4.36      get_trustwords(session, identity1, identity2_with_spaces, "en", &full_wordlist, &wsize_full, false);
    4.37      assert(full_wordlist);
    4.38      cout << full_wordlist << "\n";
    4.39 +
    4.40 +    free(full_wordlist);
    4.41 +    full_wordlist = nullptr;
    4.42      
    4.43 -    
    4.44 -    pEp_free(words1);
    4.45 -    words1 = nullptr;
    4.46 -    pEp_free(words2);
    4.47 -    words2 = nullptr;
    4.48 -    pEp_free(full_wordlist);
    4.49 -    full_wordlist = nullptr;
    4.50 -
    4.51      cout << "\nTest 2: fpr1 == fpr1, short" << endl;
    4.52      
    4.53      cout << "\nfinding French trustwords for " << fingerprint2 << "...\n";
    4.54 @@ -86,14 +91,14 @@
    4.55      cout << words1 << "\n";
    4.56          
    4.57      cout << "\nfinding French trustwords for " << identity2->address << " and " << identity2->address << "...\n";
    4.58 -    get_trustwords(session, identity2, identity2, "fr", &full_wordlist, &wsize_full, false);
    4.59 -    assert(full_wordlist);
    4.60 -    cout << full_wordlist << "\n";
    4.61 +    status = get_trustwords(session, identity2, identity2, "fr", &full_wordlist, &wsize_full, false);
    4.62 +    assert(status == PEP_TRUSTWORDS_DUPLICATE_FPR);
    4.63 +    cout << "Discovered duplicate fprs as desired" << endl;
    4.64  
    4.65      cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "... with spaces\n";
    4.66      get_trustwords(session, identity2, identity2_with_spaces, "en", &full_wordlist, &wsize_full, false);
    4.67 -    assert(full_wordlist);
    4.68 -    cout << full_wordlist << "\n";
    4.69 +    assert(status == PEP_TRUSTWORDS_DUPLICATE_FPR);
    4.70 +    cout << "Discovered duplicate fprs as desired" << endl;
    4.71  
    4.72      pEp_free(words1);
    4.73      words1 = nullptr;
    4.74 @@ -112,13 +117,13 @@
    4.75      assert(words2);
    4.76      cout << words2 << "\n";
    4.77      
    4.78 -    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "...\n";
    4.79 +    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity1->address << "...\n";
    4.80      get_trustwords(session, identity2, identity1, "en", &full_wordlist, &wsize_full, true);
    4.81      assert(full_wordlist);
    4.82      cout << full_wordlist << "\n";
    4.83      
    4.84 -    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity2->address << "... with spaces\n";
    4.85 -    get_trustwords(session, identity2_with_spaces, identity1, "en", &full_wordlist, &wsize_full, false);
    4.86 +    cout << "\nfinding English trustwords for " << identity2->address << " and " << identity1->address << "... with spaces\n";
    4.87 +    get_trustwords(session, identity2_with_spaces, identity1, "en", &full_wordlist, &wsize_full, true);
    4.88      assert(full_wordlist);
    4.89      cout << full_wordlist << "\n";
    4.90      
    4.91 @@ -199,18 +204,18 @@
    4.92      pEp_free(full_wordlist);
    4.93      full_wordlist = nullptr;
    4.94  
    4.95 -    cout << "\nTest 6: fpr2 is too short" << endl;
    4.96 +    cout << "\nTest 6: fpr2 is shorter" << endl;
    4.97      
    4.98      pEp_identity* identity6 = new_identity(
    4.99          "nobody4@kgrothoff.org",
   4.100 -        "01F932086185C15917B72D30571AFBCA5493553",
   4.101 +        "F1F932086185c15917B72D30571AFBCA5493553",
   4.102          "blargh",
   4.103          "Krista Grothoff");
   4.104      
   4.105      cout << "\nfinding Turkish trustwords for " << identity5->address << " and " << identity6->address << "...\n";
   4.106      PEP_STATUS status6 = get_trustwords(session, identity5, identity6, "tr", &full_wordlist, &wsize_full, false);
   4.107 -    assert(status6 == PEP_TRUSTWORDS_FPR_WRONG_LENGTH);
   4.108 -    cout << "Bad fpr length correctly recognised." << "\n";
   4.109 +    assert(status6 == PEP_STATUS_OK);
   4.110 +    cout << full_wordlist << endl;
   4.111      
   4.112      pEp_identity* identity7 = new_identity(
   4.113          "nobody5@kgrothoff.org",
   4.114 @@ -238,4 +243,3 @@
   4.115      release(session);
   4.116      return 0;
   4.117  }
   4.118 -