src/pgp_netpgp.c
author Edouard Tisserant
Sat, 13 Jun 2015 02:37:10 +0200
changeset 318 9e32ec25bf12
parent 316 db2bad72a93b
child 321 814faa0be78b
permissions -rw-r--r--
netpgp : pgp_send_key. Triggers server internal error (500), ignored
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@252
    20
static netpgp_t netpgp;
Edouard@254
    21
static pthread_mutex_t netpgp_mutex;
Edouard@252
    22
Edouard@263
    23
static PEP_STATUS init_netpgp()
Edouard@174
    24
{
Edouard@174
    25
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@175
    26
    const char *home = NULL;
Edouard@179
    27
Edouard@252
    28
    if(pthread_mutex_init(&netpgp_mutex, NULL)){
Edouard@252
    29
        return PEP_OUT_OF_MEMORY;
Edouard@252
    30
    }
Edouard@252
    31
Edouard@263
    32
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
    33
        return PEP_UNKNOWN_ERROR;
Edouard@252
    34
    }
Edouard@174
    35
Edouard@263
    36
    if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
Edouard@263
    37
        setlocale(LC_ALL, "");
Edouard@174
    38
Edouard@263
    39
    memset(&netpgp, 0x0, sizeof(netpgp_t));
Edouard@180
    40
Edouard@263
    41
    // netpgp_setvar(&netpgp, "max mem alloc", "4194304");
Edouard@263
    42
    netpgp_setvar(&netpgp, "need seckey", "1");
Edouard@315
    43
    // netpgp_setvar(&netpgp, "need userid", "1");
Edouard@252
    44
Edouard@263
    45
    // NetPGP shares home with GPG
Edouard@263
    46
    home = gpg_home();
Edouard@263
    47
    if(home){
Edouard@263
    48
        netpgp_set_homedir(&netpgp,(char*)home, NULL, 0);
Edouard@263
    49
    }else{
Edouard@263
    50
        status = PEP_INIT_NO_GPG_HOME;
Edouard@263
    51
        goto unlock_netpgp;
Edouard@174
    52
    }
Edouard@174
    53
Edouard@263
    54
    // pair with gpg's cert-digest-algo
Edouard@263
    55
    netpgp_setvar(&netpgp, "hash", "SHA256");
Edouard@263
    56
Edouard@263
    57
    // subset of gpg's personal-cipher-preferences
Edouard@263
    58
    // here only one cipher can be selected
Edouard@263
    59
    netpgp_setvar(&netpgp, "cipher", "CAST5");
Edouard@263
    60
Edouard@263
    61
    if (!netpgp_init(&netpgp)) {
Edouard@263
    62
        status = PEP_INIT_NETPGP_INIT_FAILED;
Edouard@263
    63
        goto unlock_netpgp;
Edouard@263
    64
    }
Edouard@175
    65
Edouard@315
    66
    // netpgp_set_debug("packet-parse.c");
Edouard@315
    67
Edouard@252
    68
unlock_netpgp:
Edouard@252
    69
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@263
    70
    
Edouard@263
    71
    return status;
Edouard@263
    72
}
Edouard@175
    73
Edouard@263
    74
static void release_netpgp()
Edouard@263
    75
{
Edouard@263
    76
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@263
    77
        return;
Edouard@263
    78
    }
Edouard@263
    79
    netpgp_end(&netpgp);
Edouard@263
    80
    memset(&netpgp, 0x0, sizeof(netpgp_t));
Edouard@263
    81
Edouard@263
    82
    pthread_mutex_destroy(&netpgp_mutex);
Edouard@263
    83
Edouard@263
    84
    return;
Edouard@263
    85
}
Edouard@263
    86
Edouard@263
    87
static PEP_STATUS init_curl(
Edouard@263
    88
    CURL **curl,
Edouard@263
    89
    pthread_mutex_t *curl_mutex,
Edouard@263
    90
    bool in_first)
Edouard@263
    91
{
Edouard@263
    92
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@263
    93
    struct curl_slist *headers=NULL;
Edouard@263
    94
Edouard@263
    95
    if(pthread_mutex_init(curl_mutex, NULL)){
Edouard@263
    96
        return PEP_OUT_OF_MEMORY;
Edouard@263
    97
    }
Edouard@263
    98
Edouard@263
    99
    if(pthread_mutex_lock(curl_mutex)){
Edouard@263
   100
        return PEP_UNKNOWN_ERROR;
Edouard@263
   101
    }
Edouard@263
   102
Edouard@263
   103
    if(in_first){
Edouard@263
   104
        curl_global_init(CURL_GLOBAL_DEFAULT);
Edouard@263
   105
    }
Edouard@263
   106
Edouard@263
   107
    if ((*curl = curl_easy_init()) == NULL) {
Edouard@263
   108
        return PEP_OUT_OF_MEMORY;
Edouard@263
   109
    }
Edouard@263
   110
Edouard@263
   111
    curl_easy_setopt(*curl, CURLOPT_FOLLOWLOCATION, 1L);
Edouard@263
   112
    curl_easy_setopt(*curl, CURLOPT_MAXREDIRS, 3L);
Edouard@263
   113
Edouard@263
   114
    headers=curl_slist_append(headers,"Pragma: no-cache");
Edouard@263
   115
    if(headers)
Edouard@263
   116
        headers=curl_slist_append(headers,"Cache-Control: no-cache");
Edouard@263
   117
Edouard@263
   118
    if(!headers)
Edouard@263
   119
    {
Edouard@263
   120
        status = PEP_OUT_OF_MEMORY;
Edouard@263
   121
        goto unlock_curl;
Edouard@174
   122
    }
Edouard@174
   123
Edouard@263
   124
    curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
Edouard@263
   125
    curl_slist_free_all(headers);
Edouard@263
   126
Edouard@263
   127
    // TODO curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
Edouard@263
   128
Edouard@263
   129
unlock_curl:
Edouard@263
   130
    pthread_mutex_unlock(curl_mutex);
Edouard@174
   131
    return status;
Edouard@174
   132
}
Edouard@174
   133
Edouard@263
   134
static void release_curl(
Edouard@263
   135
    CURL **curl,
Edouard@263
   136
    pthread_mutex_t *curl_mutex, 
Edouard@263
   137
    bool out_last)
Edouard@263
   138
{
Edouard@263
   139
    if(pthread_mutex_lock(curl_mutex)){
Edouard@263
   140
        return;
Edouard@263
   141
    }
Edouard@263
   142
Edouard@263
   143
    if(*curl)
Edouard@263
   144
        curl_easy_cleanup(*curl);
Edouard@263
   145
Edouard@263
   146
    *curl = NULL;
Edouard@263
   147
Edouard@263
   148
    if(out_last){
Edouard@263
   149
        curl_global_cleanup();
Edouard@263
   150
    }
Edouard@263
   151
Edouard@263
   152
    pthread_mutex_destroy(curl_mutex);
Edouard@263
   153
Edouard@263
   154
    return;
Edouard@263
   155
}
Edouard@263
   156
Edouard@263
   157
PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
Edouard@263
   158
{
Edouard@263
   159
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@263
   160
Edouard@263
   161
    assert(session);
Edouard@263
   162
    if(!session) return PEP_UNKNOWN_ERROR;
Edouard@263
   163
Edouard@263
   164
    if (in_first) {
Edouard@263
   165
        if((status = init_netpgp()) != PEP_STATUS_OK)
Edouard@263
   166
        return status;
Edouard@263
   167
    }
Edouard@263
   168
Edouard@263
   169
    if((status = init_curl(
Edouard@263
   170
                    &session->ctx.curl,
Edouard@263
   171
                    &session->ctx.curl_mutex,
Edouard@263
   172
                    in_first) != PEP_STATUS_OK)){
Edouard@263
   173
        if(in_first) release_netpgp();
Edouard@263
   174
        return status;
Edouard@263
   175
    }
Edouard@263
   176
Edouard@263
   177
    return PEP_STATUS_OK;
Edouard@263
   178
}
Edouard@263
   179
Edouard@174
   180
void pgp_release(PEP_SESSION session, bool out_last)
Edouard@174
   181
{
Edouard@179
   182
    assert(session);
Edouard@179
   183
    if(!session) return;
Edouard@179
   184
Edouard@263
   185
    if (out_last){
Edouard@263
   186
        release_netpgp();
Edouard@252
   187
    }
Edouard@263
   188
    release_curl(&session->ctx.curl, &session->ctx.curl_mutex, out_last);
Edouard@174
   189
}
Edouard@174
   190
Edouard@207
   191
// return 1 if the file contains ascii-armoured text 
Edouard@207
   192
// buf MUST be \0 terminated to be checked for armour
Edouard@188
   193
static unsigned
Edouard@188
   194
