src/pgp_netpgp.c
author Edouard Tisserant
Wed, 06 May 2015 12:05:48 +0200
changeset 252 d0aa4a732456
parent 244 36abc78b7de5
child 254 710ff44d3cf0
permissions -rw-r--r--
netpgp : pEp session->ctx not anymore of type netpgp_t. netpgp_t instance is now static, protected by a single pthread_mutex. pEp session->ctx is now a struct containing per session resources such as curl handle.
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@228
    14
#include <netpgp/readerwriter.h>
Edouard@179
    15
Edouard@252
    16
#include <curl/curl.h>
Edouard@252
    17
#include <pthread.h>
Edouard@188
    18
#include <regex.h>
Edouard@188
    19
Edouard@185
    20
#define PEP_NETPGP_DEBUG
Edouard@185
    21
Edouard@252
    22
static netpgp_t netpgp;
Edouard@252
    23
static pthread_mutex_t netpgp_mutex = PTHREAD_MUTEX_INITIALIZER;
Edouard@252
    24
static pthread_mutex_t curl_mutex = PTHREAD_MUTEX_INITIALIZER;
Edouard@252
    25
Edouard@252
    26
Edouard@252
    27
Edouard@252
    28
PEP_STATUS enter_curl(PEP_SESSION session, CURL **curl){
Edouard@252
    29
}
Edouard@252
    30
Edouard@174
    31
PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
Edouard@174
    32
{
Edouard@174
    33
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@175
    34
    const char *home = NULL;
Edouard@179
    35
Edouard@179
    36
    assert(session);
Edouard@179
    37
    if(!session) return PEP_UNKNOWN_ERROR;
Edouard@179
    38
Edouard@252
    39
    if(pthread_mutex_init(&netpgp_mutex, NULL)){
Edouard@252
    40
        return PEP_OUT_OF_MEMORY;
Edouard@252
    41
    }
Edouard@252
    42
Edouard@252
    43
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
    44
        return PEP_UNKNOWN_ERROR;
Edouard@252
    45
    }
Edouard@174
    46
   
Edouard@174
    47
    if (in_first) {
Edouard@175
    48
        if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
Edouard@175
    49
            setlocale(LC_ALL, "");
Edouard@174
    50
Edouard@252
    51
        memset(&netpgp, 0x0, sizeof(netpgp_t));
Edouard@252
    52
Edouard@174
    53
Edouard@252
    54
        // netpgp_setvar(&netpgp, "max mem alloc", "4194304");
Edouard@252
    55
        netpgp_setvar(&netpgp, "need seckey", "1");
Edouard@252
    56
        netpgp_setvar(&netpgp, "need userid", "1");
Edouard@180
    57
Edouard@252
    58
        // NetPGP shares home with GPG
Edouard@252
    59
        home = gpg_home();
Edouard@252
    60
        if(home){
Edouard@252
    61
            netpgp_set_homedir(&netpgp,(char*)home, NULL, 0);
Edouard@252
    62
        }else{
Edouard@252
    63
            status = PEP_INIT_NO_GPG_HOME;
Edouard@252
    64
            goto unlock_netpgp;
Edouard@252
    65
        }
Edouard@252
    66
Edouard@252
    67
        // pair with gpg's cert-digest-algo
Edouard@252
    68
        netpgp_setvar(&netpgp, "hash", "SHA256");
Edouard@252
    69
Edouard@252
    70
        // subset of gpg's personal-cipher-preferences
Edouard@252
    71
        // here only one cipher can be selected
Edouard@252
    72
        netpgp_setvar(&netpgp, "cipher", "CAST5");
Edouard@252
    73
Edouard@252
    74
        if (!netpgp_init(&netpgp)) {
Edouard@252
    75
            status = PEP_INIT_NETPGP_INIT_FAILED;
Edouard@252
    76
            goto unlock_netpgp;
Edouard@252
    77
        }
Edouard@174
    78
    }
Edouard@174
    79
Edouard@252
    80
    status = PEP_STATUS_OK;
Edouard@175
    81
Edouard@252
    82
unlock_netpgp:
Edouard@252
    83
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@175
    84
Edouard@252
    85
    if(status != PEP_STATUS_OK){
Edouard@252
    86
        pgp_release(session, in_first);
Edouard@174
    87
    }
Edouard@174
    88
Edouard@174
    89
    return status;
Edouard@174
    90
}
Edouard@174
    91
Edouard@174
    92
void pgp_release(PEP_SESSION session, bool out_last)
Edouard@174
    93
{
Edouard@179
    94
    assert(session);
Edouard@179
    95
    if(!session) return;
Edouard@179
    96
Edouard@252
    97
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
    98
        return;
Edouard@252
    99
    }
Edouard@179
   100
Edouard@252
   101
    if (out_last){
Edouard@252
   102
        netpgp_end(&netpgp);
Edouard@252
   103
        memset(&netpgp, 0x0, sizeof(netpgp_t));
Edouard@252
   104
        pthread_mutex_destroy(&netpgp_mutex);
Edouard@252
   105
        return;
Edouard@252
   106
    }
Edouard@174
   107
Edouard@252
   108
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@175
   109
    // out_last unused here
Edouard@174
   110
}
Edouard@174
   111
Edouard@207
   112
// return 1 if the file contains ascii-armoured text 
Edouard@207
   113
// buf MUST be \0 terminated to be checked for armour
Edouard@188
   114
static unsigned
Edouard@188
   115
