~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

« back to all changes in this revision

Viewing changes to libclamav/crypto.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-07-15 01:08:10 UTC
  • mfrom: (0.35.47 sid)
  • Revision ID: package-import@ubuntu.com-20140715010810-ru66ek4fun2iseba
Tags: 0.98.4+dfsg-2~ubuntu13.10.1
No-change backport to saucy (LP: #1341962)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
 
3
 *
 
4
 *  Author: Shawn Webb
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License version 2 as
 
8
 *  published by the Free Software Foundation.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
18
 *  MA 02110-1301, USA.
 
19
 *
 
20
 *  In addition, as a special exception, the copyright holders give
 
21
 *  permission to link the code of portions of this program with the
 
22
 *  OpenSSL library under certain conditions as described in each
 
23
 *  individual source file, and distribute linked combinations
 
24
 *  including the two.
 
25
 *  
 
26
 *  You must obey the GNU General Public License in all respects
 
27
 *  for all of the code used other than OpenSSL.  If you modify
 
28
 *  file(s) with this exception, you may extend this exception to your
 
29
 *  version of the file(s), but you are not obligated to do so.  If you
 
30
 *  do not wish to do so, delete this exception statement from your
 
31
 *  version.  If you delete this exception statement from all source
 
32
 *  files in the program, then also delete it here.
 
33
 */
 
34
 
 
35
#if HAVE_CONFIG_H
 
36
#include "clamav-config.h"
 
37
#endif
 
38
 
 
39
#include <stdio.h>
 
40
#include <stdlib.h>
 
41
#include <string.h>
 
42
 
 
43
#include <time.h>
 
44
 
 
45
#ifdef _WIN32
 
46
#include <io.h>
 
47
#endif
 
48
 
 
49
#include <sys/types.h>
 
50
#include <dirent.h>
 
51
#include <sys/stat.h>
 
52
#include <fcntl.h>
 
53
 
 
54
#if !defined(_WIN32)
 
55
#include <unistd.h>
 
56
#endif
 
57
 
 
58
#include <openssl/ssl.h>
 
59
#include <openssl/err.h>
 
60
#include "libclamav/crypto.h"
 
61
 
 
62
#include "clamav.h"
 
63
#include "default.h"
 
64
#include "others.h"
 
65
#include "libclamav/conv.h"
 
66
#include "libclamav/str.h"
 
67
 
 
68
#if defined(_WIN32)
 
69
char * strptime(const char *buf, const char *fmt, struct tm *tm);
 
70
#endif
 
71
 
 
72
#if !defined(MIN)
 
73
    #define MIN(x,y) ((x)<(y)?(x):(y))
 
74
#endif
 
75
 
 
76
#if !defined(HAVE_TIMEGM) && !defined(_WIN32)
 
77
/*
 
78
 * Solaris 10 and earlier don't have timegm. Provide a portable version of it.
 
79
 * A special thank you to Dave Simonson for helping test and develop this.
 
80
 */
 
81
time_t timegm(struct tm *t)
 
82
{
 
83
    time_t tl, tb;
 
84
    struct tm *tg;
 
85
 
 
86
    tl = mktime (t);
 
87
    if (tl == -1)
 
88
    {
 
89
        t->tm_hour--;
 
90
        tl = mktime (t);
 
91
        if (tl == -1)
 
92
            return -1; /* can't deal with output from strptime */
 
93
        tl += 3600;
 
94
    }
 
95
 
 
96
    tg = gmtime (&tl);
 
97
    tg->tm_isdst = 0;
 
98
    tb = mktime (tg);
 
99
 
 
100
    if (tb == -1)
 
101
    {
 
102
        tg->tm_hour--;
 
103
        tb = mktime (tg);
 
104
        if (tb == -1)
 
105
            return -1; /* can't deal with output from gmtime */
 
106
 
 
107
        tb += 3600;
 
108
    }
 
109
 
 
110
    return (tl - (tb - tl));
 
111
}
 
112
#endif
 
113
 
 
114
int cl_initialize_crypto(void)
 
115
{
 
116
    SSL_load_error_strings();
 
117
    SSL_library_init();
 
118
    OpenSSL_add_all_digests();
 
119
    OpenSSL_add_all_algorithms();
 
120
    OpenSSL_add_all_ciphers();
 
121
    ERR_load_crypto_strings();
 
122
 
 
123
    return 0;
 
124
}
 
125
 
 
126
void cl_cleanup_crypto(void)
 
127
{
 
128
    EVP_cleanup();
 
129
}
 
130
 
 
131
unsigned char *cl_hash_data(char *alg, const void *buf, size_t len, unsigned char *obuf, unsigned int *olen)
 
132
{
 
133
    EVP_MD_CTX *ctx;
 
134
    unsigned char *ret;
 
135
    size_t mdsz;
 
136
    const EVP_MD *md;
 
137
    unsigned int i;
 
138
    size_t cur;
 
139
 
 
140
    md = EVP_get_digestbyname(alg);
 
141
    if (!(md))
 
142
        return NULL;
 
143
 
 
144
    mdsz = EVP_MD_size(md);
 
145
 
 
146
    ret = (obuf != NULL) ? obuf : (unsigned char *)malloc(mdsz);
 
147
    if (!(ret))
 
148
        return NULL;
 
149
 
 
150
    ctx = EVP_MD_CTX_create();
 
151
    if (!(ctx)) {
 
152
        if (!(obuf))
 
153
            free(ret);
 
154
 
 
155
        return NULL;
 
156
    }
 
157
 
 
158
    if (!EVP_DigestInit_ex(ctx, md, NULL)) {
 
159
        if (!(obuf))
 
160
            free(ret);
 
161
 
 
162
        if ((olen))
 
163
            *olen = 0;
 
164
 
 
165
        EVP_MD_CTX_destroy(ctx);
 
166
        return NULL;
 
167
    }
 
168
 
 
169
    cur=0;
 
170
    while (cur < len) {
 
171
        size_t todo = MIN(EVP_MD_block_size(md), len-cur);
 
172
        if (!EVP_DigestUpdate(ctx, (void *)(((unsigned char *)buf)+cur), todo)) {
 
173
            if (!(obuf))
 
174
                free(ret);
 
175
 
 
176
            if ((olen))
 
177
                *olen = 0;
 
178
 
 
179
            EVP_MD_CTX_destroy(ctx);
 
180
            return NULL;
 
181
        }
 
182
 
 
183
        cur += todo;
 
184
    }
 
185
 
 
186
    if (!EVP_DigestFinal_ex(ctx, ret, &i)) {
 
187
        if (!(obuf))
 
188
            free(ret);
 
189
 
 
190
        if ((olen))
 
191
            *olen = 0;
 
192
 
 
193
        EVP_MD_CTX_destroy(ctx);
 
194
        return NULL;
 
195
    }
 
196
 
 
197
    EVP_MD_CTX_destroy(ctx);
 
198
 
 
199
    if ((olen))
 
200
        *olen = i;
 
201
 
 
202
    return ret;
 
203
}
 
204
 
 
205
unsigned char *cl_hash_file_fd(int fd, char *alg, unsigned int *olen)
 
206
{
 
207
    EVP_MD_CTX *ctx;
 
208
    const EVP_MD *md;
 
209
    unsigned char *res;
 
210
 
 
211
    md = EVP_get_digestbyname(alg);
 
212
    if (!(md))
 
213
        return NULL;
 
214
 
 
215
    ctx = EVP_MD_CTX_create();
 
216
    if (!(ctx))
 
217
        return NULL;
 
218
 
 
219
    if (!EVP_DigestInit_ex(ctx, md, NULL)) {
 
220
        EVP_MD_CTX_destroy(ctx);
 
221
        return NULL;
 
222
    }
 
223
 
 
224
    res = cl_hash_file_fd_ctx(ctx, fd, olen);
 
225
    EVP_MD_CTX_destroy(ctx);
 
226
 
 
227
    return res;
 
228
}
 
229
 
 
230
unsigned char *cl_hash_file_fd_ctx(EVP_MD_CTX *ctx, int fd, unsigned int *olen)
 
231
{
 
232
    unsigned char *buf;
 
233
    unsigned char *hash;
 
234
    int mdsz;
 
235
    unsigned int hashlen;
 
236
    STATBUF sb;
 
237
 
 
238
        unsigned int blocksize;
 
239
 
 
240
#ifdef _WIN32
 
241
    int nread;
 
242
#else
 
243
    ssize_t nread;
 
244
#endif
 
245
 
 
246
    mdsz = EVP_MD_CTX_size(ctx);
 
247
 
 
248
    if (FSTAT(fd, &sb) < 0) {
 
249
        return NULL;
 
250
    }
 
251
 
 
252
#ifdef _WIN32
 
253
        blocksize = 8192;
 
254
#else
 
255
        blocksize = sb.st_blksize;
 
256
#endif
 
257
 
 
258
    buf = (unsigned char *)malloc(blocksize);
 
259
    if (!(buf)) {
 
260
        return NULL;
 
261
    }
 
262
 
 
263
    hash = (unsigned char *)malloc(mdsz);
 
264
    if (!(hash)) {
 
265
        free(buf);
 
266
        return NULL;
 
267
    }
 
268
 
 
269
#ifdef _WIN32
 
270
    while ((nread = _read(fd, buf, blocksize)) > 0) {
 
271
#else
 
272
    while ((nread = read(fd, buf, blocksize)) > 0) {
 
273
#endif
 
274
        if (!EVP_DigestUpdate(ctx, buf, nread)) {
 
275
            free(buf);
 
276
            free(hash);
 
277
 
 
278
            return NULL;
 
279
        }
 
280
    }
 
281
 
 
282
    if (!EVP_DigestFinal_ex(ctx, hash, &hashlen)) {
 
283
        free(hash);
 
284
        free(buf);
 
285
 
 
286
        return NULL;
 
287
    }
 
288
 
 
289
    if ((olen))
 
290
        *olen = hashlen;
 
291
 
 
292
    free(buf);
 
293
 
 
294
    return hash;
 
295
}
 
296
 
 
297
unsigned char *cl_hash_file_fp(FILE *fp, char *alg, unsigned int *olen)
 
298
{
 
299
    return cl_hash_file_fd(fileno(fp), alg, olen);
 
300
}
 
301
 
 
302
unsigned char *cl_sha256(const void *buf, size_t len, unsigned char *obuf, unsigned int *olen)
 
303
{
 
304
    return cl_hash_data("sha256", buf, len, obuf, olen);
 
305
}
 
306
 
 
307
unsigned char *cl_sha1(const void *buf, size_t len, unsigned char *obuf, unsigned int *olen)
 
308
{
 
309
    return cl_hash_data("sha1", buf, len, obuf, olen);
 
310
}
 
311
 
 
312
int cl_verify_signature_hash(EVP_PKEY *pkey, char *alg, unsigned char *sig, unsigned int siglen, unsigned char *digest)
 
313
{
 
314
    EVP_MD_CTX *ctx;
 
315
    const EVP_MD *md;
 
316
    size_t mdsz;
 
317
 
 
318
    md = EVP_get_digestbyname(alg);
 
319
    if (!(md))
 
320
        return -1;
 
321
 
 
322
    ctx = EVP_MD_CTX_create();
 
323
    if (!(ctx))
 
324
        return -1;
 
325
 
 
326
    mdsz = EVP_MD_size(md);
 
327
 
 
328
    if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
 
329
        EVP_MD_CTX_destroy(ctx);
 
330
        return -1;
 
331
    }
 
332
 
 
333
    if (!EVP_VerifyUpdate(ctx, digest, mdsz)) {
 
334
        EVP_MD_CTX_destroy(ctx);
 
335
        return -1;
 
336
    }
 
337
 
 
338
    if (EVP_VerifyFinal(ctx, sig, siglen, pkey) != 0) {
 
339
        EVP_MD_CTX_destroy(ctx);
 
340
        return -1;
 
341
    }
 
342
 
 
343
    EVP_MD_CTX_destroy(ctx);
 
344
    return 0;
 
345
}
 
346
 
 
347
int cl_verify_signature_fd(EVP_PKEY *pkey, char *alg, unsigned char *sig, unsigned int siglen, int fd)
 
348
{
 
349
    EVP_MD_CTX *ctx;
 
350
    const EVP_MD *md;
 
351
    size_t mdsz;
 
352
    unsigned char *digest;
 
353
 
 
354
    digest = cl_hash_file_fd(fd, alg, NULL);
 
355
    if (!(digest))
 
356
        return -1;
 
357
 
 
358
    md = EVP_get_digestbyname(alg);
 
359
    if (!(md)) {
 
360
        free(digest);
 
361
        return -1;
 
362
    }
 
363
 
 
364
    mdsz = EVP_MD_size(md);
 
365
 
 
366
    ctx = EVP_MD_CTX_create();
 
367
    if (!(ctx)) {
 
368
        free(digest);
 
369
        return -1;
 
370
    }
 
371
 
 
372
    if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
 
373
        free(digest);
 
374
        EVP_MD_CTX_destroy(ctx);
 
375
        return -1;
 
376
    }
 
377
 
 
378
    if (!EVP_VerifyUpdate(ctx, digest, mdsz)) {
 
379
        free(digest);
 
380
        EVP_MD_CTX_destroy(ctx);
 
381
        return -1;
 
382
    }
 
383
 
 
384
    if (EVP_VerifyFinal(ctx, sig, siglen, pkey) != 0) {
 
385
        free(digest);
 
386
        EVP_MD_CTX_destroy(ctx);
 
387
        return -1;
 
388
    }
 
389
 
 
390
    free(digest);
 
391
    EVP_MD_CTX_destroy(ctx);
 
392
    return 0;
 
393
}
 
