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