src/pgp_netpgp.c
author Edouard Tisserant
Sat, 25 Apr 2015 01:23:46 +0200
changeset 226 a2079f2f7a8c
parent 225 ed16ea1bece7
child 227 9321f8fb77c2
permissions -rw-r--r--
merged and updated pgp_netpgp's pgp_key_expired and pgp_key_revoke
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@225
    55
    netpgp_setvar(netpgp, "cipher", "CAST5");
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@225
   101
static void id_to_fpr(const uint8_t *userid, char *fpr)
Edouard@225
   102
{
Edouard@225
   103
    int i;
Edouard@225
   104
    static const char *hexes = "0123456789abcdef";
Edouard@225
   105
    for (i = 0; i < 8 ; i++) {
Edouard@225
   106
        fpr[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
Edouard@225
   107
        fpr[(i * 2) + 1] = hexes[userid[i] & 0xf];
Edouard@225
   108
    }
Edouard@225
   109
    fpr[8 * 2] = 0x0;
Edouard@225
   110
}
Edouard@225
   111
Edouard@185
   112
// Iterate through netpgp' reported valid signatures 
Edouard@185
   113
// fill a list of valid figerprints
Edouard@185
   114
// returns PEP_STATUS_OK if all sig reported valid
Edouard@185
   115
// error status otherwise.
Edouard@185
   116
static PEP_STATUS _validation_results(netpgp_t *netpgp, pgp_validation_t *vresult,
Edouard@185
   117
                                             stringlist_t **_keylist)
Edouard@185
   118
{
Edouard@188
   119
    time_t    now;
Edouard@188
   120
    time_t    t;
Edouard@188
   121
    char    buf[128];
Edouard@185
   122
Edouard@188
   123
    now = time(NULL);
Edouard@188
   124
    if (now < vresult->birthtime) {
Edouard@188
   125
        // signature is not valid yet
Edouard@185
   126
#ifdef PEP_NETPGP_DEBUG
Edouard@188
   127
        (void) printf(
Edouard@188
   128
            "signature not valid until %.24s\n",
Edouard@188
   129
            ctime(&vresult->birthtime));
Edouard@185
   130
#endif //PEP_NETPGP_DEBUG
Edouard@188
   131
        return PEP_UNENCRYPTED;
Edouard@188
   132
    }
Edouard@188
   133
    if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
Edouard@188
   134
        // signature has expired
Edouard@188
   135
        t = vresult->duration + vresult->birthtime;
Edouard@185
   136
#ifdef PEP_NETPGP_DEBUG
Edouard@188
   137
        (void) printf(
Edouard@188
   138
            "signature not valid after %.24s\n",
Edouard@188
   139
            ctime(&t));
Edouard@185
   140
#endif //PEP_NETPGP_DEBUG
Edouard@188
   141
        return PEP_UNENCRYPTED;
Edouard@188
   142
    }
Edouard@185
   143
    if (vresult->validc && vresult->valid_sigs &&
Edouard@185
   144
        !vresult->invalidc && !vresult->unknownc ) {
Edouard@185
   145
        unsigned    n;
Edouard@185
   146
        stringlist_t *k;
Edouard@185
   147
        // caller responsible to free
Edouard@185
   148
        *_keylist = new_stringlist(NULL);
Edouard@185
   149
        assert(*_keylist);
Edouard@185
   150
        if (*_keylist == NULL) {
Edouard@185
   151
            return PEP_OUT_OF_MEMORY;
Edouard@185
   152
        }
Edouard@185
   153
        k = *_keylist;
Edouard@185
   154
        for (n = 0; n < vresult->validc; ++n) {
Edouard@185
   155
            char id[MAX_ID_LENGTH + 1];
Edouard@185
   156
            const uint8_t *userid = vresult->valid_sigs[n].signer_id;
Edouard@185
   157
Edouard@185
   158
#ifdef PEP_NETPGP_DEBUG
Edouard@185
   159
            const pgp_key_t *key;
Edouard@185
   160
            pgp_pubkey_t *sigkey;
Edouard@188
   161
            unsigned from = 0;
Edouard@185
   162
            key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
Edouard@185
   163
                (const uint8_t *) vresult->valid_sigs[n].signer_id,
Edouard@185
   164
                &from, &sigkey);
Edouard@185
   165
            pgp_print_keydata(netpgp->io, netpgp->pubring, key, "valid signature ", &key->key.pubkey, 0);
Edouard@185
   166
#endif //PEP_NETPGP_DEBUG
Edouard@185
   167
Edouard@225
   168
            id_to_fpr(userid, id);
Edouard@185
   169
Edouard@185
   170
            k = stringlist_add(k, id);
Edouard@185
   171
            if(!k){
Edouard@185
   172
                free_stringlist(*_keylist);
Edouard@185
   173
                return PEP_OUT_OF_MEMORY;
Edouard@185
   174
            }
Edouard@185
   175
        }
Edouard@185
   176
        return PEP_STATUS_OK;
Edouard@185
   177
    }