394
 
 
395
int cl_verify_signature(EVP_PKEY *pkey, char *alg, unsigned char *sig, unsigned int siglen, unsigned char *data, size_t datalen, int decode)
 
396
{
 
397
    EVP_MD_CTX *ctx;
 
398
    const EVP_MD *md;
 
399
    size_t mdsz;
 
400
    unsigned char *digest;
 
401
 
 
402
    if (decode) {
 
403
        unsigned char *newsig;
 
404
        size_t newsiglen;
 
405
 
 
406
        newsig = (unsigned char *)cl_base64_decode((char *)sig, siglen, NULL, &newsiglen);
 
407
        if (!(newsig))
 
408
            return -1;
 
409
 
 
410
        sig = newsig;
 
411
        siglen = newsiglen;
 
412
    }
 
413
 
 
414
    digest = cl_hash_data(alg, data, datalen, NULL, NULL);
 
415
    if (!(digest)) {
 
416
        if (decode)
 
417
            free(sig);
 
418
 
 
419
        return -1;
 
420
    }
 
421
 
 
422
    md = EVP_get_digestbyname(alg);
 
423
    if (!(md)) {
 
424
        free(digest);
 
425
        if (decode)
 
426
            free(sig);
 
427
 
 
428
        return -1;
 
429
    }
 
430
 
 
431
    mdsz = EVP_MD_size(md);
 
432
 
 
433
    ctx = EVP_MD_CTX_create();
 
434
    if (!(ctx)) {
 
435
        free(digest);
 
436
        if (decode)
 
437
            free(sig);
 
438
 
 
439
        return -1;
 
440
    }
 
441
 
 
442
    if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
 
443
        free(digest);
 
444
        if (decode)
 
445
            free(sig);
 
446
 
 
447
        EVP_MD_CTX_destroy(ctx);
 
448
        return -1;
 
449
    }
 
