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
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@209
   386
    pgp_memory_t *signedmem;
Edouard@209
   387
    pgp_memory_t *cmem;
Edouard@207
   388
    const char *userid;
Edouard@207
   389
    const char *hashalg;
Edouard@209
   390
    pgp_keyring_t *rcpts;
Edouard@207
   391
Edouard@174
   392
    PEP_STATUS result;
Edouard@174
   393
    const stringlist_t *_keylist;
Edouard@207
   394
    int i;
Edouard@174
   395
Edouard@174
   396
    assert(session);
Edouard@174
   397
    assert(keylist);
Edouard@174
   398
    assert(ptext);
Edouard@174
   399
    assert(psize);
Edouard@174
   400
    assert(ctext);
Edouard@174
   401
    assert(csize);
Edouard@174
   402
Edouard@207
   403
    if(!session || !ptext || !psize || !ctext || !csize || !keylist) 
Edouard@207
   404
        return PEP_UNKNOWN_ERROR;
Edouard@207
   405
Edouard@208
   406
    netpgp = &session->ctx;
Edouard@208
   407
Edouard@174
   408
    *ctext = NULL;
Edouard@174
   409
    *csize = 0;
Edouard@174
   410
Edouard@207
   411
    // Get signing details from netpgp
Edouard@207
   412
    if ((userid = netpgp_getvar(netpgp, "userid")) == NULL || 
Edouard@207
   413
        (keypair = pgp_getkeybyname(netpgp->io, netpgp->secring, userid)) == NULL ||
Edouard@207
   414
        (seckey = pgp_decrypt_seckey(keypair, NULL /*passfp*/)) == NULL) {
Edouard@207
   415
        return PEP_UNKNOWN_ERROR;
Edouard@207
   416
    }
Edouard@209
   417
Edouard@207
   418
    hashalg = netpgp_getvar(netpgp, "hash");
Edouard@209
   419
    // netpgp (l)imitation - XXX why ? 
Edouard@207
   420
    if (seckey->pubkey.alg == PGP_PKA_DSA) {
Edouard@209
   421
        hashalg = "sha1";
Edouard@207
   422
    }
Edouard@207
   423
Edouard@207
   424
    // Sign data
Edouard@207
   425
    signedmem = pgp_sign_buf(netpgp->io, ptext, psize, seckey,
Edouard@209
   426
                time(NULL), /* birthtime */
Edouard@209
   427
                0 /* duration */,
Edouard@209
   428
                hashalg, 
Edouard@207
   429
                0 /* armored */,
Edouard@207
   430
                0 /* cleartext */);
Edouard@207
   431
Edouard@207
   432
    pgp_forget(seckey, (unsigned)sizeof(*seckey));
Edouard@207
   433
Edouard@207
   434
    if (!signedmem) {
Edouard@207
   435
        return PEP_UNENCRYPTED;
Edouard@207
   436
    }
Edouard@207
   437
Edouard@207
   438
    // Encrypt signed data
Edouard@209
   439
    if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
Edouard@209
   440
        result = PEP_OUT_OF_MEMORY;
Edouard@209
   441
        goto free_signedmem;
Edouard@209
   442
    }
Edouard@209
   443
    for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
Edouard@174
   444
        assert(_keylist->value);
Edouard@209
   445
        // get key from netpgp's pubring
Edouard@209
   446
        const pgp_key_t *key;
Edouard@209
   447
        key = pgp_getkeybyname(netpgp->io,
Edouard@209
   448
                               netpgp->pubring,
Edouard@209
   449
                               _keylist->value);
Edouard@209
   450
Edouard@209
   451
        if(key == NULL){
Edouard@209
   452
            result = PEP_KEY_NOT_FOUND;
Edouard@209
   453
            goto free_rcpts;
Edouard@209
   454
        }
Edouard@209
   455
#ifdef PEP_NETPGP_DEBUG
Edouard@209
   456
        pgp_print_keydata(netpgp->io, netpgp->pubring, key,
Edouard@209
   457
                          "recipient pubkey ", &key->key.pubkey, 0);
Edouard@209
   458
#endif //PEP_NETPGP_DEBUG
Edouard@209
   459
Edouard@209
   460
        // add key to recipients/signers
Edouard@209
   461
        pgp_keyring_add(rcpts, key);
Edouard@209
   462
        if(rcpts->keys == NULL){
Edouard@209
   463
            result = PEP_OUT_OF_MEMORY;
Edouard@209
   464
            goto free_signedmem;
Edouard@209
   465
        }
Edouard@174
   466
    }
Edouard@174
   467
Edouard@209
   468
    cmem = pgp_encrypt_buf(netpgp->io, pgp_mem_data(signedmem),
Edouard@209
   469
            pgp_mem_len(signedmem), rcpts, 1 /* armored */,
Edouard@209
   470
            netpgp_getvar(netpgp, "cipher"), 
Edouard@209
   471
            1 /* takes raw OpenPGP message */);
