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