_armoured(const char *buf, size_t size, const char *pattern)
Edouard@188
   116
{
Edouard@188
   117
    unsigned armoured = 0;
Edouard@188
   118
    if(buf[size]=='\0'){
Edouard@188
   119
        regex_t r;
Edouard@188
   120
        regcomp(&r, pattern, REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
Edouard@188
   121
        if (regexec(&r, buf, 0, NULL, 0) == 0) {
Edouard@188
   122
            armoured = 1;
Edouard@188
   123
        }
Edouard@188
   124
        regfree(&r);
Edouard@188
   125
    }
Edouard@188
   126
    return armoured;
Edouard@188
   127
}
Edouard@188
   128
Edouard@227
   129
/* return key ID's hexdump as a string */
Edouard@227
   130
static void id_to_str(const uint8_t *userid, char *fpr)
Edouard@225
   131
{
Edouard@225
   132
    int i;
Edouard@225
   133
    static const char *hexes = "0123456789abcdef";
Edouard@225
   134
    for (i = 0; i < 8 ; i++) {
Edouard@225
   135
        fpr[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
Edouard@225
   136
        fpr[(i * 2) + 1] = hexes[userid[i] & 0xf];
Edouard@225
   137
    }
Edouard@225
   138
    fpr[8 * 2] = 0x0;
Edouard@225
   139
}
Edouard@225
   140
Edouard@185
   141
// Iterate through netpgp' reported valid signatures 
Edouard@185
   142
// fill a list of valid figerprints
Edouard@185
   143
// returns PEP_STATUS_OK if all sig reported valid
Edouard@185
   144
// error status otherwise.
Edouard@185
   145
static PEP_STATUS _validation_results(netpgp_t *netpgp, pgp_validation_t *vresult,
Edouard@185
   146
                                             stringlist_t **_keylist)
Edouard@185
   147
{
Edouard@188
   148
    time_t    now;
Edouard@188
   149
    time_t    t;
Edouard@188
   150
    char    buf[128];
Edouard@185
   151
Edouard@188
   152
    now = time(NULL);
Edouard@188
   153
    if (now < vresult->birthtime) {
Edouard@188
   154
        // signature is not valid yet
Edouard@185
   155
#ifdef PEP_NETPGP_DEBUG
Edouard@188
   156
        (void) printf(
Edouard@188
   157
            "signature not valid until %.24s\n",
Edouard@188
   158
            ctime(&vresult->birthtime));
Edouard@185
   159
#endif //PEP_NETPGP_DEBUG
Edouard@188
   160
        return PEP_UNENCRYPTED;
Edouard@188
   161
    }
Edouard@188
   162
    if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
Edouard@188
   163
        // signature has expired
Edouard@188
   164
        t = vresult->duration + vresult->birthtime;
Edouard@185
   165
#ifdef PEP_NETPGP_DEBUG
Edouard@188
   166
        (void) printf(
Edouard@188
   167
            "signature not valid after %.24s\n",
Edouard@188
   168
            ctime(&t));
Edouard@185
   169
#endif //PEP_NETPGP_DEBUG
Edouard@188
   170
        return PEP_UNENCRYPTED;
Edouard@188
   171
    }
Edouard@185
   172
    if (vresult->validc && vresult->valid_sigs &&
Edouard@185
   173
        !vresult->invalidc && !vresult->unknownc ) {
Edouard@185
   174
        unsigned    n;
Edouard@185
   175
        stringlist_t *k;
Edouard@185
   176
        // caller responsible to free
Edouard@185
   177
        *_keylist = new_stringlist(NULL);
Edouard@185
   178
        assert(*_keylist);
Edouard@185
   179
        if (*_keylist == NULL) {
Edouard@185
   180
            return PEP_OUT_OF_MEMORY;
Edouard@185
   181
        }
Edouard@185
   182
        k = *_keylist;
Edouard@185
   183
        for (n = 0; n < vresult->validc; ++n) {
Edouard@185
   184
            char id[MAX_ID_LENGTH + 1];
Edouard@185
   185
            const uint8_t *userid = vresult->valid_sigs[n].signer_id;
Edouard@185
   186
Edouard@185
   187
#ifdef PEP_NETPGP_DEBUG
Edouard@185
   188
            const pgp_key_t *key;
Edouard@185
   189
            pgp_pubkey_t *sigkey;
Edouard@188
   190
            unsigned from = 0;
Edouard@185
   191
            key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
Edouard@185
   192
                (const uint8_t *) vresult->valid_sigs[n].signer_id,
Edouard@185
   193
                &from, &sigkey);
Edouard@185
   194
            pgp_print_keydata(netpgp->io, netpgp->pubring, key, "valid signature ", &key->key.pubkey, 0);
Edouard@185
   195
#endif //PEP_NETPGP_DEBUG
Edouard@185
   196
Edouard@227
   197
            id_to_str(userid, id);
Edouard@185
   198
Edouard@185
   199
            k = stringlist_add(k, id);
Edouard@185
   200
            if(!k){
Edouard@185
   201
                free_stringlist(*_keylist);
Edouard@185
   202
                return PEP_OUT_OF_MEMORY;
Edouard@185
   203
            }
Edouard@185
   204
        }
Edouard@185
   205
        return PEP_STATUS_OK;
Edouard@185
   206
    }
Edouard@185
   207
    if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
Edouard@185
   208
        // No signatures found - is this memory signed?
Edouard@185
   209
        return PEP_VERIFY_NO_KEY; 
Edouard@185
   210
    } 
Edouard@185
   211
    
Edouard@185
   212
    if (vresult->invalidc) {
Edouard@185
   213
        // some invalid signatures
Edouard@185
   214
Edouard@185
   215
#ifdef PEP_NETPGP_DEBUG
Edouard@185
   216
        unsigned    n;
Edouard@185
   217
        for (n = 0; n < vresult->invalidc; ++n) {
Edouard@185
   218
            const pgp_key_t *key;
Edouard@185
   219
            pgp_pubkey_t *sigkey;
Edouard@185
   220
            unsigned from = 0;
Edouard@185
   221
            key = pgp_getkeybyid(netpgp->io, netpgp->pubring,
Edouard@185
   222
                (const uint8_t *) vresult->invalid_sigs[n].signer_id,
Edouard@185
   223
                &from, &sigkey);
Edouard@185
   224
            pgp_print_keydata(netpgp->io, netpgp->pubring, key, "invalid signature ", &key->key.pubkey, 0);
Edouard@188
   225
            if (sigkey->duration != 0 && now > sigkey->birthtime + sigkey->duration) {
Edouard@185
   226
                printf("EXPIRED !\n");
Edouard@185
   227
            }
Edouard@185
   228
        }
Edouard@185
   229
#endif //PEP_NETPGP_DEBUG
Edouard@185
   230
Edouard@185
   231
        return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
Edouard@185
   232
    }
Edouard@185
   233
    
Edouard@185
   234
    // only unknown sigs
Edouard@185
   235
    return PEP_DECRYPT_WRONG_FORMAT;
Edouard@185
   236
}
Edouard@185
   237
Edouard@207
   238
#define ARMOR_HEAD    "^-----BEGIN PGP MESSAGE-----\\s*$"
Edouard@174
   239
PEP_STATUS pgp_decrypt_and_verify(
Edouard@174
   240
    PEP_SESSION session, const char *ctext, size_t csize,
Edouard@174
   241
    char **ptext, size_t *psize, stringlist_t **keylist
Edouard@174
   242
    )
Edouard@174
   243
{
Edouard@185
   244
    pgp_memory_t *mem;
Edouard@185
   245
    pgp_memory_t *cat;
Edouard@185
   246
    pgp_validation_t *vresult;
Edouard@180
   247
    char *_ptext = NULL;
Edouard@180
   248
    size_t _psize = 0;
Edouard@185
   249
    int ret;
Edouard@179
   250
Edouard@174
   251
    PEP_STATUS result;
Edouard@174
   252
    stringlist_t *_keylist = NULL;
Edouard@174
   253
    int i_key = 0;
Edouard@174
   254
Edouard@174
   255
    assert(session);
Edouard@174
   256
    assert(ctext);
Edouard@174
   257
    assert(csize);
Edouard@174
   258
    assert(ptext);
Edouard@174
   259
    assert(psize);
Edouard@174
   260
    assert(keylist);
Edouard@174
   261
Edouard@179
   262
    if(!session || !ctext || !csize || !ptext || !psize || !keylist) 
Edouard@179
   263
        return PEP_UNKNOWN_ERROR;
Edouard@179
   264
Edouard@252
   265
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
   266
        return PEP_UNKNOWN_ERROR;
Edouard@252
   267
    }
Edouard@179
   268
Edouard@174
   269
    *ptext = NULL;
Edouard@174
   270
    *psize = 0;