450
 
 
451
    if (!EVP_VerifyUpdate(ctx, digest, mdsz)) {
 
452
        free(digest);
 
453
        if (decode)
 
454
            free(sig);
 
455
 
 
456
        EVP_MD_CTX_destroy(ctx);
 
457
        return -1;
 
458
    }
 
459
 
 
460
    if (EVP_VerifyFinal(ctx, sig, siglen, pkey) != 0) {
 
461
        free(digest);
 
462
        if (decode)
 
463
            free(sig);
 
464
 
 
465
        EVP_MD_CTX_destroy(ctx);
 
466
        return -1;
 
467
    }
 
468
 
 
469
    if (decode)
 
470
        free(sig);
 
471
 
 
472
    free(digest);
 
473
    EVP_MD_CTX_destroy(ctx);
 
474
    return 0;
 
475
}
 
476
 
 
477
int cl_verify_signature_hash_x509_keyfile(char *x509path, char *alg, unsigned char *sig, unsigned int siglen, unsigned char *digest)
 
478
{
 
479
    X509 *x509;
 
480
    FILE *fp;
 
481
    int res;
 
482
 
 
483
    fp = fopen(x509path, "r");
 
484
    if (!(fp)) {
 
485
        return -1;
 
486
    }
 
487
 
 
488
    x509 = PEM_read_X509(fp, NULL, NULL, NULL);
 
489
    if (!(x509)) {
 
490
        fclose(fp);
 
491
        return -1;
 
492
    }
 
493
 
 
494
    fclose(fp);
 
495
 
 
496
    res = cl_verify_signature_hash_x509(x509, alg, sig, siglen, digest);
 
497
 
 
498
    X509_free(x509);
 
499
 
 
500
    return res;
 
501
}
 
