xref: /openbsd/usr.sbin/rpki-client/crl.c (revision 09467b48)
1 /*	$OpenBSD: crl.c,v 1.8 2020/04/02 09:16:43 claudio Exp $ */
2 /*
3  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/socket.h>
19 
20 #include <arpa/inet.h>
21 #include <assert.h>
22 #include <err.h>
23 #include <inttypes.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 
29 #include <openssl/ssl.h>
30 
31 #include "extern.h"
32 
33 X509_CRL *
34 crl_parse(const char *fn, const unsigned char *dgst)
35 {
36 	int		 rc = 0, sz;
37 	X509_CRL	*x = NULL;
38 	BIO		*bio = NULL, *shamd;
39 	FILE		*f;
40 	EVP_MD		*md;
41 	char		 mdbuf[EVP_MAX_MD_SIZE];
42 
43 	if ((f = fopen(fn, "rb")) == NULL) {
44 		warn("%s", fn);
45 		return NULL;
46 	}
47 
48 	if ((bio = BIO_new_fp(f, BIO_CLOSE)) == NULL) {
49 		if (verbose > 0)
50 			cryptowarnx("%s: BIO_new_file", fn);
51 		return NULL;
52 	}
53 
54 	/*
55 	 * If we have a digest specified, create an MD chain that will
56 	 * automatically compute a digest during the X509 creation.
57 	 */
58 
59 	if (dgst != NULL) {
60 		if ((shamd = BIO_new(BIO_f_md())) == NULL)
61 			cryptoerrx("BIO_new");
62 		if (!BIO_set_md(shamd, EVP_sha256()))
63 			cryptoerrx("BIO_set_md");
64 		if ((bio = BIO_push(shamd, bio)) == NULL)
65 			cryptoerrx("BIO_push");
66 	}
67 
68 	if ((x = d2i_X509_CRL_bio(bio, NULL)) == NULL) {
69 		cryptowarnx("%s: d2i_X509_CRL_bio", fn);
70 		goto out;
71 	}
72 
73 	/*
74 	 * If we have a digest, find it in the chain (we'll already have
75 	 * made it, so assert otherwise) and verify it.
76 	 */
77 
78 	if (dgst != NULL) {
79 		shamd = BIO_find_type(bio, BIO_TYPE_MD);
80 		assert(shamd != NULL);
81 
82 		if (!BIO_get_md(shamd, &md))
83 			cryptoerrx("BIO_get_md");
84 		assert(EVP_MD_type(md) == NID_sha256);
85 
86 		if ((sz = BIO_gets(shamd, mdbuf, EVP_MAX_MD_SIZE)) < 0)
87 			cryptoerrx("BIO_gets");
88 		assert(sz == SHA256_DIGEST_LENGTH);
89 
90 		if (memcmp(mdbuf, dgst, SHA256_DIGEST_LENGTH)) {
91 			if (verbose > 0)
92 				warnx("%s: bad message digest", fn);
93 			goto out;
94 		}
95 	}
96 
97 	rc = 1;
98 out:
99 	BIO_free_all(bio);
100 	if (rc == 0) {
101 		X509_CRL_free(x);
102 		x = NULL;
103 	}
104 	return x;
105 }
106 
107 static inline int
108 crlcmp(struct crl *a, struct crl *b)
109 {
110 	return strcmp(a->aki, b->aki);
111 }
112 
113 RB_GENERATE(crl_tree, crl, entry, crlcmp);
114 
115 void
116 free_crl(struct crl *crl)
117 {
118 	free(crl->aki);
119 	X509_CRL_free(crl->x509_crl);
120 	free(crl);
121 }
122