Edouard@174
   271
    *keylist = NULL;
Edouard@174
   272
Edouard@183
   273
    vresult = malloc(sizeof(pgp_validation_t));
Edouard@185
   274
    memset(vresult, 0x0, sizeof(pgp_validation_t));
Edouard@182
   275
Edouard@252
   276
    mem = pgp_decrypt_and_validate_buf(netpgp.io, vresult, ctext, csize,
Edouard@252
   277
                netpgp.secring, netpgp.pubring,
Edouard@188
   278
                _armoured(ctext, csize, ARMOR_HEAD),
Edouard@179
   279
                0 /* sshkeys */,
Edouard@180
   280
                NULL, -1, NULL  /* pass fp,attempts,cb */);
Edouard@179
   281
    if (mem == NULL) {
Edouard@252
   282
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   283
        goto unlock_netpgp;
Edouard@179
   284
    }
Edouard@179
   285
Edouard@185
   286
    _psize = pgp_mem_len(mem);
Edouard@182
   287
    if (_psize){
Edouard@182
   288
        if ((_ptext = calloc(1, _psize)) == NULL) {
Edouard@183
   289
            result = PEP_OUT_OF_MEMORY;
Edouard@183
   290
            goto free_pgp;
Edouard@182
   291
        }
Edouard@185
   292
        memcpy(_ptext, pgp_mem_data(mem), _psize);
Edouard@182
   293
        result = PEP_DECRYPTED;
Edouard@182
   294
    }else{
Edouard@183
   295
        result = PEP_DECRYPT_NO_KEY;
Edouard@183
   296
        goto free_pgp;
Edouard@182
   297
    }
Edouard@180
   298
Edouard@185
   299
    if (result == PEP_DECRYPTED) {
Edouard@252
   300
        result = _validation_results(&netpgp, vresult, &_keylist);
Edouard@185
   301
        if (result != PEP_STATUS_OK) {
Edouard@185
   302
            goto free_ptext;
Edouard@183
   303
        }
Edouard@180
   304
        result = PEP_DECRYPTED_AND_VERIFIED;
Edouard@180
   305
    }
Edouard@174
   306
Edouard@180
   307
    if (result == PEP_DECRYPTED_AND_VERIFIED
Edouard@180
   308
        || result == PEP_DECRYPTED) {
Edouard@180
   309
        *ptext = _ptext;
Edouard@180
   310
        *psize = _psize;
Edouard@180
   311
        (*ptext)[*psize] = 0; // safeguard for naive users
Edouard@185
   312
        if (result == PEP_DECRYPTED_AND_VERIFIED) {
Edouard@185
   313
            *keylist = _keylist;
Edouard@185
   314
        }
Edouard@183
   315
Edouard@183
   316
        /* _ptext and _keylist ownership transfer, don't free */
Edouard@183
   317
        goto free_pgp;
Edouard@180
   318
    }
Edouard@183
   319
Edouard@183
   320
free_keylist:
Edouard@183
   321
    free_stringlist(_keylist);
Edouard@183
   322
Edouard@183
   323
free_ptext:
Edouard@183
   324
    free(_ptext);
Edouard@183
   325
Edouard@183
   326
free_pgp:
Edouard@185
   327
    pgp_memory_free(mem);
Edouard@183
   328
    pgp_validate_result_free(vresult);
Edouard@183
   329
Edouard@252
   330
unlock_netpgp:
Edouard@252
   331
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   332
Edouard@174
   333
    return result;
Edouard@174
   334
}
Edouard@174
   335
Edouard@207
   336
#define ARMOR_SIG_HEAD    "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----\\s*$"
Edouard@174
   337
PEP_STATUS pgp_verify_text(
Edouard@174
   338
    PEP_SESSION session, const char *text, size_t size,
Edouard@174
   339
    const char *signature, size_t sig_size, stringlist_t **keylist
Edouard@174
   340
    )
Edouard@174
   341
{
Edouard@185
   342
    pgp_memory_t *signedmem;
Edouard@185
   343
    pgp_memory_t *sig;
Edouard@185
   344
    pgp_validation_t *vresult;
Edouard@185
   345
Edouard@174
   346
    PEP_STATUS result;
Edouard@174
   347
    stringlist_t *_keylist;
Edouard@174
   348
Edouard@174
   349
    assert(session);
Edouard@174
   350
    assert(text);
Edouard@174
   351
    assert(size);
Edouard@174
   352
    assert(signature);
Edouard@174
   353
    assert(sig_size);
Edouard@174
   354
    assert(keylist);
Edouard@174
   355
Edouard@185
   356
    if(!session || !text || !size || !signature || !sig_size || !keylist) 
Edouard@185
   357
        return PEP_UNKNOWN_ERROR;
Edouard@185
   358
Edouard@252
   359
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
   360
        return PEP_UNKNOWN_ERROR;
Edouard@252
   361
    }
Edouard@185
   362
Edouard@174
   363
    *keylist = NULL;
Edouard@185
   364
Edouard@185
   365
    vresult = malloc(sizeof(pgp_validation_t));
Edouard@185
   366
    memset(vresult, 0x0, sizeof(pgp_validation_t));
Edouard@185
   367
Edouard@185
   368
    signedmem = pgp_memory_new();
Edouard@185
   369
    if (signedmem == NULL) {
Edouard@252
   370
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   371
        goto unlock_netpgp;
Edouard@185
   372
    }
Edouard@185
   373
    pgp_memory_add(signedmem, (const uint8_t*)text, size);
Edouard@185
   374
Edouard@185
   375
    sig = pgp_memory_new();
Edouard@185
   376
    if (sig == NULL) {
Edouard@185
   377
        pgp_memory_free(signedmem);
Edouard@252
   378
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   379
        goto unlock_netpgp;
Edouard@185
   380
    }
Edouard@185
   381
    pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
Edouard@185
   382
Edouard@252
   383
    pgp_validate_mem_detached(netpgp.io, vresult, sig,
Edouard@185
   384
                NULL,/* output */
Edouard@207
   385
                _armoured(signature, sig_size, ARMOR_SIG_HEAD),
Edouard@252
   386
                netpgp.pubring,
Edouard@185
   387
                signedmem);
Edouard@185
   388
Edouard@252
   389
    result = _validation_results(&netpgp, vresult, &_keylist);
Edouard@185
   390
    if (result != PEP_STATUS_OK) {
Edouard@185
   391
        goto free_pgp;
Edouard@185
   392
    }else{
Edouard@185
   393
        result = PEP_VERIFIED;
Edouard@185
   394
    }
Edouard@185
   395
Edouard@185
   396
    if (result == PEP_VERIFIED) {
Edouard@185
   397
        /* TODO : check trust level */
Edouard@185
   398
        result = PEP_VERIFIED_AND_TRUSTED;
Edouard@185
   399
    }
Edouard@185
   400
Edouard@185
   401
    if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
Edouard@185
   402
        *keylist = _keylist;
Edouard@185
   403
Edouard@185
   404
        /* _keylist ownership transfer, don't free */
Edouard@185
   405
        goto free_pgp;
Edouard@185
   406
    }
Edouard@185
   407
