src/pgp_netpgp.c
author Edouard Tisserant
Tue, 12 May 2015 16:37:31 +0200
changeset 272 f82971ed62e5
parent 271 18b5097c4428
child 276 73d4c99cf054
permissions -rw-r--r--
netpgp : ensure null terminated decryped data
     1 #include "pEp_internal.h"
     2 #include "pgp_netpgp.h"
     3 
     4 #include <limits.h>
     5 
     6 #include "wrappers.h"
     7 
     8 #include <netpgp.h>
     9 #include <netpgp/config.h>
    10 #include <netpgp/memory.h>
    11 #include <netpgp/crypto.h>
    12 #include <netpgp/netpgpsdk.h>
    13 #include <netpgp/validate.h>
    14 #include <netpgp/readerwriter.h>
    15 
    16 #include <curl/curl.h>
    17 #include <pthread.h>
    18 #include <regex.h>
    19 
    20 static netpgp_t netpgp;
    21 static pthread_mutex_t netpgp_mutex;
    22 
    23 static PEP_STATUS init_netpgp()
    24 {
    25     PEP_STATUS status = PEP_STATUS_OK;
    26     const char *home = NULL;
    27 
    28     if(pthread_mutex_init(&netpgp_mutex, NULL)){
    29         return PEP_OUT_OF_MEMORY;
    30     }
    31 
    32     if(pthread_mutex_lock(&netpgp_mutex)){
    33         return PEP_UNKNOWN_ERROR;
    34     }
    35 
    36     if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
    37         setlocale(LC_ALL, "");
    38 
    39     memset(&netpgp, 0x0, sizeof(netpgp_t));
    40 
    41     // netpgp_setvar(&netpgp, "max mem alloc", "4194304");
    42     netpgp_setvar(&netpgp, "need seckey", "1");
    43     netpgp_setvar(&netpgp, "need userid", "1");
    44 
    45     // NetPGP shares home with GPG
    46     home = gpg_home();
    47     if(home){
    48         netpgp_set_homedir(&netpgp,(char*)home, NULL, 0);
    49     }else{
    50         status = PEP_INIT_NO_GPG_HOME;
    51         goto unlock_netpgp;
    52     }
    53 
    54     // pair with gpg's cert-digest-algo
    55     netpgp_setvar(&netpgp, "hash", "SHA256");
    56 
    57     // subset of gpg's personal-cipher-preferences
    58     // here only one cipher can be selected
    59     netpgp_setvar(&netpgp, "cipher", "CAST5");
    60 
    61     if (!netpgp_init(&netpgp)) {
    62         status = PEP_INIT_NETPGP_INIT_FAILED;
    63         goto unlock_netpgp;
    64     }
    65 
    66 unlock_netpgp:
    67     pthread_mutex_unlock(&netpgp_mutex);
    68     
    69     return status;
    70 }
    71 
    72 static void release_netpgp()
    73 {
    74     if(pthread_mutex_lock(&netpgp_mutex)){
    75         return;
    76     }
    77     netpgp_end(&netpgp);
    78     memset(&netpgp, 0x0, sizeof(netpgp_t));
    79 
    80     pthread_mutex_destroy(&netpgp_mutex);
    81 
    82     return;
    83 }
    84 
    85 static PEP_STATUS init_curl(
    86     CURL **curl,
    87     pthread_mutex_t *curl_mutex,
    88     bool in_first)
    89 {
    90     PEP_STATUS status = PEP_STATUS_OK;
    91     struct curl_slist *headers=NULL;
    92 
    93     if(pthread_mutex_init(curl_mutex, NULL)){
    94         return PEP_OUT_OF_MEMORY;
    95     }
    96 
    97     if(pthread_mutex_lock(curl_mutex)){
    98         return PEP_UNKNOWN_ERROR;
    99     }
   100 
   101     if(in_first){
   102         curl_global_init(CURL_GLOBAL_DEFAULT);
   103     }
   104 
   105     if ((*curl = curl_easy_init()) == NULL) {
   106         return PEP_OUT_OF_MEMORY;
   107     }
   108 
   109     curl_easy_setopt(*curl, CURLOPT_FOLLOWLOCATION, 1L);
   110     curl_easy_setopt(*curl, CURLOPT_MAXREDIRS, 3L);
   111 
   112     headers=curl_slist_append(headers,"Pragma: no-cache");
   113     if(headers)
   114         headers=curl_slist_append(headers,"Cache-Control: no-cache");
   115 
   116     if(!headers)
   117     {
   118         status = PEP_OUT_OF_MEMORY;
   119         goto unlock_curl;
   120     }
   121 
   122     curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
   123     curl_slist_free_all(headers);
   124 
   125     // TODO curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
   126 
   127 unlock_curl:
   128     pthread_mutex_unlock(curl_mutex);
   129     return status;
   130 }
   131 
   132 static void release_curl(
   133     CURL **curl,
   134     pthread_mutex_t *curl_mutex, 
   135     bool out_last)
   136 {
   137     if(pthread_mutex_lock(curl_mutex)){
   138         return;
   139     }
   140 
   141     if(*curl)
   142         curl_easy_cleanup(*curl);
   143 
   144     *curl = NULL;
   145 
   146     if(out_last){
   147         curl_global_cleanup();
   148     }
   149 
   150     pthread_mutex_destroy(curl_mutex);
   151 
   152     return;
   153 }
   154 
   155 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
   156 {
   157     PEP_STATUS status = PEP_STATUS_OK;
   158 
   159     assert(session);
   160     if(!session) return PEP_UNKNOWN_ERROR;
   161 
   162     if (in_first) {
   163         if((status = init_netpgp()) != PEP_STATUS_OK)
   164         return status;
   165     }
   166 
   167     if((status = init_curl(
   168                     &session->ctx.curl,
   169                     &session->ctx.curl_mutex,
   170                     in_first) != PEP_STATUS_OK)){
   171         if(in_first) release_netpgp();
   172         return status;
   173     }
   174 
   175     return PEP_STATUS_OK;
   176 }
   177 
   178 void pgp_release(PEP_SESSION session, bool out_last)
   179 {
   180     assert(session);
   181     if(!session) return;
   182 
   183     if (out_last){
   184         release_netpgp();
   185     }
   186     release_curl(&session->ctx.curl, &session->ctx.curl_mutex, out_last);
   187 }
   188 
   189 // return 1 if the file contains ascii-armoured text 
   190 // buf MUST be \0 terminated to be checked for armour
   191 static unsigned
   192 _armoured(const char *buf, size_t size, const char *pattern)
   193 {
   194     unsigned armoured = 0;
   195     if(buf[size]=='\0'){
   196         regex_t r;
   197         regcomp(&r, pattern, REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
   198         if (regexec(&r, buf, 0, NULL, 0) == 0) {
   199             armoured = 1;
   200         }
   201         regfree(&r);
   202     }
   203     return armoured;
   204 }
   205 
   206 /* return key ID's hexdump as a string */
   207 static void id_to_str(const uint8_t *userid, char *fpr)
   208 {
   209     int i;
   210     static const char *hexes = "0123456789abcdef";
   211     for (i = 0; i < 8 ; i++) {
   212         fpr[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
   213         fpr[(i * 2) + 1] = hexes[userid[i] & 0xf];
   214     }
   215     fpr[8 * 2] = 0x0;
   216 }
   217 
   218 // Iterate through netpgp' reported valid signatures 
   219 // fill a list of valid figerprints
   220 // returns PEP_STATUS_OK if all sig reported valid
   221 // error status otherwise.
   222 static PEP_STATUS _validation_results(netpgp_t *netpgp, pgp_validation_t *vresult,
   223                                              stringlist_t **_keylist)
   224 {
   225     time_t    now;
   226     time_t    t;
   227     char    buf[128];
   228 
   229     now = time(NULL);
   230     if (now < vresult->birthtime) {
   231         // signature is not valid yet
   232         return PEP_UNENCRYPTED;
   233     }
   234     if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
   235         // signature has expired
   236         t = vresult->duration + vresult->birthtime;
   237         return PEP_UNENCRYPTED;
   238     }
   239     if (vresult->validc && vresult->valid_sigs &&
   240         !vresult->invalidc && !vresult->unknownc ) {
   241         unsigned    n;
   242         stringlist_t *k;
   243         // caller responsible to free
   244         *_keylist = new_stringlist(NULL);
   245         assert(*_keylist);
   246         if (*_keylist == NULL) {
   247             return PEP_OUT_OF_MEMORY;
   248         }
   249         k = *_keylist;
   250         for (n = 0; n < vresult->validc; ++n) {
   251             char id[MAX_ID_LENGTH + 1];
   252             const uint8_t *userid = vresult->valid_sigs[n].signer_id;
   253 
   254             id_to_str(userid, id);
   255 
   256             k = stringlist_add(k, id);
   257             if(!k){
   258                 free_stringlist(*_keylist);
   259                 return PEP_OUT_OF_MEMORY;
   260             }
   261         }
   262         return PEP_STATUS_OK;
   263     }
   264     if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
   265         // No signatures found - is this memory signed?
   266         return PEP_VERIFY_NO_KEY; 
   267     } 
   268     
   269     if (vresult->invalidc) {
   270         // some invalid signatures
   271         return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   272     }
   273     
   274     // only unknown sigs
   275     return PEP_DECRYPT_WRONG_FORMAT;
   276 }
   277 
   278 #define ARMOR_HEAD    "^-----BEGIN PGP MESSAGE-----\\s*$"
   279 PEP_STATUS pgp_decrypt_and_verify(
   280     PEP_SESSION session, const char *ctext, size_t csize,
   281     char **ptext, size_t *psize, stringlist_t **keylist
   282     )
   283 {
   284     pgp_memory_t *mem;
   285     pgp_memory_t *cat;
   286     pgp_validation_t *vresult;
   287     char *_ptext = NULL;
   288     size_t _psize = 0;
   289     int ret;
   290 
   291     PEP_STATUS result;
   292     stringlist_t *_keylist = NULL;
   293     int i_key = 0;
   294 
   295     assert(session);
   296     assert(ctext);
   297     assert(csize);
   298     assert(ptext);
   299     assert(psize);
   300     assert(keylist);
   301 
   302     if(!session || !ctext || !csize || !ptext || !psize || !keylist) 
   303         return PEP_UNKNOWN_ERROR;
   304 
   305     if(pthread_mutex_lock(&netpgp_mutex)){
   306         return PEP_UNKNOWN_ERROR;
   307     }
   308 
   309     *ptext = NULL;
   310     *psize = 0;
   311     *keylist = NULL;
   312 
   313     vresult = malloc(sizeof(pgp_validation_t));
   314     memset(vresult, 0x0, sizeof(pgp_validation_t));
   315 
   316     mem = pgp_decrypt_and_validate_buf(netpgp.io, vresult, ctext, csize,
   317                 netpgp.secring, netpgp.pubring,
   318                 _armoured(ctext, csize, ARMOR_HEAD),
   319                 0 /* sshkeys */,
   320                 NULL, -1, NULL  /* pass fp,attempts,cb */);
   321     if (mem == NULL) {
   322         result = PEP_OUT_OF_MEMORY;
   323         goto unlock_netpgp;
   324     }
   325 
   326     _psize = pgp_mem_len(mem);
   327     if (_psize){
   328         if ((_ptext = malloc(_psize + 1)) == NULL) {
   329             result = PEP_OUT_OF_MEMORY;
   330             goto free_pgp;
   331         }
   332         memcpy(_ptext, pgp_mem_data(mem), _psize);
   333         _ptext[_psize] = '\0'; // safeguard for naive users
   334         result = PEP_DECRYPTED;
   335     }else{
   336         result = PEP_DECRYPT_NO_KEY;
   337         goto free_pgp;
   338     }
   339 
   340     if (result == PEP_DECRYPTED) {
   341         result = _validation_results(&netpgp, vresult, &_keylist);
   342         if (result != PEP_STATUS_OK) {
   343             goto free_ptext;
   344         }
   345         result = PEP_DECRYPTED_AND_VERIFIED;
   346     }
   347 
   348     if (result == PEP_DECRYPTED_AND_VERIFIED
   349         || result == PEP_DECRYPTED) {
   350         *ptext = _ptext;
   351         *psize = _psize;
   352         (*ptext)[*psize] = 0; // safeguard for naive users
   353         if (result == PEP_DECRYPTED_AND_VERIFIED) {
   354             *keylist = _keylist;
   355         }
   356 
   357         /* _ptext and _keylist ownership transfer, don't free */
   358         goto free_pgp;
   359     }
   360 
   361 free_keylist:
   362     free_stringlist(_keylist);
   363 
   364 free_ptext:
   365     free(_ptext);
   366 
   367 free_pgp:
   368     pgp_memory_free(mem);
   369     pgp_validate_result_free(vresult);
   370 
   371 unlock_netpgp:
   372     pthread_mutex_unlock(&netpgp_mutex);
   373 
   374     return result;
   375 }
   376 
   377 #define ARMOR_SIG_HEAD    "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----\\s*$"
   378 PEP_STATUS pgp_verify_text(
   379     PEP_SESSION session, const char *text, size_t size,
   380     const char *signature, size_t sig_size, stringlist_t **keylist
   381     )
   382 {
   383     pgp_memory_t *signedmem;
   384     pgp_memory_t *sig;
   385     pgp_validation_t *vresult;
   386 
   387     PEP_STATUS result;
   388     stringlist_t *_keylist;
   389 
   390     assert(session);
   391     assert(text);
   392     assert(size);
   393     assert(signature);
   394     assert(sig_size);
   395     assert(keylist);
   396 
   397     if(!session || !text || !size || !signature || !sig_size || !keylist) 
   398         return PEP_UNKNOWN_ERROR;
   399 
   400     if(pthread_mutex_lock(&netpgp_mutex)){
   401         return PEP_UNKNOWN_ERROR;
   402     }
   403 
   404     *keylist = NULL;
   405 
   406     vresult = malloc(sizeof(pgp_validation_t));
   407     memset(vresult, 0x0, sizeof(pgp_validation_t));
   408 
   409     signedmem = pgp_memory_new();
   410     if (signedmem == NULL) {
   411         result = PEP_OUT_OF_MEMORY;
   412         goto unlock_netpgp;
   413     }
   414     pgp_memory_add(signedmem, (const uint8_t*)text, size);
   415 
   416     sig = pgp_memory_new();
   417     if (sig == NULL) {
   418         pgp_memory_free(signedmem);
   419         result = PEP_OUT_OF_MEMORY;
   420         goto unlock_netpgp;
   421     }
   422     pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
   423 
   424     pgp_validate_mem_detached(netpgp.io, vresult, sig,
   425                 NULL,/* output */
   426                 _armoured(signature, sig_size, ARMOR_SIG_HEAD),
   427                 netpgp.pubring,
   428                 signedmem);
   429 
   430     result = _validation_results(&netpgp, vresult, &_keylist);
   431     if (result != PEP_STATUS_OK) {
   432         goto free_pgp;
   433     }else{
   434         result = PEP_VERIFIED;
   435     }
   436 
   437     if (result == PEP_VERIFIED) {
   438         /* TODO : check trust level */
   439         result = PEP_VERIFIED_AND_TRUSTED;
   440     }
   441 
   442     if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
   443         *keylist = _keylist;
   444 
   445         /* _keylist ownership transfer, don't free */
   446         goto free_pgp;
   447     }
   448 
   449 free_keylist:
   450     free_stringlist(_keylist);
   451 
   452 free_pgp:
   453     // free done by pgp_validate_mem_detached
   454     // pgp_memory_free(sig);
   455     // pgp_memory_free(signedmem);
   456     pgp_validate_result_free(vresult);
   457 
   458 unlock_netpgp:
   459     pthread_mutex_unlock(&netpgp_mutex);
   460 
   461     return result;
   462 }
   463 
   464 PEP_STATUS pgp_encrypt_and_sign(
   465     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   466     size_t psize, char **ctext, size_t *csize
   467     )
   468 {
   469     const pgp_key_t *keypair;
   470     pgp_seckey_t *seckey;
   471     pgp_memory_t *signedmem;
   472     pgp_memory_t *cmem;
   473     const char *userid;
   474     const char *hashalg;
   475     pgp_keyring_t *rcpts;
   476 
   477     PEP_STATUS result;
   478     const stringlist_t *_keylist;
   479 
   480     assert(session);
   481     assert(keylist);
   482     assert(ptext);
   483     assert(psize);
   484     assert(ctext);
   485     assert(csize);
   486 
   487     if(!session || !ptext || !psize || !ctext || !csize || !keylist) 
   488         return PEP_UNKNOWN_ERROR;
   489 
   490     if(pthread_mutex_lock(&netpgp_mutex)){
   491         return PEP_UNKNOWN_ERROR;
   492     }
   493 
   494     *ctext = NULL;
   495     *csize = 0;
   496 
   497     // Get signing details from netpgp
   498     if ((userid = netpgp_getvar(&netpgp, "userid")) == NULL || 
   499         (keypair = pgp_getkeybyname(netpgp.io, netpgp.secring, userid)) == NULL ||
   500         (seckey = pgp_decrypt_seckey(keypair, NULL /*passfp*/)) == NULL) {
   501         return PEP_UNKNOWN_ERROR;
   502     }
   503 
   504     hashalg = netpgp_getvar(&netpgp, "hash");
   505     // netpgp (l)imitation - XXX why ? 
   506     if (seckey->pubkey.alg == PGP_PKA_DSA) {
   507         hashalg = "sha1";
   508     }
   509 
   510     // Sign data
   511     signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey,
   512                 time(NULL), /* birthtime */
   513                 0 /* duration */,
   514                 hashalg, 
   515                 0 /* armored */,
   516                 0 /* cleartext */);
   517 
   518     pgp_forget(seckey, (unsigned)sizeof(*seckey));
   519 
   520     if (!signedmem) {
   521         result = PEP_UNENCRYPTED;
   522         goto unlock_netpgp;
   523     }
   524 
   525     // Encrypt signed data
   526     if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
   527         result = PEP_OUT_OF_MEMORY;
   528         goto free_signedmem;
   529     }
   530     for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
   531         assert(_keylist->value);
   532         // get key from netpgp's pubring
   533         const pgp_key_t *key;
   534         key = pgp_getkeybyname(netpgp.io,
   535                                netpgp.pubring,
   536                                _keylist->value);
   537 
   538         if(key == NULL){
   539             result = PEP_KEY_NOT_FOUND;
   540             goto free_rcpts;
   541         }
   542 
   543         // add key to recipients/signers
   544         pgp_keyring_add(rcpts, key);
   545         if(rcpts->keys == NULL){
   546             result = PEP_OUT_OF_MEMORY;
   547             goto free_signedmem;
   548         }
   549     }
   550 
   551     cmem = pgp_encrypt_buf(netpgp.io, pgp_mem_data(signedmem),
   552             pgp_mem_len(signedmem), rcpts, 1 /* armored */,
   553             netpgp_getvar(&netpgp, "cipher"), 
   554             1 /* takes raw OpenPGP message */);
   555 
   556     if (cmem == NULL) {
   557         result = PEP_OUT_OF_MEMORY;
   558         goto free_signedmem;
   559     }else{
   560 
   561         char *_buffer = NULL;
   562         size_t length = pgp_mem_len(cmem);
   563 
   564         // Allocate transferable buffer
   565         _buffer = malloc(length + 1);
   566         assert(_buffer);
   567         if (_buffer == NULL) {
   568             result = PEP_OUT_OF_MEMORY;
   569             goto free_cmem;
   570         }
   571 
   572         memcpy(_buffer, pgp_mem_data(cmem), length);
   573 
   574         *ctext = _buffer;
   575         *csize = length;
   576         (*ctext)[*csize] = 0; // safeguard for naive users
   577         result = PEP_STATUS_OK;
   578     }
   579 
   580 free_cmem :
   581     pgp_memory_free(cmem);
   582 free_rcpts :
   583     pgp_keyring_free(rcpts);
   584 free_signedmem :
   585     pgp_memory_free(signedmem);
   586 unlock_netpgp:
   587     pthread_mutex_unlock(&netpgp_mutex);
   588 
   589     return result;
   590 }
   591 
   592 /* return the hexdump as a string */
   593 static unsigned
   594 fpr_to_str (char **str, const uint8_t *fpr, size_t length)
   595 {
   596     unsigned i;
   597     int	n;
   598 
   599     /* 5 char per byte (hexes + space) tuple -1 space at the end + null */
   600     *str = malloc((length / 2) * 5 - 1 + 1);
   601 
   602     if(*str == NULL)
   603         return 0;
   604 
   605     for (n = 0, i = 0 ; i < length - 2; i += 2) {
   606     	n += snprintf(&((*str)[n]), 6, "%02x%02x ", fpr[i], fpr[i+1]);
   607     }
   608     snprintf(&((*str)[n]), 5, "%02x%02x", fpr[i], fpr[i+1]);
   609 
   610     return 1;
   611 }
   612 
   613 static unsigned
   614 str_to_fpr (const char *str, uint8_t *fpr, size_t *length)
   615 {
   616     unsigned i,j;
   617 
   618     *length = 0;
   619 
   620     while(*str && *length < PGP_FINGERPRINT_SIZE){
   621         while (*str == ' ') str++;
   622         for (j = 0; j < 2; j++) {
   623             uint8_t *byte = &fpr[*length];
   624             *byte = 0;
   625             for (i = 0; i < 2; i++) {
   626                 if (i > 0)
   627                     *byte = *byte << 4;
   628                 if (*str >= 'a' && *str <= 'f')
   629                     *byte += 10 + *str - 'a';
   630                 else if (*str >= 'A' && *str <= 'F')
   631                     *byte += 10 + *str - 'A';
   632                 else if (*str >= '0' && *str <= '9')
   633                     *byte += *str - '0';
   634                 else 
   635                     return 0;
   636                 str++;
   637             }
   638             (*length)++;
   639         }
   640     }
   641     return 1;
   642 }
   643 
   644 static PEP_STATUS import_key_or_keypair(netpgp_t *netpgp, pgp_key_t *newkey){
   645     pgp_key_t	pubkey;
   646     unsigned public;
   647     PEP_STATUS result;
   648     
   649     /* XXX TODO : check key is valid */
   650     /* XXX TODO : replace/update key if already in ring */
   651 
   652     if ((public = (newkey->type == PGP_PTAG_CT_PUBLIC_KEY))){
   653         pubkey = *newkey;
   654     } else {
   655         // Duplicate key as public only
   656         bzero(&pubkey, sizeof(pubkey));
   657         if (!pgp_keydata_dup(&pubkey, newkey, 1 /* make_public */)){
   658             return PEP_OUT_OF_MEMORY;
   659         }
   660     }
   661 
   662     // Append key to netpgp's rings (key ownership transfered)
   663     if (!public && !pgp_keyring_add(netpgp->secring, newkey)){
   664         result = PEP_OUT_OF_MEMORY;
   665         goto free_pubkey;
   666     } else if (!pgp_keyring_add(netpgp->pubring, &pubkey)){
   667         result = PEP_OUT_OF_MEMORY;
   668         goto pop_secring;
   669     }
   670 
   671     // save rings 
   672     if (netpgp_save_pubring(netpgp) && 
   673         (!public || netpgp_save_secring(netpgp)))
   674     {
   675         /* free nothing, everything transfered */
   676         return PEP_STATUS_OK;
   677     } else {
   678         /* XXX in case only pubring save succeed
   679          * pubring file is left as-is, but backup restore
   680          * could be attempted if such corner case matters */
   681         result = PEP_UNKNOWN_ERROR;
   682     }
   683 
   684 pop_pubring:
   685     ((pgp_keyring_t *)netpgp->pubring)->keyc--;
   686 pop_secring:
   687     ((pgp_keyring_t *)netpgp->secring)->keyc--;
   688 free_pubkey:
   689     pgp_key_free(&pubkey);
   690 
   691     return result;
   692 }
   693 
   694 PEP_STATUS pgp_generate_keypair(
   695     PEP_SESSION session, pEp_identity *identity
   696     )
   697 {
   698     pgp_key_t	newkey;
   699 
   700     PEP_STATUS result;
   701     char newid[1024];
   702     const char *hashalg;
   703     const char *cipher;
   704 
   705     assert(session);
   706     assert(identity);
   707     assert(identity->address);
   708     assert(identity->fpr == NULL);
   709     assert(identity->username);
   710 
   711     if(!session || !identity || 
   712        !identity->address || identity->fpr || !identity->username)
   713         return PEP_UNKNOWN_ERROR;
   714 
   715     if(pthread_mutex_lock(&netpgp_mutex)){
   716         return PEP_UNKNOWN_ERROR;
   717     }
   718 
   719     if(snprintf(newid, sizeof(newid),
   720         "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
   721         result =  PEP_BUFFER_TOO_SMALL;
   722         goto unlock_netpgp;
   723     }
   724     
   725     hashalg = netpgp_getvar(&netpgp, "hash");
   726     cipher = netpgp_getvar(&netpgp, "cipher");
   727 
   728     bzero(&newkey, sizeof(newkey));
   729 
   730     // Generate the key
   731     if (!pgp_rsa_generate_keypair(&newkey, 4096, 65537UL, hashalg, cipher,
   732                                   (const uint8_t *) "", (const size_t) 0) ||
   733         !pgp_add_selfsigned_userid(&newkey, (uint8_t *)newid)) {
   734         result = PEP_CANNOT_CREATE_KEY;
   735         goto free_newkey;
   736     }
   737 
   738     // TODO "Expire-Date: 1y\n";
   739 
   740 
   741     result = import_key_or_keypair(&netpgp, &newkey);
   742 
   743     if (result == PEP_STATUS_OK) {
   744         char *fprstr = NULL;
   745         fpr_to_str(&fprstr,
   746                    newkey.sigfingerprint.fingerprint,
   747                    newkey.sigfingerprint.length);
   748         if (fprstr == NULL) {
   749             result = PEP_OUT_OF_MEMORY;
   750             goto free_newkey;
   751         } 
   752         identity->fpr = fprstr;
   753         /* free nothing, everything transfered */
   754         result = PEP_STATUS_OK;
   755         goto unlock_netpgp;
   756     }
   757 
   758 free_newkey:
   759     pgp_key_free(&newkey);
   760 unlock_netpgp:
   761     pthread_mutex_unlock(&netpgp_mutex);
   762 
   763     return result;
   764 }
   765 
   766 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr)
   767 {
   768     uint8_t fpr[PGP_FINGERPRINT_SIZE];
   769     size_t length;
   770 
   771     PEP_STATUS result;
   772 
   773     assert(session);
   774     assert(fpr);
   775 
   776     if (!session || !fpr)
   777         return PEP_UNKNOWN_ERROR;
   778 
   779     if(pthread_mutex_lock(&netpgp_mutex)){
   780         return PEP_UNKNOWN_ERROR;
   781     }
   782     
   783     if (str_to_fpr(fprstr, fpr, &length)) {
   784         unsigned insec = pgp_deletekeybyfpr(netpgp.io,
   785                                 (pgp_keyring_t *)netpgp.secring, 
   786                                 (const uint8_t *)fpr, length);
   787         unsigned inpub = pgp_deletekeybyfpr(netpgp.io,
   788                                 (pgp_keyring_t *)netpgp.pubring, 
   789                                 (const uint8_t *)fpr, length);
   790         if(!insec && !inpub){
   791             result = PEP_KEY_NOT_FOUND;
   792             goto unlock_netpgp;
   793         } else {
   794             result = PEP_STATUS_OK;
   795         }
   796     }else{
   797         result = PEP_OUT_OF_MEMORY;
   798         goto unlock_netpgp;
   799     }
   800 
   801     // save rings (key ownership transfered)
   802     if (netpgp_save_pubring(&netpgp) && 
   803         netpgp_save_secring(&netpgp))
   804     {
   805         result = PEP_STATUS_OK;
   806     }else{
   807         result = PEP_UNKNOWN_ERROR;
   808     }
   809 
   810 unlock_netpgp:
   811     pthread_mutex_unlock(&netpgp_mutex);
   812 
   813     return result;
   814 }
   815 
   816 #define ARMOR_KEY_HEAD    "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----\\s*$"
   817 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
   818 {
   819 
   820     pgp_memory_t *mem;
   821     pgp_keyring_t tmpring;
   822     unsigned i = 0;
   823 
   824     PEP_STATUS result = PEP_STATUS_OK;
   825 
   826     assert(session);
   827     assert(key_data);
   828 
   829     if(!session || !key_data) 
   830         return PEP_UNKNOWN_ERROR;
   831 
   832     if(pthread_mutex_lock(&netpgp_mutex)){
   833         return PEP_UNKNOWN_ERROR;
   834     }
   835 
   836     mem = pgp_memory_new();
   837     if (mem == NULL) {
   838         result = PEP_OUT_OF_MEMORY;
   839         goto unlock_netpgp;
   840     }
   841     pgp_memory_add(mem, (const uint8_t*)key_data, size);
   842 
   843     bzero(&tmpring, sizeof(tmpring));
   844 
   845     if (pgp_keyring_read_from_mem(netpgp.io, &tmpring, 
   846                                   _armoured(key_data, size, ARMOR_KEY_HEAD),
   847                                   mem) == 0){
   848         result = PEP_ILLEGAL_VALUE;
   849     }else if (tmpring.keyc == 0){
   850         result = PEP_UNKNOWN_ERROR;
   851     }else while(result == PEP_STATUS_OK && i < tmpring.keyc){
   852         result = import_key_or_keypair(&netpgp, &tmpring.keys[i++]);
   853     }
   854     
   855     pgp_memory_free(mem);
   856 
   857     if (result == PEP_STATUS_OK){
   858         pgp_keyring_free(&tmpring);
   859     }else{
   860         pgp_keyring_purge(&tmpring);
   861     }
   862 
   863 unlock_netpgp:
   864     pthread_mutex_unlock(&netpgp_mutex);
   865 
   866     return result;
   867 }
   868 
   869 PEP_STATUS pgp_export_keydata(
   870     PEP_SESSION session, const char *fprstr, char **key_data, size_t *size
   871     )
   872 {
   873     pgp_key_t *key;
   874 	pgp_output_t *output;
   875     pgp_memory_t *mem;
   876     uint8_t fpr[PGP_FINGERPRINT_SIZE];
   877     size_t fprlen;
   878 
   879     PEP_STATUS result;
   880     char *buffer;
   881     size_t buflen;
   882 
   883     assert(session);
   884     assert(fprstr);
   885     assert(key_data);
   886     assert(size);
   887 
   888     if (!session || !fprstr || !key_data || !size)
   889         return PEP_UNKNOWN_ERROR;
   890 
   891     if(pthread_mutex_lock(&netpgp_mutex)){
   892         return PEP_UNKNOWN_ERROR;
   893     }
   894 
   895     if (str_to_fpr(fprstr, fpr, &fprlen)) {
   896         if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring, 
   897                                                 fpr, fprlen,
   898                                                 NULL)) == NULL) {
   899             result = PEP_KEY_NOT_FOUND;
   900             goto unlock_netpgp;
   901         }
   902     }else{
   903         result = PEP_OUT_OF_MEMORY;
   904         goto unlock_netpgp;
   905     }
   906     
   907 	pgp_setup_memory_write(&output, &mem, 128);
   908 
   909     if (mem == NULL || output == NULL) {
   910         result = PEP_OUT_OF_MEMORY;
   911         goto unlock_netpgp;
   912     }
   913 
   914     if (!pgp_write_xfer_pubkey(output, key, 1)) {
   915         result = PEP_UNKNOWN_ERROR;
   916         goto free_mem;
   917     }
   918 
   919     buffer = NULL;
   920     buflen = pgp_mem_len(mem);
   921 
   922     // Allocate transferable buffer
   923     buffer = malloc(buflen + 1);
   924     assert(buffer);
   925     if (buffer == NULL) {
   926         result = PEP_OUT_OF_MEMORY;
   927         goto free_mem;
   928     }
   929 
   930     memcpy(buffer, pgp_mem_data(mem), buflen);
   931 
   932     *key_data = buffer;
   933     *size = buflen;
   934     (*key_data)[*size] = 0; // safeguard for naive users
   935     result = PEP_STATUS_OK;
   936 
   937 free_mem :
   938 	pgp_teardown_memory_write(output, mem);
   939 unlock_netpgp:
   940     pthread_mutex_unlock(&netpgp_mutex);
   941 
   942     return result;
   943 }
   944 
   945 struct HKP_answer {
   946   char *memory;
   947   size_t size;
   948 };
   949  
   950 static size_t
   951 HKPAnswerWriter(void *contents, size_t size, size_t nmemb, void *userp)
   952 {
   953   size_t realsize = size * nmemb;
   954   struct HKP_answer *mem = (struct HKP_answer *)userp;
   955  
   956   mem->memory = realloc(mem->memory, mem->size + realsize + 1);
   957   if(mem->memory == NULL) {
   958     mem->size = 0;
   959     return 0;
   960   }
   961  
   962   memcpy(&(mem->memory[mem->size]), contents, realsize);
   963   mem->size += realsize;
   964   mem->memory[mem->size] = 0;
   965  
   966   return realsize;
   967 }
   968 
   969 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
   970 {
   971     static const char *ks_cmd = "http://keys.gnupg.net:11371/pks/lookup?"
   972                                 "op=get&options=mr&exact=on&"
   973                                 "search=";
   974     char *encoded_pattern;
   975     char *request = NULL;
   976     struct HKP_answer answer;
   977     CURLcode curlres;
   978        
   979     PEP_STATUS result;
   980 
   981     CURL *curl;
   982 
   983     assert(session);
   984     assert(pattern);
   985 
   986     if (!session || !pattern )
   987         return PEP_UNKNOWN_ERROR;
   988 
   989     if(pthread_mutex_lock(&session->ctx.curl_mutex)){
   990         return PEP_UNKNOWN_ERROR;
   991     }
   992 
   993     curl = session->ctx.curl;
   994 
   995     encoded_pattern = curl_easy_escape(curl, (char*)pattern, 0);
   996     if(!encoded_pattern){
   997         result = PEP_OUT_OF_MEMORY;
   998         goto unlock_curl;
   999     }
  1000 
  1001     if((request = malloc(strlen(ks_cmd) + strlen(encoded_pattern) + 1))==NULL){
  1002         result = PEP_OUT_OF_MEMORY;
  1003         goto free_encoded_pattern;
  1004     }
  1005 
  1006     //(*stpcpy(stpcpy(request, ks_cmd), encoded_pattern)) = '\0';
  1007     stpcpy(stpcpy(request, ks_cmd), encoded_pattern);
  1008 
  1009     curl_easy_setopt(curl, CURLOPT_URL,request);
  1010 
  1011     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HKPAnswerWriter);
  1012 
  1013     answer.memory = NULL;
  1014     answer.size = 0;
  1015     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&answer);
  1016 
  1017     curlres = curl_easy_perform(curl);
  1018     if(curlres != CURLE_OK) {
  1019         result = PEP_GET_KEY_FAILED;
  1020         goto free_request;
  1021     }
  1022 
  1023     if(!answer.memory || !answer.size) {
  1024         result = PEP_OUT_OF_MEMORY;
  1025         goto free_request;
  1026     }
  1027 
  1028     printf("request :\n %s\n\nanswer :\n%s\n", request, answer);
  1029     result = pgp_import_keydata(session, 
  1030                                 answer.memory, 
  1031                                 answer.size);
  1032 
  1033 free_answer:
  1034     free(answer.memory);
  1035 free_request:
  1036     free(request);
  1037 free_encoded_pattern:
  1038     curl_free(encoded_pattern);
  1039 unlock_curl:
  1040     pthread_mutex_unlock(&session->ctx.curl_mutex);
  1041 
  1042     return result;
  1043 }
  1044 
  1045 PEP_STATUS add_key_fpr_to_stringlist(stringlist_t **keylist, pgp_key_t *key)
  1046 {
  1047     char *newfprstr = NULL;
  1048 
  1049     fpr_to_str(&newfprstr,
  1050                key->sigfingerprint.fingerprint,
  1051                key->sigfingerprint.length);
  1052 
  1053     if (newfprstr == NULL) {
  1054         return PEP_OUT_OF_MEMORY;
  1055     } else { 
  1056 
  1057         *keylist = stringlist_add(*keylist, newfprstr);
  1058         if (*keylist == NULL) {
  1059             free(newfprstr);
  1060             return PEP_OUT_OF_MEMORY;
  1061         }
  1062     }
  1063     return PEP_STATUS_OK;
  1064 }
  1065 
  1066 PEP_STATUS pgp_find_keys(
  1067     PEP_SESSION session, const char *pattern, stringlist_t **keylist
  1068     )
  1069 {
  1070     stringlist_t *_keylist, *_k;
  1071     uint8_t fpr[PGP_FINGERPRINT_SIZE];
  1072     size_t length;
  1073     pgp_key_t *key;
  1074     char *newfprstr = NULL;
  1075 
  1076     PEP_STATUS result;
  1077 
  1078     assert(session);
  1079     assert(pattern);
  1080     assert(keylist);
  1081 
  1082     if (!session || !pattern || !keylist )
  1083         return PEP_UNKNOWN_ERROR;
  1084 
  1085     if(pthread_mutex_lock(&netpgp_mutex)){
  1086         return PEP_UNKNOWN_ERROR;
  1087     }
  1088 
  1089     *keylist = NULL;
  1090     _keylist = new_stringlist(NULL);
  1091     if (_k == NULL) {
  1092         result = PEP_OUT_OF_MEMORY;
  1093         goto unlock_netpgp;
  1094     }
  1095     _k = _keylist;
  1096 
  1097     // Try find a fingerprint in pattern
  1098     if (str_to_fpr(pattern, fpr, &length)) {
  1099 
  1100         // Only one fingerprint can match
  1101         if ((key = (pgp_key_t *)pgp_getkeybyfpr(
  1102                         netpgp.io,
  1103                         (pgp_keyring_t *)netpgp.pubring, 
  1104                         (const uint8_t *)fpr, length,
  1105                         NULL)) == NULL) {
  1106 
  1107             result = PEP_KEY_NOT_FOUND;
  1108             goto unlock_netpgp;
  1109         }
  1110 
  1111         result = add_key_fpr_to_stringlist(&_k, key);
  1112 
  1113     } else {
  1114         // Search by name for pattern. Can match many.
  1115         unsigned from = 0;
  1116         result = PEP_KEY_NOT_FOUND;
  1117         while((key = (pgp_key_t *)pgp_getnextkeybyname(
  1118                         netpgp.io,
  1119                         (pgp_keyring_t *)netpgp.pubring, 
  1120 			            (const char *)pattern,
  1121                         &from)) != NULL) {
  1122 
  1123             result = add_key_fpr_to_stringlist(&_k, key);
  1124             if (result != PEP_STATUS_OK)
  1125                 goto free_keylist;
  1126 
  1127             from++;
  1128         }
  1129     }
  1130 
  1131     if (result == PEP_STATUS_OK) {
  1132         *keylist = _keylist;
  1133         // Transfer ownership, no free
  1134         goto unlock_netpgp;
  1135     }
  1136 
  1137 free_keylist:
  1138     free_stringlist(_keylist);
  1139 
  1140 unlock_netpgp:
  1141     pthread_mutex_unlock(&netpgp_mutex);
  1142 
  1143     return result;
  1144 }
  1145 
  1146 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
  1147 {
  1148     assert(session);
  1149     assert(pattern);
  1150 
  1151     /* TODO send key */
  1152 
  1153         return PEP_CANNOT_SEND_KEY;
  1154         return PEP_STATUS_OK;
  1155 }
  1156 
  1157 
  1158 PEP_STATUS pgp_get_key_rating(
  1159     PEP_SESSION session,
  1160     const char *fpr,
  1161     PEP_comm_type *comm_type
  1162     )
  1163 {
  1164     PEP_STATUS status = PEP_STATUS_OK;
  1165 
  1166     assert(session);
  1167     assert(fpr);
  1168     assert(comm_type);
  1169 
  1170     *comm_type = PEP_ct_unknown;
  1171 
  1172     /* TODO get key from fpr */
  1173     return PEP_UNKNOWN_ERROR;
  1174     return PEP_GET_KEY_FAILED;
  1175 
  1176     switch (/*TODO key->protocol*/ 4) {
  1177     case /* TODO  OpenPGP */0:
  1178     case /* TODO DEFAULT */1:
  1179         *comm_type = PEP_ct_OpenPGP_unconfirmed;
  1180         break;
  1181     case /* TODO CMS */2:
  1182         *comm_type = PEP_ct_CMS_unconfirmed;
  1183         break;
  1184     default:
  1185         *comm_type = PEP_ct_unknown;
  1186         return PEP_STATUS_OK;
  1187     }
  1188 
  1189         for (; 1 == 0; /* Each subkeys */ ) {
  1190             if (/* TODO length */0 < 1024)
  1191                 *comm_type = PEP_ct_key_too_short;
  1192             else if (
  1193                 (
  1194                 (   /* TODO pubkey_algo == RSA  */ 0)
  1195                 || (/* TODO pubkey_algo == RSA_E*/ 0)
  1196                 || (/* TODO pubkey_algo == RSA_S*/ 0)
  1197                 )
  1198                 && /* sk->length */0 == 1024
  1199                 )
  1200                 *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
  1201 
  1202             if (/* TODO invalid */ 1) {
  1203                 *comm_type = PEP_ct_key_b0rken;
  1204                 break;
  1205             }
  1206             if (/* TODO expired */ 1) {
  1207                 *comm_type = PEP_ct_key_expired;
  1208                 break;
  1209             }
  1210             if (/* TODO revoked*/ 1) {
  1211                 *comm_type = PEP_ct_key_revoked;
  1212                 break;
  1213             }
  1214         }
  1215         *comm_type = PEP_ct_unknown;
  1216         return PEP_OUT_OF_MEMORY;
  1217         return PEP_UNKNOWN_ERROR;
  1218 
  1219 
  1220     return status;
  1221 }
  1222 
  1223 PEP_STATUS pgp_renew_key(
  1224         PEP_SESSION session,
  1225         const char *fpr,
  1226         const timestamp *ts
  1227     )
  1228 {
  1229     PEP_STATUS status = PEP_STATUS_OK;
  1230     char date_text[12];
  1231 
  1232     assert(session);
  1233     assert(fpr);
  1234 
  1235     snprintf(date_text, 12, "%.4d-%.2d-%.2d\n", ts->tm_year + 1900,
  1236             ts->tm_mon + 1, ts->tm_mday);
  1237 
  1238 
  1239         return PEP_UNKNOWN_ERROR;
  1240     return PEP_STATUS_OK;
  1241 }
  1242 
  1243 PEP_STATUS pgp_revoke_key(
  1244         PEP_SESSION session,
  1245         const char *fpr,
  1246         const char *reason
  1247     )
  1248 {
  1249     PEP_STATUS status = PEP_STATUS_OK;
  1250     
  1251     assert(session);
  1252     assert(fpr);
  1253 
  1254         return PEP_UNKNOWN_ERROR;
  1255 
  1256     return PEP_STATUS_OK;
  1257 }
  1258 
  1259 PEP_STATUS pgp_key_expired(
  1260         PEP_SESSION session,
  1261         const char *fpr,
  1262         bool *expired
  1263     )
  1264 {
  1265     PEP_STATUS status = PEP_STATUS_OK;
  1266 
  1267     assert(session);
  1268     assert(fpr);
  1269     assert(expired);
  1270 
  1271     *expired = false;
  1272 
  1273     if (status != PEP_STATUS_OK)
  1274         return status;
  1275 
  1276     return PEP_STATUS_OK;
  1277 }
  1278