shelving work on low-level sign only for default w/ netpgp merge_ll_sign_only
authorKrista Bennett <krista@pep-project.org>
Thu, 22 Nov 2018 14:10:20 +0100
branchmerge_ll_sign_only
changeset 31534d88a449af16
parent 3132 9af7df5e89cd
parent 3136 56e8a45b4fa6
shelving work on low-level sign only for default w/ netpgp
src/pgp_netpgp.c
test/src/EngineTestSuite.cc
     1.1 --- a/src/cryptotech.c	Mon Nov 12 09:23:59 2018 +0100
     1.2 +++ b/src/cryptotech.c	Thu Nov 22 14:10:20 2018 +0100
     1.3 @@ -37,6 +37,7 @@
     1.4          cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify = pgp_decrypt_and_verify;
     1.5          cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign = pgp_encrypt_and_sign;
     1.6          cryptotech[PEP_crypt_OpenPGP].encrypt_only = pgp_encrypt_only;
     1.7 +        cryptotech[PEP_crypt_OpenPGP].sign_only = pgp_sign_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	Mon Nov 12 09:23:59 2018 +0100
     2.2 +++ b/src/cryptotech.h	Thu Nov 22 14:10:20 2018 +0100
     2.3 @@ -38,6 +38,11 @@
     2.4          size_t psize, char **ctext, size_t *csize
     2.5      );
     2.6  
     2.7 +typedef PEP_STATUS (*sign_only_t)(
     2.8 +        PEP_SESSION session, const char* fpr, const char *ptext,
     2.9 +        size_t psize, char **stext, size_t *ssize
    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 @@ -99,6 +104,7 @@
    2.16      verify_text_t verify_text;
    2.17      encrypt_and_sign_t encrypt_and_sign;
    2.18      encrypt_only_t encrypt_only;
    2.19 +    sign_only_t sign_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/pgp_gpg.c	Mon Nov 12 09:23:59 2018 +0100
     3.2 +++ b/src/pgp_gpg.c	Thu Nov 22 14:10:20 2018 +0100
     3.3 @@ -933,6 +933,143 @@
     3.4      return result;
     3.5  }
     3.6  
     3.7 +PEP_STATUS pgp_sign_only(    
     3.8 +    PEP_SESSION session, const char* fpr, const char *ptext,
     3.9 +    size_t psize, char **stext, size_t *ssize
    3.10 +)
    3.11 +{
    3.12 +    assert(session);
    3.13 +    assert(fpr && fpr[0]);
    3.14 +    assert(ptext);
    3.15 +    assert(psize);
    3.16 +    assert(stext);
    3.17 +    assert(ssize);
    3.18 +
    3.19 +    PEP_STATUS result;
    3.20 +    gpgme_error_t gpgme_error;
    3.21 +    gpgme_data_t plain, signed_text;
    3.22 +    gpgme_key_t* signer_key_ptr;
    3.23 +
    3.24 +    gpgme_sig_mode_t sign_mode = GPGME_SIG_MODE_DETACH;
    3.25 +       
    3.26 +    *stext = NULL;
    3.27 +    *ssize = 0;
    3.28 +
    3.29 +    gpgme_error = gpg.gpgme_data_new_from_mem(&plain, ptext, psize, 0);
    3.30 +    gpgme_error = _GPGERR(gpgme_error);
    3.31 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
    3.32 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
    3.33 +        if (gpgme_error == GPG_ERR_ENOMEM)
    3.34 +            return PEP_OUT_OF_MEMORY;
    3.35 +        else
    3.36 +            return PEP_UNKNOWN_ERROR;
    3.37 +    }
    3.38 +
    3.39 +    gpgme_error = gpg.gpgme_data_new(&signed_text);
    3.40 +    gpgme_error = _GPGERR(gpgme_error);
    3.41 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
    3.42 +    if (gpgme_error != GPG_ERR_NO_ERROR) {
    3.43 +        gpg.gpgme_data_release(plain);
    3.44 +        if (gpgme_error == GPG_ERR_ENOMEM)
    3.45 +            return PEP_OUT_OF_MEMORY;
    3.46 +        else
    3.47 +            return PEP_UNKNOWN_ERROR;
    3.48 +    }
    3.49 +
    3.50 +    signer_key_ptr = calloc(1, sizeof(gpgme_key_t));   
    3.51 +    assert(signer_key_ptr);
    3.52 +    if (signer_key_ptr == NULL) {
    3.53 +        gpg.gpgme_data_release(plain);
    3.54 +        gpg.gpgme_data_release(signed_text);
    3.55 +        return PEP_OUT_OF_MEMORY;
    3.56 +    }
    3.57 +
    3.58 +    gpg.gpgme_signers_clear(session->ctx);
    3.59 +
    3.60 +    // Get signing key
    3.61 +    gpgme_error = gpg.gpgme_get_key(session->ctx, fpr,
    3.62 +                                    signer_key_ptr, 0);
    3.63 +    gpgme_error = _GPGERR(gpgme_error);
    3.64 +    assert(gpgme_error != GPG_ERR_ENOMEM);
    3.65 +    gpgme_error_t _gpgme_error;
    3.66 +    
    3.67 +    switch (gpgme_error) {
    3.68 +    case GPG_ERR_ENOMEM:
    3.69 +        gpg.gpgme_key_unref(*signer_key_ptr);
    3.70 +        free(signer_key_ptr);
    3.71 +        gpg.gpgme_data_release(plain);
    3.72 +        gpg.gpgme_data_release(signed_text);
    3.73 +        return PEP_OUT_OF_MEMORY;
    3.74 +    case GPG_ERR_NO_ERROR:
    3.75 +        _gpgme_error = gpg.gpgme_signers_add(session->ctx, *signer_key_ptr);
    3.76 +        _gpgme_error = _GPGERR(_gpgme_error);
    3.77 +        assert(_gpgme_error == GPG_ERR_NO_ERROR);
    3.78 +        break;
    3.79 +    case GPG_ERR_EOF:
    3.80 +        gpg.gpgme_key_unref(*signer_key_ptr);
    3.81 +        free(signer_key_ptr);
    3.82 +        gpg.gpgme_data_release(plain);
    3.83 +        gpg.gpgme_data_release(signed_text);
    3.84 +        return PEP_KEY_NOT_FOUND;
    3.85 +    case GPG_ERR_AMBIGUOUS_NAME:
    3.86 +        gpg.gpgme_key_unref(*signer_key_ptr);
    3.87 +        free(signer_key_ptr);
    3.88 +        gpg.gpgme_data_release(plain);
    3.89 +        gpg.gpgme_data_release(signed_text);
    3.90 +        return PEP_KEY_HAS_AMBIG_NAME;
    3.91 +    default: // GPG_ERR_INV_VALUE if CTX or R_KEY is not a valid pointer or
    3.92 +        // FPR is not a fingerprint or key ID
    3.93 +        gpg.gpgme_key_unref(*signer_key_ptr);
    3.94 +        free(signer_key_ptr);
    3.95 +        gpg.gpgme_data_release(plain);
    3.96 +        gpg.gpgme_data_release(signed_text);
    3.97 +        return PEP_GET_KEY_FAILED;
    3.98 +    }
    3.99 + 
   3.100 +    gpgme_error = gpg.gpgme_op_sign(session->ctx, plain, signed_text, sign_mode);
   3.101 +
   3.102 +    gpgme_error = _GPGERR(gpgme_error);
   3.103 +    switch (gpgme_error) {
   3.104 +    case GPG_ERR_NO_ERROR:
   3.105 +    {
   3.106 +        char *_buffer = NULL;
   3.107 +        size_t reading;
   3.108 +        size_t length = gpg.gpgme_data_seek(signed_text, 0, SEEK_END);
   3.109 +        assert(length != -1);
   3.110 +        gpg.gpgme_data_seek(signed_text, 0, SEEK_SET);
   3.111 +
   3.112 +        // TODO: make things less memory consuming
   3.113 +        // the following algorithm allocates a buffer for the complete text
   3.114 +
   3.115 +        _buffer = malloc(length + 1);
   3.116 +        assert(_buffer);
   3.117 +        if (_buffer == NULL) {
   3.118 +            gpg.gpgme_key_unref(*signer_key_ptr);
   3.119 +            free(signer_key_ptr);
   3.120 +            gpg.gpgme_data_release(plain);
   3.121 +            gpg.gpgme_data_release(signed_text);
   3.122 +            return PEP_OUT_OF_MEMORY;
   3.123 +        }
   3.124 +
   3.125 +        reading = gpg.gpgme_data_read(signed_text, _buffer, length);
   3.126 +        assert(length == reading);
   3.127 +
   3.128 +        *stext = _buffer;
   3.129 +        *ssize = reading;
   3.130 +        (*stext)[*ssize] = 0; // safeguard for naive users
   3.131 +        result = PEP_STATUS_OK;
   3.132 +        break;
   3.133 +    }
   3.134 +    default:
   3.135 +        result = PEP_UNKNOWN_ERROR;
   3.136 +    }
   3.137 +
   3.138 +    gpg.gpgme_key_unref(*signer_key_ptr);
   3.139 +    free(signer_key_ptr);
   3.140 +    gpg.gpgme_data_release(plain);
   3.141 +    gpg.gpgme_data_release(signed_text);
   3.142 +    return result;   
   3.143 +}
   3.144  
   3.145  static PEP_STATUS pgp_encrypt_sign_optional(    
   3.146      PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
     4.1 --- a/src/pgp_gpg.h	Mon Nov 12 09:23:59 2018 +0100
     4.2 +++ b/src/pgp_gpg.h	Thu Nov 22 14:10:20 2018 +0100
     4.3 @@ -25,6 +25,10 @@
     4.4          size_t psize, char **ctext, size_t *csize
     4.5      );
     4.6  
     4.7 +PEP_STATUS pgp_sign_only(
     4.8 +        PEP_SESSION session, const char* fpr, const char *ptext,
     4.9 +        size_t psize, char **stext, size_t *ssize
    4.10 +    );
    4.11  
    4.12  PEP_STATUS pgp_verify_text(
    4.13          PEP_SESSION session, const char *text, size_t size,
     5.1 --- a/src/pgp_gpg_internal.h	Mon Nov 12 09:23:59 2018 +0100
     5.2 +++ b/src/pgp_gpg_internal.h	Thu Nov 22 14:10:20 2018 +0100
     5.3 @@ -46,6 +46,8 @@
     5.4  typedef gpgme_error_t(*gpgme_op_encrypt_t)(gpgme_ctx_t CTX,
     5.5          gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
     5.6          gpgme_data_t CIPHER);
     5.7 +typedef gpgme_error_t(*gpgme_op_sign_t)(gpgme_ctx_t CTX,
     5.8 +        gpgme_data_t PLAIN, gpgme_data_t SIG, gpgme_sig_mode_t MODE);        
     5.9  typedef gpgme_verify_result_t(*gpgme_op_verify_result_t)(gpgme_ctx_t CTX);
    5.10  typedef void(*gpgme_signers_clear_t)(gpgme_ctx_t CTX);
    5.11  typedef gpgme_error_t(*gpgme_signers_add_t)(gpgme_ctx_t CTX, const gpgme_key_t KEY);
    5.12 @@ -122,6 +124,7 @@
    5.13      gpgme_op_decrypt_result_t gpgme_op_decrypt_result;
    5.14      gpgme_op_encrypt_sign_t gpgme_op_encrypt_sign;
    5.15      gpgme_op_encrypt_t gpgme_op_encrypt;
    5.16 +    gpgme_op_sign_t gpgme_op_sign;    
    5.17      gpgme_op_verify_result_t gpgme_op_verify_result;
    5.18      gpgme_signers_clear_t gpgme_signers_clear;
    5.19      gpgme_signers_add_t gpgme_signers_add;
     6.1 --- a/src/pgp_netpgp.c	Mon Nov 12 09:23:59 2018 +0100
     6.2 +++ b/src/pgp_netpgp.c	Thu Nov 22 14:10:20 2018 +0100
     6.3 @@ -765,6 +765,129 @@
     6.4      return result;
     6.5  }
     6.6  
     6.7 +
     6.8 +PEP_STATUS pgp_sign_only(
     6.9 +    PEP_SESSION session, const char* fpr, const char *ptext,
    6.10 +    size_t psize, char **stext, size_t *ssize
    6.11 +    )
    6.12 +{
    6.13 +    pgp_key_t *signer = NULL;
    6.14 +    pgp_seckey_t *seckey = NULL;
    6.15 +    pgp_memory_t *signedmem = NULL;
    6.16 +    const char *hashalg;
    6.17 +    pgp_keyring_t *snrs;
    6.18 +
    6.19 +    PEP_STATUS result;
    6.20 +
    6.21 +    assert(session);
    6.22 +    assert(fpr);
    6.23 +    assert(ptext);
    6.24 +    assert(psize);
    6.25 +    assert(stext);
    6.26 +    assert(ssize);
    6.27 +
    6.28 +    if(!session || !ptext || !psize || !stext || !ssize || !fpr || !fpr[0])
    6.29 +        return PEP_ILLEGAL_VALUE;
    6.30 +
    6.31 +    if(pthread_mutex_lock(&netpgp_mutex)){
    6.32 +        return PEP_UNKNOWN_ERROR;
    6.33 +    }
    6.34 +
    6.35 +    *stext = NULL;
    6.36 +    *ssize = 0;
    6.37 +
    6.38 +    if ((snrs = calloc(1, sizeof(*snrs))) == NULL) {
    6.39 +        result = PEP_OUT_OF_MEMORY;
    6.40 +        goto unlock_netpgp;
    6.41 +    }
    6.42 +    
    6.43 +    assert(fpr && fpr[0]);
    6.44 +
    6.45 +    uint8_t uint_fpr[PGP_FINGERPRINT_SIZE];
    6.46 +    size_t fprlen;
    6.47 +    unsigned from = 0;
    6.48 +
    6.49 +    if (str_to_fpr(fpr, uint_fpr, &fprlen)) {
    6.50 +        if ((signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring,
    6.51 +                                                uint_fpr, fprlen, &from, NULL,
    6.52 +                                                /* reject revoked and expired */
    6.53 +                                                1,1)) == NULL) {
    6.54 +            result = PEP_KEY_NOT_FOUND;
    6.55 +            goto free_snrs;
    6.56 +        }
    6.57 +    }else{
    6.58 +        result = PEP_ILLEGAL_VALUE;
    6.59 +        goto free_snrs;
    6.60 +    }
    6.61 +
    6.62 +    // add key to signers
    6.63 +    pgp_keyring_add(snrs, signer);
    6.64 +    if(snrs->keys == NULL){
    6.65 +        result = PEP_OUT_OF_MEMORY;
    6.66 +        goto free_snrs;
    6.67 +    }
    6.68 +
    6.69 +    /* Empty keylist ?*/
    6.70 +    if(snrs->keyc == 0){
    6.71 +        result = PEP_ILLEGAL_VALUE;
    6.72 +        goto free_snrs;
    6.73 +    }
    6.74 +
    6.75 +    seckey = pgp_key_get_certkey(signer);
    6.76 +
    6.77 +    /* No signing key. Revoked ? */
    6.78 +    if(seckey == NULL){
    6.79 +        result = PEP_GET_KEY_FAILED;
    6.80 +        goto free_snrs;
    6.81 +    }
    6.82 +
    6.83 +    hashalg = netpgp_getvar(&netpgp, "hash");
    6.84 +
    6.85 +    const char *_stext;
    6.86 +    size_t _ssize;
    6.87 +   
    6.88 +    // Sign data
    6.89 +    signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey,
    6.90 +                time(NULL), /* birthtime */
    6.91 +                0 /* duration */,
    6.92 +                hashalg,
    6.93 +                1 /* armored */,
    6.94 +                0 /* cleartext */);
    6.95 +
    6.96 +    if (!signedmem) {
    6.97 +        result = PEP_UNENCRYPTED;
    6.98 +        goto free_snrs;
    6.99 +    }
   6.100 +    _stext = (char*) pgp_mem_data(signedmem);
   6.101 +    _ssize = pgp_mem_len(signedmem);
   6.102 +    
   6.103 +    // Allocate transferable buffer
   6.104 +    char *_buffer = malloc(_ssize + 1);
   6.105 +
   6.106 +    assert(_buffer);
   6.107 +    if (_buffer == NULL) {
   6.108 +        result = PEP_OUT_OF_MEMORY;
   6.109 +        goto free_signedmem;
   6.110 +    }
   6.111 +
   6.112 +    memcpy(_buffer, _stext, _ssize);
   6.113 +    *stext = _buffer;
   6.114 +    *ssize = _ssize;
   6.115 +    (*stext)[*ssize] = 0; // safeguard for naive users
   6.116 +
   6.117 +    result = PEP_STATUS_OK;
   6.118 +
   6.119 +free_signedmem :
   6.120 +    pgp_memory_free(signedmem);
   6.121 +free_snrs :
   6.122 +    pgp_keyring_free(snrs);
   6.123 +unlock_netpgp:
   6.124 +    pthread_mutex_unlock(&netpgp_mutex);
   6.125 +
   6.126 +    return result;
   6.127 +}
   6.128 +
   6.129 +
   6.130  PEP_STATUS pgp_encrypt_and_sign(
   6.131      PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   6.132      size_t psize, char **ctext, size_t *csize
   6.133 @@ -1426,7 +1549,6 @@
   6.134          if(!stringlist_add(encoded_keys, request)){
   6.135              result = PEP_OUT_OF_MEMORY;
   6.136          }
   6.137 -
   6.138          free(request);
   6.139  
   6.140  free_encoded_key:
     7.1 --- a/src/pgp_netpgp.h	Mon Nov 12 09:23:59 2018 +0100
     7.2 +++ b/src/pgp_netpgp.h	Thu Nov 22 14:10:20 2018 +0100
     7.3 @@ -25,6 +25,10 @@
     7.4          size_t psize, char **ctext, size_t *csize
     7.5      );
     7.6  
     7.7 +PEP_STATUS pgp_sign_only(
     7.8 +        PEP_SESSION session, const char* fpr, const char *ptext,
     7.9 +        size_t psize, char **stext, size_t *ssize
    7.10 +    );
    7.11  
    7.12  PEP_STATUS pgp_verify_text(
    7.13          PEP_SESSION session, const char *text, size_t size,
     8.1 --- a/test/src/EngineTestSuite.cc	Mon Nov 12 09:23:59 2018 +0100
     8.2 +++ b/test/src/EngineTestSuite.cc	Thu Nov 22 14:10:20 2018 +0100
     8.3 @@ -96,10 +96,12 @@
     8.4      
     8.5      set_my_name();
     8.6  
     8.7 +#ifndef NETPGP
     8.8      success = system("gpgconf --kill all");
     8.9      if (success != 0)
    8.10          throw std::runtime_error("SETUP: Error when executing 'gpgconf --kill all'.");
    8.11   //   sleep(1); // hopefully enough time for the system to recognise that it is dead. *sigh*    
    8.12 +#endif
    8.13  
    8.14      if (stat(test_home.c_str(), &dirchk) == 0) {
    8.15          if (!S_ISDIR(dirchk.st_mode))
    8.16 @@ -133,7 +135,11 @@
    8.17  
    8.18      // TODO: This is *nix specific, which the current testing env is anyway,
    8.19      // but it needn't remain so forever and always
    8.20 +#ifndef NETPGP
    8.21      char* tmp = getenv("GNUPGHOME");
    8.22 +#else
    8.23 +    char* tmp = strdup()
    8.24 +#endif    
    8.25      if (tmp)
    8.26          prev_gpg_home = tmp;
    8.27