src/pgp_netpgp.c
author Edouard Tisserant
Sat, 04 Apr 2015 01:01:22 +0200
changeset 180 6008e35e7735
parent 179 112fadcf74b9
child 182 2b286e499c94
permissions -rw-r--r--
netpgp : decrypt and verify. Fixing needed in netpgp. netpgp cannot decrypt msg encrypted with gpg. netpgp can decrypt its own msg, but cannot verify own clearsign msg
     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     mem = pgp_decrypt_buf(netpgp->io, ctext, csize,
   116                 netpgp->secring, netpgp->pubring,
   117                 1 /* armoured */,
   118                 0 /* sshkeys */,
   119                 NULL, -1, NULL  /* pass fp,attempts,cb */);
   120     if (mem == NULL) {
   121         return PEP_OUT_OF_MEMORY;
   122     }
   123 
   124 	_psize = pgp_mem_len(mem);
   125 	if ((_ptext = calloc(1, _psize)) == NULL) {
   126         return PEP_OUT_OF_MEMORY;
   127 	}
   128 	memcpy(_ptext, pgp_mem_data(mem), _psize);
   129 
   130     result = PEP_DECRYPTED;
   131 
   132     cat = pgp_memory_new();
   133 
   134     /* if recognized */
   135     /* decrypt */
   136     /* if OK, verify */
   137     /*
   138     result = PEP_DECRYPTED_AND_VERIFIED;
   139     result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   140     result = PEP_DECRYPTED;
   141     result = PEP_DECRYPT_WRONG_FORMAT;
   142     result = PEP_DECRYPT_NO_KEY;
   143     return PEP_OUT_OF_MEMORY;
   144     */
   145 	(void) memset(&vresult, 0x0, sizeof(vresult));
   146 	ret = pgp_validate_mem(io, &vresult, mem,
   147 				&cat, 1, netpgp->pubring);
   148 
   149 	// pgp_memory_free(mem) done by pgp_validate_mem
   150 
   151 	if (ret) {
   152 		// resultp(io, "<stdin>", &vresult, netpgp->pubring);
   153 	    // signedmem is freed from pgp_validate_mem
   154         result = PEP_DECRYPTED_AND_VERIFIED;
   155 	}else{
   156         if (vresult.validc + vresult.invalidc + vresult.unknownc == 0) {
   157             // No signatures found - is this memory signed?
   158             result = PEP_DECRYPT_NO_KEY;
   159         } else if (vresult.invalidc == 0 && vresult.unknownc == 0) {
   160             // memory verification failure: invalid signature time
   161             result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   162         } else {
   163             // memory verification failure: 
   164             // invalid signatures result.invalidc
   165             // unknown signatures result.unknownc
   166             result = PEP_DECRYPT_WRONG_FORMAT;
   167         }
   168     }
   169     //result = PEP_UNKNOWN_ERROR;
   170     //            stringlist_t *k;
   171     //            _keylist = new_stringlist(NULL);
   172     //            assert(_keylist);
   173     //            if (_keylist == NULL) {
   174     //                /* TODO */
   175     //                return PEP_OUT_OF_MEMORY;
   176     //            }
   177     //            k = _keylist;
   178     //            do {
   179     //                    k = stringlist_add(k, "SIGNATURE FPR"/*TODO*/);
   180     //            } while (0 /* TODO sign next*/);
   181 
   182     pgp_memory_free(cat);
   183 
   184     if (result == PEP_DECRYPTED_AND_VERIFIED
   185         || result == PEP_DECRYPTED) {
   186         *ptext = _ptext;
   187         *psize = _psize;
   188         (*ptext)[*psize] = 0; // safeguard for naive users
   189         // *keylist = _keylist;
   190     }
   191     else {
   192         // free_stringlist(_keylist);
   193         free(_ptext);
   194     }
   195     return result;
   196 }
   197 
   198 PEP_STATUS pgp_verify_text(
   199     PEP_SESSION session, const char *text, size_t size,
   200     const char *signature, size_t sig_size, stringlist_t **keylist
   201     )
   202 {
   203     PEP_STATUS result;
   204     stringlist_t *_keylist;
   205 
   206     assert(session);
   207     assert(text);
   208     assert(size);
   209     assert(signature);
   210     assert(sig_size);
   211     assert(keylist);
   212 
   213     *keylist = NULL;
   214     /* if OK, verify */
   215             stringlist_t *k;
   216             k = _keylist;
   217             result = PEP_VERIFIED;
   218             do {
   219                 k = stringlist_add(k, "TODO");
   220                 if (k == NULL) {
   221                     free_stringlist(_keylist);
   222                     /* TODO */
   223                     return PEP_OUT_OF_MEMORY;
   224                 }
   225             } while (0 /*TODO*/);
   226             *keylist = _keylist;
   227     /*
   228     result = PEP_UNENCRYPTED;
   229     result = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   230     result = PEP_VERIFIED_AND_TRUSTED;
   231     result = PEP_VERIFY_NO_KEY;
   232     result = PEP_UNENCRYPTED;
   233     result = PEP_DECRYPT_WRONG_FORMAT;
   234     return PEP_OUT_OF_MEMORY;
   235     */
   236     result = PEP_UNKNOWN_ERROR;
   237 
   238     return result;
   239 }
   240 
   241 PEP_STATUS pgp_encrypt_and_sign(
   242     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   243     size_t psize, char **ctext, size_t *csize
   244     )
   245 {
   246     PEP_STATUS result;
   247     const stringlist_t *_keylist;
   248     int i, j;
   249 
   250     assert(session);
   251     assert(keylist);
   252     assert(ptext);
   253     assert(psize);
   254     assert(ctext);
   255     assert(csize);
   256 
   257     *ctext = NULL;
   258     *csize = 0;
   259 
   260     for (_keylist = keylist, i = 0; _keylist != NULL; _keylist = _keylist->next, i++) {
   261         assert(_keylist->value);
   262         /* TODO */
   263         /* get key from  _keylist->value */
   264         /* add key to recipients/signers */
   265     }
   266 
   267     /* Do encrypt and sign */ 
   268     char *_buffer = NULL;
   269     size_t length = /* TODO length*/ 0;
   270     assert(length != -1);
   271 
   272     /* Allocate transferable buffer */
   273     _buffer = malloc(length + 1);
   274     assert(_buffer);
   275     if (_buffer == NULL) {
   276         /* TODO clean */
   277         return PEP_OUT_OF_MEMORY;
   278     }
   279 
   280     *ctext = _buffer;
   281     *csize = length;
   282     (*ctext)[*csize] = 0; // safeguard for naive users
   283     result = PEP_STATUS_OK;
   284 
   285     
   286     result = PEP_UNKNOWN_ERROR;
   287     return result;
   288 }
   289 
   290 PEP_STATUS pgp_generate_keypair(
   291     PEP_SESSION session, pEp_identity *identity
   292     )
   293 {
   294     char *parms;
   295     const char *template =
   296         "Key-Type: RSA\n"
   297         "Key-Length: 4096\n"
   298         "Name-Real: %s\n"
   299         "Name-Email: %s\n"
   300         /* "Passphrase: %s\n" */
   301         "Expire-Date: 1y\n";
   302     int result;
   303 
   304     assert(session);
   305     assert(identity);
   306     assert(identity->address);
   307     assert(identity->fpr == NULL);
   308     assert(identity->username);
   309 
   310     parms = calloc(1, PARMS_MAX);
   311     assert(parms);
   312     if (parms == NULL)
   313         return PEP_OUT_OF_MEMORY;
   314 
   315     result = snprintf(parms, PARMS_MAX, template, identity->username,
   316         identity->address);
   317     assert(result < PARMS_MAX);
   318     if (result >= PARMS_MAX) {
   319         free(parms);
   320         return PEP_BUFFER_TOO_SMALL;
   321     }
   322 
   323     /* TODO generate key */
   324 
   325     free(parms);
   326 
   327         return PEP_UNKNOWN_ERROR;
   328         return PEP_ILLEGAL_VALUE;
   329         return PEP_CANNOT_CREATE_KEY;
   330 
   331     identity->fpr = strdup("TODO generated key fpr");
   332 
   333     return PEP_STATUS_OK;
   334 }
   335 
   336 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
   337 {
   338     assert(session);
   339     assert(fpr);
   340 
   341     /* TODO get key with given fpr */
   342         return PEP_KEY_NOT_FOUND;
   343         return PEP_ILLEGAL_VALUE;
   344         return PEP_KEY_HAS_AMBIG_NAME;
   345         return PEP_OUT_OF_MEMORY;
   346         return PEP_UNKNOWN_ERROR;
   347 
   348     /* TODO delete that key */
   349         return PEP_UNKNOWN_ERROR;
   350         return PEP_KEY_NOT_FOUND;
   351         return PEP_KEY_HAS_AMBIG_NAME;
   352         return PEP_UNKNOWN_ERROR;
   353 
   354     return PEP_STATUS_OK;
   355 }
   356 
   357 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
   358 {
   359     assert(session);
   360     assert(key_data);
   361 
   362     /* TODO import */
   363         return PEP_UNKNOWN_ERROR;
   364         return PEP_ILLEGAL_VALUE;
   365         return PEP_UNKNOWN_ERROR;
   366     return PEP_STATUS_OK;
   367 }
   368 
   369 PEP_STATUS pgp_export_keydata(
   370     PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   371     )
   372 {
   373     size_t _size;
   374     char *buffer;
   375     int reading;
   376 
   377     assert(session);
   378     assert(fpr);
   379     assert(key_data);
   380     assert(size);
   381 
   382 
   383     /* TODO export */
   384         return PEP_KEY_NOT_FOUND;
   385         return PEP_UNKNOWN_ERROR;
   386         return PEP_UNKNOWN_ERROR;
   387 
   388     _size = /* TODO */ 0;
   389     assert(_size != -1);
   390 
   391     buffer = malloc(_size + 1);
   392     assert(buffer);
   393     if (buffer == NULL) {
   394         /* TODO clean */
   395         return PEP_OUT_OF_MEMORY;
   396     }
   397 
   398     // safeguard for the naive user
   399     buffer[_size] = 0;
   400 
   401     *key_data = buffer;
   402     *size = _size;
   403 
   404     return PEP_STATUS_OK;
   405 }
   406 
   407 // "keyserver"
   408 // "hkp://keys.gnupg.net"
   409 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
   410 {
   411     assert(session);
   412     assert(pattern);
   413 
   414     /* TODO ask for key */
   415         return PEP_UNKNOWN_ERROR;
   416         return PEP_GET_KEY_FAILED;
   417 
   418     do {
   419 
   420         /* For each key */
   421         /* import key */
   422     } while (0);
   423 
   424     return PEP_STATUS_OK;
   425 }
   426 
   427 PEP_STATUS pgp_find_keys(
   428     PEP_SESSION session, const char *pattern, stringlist_t **keylist
   429     )
   430 {
   431     stringlist_t *_keylist;
   432     char *fpr;
   433 
   434     assert(session);
   435     assert(pattern);
   436     assert(keylist);
   437 
   438     *keylist = NULL;
   439 
   440     /* Ask for key */
   441         return PEP_UNKNOWN_ERROR;
   442         return PEP_GET_KEY_FAILED;
   443 
   444     _keylist = new_stringlist(NULL);
   445     stringlist_t *_k = _keylist;
   446 
   447     do {
   448             fpr = "TODO key->subkeys->fpr";
   449             assert(fpr);
   450             _k = stringlist_add(_k, fpr);
   451             assert(_k);
   452             if (_k == NULL){
   453                 free_stringlist(_keylist);
   454                 return PEP_OUT_OF_MEMORY;
   455             }
   456     } while (0);
   457 
   458     *keylist = _keylist;
   459     return PEP_STATUS_OK;
   460 }
   461 
   462 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
   463 {
   464     assert(session);
   465     assert(pattern);
   466 
   467     /* TODO send key */
   468 
   469         return PEP_CANNOT_SEND_KEY;
   470         return PEP_STATUS_OK;
   471 }
   472 
   473 
   474 PEP_STATUS pgp_get_key_rating(
   475     PEP_SESSION session,
   476     const char *fpr,
   477     PEP_comm_type *comm_type
   478     )
   479 {
   480     PEP_STATUS status = PEP_STATUS_OK;
   481 
   482     assert(session);
   483     assert(fpr);
   484     assert(comm_type);
   485 
   486     *comm_type = PEP_ct_unknown;
   487 
   488     /* TODO get key from fpr */
   489     return PEP_UNKNOWN_ERROR;
   490     return PEP_GET_KEY_FAILED;
   491 
   492     switch (/*TODO key->protocol*/ 4) {
   493     case /* TODO  OpenPGP */0:
   494     case /* TODO DEFAULT */1:
   495         *comm_type = PEP_ct_OpenPGP_unconfirmed;
   496         break;
   497     case /* TODO CMS */2:
   498         *comm_type = PEP_ct_CMS_unconfirmed;
   499         break;
   500     default:
   501         *comm_type = PEP_ct_unknown;
   502         return PEP_STATUS_OK;
   503     }
   504 
   505         for (; 1 == 0; /* Each subkeys */ ) {
   506             if (/* TODO length */0 < 1024)
   507                 *comm_type = PEP_ct_key_too_short;
   508             else if (
   509                 (
   510                 (   /* TODO pubkey_algo == RSA  */ 0)
   511                 || (/* TODO pubkey_algo == RSA_E*/ 0)
   512                 || (/* TODO pubkey_algo == RSA_S*/ 0)
   513                 )
   514                 && /* sk->length */0 == 1024
   515                 )
   516                 *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
   517 
   518             if (/* TODO invalid */ 1) {
   519                 *comm_type = PEP_ct_key_b0rken;
   520                 break;
   521             }
   522             if (/* TODO expired */ 1) {
   523                 *comm_type = PEP_ct_key_expired;
   524                 break;
   525             }
   526             if (/* TODO revoked*/ 1) {
   527                 *comm_type = PEP_ct_key_revoked;
   528                 break;
   529             }
   530         }
   531         *comm_type = PEP_ct_unknown;
   532         return PEP_OUT_OF_MEMORY;
   533         return PEP_UNKNOWN_ERROR;
   534 
   535 
   536     return status;
   537 }