502
 
 
503
int cl_verify_signature_fd_x509_keyfile(char *x509path, char *alg, unsigned char *sig, unsigned int siglen, int fd)
 
504
{
 
505
    X509 *x509;
 
506
    FILE *fp;
 
507
    int res;
 
508
 
 
509
    fp = fopen(x509path, "r");
 
510
    if (!(fp)) {
 
511
        return -1;
 
512
    }
 
513
 
 
514
    x509 = PEM_read_X509(fp, NULL, NULL, NULL);
 
515
    if (!(x509)) {
 
516
        fclose(fp);
 
517
        return -1;
 
518
    }
 
519
 
 
520
    fclose(fp);
 
521
 
 
522
    res = cl_verify_signature_fd_x509(x509, alg, sig, siglen, fd);
 
523
 
 
524
    X509_free(x509);
 
525
 
 
526
    return res;
 
527
}
 
528
 
 
529
int cl_verify_signature_x509_keyfile(char *x509path, char *alg, unsigned char *sig, unsigned int siglen, unsigned char *data, size_t datalen, int decode)
 
530
{
 
531
    X509 *x509;
 
532
    FILE *fp;
 
533
    int res;
 
534
 
 
535
    fp = fopen(x509path, "r");
 
536
    if (!(fp)) {
 
537
        return -1;
 
538
    }
 
539
 
 
540
    x509 = PEM_read_X509(fp, NULL, NULL, NULL);
 
541
    if (!(x509)) {
 
542
        fclose(fp);
 
543
        return -1;
 
544
    }
 
545
 
 
546
    fclose(fp);
 
547
 
 
548
    res = cl_verify_signature_x509(x509, alg, sig, siglen, data, datalen, decode);
 
549
 
 
550
    X509_free(x509);
 
551
 
 
552
    return res;
 
553
}
 
554
 
 
555
int cl_verify_signature_hash_x509(X509 *x509, char *alg, unsigned char *sig, unsigned int siglen, unsigned char *digest)
 
556
{
 
557
    EVP_PKEY *pkey;
 
558
    int res;
 
559
 
 
560
    pkey = X509_get_pubkey(x509);
 
561
    if (!(pkey))
 
562
        return -1;
 
563
 
 
564
    res = cl_verify_signature_hash(pkey, alg, sig, siglen, digest);
 
565
 
 
566
    EVP_PKEY_free(pkey);
 
567
 
 
568
    return res;
 
569
}
 
