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