Edouard@185
   408
free_keylist:
Edouard@185
   409
    free_stringlist(_keylist);
Edouard@185
   410
Edouard@185
   411
free_pgp:
Edouard@187
   412
    // free done by pgp_validate_mem_detached
Edouard@187
   413
    // pgp_memory_free(sig);
Edouard@187
   414
    // pgp_memory_free(signedmem);
Edouard@185
   415
    pgp_validate_result_free(vresult);
Edouard@185
   416
Edouard@252
   417
unlock_netpgp:
Edouard@252
   418
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   419
Edouard@185
   420
    return result;
Edouard@174
   421
}
Edouard@174
   422
Edouard@174
   423
PEP_STATUS pgp_encrypt_and_sign(
Edouard@174
   424
    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
Edouard@174
   425
    size_t psize, char **ctext, size_t *csize
Edouard@174
   426
    )
Edouard@174
   427
{
Edouard@207
   428
    const pgp_key_t *keypair;
Edouard@207
   429
    pgp_seckey_t *seckey;
Edouard@209
   430
    pgp_memory_t *signedmem;
Edouard@209
   431
    pgp_memory_t *cmem;
Edouard@207
   432
    const char *userid;
Edouard@207
   433
    const char *hashalg;
Edouard@209
   434
    pgp_keyring_t *rcpts;
Edouard@207
   435
Edouard@174
   436
    PEP_STATUS result;
Edouard@174
   437
    const stringlist_t *_keylist;
Edouard@174
   438
Edouard@174
   439
    assert(session);
Edouard@174
   440
    assert(keylist);
Edouard@174
   441
    assert(ptext);
Edouard@174
   442
    assert(psize);
Edouard@174
   443
    assert(ctext);
Edouard@174
   444
    assert(csize);
Edouard@174
   445
Edouard@207
   446
    if(!session || !ptext || !psize || !ctext || !csize || !keylist) 
Edouard@207
   447
        return PEP_UNKNOWN_ERROR;
Edouard@207
   448
Edouard@252
   449
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
   450
        return PEP_UNKNOWN_ERROR;
Edouard@252
   451
    }
Edouard@208
   452
Edouard@174
   453
    *ctext = NULL;
Edouard@174
   454
    *csize = 0;
Edouard@174
   455
Edouard@207
   456
    // Get signing details from netpgp
Edouard@252
   457
    if ((userid = netpgp_getvar(&netpgp, "userid")) == NULL || 
Edouard@252
   458
        (keypair = pgp_getkeybyname(netpgp.io, netpgp.secring, userid)) == NULL ||
Edouard@207
   459
        (seckey = pgp_decrypt_seckey(keypair, NULL /*passfp*/)) == NULL) {
Edouard@207
   460
        return PEP_UNKNOWN_ERROR;
Edouard@207
   461
    }
Edouard@209
   462
Edouard@252
   463
    hashalg = netpgp_getvar(&netpgp, "hash");
Edouard@209
   464
    // netpgp (l)imitation - XXX why ? 
Edouard@207
   465
    if (seckey->pubkey.alg == PGP_PKA_DSA) {
Edouard@209
   466
        hashalg = "sha1";
Edouard@207
   467
    }
Edouard@207
   468
Edouard@207
   469
    // Sign data
Edouard@252
   470
    signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey,
Edouard@209
   471
                time(NULL), /* birthtime */
Edouard@209
   472
                0 /* duration */,
Edouard@209
   473
                hashalg, 
Edouard@207
   474
                0 /* armored */,
Edouard@207
   475
                0 /* cleartext */);
Edouard@207
   476
Edouard@207
   477
    pgp_forget(seckey, (unsigned)sizeof(*seckey));
Edouard@207
   478
Edouard@207
   479
    if (!signedmem) {
Edouard@252
   480
        result = PEP_UNENCRYPTED;
Edouard@252
   481
        goto unlock_netpgp;
Edouard@207
   482
    }
Edouard@207
   483
Edouard@207
   484
    // Encrypt signed data
Edouard@209
   485
    if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
Edouard@209
   486
        result = PEP_OUT_OF_MEMORY;
Edouard@209
   487
        goto free_signedmem;
Edouard@209
   488
    }
Edouard@209
   489
    for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
Edouard@174
   490
        assert(_keylist->value);
Edouard@209
   491
        // get key from netpgp's pubring
Edouard@209
   492
        const pgp_key_t *key;
Edouard@252
   493
        key = pgp_getkeybyname(netpgp.io,
Edouard@252
   494
                               netpgp.pubring,
Edouard@209
   495
                               _keylist->value);
Edouard@209
   496
Edouard@209
   497
        if(key == NULL){
Edouard@209
   498
            result = PEP_KEY_NOT_FOUND;
Edouard@209
   499
            goto free_rcpts;
Edouard@209
   500
        }
Edouard@209
   501
#ifdef PEP_NETPGP_DEBUG
Edouard@252
   502
        pgp_print_keydata(netpgp.io, netpgp.pubring, key,
Edouard@209
   503
                          "recipient pubkey ", &key->key.pubkey, 0);
Edouard@209
   504
#endif //PEP_NETPGP_DEBUG
Edouard@209
   505
Edouard@209
   506
        // add key to recipients/signers
Edouard@209
   507
        pgp_keyring_add(rcpts, key);
Edouard@209
   508
        if(rcpts->keys == NULL){
Edouard@209
   509
            result = PEP_OUT_OF_MEMORY;
Edouard@209
   510
            goto free_signedmem;
Edouard@209
   511
        }
Edouard@174
   512
    }
Edouard@174
   513
Edouard@252
   514
    cmem = pgp_encrypt_buf(netpgp.io, pgp_mem_data(signedmem),
Edouard@209
   515
            pgp_mem_len(signedmem), rcpts, 1 /* armored */,
Edouard@252
   516
            netpgp_getvar(&netpgp, "cipher"), 
Edouard@209
   517
            1 /* takes raw OpenPGP message */);
Edouard@209
   518
Edouard@209
   519
    if (cmem == NULL) {
Edouard@209
   520
        result = PEP_OUT_OF_MEMORY;
Edouard@209
   521
        goto free_signedmem;
Edouard@209
   522
    }else{
Edouard@209
   523
Edouard@209
   524
        char *_buffer = NULL;
Edouard@209
   525
        size_t length = pgp_mem_len(cmem);
Edouard@174
   526
Edouard@209
   527
        // Allocate transferable buffer
Edouard@209
   528
        _buffer = malloc(length + 1);
Edouard@209
   529
        assert(_buffer);
Edouard@209
   530
        if (_buffer == NULL) {
Edouard@209
   531
            result = PEP_OUT_OF_MEMORY;
Edouard@209
   532
            goto free_cmem;
Edouard@209
   533
        }
Edouard@209
   534
Edouard@209
   535
        memcpy(_buffer, pgp_mem_data(cmem), length);
Edouard@209
   536
Edouard@209
   537
        *ctext = _buffer;
Edouard@209
   538
        *csize = length;
Edouard@209
   539
        (*ctext)[*csize] = 0; // safeguard for naive users
Edouard@209
   540
        result = PEP_STATUS_OK;
Edouard@174
   541
    }