570
 
 
571
int cl_verify_signature_fd_x509(X509 *x509, char *alg, unsigned char *sig, unsigned int siglen, int fd)
 
572
{
 
573
    EVP_PKEY *pkey;
 
574
    int res;
 
575
 
 
576
    pkey = X509_get_pubkey(x509);
 
577
    if (!(pkey))
 
578
        return -1;
 
579
 
 
580
    res = cl_verify_signature_fd(pkey, alg, sig, siglen, fd);
 
581
 
 
582
    EVP_PKEY_free(pkey);
 
583
 
 
584
    return res;
 
585
}
 
586
 
 
587
int cl_verify_signature_x509(X509 *x509, char *alg, unsigned char *sig, unsigned int siglen, unsigned char *data, size_t datalen, int decode)
 
588
{
 
589
    EVP_PKEY *pkey;
 
590
    int res;
 
591
 
 
592
    pkey = X509_get_pubkey(x509);
 
593
    if (!(pkey))
 
594
        return -1;
 
595
 
 
596
    res = cl_verify_signature(pkey, alg, sig, siglen, data, datalen, decode);
 
597
 
 
598
    EVP_PKEY_free(pkey);
 
599
 
 
600
    return res;
 
601
}
 
602
 
 
603
unsigned char *cl_sign_data_keyfile(char *keypath, char *alg, unsigned char *hash, unsigned int *olen, int encode)
 
604
{
 
605
    FILE *fp;
 
606
    EVP_PKEY *pkey;
 
607
    unsigned char *res;
 
608
 
 
609
    fp = fopen(keypath, "r");
 
610
    if (!(fp)) {
 
611
        return NULL;
 
612
    }
 
613
 
 
614
    pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
 
615
    if (!(pkey)) {
 
616
        fclose(fp);
 
617
        return NULL;
 
618
    }
 
619
 
 
620
    fclose(fp);
 
621
 
 
622
    res = cl_sign_data(pkey, alg, hash, olen, encode);
 
623
 
 
624
    EVP_PKEY_free(pkey);
 
625
 
 
626
    return res;
 
627
}
 
628
 
 
629
unsigned char *cl_sign_data(EVP_PKEY *pkey, char *alg, unsigned char *hash, unsigned int *olen, int encode)
 
630
{
 
631
    EVP_MD_CTX *ctx;
 
632
    const EVP_MD *md;
 
633
    unsigned int siglen;
 
634
    unsigned char *sig;
 
635
 
 
636
    md = EVP_get_digestbyname(alg);
 
637
    if (!(md))
 
638
        return NULL;
 
639
 
 
640
    ctx = EVP_MD_CTX_create();
 
641
    if (!(ctx))
 
642
        return NULL;
 
643
 
 
644
    sig = (unsigned char *)calloc(1, EVP_PKEY_size(pkey));
 
645
    if (!(sig)) {
 
646
        EVP_MD_CTX_destroy(ctx);
 
647
        return NULL;
 
648
    }
 
649
 
 
650
    if (!EVP_SignInit_ex(ctx, md, NULL)) {
 
651
        free(sig);
 
652
        EVP_MD_CTX_destroy(ctx);
 
653
        return NULL;
 
654
    }
 
655
 
 
656
    if (!EVP_SignUpdate(ctx, hash, EVP_MD_size(md))) {
 
657
        free(sig);
 
658
        EVP_MD_CTX_destroy(ctx);
 
659
        return NULL;
 
660
    }
 
661
 
 
662
    if (!EVP_SignFinal(ctx, sig, &siglen, pkey)) {
 
663
        free(sig);
 
664
        EVP_MD_CTX_destroy(ctx);
 
665
        return NULL;
 
666
    }
 
667
 
 
668
    if (encode) {
 
669
        unsigned char *newsig = (unsigned char *)cl_base64_encode(sig, siglen);
 
670
        if (!(newsig)) {
 
671
            free(sig);
 
672
            EVP_MD_CTX_destroy(ctx);
 
673
            return NULL;
 
674
        }
 
675
 
 
676
        free(sig);
 
677
        sig = newsig;
 
678
        siglen = (unsigned int)strlen((const char *)newsig);
 
679
    }
 
680
 
 
681
    *olen = siglen;
 
682
    EVP_MD_CTX_destroy(ctx);
 
683
    return sig;
 
684
}
 
685
 
 
686
unsigned char *cl_sign_file_fd(int fd, EVP_PKEY *pkey, char *alg, unsigned int *olen, int encode)
 
687
{
 
688
    unsigned char *hash, *res;
 
689
    unsigned int hashlen;
 
690
 
 
691
    hash = cl_hash_file_fd(fd, alg, &hashlen);
 
692
    if (!(hash)) {
 
693
        return NULL;
 
694
    }
 
695
 
 
696
    res = cl_sign_data(pkey, alg, hash, olen, encode);
 
697
 
 
698
    free(hash);
 
699
    return res;
 
700
}
 
