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