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