_armoured(const char *buf, size_t size, const char *pattern)
Edouard@188
   195
{
Edouard@188
   196
    unsigned armoured = 0;
Edouard@188
   197
    if(buf[size]=='\0'){
Edouard@188
   198
        regex_t r;
Edouard@188
   199
        regcomp(&r, pattern, REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
Edouard@188
   200
        if (regexec(&r, buf, 0, NULL, 0) == 0) {
Edouard@188
   201
            armoured = 1;
Edouard@188
   202
        }
Edouard@188
   203
        regfree(&r);
Edouard@188
   204
    }
Edouard@188
   205
    return armoured;
Edouard@188
   206
}
Edouard@188
   207
Edouard@316
   208
/* write key ID's hexdump as a string */
Edouard@315
   209
static void id_to_str(const uint8_t *keyid, char *str)
Edouard@225
   210
{
Edouard@225
   211
    int i;
Edouard@225
   212
    static const char *hexes = "0123456789abcdef";
Edouard@315
   213
    for (i = 0; i < PGP_KEY_ID_SIZE ; i++) {
Edouard@315
   214
        str[i * 2] = hexes[(unsigned)(keyid[i] & 0xf0) >> 4];
Edouard@315
   215
        str[(i * 2) + 1] = hexes[keyid[i] & 0xf];
Edouard@225
   216
    }
Edouard@315
   217
    str[PGP_KEY_ID_SIZE * 2] = 0x0;
Edouard@315
   218
}
Edouard@315
   219
Edouard@316
   220
/* write key ID bytes read from hex string 
Edouard@316
   221
 * tolerates no space, only hexes */
Edouard@315
   222
static unsigned str_to_id(uint8_t *keyid, const char *str)
Edouard@315
   223
{
Edouard@315
   224
    int i, n;
Edouard@315
   225
    for (i = 0; i < PGP_KEY_ID_SIZE ; i++) {
Edouard@315
   226
        uint8_t b = 0;
Edouard@315
   227
        for (n = 0; n < 2; n++) {
Edouard@315
   228
            char c = str[i * 2 + n];
Edouard@315
   229
            uint8_t q;
Edouard@315
   230
            if(c >= '0' &&  c <= '9'){
Edouard@315
   231
                q = (c - '0');
Edouard@316
   232
            }else if(c >= 'a' &&  c <= 'f'){
Edouard@315
   233
                q = (c - 'a' + 0xA);
Edouard@316
   234
            }else if(c >= 'A' &&  c <= 'F'){
Edouard@315
   235
                q = (c - 'A' + 0xA);
Edouard@315
   236
            }else{
Edouard@315
   237
                return 0;
Edouard@315
   238
            }
Edouard@315
   239
            b |= q << (4 * (1 - n));
Edouard@315
   240
        }
Edouard@315
   241
        keyid[i] = b;
Edouard@315
   242
    }
Edouard@315
   243
    return 1;
Edouard@225
   244
}
Edouard@225
   245
Edouard@185
   246
// Iterate through netpgp' reported valid signatures 
Edouard@185
   247
// fill a list of valid figerprints
Edouard@185
   248
// returns PEP_STATUS_OK if all sig reported valid
Edouard@185
   249
// error status otherwise.
Edouard@279
   250
static PEP_STATUS _validation_results(
Edouard@279
   251
        netpgp_t *netpgp,
Edouard@279
   252
        pgp_validation_t *vresult,
Edouard@279
   253
        stringlist_t **_keylist
Edouard@279
   254
    )
Edouard@185
   255
{
Edouard@188
   256
    time_t    now;
Edouard@188
   257
    time_t    t;
Edouard@188
   258
    char    buf[128];
Edouard@185
   259
Edouard@188
   260
    now = time(NULL);
Edouard@188
   261
    if (now < vresult->birthtime) {
Edouard@188
   262
        // signature is not valid yet
Edouard@188
   263
        return PEP_UNENCRYPTED;
Edouard@188
   264
    }
Edouard@188
   265
    if (vresult->duration != 0 && now > vresult->birthtime + vresult->duration) {
Edouard@188
   266
        // signature has expired
Edouard@188
   267
        t = vresult->duration + vresult->birthtime;
Edouard@188
   268
        return PEP_UNENCRYPTED;
Edouard@188
   269
    }
Edouard@185
   270
    if (vresult->validc && vresult->valid_sigs &&
Edouard@185
   271
        !vresult->invalidc && !vresult->unknownc ) {
Edouard@185
   272
        unsigned    n;
Edouard@185
   273
        stringlist_t *k;
Edouard@185
   274
        // caller responsible to free
Edouard@185
   275
        *_keylist = new_stringlist(NULL);
Edouard@185
   276
        assert(*_keylist);
Edouard@185
   277
        if (*_keylist == NULL) {
Edouard@185
   278
            return PEP_OUT_OF_MEMORY;
Edouard@185
   279
        }
Edouard@185
   280
        k = *_keylist;
Edouard@185
   281
        for (n = 0; n < vresult->validc; ++n) {
Edouard@185
   282
            char id[MAX_ID_LENGTH + 1];
Edouard@315
   283
            const uint8_t *keyid = vresult->valid_sigs[n].signer_id;
Edouard@185
   284
Edouard@315
   285
            id_to_str(keyid, id);
Edouard@185
   286
Edouard@185
   287
            k = stringlist_add(k, id);
Edouard@185
   288
            if(!k){
Edouard@185
   289
                free_stringlist(*_keylist);
Edouard@185
   290
                return PEP_OUT_OF_MEMORY;
Edouard@185
   291
            }
Edouard@185
   292
        }
Edouard@185
   293
        return PEP_STATUS_OK;
Edouard@185
   294
    }
Edouard@185
   295
    if (vresult->validc + vresult->invalidc + vresult->unknownc == 0) {
Edouard@185
   296
        // No signatures found - is this memory signed?
Edouard@185
   297
        return PEP_VERIFY_NO_KEY; 
Edouard@185
   298
    } 
Edouard@185
   299
    
Edouard@185
   300
    if (vresult->invalidc) {
Edouard@185
   301
        // some invalid signatures
Edouard@185
   302
        return PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
Edouard@185
   303
    }
Edouard@185
   304
    
Edouard@185
   305
    // only unknown sigs
Edouard@185
   306
    return PEP_DECRYPT_WRONG_FORMAT;
Edouard@185
   307
}
Edouard@185
   308
Edouard@207
   309
#define ARMOR_HEAD    "^-----BEGIN PGP MESSAGE-----\\s*$"
Edouard@174
   310
PEP_STATUS pgp_decrypt_and_verify(
Edouard@174
   311
    PEP_SESSION session, const char *ctext, size_t csize,
Edouard@174
   312
    char **ptext, size_t *psize, stringlist_t **keylist
Edouard@174
   313
    )
Edouard@174
   314
{
Edouard@185
   315
    pgp_memory_t *mem;
Edouard@185
   316
    pgp_memory_t *cat;
Edouard@185
   317
    pgp_validation_t *vresult;
Edouard@180
   318
    char *_ptext = NULL;
Edouard@180
   319
    size_t _psize = 0;
Edouard@185
   320
    int ret;
Edouard@179
   321
Edouard@174
   322
    PEP_STATUS result;
Edouard@174
   323
    stringlist_t *_keylist = NULL;
Edouard@174
   324
    int i_key = 0;
Edouard@174
   325
Edouard@174
   326
    assert(session);
Edouard@174
   327
    assert(ctext);
Edouard@174
   328
    assert(csize);
Edouard@174
   329
    assert(ptext);
Edouard@174
   330
    assert(psize);
Edouard@174
   331
    assert(keylist);
Edouard@174
   332
Edouard@179
   333
    if(!session || !ctext || !csize || !ptext || !psize || !keylist) 
Edouard@179
   334
        return PEP_UNKNOWN_ERROR;
Edouard@179
   335
Edouard@263
   336
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
   337
        return PEP_UNKNOWN_ERROR;
Edouard@252
   338
    }
Edouard@179
   339
Edouard@174
   340
    *ptext = NULL;
Edouard@174
   341
    *psize = 0;
Edouard@174
   342
    *keylist = NULL;
Edouard@174
   343
Edouard@183
   344
    vresult = malloc(sizeof(pgp_validation_t));
Edouard@185
   345
    memset(vresult, 0x0, sizeof(pgp_validation_t));
Edouard@182
   346
Edouard@252
   347
    mem = pgp_decrypt_and_validate_buf(netpgp.io, vresult, ctext, csize,
Edouard@252
   348
                netpgp.secring, netpgp.pubring,
Edouard@188
   349
                _armoured(ctext, csize, ARMOR_HEAD),
Edouard@179
   350
                0 /* sshkeys */,
Edouard@180
   351
                NULL, -1, NULL  /* pass fp,attempts,cb */);
Edouard@179
   352
    if (mem == NULL) {
Edouard@252
   353
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   354
        goto unlock_netpgp;
Edouard@179
   355
    }
Edouard@179
   356
Edouard@185
   357
    _psize = pgp_mem_len(mem);
Edouard@182
   358
    if (_psize){
Edouard@272
   359
        if ((_ptext = malloc(_psize + 1)) == NULL) {
Edouard@183
   360
            result = PEP_OUT_OF_MEMORY;
Edouard@183
   361
            goto free_pgp;
Edouard@182
   362
        }
Edouard@185
   363
        memcpy(_ptext, pgp_mem_data(mem), _psize);
Edouard@272
   364
        _ptext[_psize] = '\0'; // safeguard for naive users
Edouard@182
   365
        result = PEP_DECRYPTED;
Edouard@182
   366
    }else{
Edouard@183
   367
        result = PEP_DECRYPT_NO_KEY;
Edouard@183
   368
        goto free_pgp;
Edouard@182
   369
    }
Edouard@180
   370
Edouard@185
   371
    if (result == PEP_DECRYPTED) {
Edouard@252
   372
        result = _validation_results(&netpgp, vresult, &_keylist);
Edouard@185
   373
        if (result != PEP_STATUS_OK) {
Edouard@185
   374
            goto free_ptext;
Edouard@183
   375
        }
Edouard@180
   376
        result = PEP_DECRYPTED_AND_VERIFIED;
Edouard@180
   377
    }
Edouard@174
   378
Edouard@180
   379
    if (result == PEP_DECRYPTED_AND_VERIFIED
Edouard@180
   380
        || result == PEP_DECRYPTED) {
Edouard@180
   381
        *ptext = _ptext;
Edouard@180
   382
        *psize = _psize;
Edouard@180
   383
        (*ptext)[*psize] = 0; // safeguard for naive users
Edouard@185
   384
        if (result == PEP_DECRYPTED_AND_VERIFIED) {
Edouard@185
   385
            *keylist = _keylist;
Edouard@185
   386
        }
Edouard@183
   387
Edouard@183
   388
        /* _ptext and _keylist ownership transfer, don't free */
Edouard@183
   389
        goto free_pgp;
Edouard@180
   390
    }
Edouard@183
   391
Edouard@183
   392
free_keylist:
Edouard@183
   393
    free_stringlist(_keylist);
Edouard@183
   394
Edouard@183
   395
free_ptext:
Edouard@183
   396
    free(_ptext);
Edouard@183
   397
Edouard@183
   398
free_pgp:
Edouard@185
   399
    pgp_memory_free(mem);
Edouard@183
   400
    pgp_validate_result_free(vresult);
Edouard@183
   401
Edouard@252
   402
unlock_netpgp:
Edouard@252
   403
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   404
Edouard@174
   405
    return result;
Edouard@174
   406
}
Edouard@174
   407