Edouard@174
   542
Edouard@209
   543
free_cmem :
Edouard@209
   544
    pgp_memory_free(cmem);
Edouard@209
   545
free_rcpts :
Edouard@209
   546
    pgp_keyring_free(rcpts);
Edouard@209
   547
free_signedmem :
Edouard@209
   548
    pgp_memory_free(signedmem);
Edouard@252
   549
unlock_netpgp:
Edouard@252
   550
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@175
   551
Edouard@174
   552
    return result;
Edouard@174
   553
}
Edouard@174
   554
Edouard@227
   555
/* return the hexdump as a string */
Edouard@227
   556
static unsigned
Edouard@227
   557
fpr_to_str (char **str, const uint8_t *fpr, size_t length)
Edouard@227
   558
{
Edouard@228
   559
    unsigned i;
Edouard@228
   560
    int	n;
Edouard@227
   561
Edouard@227
   562
    /* 5 char per byte (hexes + space) tuple -1 space at the end + null */
Edouard@227
   563
    *str = malloc((length / 2) * 5 - 1 + 1);
Edouard@227
   564
Edouard@227
   565
    if(*str == NULL)
Edouard@227
   566
        return 0;
Edouard@227
   567
Edouard@243
   568
    for (n = 0, i = 0 ; i < length - 2; i += 2) {
Edouard@243
   569
    	n += snprintf(&((*str)[n]), 6, "%02x%02x ", fpr[i], fpr[i+1]);
Edouard@228
   570
    }
Edouard@243
   571
    snprintf(&((*str)[n]), 5, "%02x%02x", fpr[i], fpr[i+1]);
Edouard@227
   572
Edouard@228
   573
    return 1;
Edouard@227
   574
}
Edouard@227
   575
Edouard@227
   576
static unsigned
Edouard@227
   577
str_to_fpr (const char *str, uint8_t *fpr, size_t *length)
Edouard@227
   578
{
Edouard@227
   579
    unsigned i,j;
Edouard@227
   580
Edouard@227
   581
    *length = 0;
Edouard@227
   582
Edouard@227
   583
    while(*str && *length < PGP_FINGERPRINT_SIZE){
Edouard@227
   584
        while (*str == ' ') str++;
Edouard@227
   585
        for (j = 0; j < 2; j++) {
Edouard@227
   586
            uint8_t *byte = &fpr[*length];
Edouard@243
   587
            *byte = 0;
Edouard@227
   588
            for (i = 0; i < 2; i++) {
Edouard@227
   589
                if (i > 0)
Edouard@243
   590
                    *byte = *byte << 4;
Edouard@227
   591
                if (*str >= 'a' && *str <= 'f')
Edouard@227
   592
                    *byte += 10 + *str - 'a';
Edouard@227
   593
                else if (*str >= 'A' && *str <= 'F')
Edouard@227
   594
                    *byte += 10 + *str - 'A';
Edouard@227
   595
                else if (*str >= '0' && *str <= '9')
Edouard@227
   596
                    *byte += *str - '0';
Edouard@227
   597
                else 
Edouard@227
   598
                    return 0;
Edouard@227
   599
                str++;
Edouard@227
   600
            }
Edouard@243
   601
            (*length)++;
Edouard@227
   602
        }
Edouard@227
   603
    }
Edouard@227
   604
    return 1;
Edouard@227
   605
}
Edouard@227
   606
Edouard@228
   607
static PEP_STATUS import_key_or_keypair(netpgp_t *netpgp, pgp_key_t *newkey){
Edouard@228
   608
    pgp_key_t	pubkey;
Edouard@228
   609
    unsigned public;
Edouard@228
   610
    PEP_STATUS result;
Edouard@243
   611
    
Edouard@228
   612
    if ((public = (newkey->type == PGP_PTAG_CT_PUBLIC_KEY))){
Edouard@228
   613
        pubkey = *newkey;
Edouard@228
   614
    } else {
Edouard@228
   615
        // Duplicate key as public only
Edouard@243
   616
        bzero(&pubkey, sizeof(pubkey));
Edouard@228
   617
        if (!pgp_keydata_dup(&pubkey, newkey, 1 /* make_public */)){
Edouard@228
   618
            return PEP_OUT_OF_MEMORY;
Edouard@228
   619
        }
Edouard@228
   620
    }
Edouard@228
   621
Edouard@252
   622
    // Append key to netpgp's rings (key ownership transfered)
Edouard@228
   623
    if (!public && !pgp_keyring_add(netpgp->secring, newkey)){
Edouard@228
   624
        result = PEP_OUT_OF_MEMORY;
Edouard@228
   625
        goto free_pubkey;
Edouard@228
   626
    } else if (!pgp_keyring_add(netpgp->pubring, &pubkey)){
Edouard@228
   627
        result = PEP_OUT_OF_MEMORY;
Edouard@228
   628
        goto pop_secring;
Edouard@228
   629
    }
Edouard@228
   630
Edouard@228
   631
    // save rings 
Edouard@228
   632
    if (netpgp_save_pubring(netpgp) && 
Edouard@228
   633
        (!public || netpgp_save_secring(netpgp)))
Edouard@228
   634
    {
Edouard@228
   635
        /* free nothing, everything transfered */
Edouard@228
   636
        return PEP_STATUS_OK;
Edouard@228
   637
    } else {
Edouard@228
   638
        /* XXX in case only pubring save succeed
Edouard@228
   639
         * pubring file is left as-is, but backup restore
Edouard@228
   640
         * could be attempted if such corner case matters */
Edouard@228
   641
        result = PEP_UNKNOWN_ERROR;
Edouard@228
   642
    }
Edouard@228
   643
Edouard@228
   644
pop_pubring:
Edouard@228
   645
    ((pgp_keyring_t *)netpgp->pubring)->keyc--;
Edouard@228
   646
pop_secring:
Edouard@228
   647
    ((pgp_keyring_t *)netpgp->secring)->keyc--;
Edouard@228
   648
free_pubkey:
Edouard@228
   649
    pgp_key_free(&pubkey);
Edouard@228
   650
Edouard@228
   651
    return result;
Edouard@228
   652
}
Edouard@228
   653
Edouard@174
   654
PEP_STATUS pgp_generate_keypair(
Edouard@174
   655
    PEP_SESSION session, pEp_identity *identity
Edouard@174
   656
    )
Edouard@174
   657
{
Edouard@228
   658
    pgp_key_t	newkey;
Edouard@225
   659
Edouard@225
   660
    PEP_STATUS result;
Edouard@228
   661
    char newid[1024];
Edouard@225
   662
    const char *hashalg;
Edouard@225
   663
    const char *cipher;
Edouard@228
   664
    char *fprstr = NULL;
Edouard@174
   665
Edouard@174
   666
    assert(session);
Edouard@174
   667
    assert(identity);
Edouard@174
   668
    assert(identity->address);
Edouard@174
   669
    assert(identity->fpr == NULL);
Edouard@174
   670
    assert(identity->username);
Edouard@174
   671
Edouard@225
   672
    if(!session || !identity || 
Edouard@225
   673
       !identity->address || identity->fpr || !identity->username)
Edouard@225
   674
        return PEP_UNKNOWN_ERROR;
Edouard@174
   675
Edouard@252
   676
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
   677
        return PEP_UNKNOWN_ERROR;
Edouard@252
   678
    }