Edouard@185
   178
    if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
Edouard@185
   179
        // No signatures found - is this memory signed?
Edouard@185
   180
        return PEP_VERIFY_NO_KEY; 
Edouard@185
   181
    } 
Edouard@185
   182
    
Edouard@185
   183
    if (vresult->invalidc) {
Edouard@185
   184
        // some invalid signatures
Edouard@185
   185
Edouard@185
   186
#ifdef PEP_NETPGP_DEBUG
Edouard@185
   187
        unsigned    n;
Edouard@185
   188
        for (n = 0; n < vresult->invalidc; ++n) {
Edouard@185
   189
            const pgp_key_t *key;
Edouard@185
   190
            pgp_pubkey_t *sigkey;
Edouard@185
   191
            unsigned from = 0;
Edouard@185
   192
            key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
Edouard@185
   193
                (const uint8_t *) vresult->invalid_sigs[n].signer_id,
Edouard@185
   194
                &from, &sigkey);
Edouard@185
   195
            pgp_print_keydata(netpgp->io, netpgp->pubring, key, "invalid signature ", &key->key.pubkey, 0);
Edouard@188
   196
            if (sigkey->duration != 0 && now > sigkey->birthtime + sigkey->duration) {
Edouard@185
   197
                printf("EXPIRED !\n");
Edouard@185
   198
            }
Edouard@185
   199
        }
Edouard@185
   200
#endif //PEP_NETPGP_DEBUG
Edouard@185
   201
Edouard@185
   202
        return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
Edouard@185
   203
    }
Edouard@185
   204
    
Edouard@185
   205
    // only unknown sigs
Edouard@185
   206
    return PEP_DECRYPT_WRONG_FORMAT;
Edouard@185
   207
}
Edouard@185
   208
Edouard@207
   209
#define ARMOR_HEAD    "^-----BEGIN PGP MESSAGE-----\\s*$"
Edouard@174
   210
PEP_STATUS pgp_decrypt_and_verify(
Edouard@174
   211
    PEP_SESSION session, const char *ctext, size_t csize,
Edouard@174
   212
    char **ptext, size_t *psize, stringlist_t **keylist
Edouard@174
   213
    )
Edouard@174
   214
{
Edouard@179
   215
    netpgp_t *netpgp;
Edouard@185
   216
    pgp_memory_t *mem;
Edouard@185
   217
    pgp_memory_t *cat;
Edouard@185
   218
    pgp_validation_t *vresult;
Edouard@180
   219
    char *_ptext = NULL;
Edouard@180
   220
    size_t _psize = 0;
Edouard@185
   221
    int ret;
Edouard@179
   222
Edouard@174
   223
    PEP_STATUS result;
Edouard@174
   224
    stringlist_t *_keylist = NULL;
Edouard@174
   225
    int i_key = 0;
Edouard@174
   226
Edouard@174
   227
    assert(session);
Edouard@174
   228
    assert(ctext);
Edouard@174
   229
    assert(csize);
Edouard@174
   230
    assert(ptext);
Edouard@174
   231
    assert(psize);
Edouard@174
   232
    assert(keylist);
Edouard@174
   233
Edouard@179
   234
    if(!session || !ctext || !csize || !ptext || !psize || !keylist) 
Edouard@179
   235
        return PEP_UNKNOWN_ERROR;
Edouard@179
   236
Edouard@179
   237
    netpgp = &session->ctx;
Edouard@179
   238
Edouard@174
   239
    *ptext = NULL;
Edouard@174
   240
    *psize = 0;
Edouard@174
   241
    *keylist = NULL;
Edouard@174
   242
Edouard@183
   243
    vresult = malloc(sizeof(pgp_validation_t));
Edouard@185
   244
    memset(vresult, 0x0, sizeof(pgp_validation_t));
Edouard@182
   245
Edouard@183
   246
    mem = pgp_decrypt_and_validate_buf(netpgp->io, vresult, ctext, csize,
Edouard@179
   247
                netpgp->secring, netpgp->pubring,
Edouard@188
   248
                _armoured(ctext, csize, ARMOR_HEAD),
Edouard@179
   249
                0 /* sshkeys */,
Edouard@180
   250
                NULL, -1, NULL  /* pass fp,attempts,cb */);
Edouard@179
   251
    if (mem == NULL) {
Edouard@179
   252
        return PEP_OUT_OF_MEMORY;
Edouard@179
   253
    }
Edouard@179
   254
Edouard@185
   255
    _psize = pgp_mem_len(mem);
Edouard@182
   256
    if (_psize){
Edouard@182
   257
        if ((_ptext = calloc(1, _psize)) == NULL) {
Edouard@183
   258
            result = PEP_OUT_OF_MEMORY;
Edouard@183
   259
            goto free_pgp;
Edouard@182
   260
        }
Edouard@185
   261
        memcpy(_ptext, pgp_mem_data(mem), _psize);
Edouard@182
   262
        result = PEP_DECRYPTED;
Edouard@182
   263
    }else{
Edouard@183
   264
        result = PEP_DECRYPT_NO_KEY;
Edouard@183
   265
        goto free_pgp;
Edouard@182
   266
    }
Edouard@180
   267
Edouard@185
   268
    if (result == PEP_DECRYPTED) {
Edouard@185
   269
        result = _validation_results(netpgp, vresult, &_keylist);
Edouard@185
   270
        if (result != PEP_STATUS_OK) {
Edouard@185
   271
            goto free_ptext;
Edouard@183
   272
        }
Edouard@180
   273
        result = PEP_DECRYPTED_AND_VERIFIED;
Edouard@180
   274
    }
Edouard@174
   275
Edouard@180
   276
    if (result == PEP_DECRYPTED_AND_VERIFIED
Edouard@180
   277
        || result == PEP_DECRYPTED) {
Edouard@180
   278
        *ptext = _ptext;
Edouard@180
   279
        *psize = _psize;
Edouard@180
   280
        (*ptext)[*psize] = 0; // safeguard for naive users
Edouard@185
   281
        if (result == PEP_DECRYPTED_AND_VERIFIED) {
Edouard@185
   282
            *keylist = _keylist;
Edouard@185
   283
        }
Edouard@183
   284
Edouard@183
   285
        /* _ptext and _keylist ownership transfer, don't free */
Edouard@183
   286
        goto free_pgp;
Edouard@180
   287
    }
Edouard@183
   288
Edouard@183
   289
free_keylist:
Edouard@183
   290
    free_stringlist(_keylist);
Edouard@183
   291
Edouard@183
   292
free_ptext:
Edouard@183
   293
    free(_ptext);
Edouard@183
   294
Edouard@183
   295
free_pgp:
Edouard@185
   296
    pgp_memory_free(mem);
Edouard@183
   297
    pgp_validate_result_free(vresult);
Edouard@183
   298
Edouard@174
   299
    return result;
Edouard@174
   300
}
Edouard@174
   301