Edouard@207
   408
#define ARMOR_SIG_HEAD    "^-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----\\s*$"
Edouard@174
   409
PEP_STATUS pgp_verify_text(
Edouard@174
   410
    PEP_SESSION session, const char *text, size_t size,
Edouard@174
   411
    const char *signature, size_t sig_size, stringlist_t **keylist
Edouard@174
   412
    )
Edouard@174
   413
{
Edouard@185
   414
    pgp_memory_t *signedmem;
Edouard@185
   415
    pgp_memory_t *sig;
Edouard@185
   416
    pgp_validation_t *vresult;
Edouard@185
   417
Edouard@174
   418
    PEP_STATUS result;
Edouard@174
   419
    stringlist_t *_keylist;
Edouard@174
   420
Edouard@174
   421
    assert(session);
Edouard@174
   422
    assert(text);
Edouard@174
   423
    assert(size);
Edouard@174
   424
    assert(signature);
Edouard@174
   425
    assert(sig_size);
Edouard@174
   426
    assert(keylist);
Edouard@174
   427
Edouard@185
   428
    if(!session || !text || !size || !signature || !sig_size || !keylist) 
Edouard@185
   429
        return PEP_UNKNOWN_ERROR;
Edouard@185
   430
Edouard@263
   431
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
   432
        return PEP_UNKNOWN_ERROR;
Edouard@252
   433
    }
Edouard@185
   434
Edouard@174
   435
    *keylist = NULL;
Edouard@185
   436
Edouard@185
   437
    vresult = malloc(sizeof(pgp_validation_t));
Edouard@276
   438
    if (vresult == NULL) {
Edouard@276
   439
        result = PEP_OUT_OF_MEMORY;
Edouard@276
   440
        goto unlock_netpgp;
Edouard@276
   441
    }
Edouard@185
   442
    memset(vresult, 0x0, sizeof(pgp_validation_t));
Edouard@185
   443
Edouard@185
   444
    signedmem = pgp_memory_new();
Edouard@185
   445
    if (signedmem == NULL) {
Edouard@252
   446
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   447
        goto unlock_netpgp;
Edouard@185
   448
    }
Edouard@185
   449
    pgp_memory_add(signedmem, (const uint8_t*)text, size);
Edouard@185
   450
Edouard@185
   451
    sig = pgp_memory_new();
Edouard@185
   452
    if (sig == NULL) {
Edouard@185
   453
        pgp_memory_free(signedmem);
Edouard@252
   454
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   455
        goto unlock_netpgp;
Edouard@185
   456
    }
Edouard@185
   457
    pgp_memory_add(sig, (const uint8_t*)signature, sig_size);
Edouard@185
   458
Edouard@252
   459
    pgp_validate_mem_detached(netpgp.io, vresult, sig,
Edouard@185
   460
                NULL,/* output */
Edouard@207
   461
                _armoured(signature, sig_size, ARMOR_SIG_HEAD),
Edouard@252
   462
                netpgp.pubring,
Edouard@185
   463
                signedmem);
Edouard@185
   464
Edouard@252
   465
    result = _validation_results(&netpgp, vresult, &_keylist);
Edouard@185
   466
    if (result != PEP_STATUS_OK) {
Edouard@185
   467
        goto free_pgp;
Edouard@185
   468
    }else{
Edouard@185
   469
        result = PEP_VERIFIED;
Edouard@185
   470
    }
Edouard@185
   471
Edouard@185
   472
    if (result == PEP_VERIFIED) {
Edouard@185
   473
        /* TODO : check trust level */
Edouard@185
   474
        result = PEP_VERIFIED_AND_TRUSTED;
Edouard@185
   475
    }
Edouard@185
   476
Edouard@185
   477
    if (result == PEP_VERIFIED || result == PEP_VERIFIED_AND_TRUSTED) {
Edouard@185
   478
        *keylist = _keylist;
Edouard@185
   479
Edouard@185
   480
        /* _keylist ownership transfer, don't free */
Edouard@185
   481
        goto free_pgp;
Edouard@185
   482
    }
Edouard@185
   483
Edouard@185
   484
free_keylist:
Edouard@185
   485
    free_stringlist(_keylist);
Edouard@185
   486
Edouard@185
   487
free_pgp:
Edouard@187
   488
    // free done by pgp_validate_mem_detached
Edouard@187
   489
    // pgp_memory_free(sig);
Edouard@187
   490
    // pgp_memory_free(signedmem);
Edouard@185
   491
    pgp_validate_result_free(vresult);
Edouard@185
   492
Edouard@252
   493
unlock_netpgp:
Edouard@252
   494
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   495
Edouard@185
   496
    return result;
Edouard@174
   497
}
Edouard@174
   498
Edouard@174
   499
PEP_STATUS pgp_encrypt_and_sign(
Edouard@174
   500
    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
Edouard@174
   501
    size_t psize, char **ctext, size_t *csize
Edouard@174
   502
    )
Edouard@174
   503
{
Edouard@315
   504
    const pgp_key_t *signer = NULL;
Edouard@315
   505
    const pgp_seckey_t *seckey = NULL;
Edouard@209
   506
    pgp_memory_t *signedmem;
Edouard@209
   507
    pgp_memory_t *cmem;
Edouard@207
   508
    const char *hashalg;
Edouard@209
   509
    pgp_keyring_t *rcpts;
Edouard@207
   510
Edouard@174
   511
    PEP_STATUS result;
Edouard@174
   512
    const stringlist_t *_keylist;
Edouard@174
   513
Edouard@174
   514
    assert(session);
Edouard@174
   515
    assert(keylist);
Edouard@174
   516
    assert(ptext);
Edouard@174
   517
    assert(psize);
Edouard@174
   518
    assert(ctext);
Edouard@174
   519
    assert(csize);
Edouard@174
   520
Edouard@207
   521
    if(!session || !ptext || !psize || !ctext || !csize || !keylist) 
Edouard@207
   522
        return PEP_UNKNOWN_ERROR;
Edouard@207
   523
Edouard@263
   524
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
   525
        return PEP_UNKNOWN_ERROR;
Edouard@252
   526
    }
Edouard@208
   527
Edouard@174
   528
    *ctext = NULL;
Edouard@174
   529
    *csize = 0;
Edouard@174
   530
Edouard@315
   531
    if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) {
Edouard@315
   532
        result = PEP_OUT_OF_MEMORY;
Edouard@315
   533
        goto free_signedmem;
Edouard@315
   534
    }
Edouard@315
   535
    for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
Edouard@315
   536
        assert(_keylist->value);
Edouard@315
   537
        const pgp_key_t *key;
Edouard@315
   538
        uint8_t keyid[PGP_KEY_ID_SIZE];
Edouard@315
   539
        unsigned from = 0;
Edouard@315
   540
Edouard@315
   541
        if(!str_to_id(keyid, _keylist->value))
Edouard@315
   542
        {
Edouard@315
   543
            result = PEP_ILLEGAL_VALUE;
Edouard@315
   544
            goto free_rcpts;
Edouard@315
   545
        }
Edouard@315
   546
Edouard@315
   547
        key = pgp_getkeybyid(netpgp.io, netpgp.pubring, 
Edouard@315
   548
                 keyid, &from, NULL, NULL, 
Edouard@315
   549
                 1, 0); /* reject revoked, accept expired */