Edouard@225
   679
Edouard@225
   680
    if(snprintf(newid, sizeof(newid),
Edouard@225
   681
        "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
Edouard@252
   682
        result =  PEP_BUFFER_TOO_SMALL;
Edouard@252
   683
        goto unlock_netpgp;
Edouard@174
   684
    }
Edouard@225
   685
    
Edouard@252
   686
    hashalg = netpgp_getvar(&netpgp, "hash");
Edouard@252
   687
    cipher = netpgp_getvar(&netpgp, "cipher");
Edouard@174
   688
Edouard@225
   689
    bzero(&newkey, sizeof(newkey));
Edouard@174
   690
Edouard@225
   691
    // Generate the key
Edouard@225
   692
    if (!pgp_rsa_generate_keypair(&newkey, 4096, 65537UL, hashalg, cipher,
Edouard@225
   693
                                  (const uint8_t *) "", (const size_t) 0) ||
Edouard@228
   694
        !pgp_add_selfsigned_userid(&newkey, (uint8_t *)newid)) {
Edouard@228
   695
        result = PEP_CANNOT_CREATE_KEY;
Edouard@228
   696
        goto free_newkey;
Edouard@228
   697
    }
Edouard@225
   698
Edouard@225
   699
    // TODO "Expire-Date: 1y\n";
Edouard@225
   700
Edouard@228
   701
    fpr_to_str(&fprstr,
Edouard@228
   702
               newkey.sigfingerprint.fingerprint,
Edouard@228
   703
               newkey.sigfingerprint.length);
Edouard@228
   704
    if (fprstr == NULL) {
Edouard@228
   705
        result = PEP_OUT_OF_MEMORY;
Edouard@228
   706
        goto free_newkey;
Edouard@228
   707
    } 
Edouard@174
   708
Edouard@252
   709
    result = import_key_or_keypair(&netpgp, &newkey);
Edouard@225
   710
Edouard@228
   711
    if (result == PEP_STATUS_OK) {
Edouard@228
   712
        identity->fpr = fprstr;
Edouard@228
   713
        /* free nothing, everything transfered */
Edouard@252
   714
        result = PEP_STATUS_OK;
Edouard@252
   715
        goto unlock_netpgp;
Edouard@225
   716
    }
Edouard@174
   717
Edouard@228
   718
free_fprstr:
Edouard@228
   719
    free(fprstr);
Edouard@228
   720
free_newkey:
Edouard@228
   721
    pgp_key_free(&newkey);
Edouard@252
   722
unlock_netpgp:
Edouard@252
   723
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@228
   724
Edouard@225
   725
    return result;
Edouard@174
   726
}
Edouard@174
   727
Edouard@227
   728
PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr)
Edouard@174
   729
{
Edouard@227
   730
    uint8_t fpr[PGP_FINGERPRINT_SIZE];
Edouard@227
   731
    size_t length;
Edouard@227
   732
    unsigned res;
Edouard@227
   733
Edouard@227
   734
    PEP_STATUS result;
Edouard@227
   735
Edouard@174
   736
    assert(session);
Edouard@174
   737
    assert(fpr);
Edouard@174
   738
Edouard@227
   739
    if (!session || !fpr)
Edouard@174
   740
        return PEP_UNKNOWN_ERROR;
Edouard@174
   741
Edouard@252
   742
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
   743
        return PEP_UNKNOWN_ERROR;
Edouard@252
   744
    }
Edouard@227
   745
    
Edouard@227
   746
    if (str_to_fpr(fprstr, fpr, &length)) {
Edouard@252
   747
        unsigned insec = pgp_deletekeybyfpr(netpgp.io,
Edouard@252
   748
                                (pgp_keyring_t *)netpgp.secring, 
Edouard@244
   749
                                (const uint8_t *)fpr, length);
Edouard@252
   750
        unsigned inpub = pgp_deletekeybyfpr(netpgp.io,
Edouard@252
   751
                                (pgp_keyring_t *)netpgp.pubring, 
Edouard@244
   752
                                (const uint8_t *)fpr, length);
Edouard@244
   753
        if(!insec && !inpub){
Edouard@244
   754
            result = PEP_KEY_NOT_FOUND;
Edouard@252
   755
            goto unlock_netpgp;
Edouard@244
   756
        } else {
Edouard@244
   757
            result = PEP_STATUS_OK;
Edouard@227
   758
        }
Edouard@227
   759
    }else{
Edouard@252
   760
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   761
        goto unlock_netpgp;
Edouard@227
   762
    }
Edouard@174
   763
Edouard@227
   764
    // save rings (key ownership transfered)
Edouard@252
   765
    if (netpgp_save_pubring(&netpgp) && 
Edouard@252
   766
        netpgp_save_secring(&netpgp))
Edouard@227
   767
    {
Edouard@227
   768
        result = PEP_STATUS_OK;
Edouard@227
   769
    }else{
Edouard@227
   770
        result = PEP_UNKNOWN_ERROR;
Edouard@227
   771
    }
Edouard@227
   772
Edouard@252
   773
unlock_netpgp:
Edouard@252
   774
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   775
Edouard@227
   776
    return result;
Edouard@174
   777
}
Edouard@174
   778
Edouard@228
   779
#define ARMOR_KEY_HEAD    "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----\\s*$"
Edouard@179
   780
PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data, size_t size)
Edouard@174
   781
{
Edouard@228
   782
Edouard@228
   783
    pgp_memory_t *mem;
Edouard@228
   784
    pgp_keyring_t tmpring;
Edouard@228
   785
Edouard@228
   786
    PEP_STATUS result;
Edouard@228
   787
Edouard@174
   788
    assert(session);
Edouard@174
   789
    assert(key_data);
Edouard@174
   790
Edouard@228
   791
    if(!session || !key_data) 
Edouard@174
   792
        return PEP_UNKNOWN_ERROR;
Edouard@228
   793
Edouard@252
   794
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
   795
        return PEP_UNKNOWN_ERROR;
Edouard@252
   796
    }
Edouard@228
   797
Edouard@228
   798
    mem = pgp_memory_new();
Edouard@228
   799
    if (mem == NULL) {
Edouard@252
   800
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   801
        goto unlock_netpgp;
Edouard@228
   802
    }
Edouard@228
   803
    pgp_memory_add(mem, (const uint8_t*)key_data, size);
Edouard@228
   804
Edouard@244
   805
    bzero(&tmpring, sizeof(tmpring));
Edouard@244
   806