Edouard@207
   302
#define ARMOR_SIG_HEAD    "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----\\s*$"
Edouard@174
   303
PEP_STATUS pgp_verify_text(
Edouard@174
   304
    PEP_SESSION session, const char *text, size_t size,
Edouard@174
   305
    const char *signature, size_t sig_size, stringlist_t **keylist
Edouard@174
   306
    )
Edouard@174
   307
{
Edouard@185
   308
    netpgp_t *netpgp;
Edouard@185
   309
    pgp_memory_t *signedmem;
Edouard@185
   310
    pgp_memory_t *sig;
Edouard@185
   311
    pgp_validation_t *vresult;
Edouard@185
   312
Edouard@174
   313
    PEP_STATUS result;
Edouard@174
   314
    stringlist_t *_keylist;
Edouard@174
   315
Edouard@174
   316
    assert(session);
Edouard@174
   317
    assert(text);
Edouard@174
   318
    assert(size);
Edouard@174
   319
    assert(signature);
Edouard@174
   320
    assert(sig_size);
Edouard@174
   321
    assert(keylist);
Edouard@174
   322
Edouard@185
   323
    if(!session || !text || !size || !signature || !sig_size || !keylist) 
Edouard@185
   324
        return PEP_UNKNOWN_ERROR;
Edouard@185
   325
Edouard@185
   326
    netpgp = &session->ctx;
Edouard@185
   327
Edouard@174
   328
    *keylist = NULL;
Edouard@185
   329
Edouard@185
   330
    vresult = malloc(sizeof(pgp_validation_t));
Edouard@185
   331
    memset(vresult, 0x0, sizeof(pgp_validation_t));
Edouard@185
   332
Edouard@185
   333
    signedmem = pgp_memory_new();
Edouard@185
   334
    if (signedmem == NULL) {
Edouard@185
   335
        return PEP_OUT_OF_MEMORY;
Edouard@185
   336
    }
Edouard@185
   337
    pgp_memory_add(signedmem, (const uint8_t*)text, size);
Edouard@185
   338
Edouard@185
   339
    sig = pgp_memory_new();
Edouard@185
   340
    if (sig == NULL) {
Edouard@185
   341
        pgp_memory_free(signedmem);
Edouard@185
   342
        return PEP_OUT_OF_MEMORY;
Edouard@185
   343
    }
Edouard@185
   344
    pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
Edouard@185
   345
Edouard@185
   346
    pgp_validate_mem_detached(netpgp->io, vresult, sig,
Edouard@185
   347
                NULL,/* output */
Edouard@207
   348
                _armoured(signature, sig_size, ARMOR_SIG_HEAD),
Edouard@185
   349
                netpgp->pubring,
Edouard@185
   350
                signedmem);
Edouard@185
   351
Edouard@185
   352
    result = _validation_results(netpgp, vresult, &_keylist);
Edouard@185
   353
    if (result != PEP_STATUS_OK) {
Edouard@185
   354
        goto free_pgp;
Edouard@185
   355
    }else{
Edouard@185
   356
        result = PEP_VERIFIED;
Edouard@185
   357
    }
Edouard@185
   358
Edouard@185
   359
    if (result == PEP_VERIFIED) {
Edouard@185
   360
        /* TODO : check trust level */
Edouard@185
   361
        result = PEP_VERIFIED_AND_TRUSTED;
Edouard@185
   362
    }
Edouard@185
   363
Edouard@185
   364
    if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
Edouard@185
   365
        *keylist = _keylist;
Edouard@185
   366
Edouard@185
   367
        /* _keylist ownership transfer, don't free */
Edouard@185
   368
        goto free_pgp;
Edouard@185
   369
    }
