src/pgp_netpgp.c
author Volker Birk <vb@pep-project.org>
Fri, 17 May 2019 17:59:06 +0200
branchsync
changeset 3720 9ed76a79d784
parent 3270 d8aea79654c3
child 4079 da3b0627a59c
permissions -rw-r--r--
...
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #include "pEp_internal.h"
     5 #include "pgp_netpgp.h"
     6 
     7 #include <limits.h>
     8 
     9 #include "wrappers.h"
    10 
    11 #include "netpgp.h"
    12 #include <netpgp/config.h>
    13 #include <netpgp/memory.h>
    14 #include <netpgp/crypto.h>
    15 #include <netpgp/netpgpsdk.h>
    16 #include <netpgp/validate.h>
    17 #include <netpgp/readerwriter.h>
    18 
    19 #include <curl/curl.h>
    20 #include <pthread.h>
    21 #include <regex.h>
    22 
    23 static netpgp_t netpgp;
    24 static pthread_mutex_t netpgp_mutex;
    25 
    26 static PEP_STATUS init_netpgp()
    27 {
    28     PEP_STATUS status = PEP_STATUS_OK;
    29     const char *home = NULL;
    30 
    31     if(pthread_mutex_init(&netpgp_mutex, NULL)){
    32         return PEP_OUT_OF_MEMORY;
    33     }
    34 
    35     if(pthread_mutex_lock(&netpgp_mutex)){
    36         return PEP_UNKNOWN_ERROR;
    37     }
    38 
    39     if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
    40         setlocale(LC_ALL, "");
    41 
    42     memset(&netpgp, 0x0, sizeof(netpgp_t));
    43 
    44     // netpgp_setvar(&netpgp, "max mem alloc", "4194304");
    45     netpgp_setvar(&netpgp, "need seckey", "1");
    46     // netpgp_setvar(&netpgp, "need userid", "1");
    47 
    48     // NetPGP shares home with GPG
    49     #if defined(WIN32) || defined(NDEBUG)
    50         home = gpg_home();
    51     #else
    52         home = gpg_home(false);
    53     #endif
    54     
    55     if(home){
    56         netpgp_set_homedir(&netpgp,(char*)home, NULL, 0);
    57     }else{
    58         status = PEP_INIT_NO_GPG_HOME;
    59         goto unlock_netpgp;
    60     }
    61 
    62     // pair with gpg's cert-digest-algo
    63     netpgp_setvar(&netpgp, "hash", "SHA256");
    64 
    65     // subset of gpg's personal-cipher-preferences
    66     // here only one cipher can be selected
    67     netpgp_setvar(&netpgp, "cipher", "CAST5");
    68 
    69     if (!netpgp_init(&netpgp)) {
    70         status = PEP_INIT_NETPGP_INIT_FAILED;
    71         goto unlock_netpgp;
    72     }
    73 
    74     // netpgp_set_debug("packet-parse.c");
    75 
    76 unlock_netpgp:
    77     pthread_mutex_unlock(&netpgp_mutex);
    78 
    79     return status;
    80 }
    81 
    82 static void release_netpgp()
    83 {
    84     if(pthread_mutex_lock(&netpgp_mutex)){
    85         return;
    86     }
    87     netpgp_end(&netpgp);
    88     memset(&netpgp, 0x0, sizeof(netpgp_t));
    89 
    90     pthread_mutex_destroy(&netpgp_mutex);
    91 
    92     return;
    93 }
    94 
    95 static PEP_STATUS init_curl(
    96     pthread_mutex_t *curl_mutex,
    97     bool in_first)
    98 {
    99     PEP_STATUS status = PEP_STATUS_OK;
   100 
   101     if(pthread_mutex_init(curl_mutex, NULL)){
   102         return PEP_OUT_OF_MEMORY;
   103     }
   104 
   105     if(pthread_mutex_lock(curl_mutex)){
   106         return PEP_UNKNOWN_ERROR;
   107     }
   108 
   109     if(in_first){
   110         curl_global_init(CURL_GLOBAL_DEFAULT);
   111     }
   112 
   113     pthread_mutex_unlock(curl_mutex);
   114     return status;
   115 }
   116 
   117 static void release_curl(
   118     pthread_mutex_t *curl_mutex,
   119     bool out_last)
   120 {
   121     if(pthread_mutex_lock(curl_mutex)){
   122         return;
   123     }
   124 
   125     if(out_last){
   126         curl_global_cleanup();
   127     }
   128 
   129     pthread_mutex_destroy(curl_mutex);
   130 
   131     return;
   132 }
   133 
   134 static PEP_STATUS curl_get_ctx(
   135     CURL **curl)
   136 {
   137     PEP_STATUS status = PEP_STATUS_OK;
   138     struct curl_slist *headers=NULL;
   139 
   140     if ((*curl = curl_easy_init()) == NULL) {
   141         return PEP_OUT_OF_MEMORY;
   142     }
   143 
   144     curl_easy_setopt(*curl, CURLOPT_FOLLOWLOCATION, 1L);
   145     curl_easy_setopt(*curl, CURLOPT_MAXREDIRS, 3L);
   146 
   147     headers=curl_slist_append(headers,"Pragma: no-cache");
   148     if(headers)
   149         headers=curl_slist_append(headers,"Cache-Control: no-cache");
   150 
   151     if(!headers)
   152     {
   153         return PEP_OUT_OF_MEMORY;
   154     }
   155 
   156     curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
   157     curl_slist_free_all(headers);
   158 
   159     // TODO curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
   160     return status;
   161 }
   162 
   163 static void curl_release_ctx(
   164     CURL **curl)
   165 {
   166     if(*curl)
   167         curl_easy_cleanup(*curl);
   168 
   169     *curl = NULL;
   170 
   171     return;
   172 }
   173 
   174 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
   175 {
   176     PEP_STATUS status = PEP_STATUS_OK;
   177 
   178     assert(session);
   179     if(!session) return PEP_ILLEGAL_VALUE;
   180 
   181     if (in_first) {
   182         if((status = init_netpgp()) != PEP_STATUS_OK)
   183         return status;
   184     }
   185 
   186     if((status = init_curl(
   187                     &session->ctx.curl_mutex,
   188                     in_first) != PEP_STATUS_OK)){
   189         if(in_first) release_netpgp();
   190         return status;
   191     }
   192 
   193     return PEP_STATUS_OK;
   194 }
   195 
   196 void pgp_release(PEP_SESSION session, bool out_last)
   197 {
   198     assert(session);
   199     if(!session) return;
   200 
   201     if (out_last){
   202         release_netpgp();
   203     }
   204     release_curl(&session->ctx.curl_mutex, out_last);
   205 }
   206 
   207 // return 1 if the file contains ascii-armoured text
   208 static unsigned
   209 _armoured(const char *buf, size_t size, const char *pattern)
   210 {
   211     unsigned armoured = 0;
   212     regex_t r;
   213     regcomp(&r, pattern, REG_EXTENDED|REG_NOSUB);
   214     if (regnexec(&r, buf, size, 0, NULL, 0) == 0) {
   215         armoured = 1;
   216     }
   217     regfree(&r);
   218     return armoured;
   219 }
   220 
   221 /* write key fingerprint hexdump as a string */
   222 static unsigned
   223 fpr_to_str (char **str, const uint8_t *fpr, size_t length)
   224 {
   225     unsigned i;
   226     int	n;
   227 
   228     /* 4 hexes per short + null */
   229     *str = malloc((length / 2) * 4 + 1);
   230 
   231     if(*str == NULL)
   232         return 0;
   233 
   234     for (n = 0, i = 0 ; i < length; i += 2) {
   235         n += snprintf(&((*str)[n]), 5, "%02X%02X", fpr[i], fpr[i+1]);
   236     }
   237 
   238     return 1;
   239 }
   240 
   241 /* write key fingerprint bytes read from hex string
   242  * accept spaces and hexes */
   243 static unsigned
   244 str_to_fpr (const char *str, uint8_t *fpr, size_t *length)
   245 {
   246     unsigned i,j;
   247 
   248     *length = 0;
   249     
   250     if (str == NULL)
   251         return 0;
   252 
   253     while(*str && *length < PGP_FINGERPRINT_SIZE){
   254         while (*str == ' ') str++;
   255         for (j = 0; j < 2; j++) {
   256             uint8_t *byte = &fpr[*length];
   257             *byte = 0;
   258             for (i = 0; i < 2; i++) {
   259                 if (i > 0)
   260                     *byte = *byte << 4;
   261                 if (*str >= 'a' && *str <= 'f')
   262                     *byte += 10 + *str - 'a';
   263                 else if (*str >= 'A' && *str <= 'F')
   264                     *byte += 10 + *str - 'A';
   265                 else if (*str >= '0' && *str <= '9')
   266                     *byte += *str - '0';
   267                 else
   268                     return 0;
   269                 str++;
   270             }
   271             (*length)++;
   272         }
   273     }
   274     return 1;
   275 }
   276 
   277 // Iterate through netpgp' reported valid signatures
   278 // fill a list of valid figerprints
   279 // returns PEP_STATUS_OK if all sig reported valid
   280 // error status otherwise.
   281 static PEP_STATUS _validation_results(
   282         netpgp_t *netpgp,
   283         pgp_validation_t *vresult,
   284         stringlist_t **keylist
   285     )
   286 {
   287     time_t    now;
   288     time_t    t;
   289 
   290     *keylist = NULL;
   291 
   292     now = time(NULL);
   293     if (now < vresult->birthtime) {
   294         // signature is not valid yet
   295         return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   296     }
   297     if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
   298         // signature has expired
   299         t = vresult->duration + vresult->birthtime;
   300         return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   301     }
   302     if (vresult->validc && vresult->valid_sigs &&
   303         !vresult->invalidc && !vresult->unknownc ) {
   304         
   305         stringlist_t *_keylist;
   306 
   307         // caller responsible to free
   308         _keylist = new_stringlist(NULL);
   309         assert(_keylist);
   310         if (_keylist == NULL) {
   311             return PEP_OUT_OF_MEMORY;
   312         }
   313         
   314         stringlist_t *k = _keylist;
   315         unsigned c = 0;
   316         for (unsigned n = 0; n < vresult->validc; ++n) {
   317             unsigned from = 0;
   318             const pgp_key_t	 *signer;
   319             char *fprstr = NULL;
   320             const uint8_t *keyid = vresult->valid_sigs[n].signer_id;
   321 
   322             signer = pgp_getkeybyid(netpgp->io, netpgp->pubring,
   323                                     keyid, &from, NULL, NULL,
   324                                     0, 0); /* check neither revocation nor expiry
   325                                               as is should be checked already */
   326             if(signer)
   327                 fpr_to_str(&fprstr,
   328                            signer->pubkeyfpr.fingerprint,
   329                            signer->pubkeyfpr.length);
   330             else
   331                 continue;
   332 
   333             if (fprstr == NULL){
   334                 free_stringlist(_keylist);
   335                 return PEP_OUT_OF_MEMORY;
   336             }
   337 
   338             k = stringlist_add(k, fprstr);
   339 
   340             free(fprstr);
   341 
   342             if(!k){
   343                 free_stringlist(_keylist);
   344                 return PEP_OUT_OF_MEMORY;
   345             }
   346 
   347             c++;
   348         }
   349         if(c > 0) {
   350             *keylist = _keylist;
   351             return PEP_STATUS_OK;
   352         }
   353 
   354         free_stringlist(_keylist);
   355         return PEP_VERIFY_NO_KEY;
   356     }
   357     if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
   358         // No signatures found - is this memory signed?
   359         return PEP_VERIFY_NO_KEY;
   360     }
   361 
   362     if (vresult->invalidc) {
   363         // some invalid signatures
   364         return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   365     }
   366 
   367     // only unknown sigs
   368     return PEP_DECRYPTED;
   369 }
   370 
   371 #define _ENDL    "\\s*(\r\n|\r|\n)"
   372 #define ARMOR_HEAD    "^-----BEGIN PGP MESSAGE-----"_ENDL
   373 PEP_STATUS pgp_decrypt_and_verify(
   374     PEP_SESSION session, const char *ctext, size_t csize,
   375     const char *dsigtext, size_t dsigsize,
   376     char **ptext, size_t *psize, stringlist_t **keylist,
   377     char** filename_ptr // will be ignored
   378     )
   379 {
   380     char *_ptext = NULL;
   381 
   382     PEP_STATUS result;
   383     stringlist_t *_keylist = NULL;
   384 
   385     assert(session);
   386     assert(ctext);
   387     assert(csize);
   388     assert(ptext);
   389     assert(psize);
   390     assert(keylist);
   391 
   392     if(!session || !ctext || !csize || !ptext || !psize || !keylist)
   393         return PEP_ILLEGAL_VALUE;
   394 
   395     if(pthread_mutex_lock(&netpgp_mutex)){
   396         return PEP_UNKNOWN_ERROR;
   397     }
   398 
   399     *ptext = NULL;
   400     *psize = 0;
   401     *keylist = NULL;
   402 
   403     pgp_validation_t *vresult = malloc(sizeof(pgp_validation_t));
   404     memset(vresult, 0x0, sizeof(pgp_validation_t));
   405 
   406     key_id_t *recipients_key_ids = NULL;
   407     unsigned recipients_count = 0;
   408 
   409     pgp_memory_t *mem = pgp_decrypt_and_validate_buf(netpgp.io, vresult, ctext, csize,
   410                 netpgp.secring, netpgp.pubring,
   411                 _armoured(ctext, csize, ARMOR_HEAD),
   412                  &recipients_key_ids, &recipients_count);
   413 
   414     if (mem == NULL) {
   415         result = PEP_OUT_OF_MEMORY;
   416         goto unlock_netpgp;
   417     }
   418 
   419     const size_t _psize = pgp_mem_len(mem);
   420     if (_psize){
   421         if ((_ptext = malloc(_psize + 1)) == NULL) {
   422             result = PEP_OUT_OF_MEMORY;
   423             goto free_pgp;
   424         }
   425         memcpy(_ptext, pgp_mem_data(mem), _psize);
   426         _ptext[_psize] = '\0'; // safeguard for naive users
   427         result = PEP_DECRYPTED;
   428     }else{
   429         result = PEP_DECRYPT_NO_KEY;
   430         goto free_pgp;
   431     }
   432 
   433     if (result == PEP_DECRYPTED) {
   434         result = _validation_results(&netpgp, vresult, &_keylist);
   435         if (result == PEP_DECRYPTED ||
   436             result == PEP_VERIFY_NO_KEY) {
   437             if((_keylist = new_stringlist("")) == NULL) {
   438                 result = PEP_OUT_OF_MEMORY;
   439                 goto free_ptext;
   440             }
   441             result = PEP_DECRYPTED;
   442         }else if (result != PEP_STATUS_OK) {
   443             goto free_ptext;
   444         }else{
   445             result = PEP_DECRYPTED_AND_VERIFIED;
   446         }
   447     }
   448 
   449     stringlist_t *k = _keylist;
   450     for (unsigned n = 0; n < recipients_count; ++n) {
   451         unsigned from = 0;
   452         const pgp_key_t	 *rcpt;
   453         char *fprstr = NULL;
   454         key_id_t *keyid = &recipients_key_ids[n];
   455 
   456         rcpt = pgp_getkeybyid(netpgp.io, netpgp.pubring,
   457                                 *keyid, &from, NULL, NULL,
   458                                 0, 0); /* check neither revocation nor expiry*/
   459         if(rcpt)
   460             fpr_to_str(&fprstr,
   461                        rcpt->pubkeyfpr.fingerprint,
   462                        rcpt->pubkeyfpr.length);
   463         else
   464             // if no key found put ID instead of fpr
   465             fpr_to_str(&fprstr,
   466                        *keyid,
   467                        sizeof(key_id_t));
   468 
   469         if (fprstr == NULL){
   470             result = PEP_OUT_OF_MEMORY;
   471             goto free_keylist;
   472         }
   473 
   474         k = stringlist_add_unique(k, fprstr);
   475 
   476         free(fprstr);
   477 
   478         if(!k){
   479             result = PEP_OUT_OF_MEMORY;
   480             goto free_keylist;
   481         }
   482     }
   483 
   484     if (result == PEP_DECRYPTED_AND_VERIFIED
   485         || result == PEP_DECRYPTED) {
   486         *ptext = _ptext;
   487         *psize = _psize;
   488         (*ptext)[*psize] = 0; // safeguard for naive users
   489         *keylist = _keylist;
   490 
   491         /* _ptext and _keylist ownership transfer, don't free */
   492         goto free_pgp;
   493     }
   494 
   495 free_keylist:
   496     free_stringlist(_keylist);
   497 
   498 free_ptext:
   499     free(_ptext);
   500 
   501 free_pgp:
   502     pgp_memory_free(mem);
   503     pgp_validate_result_free(vresult);
   504 
   505 unlock_netpgp:
   506     free(recipients_key_ids);
   507     pthread_mutex_unlock(&netpgp_mutex);
   508 
   509     return result;
   510 }
   511 
   512 #define ARMOR_SIG_HEAD    "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----"_ENDL
   513 PEP_STATUS pgp_verify_text(
   514     PEP_SESSION session, const char *text, size_t size,
   515     const char *signature, size_t sig_size, stringlist_t **keylist
   516     )
   517 {
   518     pgp_memory_t *signedmem;
   519     pgp_memory_t *sig;
   520     pgp_validation_t *vresult;
   521 
   522     PEP_STATUS result;
   523     stringlist_t *_keylist;
   524 
   525     assert(session);
   526     assert(text);
   527     assert(size);
   528     assert(signature);
   529     assert(sig_size);
   530     assert(keylist);
   531 
   532     if(!session || !text || !size || !signature || !sig_size || !keylist)
   533         return PEP_ILLEGAL_VALUE;
   534 
   535     if(pthread_mutex_lock(&netpgp_mutex)){
   536         return PEP_UNKNOWN_ERROR;
   537     }
   538 
   539     *keylist = NULL;
   540 
   541     vresult = malloc(sizeof(pgp_validation_t));
   542     if (vresult == NULL) {
   543         result = PEP_OUT_OF_MEMORY;
   544         goto unlock_netpgp;
   545     }
   546     memset(vresult, 0x0, sizeof(pgp_validation_t));
   547 
   548     signedmem = pgp_memory_new();
   549     if (signedmem == NULL) {
   550         result = PEP_OUT_OF_MEMORY;
   551         goto unlock_netpgp;
   552     }
   553     pgp_memory_add(signedmem, (const uint8_t*)text, size);
   554 
   555     sig = pgp_memory_new();
   556     if (sig == NULL) {
   557         pgp_memory_free(signedmem);
   558         result = PEP_OUT_OF_MEMORY;
   559         goto unlock_netpgp;
   560     }
   561     pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
   562 
   563     pgp_validate_mem_detached(netpgp.io, vresult, sig,
   564                 NULL,/* output */
   565                 _armoured(signature, sig_size, ARMOR_SIG_HEAD),
   566                 netpgp.pubring,
   567                 signedmem);
   568 
   569     result = _validation_results(&netpgp, vresult, &_keylist);
   570     if (result != PEP_STATUS_OK) {
   571         goto free_pgp;
   572     }else{
   573         result = PEP_VERIFIED;
   574     }
   575 
   576     if (result == PEP_VERIFIED) {
   577         /* TODO : check trust level */
   578         result = PEP_VERIFIED_AND_TRUSTED;
   579     }
   580 
   581     if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
   582         *keylist = _keylist;
   583 
   584         /* _keylist ownership transfer, don't free */
   585         goto free_pgp;
   586     }
   587 
   588     free_stringlist(_keylist);
   589 
   590 free_pgp:
   591     // free done by pgp_validate_mem_detached
   592     // pgp_memory_free(sig);
   593     // pgp_memory_free(signedmem);
   594     pgp_validate_result_free(vresult);
   595 
   596 unlock_netpgp:
   597     pthread_mutex_unlock(&netpgp_mutex);
   598 
   599     return result;
   600 }
   601 
   602 static PEP_STATUS _encrypt_and_sign(
   603     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   604     size_t psize, char **ctext, size_t *csize, bool do_sign
   605     )
   606 {
   607     pgp_key_t *signer = NULL;
   608     pgp_seckey_t *seckey = NULL;
   609     pgp_memory_t *signedmem = NULL;
   610     pgp_memory_t *cmem;
   611     const char *hashalg;
   612     pgp_keyring_t *rcpts;
   613 
   614     PEP_STATUS result;
   615     const stringlist_t *_keylist;
   616 
   617     assert(session);
   618     assert(keylist);
   619     assert(ptext);
   620     assert(psize);
   621     assert(ctext);
   622     assert(csize);
   623 
   624     if(!session || !ptext || !psize || !ctext || !csize || !keylist)
   625         return PEP_ILLEGAL_VALUE;
   626 
   627     if(pthread_mutex_lock(&netpgp_mutex)){
   628         return PEP_UNKNOWN_ERROR;
   629     }
   630 
   631     *ctext = NULL;
   632     *csize = 0;
   633 
   634     if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
   635         result = PEP_OUT_OF_MEMORY;
   636         goto unlock_netpgp;
   637     }
   638     for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
   639         assert(_keylist->value);
   640 
   641         const pgp_key_t *key;
   642         uint8_t fpr[PGP_FINGERPRINT_SIZE];
   643         size_t fprlen;
   644         unsigned from = 0;
   645 
   646         if (str_to_fpr(_keylist->value, fpr, &fprlen)) {
   647             if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring,
   648                                                     fpr, fprlen, &from, NULL,
   649                                                     /* reject revoked, accept expired */
   650                                                     1,0)) == NULL) {
   651                 result = PEP_KEY_NOT_FOUND;
   652                 goto free_rcpts;
   653             }
   654         }else{
   655             result = PEP_ILLEGAL_VALUE;
   656             goto free_rcpts;
   657         }
   658 
   659         /* Signer is the first key in the list */
   660         if(signer == NULL){
   661             from = 0;
   662             signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring,
   663                                                   fpr, fprlen,
   664                                                   &from,
   665                                                   NULL,
   666                                                   0,0); /* accept any */
   667             if(signer == NULL){
   668                 result = PEP_KEY_NOT_FOUND;
   669                 goto free_rcpts;
   670             }
   671         }
   672 
   673         // add key to recipients/signers
   674         pgp_keyring_add(rcpts, key);
   675         if(rcpts->keys == NULL){
   676             result = PEP_OUT_OF_MEMORY;
   677             goto free_rcpts;
   678         }
   679     }
   680 
   681     /* Empty keylist ?*/
   682     if(rcpts->keyc == 0){
   683         result = PEP_ILLEGAL_VALUE;
   684         goto free_rcpts;
   685     }
   686 
   687     seckey = pgp_key_get_certkey(signer);
   688 
   689     /* No signig key. Revoked ? */
   690     if(seckey == NULL){
   691         result = PEP_GET_KEY_FAILED;
   692         goto free_rcpts;
   693     }
   694 
   695     hashalg = netpgp_getvar(&netpgp, "hash");
   696 
   697     const char *stext;
   698     size_t ssize;
   699     unsigned encrypt_raw_packet;
   700    
   701     if (do_sign) {  
   702         // Sign data
   703         signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey,
   704                     time(NULL), /* birthtime */
   705                     0 /* duration */,
   706                     hashalg,
   707                     0 /* armored */,
   708                     0 /* cleartext */);
   709 
   710         if (!signedmem) {
   711             result = PEP_UNENCRYPTED;
   712             goto free_rcpts;
   713         }
   714         stext = (char*) pgp_mem_data(signedmem);
   715         ssize = pgp_mem_len(signedmem);
   716         encrypt_raw_packet = 1 /* takes raw OpenPGP message */;
   717     } else {
   718         stext = ptext;
   719         ssize = psize;
   720         encrypt_raw_packet = 0 /* not a raw OpenPGP message */;
   721     }
   722 
   723     // Encrypt (maybe) signed data
   724 
   725     cmem = pgp_encrypt_buf(netpgp.io, stext,
   726             ssize, rcpts, 1 /* armored */,
   727             netpgp_getvar(&netpgp, "cipher"),
   728             encrypt_raw_packet);
   729 
   730     if (cmem == NULL) {
   731         result = PEP_OUT_OF_MEMORY;
   732         goto free_signedmem;
   733     }else{
   734 
   735         char *_buffer = NULL;
   736         size_t length = pgp_mem_len(cmem);
   737 
   738         // Allocate transferable buffer
   739         _buffer = malloc(length + 1);
   740         assert(_buffer);
   741         if (_buffer == NULL) {
   742             result = PEP_OUT_OF_MEMORY;
   743             goto free_cmem;
   744         }
   745 
   746         memcpy(_buffer, pgp_mem_data(cmem), length);
   747 
   748         *ctext = _buffer;
   749         *csize = length;
   750         (*ctext)[*csize] = 0; // safeguard for naive users
   751         result = PEP_STATUS_OK;
   752     }
   753 
   754 free_cmem :
   755     pgp_memory_free(cmem);
   756 free_signedmem :
   757     if (do_sign) {
   758         pgp_memory_free(signedmem);
   759     }
   760 free_rcpts :
   761     pgp_keyring_free(rcpts);
   762 unlock_netpgp:
   763     pthread_mutex_unlock(&netpgp_mutex);
   764 
   765     return result;
   766 }
   767 
   768 
   769 PEP_STATUS pgp_sign_only(
   770     PEP_SESSION session, const char* fpr, const char *ptext,
   771     size_t psize, char **stext, size_t *ssize
   772     )
   773 {
   774     pgp_key_t *signer = NULL;
   775     pgp_seckey_t *seckey = NULL;
   776     pgp_memory_t *signedmem = NULL;
   777     pgp_memory_t *text = NULL;
   778 	pgp_output_t *output;
   779     
   780     const char *hashalg;
   781     pgp_keyring_t *snrs;
   782 
   783 	pgp_create_sig_t	*sig;
   784 	uint8_t	keyid[PGP_KEY_ID_SIZE];
   785 
   786     PEP_STATUS result;
   787 
   788     assert(session);
   789     assert(fpr);
   790     assert(ptext);
   791     assert(psize);
   792     assert(stext);
   793     assert(ssize);
   794 
   795     if(!session || !ptext || !psize || !stext || !ssize || !fpr || !fpr[0])
   796         return PEP_ILLEGAL_VALUE;
   797 
   798     if(pthread_mutex_lock(&netpgp_mutex)){
   799         return PEP_UNKNOWN_ERROR;
   800     }
   801 
   802     *stext = NULL;
   803     *ssize = 0;
   804 
   805     if ((snrs = calloc(1, sizeof(*snrs))) == NULL) {
   806         result = PEP_OUT_OF_MEMORY;
   807         goto unlock_netpgp;
   808     }
   809     
   810     assert(fpr && fpr[0]);
   811 
   812     uint8_t uint_fpr[PGP_FINGERPRINT_SIZE];
   813     size_t fprlen;
   814     unsigned from = 0;
   815 
   816     if (str_to_fpr(fpr, uint_fpr, &fprlen)) {
   817         if ((signer = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.secring,
   818                                                 uint_fpr, fprlen, &from, NULL,
   819                                                 /* reject revoked and expired */
   820                                                 1,1)) == NULL) {
   821             result = PEP_KEY_NOT_FOUND;
   822             goto free_snrs;
   823         }
   824     } else{
   825         result = PEP_ILLEGAL_VALUE;
   826         goto free_snrs;
   827     }
   828 
   829     // add key to signers
   830     pgp_keyring_add(snrs, signer);
   831     if(snrs->keys == NULL){
   832         result = PEP_OUT_OF_MEMORY;
   833         goto free_snrs;
   834     }
   835 
   836     /* Empty keylist ?*/
   837     if(snrs->keyc == 0){
   838         result = PEP_ILLEGAL_VALUE;
   839         goto free_snrs;
   840     }
   841 
   842     seckey = pgp_key_get_certkey(signer);
   843 
   844     /* No signing key. Revoked ? */
   845     if(seckey == NULL){
   846         result = PEP_GET_KEY_FAILED;
   847         goto free_snrs;
   848     }
   849 
   850     hashalg = netpgp_getvar(&netpgp, "hash");
   851     
   852     const char *_stext;
   853     size_t _ssize;
   854 
   855 	text = pgp_memory_new();
   856     pgp_memory_add(text, (const uint8_t*)ptext, psize);
   857 
   858     pgp_setup_memory_write(&output, &signedmem, psize);
   859 	pgp_writer_push_armor_msg(output);
   860 
   861     pgp_hash_alg_t hash_alg = pgp_str_to_hash_alg(hashalg);
   862     
   863 	sig = pgp_create_sig_new();
   864 	pgp_start_sig(sig, seckey, hash_alg, PGP_SIG_BINARY);
   865 
   866 	pgp_sig_add_data(sig, pgp_mem_data(text), pgp_mem_len(text));
   867 	pgp_memory_free(text);
   868 
   869 	pgp_add_creation_time(sig, time(NULL));
   870 	pgp_add_sig_expiration_time(sig, 0);
   871 	pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg);
   872 	pgp_add_issuer_keyid(sig, keyid);
   873 	pgp_end_hashed_subpkts(sig);
   874 
   875     pgp_write_sig(output, sig, &seckey->pubkey, seckey);
   876 	pgp_writer_close(output);
   877 	pgp_create_sig_delete(sig);
   878    
   879     if (!signedmem) {
   880         result = PEP_UNENCRYPTED;
   881         goto free_snrs;
   882     }
   883     _stext = (char*) pgp_mem_data(signedmem);
   884     _ssize = pgp_mem_len(signedmem);
   885         
   886     // Allocate transferable buffer
   887     char *_buffer = malloc(_ssize + 1);
   888 
   889     assert(_buffer);
   890     if (_buffer == NULL) {
   891         result = PEP_OUT_OF_MEMORY;
   892         goto free_signedmem;
   893     }
   894 
   895     memcpy(_buffer, _stext, _ssize);
   896     *stext = _buffer;
   897     *ssize = _ssize;
   898     (*stext)[*ssize] = 0; // safeguard for naive users
   899 
   900     result = PEP_STATUS_OK;
   901 
   902 free_signedmem :
   903     pgp_memory_free(signedmem);
   904 free_snrs :
   905     pgp_keyring_free(snrs);
   906 unlock_netpgp:
   907     pthread_mutex_unlock(&netpgp_mutex);
   908 
   909     return result;
   910 }
   911 
   912 
   913 PEP_STATUS pgp_encrypt_and_sign(
   914     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   915     size_t psize, char **ctext, size_t *csize
   916     )
   917 {
   918     PEP_STATUS result;
   919     result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize,
   920                                true);
   921     return result;
   922 }
   923 
   924 PEP_STATUS pgp_encrypt_only(
   925         PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   926         size_t psize, char **ctext, size_t *csize
   927     )
   928 {
   929     PEP_STATUS result;
   930     result = _encrypt_and_sign(session, keylist, ptext, psize, ctext, csize,
   931                                false);
   932     return result;
   933 }
   934 
   935 
   936 PEP_STATUS pgp_generate_keypair(
   937     PEP_SESSION session, pEp_identity *identity
   938     )
   939 {
   940     pgp_key_t	newseckey;
   941     pgp_key_t	*newpubkey;
   942 
   943     PEP_STATUS result;
   944     char newid[1024];
   945     const char *hashalg;
   946     const char *cipher;
   947 
   948     assert(session);
   949     assert(identity);
   950     assert(identity->address);
   951     assert(identity->fpr == NULL);
   952     assert(identity->username);
   953 
   954     if(!session || !identity ||
   955        !identity->address || identity->fpr || !identity->username)
   956         return PEP_ILLEGAL_VALUE;
   957 
   958     if(pthread_mutex_lock(&netpgp_mutex)){
   959         return PEP_UNKNOWN_ERROR;
   960     }
   961 
   962     if(snprintf(newid, sizeof(newid),
   963         "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
   964         result =  PEP_BUFFER_TOO_SMALL;
   965         goto unlock_netpgp;
   966     }
   967 
   968     hashalg = netpgp_getvar(&netpgp, "hash");
   969     cipher = netpgp_getvar(&netpgp, "cipher");
   970 
   971     bzero(&newseckey, sizeof(newseckey));
   972 
   973     // Generate the key
   974     if (!pgp_rsa_generate_keypair(&newseckey, 4096, 65537UL, hashalg, cipher,
   975                                   (const uint8_t *) "", (const size_t) 0))
   976     {
   977         result = PEP_CANNOT_CREATE_KEY;
   978         goto free_seckey;
   979     }
   980 
   981     /* make a public key out of generated secret key */
   982     if((newpubkey = pgp_ensure_pubkey(
   983             netpgp.pubring,
   984             &newseckey.key.seckey.pubkey,
   985             newseckey.pubkeyid))==NULL)
   986     {
   987         result = PEP_OUT_OF_MEMORY;
   988         goto free_seckey;
   989     }
   990 
   991     // "Expire-Date: 1y\n";
   992     if (!pgp_add_selfsigned_userid(&newseckey, newpubkey,
   993                                   (uint8_t *)newid, 365*24*3600))
   994     {
   995         result = PEP_CANNOT_CREATE_KEY;
   996         goto delete_pubkey;
   997     }
   998 
   999     if (newpubkey == NULL)
  1000     {
  1001         result = PEP_OUT_OF_MEMORY;
  1002         goto delete_pubkey;
  1003     }
  1004 
  1005     // Append key to netpgp's rings (key ownership transfered)
  1006     if (!pgp_keyring_add(netpgp.secring, &newseckey)){
  1007         result = PEP_OUT_OF_MEMORY;
  1008         goto delete_pubkey;
  1009     }
  1010 
  1011     // save rings
  1012     if (netpgp_save_pubring(&netpgp) && netpgp_save_secring(&netpgp))
  1013     {
  1014         char *fprstr = NULL;
  1015         fpr_to_str(&fprstr,
  1016                    newseckey.pubkeyfpr.fingerprint,
  1017                    newseckey.pubkeyfpr.length);
  1018 
  1019         if (fprstr == NULL) {
  1020             result = PEP_OUT_OF_MEMORY;
  1021             goto pop_secring;
  1022         }
  1023 
  1024         /* keys saved, pass fingerprint back */
  1025         identity->fpr = fprstr;
  1026         result = PEP_STATUS_OK;
  1027 
  1028         /* free nothing, everything transfered */
  1029         goto unlock_netpgp;
  1030     } else {
  1031         /* XXX in case only pubring save succeed
  1032          * pubring file is left as-is, but backup restore
  1033          * could be attempted if such corner case matters */
  1034         result = PEP_UNKNOWN_ERROR;
  1035     }
  1036 
  1037 pop_secring:
  1038     ((pgp_keyring_t *)netpgp.secring)->keyc--;
  1039 delete_pubkey:
  1040     pgp_deletekeybyfpr(netpgp.io,
  1041                     (pgp_keyring_t *)netpgp.pubring,
  1042                     newseckey.pubkeyfpr.fingerprint,
  1043                     newseckey.pubkeyfpr.length);
  1044 free_seckey:
  1045     pgp_key_free(&newseckey);
  1046 unlock_netpgp:
  1047     pthread_mutex_unlock(&netpgp_mutex);
  1048 
  1049     return result;
  1050 }
  1051 
  1052 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr)
  1053 {
  1054     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1055     size_t length;
  1056 
  1057     PEP_STATUS result;
  1058 
  1059     assert(session);
  1060     assert(fprstr);
  1061 
  1062     if (!session || !fprstr)
  1063         return PEP_ILLEGAL_VALUE;
  1064 
  1065     if(pthread_mutex_lock(&netpgp_mutex)){
  1066         return PEP_UNKNOWN_ERROR;
  1067     }
  1068 
  1069     if (str_to_fpr(fprstr, fpr, &length)) {
  1070         unsigned insec = pgp_deletekeybyfpr(netpgp.io,
  1071                                 (pgp_keyring_t *)netpgp.secring,
  1072                                 (const uint8_t *)fpr, length);
  1073         unsigned inpub = pgp_deletekeybyfpr(netpgp.io,
  1074                                 (pgp_keyring_t *)netpgp.pubring,
  1075                                 (const uint8_t *)fpr, length);
  1076         if(!insec && !inpub){
  1077             result = PEP_KEY_NOT_FOUND;
  1078             goto unlock_netpgp;
  1079         } else {
  1080             result = PEP_STATUS_OK;
  1081         }
  1082     }else{
  1083         result = PEP_OUT_OF_MEMORY;
  1084         goto unlock_netpgp;
  1085     }
  1086 
  1087     // save rings
  1088     if (netpgp_save_pubring(&netpgp) &&
  1089         netpgp_save_secring(&netpgp))
  1090     {
  1091         result = PEP_STATUS_OK;
  1092     }else{
  1093         result = PEP_UNKNOWN_ERROR;
  1094     }
  1095 
  1096 unlock_netpgp:
  1097     pthread_mutex_unlock(&netpgp_mutex);
  1098 
  1099     return result;
  1100 }
  1101 
  1102 #define ARMOR_KEY_HEAD    "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----"_ENDL
  1103 PEP_STATUS pgp_import_keydata(
  1104         PEP_SESSION session,
  1105         const char *key_data,
  1106         size_t size,
  1107         identity_list **private_idents
  1108     )
  1109 {
  1110     pgp_memory_t *mem;
  1111 
  1112     PEP_STATUS result = PEP_STATUS_OK;
  1113 
  1114     assert(session);
  1115     assert(key_data);
  1116 
  1117     // reporting imported private keys not supported
  1118     // stub code to be reomoved
  1119     if(private_idents)
  1120         *private_idents = NULL;
  1121 
  1122     if(!session || !key_data)
  1123         return PEP_ILLEGAL_VALUE;
  1124 
  1125     if(pthread_mutex_lock(&netpgp_mutex)){
  1126         return PEP_UNKNOWN_ERROR;
  1127     }
  1128 
  1129     mem = pgp_memory_new();
  1130     if (mem == NULL) {
  1131         result = PEP_OUT_OF_MEMORY;
  1132         goto unlock_netpgp;
  1133     }
  1134     pgp_memory_add(mem, (const uint8_t*)key_data, size);
  1135 
  1136     if (pgp_keyring_read_from_mem(netpgp.io, netpgp.pubring, netpgp.secring,
  1137                                   _armoured(key_data, size, ARMOR_KEY_HEAD),
  1138                                   mem) == 0){
  1139         result = PEP_ILLEGAL_VALUE;
  1140     }
  1141 
  1142     pgp_memory_free(mem);
  1143 
  1144     // save rings
  1145     if (netpgp_save_pubring(&netpgp) &&
  1146         netpgp_save_secring(&netpgp))
  1147     {
  1148         // we never really know if a key was imported. MEH.
  1149         result = PEP_KEY_IMPORT_STATUS_UNKNOWN;
  1150     }else{
  1151         result = PEP_UNKNOWN_ERROR;
  1152     }
  1153 
  1154 unlock_netpgp:
  1155     pthread_mutex_unlock(&netpgp_mutex);
  1156 
  1157     return result;
  1158 }
  1159 
  1160 static PEP_STATUS _export_keydata(
  1161     pgp_key_t *key,
  1162     char **buffer,
  1163     size_t *buflen
  1164     )
  1165 {
  1166     PEP_STATUS result;
  1167 	pgp_output_t *output;
  1168     pgp_memory_t *mem;
  1169 	pgp_setup_memory_write(&output, &mem, 128);
  1170 
  1171     if (mem == NULL || output == NULL) {
  1172         return PEP_ILLEGAL_VALUE;
  1173     }
  1174 
  1175     if (!pgp_write_xfer_key(output, key, 1)) {
  1176         result = PEP_UNKNOWN_ERROR;
  1177         goto free_mem;
  1178     }
  1179 
  1180     *buffer = NULL;
  1181     *buflen = pgp_mem_len(mem);
  1182 
  1183     // Allocate transferable buffer
  1184     *buffer = malloc(*buflen + 1);
  1185     assert(*buffer);
  1186     if (*buffer == NULL) {
  1187         result = PEP_OUT_OF_MEMORY;
  1188         goto free_mem;
  1189     }
  1190 
  1191     memcpy(*buffer, pgp_mem_data(mem), *buflen);
  1192     (*buffer)[*buflen] = 0; // safeguard for naive users
  1193 
  1194     return PEP_STATUS_OK;
  1195 
  1196 free_mem :
  1197 	pgp_teardown_memory_write(output, mem);
  1198 
  1199     return result;
  1200 }
  1201 
  1202 PEP_STATUS pgp_export_keydata(
  1203     PEP_SESSION session, const char *fprstr, char **key_data, size_t *size,
  1204     bool secret
  1205     )
  1206 {
  1207     pgp_key_t *key;
  1208     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1209     size_t fprlen;
  1210 
  1211     PEP_STATUS result;
  1212     char *buffer;
  1213     size_t buflen;
  1214     const pgp_keyring_t *srcring;
  1215 
  1216     assert(session);
  1217     assert(fprstr);
  1218     assert(key_data);
  1219     assert(size);
  1220 
  1221     if (secret)
  1222         srcring = netpgp.secring;
  1223     else
  1224         srcring = netpgp.pubring;
  1225     
  1226     if (!session || !fprstr || !key_data || !size)
  1227         return PEP_ILLEGAL_VALUE;
  1228 
  1229     if(pthread_mutex_lock(&netpgp_mutex)){
  1230         return PEP_UNKNOWN_ERROR;
  1231     }
  1232 
  1233     if (str_to_fpr(fprstr, fpr, &fprlen)) {
  1234         unsigned from = 0;
  1235 
  1236         if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, srcring,
  1237                                                 fpr, fprlen, &from,
  1238                                                 NULL,0,0)) == NULL) {
  1239             result = PEP_KEY_NOT_FOUND;
  1240             goto unlock_netpgp;
  1241         }
  1242     }else{
  1243         result = PEP_OUT_OF_MEMORY;
  1244         goto unlock_netpgp;
  1245     }
  1246 
  1247     result = _export_keydata(key, &buffer, &buflen);
  1248 
  1249     if(result == PEP_STATUS_OK)
  1250     {
  1251         *key_data = buffer;
  1252         *size = buflen;
  1253         result = PEP_STATUS_OK;
  1254     }
  1255 
  1256 unlock_netpgp:
  1257     pthread_mutex_unlock(&netpgp_mutex);
  1258 
  1259     return result;
  1260 }
  1261 
  1262 struct HKP_answer {
  1263   char *memory;
  1264   size_t size;
  1265 };
  1266 
  1267 static size_t
  1268 HKPAnswerWriter(void *contents, size_t size, size_t nmemb, void *userp)
  1269 {
  1270   size_t realsize = size * nmemb;
  1271   struct HKP_answer *mem = (struct HKP_answer *)userp;
  1272 
  1273   mem->memory = realloc(mem->memory, mem->size + realsize + 1);
  1274   if(mem->memory == NULL) {
  1275     mem->size = 0;
  1276     return 0;
  1277   }
  1278 
  1279   memcpy(&(mem->memory[mem->size]), contents, realsize);
  1280   mem->size += realsize;
  1281   mem->memory[mem->size] = 0;
  1282 
  1283   return realsize;
  1284 }
  1285 
  1286 #define HKP_SERVER "http://keys.gnupg.net:11371"
  1287 // #define HKP_SERVER "http://127.0.0.1:11371"
  1288 
  1289 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
  1290 {
  1291     static const char *ks_cmd = HKP_SERVER
  1292                                 "/pks/lookup?"
  1293                                 "op=get&options=mr&exact=on&"
  1294                                 "search=";
  1295     char *encoded_pattern;
  1296     char *request = NULL;
  1297     struct HKP_answer answer;
  1298     CURLcode curlres;
  1299 
  1300     PEP_STATUS result;
  1301 
  1302     CURL *curl;
  1303 
  1304     assert(session);
  1305     assert(pattern);
  1306 
  1307     if (!session || !pattern )
  1308         return PEP_ILLEGAL_VALUE;
  1309 
  1310     if(pthread_mutex_lock(&session->ctx.curl_mutex)){
  1311         return PEP_UNKNOWN_ERROR;
  1312     }
  1313 
  1314     result = curl_get_ctx(&curl);
  1315     if(result != PEP_STATUS_OK){
  1316         goto unlock_curl;
  1317     }
  1318 
  1319     encoded_pattern = curl_easy_escape(curl, (char*)pattern, 0);
  1320     if(!encoded_pattern){
  1321         result = PEP_OUT_OF_MEMORY;
  1322         goto release_curl_ctx;
  1323     }
  1324 
  1325     if((request = malloc(strlen(ks_cmd) + strlen(encoded_pattern) + 1))==NULL){
  1326         result = PEP_OUT_OF_MEMORY;
  1327         goto free_encoded_pattern;
  1328     }
  1329 
  1330     //(*stpcpy(stpcpy(request, ks_cmd), encoded_pattern)) = '\0';
  1331     stpcpy(stpcpy(request, ks_cmd), encoded_pattern);
  1332 
  1333     curl_easy_setopt(curl, CURLOPT_URL,request);
  1334 
  1335     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HKPAnswerWriter);
  1336 
  1337     answer.memory = NULL;
  1338     answer.size = 0;
  1339     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&answer);
  1340 
  1341     curlres = curl_easy_perform(curl);
  1342     if(curlres != CURLE_OK) {
  1343         result = PEP_GET_KEY_FAILED;
  1344         goto free_request;
  1345     }
  1346 
  1347     if(!answer.memory || !answer.size) {
  1348         result = PEP_OUT_OF_MEMORY;
  1349         goto free_request;
  1350     }
  1351 
  1352     result = pgp_import_keydata(session,
  1353                                 answer.memory,
  1354                                 answer.size,
  1355                                 NULL);
  1356 
  1357     free(answer.memory);
  1358 free_request:
  1359     free(request);
  1360 free_encoded_pattern:
  1361     curl_free(encoded_pattern);
  1362 release_curl_ctx:
  1363     curl_release_ctx(&curl);
  1364 unlock_curl:
  1365     pthread_mutex_unlock(&session->ctx.curl_mutex);
  1366 
  1367     return result;
  1368 }
  1369 
  1370 typedef PEP_STATUS (*find_key_cb_t)(void*, pgp_key_t *);
  1371 
  1372 static PEP_STATUS find_keys_do(pgp_keyring_t* keyring,
  1373         const char *pattern, find_key_cb_t cb, void* cb_arg)
  1374 {
  1375     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1376     size_t length;
  1377     pgp_key_t *key;
  1378 
  1379     PEP_STATUS result;
  1380 
  1381     // Try find a fingerprint in pattern
  1382     if (str_to_fpr(pattern, fpr, &length)) {
  1383         unsigned from = 0;
  1384 
  1385 
  1386         // Only one fingerprint can match
  1387         if ((key = (pgp_key_t *)pgp_getkeybyfpr(
  1388                         netpgp.io,
  1389                         keyring,
  1390                         (const uint8_t *)fpr, length,
  1391                         &from,
  1392                         NULL, 0, 0)) == NULL) {
  1393 
  1394             return PEP_KEY_NOT_FOUND;
  1395         }
  1396 
  1397         result = cb(cb_arg, key);
  1398 
  1399     } else {
  1400         // Search by name for pattern. Can match many.
  1401         unsigned from = 0;
  1402         result = PEP_KEY_NOT_FOUND;
  1403         while((key = (pgp_key_t *)pgp_getnextkeybyname(
  1404                         netpgp.io,
  1405                         keyring,
  1406 			            (const char *)pattern,
  1407                         &from)) != NULL) {
  1408 
  1409             result = cb(cb_arg, key);
  1410             if (result != PEP_STATUS_OK)
  1411                 break;
  1412 
  1413             from++;
  1414         }
  1415     }
  1416 
  1417     return result;
  1418 }
  1419 
  1420 static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key)
  1421 {
  1422     stringlist_t **keylist = arg;
  1423     char *newfprstr = NULL;
  1424 
  1425     fpr_to_str(&newfprstr,
  1426                key->pubkeyfpr.fingerprint,
  1427                key->pubkeyfpr.length);
  1428 
  1429     if (newfprstr == NULL) {
  1430         return PEP_OUT_OF_MEMORY;
  1431     } else {
  1432 
  1433         stringlist_add(*keylist, newfprstr);
  1434         free(newfprstr);
  1435         if (*keylist == NULL) {
  1436             return PEP_OUT_OF_MEMORY;
  1437         }
  1438     }
  1439     return PEP_STATUS_OK;
  1440 }
  1441 
  1442 static PEP_STATUS add_secret_key_fpr_to_stringlist(void *arg, pgp_key_t *key)
  1443 {
  1444     if (pgp_is_key_secret(key)) {
  1445         stringlist_t **keylist = arg;
  1446         char *newfprstr = NULL;
  1447 
  1448         fpr_to_str(&newfprstr,
  1449                 key->pubkeyfpr.fingerprint,
  1450                 key->pubkeyfpr.length);
  1451 
  1452         if (newfprstr == NULL) {
  1453             return PEP_OUT_OF_MEMORY;
  1454         } else {
  1455             stringlist_add(*keylist, newfprstr);
  1456             free(newfprstr);
  1457             if (*keylist == NULL) {
  1458                 return PEP_OUT_OF_MEMORY;
  1459             }
  1460         }
  1461     }
  1462     return PEP_STATUS_OK;
  1463 }
  1464 
  1465 static PEP_STATUS add_keyinfo_to_stringpair_list(void* arg, pgp_key_t *key) {
  1466     stringpair_list_t** keyinfo_list = (stringpair_list_t**)arg;
  1467     stringpair_t* pair = NULL;
  1468     char* id_fpr = NULL;
  1469     char* primary_userid = (char*)pgp_key_get_primary_userid(key);
  1470 
  1471 // Unused:
  1472 //    bool key_revoked = false;
  1473 
  1474 //    PEP_STATUS key_status = pgp_key_revoked(session, id_fpr, &key_revoked);
  1475 
  1476 //    if (key_revoked || key_status == PEP_GET_KEY_FAILED)
  1477 //        return PEP_STATUS_OK; // we just move on
  1478 
  1479     fpr_to_str(&id_fpr, key->pubkeyfpr.fingerprint,
  1480                 key->pubkeyfpr.length);
  1481 
  1482     pair = new_stringpair(id_fpr, primary_userid);
  1483 
  1484     if (pair == NULL)
  1485         return PEP_OUT_OF_MEMORY;
  1486 
  1487     *keyinfo_list = stringpair_list_add(*keyinfo_list, pair);
  1488     free(id_fpr);
  1489     if (*keyinfo_list == NULL)
  1490         return PEP_OUT_OF_MEMORY;
  1491     return PEP_STATUS_OK;
  1492 }
  1493 
  1494 PEP_STATUS pgp_find_keys(
  1495     PEP_SESSION session, const char *pattern, stringlist_t **keylist
  1496     )
  1497 {
  1498     stringlist_t *_keylist, *_k;
  1499 
  1500     PEP_STATUS result;
  1501 
  1502     assert(session);
  1503     assert(pattern);
  1504     assert(keylist);
  1505 
  1506     if (!session || !pattern || !keylist )
  1507     {
  1508         return PEP_ILLEGAL_VALUE;
  1509     }
  1510 
  1511     if (pthread_mutex_lock(&netpgp_mutex))
  1512     {
  1513         return PEP_UNKNOWN_ERROR;
  1514     }
  1515 
  1516     *keylist = NULL;
  1517     _keylist = new_stringlist(NULL);
  1518     if (_keylist == NULL) {
  1519         result = PEP_OUT_OF_MEMORY;
  1520         goto unlock_netpgp;
  1521     }
  1522     _k = _keylist;
  1523 
  1524     result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
  1525                           pattern, &add_key_fpr_to_stringlist, &_k);
  1526 
  1527     if (result == PEP_STATUS_OK) {
  1528         *keylist = _keylist;
  1529         // Transfer ownership, no free
  1530         goto unlock_netpgp;
  1531     }
  1532 
  1533     free_stringlist(_keylist);
  1534 
  1535 unlock_netpgp:
  1536     pthread_mutex_unlock(&netpgp_mutex);
  1537 
  1538     return result;
  1539 }
  1540 
  1541 #define HKP_REQ_PREFIX "keytext="
  1542 #define HKP_REQ_PREFIX_LEN 8
  1543 
  1544 static PEP_STATUS send_key_cb(void *arg, pgp_key_t *key)
  1545 {
  1546     char *buffer = NULL;
  1547     size_t buflen = 0;
  1548     PEP_STATUS result;
  1549     stringlist_t *encoded_keys;
  1550     encoded_keys = (stringlist_t*)arg;
  1551 
  1552     result = _export_keydata(key, &buffer, &buflen);
  1553 
  1554     if(result == PEP_STATUS_OK){
  1555         char *encoded_key = curl_escape(buffer, (int)buflen);
  1556         if(!encoded_key){
  1557             result = PEP_OUT_OF_MEMORY;
  1558             goto free_buffer;
  1559         }
  1560         size_t encoded_key_len = strlen(encoded_key);
  1561 
  1562         char *request = calloc(1, HKP_REQ_PREFIX_LEN + encoded_key_len + 1);
  1563         if(!request){
  1564             result = PEP_OUT_OF_MEMORY;
  1565             goto free_encoded_key;
  1566         }
  1567 
  1568         memcpy(request, HKP_REQ_PREFIX, HKP_REQ_PREFIX_LEN);
  1569         memcpy(request + HKP_REQ_PREFIX_LEN, encoded_key, encoded_key_len);
  1570         request[HKP_REQ_PREFIX_LEN + encoded_key_len] = '\0';
  1571 
  1572         if(!stringlist_add(encoded_keys, request)){
  1573             result = PEP_OUT_OF_MEMORY;
  1574         }
  1575         free(request);
  1576 
  1577 free_encoded_key:
  1578         curl_free(encoded_key);
  1579 
  1580 free_buffer:
  1581         free(buffer);
  1582     }
  1583 
  1584     return result;
  1585 }
  1586 
  1587 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
  1588 {
  1589     static const char *ks_cmd = HKP_SERVER "/pks/add";
  1590 
  1591     PEP_STATUS result;
  1592     CURL *curl = NULL;
  1593 
  1594     assert(session);
  1595     assert(pattern);
  1596 
  1597     if (!session || !pattern )
  1598         return PEP_ILLEGAL_VALUE;
  1599 
  1600     stringlist_t *encoded_keys = new_stringlist(NULL);
  1601     assert(encoded_keys);
  1602     if (encoded_keys == NULL) {
  1603         return PEP_OUT_OF_MEMORY;
  1604     }
  1605 
  1606     if(pthread_mutex_lock(&netpgp_mutex)){
  1607         result = PEP_UNKNOWN_ERROR;
  1608         goto free_encoded_keys;
  1609     }
  1610 
  1611     result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
  1612                           pattern, &send_key_cb, (void*)encoded_keys);
  1613 
  1614     pthread_mutex_unlock(&netpgp_mutex);
  1615 
  1616     if(result != PEP_STATUS_OK){
  1617         goto free_encoded_keys;
  1618     }
  1619 
  1620     if(pthread_mutex_lock(&session->ctx.curl_mutex)){
  1621         result = PEP_UNKNOWN_ERROR;
  1622         goto free_encoded_keys;
  1623     }
  1624 
  1625     result = curl_get_ctx(&curl);
  1626     if(result != PEP_STATUS_OK){
  1627         goto unlock_curl;
  1628     }
  1629 
  1630     if(result == PEP_STATUS_OK){
  1631         CURLcode curlres;
  1632 
  1633         for (const stringlist_t *post = encoded_keys; post != NULL; post = post->next) {
  1634             assert(post->value);
  1635 
  1636             curl_easy_setopt(curl, CURLOPT_URL, ks_cmd);
  1637             curl_easy_setopt(curl, CURLOPT_POST, 1L);
  1638             curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post->value);
  1639             curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
  1640 
  1641             // Uncomment if debugging
  1642             // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  1643 
  1644             curlres = curl_easy_perform(curl);
  1645 
  1646             if(curlres != CURLE_OK) {
  1647 
  1648                 result = PEP_CANNOT_SEND_KEY;
  1649                 goto release_curl_ctx;
  1650             }
  1651         }
  1652     }
  1653 
  1654 release_curl_ctx:
  1655     curl_release_ctx(&curl);
  1656 unlock_curl:
  1657     pthread_mutex_unlock(&session->ctx.curl_mutex);
  1658 free_encoded_keys:
  1659     free_stringlist(encoded_keys);
  1660 
  1661     return result;
  1662 }
  1663 
  1664 
  1665 PEP_STATUS pgp_get_key_rating(
  1666     PEP_SESSION session,
  1667     const char *fprstr,
  1668     PEP_comm_type *comm_type
  1669     )
  1670 {
  1671     pgp_key_t *key;
  1672     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1673     unsigned from = 0;
  1674     size_t length;
  1675 
  1676 
  1677     PEP_STATUS status = PEP_STATUS_OK;
  1678 
  1679     assert(session);
  1680     assert(fprstr);
  1681     assert(comm_type);
  1682 
  1683     if (!session || !fprstr || !comm_type )
  1684         return PEP_ILLEGAL_VALUE;
  1685 
  1686     *comm_type = PEP_ct_unknown;
  1687 
  1688     if(pthread_mutex_lock(&netpgp_mutex)){
  1689         return PEP_UNKNOWN_ERROR;
  1690     }
  1691 
  1692     if (!str_to_fpr(fprstr, fpr, &length)) {
  1693         status = PEP_ILLEGAL_VALUE;
  1694         goto unlock_netpgp;
  1695     }
  1696 
  1697     key = pgp_getkeybyfpr(
  1698            netpgp.io,
  1699            netpgp.pubring,
  1700            fpr, length, &from, NULL,0,0);
  1701 
  1702     if(key == NULL)
  1703     {
  1704         status = PEP_KEY_NOT_FOUND;
  1705         goto unlock_netpgp;
  1706     }
  1707 
  1708     switch(pgp_key_get_rating(key)){
  1709 	case PGP_VALID:
  1710         *comm_type = PEP_ct_OpenPGP_unconfirmed;
  1711         break;
  1712     case PGP_WEAK:
  1713         *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
  1714         break;
  1715     case PGP_TOOSHORT:
  1716         *comm_type = PEP_ct_key_too_short;
  1717         break;
  1718 	case PGP_INVALID:
  1719         *comm_type = PEP_ct_key_b0rken;
  1720         break;
  1721 	case PGP_EXPIRED:
  1722         *comm_type = PEP_ct_key_expired;
  1723         break;
  1724     case PGP_REVOKED:
  1725         *comm_type = PEP_ct_key_revoked;
  1726         break;
  1727     default:
  1728         break;
  1729     }
  1730 
  1731 unlock_netpgp:
  1732     pthread_mutex_unlock(&netpgp_mutex);
  1733 
  1734     return status;
  1735 }
  1736 
  1737 PEP_STATUS pgp_renew_key(
  1738         PEP_SESSION session,
  1739         const char *fprstr,
  1740         const timestamp *ts
  1741     )
  1742 {
  1743     pgp_key_t *pkey;
  1744     pgp_key_t *skey;
  1745     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1746     size_t length;
  1747     unsigned from = 0;
  1748     time_t duration;
  1749     const uint8_t *primid;
  1750 
  1751     PEP_STATUS status = PEP_STATUS_OK;
  1752 
  1753     assert(session);
  1754     assert(fprstr);
  1755 
  1756     if (!session || !fprstr )
  1757         return PEP_ILLEGAL_VALUE;
  1758 
  1759     if(ts)
  1760     {
  1761         time_t    now, when;
  1762         now = time(NULL);
  1763         when = mktime((struct tm*)ts);
  1764         if(now && when && when > now){
  1765             duration = when - now;
  1766         }else{
  1767             return PEP_ILLEGAL_VALUE;
  1768         }
  1769     }else{
  1770         /* Default 1 year from now */
  1771         duration = 365*24*3600;
  1772     }
  1773 
  1774     if(pthread_mutex_lock(&netpgp_mutex)){
  1775         return PEP_UNKNOWN_ERROR;
  1776     }
  1777 
  1778 
  1779     if (!str_to_fpr(fprstr, fpr, &length)) {
  1780         status = PEP_ILLEGAL_VALUE;
  1781         goto unlock_netpgp;
  1782     }
  1783 
  1784     pkey = pgp_getkeybyfpr(
  1785                           netpgp.io,
  1786                           netpgp.pubring,
  1787                           fpr, length, &from, NULL,
  1788                           1, 0); /* reject revoked, accept expired */
  1789 
  1790     if(pkey == NULL)
  1791     {
  1792         status = PEP_KEY_NOT_FOUND;
  1793         goto unlock_netpgp;
  1794     }
  1795 
  1796     from = 0;
  1797     skey = pgp_getkeybyfpr(
  1798                            netpgp.io,
  1799                            netpgp.secring,
  1800                            fpr, length, &from, NULL,
  1801                            1, 0); /* reject revoked, accept expired */
  1802 
  1803     if(skey == NULL)
  1804     {
  1805         status = PEP_KEY_NOT_FOUND;
  1806         goto unlock_netpgp;
  1807     }
  1808 
  1809     if((primid = pgp_key_get_primary_userid(skey)) == NULL)
  1810     {
  1811         status = PEP_KEY_HAS_AMBIG_NAME;
  1812         goto unlock_netpgp;
  1813     }
  1814 
  1815     // FIXME : renew in a more gentle way
  1816     if (!pgp_add_selfsigned_userid(skey, pkey, primid, duration))
  1817     {
  1818         status = PEP_CANNOT_CREATE_KEY;
  1819         goto unlock_netpgp;
  1820     }
  1821 
  1822     // save rings
  1823     if (netpgp_save_pubring(&netpgp) &&
  1824         netpgp_save_secring(&netpgp))
  1825     {
  1826         status = PEP_STATUS_OK;
  1827     }else{
  1828         status = PEP_UNKNOWN_ERROR;
  1829     }
  1830 
  1831 unlock_netpgp:
  1832     pthread_mutex_unlock(&netpgp_mutex);
  1833 
  1834     return status;
  1835 }
  1836 
  1837 PEP_STATUS pgp_revoke_key(
  1838         PEP_SESSION session,
  1839         const char *fprstr,
  1840         const char *reason
  1841     )
  1842 {
  1843     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1844     size_t length;
  1845     unsigned from = 0;
  1846 
  1847     PEP_STATUS status = PEP_STATUS_OK;
  1848 
  1849     assert(session);
  1850     assert(fprstr);
  1851 
  1852     if (!session || !fprstr)
  1853         return PEP_UNKNOWN_ERROR;
  1854 
  1855     if(pthread_mutex_lock(&netpgp_mutex)){
  1856         return PEP_UNKNOWN_ERROR;
  1857     }
  1858 
  1859     // FIXME : deduplicate that code w/ renew
  1860     if (!str_to_fpr(fprstr, fpr, &length)) {
  1861         status = PEP_ILLEGAL_VALUE;
  1862         goto unlock_netpgp;
  1863     }
  1864 
  1865     pgp_key_t *pkey = pgp_getkeybyfpr(
  1866                            netpgp.io,
  1867                            netpgp.pubring,
  1868                            fpr, length, &from, NULL,
  1869                            1, 0); /* reject revoked, accept expired */
  1870 
  1871     if(pkey == NULL)
  1872     {
  1873         status = PEP_KEY_NOT_FOUND;
  1874         goto unlock_netpgp;
  1875     }
  1876 
  1877     from = 0;
  1878     pgp_key_t *skey = pgp_getkeybyfpr(
  1879                            netpgp.io,
  1880                            netpgp.secring,
  1881                            fpr, length, &from, NULL,
  1882                            1, 0); /* reject revoked, accept expired */
  1883 
  1884     if(skey == NULL)
  1885     {
  1886         status = PEP_KEY_NOT_FOUND;
  1887         goto unlock_netpgp;
  1888     }
  1889 
  1890     pgp_key_revoke(skey, pkey,
  1891                    0, /* no reason code specified */
  1892                    reason);
  1893 
  1894 unlock_netpgp:
  1895     pthread_mutex_unlock(&netpgp_mutex);
  1896 
  1897     return status;
  1898 }
  1899 
  1900 PEP_STATUS pgp_key_expired(
  1901         PEP_SESSION session,
  1902         const char *fprstr,
  1903         const time_t when,
  1904         bool *expired
  1905     )
  1906 {
  1907     PEP_STATUS status = PEP_STATUS_OK;
  1908     PEP_comm_type comm_type;
  1909 
  1910     assert(session);
  1911     assert(fprstr);
  1912     assert(expired);
  1913 
  1914     if (!session || !fprstr || !expired)
  1915         return PEP_UNKNOWN_ERROR;
  1916 
  1917     // TODO : take "when" in account
  1918 
  1919     *expired = false;
  1920 
  1921     status = pgp_get_key_rating(session, fprstr, &comm_type);
  1922 
  1923     if (status != PEP_STATUS_OK)
  1924         return status;
  1925 
  1926     if (comm_type == PEP_ct_key_expired){
  1927         *expired = true;
  1928     }
  1929 
  1930     return PEP_STATUS_OK;
  1931 }
  1932 
  1933 PEP_STATUS pgp_key_revoked(
  1934         PEP_SESSION session,
  1935         const char *fprstr,
  1936         bool *revoked
  1937     )
  1938 {
  1939     PEP_STATUS status = PEP_STATUS_OK;
  1940     PEP_comm_type comm_type;
  1941 
  1942     assert(session);
  1943     assert(fprstr);
  1944     assert(revoked);
  1945 
  1946     *revoked = false;
  1947 
  1948     status = pgp_get_key_rating(session, fprstr, &comm_type);
  1949 
  1950     if (status != PEP_STATUS_OK)
  1951         return status;
  1952 
  1953     if (comm_type == PEP_ct_key_revoked){
  1954         *revoked = true;
  1955     }
  1956 
  1957     return PEP_STATUS_OK;
  1958 }
  1959 
  1960 PEP_STATUS pgp_key_created(
  1961         PEP_SESSION session,
  1962         const char *fprstr,
  1963         time_t *created
  1964     )
  1965 {
  1966     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1967     pgp_key_t *key;
  1968     size_t length;
  1969     unsigned from = 0;
  1970 
  1971     PEP_STATUS status = PEP_STATUS_OK;
  1972 
  1973     assert(session);
  1974     assert(fprstr);
  1975     assert(created);
  1976 
  1977     if (!session || !fprstr || !created)
  1978         return PEP_UNKNOWN_ERROR;
  1979 
  1980     *created = 0;
  1981 
  1982     if(pthread_mutex_lock(&netpgp_mutex)){
  1983         return PEP_UNKNOWN_ERROR;
  1984     }
  1985 
  1986     if (!str_to_fpr(fprstr, fpr, &length)) {
  1987         status = PEP_ILLEGAL_VALUE;
  1988         goto unlock_netpgp;
  1989     }
  1990 
  1991     key = pgp_getkeybyfpr(
  1992            netpgp.io,
  1993            netpgp.pubring,
  1994            fpr, length, &from, NULL,0,0);
  1995 
  1996     if (key)
  1997     {
  1998         *created = (time_t) key->key.pubkey.birthtime;
  1999     }
  2000     else
  2001     {
  2002         status = PEP_KEY_NOT_FOUND;
  2003         goto unlock_netpgp;
  2004     }
  2005 
  2006 
  2007 
  2008 unlock_netpgp:
  2009     pthread_mutex_unlock(&netpgp_mutex);
  2010 
  2011     return status;
  2012 }
  2013 
  2014 
  2015 PEP_STATUS pgp_list_keyinfo(
  2016         PEP_SESSION session, const char* pattern, stringpair_list_t** keyinfo_list)
  2017 {
  2018 
  2019     if (!session || !keyinfo_list)
  2020         return PEP_UNKNOWN_ERROR;
  2021 
  2022     if (pthread_mutex_lock(&netpgp_mutex))
  2023     {
  2024         return PEP_UNKNOWN_ERROR;
  2025     }
  2026 
  2027 // Unused:
  2028 //    pgp_key_t *key;
  2029 
  2030     PEP_STATUS result;
  2031 
  2032     result = find_keys_do((pgp_keyring_t *)netpgp.pubring,
  2033                           pattern, &add_keyinfo_to_stringpair_list, (void*)keyinfo_list);
  2034 
  2035     if (!keyinfo_list)
  2036         result = PEP_KEY_NOT_FOUND;
  2037 
  2038     pthread_mutex_unlock(&netpgp_mutex);
  2039 
  2040     return result;
  2041 }
  2042 
  2043 /* copied from find_keys, but we need to use a callback that filters. */
  2044 PEP_STATUS pgp_find_private_keys(
  2045     PEP_SESSION session, const char *pattern, stringlist_t **keylist)
  2046 {
  2047     stringlist_t *_keylist, *_k;
  2048 
  2049     PEP_STATUS result;
  2050 
  2051     assert(session);
  2052     assert(keylist);
  2053 
  2054     if (!session || !keylist )
  2055     {
  2056         return PEP_ILLEGAL_VALUE;
  2057     }
  2058 
  2059     if (pthread_mutex_lock(&netpgp_mutex))
  2060     {
  2061         return PEP_UNKNOWN_ERROR;
  2062     }
  2063 
  2064     *keylist = NULL;
  2065     _keylist = new_stringlist(NULL);
  2066     if (_keylist == NULL) {
  2067         result = PEP_OUT_OF_MEMORY;
  2068         goto unlock_netpgp;
  2069     }
  2070     _k = _keylist;
  2071 
  2072     result = find_keys_do((pgp_keyring_t *)netpgp.secring,
  2073                           pattern, &add_secret_key_fpr_to_stringlist, &_k);
  2074 
  2075     if (result == PEP_STATUS_OK) {
  2076         *keylist = _keylist;
  2077         // Transfer ownership, no free
  2078         goto unlock_netpgp;
  2079     }
  2080 
  2081     free_stringlist(_keylist);
  2082 
  2083 unlock_netpgp:
  2084     pthread_mutex_unlock(&netpgp_mutex);
  2085 
  2086     return result;
  2087 }
  2088 
  2089 PEP_STATUS pgp_contains_priv_key(
  2090     PEP_SESSION session,
  2091     const char *fpr,
  2092     bool *has_private) {
  2093     stringlist_t* keylist = NULL;
  2094     PEP_STATUS status = pgp_find_private_keys(session, fpr, &keylist);
  2095     if (status == PEP_STATUS_OK && keylist) {
  2096         free_stringlist(keylist);
  2097         *has_private = true;
  2098     }
  2099     else {
  2100         *has_private = false;
  2101     }
  2102     return status;
  2103 }
  2104 
  2105 PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session) {
  2106     // Not implemented - netpgp doesn't appear to keep track of trust status in
  2107     // a meaningful way, though there is space for it in the structs.
  2108     return PEP_STATUS_OK;
  2109 }