Edouard@315
   550
        if(key == NULL){
Edouard@315
   551
            result = PEP_KEY_NOT_FOUND;
Edouard@315
   552
            goto free_rcpts;
Edouard@315
   553
        }
Edouard@315
   554
Edouard@315
   555
        /* Signer is the first key in the list */
Edouard@315
   556
        if(signer == NULL){
Edouard@315
   557
            from = 0;
Edouard@315
   558
            signer = pgp_getkeybyid(netpgp.io, netpgp.secring, 
Edouard@315
   559
                     keyid, &from, NULL, NULL, 
Edouard@315
   560
                     0, 0); /* accept any */
Edouard@315
   561
            if(signer == NULL){
Edouard@315
   562
                result = PEP_KEY_NOT_FOUND;
Edouard@315
   563
                goto free_rcpts;
Edouard@315
   564
            }
Edouard@315
   565
        }
Edouard@315
   566
Edouard@315
   567
        // add key to recipients/signers
Edouard@315
   568
        pgp_keyring_add(rcpts, key);
Edouard@315
   569
        if(rcpts->keys == NULL){
Edouard@315
   570
            result = PEP_OUT_OF_MEMORY;
Edouard@315
   571
            goto free_signedmem;
Edouard@315
   572
        }
Edouard@207
   573
    }
Edouard@209
   574
Edouard@315
   575
    /* Empty keylist ?*/
Edouard@315
   576
    if(rcpts->keyc == 0){
Edouard@315
   577
        result = PEP_ILLEGAL_VALUE;
Edouard@315
   578
        goto free_signedmem;
Edouard@315
   579
    }
Edouard@315
   580
Edouard@315
   581
    seckey = pgp_key_get_certkey(signer);
Edouard@315
   582
Edouard@315
   583
    /* No signig key. Revoked ? */
Edouard@315
   584
    if(seckey == NULL){
Edouard@315
   585
        result = PEP_GET_KEY_FAILED;
Edouard@315
   586
        goto free_signedmem;
Edouard@315
   587
    }
Edouard@286
   588
Edouard@252
   589
    hashalg = netpgp_getvar(&netpgp, "hash");
Edouard@207
   590
Edouard@207
   591
    // Sign data
Edouard@252
   592
    signedmem = pgp_sign_buf(netpgp.io, ptext, psize, seckey,
Edouard@209
   593
                time(NULL), /* birthtime */
Edouard@209
   594
                0 /* duration */,
Edouard@209
   595
                hashalg, 
Edouard@207
   596
                0 /* armored */,
Edouard@207
   597
                0 /* cleartext */);
Edouard@207
   598
Edouard@207
   599
    if (!signedmem) {
Edouard@252
   600
        result = PEP_UNENCRYPTED;
Edouard@252
   601
        goto unlock_netpgp;
Edouard@207
   602
    }
Edouard@207
   603
Edouard@207
   604
    // Encrypt signed data
Edouard@174
   605
Edouard@252
   606
    cmem = pgp_encrypt_buf(netpgp.io, pgp_mem_data(signedmem),
Edouard@209
   607
            pgp_mem_len(signedmem), rcpts, 1 /* armored */,
Edouard@252
   608
            netpgp_getvar(&netpgp, "cipher"), 
Edouard@209
   609
            1 /* takes raw OpenPGP message */);
Edouard@209
   610
Edouard@209
   611
    if (cmem == NULL) {
Edouard@209
   612
        result = PEP_OUT_OF_MEMORY;
Edouard@209
   613
        goto free_signedmem;
Edouard@209
   614
    }else{
Edouard@209
   615
Edouard@209
   616
        char *_buffer = NULL;
Edouard@209
   617
        size_t length = pgp_mem_len(cmem);
Edouard@174
   618
Edouard@209
   619
        // Allocate transferable buffer
Edouard@209
   620
        _buffer = malloc(length + 1);
Edouard@209
   621
        assert(_buffer);
Edouard@209
   622
        if (_buffer == NULL) {
Edouard@209
   623
            result = PEP_OUT_OF_MEMORY;
Edouard@209
   624
            goto free_cmem;
Edouard@209
   625
        }
Edouard@209
   626
Edouard@209
   627
        memcpy(_buffer, pgp_mem_data(cmem), length);
Edouard@209
   628
Edouard@209
   629
        *ctext = _buffer;
Edouard@209
   630
        *csize = length;
Edouard@209
   631
        (*ctext)[*csize] = 0; // safeguard for naive users
Edouard@209
   632
        result = PEP_STATUS_OK;
Edouard@174
   633
    }
Edouard@174
   634
Edouard@209
   635
free_cmem :
Edouard@209
   636
    pgp_memory_free(cmem);
Edouard@315
   637
free_signedmem :
Edouard@315
   638
    pgp_memory_free(signedmem);
Edouard@209
   639
free_rcpts :
Edouard@209
   640
    pgp_keyring_free(rcpts);
Edouard@252
   641
unlock_netpgp:
Edouard@252
   642
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@175
   643
Edouard@174
   644
    return result;
Edouard@174
   645
}
Edouard@174
   646
Edouard@316
   647
/* write key fingerprint hexdump as a string */
Edouard@227
   648
static unsigned
Edouard@227
   649
fpr_to_str (char **str, const uint8_t *fpr, size_t length)
Edouard@227
   650
{
Edouard@228
   651
    unsigned i;
Edouard@228
   652
    int	n;
Edouard@227
   653
Edouard@227
   654
    /* 5 char per byte (hexes + space) tuple -1 space at the end + null */
Edouard@227
   655
    *str = malloc((length / 2) * 5 - 1 + 1);
Edouard@227
   656
Edouard@227
   657
    if(*str == NULL)
Edouard@227
   658
        return 0;
Edouard@227
   659
Edouard@243
   660
    for (n = 0, i = 0 ; i < length - 2; i += 2) {
Edouard@243
   661
    	n += snprintf(&((*str)[n]), 6, "%02x%02x ", fpr[i], fpr[i+1]);
Edouard@228
   662
    }
Edouard@243
   663
    snprintf(&((*str)[n]), 5, "%02x%02x", fpr[i], fpr[i+1]);
Edouard@227
   664
Edouard@228
   665
    return 1;
Edouard@227
   666
}
Edouard@227
   667
Edouard@316
   668
/* write key fingerprint bytes read from hex string 
Edouard@316
   669
 * accept spaces and hexes */
Edouard@227
   670
static unsigned
Edouard@227
   671
str_to_fpr (const char *str, uint8_t *fpr, size_t *length)
Edouard@227
   672
{
Edouard@227
   673
    unsigned i,j;
Edouard@227
   674
Edouard@227
   675
    *length = 0;
Edouard@227
   676
Edouard@227
   677
    while(*str && *length < PGP_FINGERPRINT_SIZE){
Edouard@227
   678
        while (*str == ' ') str++;
Edouard@227
   679
        for (j = 0; j < 2; j++) {
Edouard@227
   680
            uint8_t *byte = &fpr[*length];
Edouard@243
   681
            *byte = 0;
Edouard@227
   682
            for (i = 0; i < 2; i++) {
Edouard@227
   683
                if (i > 0)
Edouard@243
   684
                    *byte = *byte << 4;
Edouard@227
   685
                if (*str >= 'a' && *str <= 'f')
Edouard@227
   686
                    *byte += 10 + *str - 'a';
Edouard@227
   687
                else if (*str >= 'A' && *str <= 'F')
Edouard@227
   688
                    *byte += 10 + *str - 'A';
Edouard@227
   689
                else if (*str >= '0' && *str <= '9')
Edouard@227
   690
                    *byte += *str - '0';
Edouard@227
   691
                else 
Edouard@227
   692
                    return 0;
Edouard@227
   693
                str++;
Edouard@227
   694
            }
Edouard@243
   695
            (*length)++;
Edouard@227
   696
        }
Edouard@227
   697
    }
Edouard@227
   698
    return 1;
Edouard@227
   699
}
Edouard@227
   700
Edouard@174
   701
PEP_STATUS pgp_generate_keypair(
Edouard@174
   702
    PEP_SESSION session, pEp_identity *identity
Edouard@174
   703
    )
Edouard@174
   704
{
Edouard@313
   705
    pgp_key_t	newseckey;
Edouard@316
   706
    pgp_key_t	*newpubkey;
Edouard@225
   707
Edouard@225
   708
    PEP_STATUS result;
Edouard@228
   709
    char newid[1024];
Edouard@225
   710
    const char *hashalg;
Edouard@225
   711
    const char *cipher;
Edouard@174
   712
Edouard@174
   713
    assert(session);
Edouard@174
   714
    assert(identity);
Edouard@174
   715
    assert(identity->address);
Edouard@174
   716
    assert(identity->fpr == NULL);
Edouard@174
   717
    assert(identity->username);
Edouard@174
   718
Edouard@225
   719
    if(!session || !identity || 
Edouard@225
   720
       !identity->address || identity->fpr || !identity->username)
Edouard@225
   721
        return PEP_UNKNOWN_ERROR;
Edouard@174
   722
Edouard@263
   723
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
   724
        return PEP_UNKNOWN_ERROR;
Edouard@252
   725
    }
Edouard@225
   726