701
 
 
702
unsigned char *cl_sign_file_fp(FILE *fp, EVP_PKEY *pkey, char *alg, unsigned int *olen, int encode)
 
703
{
 
704
    return cl_sign_file_fd(fileno(fp), pkey, alg, olen, encode);
 
705
}
 
706
 
 
707
EVP_PKEY *cl_get_pkey_file(char *keypath)
 
708
{
 
709
    EVP_PKEY *pkey;
 
710
    FILE *fp;
 
711
 
 
712
    fp = fopen(keypath, "r");
 
713
    if (!(fp))
 
714
        return NULL;
 
715
 
 
716
    if (!(pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))) {
 
717
        fclose(fp);
 
718
        return NULL;
 
719
    }
 
720
 
 
721
    fclose(fp);
 
722
 
 
723
    return pkey;
 
724
}
 
725
 
 
726
X509 *cl_get_x509_from_mem(void *data, unsigned int len)
 
727
{
 
728
    X509 *cert;
 
729
    BIO *cbio;
 
730
 
 
731
    cbio = BIO_new_mem_buf(data, len);
 
732
    if (!(cbio))
 
733
        return NULL;
 
734
 
 
735
    cert = PEM_read_bio_X509(cbio, NULL, 0, NULL);
 
736
    BIO_free(cbio);
 
737
 
 
738
    return cert;
 
739
}
 
740
 
 
741
int cl_validate_certificate_chain_ts_dir(char *tsdir, char *certpath)
 