Edouard@185
   370
Edouard@185
   371
free_keylist:
Edouard@185
   372
    free_stringlist(_keylist);
Edouard@185
   373
Edouard@185
   374
free_pgp:
Edouard@187
   375
    // free done by pgp_validate_mem_detached
Edouard@187
   376
    // pgp_memory_free(sig);
Edouard@187
   377
    // pgp_memory_free(signedmem);
Edouard@185
   378
    pgp_validate_result_free(vresult);
Edouard@185
   379
Edouard@185
   380
    return result;
Edouard@174
   381
}
Edouard@174
   382
Edouard@174
   383
PEP_STATUS pgp_encrypt_and_sign(
Edouard@174
   384
    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
Edouard@174
   385
    size_t psize, char **ctext, size_t *csize
Edouard@174
   386
    )
Edouard@174
   387
{
Edouard@207
   388
    netpgp_t *netpgp;
Edouard@207
   389
    const pgp_key_t *keypair;
Edouard@207
   390
    pgp_seckey_t *seckey;
Edouard@209
   391
    pgp_memory_t *signedmem;
Edouard@209
   392
    pgp_memory_t *cmem;
Edouard@207
   393
    const char *userid;
Edouard@207
   394
    const char *hashalg;
Edouard@209
   395
    pgp_keyring_t *rcpts;
Edouard@207
   396
Edouard@174
   397
    PEP_STATUS result;
Edouard@174
   398
    const stringlist_t *_keylist;
Edouard@174
   399
Edouard@174
   400
    assert(session);
Edouard@174
   401
    assert(keylist);
Edouard@174
   402
    assert(ptext);
Edouard@174
   403
    assert(psize);
Edouard@174
   404
    assert(ctext);
Edouard@174
   405
    assert(csize);
Edouard@174
   406
Edouard@207
   407
    if(!session || !ptext || !psize || !ctext || !csize || !keylist) 
Edouard@207
   408
        return PEP_UNKNOWN_ERROR;
Edouard@207
   409
Edouard@208
   410
    netpgp = &session->ctx;
Edouard@208
   411
Edouard@174
   412
    *ctext = NULL;
Edouard@174
   413
    *csize = 0;
Edouard@174
   414
Edouard@207
   415
    // Get signing details from netpgp
Edouard@207
   416
    if ((userid = netpgp_getvar(netpgp, "userid")) == NULL || 
Edouard@207
   417
        (keypair = pgp_getkeybyname(netpgp->io, netpgp->secring, userid)) == NULL ||
Edouard@207
   418
        (seckey = pgp_decrypt_seckey(keypair, NULL /*passfp*/)) == NULL) {
Edouard@207
   419
        return PEP_UNKNOWN_ERROR;
Edouard@207
   420
    }
Edouard@209
   421
Edouard@207
   422
    hashalg = netpgp_getvar(netpgp, "hash");
Edouard@209
   423
    // netpgp (l)imitation - XXX why ? 
Edouard@207
   424
    if (seckey->pubkey.alg == PGP_PKA_DSA) {
Edouard@209
   425
        hashalg = "sha1";
Edouard@207
   426
    }
Edouard@207
   427
Edouard@207
   428
    // Sign data
Edouard@207
   429
    signedmem = pgp_sign_buf(netpgp->io, ptext, psize, seckey,
Edouard@209
   430
                time(NULL), /* birthtime */
Edouard@209
   431
                0 /* duration */,
Edouard@209
   432
                hashalg, 
Edouard@207
   433
                0 /* armored */,
Edouard@207
   434
                0 /* cleartext */);
Edouard@207
   435
Edouard@207
   436
    pgp_forget(seckey, (unsigned)sizeof(*seckey));
Edouard@207
   437
Edouard@207
   438
    if (!signedmem) {
Edouard@207
   439
        return PEP_UNENCRYPTED;
Edouard@207
   440
    }
Edouard@207
   441
Edouard@207
   442
    // Encrypt signed data
Edouard@209
   443
    if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
Edouard@209
   444
        result = PEP_OUT_OF_MEMORY;
Edouard@209
   445
        goto free_signedmem;
Edouard@209
   446
    }
Edouard@209
   447
    for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
Edouard@174
   448
        assert(_keylist->value);
Edouard@209
   449
        // get key from netpgp's pubring
Edouard@209
   450
        const pgp_key_t *key;
