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