Edouard@225
   727
    if(snprintf(newid, sizeof(newid),
Edouard@225
   728
        "%s <%s>", identity->username, identity->address) >= sizeof(newid)){
Edouard@252
   729
        result =  PEP_BUFFER_TOO_SMALL;
Edouard@252
   730
        goto unlock_netpgp;
Edouard@174
   731
    }
Edouard@225
   732
    
Edouard@252
   733
    hashalg = netpgp_getvar(&netpgp, "hash");
Edouard@252
   734
    cipher = netpgp_getvar(&netpgp, "cipher");
Edouard@174
   735
Edouard@313
   736
    bzero(&newseckey, sizeof(newseckey));
Edouard@225
   737
Edouard@225
   738
    // TODO "Expire-Date: 1y\n";
Edouard@313
   739
    // Generate the key
Edouard@313
   740
    if (!pgp_rsa_generate_keypair(&newseckey, 4096, 65537UL, hashalg, cipher,
Edouard@313
   741
                                  (const uint8_t *) "", (const size_t) 0) ||
Edouard@313
   742
        !pgp_add_selfsigned_userid(&newseckey, (uint8_t *)newid)) {
Edouard@313
   743
        result = PEP_CANNOT_CREATE_KEY;
Edouard@313
   744
        goto free_seckey;
Edouard@225
   745
    }
Edouard@174
   746
Edouard@316
   747
    /* make a public key out of generated secret key */
Edouard@316
   748
    newpubkey = pgp_ensure_pubkey(
Edouard@316
   749
            netpgp.pubring,
Edouard@316
   750
            &newseckey.key.seckey.pubkey,
Edouard@316
   751
            newseckey.pubkeyid);
Edouard@316
   752
Edouard@316
   753
    if (newpubkey == NULL) {
Edouard@316
   754
        result = PEP_OUT_OF_MEMORY;
Edouard@316
   755
        goto free_seckey;
Edouard@316
   756
    }
Edouard@316
   757
Edouard@316
   758
    /* Copy the only user ID given to that key */
Edouard@316
   759
    pgp_update_userid(newpubkey,
Edouard@313
   760
                      newseckey.uids[0], 
Edouard@313
   761
                      &newseckey.uidsigs[0].packet, 
Edouard@313
   762
                      &newseckey.uidsigs[0].siginfo);
Edouard@313
   763
Edouard@316
   764
    /* No subkey have been created nothing else to copy to public */
Edouard@313
   765
Edouard@313
   766
    // Append key to netpgp's rings (key ownership transfered)
Edouard@313
   767
    if (!pgp_keyring_add(netpgp.secring, &newseckey)){
Edouard@313
   768
        result = PEP_OUT_OF_MEMORY;
Edouard@316
   769
        goto delete_pubkey;
Edouard@316
   770
    } 
Edouard@313
   771
Edouard@313
   772
    // save rings 
Edouard@313
   773
    if (netpgp_save_pubring(&netpgp) && netpgp_save_secring(&netpgp))
Edouard@313
   774
    {
Edouard@316
   775
        char *fprstr = NULL;
Edouard@316
   776
        fpr_to_str(&fprstr,
Edouard@316
   777
                   newseckey.pubkeyfpr.fingerprint,
Edouard@316
   778
                   newseckey.pubkeyfpr.length);
Edouard@316
   779
Edouard@316
   780
        if (fprstr == NULL) {
Edouard@316
   781
            result = PEP_OUT_OF_MEMORY;
Edouard@316
   782
            goto pop_secring;
Edouard@316
   783
        } 
Edouard@316
   784
Edouard@316
   785
        /* keys saved, pass fingerprint back */
Edouard@313
   786
        identity->fpr = fprstr;
Edouard@313
   787
        result = PEP_STATUS_OK;
Edouard@316
   788
Edouard@313
   789
        /* free nothing, everything transfered */
Edouard@313
   790
        goto unlock_netpgp;
Edouard@313
   791
    } else {
Edouard@313
   792
        /* XXX in case only pubring save succeed
Edouard@313
   793
         * pubring file is left as-is, but backup restore
Edouard@313
   794
         * could be attempted if such corner case matters */
Edouard@313
   795
        result = PEP_UNKNOWN_ERROR;
Edouard@313
   796
    }
Edouard@313
   797
Edouard@313
   798
pop_secring:
Edouard@313
   799
    ((pgp_keyring_t *)netpgp.secring)->keyc--;
Edouard@316
   800
delete_pubkey:
Edouard@316
   801
    pgp_deletekeybyfpr(netpgp.io,
Edouard@316
   802
                    (pgp_keyring_t *)netpgp.pubring, 
Edouard@316
   803
                    newseckey.pubkeyfpr.fingerprint,
Edouard@316
   804
                    newseckey.pubkeyfpr.length);
Edouard@316
   805
    /* TODO delete key from ring */
Edouard@316
   806
    /* pgp_key_free(newpubkey);*/ 
Edouard@313
   807
free_seckey:
Edouard@313
   808
    pgp_key_free(&newseckey);
Edouard@252
   809
unlock_netpgp:
Edouard@252
   810
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@228
   811
Edouard@225
   812
    return result;
Edouard@174
   813
}
Edouard@174
   814
Edouard@227
   815
PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fprstr)
Edouard@174
   816
{
Edouard@227
   817
    uint8_t fpr[PGP_FINGERPRINT_SIZE];
Edouard@227
   818
    size_t length;
Edouard@227
   819
Edouard@227
   820
    PEP_STATUS result;
Edouard@227
   821
Edouard@174
   822
    assert(session);
Edouard@174
   823
    assert(fpr);
Edouard@174
   824
Edouard@227
   825
    if (!session || !fpr)
Edouard@174
   826
        return PEP_UNKNOWN_ERROR;
Edouard@174
   827
Edouard@263
   828
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
   829
        return PEP_UNKNOWN_ERROR;
Edouard@252
   830
    }
Edouard@227
   831
    
Edouard@227
   832
    if (str_to_fpr(fprstr, fpr, &length)) {
Edouard@252
   833
        unsigned insec = pgp_deletekeybyfpr(netpgp.io,
Edouard@252
   834
                                (pgp_keyring_t *)netpgp.secring, 
Edouard@244
   835
                                (const uint8_t *)fpr, length);
Edouard@252
   836
        unsigned inpub = pgp_deletekeybyfpr(netpgp.io,
Edouard@252
   837
                                (pgp_keyring_t *)netpgp.pubring, 
Edouard@244
   838
                                (const uint8_t *)fpr, length);
Edouard@244
   839
        if(!insec && !inpub){
Edouard@244
   840
            result = PEP_KEY_NOT_FOUND;
Edouard@252
   841
            goto unlock_netpgp;
Edouard@244
   842
        } else {
Edouard@244
   843
            result = PEP_STATUS_OK;
Edouard@227
   844
        }
Edouard@227
   845
    }else{
Edouard@252
   846
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   847
        goto unlock_netpgp;
Edouard@227
   848
    }
Edouard@174
   849
Edouard@227
   850
    // save rings (key ownership transfered)
Edouard@252
   851
    if (netpgp_save_pubring(&netpgp) && 
Edouard@252
   852
        netpgp_save_secring(&netpgp))
Edouard@227
   853
    {
Edouard@227
   854
        result = PEP_STATUS_OK;
Edouard@227
   855
    }else{
Edouard@227
   856
        result = PEP_UNKNOWN_ERROR;
Edouard@227
   857
    }
Edouard@227
   858
Edouard@252
   859
unlock_netpgp:
Edouard@252
   860
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   861
Edouard@227
   862
    return result;
Edouard@174
   863
}
Edouard@174
   864
Edouard@228
   865
#define ARMOR_KEY_HEAD    "^-----BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK-----\\s*$"
Edouard@279
   866
PEP_STATUS pgp_import_keydata(
Edouard@279
   867
        PEP_SESSION session,
Edouard@279
   868
        const char *key_data, 
Edouard@279
   869
        size_t size
Edouard@279
   870
    )
Edouard@174
   871
{
Edouard@228
   872
    pgp_memory_t *mem;
Edouard@271
   873
    unsigned i = 0;
Edouard@228
   874
Edouard@271
   875
    PEP_STATUS result = PEP_STATUS_OK;
Edouard@228
   876
Edouard@174
   877
    assert(session);
Edouard@174
   878
    assert(key_data);
Edouard@174
   879
Edouard@228
   880
    if(!session || !key_data) 
Edouard@174
   881
        return PEP_UNKNOWN_ERROR;
Edouard@228
   882
Edouard@263
   883
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
   884
        return PEP_UNKNOWN_ERROR;
Edouard@252
   885
    }
Edouard@228
   886
Edouard@228
   887
    mem = pgp_memory_new();
Edouard@228
   888
    if (mem == NULL) {
Edouard@252
   889
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   890
        goto unlock_netpgp;
Edouard@228
   891
    }
Edouard@228
   892
    pgp_memory_add(mem, (const uint8_t*)key_data, size);
Edouard@228
   893
Edouard@313
   894
    if (pgp_keyring_read_from_mem(netpgp.io, netpgp.pubring, netpgp.secring, 
Edouard@228
   895
                                  _armoured(key_data, size, ARMOR_KEY_HEAD),
Edouard@228
   896
                                  mem) == 0){
Edouard@228
   897
        result = PEP_ILLEGAL_VALUE;
Edouard@313
   898
    }    