Edouard@209
   451
        key = pgp_getkeybyname(netpgp->io,
Edouard@209
   452
                               netpgp->pubring,
Edouard@209
   453
                               _keylist->value);
Edouard@209
   454
Edouard@209
   455
        if(key == NULL){
Edouard@209
   456
            result = PEP_KEY_NOT_FOUND;
Edouard@209
   457
            goto free_rcpts;
Edouard@209
   458
        }
Edouard@209
   459
#ifdef PEP_NETPGP_DEBUG
Edouard@209
   460
        pgp_print_keydata(netpgp->io, netpgp->pubring, key,
Edouard@209
   461
                          "recipient pubkey ", &key->key.pubkey, 0);
Edouard@209
   462
#endif //PEP_NETPGP_DEBUG
Edouard@209
   463
Edouard@209
   464
        // add key to recipients/signers
Edouard@209
   465
        pgp_keyring_add(rcpts, key);
Edouard@209
   466
        if(rcpts->keys == NULL){
Edouard@209
   467
            result = PEP_OUT_OF_MEMORY;
Edouard@209
   468
            goto free_signedmem;
Edouard@209
   469
        }
Edouard@174
   470
    }
Edouard@174
   471
Edouard@209
   472
    cmem = pgp_encrypt_buf(netpgp->io, pgp_mem_data(signedmem),
Edouard@209
   473
            pgp_mem_len(signedmem), rcpts, 1 /* armored */,
Edouard@209
   474
            netpgp_getvar(netpgp, "cipher"), 
Edouard@209
   475
            1 /* takes raw OpenPGP message */);
Edouard@209
   476
Edouard@209
   477
    if (cmem == NULL) {
Edouard@209
   478
        result = PEP_OUT_OF_MEMORY;
Edouard@209
   479
        goto free_signedmem;
Edouard@209
   480
    }else{
Edouard@209
   481
Edouard@209
   482
        char *_buffer = NULL;
Edouard@209
   483
        size_t length = pgp_mem_len(cmem);
Edouard@209
   484
        assert(length != -1);
Edouard@174
   485
Edouard@209
   486
        // Allocate transferable buffer
Edouard@209
   487
        _buffer = malloc(length + 1);
Edouard@209
   488
        assert(_buffer);
Edouard@209
   489
        if (_buffer == NULL) {
Edouard@209
   490
            result = PEP_OUT_OF_MEMORY;
Edouard@209
   491
            goto free_cmem;
Edouard@209
   492
        }
Edouard@209
   493
Edouard@209
   494
        memcpy(_buffer, pgp_mem_data(cmem), length);
Edouard@209
   495
Edouard@209
   496
        *ctext = _buffer;
Edouard@209
   497
        *csize = length;
Edouard@209
   498
        (*ctext)[*csize] = 0; // safeguard for naive users
Edouard@209
   499
        result = PEP_STATUS_OK;
Edouard@174
   500
    }
Edouard@174
   501
Edouard@209
   502
free_cmem :
Edouard@209
   503
    pgp_memory_free(cmem);
Edouard@209
   504
free_rcpts :
Edouard@209
   505
    pgp_keyring_free(rcpts);
Edouard@209
   506
free_signedmem :
Edouard@209
   507
    pgp_memory_free(signedmem);
Edouard@175
   508
Edouard@174
   509
    return result;
Edouard@174
   510
}
Edouard@174
   511
Edouard@174
   512
PEP_STATUS pgp_generate_keypair(
Edouard@174
   513
    PEP_SESSION session, pEp_identity *identity
Edouard@174
   514
    )