Edouard@209
   472
Edouard@209
   473
    if (cmem == NULL) {
Edouard@209
   474
        result = PEP_OUT_OF_MEMORY;
Edouard@209
   475
        goto free_signedmem;
Edouard@209
   476
    }else{
Edouard@209
   477
Edouard@209
   478
        char *_buffer = NULL;
Edouard@209
   479
        size_t length = pgp_mem_len(cmem);
Edouard@209
   480
        assert(length != -1);
Edouard@174
   481
Edouard@209
   482
        // Allocate transferable buffer
Edouard@209
   483
        _buffer = malloc(length + 1);
Edouard@209
   484
        assert(_buffer);
Edouard@209
   485
        if (_buffer == NULL) {
Edouard@209
   486
            result = PEP_OUT_OF_MEMORY;
Edouard@209
   487
            goto free_cmem;
Edouard@209
   488
        }
Edouard@209
   489
Edouard@209
   490
        memcpy(_buffer, pgp_mem_data(cmem), length);
Edouard@209
   491
Edouard@209
   492
        *ctext = _buffer;
Edouard@209
   493
        *csize = length;
Edouard@209
   494
        (*ctext)[*csize] = 0; // safeguard for naive users
Edouard@209
   495
        result = PEP_STATUS_OK;
Edouard@174
   496
    }
Edouard@174
   497
Edouard@209
   498
free_cmem :
Edouard@209
   499
    pgp_memory_free(cmem);
Edouard@209
   500
free_rcpts :
Edouard@209
   501
    pgp_keyring_free(rcpts);
Edouard@209
   502
free_signedmem :
Edouard@209
   503
    pgp_memory_free(signedmem);
Edouard@175
   504
Edouard@174
   505
    return result;
Edouard@174
   506
}
Edouard@174
   507
Edouard@174
   508
PEP_STATUS pgp_generate_keypair(
Edouard@174
   509
    PEP_SESSION session, pEp_identity *identity
Edouard@174
   510
    )
Edouard@174
   511
{
Edouard@174
   512
    char *parms;
Edouard@174
   513
    const char *template =
Edouard@174
   514
        "Key-Type: RSA\n"
Edouard@174
   515
        "Key-Length: 4096\n"
Edouard@174
   516
        "Name-Real: %s\n"
Edouard@174
   517
        "Name-Email: %s\n"
Edouard@174
   518
        /* "Passphrase: %s\n" */
Edouard@174
   519
        "Expire-Date: 1y\n";
Edouard@174
   520
    int result;
Edouard@174
   521
Edouard@174
   522
    assert(session);
Edouard@174
   523
    assert(identity);
Edouard@174
   524
    assert(identity->address);
Edouard@174
   525
    assert(identity->fpr == NULL);
Edouard@174
   526
    assert(identity->username);
Edouard@174
   527
Edouard@174
   528
    parms = calloc(1, PARMS_MAX);
Edouard@174
   529
    assert(parms);
Edouard@174
   530
    if (parms == NULL)
Edouard@174
   531
        return PEP_OUT_OF_MEMORY;
Edouard@174
   532
Edouard@174
   533
    result = snprintf(parms, PARMS_MAX, template, identity->username,
Edouard@174
   534
        identity->address);
Edouard@174
   535
    assert(result < PARMS_MAX);
Edouard@174
   536
    if (result >= PARMS_MAX) {
Edouard@174
   537
        free(parms);
Edouard@174
   538
        return PEP_BUFFER_TOO_SMALL;
Edouard@174
   539
    }
Edouard@174
   540
Edouard@174
   541
    /* TODO generate key */
Edouard@174
   542
Edouard@174
   543
    free(parms);
Edouard@174
   544
Edouard@174
   545
        return PEP_UNKNOWN_ERROR;
Edouard@174
   546
        return PEP_ILLEGAL_VALUE;
Edouard@174
   547
        return PEP_CANNOT_CREATE_KEY;
Edouard@174
   548
Edouard@174
   549
    identity->fpr = strdup("TODO generated key fpr");
Edouard@174
   550
Edouard@174
   551
    return PEP_STATUS_OK;
Edouard@174
   552
}
Edouard@174
   553
Edouard@174
   554
PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
Edouard@174
   555
{
Edouard@174
   556
    assert(session);
Edouard@174
   557
    assert(fpr);
Edouard@174
   558
Edouard@174
   559
    /* TODO get key with given fpr */
Edouard@174
   560
        return PEP_KEY_NOT_FOUND;
Edouard@174
   561
        return PEP_ILLEGAL_VALUE;
Edouard@174
   562
        return PEP_KEY_HAS_AMBIG_NAME;
Edouard@174
   563
        return PEP_OUT_OF_MEMORY;
Edouard@174
   564
        return PEP_UNKNOWN_ERROR;
Edouard@174
   565
Edouard@174
   566
    /* TODO delete that key */
Edouard@174
   567
        return PEP_UNKNOWN_ERROR;
Edouard@174
   568
        return PEP_KEY_NOT_FOUND;
Edouard@174
   569
        return PEP_KEY_HAS_AMBIG_NAME;
Edouard@174
   570
        return PEP_UNKNOWN_ERROR;
Edouard@174
   571
Edouard@174
   572
    return PEP_STATUS_OK;
Edouard@174
   573
}
Edouard@174
   574
Edouard@179
   575
PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
Edouard@174
   576
{
Edouard@174
   577
    assert(session);
Edouard@174
   578
    assert(key_data);
Edouard@174
   579
Edouard@174
   580
    /* TODO import */
Edouard@174
   581
        return PEP_UNKNOWN_ERROR;
Edouard@174
   582
        return PEP_ILLEGAL_VALUE;
Edouard@174
   583
        return PEP_UNKNOWN_ERROR;
Edouard@174
   584
    return PEP_STATUS_OK;
Edouard@174
   585
}
Edouard@174
   586
Edouard@179
   587
PEP_STATUS pgp_export_keydata(
Edouard@174
   588
    PEP_SESSION session, const char *fpr, char **key_data, size_t *size
Edouard@174
   589
    )
Edouard@174
   590
{
Edouard@174
   591
    size_t _size;
Edouard@174
   592
    char *buffer;
Edouard@174
   593
    int reading;
Edouard@174
   594
Edouard@174
   595
    assert(session);
Edouard@174
   596
    assert(fpr);
Edouard@174
   597
    assert(key_data);
Edouard@174
   598
    assert(size);
Edouard@174
   599
Edouard@174
   600
Edouard@174
   601
    /* TODO export */
Edouard@174
   602
        return PEP_KEY_NOT_FOUND;
Edouard@174
   603
        return PEP_UNKNOWN_ERROR;
Edouard@174
   604
        return PEP_UNKNOWN_ERROR;
Edouard@174
   605
Edouard@174
   606
    _size = /* TODO */ 0;
Edouard@174
   607
    assert(_size != -1);
Edouard@174
   608
Edouard@174
   609
    buffer = malloc(_size + 1);
Edouard@174
   610
    assert(buffer);
Edouard@174
   611
    if (buffer == NULL) {
Edouard@174
   612
        /* TODO clean */
Edouard@174
   613
        return PEP_OUT_OF_MEMORY;
Edouard@174
   614
    }
Edouard@174
   615
Edouard@174
   616
    // safeguard for the naive user
Edouard@174
   617
    buffer[_size] = 0;
Edouard@174
   618
Edouard@174
   619
    *key_data = buffer;
Edouard@174
   620
    *size = _size;
Edouard@174
   621
Edouard@174
   622
    return PEP_STATUS_OK;
Edouard@174
   623
}
Edouard@174
   624
Edouard@175
   625
// "keyserver"
Edouard@175
   626
// "hkp://keys.gnupg.net"
Edouard@174
   627
PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
Edouard@174
   628
{
Edouard@174
   629
    assert(session);
Edouard@174
   630
    assert(pattern);
Edouard@174
   631
Edouard@174
   632
    /* TODO ask for key */
Edouard@174
   633
        return PEP_UNKNOWN_ERROR;
Edouard@174
   634
        return PEP_GET_KEY_FAILED;
Edouard@174
   635
Edouard@174
   636
    do {
Edouard@174
   637
Edouard@174
   638
        /* For each key */
Edouard@174
   639
        /* import key */
Edouard@174
   640
    } while (0);
Edouard@174
   641
Edouard@174
   642
    return PEP_STATUS_OK;
Edouard@174
   643
}
Edouard@174
   644
Edouard@174
   645
PEP_STATUS pgp_find_keys(
Edouard@174
   646
    PEP_SESSION session, const char *pattern, stringlist_t **keylist
Edouard@174
   647
    )