Edouard@313
   899
Edouard@228
   900
    pgp_memory_free(mem);
Edouard@228
   901
Edouard@252
   902
unlock_netpgp:
Edouard@252
   903
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@252
   904
Edouard@228
   905
    return result;
Edouard@174
   906
}
Edouard@174
   907
Edouard@318
   908
static PEP_STATUS _export_keydata(
Edouard@318
   909
    pgp_key_t *key,
Edouard@318
   910
    char **buffer,
Edouard@318
   911
    size_t *buflen
Edouard@318
   912
    )
Edouard@318
   913
{
Edouard@318
   914
    PEP_STATUS result;
Edouard@318
   915
	pgp_output_t *output;
Edouard@318
   916
    pgp_memory_t *mem;
Edouard@318
   917
	pgp_setup_memory_write(&output, &mem, 128);
Edouard@318
   918
Edouard@318
   919
    if (mem == NULL || output == NULL) {
Edouard@318
   920
        return PEP_OUT_OF_MEMORY;
Edouard@318
   921
    }
Edouard@318
   922
Edouard@318
   923
    if (!pgp_write_xfer_key(output, key, 1)) {
Edouard@318
   924
        result = PEP_UNKNOWN_ERROR;
Edouard@318
   925
        goto free_mem;
Edouard@318
   926
    }
Edouard@318
   927
Edouard@318
   928
    *buffer = NULL;
Edouard@318
   929
    *buflen = pgp_mem_len(mem);
Edouard@318
   930
Edouard@318
   931
    // Allocate transferable buffer
Edouard@318
   932
    *buffer = malloc(*buflen + 1);
Edouard@318
   933
    assert(*buffer);
Edouard@318
   934
    if (*buffer == NULL) {
Edouard@318
   935
        result = PEP_OUT_OF_MEMORY;
Edouard@318
   936
        goto free_mem;
Edouard@318
   937
    }
Edouard@318
   938
Edouard@318
   939
    memcpy(*buffer, pgp_mem_data(mem), *buflen);
Edouard@318
   940
    (*buffer)[*buflen] = 0; // safeguard for naive users
Edouard@318
   941
Edouard@318
   942
    return PEP_STATUS_OK;
Edouard@318
   943
Edouard@318
   944
free_mem :
Edouard@318
   945
	pgp_teardown_memory_write(output, mem);
Edouard@318
   946
Edouard@318
   947
    return result;
Edouard@318
   948
}
Edouard@318
   949
Edouard@179
   950
PEP_STATUS pgp_export_keydata(
Edouard@228
   951
    PEP_SESSION session, const char *fprstr, char **key_data, size_t *size
Edouard@174
   952
    )
Edouard@174
   953
{
Edouard@228
   954
    pgp_key_t *key;
Edouard@228
   955
    uint8_t fpr[PGP_FINGERPRINT_SIZE];
Edouard@228
   956
    size_t fprlen;
Edouard@228
   957
Edouard@228
   958
    PEP_STATUS result;
Edouard@174
   959
    char *buffer;
Edouard@228
   960
    size_t buflen;
Edouard@174
   961
Edouard@174
   962
    assert(session);
Edouard@243
   963
    assert(fprstr);
Edouard@174
   964
    assert(key_data);
Edouard@174
   965
    assert(size);
Edouard@174
   966
Edouard@243
   967
    if (!session || !fprstr || !key_data || !size)
Edouard@174
   968
        return PEP_UNKNOWN_ERROR;
Edouard@174
   969
Edouard@263
   970
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@252
   971
        return PEP_UNKNOWN_ERROR;
Edouard@252
   972
    }
Edouard@252
   973
Edouard@228
   974
    if (str_to_fpr(fprstr, fpr, &fprlen)) {
Edouard@252
   975
        if ((key = (pgp_key_t *)pgp_getkeybyfpr(netpgp.io, netpgp.pubring, 
Edouard@228
   976
                                                fpr, fprlen,
Edouard@254
   977
                                                NULL)) == NULL) {
Edouard@252
   978
            result = PEP_KEY_NOT_FOUND;
Edouard@252
   979
            goto unlock_netpgp;
Edouard@228
   980
        }
Edouard@228
   981
    }else{
Edouard@252
   982
        result = PEP_OUT_OF_MEMORY;
Edouard@252
   983
        goto unlock_netpgp;
Edouard@228
   984
    }
Edouard@228
   985
    
Edouard@318
   986
    result = _export_keydata(key, &buffer, &buflen);
Edouard@318
   987
    
Edouard@318
   988
    if(result == PEP_STATUS_OK)
Edouard@318
   989
    {
Edouard@318
   990
        *key_data = buffer;
Edouard@318
   991
        *size = buflen;
Edouard@318
   992
        result = PEP_STATUS_OK;
Edouard@228
   993
    }
Edouard@228
   994
Edouard@252
   995
unlock_netpgp:
Edouard@252
   996
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@228
   997
Edouard@228
   998
    return result;
Edouard@174
   999
}
Edouard@174
  1000
Edouard@271
  1001
struct HKP_answer {
Edouard@271
  1002
  char *memory;
Edouard@271
  1003
  size_t size;
Edouard@271
  1004
};
Edouard@271
  1005
 
Edouard@271
  1006
static size_t
Edouard@271
  1007
HKPAnswerWriter(void *contents, size_t size, size_t nmemb, void *userp)
Edouard@271
  1008
{
Edouard@271
  1009
  size_t realsize = size * nmemb;
Edouard@271
  1010
  struct HKP_answer *mem = (struct HKP_answer *)userp;
Edouard@271
  1011
 
Edouard@271
  1012
  mem->memory = realloc(mem->memory, mem->size + realsize + 1);
Edouard@271
  1013
  if(mem->memory == NULL) {
Edouard@271
  1014
    mem->size = 0;
Edouard@271
  1015
    return 0;
Edouard@271
  1016
  }
Edouard@271
  1017
 
Edouard@271
  1018
  memcpy(&(mem->memory[mem->size]), contents, realsize);
Edouard@271
  1019
  mem->size += realsize;
Edouard@271
  1020
  mem->memory[mem->size] = 0;
Edouard@271
  1021
 
Edouard@271
  1022
  return realsize;
Edouard@271
  1023
}
Edouard@271
  1024
Edouard@174
  1025
PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
Edouard@174
  1026
{
Edouard@271
  1027
    static const char *ks_cmd = "http://keys.gnupg.net:11371/pks/lookup?"
Edouard@271
  1028
                                "op=get&options=mr&exact=on&"
Edouard@271
  1029
                                "search=";
Edouard@271
  1030
    char *encoded_pattern;
Edouard@271
  1031
    char *request = NULL;
Edouard@271
  1032
    struct HKP_answer answer;
Edouard@271
  1033
    CURLcode curlres;
Edouard@271
  1034
       
Edouard@271
  1035
    PEP_STATUS result;
Edouard@271
  1036
Edouard@271
  1037
    CURL *curl;
Edouard@271
  1038
Edouard@174
  1039
    assert(session);
Edouard@174
  1040
    assert(pattern);
Edouard@174
  1041
Edouard@271
  1042
    if (!session || !pattern )
Edouard@271
  1043
        return PEP_UNKNOWN_ERROR;
Edouard@271
  1044
Edouard@271
  1045
    if(pthread_mutex_lock(&session->ctx.curl_mutex)){
Edouard@271
  1046
        return PEP_UNKNOWN_ERROR;
Edouard@271
  1047
    }
Edouard@271
  1048
Edouard@252
  1049
    curl = session->ctx.curl;
Edouard@252
  1050
Edouard@271
  1051
    encoded_pattern = curl_easy_escape(curl, (char*)pattern, 0);
Edouard@271
  1052
    if(!encoded_pattern){
Edouard@271
  1053
        result = PEP_OUT_OF_MEMORY;
Edouard@271
  1054
        goto unlock_curl;
Edouard@271
  1055
    }
Edouard@271
  1056
Edouard@271
  1057
    if((request = malloc(strlen(ks_cmd) + strlen(encoded_pattern) + 1))==NULL){
Edouard@271
  1058
        result = PEP_OUT_OF_MEMORY;
Edouard@271
  1059
        goto free_encoded_pattern;
Edouard@271
  1060
    }
Edouard@174
  1061
Edouard@271
  1062
    //(*stpcpy(stpcpy(request, ks_cmd), encoded_pattern)) = '\0';
Edouard@271
  1063
    stpcpy(stpcpy(request, ks_cmd), encoded_pattern);
Edouard@271
  1064
Edouard@271
  1065
    curl_easy_setopt(curl, CURLOPT_URL,request);
Edouard@271
  1066
Edouard@271
  1067
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HKPAnswerWriter);
Edouard@271
  1068
Edouard@271
  1069
    answer.memory = NULL;
Edouard@271
  1070
    answer.size = 0;
Edouard@271
  1071
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&answer);
Edouard@174
  1072
Edouard@271
  1073
    curlres = curl_easy_perform(curl);
Edouard@271
  1074
    if(curlres != CURLE_OK) {
Edouard@271
  1075
        result = PEP_GET_KEY_FAILED;
Edouard@271
  1076
        goto free_request;
Edouard@271
  1077
    }