Edouard@174
   515
{
Edouard@225
   516
    netpgp_t *netpgp;
Edouard@225
   517
	pgp_key_t	newkey;
Edouard@225
   518
	pgp_key_t	pubkey;
Edouard@225
   519
Edouard@225
   520
    PEP_STATUS result;
Edouard@225
   521
	char newid[1024];
Edouard@225
   522
    const char *hashalg;
Edouard@225
   523
    const char *cipher;
Edouard@174
   524
Edouard@174
   525
    assert(session);
Edouard@174
   526
    assert(identity);
Edouard@174
   527
    assert(identity->address);
Edouard@174
   528
    assert(identity->fpr == NULL);
Edouard@174
   529
    assert(identity->username);
Edouard@174
   530
Edouard@225
   531
    if(!session || !identity || 
Edouard@225
   532
       !identity->address || identity->fpr || !identity->username)
Edouard@225
   533
        return PEP_UNKNOWN_ERROR;
Edouard@174
   534
Edouard@225
   535
    netpgp = &session->ctx;
Edouard@225
   536
Edouard@225
   537
    if(snprintf(newid, sizeof(newid),
Edouard@225
   538
        "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
Edouard@174
   539
        return PEP_BUFFER_TOO_SMALL;
Edouard@174
   540
    }
Edouard@225
   541
    
Edouard@225
   542
    hashalg = netpgp_getvar(netpgp, "hash");
Edouard@225
   543
    cipher = netpgp_getvar(netpgp, "cipher");
Edouard@174
   544
Edouard@225
   545
    bzero(&newkey, sizeof(newkey));
Edouard@225
   546
    bzero(&pubkey, sizeof(pubkey));
Edouard@174
   547
Edouard@225
   548
    // Generate the key
Edouard@225
   549
    if (!pgp_rsa_generate_keypair(&newkey, 4096, 65537UL, hashalg, cipher,
Edouard@225
   550
                                  (const uint8_t *) "", (const size_t) 0) ||
Edouard@225
   551
        !pgp_add_selfsigned_userid(&newkey, newid)) {
Edouard@225
   552
        return PEP_CANNOT_CREATE_KEY;
Edouard@225
   553
	}
Edouard@225
   554
Edouard@225
   555
    // TODO "Expire-Date: 1y\n";
Edouard@225
   556
Edouard@225
   557
    // Duplicate key as public only
Edouard@225
   558
    pgp_keydata_dup(&pubkey, &newkey, 1 /* make_public */);
Edouard@174
   559
Edouard@225
   560
    // Append generated key to netpgp's rings
Edouard@225
   561
    pgp_keyring_add(netpgp->secring, &newkey);
Edouard@225
   562
    pgp_keyring_add(netpgp->pubring, &pubkey);
Edouard@225
   563
    // FIXME doesn't check result since always true 
Edouard@225
   564
    // TODO alloc error feedback in netpgp
Edouard@225
   565
Edouard@225
   566
    // save rings
Edouard@225
   567
    if (netpgp_save_pubring(netpgp) && 
Edouard@225
   568
        netpgp_save_secring(netpgp))
Edouard@225
   569
    {
Edouard@225
   570
        char fpr[MAX_ID_LENGTH + 1];
Edouard@225
   571
        id_to_fpr(pubkey.sigid, fpr);
Edouard@174
   572
Edouard@225
   573
        if ((identity->fpr = strdup(fpr)) == NULL) {
Edouard@225
   574
            result = PEP_OUT_OF_MEMORY;
Edouard@225
   575
        }else{
Edouard@225
   576
            result = PEP_STATUS_OK;
Edouard@225
   577
        }
Edouard@225
   578
    }else{
Edouard@225
   579
        result = PEP_UNKNOWN_ERROR;
Edouard@225
   580
    }
Edouard@174
   581
Edouard@225
   582
    // pgp_keydata_free(key);
Edouard@225
   583
Edouard@225
   584
    return result;
Edouard@174
   585
}
Edouard@174
   586
Edouard@174
   587
PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
Edouard@174
   588
{
Edouard@174
   589
    assert(session);
Edouard@174
   590
    assert(fpr);
Edouard@174
   591
Edouard@174
   592
    /* TODO get key with given fpr */
Edouard@174
   593
        return PEP_KEY_NOT_FOUND;
Edouard@174
   594
        return PEP_ILLEGAL_VALUE;
Edouard@174
   595
        return PEP_KEY_HAS_AMBIG_NAME;
Edouard@174
   596
        return PEP_OUT_OF_MEMORY;
Edouard@174
   597
        return PEP_UNKNOWN_ERROR;
Edouard@174
   598
Edouard@174
   599
    /* TODO delete that key */
Edouard@174
   600
        return PEP_UNKNOWN_ERROR;
Edouard@174
   601
        return PEP_KEY_NOT_FOUND;
Edouard@174
   602
        return PEP_KEY_HAS_AMBIG_NAME;
Edouard@174
   603
        return PEP_UNKNOWN_ERROR;
Edouard@174
   604
Edouard@174
   605
    return PEP_STATUS_OK;
Edouard@174
   606
}
Edouard@174
   607
Edouard@179
   608
PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
Edouard@174
   609
{
Edouard@174
   610
    assert(session);
Edouard@174
   611
    assert(key_data);
Edouard@174
   612
Edouard@174
   613
    /* TODO import */
Edouard@174
   614
        return PEP_UNKNOWN_ERROR;
Edouard@174
   615
        return PEP_ILLEGAL_VALUE;
Edouard@174
   616
        return PEP_UNKNOWN_ERROR;
Edouard@174
   617
    return PEP_STATUS_OK;
Edouard@174
   618
}
Edouard@174
   619
Edouard@179
   620
PEP_STATUS pgp_export_keydata(
Edouard@174
   621
    PEP_SESSION session, const char *fpr, char **key_data, size_t *size
Edouard@174
   622
    )
Edouard@174
   623
{
Edouard@174
   624
    size_t _size;
Edouard@174
   625
    char *buffer;
Edouard@174
   626
    int reading;
Edouard@174
   627
Edouard@174
   628
    assert(session);
Edouard@174
   629
    assert(fpr);
Edouard@174
   630
    assert(key_data);
Edouard@174
   631
    assert(size);
Edouard@174
   632
Edouard@174
   633
Edouard@174
   634
    /* TODO export */
Edouard@174
   635
        return PEP_KEY_NOT_FOUND;
Edouard@174
   636
        return PEP_UNKNOWN_ERROR;
Edouard@174
   637
        return PEP_UNKNOWN_ERROR;
Edouard@174
   638
Edouard@174
   639
    _size = /* TODO */ 0;
Edouard@174
   640
    assert(_size != -1);
Edouard@174
   641
Edouard@174
   642
    buffer = malloc(_size + 1);
Edouard@174
   643
    assert(buffer);
Edouard@174
   644
    if (buffer == NULL) {
Edouard@174
   645
        /* TODO clean */
Edouard@174
   646
        return PEP_OUT_OF_MEMORY;
Edouard@174
   647
    }
Edouard@174
   648
Edouard@174
   649
    // safeguard for the naive user
Edouard@174
   650
    buffer[_size] = 0;
Edouard@174
   651
Edouard@174
   652
    *key_data = buffer;
Edouard@174
   653
    *size = _size;
Edouard@174
   654
Edouard@174
   655
    return PEP_STATUS_OK;
Edouard@174
   656
}
Edouard@174
   657
Edouard@175
   658
// "keyserver"
Edouard@175
   659
// "hkp://keys.gnupg.net"
Edouard@174
   660
PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
Edouard@174
   661
{
Edouard@174
   662
    assert(session);
Edouard@174
   663
    assert(pattern);
Edouard@174
   664
Edouard@174
   665
    /* TODO ask for key */
Edouard@174
   666
        return PEP_UNKNOWN_ERROR;
Edouard@174
   667
        return PEP_GET_KEY_FAILED;
Edouard@174
   668
Edouard@174
   669
    do {
Edouard@174
   670
Edouard@174
   671
        /* For each key */
Edouard@174
   672
        /* import key */
Edouard@174
   673
    } while (0);
Edouard@174
   674
Edouard@174
   675
    return PEP_STATUS_OK;
Edouard@174
   676
}
Edouard@174
   677
Edouard@174
   678
PEP_STATUS pgp_find_keys(
Edouard@174
   679
    PEP_SESSION session, const char *pattern, stringlist_t **keylist
Edouard@174
   680
    )
Edouard@174
   681
{
Edouard@174
   682
    stringlist_t *_keylist;
Edouard@174
   683
    char *fpr;
Edouard@174
   684
Edouard@174
   685
    assert(session);
Edouard@174
   686
    assert(pattern);
Edouard@174
   687
    assert(keylist);
Edouard@174
   688
Edouard@174
   689
    *keylist = NULL;
Edouard@174
   690
Edouard@174
   691
    /* Ask for key */
Edouard@174
   692
        return PEP_UNKNOWN_ERROR;
Edouard@174
   693
        return PEP_GET_KEY_FAILED;
Edouard@174
   694
Edouard@174
   695
    _keylist = new_stringlist(NULL);
Edouard@174
   696
    stringlist_t *_k = _keylist;
Edouard@174
   697
Edouard@174
   698
    do {
Edouard@174
   699
            fpr = "TODO key->subkeys->fpr";
Edouard@174
   700
            assert(fpr);
Edouard@174
   701
            _k = stringlist_add(_k, fpr);
Edouard@174
   702
            assert(_k);
Edouard@174
   703
            if (_k == NULL){
Edouard@174
   704
                free_stringlist(_keylist);
Edouard@174
   705
                return PEP_OUT_OF_MEMORY;
Edouard@174
   706
            }
Edouard@174
   707
    } while (0);
Edouard@174
   708
Edouard@174
   709
    *keylist = _keylist;
Edouard@174
   710
    return PEP_STATUS_OK;
Edouard@174
   711
}
Edouard@174
   712
Edouard@174
   713
PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
Edouard@174
   714
{
Edouard@174
   715
    assert(session);
Edouard@174
   716
    assert(pattern);
Edouard@174
   717
Edouard@174
   718
    /* TODO send key */
Edouard@174
   719
Edouard@174
   720
        return PEP_CANNOT_SEND_KEY;
Edouard@174
   721
        return PEP_STATUS_OK;
Edouard@174
   722
}
Edouard@174
   723
Edouard@174
   724
Edouard@174
   725
PEP_STATUS pgp_get_key_rating(
Edouard@174
   726
    PEP_SESSION session,
Edouard@174
   727
    const char *fpr,
Edouard@174
   728
    PEP_comm_type *comm_type
Edouard@174
   729
    )
Edouard@174
   730
{
Edouard@174
   731
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@174
   732
Edouard@174
   733
    assert(session);
Edouard@174
   734
    assert(fpr);
Edouard@174
   735
    assert(comm_type);
Edouard@174
   736
Edouard@174
   737
    *comm_type = PEP_ct_unknown;
Edouard@174
   738
Edouard@174
   739
    /* TODO get key from fpr */
Edouard@174
   740
    return PEP_UNKNOWN_ERROR;
Edouard@174
   741
    return PEP_GET_KEY_FAILED;
Edouard@174
   742
Edouard@174
   743
    switch (/*TODO key->protocol*/ 4) {
Edouard@174
   744
    case /* TODO  OpenPGP */0:
Edouard@174
   745
    case /* TODO DEFAULT */1:
Edouard@174
   746
        *comm_type = PEP_ct_OpenPGP_unconfirmed;
Edouard@174
   747
        break;
Edouard@174
   748
    case /* TODO CMS */2:
Edouard@174
   749
        *comm_type = PEP_ct_CMS_unconfirmed;
Edouard@174
   750
        break;
Edouard@174
   751
    default:
Edouard@174
   752
        *comm_type = PEP_ct_unknown;
Edouard@174
   753
        return PEP_STATUS_OK;
Edouard@174
   754
    }
Edouard@174
   755
Edouard@174
   756
        for (; 1 == 0; /* Each subkeys */ ) {
Edouard@174
   757
            if (/* TODO length */0 < 1024)
Edouard@174
   758
                *comm_type = PEP_ct_key_too_short;
Edouard@174
   759
            else if (
Edouard@174
   760
                (
Edouard@174
   761
                (   /* TODO pubkey_algo == RSA  */ 0)
Edouard@174
   762
                || (/* TODO pubkey_algo == RSA_E*/ 0)
Edouard@174
   763
                || (/* TODO pubkey_algo == RSA_S*/ 0)
Edouard@174
   764
                )
Edouard@174
   765
                && /* sk->length */0 == 1024
Edouard@174
   766
                )
Edouard@174
   767
                *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
Edouard@174
   768
Edouard@174
   769
            if (/* TODO invalid */ 1) {
Edouard@174
   770
                *comm_type = PEP_ct_key_b0rken;
Edouard@174
   771
                break;
Edouard@174
   772
            }
Edouard@174
   773
            if (/* TODO expired */ 1) {
Edouard@174
   774
                *comm_type = PEP_ct_key_expired;
Edouard@174
   775
                break;
Edouard@174
   776
            }
Edouard@175
   777
            if (/* TODO revoked*/ 1) {
Edouard@174
   778
                *comm_type = PEP_ct_key_revoked;
Edouard@174
   779
                break;
Edouard@174
   780
            }
Edouard@174
   781
        }
Edouard@174
   782
        *comm_type = PEP_ct_unknown;
Edouard@174
   783
        return PEP_OUT_OF_MEMORY;
Edouard@174
   784
        return PEP_UNKNOWN_ERROR;
Edouard@174
   785
Edouard@174
   786
Edouard@174
   787
    return status;
Edouard@174
   788
}
Edouard@210
   789
Edouard@210
   790
PEP_STATUS pgp_renew_key(
Edouard@210
   791
        PEP_SESSION session,
Edouard@210
   792
        const char *fpr,
Edouard@210
   793
        const timestamp *ts
Edouard@210
   794
    )
Edouard@210
   795
{
Edouard@210
   796
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@210
   797
    char date_text[12];
Edouard@210
   798
Edouard@210
   799
    assert(session);
Edouard@210
   800
    assert(fpr);
Edouard@210
   801
Edouard@210
   802
    snprintf(date_text, 12, "%.4d-%.2d-%.2d\n", ts->tm_year + 1900,
Edouard@210
   803
            ts->tm_mon + 1, ts->tm_mday);
Edouard@210
   804
Edouard@210
   805
Edouard@210
   806
        return PEP_UNKNOWN_ERROR;
Edouard@210
   807
    return PEP_STATUS_OK;
Edouard@210
   808
}
Edouard@210
   809
Edouard@226
   810
PEP_STATUS pgp_revoke_key(
Edouard@226
   811
        PEP_SESSION session,
Edouard@226
   812
        const char *fpr,
Edouard@226
   813
        const char *reason
Edouard@226
   814
    )
Edouard@210
   815
{
Edouard@210
   816
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@210
   817
    
Edouard@210
   818
    assert(session);
Edouard@210
   819
    assert(fpr);
Edouard@210
   820
Edouard@210
   821
        return PEP_UNKNOWN_ERROR;
Edouard@210
   822
Edouard@210
   823
    return PEP_STATUS_OK;
Edouard@210
   824
}
Edouard@210
   825
Edouard@226
   826
PEP_STATUS pgp_key_expired(
Edouard@226
   827
        PEP_SESSION session,
Edouard@226
   828
        const char *fpr,
Edouard@226
   829
        bool *expired
Edouard@226
   830
    )
Edouard@226
   831
{
Edouard@226
   832
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@226
   833
Edouard@226
   834
    assert(session);
Edouard@226
   835
    assert(fpr);
Edouard@226
   836
    assert(expired);
Edouard@226
   837
Edouard@226
   838
    *expired = false;
Edouard@226
   839
Edouard@226
   840
    if (status != PEP_STATUS_OK)
Edouard@226
   841
        return status;
Edouard@226
   842
Edouard@226
   843
    return PEP_STATUS_OK;
Edouard@226
   844
}
Edouard@226
   845