Edouard@174
   648
{
Edouard@174
   649
    stringlist_t *_keylist;
Edouard@174
   650
    char *fpr;
Edouard@174
   651
Edouard@174
   652
    assert(session);
Edouard@174
   653
    assert(pattern);
Edouard@174
   654
    assert(keylist);
Edouard@174
   655
Edouard@174
   656
    *keylist = NULL;
Edouard@174
   657
Edouard@174
   658
    /* Ask for key */
Edouard@174
   659
        return PEP_UNKNOWN_ERROR;
Edouard@174
   660
        return PEP_GET_KEY_FAILED;
Edouard@174
   661
Edouard@174
   662
    _keylist = new_stringlist(NULL);
Edouard@174
   663
    stringlist_t *_k = _keylist;
Edouard@174
   664
Edouard@174
   665
    do {
Edouard@174
   666
            fpr = "TODO key->subkeys->fpr";
Edouard@174
   667
            assert(fpr);
Edouard@174
   668
            _k = stringlist_add(_k, fpr);
Edouard@174
   669
            assert(_k);
Edouard@174
   670
            if (_k == NULL){
Edouard@174
   671
                free_stringlist(_keylist);
Edouard@174
   672
                return PEP_OUT_OF_MEMORY;
Edouard@174
   673
            }
Edouard@174
   674
    } while (0);
Edouard@174
   675
Edouard@174
   676
    *keylist = _keylist;
Edouard@174
   677
    return PEP_STATUS_OK;
Edouard@174
   678
}
Edouard@174
   679
Edouard@174
   680
PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
Edouard@174
   681
{
Edouard@174
   682
    assert(session);
Edouard@174
   683
    assert(pattern);
Edouard@174
   684
Edouard@174
   685
    /* TODO send key */
Edouard@174
   686
Edouard@174
   687
        return PEP_CANNOT_SEND_KEY;
Edouard@174
   688
        return PEP_STATUS_OK;
Edouard@174
   689
}
Edouard@174
   690
Edouard@174
   691
Edouard@174
   692
PEP_STATUS pgp_get_key_rating(
Edouard@174
   693
    PEP_SESSION session,
Edouard@174
   694
    const char *fpr,
Edouard@174
   695
    PEP_comm_type *comm_type
Edouard@174
   696
    )
Edouard@174
   697
{
Edouard@174
   698
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@174
   699
Edouard@174
   700
    assert(session);
Edouard@174
   701
    assert(fpr);
Edouard@174
   702
    assert(comm_type);
Edouard@174
   703
Edouard@174
   704
    *comm_type = PEP_ct_unknown;
Edouard@174
   705
Edouard@174
   706
    /* TODO get key from fpr */
Edouard@174
   707
    return PEP_UNKNOWN_ERROR;
Edouard@174
   708
    return PEP_GET_KEY_FAILED;
Edouard@174
   709
Edouard@174
   710
    switch (/*TODO key->protocol*/ 4) {
Edouard@174
   711
    case /* TODO  OpenPGP */0:
Edouard@174
   712
    case /* TODO DEFAULT */1:
Edouard@174
   713
        *comm_type = PEP_ct_OpenPGP_unconfirmed;
Edouard@174
   714
        break;
Edouard@174
   715
    case /* TODO CMS */2:
Edouard@174
   716
        *comm_type = PEP_ct_CMS_unconfirmed;
Edouard@174
   717
        break;
Edouard@174
   718
    default:
Edouard@174
   719
        *comm_type = PEP_ct_unknown;
Edouard@174
   720
        return PEP_STATUS_OK;
Edouard@174
   721
    }
Edouard@174
   722
Edouard@174
   723
        for (; 1 == 0; /* Each subkeys */ ) {
Edouard@174
   724
            if (/* TODO length */0 < 1024)
Edouard@174
   725
                *comm_type = PEP_ct_key_too_short;
Edouard@174
   726
            else if (
Edouard@174
   727
                (
Edouard@174
   728
                (   /* TODO pubkey_algo == RSA  */ 0)
Edouard@174
   729
                || (/* TODO pubkey_algo == RSA_E*/ 0)
Edouard@174
   730
                || (/* TODO pubkey_algo == RSA_S*/ 0)
Edouard@174
   731
                )
Edouard@174
   732
                && /* sk->length */0 == 1024
Edouard@174
   733
                )
Edouard@174
   734
                *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
Edouard@174
   735
Edouard@174
   736
            if (/* TODO invalid */ 1) {
Edouard@174
   737
                *comm_type = PEP_ct_key_b0rken;
Edouard@174
   738
                break;
Edouard@174
   739
            }
Edouard@174
   740
            if (/* TODO expired */ 1) {
Edouard@174
   741
                *comm_type = PEP_ct_key_expired;
Edouard@174
   742
                break;
Edouard@174
   743
            }
Edouard@175
   744
            if (/* TODO revoked*/ 1) {
Edouard@174
   745
                *comm_type = PEP_ct_key_revoked;
Edouard@174
   746
                break;
Edouard@174
   747
            }
Edouard@174
   748
        }
Edouard@174
   749
        *comm_type = PEP_ct_unknown;
Edouard@174
   750
        return PEP_OUT_OF_MEMORY;
Edouard@174
   751
        return PEP_UNKNOWN_ERROR;
Edouard@174
   752
Edouard@174
   753
Edouard@174
   754
    return status;
Edouard@174
   755
}