Edouard@271
  1078
Edouard@271
  1079
    if(!answer.memory || !answer.size) {
Edouard@271
  1080
        result = PEP_OUT_OF_MEMORY;
Edouard@271
  1081
        goto free_request;
Edouard@271
  1082
    }
Edouard@174
  1083
Edouard@271
  1084
    result = pgp_import_keydata(session, 
Edouard@271
  1085
                                answer.memory, 
Edouard@271
  1086
                                answer.size);
Edouard@271
  1087
Edouard@271
  1088
free_answer:
Edouard@271
  1089
    free(answer.memory);
Edouard@271
  1090
free_request:
Edouard@271
  1091
    free(request);
Edouard@271
  1092
free_encoded_pattern:
Edouard@271
  1093
    curl_free(encoded_pattern);
Edouard@271
  1094
unlock_curl:
Edouard@271
  1095
    pthread_mutex_unlock(&session->ctx.curl_mutex);
Edouard@271
  1096
Edouard@271
  1097
    return result;
Edouard@174
  1098
}
Edouard@174
  1099
Edouard@277
  1100
typedef PEP_STATUS (*find_key_cb_t)(void*, pgp_key_t *);
Edouard@277
  1101
Edouard@277
  1102
static PEP_STATUS find_keys_do(
Edouard@277
  1103
        const char *pattern, find_key_cb_t cb, void* cb_arg)
Edouard@254
  1104
{
Edouard@277
  1105
    uint8_t fpr[PGP_FINGERPRINT_SIZE];
Edouard@277
  1106
    size_t length;
Edouard@277
  1107
    pgp_key_t *key;
Edouard@277
  1108
Edouard@277
  1109
    PEP_STATUS result;
Edouard@277
  1110
Edouard@277
  1111
    // Try find a fingerprint in pattern
Edouard@277
  1112
    if (str_to_fpr(pattern, fpr, &length)) {
Edouard@277
  1113
Edouard@277
  1114
        // Only one fingerprint can match
Edouard@277
  1115
        if ((key = (pgp_key_t *)pgp_getkeybyfpr(
Edouard@277
  1116
                        netpgp.io,
Edouard@277
  1117
                        (pgp_keyring_t *)netpgp.pubring, 
Edouard@277
  1118
                        (const uint8_t *)fpr, length,
Edouard@277
  1119
                        NULL)) == NULL) {
Edouard@277
  1120
Edouard@277
  1121
            return PEP_KEY_NOT_FOUND;
Edouard@277
  1122
        }
Edouard@277
  1123
Edouard@277
  1124
        result = cb(cb_arg, key);
Edouard@277
  1125
Edouard@277
  1126
    } else {
Edouard@277
  1127
        // Search by name for pattern. Can match many.
Edouard@277
  1128
        unsigned from = 0;
Edouard@277
  1129
        result = PEP_KEY_NOT_FOUND;
Edouard@277
  1130
        while((key = (pgp_key_t *)pgp_getnextkeybyname(
Edouard@277
  1131
                        netpgp.io,
Edouard@277
  1132
                        (pgp_keyring_t *)netpgp.pubring, 
Edouard@277
  1133
			            (const char *)pattern,
Edouard@277
  1134
                        &from)) != NULL) {
Edouard@277
  1135
Edouard@277
  1136
            result = cb(cb_arg, key);
Edouard@277
  1137
            if (result != PEP_STATUS_OK)
Edouard@277
  1138
                break;
Edouard@277
  1139
Edouard@277
  1140
            from++;
Edouard@277
  1141
        }
Edouard@277
  1142
    }
Edouard@277
  1143
Edouard@277
  1144
    return result;
Edouard@277
  1145
}
Edouard@277
  1146
Edouard@277
  1147
static PEP_STATUS add_key_fpr_to_stringlist(void *arg, pgp_key_t *key)
Edouard@277
  1148
{
Edouard@277
  1149
    stringlist_t **keylist = arg;
Edouard@254
  1150
    char *newfprstr = NULL;
Edouard@254
  1151
Edouard@254
  1152
    fpr_to_str(&newfprstr,
Edouard@313
  1153
               key->pubkeyfpr.fingerprint,
Edouard@313
  1154
               key->pubkeyfpr.length);
Edouard@254
  1155
Edouard@254
  1156
    if (newfprstr == NULL) {
Edouard@254
  1157
        return PEP_OUT_OF_MEMORY;
Edouard@254
  1158
    } else { 
Edouard@254
  1159
Edouard@254
  1160
        *keylist = stringlist_add(*keylist, newfprstr);
Edouard@254
  1161
        if (*keylist == NULL) {
Edouard@254
  1162
            free(newfprstr);
Edouard@254
  1163
            return PEP_OUT_OF_MEMORY;
Edouard@254
  1164
        }
Edouard@254
  1165
    }
Edouard@254
  1166
    return PEP_STATUS_OK;
Edouard@254
  1167
}
Edouard@254
  1168
Edouard@174
  1169
PEP_STATUS pgp_find_keys(
Edouard@174
  1170
    PEP_SESSION session, const char *pattern, stringlist_t **keylist
Edouard@174
  1171
    )
Edouard@174
  1172
{
Edouard@254
  1173
    stringlist_t *_keylist, *_k;
Edouard@254
  1174
Edouard@254
  1175
    PEP_STATUS result;
Edouard@174
  1176
Edouard@174
  1177
    assert(session);
Edouard@174
  1178
    assert(pattern);
Edouard@174
  1179
    assert(keylist);
Edouard@174
  1180
Edouard@254
  1181
    if (!session || !pattern || !keylist )
Edouard@254
  1182
        return PEP_UNKNOWN_ERROR;
Edouard@174
  1183
Edouard@263
  1184
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@174
  1185
        return PEP_UNKNOWN_ERROR;
Edouard@254
  1186
    }
Edouard@254
  1187
Edouard@254
  1188
    *keylist = NULL;
Edouard@254
  1189
    _keylist = new_stringlist(NULL);
Edouard@254
  1190
    if (_k == NULL) {
Edouard@254
  1191
        result = PEP_OUT_OF_MEMORY;
Edouard@254
  1192
        goto unlock_netpgp;
Edouard@254
  1193
    }
Edouard@254
  1194
    _k = _keylist;
Edouard@254
  1195
Edouard@277
  1196
    result = find_keys_do(pattern, &add_key_fpr_to_stringlist, &_k);
Edouard@254
  1197
Edouard@254
  1198
    if (result == PEP_STATUS_OK) {
Edouard@254
  1199
        *keylist = _keylist;
Edouard@254
  1200
        // Transfer ownership, no free
Edouard@254
  1201
        goto unlock_netpgp;
Edouard@254
  1202
    }
Edouard@254
  1203
Edouard@254
  1204
free_keylist:
Edouard@254
  1205
    free_stringlist(_keylist);
Edouard@254
  1206
Edouard@254
  1207
unlock_netpgp:
Edouard@254
  1208
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@254
  1209
Edouard@254
  1210
    return result;
Edouard@174
  1211
}
Edouard@174
  1212
Edouard@277
  1213
static PEP_STATUS send_key_cb(void *arg, pgp_key_t *key)
Edouard@277
  1214
{
Edouard@318
  1215
    char *buffer = NULL;
Edouard@318
  1216
    size_t buflen = 0;
Edouard@318
  1217
    PEP_STATUS result;
Edouard@318
  1218
    stringlist_t *encoded_keys;
Edouard@318
  1219
    encoded_keys = (stringlist_t*)arg;
Edouard@277
  1220
Edouard@318
  1221
    result = _export_keydata(key, &buffer, &buflen);
Edouard@318
  1222
    
Edouard@318
  1223
    if(result == PEP_STATUS_OK){
Edouard@318
  1224
        char *encoded_key;
Edouard@318
  1225
        encoded_key = curl_escape(buffer, buflen);
Edouard@318
  1226
        if(!encoded_key){
Edouard@318
  1227
            return PEP_OUT_OF_MEMORY;
Edouard@318
  1228
        }
Edouard@318
  1229
        if(!stringlist_add(encoded_keys, buffer)){
Edouard@318
  1230
            result = PEP_OUT_OF_MEMORY;
Edouard@318
  1231
        }
Edouard@318
  1232
        curl_free(encoded_key);
Edouard@318
  1233
    }
Edouard@277
  1234
Edouard@318
  1235
    return result;
Edouard@277
  1236
}
Edouard@277
  1237
Edouard@174
  1238
PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
Edouard@174
  1239
{
Edouard@318
  1240
    static const char *ks_cmd = "http://keys.gnupg.net:11371/pks/add";
Edouard@318
  1241
Edouard@318
  1242
    stringlist_t *encoded_keys;
Edouard@318
  1243
    const stringlist_t *post;
Edouard@277
  1244
Edouard@277
  1245
    PEP_STATUS result;
Edouard@277
  1246
Edouard@174
  1247
    assert(session);
Edouard@174
  1248
    assert(pattern);
Edouard@174
  1249
Edouard@277
  1250
    if (!session || !pattern )
Edouard@277
  1251
        return PEP_UNKNOWN_ERROR;
Edouard@277
  1252
Edouard@318
  1253
    encoded_keys = new_stringlist(NULL);
Edouard@318
  1254
    assert(encoded_keys);
Edouard@318
  1255
    if (encoded_keys == NULL) {
Edouard@318
  1256
        return PEP_OUT_OF_MEMORY;
Edouard@318
  1257
    }
Edouard@318
  1258
Edouard@277
  1259
    if(pthread_mutex_lock(&netpgp_mutex)){
Edouard@277
  1260
        return PEP_UNKNOWN_ERROR;
Edouard@277
  1261
    }
Edouard@174
  1262
Edouard@318
  1263
    result = find_keys_do(pattern, &send_key_cb, (void*)encoded_keys);
Edouard@277
  1264
Edouard@277
  1265
unlock_netpgp:
Edouard@277
  1266
    pthread_mutex_unlock(&netpgp_mutex);
Edouard@277
  1267
Edouard@318
  1268
    if(pthread_mutex_lock(&session->ctx.curl_mutex)){
Edouard@318
  1269
        return PEP_UNKNOWN_ERROR;
Edouard@318
  1270
    }
Edouard@318
  1271
Edouard@318
  1272
    if(result == PEP_STATUS_OK){
Edouard@318
  1273
        CURLcode curlres;
Edouard@318
  1274
        CURL *curl;
Edouard@318
  1275
Edouard@318
  1276
        curl = session->ctx.curl;
Edouard@318
  1277
Edouard@318
  1278
        for (post = encoded_keys; post != NULL; post = post->next) {
Edouard@318
  1279
            assert(post->value);
Edouard@318
  1280
Edouard@318
  1281
            curl_easy_setopt(curl, CURLOPT_URL, ks_cmd);
Edouard@318
  1282
            curl_easy_setopt(curl, CURLOPT_POST, 1L);
Edouard@318
  1283
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post->value);
Edouard@318
  1284
            curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
Edouard@318
  1285
Edouard@318
  1286
            /* TODO remove */
Edouard@318
  1287
            curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
Edouard@318
  1288
Edouard@318
  1289
            curlres = curl_easy_perform(curl);
Edouard@318
  1290
Edouard@318
  1291
            if(curlres != CURLE_OK) {
Edouard@318
  1292
Edouard@318
  1293
                continue; /* TODO Stop ignoring it doens't work */
Edouard@318
  1294
Edouard@318
  1295
                result = PEP_CANNOT_SEND_KEY;
Edouard@318
  1296
                goto free_encoded_keys;
Edouard@318
  1297
            }
Edouard@318
  1298
        }
Edouard@318
  1299
    }
Edouard@318
  1300
Edouard@318
  1301
free_encoded_keys:
Edouard@318
  1302
    free_stringlist(encoded_keys);
Edouard@318
  1303
Edouard@318
  1304
unlock_curl:
Edouard@318
  1305
    pthread_mutex_unlock(&session->ctx.curl_mutex);
Edouard@318
  1306
Edouard@277
  1307
    return result;
Edouard@174
  1308
}
Edouard@174
  1309
Edouard@174
  1310
Edouard@174
  1311
PEP_STATUS pgp_get_key_rating(
Edouard@174
  1312
    PEP_SESSION session,
Edouard@174
  1313
    const char *fpr,
Edouard@174
  1314
    PEP_comm_type *comm_type
Edouard@174
  1315
    )
Edouard@174
  1316
{
Edouard@174
  1317
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@174
  1318
Edouard@174
  1319
    assert(session);
Edouard@174
  1320
    assert(fpr);
Edouard@174
  1321
    assert(comm_type);
Edouard@174
  1322
Edouard@174
  1323
    *comm_type = PEP_ct_unknown;
Edouard@174
  1324
Edouard@174
  1325
    /* TODO get key from fpr */
Edouard@174
  1326
    return PEP_UNKNOWN_ERROR;
Edouard@174
  1327
    return PEP_GET_KEY_FAILED;
Edouard@174
  1328
Edouard@174
  1329
    switch (/*TODO key->protocol*/ 4) {
Edouard@174
  1330
    case /* TODO  OpenPGP */0:
Edouard@174
  1331
    case /* TODO DEFAULT */1:
Edouard@174
  1332
        *comm_type = PEP_ct_OpenPGP_unconfirmed;
Edouard@174
  1333
        break;
Edouard@174
  1334
    case /* TODO CMS */2:
Edouard@174
  1335
        *comm_type = PEP_ct_CMS_unconfirmed;
Edouard@174
  1336
        break;
Edouard@174
  1337
    default:
Edouard@174
  1338
        *comm_type = PEP_ct_unknown;
Edouard@174
  1339
        return PEP_STATUS_OK;
Edouard@174
  1340
    }
Edouard@174
  1341
Edouard@174
  1342
        for (; 1 == 0; /* Each subkeys */ ) {
Edouard@174
  1343
            if (/* TODO length */0 < 1024)
Edouard@174
  1344
                *comm_type = PEP_ct_key_too_short;
Edouard@174
  1345
            else if (
Edouard@174
  1346
                (
Edouard@174
  1347
                (   /* TODO pubkey_algo == RSA  */ 0)
Edouard@174
  1348
                || (/* TODO pubkey_algo == RSA_E*/ 0)
Edouard@174
  1349
                || (/* TODO pubkey_algo == RSA_S*/ 0)
Edouard@174
  1350
                )
Edouard@174
  1351
                && /* sk->length */0 == 1024
Edouard@174
  1352
                )
Edouard@174
  1353
                *comm_type = PEP_ct_OpenPGP_weak_unconfirmed;
Edouard@174
  1354
Edouard@174
  1355
            if (/* TODO invalid */ 1) {
Edouard@174
  1356
                *comm_type = PEP_ct_key_b0rken;
Edouard@174
  1357
                break;
Edouard@174
  1358
            }
Edouard@174
  1359
            if (/* TODO expired */ 1) {
Edouard@174
  1360
                *comm_type = PEP_ct_key_expired;
Edouard@174
  1361
                break;
Edouard@174
  1362
            }
Edouard@175
  1363
            if (/* TODO revoked*/ 1) {
Edouard@174
  1364
                *comm_type = PEP_ct_key_revoked;
Edouard@174
  1365
                break;
Edouard@174
  1366
            }
Edouard@174
  1367
        }
Edouard@174
  1368
        *comm_type = PEP_ct_unknown;
Edouard@174
  1369
        return PEP_OUT_OF_MEMORY;
Edouard@174
  1370
        return PEP_UNKNOWN_ERROR;
Edouard@174
  1371
Edouard@174
  1372
Edouard@174
  1373
    return status;
Edouard@174
  1374
}
Edouard@210
  1375
Edouard@210
  1376
PEP_STATUS pgp_renew_key(
Edouard@210
  1377
        PEP_SESSION session,
Edouard@210
  1378
        const char *fpr,
Edouard@210
  1379
        const timestamp *ts
Edouard@210
  1380
    )
Edouard@210
  1381
{
Edouard@210
  1382
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@210
  1383
    char date_text[12];
Edouard@210
  1384
Edouard@210
  1385
    assert(session);
Edouard@210
  1386
    assert(fpr);
Edouard@210
  1387
Edouard@210
  1388
    snprintf(date_text, 12, "%.4d-%.2d-%.2d\n", ts->tm_year + 1900,
Edouard@210
  1389
            ts->tm_mon + 1, ts->tm_mday);
Edouard@210
  1390
Edouard@210
  1391
Edouard@210
  1392
        return PEP_UNKNOWN_ERROR;
Edouard@210
  1393
    return PEP_STATUS_OK;
Edouard@210
  1394
}
Edouard@210
  1395
Edouard@226
  1396
PEP_STATUS pgp_revoke_key(
Edouard@226
  1397
        PEP_SESSION session,
Edouard@226
  1398
        const char *fpr,
Edouard@226
  1399
        const char *reason
Edouard@226
  1400
    )
Edouard@210
  1401
{
Edouard@210
  1402
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@210
  1403
    
Edouard@210
  1404
    assert(session);
Edouard@210
  1405
    assert(fpr);
Edouard@210
  1406
Edouard@210
  1407
        return PEP_UNKNOWN_ERROR;
Edouard@210
  1408
Edouard@210
  1409
    return PEP_STATUS_OK;
Edouard@210
  1410
}
Edouard@210
  1411
Edouard@226
  1412
PEP_STATUS pgp_key_expired(
Edouard@226
  1413
        PEP_SESSION session,
Edouard@226
  1414
        const char *fpr,
Edouard@226
  1415
        bool *expired
Edouard@226
  1416
    )
Edouard@226
  1417
{
Edouard@226
  1418
    PEP_STATUS status = PEP_STATUS_OK;
Edouard@226
  1419
Edouard@226
  1420
    assert(session);
Edouard@226
  1421
    assert(fpr);
Edouard@226
  1422
    assert(expired);
Edouard@226
  1423
Edouard@226
  1424
    *expired = false;
Edouard@226
  1425
Edouard@226
  1426
    if (status != PEP_STATUS_OK)
Edouard@226
  1427
        return status;
Edouard@226
  1428
Edouard@226
  1429
    return PEP_STATUS_OK;
Edouard@226
  1430
}
Edouard@226
  1431