src/pgp_netpgp.c
author Edouard Tisserant
Mon, 13 Apr 2015 15:23:33 +0200
changeset 187 0199040b3395
parent 186 cfd6fe0e9dc5
child 188 0a882568ccd3
permissions -rw-r--r--
netpgp : ...
     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 
    15 #define PEP_NETPGP_DEBUG
    16 
    17 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
    18 {
    19     netpgp_t *netpgp;
    20     PEP_STATUS status = PEP_STATUS_OK;
    21     const char *home = NULL;
    22 
    23     assert(session);
    24     if(!session) return PEP_UNKNOWN_ERROR;
    25 
    26     netpgp = &session->ctx;
    27    
    28     if (in_first) {
    29         if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
    30             setlocale(LC_ALL, "");
    31     }
    32 
    33     memset(netpgp, 0x0, sizeof(session->ctx));
    34 
    35     // netpgp_setvar(netpgp, "max mem alloc", "4194304");
    36     netpgp_setvar(netpgp, "need seckey", "1");
    37     netpgp_setvar(netpgp, "need userid", "1");
    38 
    39     // NetPGP shares home with GPG
    40     home = gpg_home();
    41     if(home){
    42         netpgp_set_homedir(netpgp,(char*)home, NULL, 0);
    43     }else{
    44         status = PEP_INIT_NO_GPG_HOME;
    45         goto pep_error;
    46     }
    47 
    48     // pair with gpg's cert-digest-algo
    49     netpgp_setvar(netpgp, "hash", "SHA256");
    50 
    51     // subset of gpg's personal-cipher-preferences
    52     // here only one cipher can be selected
    53     netpgp_setvar(netpgp, "cipher", "AES256");
    54 
    55     if (!netpgp_init(netpgp)) {
    56         status = PEP_INIT_NETPGP_INIT_FAILED;
    57         goto pep_error;
    58     }
    59 
    60     return PEP_STATUS_OK;
    61 
    62 pep_error:
    63     pgp_release(session, in_first);
    64     return status;
    65 }
    66 
    67 void pgp_release(PEP_SESSION session, bool out_last)
    68 {
    69     netpgp_t *netpgp;
    70 
    71     assert(session);
    72     if(!session) return;
    73 
    74     netpgp = &session->ctx;
    75 
    76     netpgp_end(netpgp);
    77     memset(netpgp, 0x0, sizeof(session->ctx));
    78 
    79     // out_last unused here
    80 }
    81 
    82 // Iterate through netpgp' reported valid signatures 
    83 // fill a list of valid figerprints
    84 // returns PEP_STATUS_OK if all sig reported valid
    85 // error status otherwise.
    86 static PEP_STATUS _validation_results(netpgp_t *netpgp, pgp_validation_t *vresult,
    87                                              stringlist_t **_keylist)
    88 {
    89 	time_t	now;
    90 	time_t	t;
    91 	char	buf[128];
    92 
    93 	now = time(NULL);
    94 	if (now < vresult->birthtime) {
    95 		// signature is not valid yet
    96 #ifdef PEP_NETPGP_DEBUG
    97 		(void) printf(
    98 			"signature not valid until %.24s\n",
    99 			ctime(&vresult->birthtime));
   100 #endif //PEP_NETPGP_DEBUG
   101 		return PEP_UNENCRYPTED;
   102 	}
   103 	if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
   104 		// signature has expired
   105 		t = vresult->duration + vresult->birthtime;
   106 #ifdef PEP_NETPGP_DEBUG
   107 		(void) printf(
   108 			"signature not valid after %.24s\n",
   109 			ctime(&t));
   110 #endif //PEP_NETPGP_DEBUG
   111 		return PEP_UNENCRYPTED;
   112 	}
   113     if (vresult->validc && vresult->valid_sigs &&
   114         !vresult->invalidc && !vresult->unknownc ) {
   115         unsigned    n;
   116         stringlist_t *k;
   117         // caller responsible to free
   118         *_keylist = new_stringlist(NULL);
   119         assert(*_keylist);
   120         if (*_keylist == NULL) {
   121             return PEP_OUT_OF_MEMORY;
   122         }
   123         k = *_keylist;
   124         for (n = 0; n < vresult->validc; ++n) {
   125             int i;
   126             char id[MAX_ID_LENGTH + 1];
   127             static const char *hexes = "0123456789abcdef";
   128             const uint8_t *userid = vresult->valid_sigs[n].signer_id;
   129 
   130 #ifdef PEP_NETPGP_DEBUG
   131             const pgp_key_t *key;
   132             pgp_pubkey_t *sigkey;
   133 	        unsigned from = 0;
   134             key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
   135                 (const uint8_t *) vresult->valid_sigs[n].signer_id,
   136                 &from, &sigkey);
   137             pgp_print_keydata(netpgp->io, netpgp->pubring, key, "valid signature ", &key->key.pubkey, 0);
   138 #endif //PEP_NETPGP_DEBUG
   139 
   140             for (i = 0; i < 8 ; i++) {
   141                 id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
   142                 id[(i * 2) + 1] = hexes[userid[i] & 0xf];
   143             }
   144             id[8 * 2] = 0x0;
   145 
   146             k = stringlist_add(k, id);
   147             if(!k){
   148                 free_stringlist(*_keylist);
   149                 return PEP_OUT_OF_MEMORY;
   150             }
   151         }
   152         return PEP_STATUS_OK;
   153     }
   154     if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
   155         // No signatures found - is this memory signed?
   156         return PEP_VERIFY_NO_KEY; 
   157     } 
   158     
   159     if (vresult->invalidc) {
   160         // some invalid signatures
   161 
   162 #ifdef PEP_NETPGP_DEBUG
   163         unsigned    n;
   164         for (n = 0; n < vresult->invalidc; ++n) {
   165             const pgp_key_t *key;
   166             pgp_pubkey_t *sigkey;
   167             unsigned from = 0;
   168             key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
   169                 (const uint8_t *) vresult->invalid_sigs[n].signer_id,
   170                 &from, &sigkey);
   171             pgp_print_keydata(netpgp->io, netpgp->pubring, key, "invalid signature ", &key->key.pubkey, 0);
   172 	        if (sigkey->duration != 0 && now > sigkey->birthtime + sigkey->duration) {
   173                 printf("EXPIRED !\n");
   174             }
   175         }
   176 #endif //PEP_NETPGP_DEBUG
   177 
   178         return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   179     }
   180     
   181     // only unknown sigs
   182     return PEP_DECRYPT_WRONG_FORMAT;
   183 }
   184 
   185 PEP_STATUS pgp_decrypt_and_verify(
   186     PEP_SESSION session, const char *ctext, size_t csize,
   187     char **ptext, size_t *psize, stringlist_t **keylist
   188     )
   189 {
   190     netpgp_t *netpgp;
   191     pgp_memory_t *mem;
   192     pgp_memory_t *cat;
   193     pgp_validation_t *vresult;
   194     char *_ptext = NULL;
   195     size_t _psize = 0;
   196     int ret;
   197 
   198     PEP_STATUS result;
   199     stringlist_t *_keylist = NULL;
   200     int i_key = 0;
   201 
   202     assert(session);
   203     assert(ctext);
   204     assert(csize);
   205     assert(ptext);
   206     assert(psize);
   207     assert(keylist);
   208 
   209     if(!session || !ctext || !csize || !ptext || !psize || !keylist) 
   210         return PEP_UNKNOWN_ERROR;
   211 
   212     netpgp = &session->ctx;
   213 
   214     *ptext = NULL;
   215     *psize = 0;
   216     *keylist = NULL;
   217 
   218     vresult = malloc(sizeof(pgp_validation_t));
   219     memset(vresult, 0x0, sizeof(pgp_validation_t));
   220 
   221     mem = pgp_decrypt_and_validate_buf(netpgp->io, vresult, ctext, csize,
   222                 netpgp->secring, netpgp->pubring,
   223                 1 /* armoured */,
   224                 0 /* sshkeys */,
   225                 NULL, -1, NULL  /* pass fp,attempts,cb */);
   226     if (mem == NULL) {
   227         return PEP_OUT_OF_MEMORY;
   228     }
   229 
   230     _psize = pgp_mem_len(mem);
   231     if (_psize){
   232         if ((_ptext = calloc(1, _psize)) == NULL) {
   233             result = PEP_OUT_OF_MEMORY;
   234             goto free_pgp;
   235         }
   236         memcpy(_ptext, pgp_mem_data(mem), _psize);
   237         result = PEP_DECRYPTED;
   238     }else{
   239         result = PEP_DECRYPT_NO_KEY;
   240         goto free_pgp;
   241     }
   242 
   243     if (result == PEP_DECRYPTED) {
   244         result = _validation_results(netpgp, vresult, &_keylist);
   245         if (result != PEP_STATUS_OK) {
   246             goto free_ptext;
   247         }
   248         result = PEP_DECRYPTED_AND_VERIFIED;
   249     }
   250 
   251     if (result == PEP_DECRYPTED_AND_VERIFIED
   252         || result == PEP_DECRYPTED) {
   253         *ptext = _ptext;
   254         *psize = _psize;
   255         (*ptext)[*psize] = 0; // safeguard for naive users
   256         if (result == PEP_DECRYPTED_AND_VERIFIED) {
   257             *keylist = _keylist;
   258         }
   259 
   260         /* _ptext and _keylist ownership transfer, don't free */
   261         goto free_pgp;
   262     }
   263 
   264 free_keylist:
   265     free_stringlist(_keylist);
   266 
   267 free_ptext:
   268     free(_ptext);
   269 
   270 free_pgp:
   271     pgp_memory_free(mem);
   272     pgp_validate_result_free(vresult);
   273 
   274     return result;
   275 }
   276 
   277 PEP_STATUS pgp_verify_text(
   278     PEP_SESSION session, const char *text, size_t size,
   279     const char *signature, size_t sig_size, stringlist_t **keylist
   280     )
   281 {
   282     netpgp_t *netpgp;
   283     pgp_memory_t *signedmem;
   284     pgp_memory_t *sig;
   285     pgp_validation_t *vresult;
   286     pgp_io_t *io;
   287 
   288     PEP_STATUS result;
   289     stringlist_t *_keylist;
   290 
   291     assert(session);
   292     assert(text);
   293     assert(size);
   294     assert(signature);
   295     assert(sig_size);
   296     assert(keylist);
   297 
   298     if(!session || !text || !size || !signature || !sig_size || !keylist) 
   299         return PEP_UNKNOWN_ERROR;
   300 
   301     netpgp = &session->ctx;
   302 
   303     *keylist = NULL;
   304 
   305     vresult = malloc(sizeof(pgp_validation_t));
   306     memset(vresult, 0x0, sizeof(pgp_validation_t));
   307 
   308     signedmem = pgp_memory_new();
   309     if (signedmem == NULL) {
   310         return PEP_OUT_OF_MEMORY;
   311     }
   312     pgp_memory_add(signedmem, (const uint8_t*)text, size);
   313 
   314     sig = pgp_memory_new();
   315     if (sig == NULL) {
   316         pgp_memory_free(signedmem);
   317         return PEP_OUT_OF_MEMORY;
   318     }
   319     pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
   320 
   321     pgp_validate_mem_detached(netpgp->io, vresult, sig,
   322                 NULL,/* output */
   323                 1,/* armored */
   324                 netpgp->pubring,
   325                 signedmem);
   326 
   327     result = _validation_results(netpgp, vresult, &_keylist);
   328     if (result != PEP_STATUS_OK) {
   329         goto free_pgp;
   330     }else{
   331         result = PEP_VERIFIED;
   332     }
   333 
   334     if (result == PEP_VERIFIED) {
   335         /* TODO : check trust level */
   336         result = PEP_VERIFIED_AND_TRUSTED;
   337     }
   338 
   339     if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
   340         *keylist = _keylist;
   341 
   342         /* _keylist ownership transfer, don't free */
   343         goto free_pgp;
   344     }
   345 
   346 free_keylist:
   347     free_stringlist(_keylist);
   348 
   349 free_pgp:
   350     // free done by pgp_validate_mem_detached
   351     // pgp_memory_free(sig);
   352     // pgp_memory_free(signedmem);
   353     pgp_validate_result_free(vresult);
   354 
   355     return result;
   356 }
   357 
   358 PEP_STATUS pgp_encrypt_and_sign(
   359     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   360     size_t psize, char **ctext, size_t *csize
   361     )
   362 {
   363     PEP_STATUS result;
   364     const stringlist_t *_keylist;
   365     int i, j;
   366 
   367     assert(session);
   368     assert(keylist);
   369     assert(ptext);
   370     assert(psize);
   371     assert(ctext);
   372     assert(csize);
   373 
   374     *ctext = NULL;
   375     *csize = 0;
   376 
   377     for (_keylist = keylist, i = 0; _keylist != NULL; _keylist = _keylist->next, i++) {
   378         assert(_keylist->value);
   379         /* TODO */
   380         /* get key from  _keylist->value */
   381         /* add key to recipients/signers */
   382     }
   383 
   384     /* Do encrypt and sign */ 
   385     char *_buffer = NULL;
   386     size_t length = /* TODO length*/ 0;
   387     assert(length != -1);
   388 
   389     /* Allocate transferable buffer */
   390     _buffer = malloc(length + 1);
   391     assert(_buffer);
   392     if (_buffer == NULL) {
   393         /* TODO clean */
   394         return PEP_OUT_OF_MEMORY;
   395     }
   396 
   397     *ctext = _buffer;
   398     *csize = length;
   399     (*ctext)[*csize] = 0; // safeguard for naive users
   400     result = PEP_STATUS_OK;
   401 
   402     
   403     result = PEP_UNKNOWN_ERROR;
   404     return result;
   405 }
   406 
   407 PEP_STATUS pgp_generate_keypair(
   408     PEP_SESSION session, pEp_identity *identity
   409     )
   410 {
   411     char *parms;
   412     const char *template =
   413         "Key-Type: RSA\n"
   414         "Key-Length: 4096\n"
   415         "Name-Real: %s\n"
   416         "Name-Email: %s\n"
   417         /* "Passphrase: %s\n" */
   418         "Expire-Date: 1y\n";
   419     int result;
   420 
   421     assert(session);
   422     assert(identity);
   423     assert(identity->address);
   424     assert(identity->fpr == NULL);
   425     assert(identity->username);
   426 
   427     parms = calloc(1, PARMS_MAX);
   428     assert(parms);
   429     if (parms == NULL)
   430         return PEP_OUT_OF_MEMORY;
   431 
   432     result = snprintf(parms, PARMS_MAX, template, identity->username,
   433         identity->address);
   434     assert(result < PARMS_MAX);
   435     if (result >= PARMS_MAX) {
   436         free(parms);
   437         return PEP_BUFFER_TOO_SMALL;
   438     }
   439 
   440     /* TODO generate key */
   441 
   442     free(parms);
   443 
   444         return PEP_UNKNOWN_ERROR;
   445         return PEP_ILLEGAL_VALUE;
   446         return PEP_CANNOT_CREATE_KEY;
   447 
   448     identity->fpr = strdup("TODO generated key fpr");
   449 
   450     return PEP_STATUS_OK;
   451 }
   452 
   453 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
   454 {
   455     assert(session);
   456     assert(fpr);
   457 
   458     /* TODO get key with given fpr */
   459         return PEP_KEY_NOT_FOUND;
   460         return PEP_ILLEGAL_VALUE;
   461         return PEP_KEY_HAS_AMBIG_NAME;
   462         return PEP_OUT_OF_MEMORY;
   463         return PEP_UNKNOWN_ERROR;
   464 
   465     /* TODO delete that key */
   466         return PEP_UNKNOWN_ERROR;
   467         return PEP_KEY_NOT_FOUND;
   468         return PEP_KEY_HAS_AMBIG_NAME;
   469         return PEP_UNKNOWN_ERROR;
   470 
   471     return PEP_STATUS_OK;
   472 }
   473 
   474 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
   475 {
   476     assert(session);
   477     assert(key_data);
   478 
   479     /* TODO import */
   480         return PEP_UNKNOWN_ERROR;
   481         return PEP_ILLEGAL_VALUE;
   482         return PEP_UNKNOWN_ERROR;
   483     return PEP_STATUS_OK;
   484 }
   485 
   486 PEP_STATUS pgp_export_keydata(
   487     PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   488     )
   489 {
   490     size_t _size;
   491     char *buffer;
   492     int reading;
   493 
   494     assert(session);
   495     assert(fpr);
   496     assert(key_data);
   497     assert(size);
   498 
   499 
   500     /* TODO export */
   501         return PEP_KEY_NOT_FOUND;
   502         return PEP_UNKNOWN_ERROR;
   503         return PEP_UNKNOWN_ERROR;
   504 
   505     _size = /* TODO */ 0;
   506     assert(_size != -1);
   507 
   508     buffer = malloc(_size + 1);
   509     assert(buffer);
   510     if (buffer == NULL) {
   511         /* TODO clean */
   512         return PEP_OUT_OF_MEMORY;
   513     }
   514 
   515     // safeguard for the naive user
   516     buffer[_size] = 0;
   517 
   518     *key_data = buffer;
   519     *size = _size;
   520 
   521     return PEP_STATUS_OK;
   522 }
   523 
   524 // "keyserver"
   525 // "hkp://keys.gnupg.net"
   526 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
   527 {
   528     assert(session);
   529     assert(pattern);
   530 
   531     /* TODO ask for key */
   532         return PEP_UNKNOWN_ERROR;
   533         return PEP_GET_KEY_FAILED;
   534 
   535     do {
   536 
   537         /* For each key */
   538         /* import key */
   539     } while (0);
   540 
   541     return PEP_STATUS_OK;
   542 }
   543 
   544 PEP_STATUS pgp_find_keys(
   545     PEP_SESSION session, const char *pattern, stringlist_t **keylist
   546     )
   547 {
   548     stringlist_t *_keylist;
   549     char *fpr;
   550 
   551     assert(session);
   552     assert(pattern);
   553     assert(keylist);
   554 
   555     *keylist = NULL;
   556 
   557     /* Ask for key */
   558         return PEP_UNKNOWN_ERROR;
   559         return PEP_GET_KEY_FAILED;
   560 
   561     _keylist = new_stringlist(NULL);
   562     stringlist_t *_k = _keylist;
   563 
   564     do {
   565             fpr = "TODO key->subkeys->fpr";
   566             assert(fpr);
   567             _k = stringlist_add(_k, fpr);
   568             assert(_k);
   569             if (_k == NULL){
   570                 free_stringlist(_keylist);
   571                 return PEP_OUT_OF_MEMORY;
   572             }
   573     } while (0);
   574 
   575     *keylist = _keylist;
   576     return PEP_STATUS_OK;
   577 }
   578 
   579 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
   580 {
   581     assert(session);
   582     assert(pattern);
   583 
   584     /* TODO send key */
   585 
   586         return PEP_CANNOT_SEND_KEY;
   587         return PEP_STATUS_OK;
   588 }
   589 
   590 
   591 PEP_STATUS pgp_get_key_rating(
   592     PEP_SESSION session,
   593     const char *fpr,
   594     PEP_comm_type *comm_type
   595     )
   596 {
   597     PEP_STATUS status = PEP_STATUS_OK;
   598 
   599     assert(session);
   600     assert(fpr);
   601     assert(comm_type);
   602 
   603     *comm_type = PEP_ct_unknown;
   604 
   605     /* TODO get key from fpr */
   606     return PEP_UNKNOWN_ERROR;
   607     return PEP_GET_KEY_FAILED;
   608 
   609     switch (/*TODO key->protocol*/ 4) {
   610     case /* TODO  OpenPGP */0:
   611     case /* TODO DEFAULT */1:
   612         *comm_type = PEP_ct_OpenPGP_unconfirmed;
   613         break;
   614     case /* TODO CMS */2:
   615         *comm_type = PEP_ct_CMS_unconfirmed;
   616         break;
   617     default:
   618         *comm_type = PEP_ct_unknown;
   619         return PEP_STATUS_OK;
   620     }
   621 
   622         for (; 1 == 0; /* Each subkeys */ ) {
   623             if (/* TODO length */0 < 1024)
   624                 *comm_type = PEP_ct_key_too_short;
   625             else if (
   626                 (
   627                 (   /* TODO pubkey_algo == RSA  */ 0)
   628                 || (/* TODO pubkey_algo == RSA_E*/ 0)
   629                 || (/* TODO pubkey_algo == RSA_S*/ 0)
   630                 )
   631                 && /* sk->length */0 == 1024
   632                 )
   633                 *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
   634 
   635             if (/* TODO invalid */ 1) {
   636                 *comm_type = PEP_ct_key_b0rken;
   637                 break;
   638             }
   639             if (/* TODO expired */ 1) {
   640                 *comm_type = PEP_ct_key_expired;
   641                 break;
   642             }
   643             if (/* TODO revoked*/ 1) {
   644                 *comm_type = PEP_ct_key_revoked;
   645                 break;
   646             }
   647         }
   648         *comm_type = PEP_ct_unknown;
   649         return PEP_OUT_OF_MEMORY;
   650         return PEP_UNKNOWN_ERROR;
   651 
   652 
   653     return status;
   654 }