Edouard@252
   807
    if (pgp_keyring_read_from_mem(netpgp.io, &tmpring, 
Edouard@228
   808
                                  _armoured(key_data, size, ARMOR_KEY_HEAD),
Edouard@228
   809
                                  mem) == 0){
Edouard@228
   810
        result = PEP_ILLEGAL_VALUE;
Edouard@228
   811
    }else if (tmpring.keyc == 0){
Edouard@228
   812
        result = PEP_UNKNOWN_ERROR;
Edouard@228
   813
    }else if (tmpring.keyc > 1){
Edouard@228
   814
        /* too many keys given */
Edouard@252
   815
        /* XXX TODO accept many */
Edouard@228
   816
        result = PEP_ILLEGAL_VALUE;
Edouard@228
   817
    }else{
Edouard@252
   818
        result = import_key_or_keypair(&netpgp, &tmpring.keys[0]);
Edouard@228
   819
    }
Edouard@228
   820
    
Edouard@228
   821
    pgp_memory_free(mem);
Edouard@228
   822
Edouard@244
   823
    if (result == PEP_STATUS_OK){
Edouard@244
   824
        pgp_keyring_free(&tmpring);
Edouard@244
   825
    }else{
Edouard@228
   826
        pgp_keyring_purge(&tmpring);
Edouard@228
   827
    }
Edouard@228
   828
Edouard@252
   829
unlock_netpgp:
Edouard@252
   830
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   831
Edouard@228
   832
    return result;
Edouard@174
   833
}
Edouard@174
   834
Edouard@179
   835
PEP_STATUS pgp_export_keydata(
Edouard@228
   836
    PEP_SESSION session, const char *fprstr, char **key_data, size_t *size
Edouard@174
   837
    )
Edouard@174
   838
{
Edouard@228
   839
    pgp_key_t *key;
Edouard@228
   840
	pgp_output_t *output;
Edouard@228
   841
    pgp_memory_t *mem;
Edouard@228
   842
    uint8_t fpr[PGP_FINGERPRINT_SIZE];
Edouard@228
   843
    size_t fprlen;
Edouard@228
   844
Edouard@228
   845
    PEP_STATUS result;
Edouard@174
   846
    char *buffer;
Edouard@228
   847
    size_t buflen;
Edouard@174
   848
Edouard@174
   849
    assert(session);
Edouard@243
   850
    assert(fprstr);
Edouard@174
   851
    assert(key_data);
Edouard@174
   852
    assert(size);
Edouard@174
   853
Edouard@243
   854
    if (!session || !fprstr || !key_data || !size)
Edouard@174
   855
        return PEP_UNKNOWN_ERROR;
Edouard@174
   856
Edouard@252
   857
    if(pthread_mutex_lock(&netpgp_mutex)){;
Edouard@252
   858
        return PEP_UNKNOWN_ERROR;
Edouard@252
   859
    }
Edouard@252
   860
Edouard@228
   861
    if (str_to_fpr(fprstr, fpr, &fprlen)) {
Edouard@228
   862
        unsigned from = 0;
Edouard@252
   863
        if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring, 
Edouard@228
   864
                                                fpr, fprlen,
Edouard@228
   865
                                                &from, NULL)) == NULL) {
Edouard@252
   866
            result = PEP_KEY_NOT_FOUND;
Edouard@252
   867
            goto unlock_netpgp;
Edouard@228
   868
        }
Edouard@228
   869
    }else{
Edouard@252
   870
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   871
        goto unlock_netpgp;
Edouard@228
   872
    }
Edouard@228
   873
    
Edouard@228
   874
	pgp_setup_memory_write(&output, &mem, 128);
Edouard@174
   875
Edouard@228
   876
    if (mem == NULL || output == NULL) {
Edouard@252
   877
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   878
        goto unlock_netpgp;
Edouard@174
   879
    }
Edouard@174
   880
Edouard@228
   881
    if (!pgp_write_xfer_pubkey(output, key, 1)) {
Edouard@228
   882
        result = PEP_UNKNOWN_ERROR;
Edouard@228
   883
        goto free_mem;
Edouard@228
   884
    }
Edouard@228
   885
Edouard@228
   886
    buffer = NULL;
Edouard@228
   887
    buflen = pgp_mem_len(mem);
Edouard@228
   888
Edouard@228
   889
    // Allocate transferable buffer
Edouard@228
   890
    buffer = malloc(buflen + 1);
Edouard@228
   891
    assert(buffer);
Edouard@228
   892
    if (buffer == NULL) {
Edouard@228
   893
        result = PEP_OUT_OF_MEMORY;
Edouard@228
   894
        goto free_mem;
Edouard@228
   895
    }
Edouard@228
   896
Edouard@228
   897
    memcpy(buffer, pgp_mem_data(mem), buflen);
Edouard@174
   898
Edouard@174
   899
    *key_data = buffer;
Edouard@228
   900
    *size = buflen;
Edouard@228
   901
    (*key_data)[*size] = 0; // safeguard for naive users
Edouard@228
   902
    result = PEP_STATUS_OK;
Edouard@174
   903
Edouard@228
   904
free_mem :
Edouard@228
   905
	pgp_teardown_memory_write(output, mem);
Edouard@252
   906
unlock_netpgp:
Edouard@252
   907
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@228
   908
Edouard@228
   909
    return result;
Edouard@174
   910
}
Edouard@174
   911
Edouard@175
   912
// "keyserver"
Edouard@175
   913
// "hkp://keys.gnupg.net"
Edouard@174
   914
PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
Edouard@174
   915
{
Edouard@174
   916
    assert(session);
Edouard@174
   917
    assert(pattern);
Edouard@174
   918
Edouard@252
   919
    CURL *curl;
Edouard@252
   920
    curl = session->ctx.curl;
Edouard@252
   921
Edouard@174
   922
    /* TODO ask for key */
Edouard@174
   923
        return PEP_UNKNOWN_ERROR;
Edouard@174
   924
        return PEP_GET_KEY_FAILED;
Edouard@174
   925
Edouard@174
   926
    do {
Edouard@174
   927
Edouard@174
   928
        /* For each key */
Edouard@174
   929
        /* import key */
Edouard@174
   930
    } while (0);
Edouard@174
   931
Edouard@174
   932
    return PEP_STATUS_OK;
Edouard@174
   933
}
Edouard@174
   934
Edouard@174
   935
PEP_STATUS pgp_find_keys(
Edouard@174
   936
    PEP_SESSION session, const char *pattern, stringlist_t **keylist
Edouard@174
   937
    )
Edouard@174
   938
{
Edouard@174
   939
    stringlist_t *_keylist;
Edouard@174
   940
    char *fpr;
Edouard@174
   941
Edouard@174
   942
    assert(session);
Edouard@174
   943
    assert(pattern);
Edouard@174
   944
    assert(keylist);
Edouard@174
   945
Edouard@174
   946
    *keylist = NULL;
Edouard@174
   947
Edouard@174
   948
    /* Ask for key */
Edouard@174
   949
        return PEP_UNKNOWN_ERROR;
Edouard@174
   950
        return PEP_GET_KEY_FAILED;
Edouard@174
   951
Edouard@174
   952
    _keylist = new_stringlist(NULL);
Edouard@174
   953
    stringlist_t *_k = _keylist;
Edouard@174
   954
Edouard@174
   955
    do {
Edouard@174
   956
            fpr = "TODO key->subkeys->fpr";
Edouard@174
   957
            assert(fpr);
Edouard@174
   958
            _k = stringlist_add(_k, fpr);
Edouard@174
   959
            assert(_k);
Edouard@174
   960
            if (_k == NULL){
Edouard@174
   961
                free_stringlist(_keylist);
Edouard@174
   962
                return PEP_OUT_OF_MEMORY;
Edouard@174
   963
            }
Edouard@174
   964
    } while (0);
Edouard@174
   965
Edouard@174
   966
    *keylist = _keylist;
Edouard@174
   967
    return PEP_STATUS_OK;
Edouard@174
   968
}
Edouard@174
   969