742
{
 
743
    char **authorities=NULL, **t, *fullpath;
 
744
    size_t nauths = 0;
 
745
    int res;
 
746
    DIR *dp;
 
747
    struct dirent *dirent;
 
748
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
 
749
    union {
 
750
        struct dirent d;
 
751
        char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
 
752
    } result;
 
753
#endif
 
754
 
 
755
    dp = opendir(tsdir);
 
756
    if (!(dp))
 
757
        return CL_EOPEN;
 
758
 
 
759
#if defined(HAVE_READDIR_R_3)
 
760
    while (!readdir_r(dp, &result.d, &dirent) && dirent) {
 
761
#elif defined(HAVE_READDIR_R_2)
 
762
    while ((dirent = (struct dirent *)readdir_r(dp, &result.d))) {
 
763
#else
 
764
    while ((dirent = readdir(dp))) {
 
765
#endif
 
766
        if (dirent->d_name[0] == '.')
 
767
            continue;
 
768
 
 
769
        if (!cli_strbcasestr(dirent->d_name, ".crt"))
 
770
            continue;
 
771
 
 
772
        t = (char **)realloc(authorities, sizeof(char **) * (nauths + 1));
 
773
        if (!(t)) {
 
774
            if (nauths) {
 
775
                while (nauths > 0)
 
776
                    free(authorities[--nauths]);
 
777
                free(authorities);
 
778
            }
 
779
 
 
780
            closedir(dp);
 
781
            return -1;
 
782
        }
 
783
 
 
784
        authorities = t;
 
785
        authorities[nauths] = (char *)malloc(strlen(tsdir) + strlen(dirent->d_name) + 2);
 
786
        if (!authorities[nauths]) {
 
787
            if (nauths) {
 
788
                while (nauths > 0)
 
789
                    free(authorities[nauths--]);
 
790
                free(authorities[0]);
 
791
            }
 
792
 
 
793
            free(authorities);
 
794
            closedir(dp);
 
795
            return -1;
 
796
        }
 
797
 
 
798
        sprintf(authorities[nauths], "%s"PATHSEP"%s", tsdir, dirent->d_name);
 
799
        nauths++;
 
800
    }
 
801
 
 
802
    closedir(dp);
 
803
 
 
804
    t = (char **)realloc(authorities, sizeof(char **) * (nauths + 1));
 
805
    if (!(t)) {
 
806
        if (nauths) {
 
807
            while (nauths > 0)
 
808
                free(authorities[--nauths]);
 
809
            free(authorities);
 
810
        }
 
811
 
 
812
        return -1;
 
813
    }
 
814
 
 
815
    authorities = t;
 
816
    authorities[nauths] = NULL;
 
817
 
 
818
    res = cl_validate_certificate_chain(authorities, NULL, certpath);
 
819
 
 
820
    while (nauths > 0)
 
821
        free(authorities[--nauths]);
 
822
    
 
823
    free(authorities);
 
824
 
 
825
    return res;
 
826
}
 
827
 
 
828
int cl_validate_certificate_chain(char **authorities, char *crlpath, char *certpath)
 
829
{
 
830
    X509_STORE *store=NULL;
 
831
    X509_STORE_CTX *store_ctx;
 
832
    X509_LOOKUP *lookup=NULL;
 
833
    X509_CRL *crl=NULL;
 
834
    X509_VERIFY_PARAM *param=NULL;
 
835
    X509 *cert;
 
836
    unsigned long i;
 
837
    int res;
 
838
 
 
839
    store = X509_STORE_new();
 
840
    if (!(store)) {
 
841
        return -1;
 
842
    }
 
843
    X509_STORE_set_flags(store, 0);
 
844
 
 
845
    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
 
846
    if (!(lookup)) {
 
847
        X509_STORE_free(store);
 
848
        return -1;
 
849
    }
 
850
 
 
851
    if ((crlpath)) {
 
852
 
 
853
        crl = cl_load_crl(crlpath);
 
854
        if (!(crl)) {
 
855
            X509_STORE_free(store);
 
856
            return -1;
 
857
        }
 
858
 
 
859
        X509_STORE_add_crl(store, crl);
 
860
        param = X509_VERIFY_PARAM_new();
 
861
        if ((param)) {
 
862
            X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
 
863
            X509_STORE_set1_param(store, param);
 
864
        } else {
 
865
            X509_STORE_free(store);
 
866
            X509_CRL_free(crl);
 
867
            return -1;
 
868
        }
 
869
    }
 
870
 
 
871
    /* Support multi-tiered setups */
 
872
    for (i=0; authorities[i]; i++) {
 
873
        if (!X509_LOOKUP_load_file(lookup, authorities[i], X509_FILETYPE_PEM)) {
 
874
            X509_STORE_free(store);
 
875
            if ((crl))
 
876
                X509_CRL_free(crl);
 
877
            if ((param))
 
878
                X509_VERIFY_PARAM_free(param);
 
879
            return -1;
 
880
        }
 
881
    }
 
882
 
 
883
    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
 
884
    if (!(lookup)) {
 
885
        X509_STORE_free(store);
 
886
        if ((crl))
 
887
            X509_CRL_free(crl);
 
888
        if ((param))
 
889
            X509_VERIFY_PARAM_free(param);
 
890
        return -1;
 
891
    }
 
892
 
 
893
    X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
 
894
 
 
895
    store_ctx = X509_STORE_CTX_new();
 
896
    if (!(store_ctx)) {
 
897
        X509_STORE_free(store);
 
898
        if ((crl))
 
899
            X509_CRL_free(crl);
 
900
        if ((param))
 
901
            X509_VERIFY_PARAM_free(param);
 
902
        return -1;
 
903
    }
 
904
 
 
905
    cert = cl_load_cert(certpath);
 
906
    if (!(cert)) {
 
907
        X509_STORE_CTX_free(store_ctx);
 
908
        X509_STORE_free(store);
 
909
        if ((crl))
 
910
            X509_CRL_free(crl);
 
911
        if ((param))
 
912
            X509_VERIFY_PARAM_free(param);
 
913
 
 
914
        return -1;
 
915
    }
 
916
 
 
917
    if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) {
 
918
        X509_STORE_CTX_free(store_ctx);
 
919
        X509_STORE_free(store);
 
920
        if ((crl))
 
921
            X509_CRL_free(crl);
 
922
        if ((param))
 
923
            X509_VERIFY_PARAM_free(param);
 
924
 
 
925
        X509_free(cert);
 
926
 
 
927
        return -1;
 
928
    }
 
929
 
 
930
    res = X509_verify_cert(store_ctx);
 
931
 
 
932
    X509_STORE_CTX_free(store_ctx);
 
933
    if ((crl))
 
934
        X509_CRL_free(crl);
 
935
 
 
936
    if ((param))
 
937
        X509_VERIFY_PARAM_free(param);
 
938
 
 
939
    X509_STORE_free(store);
 
940
 
 
941
    X509_free(cert);
 
942
 
 
943
    return (res > 0);
 
944
}
 
945
 
 
946
X509 *cl_load_cert(const char *certpath)
 
947
{
 
948
    X509 *cert;
 
949
    BIO *bio;
 
950
 
 
951
    bio = BIO_new(BIO_s_file());
 
952
    if (!(bio))
 
953
        return NULL;
 
954
 
 
955
    if (BIO_read_filename(bio, certpath) != 1) {
 
956
        BIO_free(bio);
 
957
        return NULL;
 
958
    }
 
959
 
 
960
    cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
 
961
 
 
962
    BIO_free(bio);
 
963
 
 
964
    return cert;
 
965
}
 
966
 
 
967
struct tm *cl_ASN1_GetTimeT(ASN1_TIME *timeobj)
 
968
{
 
969
    struct tm *t;
 
970
    char* str;
 
971
    size_t i = 0;
 
972
    const char *fmt=NULL;
 
973
    time_t localt;
 
974
#ifdef _WIN32
 
975
    struct tm localtm, *ltm;
 
976
#else
 
977
    struct tm localtm;
 
978
#endif
 
979
 
 
980
    if (!(timeobj) || !(timeobj->data))
 
981
        return NULL;
 
982
 
 
983
    str = (char *)(timeobj->data);
 
984
    if (strlen(str) < 12)
 
985
        return NULL;
 
986
 
 
987
    t = (struct tm *)calloc(1, sizeof(struct tm));
 
988
    if (!(t))
 
989
        return NULL;
 
990
 
 
991
    if (timeobj->type == V_ASN1_UTCTIME) {
 
992
        /* two digit year */
 
993
        fmt = "%y%m%d%H%M%S";
 
994
        if (str[3] == '0') {
 
995
            str[2] = '0';
 
996
            str[3] = '9';
 
997
        } else {
 
998
            str[3]--;
 
999
        }
 
1000
    }
 
1001
    else if (timeobj->type == V_ASN1_GENERALIZEDTIME) {
 
1002
        /* four digit year */
 
1003
        fmt = "%Y%m%d%H%M%S";
 
1004
        if (str[5] == '0') {
 
1005
            str[4] = '0';
 
1006
            str[5] = '9';
 
1007
        } else {
 
1008
            str[5]--;
 
1009
        }
 
1010
    }
 
1011
 
 
1012
    if (!(fmt)) {
 
1013
        free(t);
 
1014
        return NULL;
 
1015
    }
 
1016
 
 
1017
    if (!strptime(str, fmt, t)) {
 
1018
        free(t);
 
1019
        return NULL;
 
1020
    }
 
1021
 
 
1022
    /* Convert to local time */
 
1023
    localt = time(NULL);
 
1024
#ifdef _WIN32
 
1025
    ltm = localtime(&localt);
 
1026
    memcpy((void *)(&localtm), (void *)ltm, sizeof(struct tm));
 
1027
#else
 
1028
    localtime_r(&localt, &localtm);
 
1029
#endif
 
1030
    t->tm_isdst = localtm.tm_isdst;
 
1031
    return t;
 
1032
}
 
1033
 
 
1034
X509_CRL *cl_load_crl(const char *file)
 
1035
{
 
1036
    X509_CRL *x=NULL;
 
1037
    FILE *fp;
 
1038
    struct tm *tm;
 
1039
    time_t crltime;
 
1040
 
 
1041
    if (!(file))
 
1042
        return NULL;
 
1043
 
 
1044
    fp = fopen(file, "r");
 
1045
    if (!(fp))
 
1046
        return NULL;
 
1047
 
 
1048
    x = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
 
1049
 
 
1050
    fclose(fp);
 
1051
 
 
1052
    if ((x)) {
 
1053
        tm = cl_ASN1_GetTimeT(x->crl->nextUpdate);
 
1054
        if (!(tm)) {
 
1055
            X509_CRL_free(x);
 
1056
            return NULL;
 
1057
        }
 
1058
 
 
1059
#if !defined(_WIN32)
 
1060
        if (timegm(tm) < time(NULL)) {
 
1061
            X509_CRL_free(x);
 
1062
            free(tm);
 
1063
            return NULL;
 
1064
        }
 
1065
#endif
 
1066
 
 
1067
        free(tm);
 
1068
    }
 
1069
 
 
1070
    return x;
 
1071
}
 
1072
 
 
1073
void *cl_hash_init(const char *alg)
 
1074
{
 
1075
    EVP_MD_CTX *ctx;
 
1076
    const EVP_MD *md;
 
1077
 
 
1078
    md = EVP_get_digestbyname(alg);
 
1079
    if (!(md))
 
1080
        return NULL;
 
1081
 
 
1082
    ctx = EVP_MD_CTX_create();
 
1083
    if (!(ctx)) {
 
1084
        return NULL;
 
1085
    }
 
1086
 
 
1087
    if (!EVP_DigestInit_ex(ctx, md, NULL)) {
 
1088
        EVP_MD_CTX_destroy(ctx);
 
1089
        return NULL;
 
1090
    }
 
1091
 
 
1092
    return (void *)ctx;
 
1093
}
 
1094
 
 
1095
int cl_update_hash(void *ctx, void *data, size_t sz)
 
1096
{
 
1097
    if (!(ctx) || !(data))
 
1098
        return -1;
 
1099
 
 
1100
    if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx, data, sz))
 
1101
        return -1;
 
1102
 
 
1103
    return 0;
 
1104
}
 
1105
 
 
1106
int cl_finish_hash(void *ctx, void *buf)
 
1107
{
 
1108
    int res=0;
 
1109
 
 
1110
    if (!(ctx) || !(buf))
 
1111
        return -1;
 
1112
 
 
1113
    if (!EVP_DigestFinal_ex((EVP_MD_CTX *)ctx, (unsigned char *)buf, NULL))
 
1114
        res = -1;
 
1115
 
 
1116
    EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx);
 
1117
 
 
1118
    return res;
 
1119
}
 
1120
 
 
1121
void cl_hash_destroy(void *ctx)
 
1122
{
 
1123
    if (!(ctx))
 
1124
        return;
 
1125
 
 
1126
    EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx);
 
1127
}