ENGINE 172 and ENGINE 180 merged into default. Additional flags now exist for encryption without signing and without attached keys, plus functionality - these are only to be used in strictly-predefined special cases
authorKrista Grothoff <krista@pep-project.org>
Mon, 13 Mar 2017 09:51:53 +0100
changeset 16455f5d81b05b0e
parent 1638 6474eeaee8e0
parent 1644 6b88877f8885
child 1648 158e65c83311
child 1649 a06807cad94d
child 1650 39375af2cfb5
ENGINE 172 and ENGINE 180 merged into default. Additional flags now exist for encryption without signing and without attached keys, plus functionality - these are only to be used in strictly-predefined special cases
     1.1 --- a/src/cryptotech.c	Fri Mar 10 14:17:43 2017 +0100
     1.2 +++ b/src/cryptotech.c	Mon Mar 13 09:51:53 2017 +0100
     1.3 @@ -36,6 +36,7 @@
     1.4          cryptotech[PEP_crypt_OpenPGP].confirmed_comm_type = PEP_ct_OpenPGP;
     1.5          cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify = pgp_decrypt_and_verify;
     1.6          cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign = pgp_encrypt_and_sign;
     1.7 +        cryptotech[PEP_crypt_OpenPGP].encrypt_only = pgp_encrypt_only;
     1.8          cryptotech[PEP_crypt_OpenPGP].verify_text = pgp_verify_text;
     1.9          cryptotech[PEP_crypt_OpenPGP].delete_keypair = pgp_delete_keypair;
    1.10          cryptotech[PEP_crypt_OpenPGP].export_key = pgp_export_keydata;
     2.1 --- a/src/cryptotech.h	Fri Mar 10 14:17:43 2017 +0100
     2.2 +++ b/src/cryptotech.h	Mon Mar 13 09:51:53 2017 +0100
     2.3 @@ -32,6 +32,11 @@
     2.4          size_t psize, char **ctext, size_t *csize
     2.5      );
     2.6  
     2.7 +typedef PEP_STATUS (*encrypt_only_t)(
     2.8 +        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
     2.9 +        size_t psize, char **ctext, size_t *csize
    2.10 +    );
    2.11 +
    2.12  typedef PEP_STATUS (*delete_keypair_t)(PEP_SESSION session, const char *fpr);
    2.13  
    2.14  typedef PEP_STATUS (*export_key_t)(
    2.15 @@ -92,6 +97,7 @@
    2.16      decrypt_and_verify_t decrypt_and_verify;
    2.17      verify_text_t verify_text;
    2.18      encrypt_and_sign_t encrypt_and_sign;
    2.19 +    encrypt_only_t encrypt_only;
    2.20      delete_keypair_t delete_keypair;
    2.21      export_key_t export_key;
    2.22      find_keys_t find_keys;
     3.1 --- a/src/keymanagement.c	Fri Mar 10 14:17:43 2017 +0100
     3.2 +++ b/src/keymanagement.c	Mon Mar 13 09:51:53 2017 +0100
     3.3 @@ -779,10 +779,10 @@
     3.4      assert(!EMPTYSTR(ident->address));
     3.5      assert(!EMPTYSTR(ident->user_id));
     3.6      assert(!EMPTYSTR(ident->fpr));
     3.7 -    assert(!ident->me);
     3.8 +//    assert(!ident->me);
     3.9  
    3.10      if (!ident || EMPTYSTR(ident->address) || EMPTYSTR(ident->user_id) ||
    3.11 -            EMPTYSTR(ident->fpr) || ident->me)
    3.12 +            EMPTYSTR(ident->fpr)) // || ident->me)
    3.13          return PEP_ILLEGAL_VALUE;
    3.14  
    3.15      status = update_identity(session, ident);
     4.1 --- a/src/message_api.c	Fri Mar 10 14:17:43 2017 +0100
     4.2 +++ b/src/message_api.c	Mon Mar 13 09:51:53 2017 +0100
     4.3 @@ -340,7 +340,8 @@
     4.4      PEP_SESSION session,
     4.5      const message *src,
     4.6      stringlist_t *keys,
     4.7 -    message *dst
     4.8 +    message *dst,
     4.9 +    PEP_encrypt_flags_t flags
    4.10      )
    4.11  {
    4.12      PEP_STATUS status = PEP_STATUS_OK;
    4.13 @@ -396,8 +397,12 @@
    4.14      if (mimetext == NULL)
    4.15          goto pep_error;
    4.16  
    4.17 -    status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
    4.18 -        &ctext, &csize);
    4.19 +    if (flags & PEP_encrypt_flag_force_unsigned)
    4.20 +        status = encrypt_only(session, keys, mimetext, strlen(mimetext),
    4.21 +            &ctext, &csize);
    4.22 +    else
    4.23 +        status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
    4.24 +            &ctext, &csize);
    4.25      free(mimetext);
    4.26      if (ctext == NULL)
    4.27          goto pep_error;
    4.28 @@ -439,7 +444,8 @@
    4.29      PEP_SESSION session,
    4.30      const message *src,
    4.31      stringlist_t *keys,
    4.32 -    message *dst
    4.33 +    message *dst,
    4.34 +    PEP_encrypt_flags_t flags
    4.35      )
    4.36  {
    4.37      PEP_STATUS status = PEP_STATUS_OK;
    4.38 @@ -453,6 +459,8 @@
    4.39  
    4.40      dst->enc_format = PEP_enc_pieces;
    4.41  
    4.42 +    bool nosign = (flags & PEP_encrypt_flag_force_unsigned);
    4.43 +
    4.44      if (src->shortmsg && src->shortmsg[0] && strcmp(src->shortmsg, "pEp") != 0) {
    4.45          if (session->unencrypted_subject) {
    4.46              dst->shortmsg = strdup(src->shortmsg);
    4.47 @@ -468,8 +476,12 @@
    4.48              free_ptext = true;
    4.49          }
    4.50  
    4.51 -        status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    4.52 -            &csize);
    4.53 +        if (nosign)
    4.54 +            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
    4.55 +                &csize);
    4.56 +        else 
    4.57 +            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    4.58 +                &csize);
    4.59          if (free_ptext)
    4.60              free(ptext);
    4.61          free_ptext = false;
    4.62 @@ -482,8 +494,12 @@
    4.63      }
    4.64      else if (src->longmsg && src->longmsg[0]) {
    4.65          ptext = src->longmsg;
    4.66 -        status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    4.67 -            &csize);
    4.68 +        if (nosign)
    4.69 +            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
    4.70 +                &csize);
    4.71 +        else 
    4.72 +            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    4.73 +                &csize);
    4.74          if (ctext) {
    4.75              dst->longmsg = ctext;
    4.76          }
    4.77 @@ -500,8 +516,12 @@
    4.78  
    4.79      if (src->longmsg_formatted && src->longmsg_formatted[0]) {
    4.80          ptext = src->longmsg_formatted;
    4.81 -        status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    4.82 -            &csize);
    4.83 +        if (nosign)
    4.84 +            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
    4.85 +                &csize);
    4.86 +        else 
    4.87 +            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    4.88 +                &csize);
    4.89          if (ctext) {
    4.90  
    4.91              bloblist_t *_a = bloblist_add(dst->attachments, ctext, csize,
    4.92 @@ -535,8 +555,12 @@
    4.93              else {
    4.94                  size_t psize = _s->size;
    4.95                  ptext = _s->value;
    4.96 -                status = encrypt_and_sign(session, keys, ptext, psize, &ctext,
    4.97 -                    &csize);
    4.98 +                if (nosign)
    4.99 +                    status = encrypt_only(session, keys, ptext, psize, &ctext,
   4.100 +                        &csize);
   4.101 +                else 
   4.102 +                    status = encrypt_and_sign(session, keys, ptext, psize, &ctext,
   4.103 +                        &csize);
   4.104                  if (ctext) {
   4.105                      char *filename = NULL;
   4.106  
   4.107 @@ -1168,12 +1192,12 @@
   4.108      }
   4.109  
   4.110      if (!dest_keys_found ||
   4.111 -        stringlist_length(keys) == 0 ||
   4.112 +        stringlist_length(keys)  == 0 ||
   4.113          _rating(max_comm_type,
   4.114                  PEP_rating_undefined) < PEP_rating_reliable)
   4.115      {
   4.116          free_stringlist(keys);
   4.117 -        if (!session->passive_mode)
   4.118 +        if (!session->passive_mode && !(flags & PEP_encrypt_flag_force_no_attached_key))
   4.119              attach_own_key(session, src);
   4.120          return PEP_UNENCRYPTED;
   4.121      }
   4.122 @@ -1182,16 +1206,17 @@
   4.123          if (msg == NULL)
   4.124              goto enomem;
   4.125  
   4.126 -        attach_own_key(session, src);
   4.127 +        if (!(flags & PEP_encrypt_flag_force_no_attached_key))
   4.128 +            attach_own_key(session, src);
   4.129  
   4.130          switch (enc_format) {
   4.131          case PEP_enc_PGP_MIME:
   4.132          case PEP_enc_PEP: // BUG: should be implemented extra
   4.133 -            status = encrypt_PGP_MIME(session, src, keys, msg);
   4.134 +            status = encrypt_PGP_MIME(session, src, keys, msg, flags);
   4.135              break;
   4.136  
   4.137          case PEP_enc_pieces:
   4.138 -            status = encrypt_PGP_in_pieces(session, src, keys, msg);
   4.139 +            status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
   4.140              break;
   4.141  
   4.142          /* case PEP_enc_PEP:
   4.143 @@ -1290,6 +1315,9 @@
   4.144  
   4.145      keys = new_stringlist(target_fpr);
   4.146  
   4.147 +    /* KG: did we ever do this??? */
   4.148 +    if (!(flags & PEP_encrypt_flag_force_no_attached_key))
   4.149 +        attach_own_key(session, src);
   4.150  
   4.151      msg = clone_to_empty_message(src);
   4.152      if (msg == NULL)
   4.153 @@ -1298,16 +1326,16 @@
   4.154      switch (enc_format) {
   4.155          case PEP_enc_PGP_MIME:
   4.156          case PEP_enc_PEP: // BUG: should be implemented extra
   4.157 -            status = encrypt_PGP_MIME(session, src, keys, msg);
   4.158 +            status = encrypt_PGP_MIME(session, src, keys, msg, flags);
   4.159              break;
   4.160  
   4.161          case PEP_enc_pieces:
   4.162 -            status = encrypt_PGP_in_pieces(session, src, keys, msg);
   4.163 +            status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
   4.164              break;
   4.165  
   4.166          /* case PEP_enc_PEP:
   4.167 +            NOT_IMPLEMENTED */
   4.168              // TODO: implement
   4.169 -            NOT_IMPLEMENTED */
   4.170  
   4.171          default:
   4.172              assert(0);
   4.173 @@ -2498,17 +2526,18 @@
   4.174      if (status != PEP_STATUS_OK)
   4.175          goto pep_error;
   4.176  
   4.177 -    status = decrypt_message(session,
   4.178 -                             tmp_msg,
   4.179 -                             &dec_msg,
   4.180 -                             keylist,
   4.181 -                             rating,
   4.182 -                             flags);
   4.183 -    if (status != PEP_STATUS_OK)
   4.184 -        goto pep_error;
   4.185 -
   4.186 +    PEP_STATUS decrypt_status = decrypt_message(session,
   4.187 +                                                tmp_msg,
   4.188 +                                                &dec_msg,
   4.189 +                                                keylist,
   4.190 +                                                rating,
   4.191 +                                                flags);
   4.192 +                                                
   4.193      status = mime_encode_message(dec_msg, false, mime_plaintext);
   4.194  
   4.195 +    if (status == PEP_STATUS_OK)
   4.196 +        return decrypt_status;
   4.197 +        
   4.198  pep_error:
   4.199      free_message(tmp_msg);
   4.200      free_message(dec_msg);
   4.201 @@ -2516,6 +2545,7 @@
   4.202      return status;
   4.203  }
   4.204  
   4.205 +
   4.206  DYNAMIC_API PEP_STATUS MIME_encrypt_message(
   4.207      PEP_SESSION session,
   4.208      const char *mimetext,
   4.209 @@ -2554,3 +2584,41 @@
   4.210      return status;
   4.211  
   4.212  }
   4.213 +
   4.214 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
   4.215 +    PEP_SESSION session,
   4.216 +    pEp_identity* target_id,
   4.217 +    const char *mimetext,
   4.218 +    size_t size,
   4.219 +    char** mime_ciphertext,
   4.220 +    PEP_enc_format enc_format,
   4.221 +    PEP_encrypt_flags_t flags
   4.222 +)
   4.223 +{
   4.224 +    PEP_STATUS status = PEP_STATUS_OK;
   4.225 +    message* tmp_msg = NULL;
   4.226 +    message* enc_msg = NULL;
   4.227 +
   4.228 +    status = mime_decode_message(mimetext, size, &tmp_msg);
   4.229 +    if (status != PEP_STATUS_OK)
   4.230 +        goto pep_error;
   4.231 +
   4.232 +    // This isn't incoming, though... so we need to reverse the direction
   4.233 +    tmp_msg->dir = PEP_dir_outgoing;
   4.234 +    status = encrypt_message_for_self(session,
   4.235 +                                      target_id,
   4.236 +                                      tmp_msg,
   4.237 +                                      &enc_msg,
   4.238 +                                      enc_format,
   4.239 +                                      flags);
   4.240 +    if (status != PEP_STATUS_OK)
   4.241 +        goto pep_error;
   4.242 +
   4.243 +    status = mime_encode_message(enc_msg, false, mime_ciphertext);
   4.244 +
   4.245 +pep_error:
   4.246 +    free_message(tmp_msg);
   4.247 +    free_message(enc_msg);
   4.248 +
   4.249 +    return status;
   4.250 +}
     5.1 --- a/src/message_api.h	Fri Mar 10 14:17:43 2017 +0100
     5.2 +++ b/src/message_api.h	Mon Mar 13 09:51:53 2017 +0100
     5.3 @@ -23,11 +23,14 @@
     5.4  void add_opt_field(message *msg, const char *name, const char *value);
     5.5  
     5.6  typedef enum _PEP_encrypt_flags {
     5.7 +    // "default" means whatever the default behaviour for the function is.
     5.8 +    PEP_encrypt_flag_default = 0x0,
     5.9      PEP_encrypt_flag_force_encryption = 0x1,
    5.10  
    5.11      // This flag is for special use cases and should not be used
    5.12      // by normal pEp clients!
    5.13 -    PEP_encrypt_flag_force_unsigned = 0x2
    5.14 +    PEP_encrypt_flag_force_unsigned = 0x2,
    5.15 +    PEP_encrypt_flag_force_no_attached_key = 0x4
    5.16  } PEP_encrypt_flags; 
    5.17  
    5.18  typedef unsigned int PEP_encrypt_flags_t;
    5.19 @@ -132,6 +135,43 @@
    5.20      PEP_encrypt_flags_t flags
    5.21  );
    5.22  
    5.23 +// MIME_encrypt_message_for_self() - encrypt MIME message for user's identity only,
    5.24 +//                              ignoring recipients and other identities from
    5.25 +//                              the message, with MIME output
    5.26 +//  parameters:
    5.27 +//      session (in)            session handle
    5.28 +//      target_id (in)      self identity this message should be encrypted for
    5.29 +//      mimetext (in)           MIME encoded text to encrypt
    5.30 +//      size (in)               size of input mime text
    5.31 +//      mime_ciphertext (out)   encrypted, encoded message
    5.32 +//      enc_format (in)         encrypted format
    5.33 +//      flags (in)              flags to set special encryption features
    5.34 +//
    5.35 +//  return value:
    5.36 +//      PEP_STATUS_OK           if everything worked
    5.37 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
    5.38 +//      PEP_CANNOT_CREATE_TEMP_FILE
    5.39 +//                              if there are issues with temp files; in
    5.40 +//                              this case errno will contain the underlying
    5.41 +//                              error
    5.42 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
    5.43 +//
    5.44 +//  caveat:
    5.45 +//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
    5.46 +//      will remain in the ownership of the caller
    5.47 +
    5.48 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
    5.49 +    PEP_SESSION session,
    5.50 +    pEp_identity* target_id,
    5.51 +    const char *mimetext,
    5.52 +    size_t size,
    5.53 +    char** mime_ciphertext,
    5.54 +    PEP_enc_format enc_format,
    5.55 +    PEP_encrypt_flags_t flags
    5.56 +);
    5.57 +
    5.58 +
    5.59 +
    5.60  typedef enum _PEP_rating {
    5.61      PEP_rating_undefined = 0,
    5.62      PEP_rating_cannot_decrypt,
    5.63 @@ -214,7 +254,9 @@
    5.64  //      flags (out)             flags to signal special decryption features
    5.65  //
    5.66  //  return value:
    5.67 -//      PEP_STATUS_OK           if everything worked
    5.68 +//      decrypt status          if everything worked with MIME encode/decode, 
    5.69 +//                              the status of the decryption is returned 
    5.70 +//                              (PEP_STATUS_OK or decryption error status)
    5.71  //      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
    5.72  //      PEP_CANNOT_CREATE_TEMP_FILE
    5.73  //                              if there are issues with temp files; in
    5.74 @@ -383,4 +425,3 @@
    5.75  #ifdef __cplusplus
    5.76  }
    5.77  #endif
    5.78 -
     6.1 --- a/src/pEpEngine.c	Fri Mar 10 14:17:43 2017 +0100
     6.2 +++ b/src/pEpEngine.c	Mon Mar 13 09:51:53 2017 +0100
     6.3 @@ -1477,6 +1477,26 @@
     6.4              keylist, ptext, psize, ctext, csize);
     6.5  }
     6.6  
     6.7 +PEP_STATUS encrypt_only(
     6.8 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
     6.9 +    size_t psize, char **ctext, size_t *csize
    6.10 +    )
    6.11 +{
    6.12 +    assert(session);
    6.13 +    assert(keylist);
    6.14 +    assert(ptext);
    6.15 +    assert(psize);
    6.16 +    assert(ctext);
    6.17 +    assert(csize);
    6.18 +
    6.19 +    if (!(session && keylist && ptext && psize && ctext && csize))
    6.20 +        return PEP_ILLEGAL_VALUE;
    6.21 +
    6.22 +    return session->cryptotech[PEP_crypt_OpenPGP].encrypt_only(session,
    6.23 +            keylist, ptext, psize, ctext, csize);
    6.24 +}
    6.25 +
    6.26 +
    6.27  DYNAMIC_API PEP_STATUS verify_text(
    6.28      PEP_SESSION session, const char *text, size_t size,
    6.29      const char *signature, size_t sig_size, stringlist_t **keylist
     7.1 --- a/src/pEp_internal.h	Fri Mar 10 14:17:43 2017 +0100
     7.2 +++ b/src/pEp_internal.h	Mon Mar 13 09:51:53 2017 +0100
     7.3 @@ -167,6 +167,12 @@
     7.4  PEP_STATUS init_transport_system(PEP_SESSION session, bool in_first);
     7.5  void release_transport_system(PEP_SESSION session, bool out_last);
     7.6  
     7.7 +/* NOT to be exposed to the outside!!! */
     7.8 +PEP_STATUS encrypt_only(
     7.9 +        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    7.10 +        size_t psize, char **ctext, size_t *csize
    7.11 +);
    7.12 +
    7.13  #ifdef NDEBUG
    7.14  #define DEBUG_LOG(TITLE, ENTITY, DESC)
    7.15  #define  LOGD(...)
     8.1 --- a/src/pgp_gpg.c	Fri Mar 10 14:17:43 2017 +0100
     8.2 +++ b/src/pgp_gpg.c	Mon Mar 13 09:51:53 2017 +0100
     8.3 @@ -250,6 +250,11 @@
     8.4              "gpgme_op_encrypt_sign");
     8.5          assert(gpg.gpgme_op_encrypt_sign);
     8.6  
     8.7 +        gpg.gpgme_op_encrypt
     8.8 +            = (gpgme_op_encrypt_t) (intptr_t) dlsym(gpgme,
     8.9 +            "gpgme_op_encrypt");
    8.10 +        assert(gpg.gpgme_op_encrypt);
    8.11 +
    8.12          gpg.gpgme_op_verify_result
    8.13              = (gpgme_op_verify_result_t) (intptr_t) dlsym(gpgme,
    8.14              "gpgme_op_verify_result");
    8.15 @@ -873,11 +878,12 @@
    8.16      return result;
    8.17  }
    8.18  
    8.19 -PEP_STATUS pgp_encrypt_and_sign(
    8.20 +
    8.21 +static PEP_STATUS pgp_encrypt_sign_optional(    
    8.22      PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    8.23 -    size_t psize, char **ctext, size_t *csize
    8.24 -    )
    8.25 -{
    8.26 +    size_t psize, char **ctext, size_t *csize, bool sign
    8.27 +)
    8.28 +{    
    8.29      PEP_STATUS result;
    8.30      gpgme_error_t gpgme_error;
    8.31      gpgme_data_t plain, cipher;
    8.32 @@ -943,7 +949,7 @@
    8.33              gpg.gpgme_data_release(cipher);
    8.34              return PEP_OUT_OF_MEMORY;
    8.35          case GPG_ERR_NO_ERROR:
    8.36 -            if (i == 0) {
    8.37 +            if (i == 0 && sign) {
    8.38                  gpgme_error_t _gpgme_error = gpg.gpgme_signers_add(session->ctx, rcpt[0]);
    8.39                  _gpgme_error = _GPGERR(_gpgme_error);
    8.40                  assert(_gpgme_error == GPG_ERR_NO_ERROR);
    8.41 @@ -976,9 +982,16 @@
    8.42  
    8.43      // TODO: remove that and replace with proper key management
    8.44      flags = GPGME_ENCRYPT_ALWAYS_TRUST;
    8.45 -
    8.46 -    gpgme_error = gpg.gpgme_op_encrypt_sign(session->ctx, rcpt, flags,
    8.47 -        plain, cipher);
    8.48 +    
    8.49 +    if (sign) {
    8.50 +        gpgme_error = gpg.gpgme_op_encrypt_sign(session->ctx, rcpt, flags,
    8.51 +            plain, cipher);
    8.52 +    }
    8.53 +    else {
    8.54 +        gpgme_error = gpg.gpgme_op_encrypt(session->ctx, rcpt, flags,
    8.55 +            plain, cipher);
    8.56 +    }
    8.57 +    
    8.58      gpgme_error = _GPGERR(gpgme_error);
    8.59      switch (gpgme_error) {
    8.60      case GPG_ERR_NO_ERROR:
    8.61 @@ -1024,6 +1037,24 @@
    8.62      return result;
    8.63  }
    8.64  
    8.65 +PEP_STATUS pgp_encrypt_only(
    8.66 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    8.67 +    size_t psize, char **ctext, size_t *csize
    8.68 +    )
    8.69 +{
    8.70 +    return pgp_encrypt_sign_optional(session, keylist, ptext,
    8.71 +        psize, ctext, csize, false);
    8.72 +}
    8.73 +
    8.74 +PEP_STATUS pgp_encrypt_and_sign(
    8.75 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    8.76 +    size_t psize, char **ctext, size_t *csize
    8.77 +    )
    8.78 +{
    8.79 +    return pgp_encrypt_sign_optional(session, keylist, ptext,
    8.80 +        psize, ctext, csize, true);
    8.81 +}
    8.82 +
    8.83  PEP_STATUS pgp_generate_keypair(
    8.84      PEP_SESSION session, pEp_identity *identity
    8.85      )
     9.1 --- a/src/pgp_gpg.h	Fri Mar 10 14:17:43 2017 +0100
     9.2 +++ b/src/pgp_gpg.h	Mon Mar 13 09:51:53 2017 +0100
     9.3 @@ -19,6 +19,12 @@
     9.4          size_t psize, char **ctext, size_t *csize
     9.5      );
     9.6  
     9.7 +PEP_STATUS pgp_encrypt_only(
     9.8 +        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
     9.9 +        size_t psize, char **ctext, size_t *csize
    9.10 +    );
    9.11 +
    9.12 +
    9.13  PEP_STATUS pgp_verify_text(
    9.14          PEP_SESSION session, const char *text, size_t size,
    9.15          const char *signature, size_t sig_size, stringlist_t **keylist
    9.16 @@ -100,4 +106,3 @@
    9.17  
    9.18  PEP_STATUS pgp_binary(const char **path);
    9.19  #define PGP_BINARY_PATH pgp_binary
    9.20 -
    10.1 --- a/src/pgp_gpg_internal.h	Fri Mar 10 14:17:43 2017 +0100
    10.2 +++ b/src/pgp_gpg_internal.h	Mon Mar 13 09:51:53 2017 +0100
    10.3 @@ -43,6 +43,9 @@
    10.4  typedef gpgme_error_t(*gpgme_op_encrypt_sign_t)(gpgme_ctx_t CTX,
    10.5      gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
    10.6      gpgme_data_t CIPHER);
    10.7 +typedef gpgme_error_t(*gpgme_op_encrypt_t)(gpgme_ctx_t CTX,
    10.8 +        gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
    10.9 +        gpgme_data_t CIPHER);
   10.10  typedef gpgme_verify_result_t(*gpgme_op_verify_result_t)(gpgme_ctx_t CTX);
   10.11  typedef void(*gpgme_signers_clear_t)(gpgme_ctx_t CTX);
   10.12  typedef gpgme_error_t(*gpgme_signers_add_t)(gpgme_ctx_t CTX, const gpgme_key_t KEY);
   10.13 @@ -102,6 +105,7 @@
   10.14      gpgme_op_decrypt_verify_t gpgme_op_decrypt_verify;
   10.15      gpgme_op_decrypt_result_t gpgme_op_decrypt_result;
   10.16      gpgme_op_encrypt_sign_t gpgme_op_encrypt_sign;
   10.17 +    gpgme_op_encrypt_t gpgme_op_encrypt;
   10.18      gpgme_op_verify_result_t gpgme_op_verify_result;
   10.19      gpgme_signers_clear_t gpgme_signers_clear;
   10.20      gpgme_signers_add_t gpgme_signers_add;
   10.21 @@ -125,4 +129,3 @@
   10.22      gpgme_op_edit_t gpgme_op_edit;
   10.23      gpgme_io_write_t gpgme_io_write;
   10.24  };
   10.25 -
    11.1 --- a/test/encrypt_for_identity_test.cc	Fri Mar 10 14:17:43 2017 +0100
    11.2 +++ b/test/encrypt_for_identity_test.cc	Mon Mar 13 09:51:53 2017 +0100
    11.3 @@ -35,6 +35,7 @@
    11.4      outgoing_message->from = alice;
    11.5      outgoing_message->to = to_list;
    11.6      outgoing_message->shortmsg = strdup("Greetings, humans!");
    11.7 +    outgoing_message->longmsg = strdup("This is a test of the emergency message system. This is only a test. BEEP.");
    11.8      outgoing_message->attachments = new_bloblist(NULL, 0, "application/octet-stream", NULL);
    11.9      cout << "message created.\n";
   11.10  
   11.11 @@ -51,7 +52,7 @@
   11.12      cout << "encrypting message as MIME multipart…\n";
   11.13      message* encrypted_msg = nullptr;
   11.14      cout << "calling encrypt_message_for_identity()\n";
   11.15 -    status = encrypt_message_for_self(session, alice, outgoing_message, &encrypted_msg, PEP_enc_PGP_MIME);
   11.16 +    status = encrypt_message_for_self(session, alice, outgoing_message, &encrypted_msg, PEP_enc_PGP_MIME, PEP_encrypt_flag_force_unsigned | PEP_encrypt_flag_force_no_attached_key);
   11.17      cout << "encrypt_message() returns " << std::hex << status << '.' << endl;
   11.18      assert(status == PEP_STATUS_OK);
   11.19      assert(encrypted_msg);
   11.20 @@ -81,20 +82,27 @@
   11.21      PEP_decrypt_flags_t flags;
   11.22  
   11.23      status = decrypt_message(session, encrypted_msg, &decrypted_msg, &keylist_used, &rating, &flags);
   11.24 -    assert(status == PEP_STATUS_OK);
   11.25      assert(decrypted_msg);
   11.26      assert(keylist_used);
   11.27      assert(rating);
   11.28 +    assert(status == PEP_DECRYPTED && rating == PEP_rating_unreliable);
   11.29      PEP_comm_type ct = encrypted_msg->from->comm_type;
   11.30      assert(ct == PEP_ct_pEp || ct == PEP_ct_pEp_unconfirmed || ct == PEP_ct_OpenPGP || ct == PEP_ct_OpenPGP_unconfirmed );
   11.31  
   11.32      cout << "keys used:\n";
   11.33  
   11.34 -    for (stringlist_t* kl4 = keylist_used; kl4 && kl4->value; kl4 = kl4->next)
   11.35 +    int i = 0;
   11.36 +
   11.37 +    for (stringlist_t* kl4 = keylist_used; kl4 && kl4->value; kl4 = kl4->next, i++)
   11.38      {
   11.39 -        cout << "\t " << kl4->value << endl;
   11.40 -        assert(strcasecmp("4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", kl4->value) == 0);
   11.41 -        cout << "Encrypted for Alice! Yay! It worked!" << endl;
   11.42 +        if (i == 0)
   11.43 +            assert(strcasecmp("",kl4->value) == 0);
   11.44 +        else {
   11.45 +            cout << "\t " << kl4->value << endl;
   11.46 +            assert(strcasecmp("4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", kl4->value) == 0);
   11.47 +            cout << "Encrypted for Alice! Yay! It worked!" << endl;
   11.48 +        }
   11.49 +        assert(i < 2);
   11.50      }
   11.51      cout << "Encrypted ONLY for Alice! Test passed. Move along. These are not the bugs you are looking for." << endl;
   11.52   
   11.53 @@ -104,6 +112,82 @@
   11.54      free_message(outgoing_message);
   11.55      cout << "done.\n";
   11.56  
   11.57 +    cout << "*** Now testing MIME_encrypt_for_self ***" << endl;
   11.58 +
   11.59 +    alice = new_identity("pep.test.alice@pep-project.org", NULL, PEP_OWN_USERID, "Alice Test");
   11.60 +    bob = new_identity("pep.test.bob@pep-project.org", NULL, "42", "Bob Test");
   11.61 +
   11.62 +    cout << "Reading in alice_bob_encrypt_test_plaintext_mime.eml..." << endl;
   11.63 +    
   11.64 +    ifstream inFile("test_mails/alice_bob_encrypt_test_plaintext_mime.eml");
   11.65 +    assert(inFile.is_open());
   11.66 +
   11.67 +    string mimetext;
   11.68 +
   11.69 +    cout << "reading mime mail\n";
   11.70 +    while (!inFile.eof()) {
   11.71 +        static string line;
   11.72 +        getline(inFile, line);
   11.73 +        mimetext += line + "\n";
   11.74 +    }
   11.75 +    inFile.close();
   11.76 +
   11.77 +    cout << "Text read:" << endl;
   11.78 +    cout << mimetext.c_str() << endl;
   11.79 +    char* encrypted_mimetext = nullptr;
   11.80 +    
   11.81 +    cout << "Calling MIME_encrypt_message_for_self" << endl;
   11.82 +    status = MIME_encrypt_message_for_self(session, alice, mimetext.c_str(),
   11.83 +                                           mimetext.size(), 
   11.84 +                                           &encrypted_mimetext, 
   11.85 +                                           PEP_enc_PGP_MIME, 
   11.86 +                                           PEP_encrypt_flag_force_unsigned | PEP_encrypt_flag_force_no_attached_key);
   11.87 +    
   11.88 +    cout << "Encrypted message:" << endl;
   11.89 +    cout << encrypted_mimetext << endl;
   11.90 +
   11.91 +    cout << "Calling MIME_decrypt_message" << endl;
   11.92 +    
   11.93 +    char* decrypted_mimetext = nullptr;
   11.94 +    free_stringlist(keylist_used);
   11.95 +    keylist_used = nullptr;
   11.96 +    PEP_decrypt_flags_t mimeflags;
   11.97 +    PEP_rating mimerating;
   11.98 +
   11.99 +    status = MIME_decrypt_message(session,
  11.100 +                                  encrypted_mimetext,
  11.101 +                                  strlen(encrypted_mimetext),
  11.102 +                                  &decrypted_mimetext,
  11.103 +                                  &keylist_used,
  11.104 +                                  &mimerating,
  11.105 +                                  &mimeflags);
  11.106 +
  11.107 +    assert(decrypted_msg);
  11.108 +    assert(keylist_used);
  11.109 +    assert(mimerating);
  11.110 +                             
  11.111 +    assert(status == PEP_DECRYPTED && mimerating == PEP_rating_unreliable);
  11.112 +
  11.113 +    cout << "Decrypted message:" << endl;
  11.114 +    cout << decrypted_mimetext << endl;
  11.115 +
  11.116 +    cout << "keys used:\n";
  11.117 +
  11.118 +    i = 0;
  11.119 +
  11.120 +    for (stringlist_t* kl4 = keylist_used; kl4 && kl4->value; kl4 = kl4->next, i++)
  11.121 +    {
  11.122 +        if (i == 0)
  11.123 +            assert(strcasecmp("",kl4->value) == 0);
  11.124 +        else {
  11.125 +            cout << "\t " << kl4->value << endl;
  11.126 +            assert(strcasecmp("4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", kl4->value) == 0);
  11.127 +            cout << "Encrypted for Alice! Yay! It worked!" << endl;
  11.128 +        }
  11.129 +        assert(i < 2);
  11.130 +    }
  11.131 +    cout << "Encrypted ONLY for Alice! Test passed. Move along. These are not the bugs you are looking for." << endl;
  11.132 +    
  11.133      cout << "calling release()\n";
  11.134      release(session);
  11.135      return 0;