Edouard@174
   970
PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
Edouard@174
   971
{
Edouard@174
   972
    assert(session);
Edouard@174
   973
    assert(pattern);
Edouard@174
   974
Edouard@174
   975
    /* TODO send key */
Edouard@174
   976
Edouard@174
   977
        return PEP_CANNOT_SEND_KEY;
Edouard@174
   978
        return PEP_STATUS_OK;
Edouard@174
   979
}
Edouard@174
   980
Edouard@174
   981
Edouard@174
   982
PEP_STATUS pgp_get_key_rating(
Edouard@174
   983
    PEP_SESSION session,
Edouard@174
   984
    const char *fpr,
Edouard@174
   985
    PEP_comm_type *comm_type
Edouard@174
   986
    )
Edouard@174
   987
{
Edouard@174
   988
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@174
   989
Edouard@174
   990
    assert(session);
Edouard@174
   991
    assert(fpr);
Edouard@174
   992
    assert(comm_type);
Edouard@174
   993
Edouard@174
   994
    *comm_type = PEP_ct_unknown;
Edouard@174
   995
Edouard@174
   996
    /* TODO get key from fpr */
Edouard@174
   997
    return PEP_UNKNOWN_ERROR;
Edouard@174
   998
    return PEP_GET_KEY_FAILED;
Edouard@174
   999
Edouard@174
  1000
    switch (/*TODO key->protocol*/ 4) {
Edouard@174
  1001
    case /* TODO  OpenPGP */0:
Edouard@174
  1002
    case /* TODO DEFAULT */1:
Edouard@174
  1003
        *comm_type = PEP_ct_OpenPGP_unconfirmed;
Edouard@174
  1004
        break;
Edouard@174
  1005
    case /* TODO CMS */2:
Edouard@174
  1006
        *comm_type = PEP_ct_CMS_unconfirmed;
Edouard@174
  1007
        break;
Edouard@174
  1008
    default:
Edouard@174
  1009
        *comm_type = PEP_ct_unknown;
Edouard@174
  1010
        return PEP_STATUS_OK;
Edouard@174
  1011
    }
Edouard@174
  1012
Edouard@174
  1013
        for (; 1 == 0; /* Each subkeys */ ) {
Edouard@174
  1014
            if (/* TODO length */0 < 1024)
Edouard@174
  1015
                *comm_type = PEP_ct_key_too_short;
Edouard@174
  1016
            else if (
Edouard@174
  1017
                (
Edouard@174
  1018
                (   /* TODO pubkey_algo == RSA  */ 0)
Edouard@174
  1019
                || (/* TODO pubkey_algo == RSA_E*/ 0)
Edouard@174
  1020
                || (/* TODO pubkey_algo == RSA_S*/ 0)
Edouard@174
  1021
                )
Edouard@174
  1022
                && /* sk->length */0 == 1024
Edouard@174
  1023
                )
Edouard@174
  1024
                *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
Edouard@174
  1025
Edouard@174
  1026
            if (/* TODO invalid */ 1) {
Edouard@174
  1027
                *comm_type = PEP_ct_key_b0rken;
Edouard@174
  1028
                break;
Edouard@174
  1029
            }
Edouard@174
  1030
            if (/* TODO expired */ 1) {
Edouard@174
  1031
                *comm_type = PEP_ct_key_expired;
Edouard@174
  1032
                break;
Edouard@174
  1033
            }
Edouard@175
  1034
            if (/* TODO revoked*/ 1) {
Edouard@174
  1035
                *comm_type = PEP_ct_key_revoked;
Edouard@174
  1036
                break;
Edouard@174
  1037
            }
Edouard@174
  1038
        }
Edouard@174
  1039
        *comm_type = PEP_ct_unknown;
Edouard@174
  1040
        return PEP_OUT_OF_MEMORY;
Edouard@174
  1041
        return PEP_UNKNOWN_ERROR;
Edouard@174
  1042
Edouard@174
  1043
Edouard@174
  1044
    return status;
Edouard@174
  1045
}
Edouard@210
  1046
Edouard@210
  1047
PEP_STATUS pgp_renew_key(
Edouard@210
  1048
        PEP_SESSION session,
Edouard@210
  1049
        const char *fpr,
Edouard@210
  1050
        const timestamp *ts
Edouard@210
  1051
    )
Edouard@210
  1052
{
Edouard@210
  1053
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@210
  1054
    char date_text[12];
Edouard@210
  1055
Edouard@210
  1056
    assert(session);
Edouard@210
  1057
    assert(fpr);
Edouard@210
  1058
Edouard@210
  1059
    snprintf(date_text, 12, "%.4d-%.2d-%.2d\n", ts->tm_year + 1900,
Edouard@210
  1060
            ts->tm_mon + 1, ts->tm_mday);
Edouard@210
  1061
Edouard@210
  1062
Edouard@210
  1063
        return PEP_UNKNOWN_ERROR;
Edouard@210
  1064
    return PEP_STATUS_OK;
Edouard@210
  1065
}
Edouard@210
  1066
Edouard@226
  1067
PEP_STATUS pgp_revoke_key(
Edouard@226
  1068
        PEP_SESSION session,
Edouard@226
  1069
        const char *fpr,
Edouard@226
  1070
        const char *reason
Edouard@226
  1071
    )
Edouard@210
  1072
{
Edouard@210
  1073
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@210
  1074
    
Edouard@210
  1075
    assert(session);
Edouard@210
  1076
    assert(fpr);
Edouard@210
  1077
Edouard@210
  1078
        return PEP_UNKNOWN_ERROR;
Edouard@210
  1079
Edouard@210
  1080
    return PEP_STATUS_OK;
Edouard@210
  1081
}
Edouard@210
  1082
Edouard@226
  1083
PEP_STATUS pgp_key_expired(
Edouard@226
  1084
        PEP_SESSION session,
Edouard@226
  1085
        const char *fpr,
Edouard@226
  1086
        bool *expired
Edouard@226
  1087
    )
Edouard@226
  1088
{
Edouard@226
  1089
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@226
  1090
Edouard@226
  1091
    assert(session);
Edouard@226
  1092
    assert(fpr);
Edouard@226
  1093
    assert(expired);
Edouard@226
  1094
Edouard@226
  1095
    *expired = false;
Edouard@226
  1096
Edouard@226
  1097
    if (status != PEP_STATUS_OK)
Edouard@226
  1098
        return status;
Edouard@226
  1099
Edouard@226
  1100
    return PEP_STATUS_OK;
Edouard@226
  1101
}
Edouard@226
  1102