xref: /openbsd-src/usr.sbin/rpki-client/crl.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: crl.c,v 1.9 2020/09/12 15:46:48 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 "extern.h"
30 
31 X509_CRL *
32 crl_parse(const char *fn, const unsigned char *dgst)
33 {
34 	int		 rc = 0, sz;
35 	X509_CRL	*x = NULL;
36 	BIO		*bio = NULL, *shamd;
37 	FILE		*f;
38 	EVP_MD		*md;
39 	char		 mdbuf[EVP_MAX_MD_SIZE];
40 
41 	if ((f = fopen(fn, "rb")) == NULL) {
42 		warn("%s", fn);
43 		return NULL;
44 	}
45 
46 	if ((bio = BIO_new_fp(f, BIO_CLOSE)) == NULL) {
47 		if (verbose > 0)
48 			cryptowarnx("%s: BIO_new_file", fn);
49 		return NULL;
50 	}
51 
52 	/*
53 	 * If we have a digest specified, create an MD chain that will
54 	 * automatically compute a digest during the X509 creation.
55 	 */
56 
57 	if (dgst != NULL) {
58 		if ((shamd = BIO_new(BIO_f_md())) == NULL)
59 			cryptoerrx("BIO_new");
60 		if (!BIO_set_md(shamd, EVP_sha256()))
61 			cryptoerrx("BIO_set_md");
62 		if ((bio = BIO_push(shamd, bio)) == NULL)
63 			cryptoerrx("BIO_push");
64 	}
65 
66 	if ((x = d2i_X509_CRL_bio(bio, NULL)) == NULL) {
67 		cryptowarnx("%s: d2i_X509_CRL_bio", fn);
68 		goto out;
69 	}
70 
71 	/*
72 	 * If we have a digest, find it in the chain (we'll already have
73 	 * made it, so assert otherwise) and verify it.
74 	 */
75 
76 	if (dgst != NULL) {
77 		shamd = BIO_find_type(bio, BIO_TYPE_MD);
78 		assert(shamd != NULL);
79 
80 		if (!BIO_get_md(shamd, &md))
81 			cryptoerrx("BIO_get_md");
82 		assert(EVP_MD_type(md) == NID_sha256);
83 
84 		if ((sz = BIO_gets(shamd, mdbuf, EVP_MAX_MD_SIZE)) < 0)
85 			cryptoerrx("BIO_gets");
86 		assert(sz == SHA256_DIGEST_LENGTH);
87 
88 		if (memcmp(mdbuf, dgst, SHA256_DIGEST_LENGTH)) {
89 			if (verbose > 0)
90 				warnx("%s: bad message digest", fn);
91 			goto out;
92 		}
93 	}
94 
95 	rc = 1;
96 out:
97 	BIO_free_all(bio);
98 	if (rc == 0) {
99 		X509_CRL_free(x);
100 		x = NULL;
101 	}
102 	return x;
103 }
104 
105 static inline int
106 crlcmp(struct crl *a, struct crl *b)
107 {
108 	return strcmp(a->aki, b->aki);
109 }
110 
111 RB_GENERATE(crl_tree, crl, entry, crlcmp);
112 
113 void
114 free_crl(struct crl *crl)
115 {
116 	free(crl->aki);
117 	X509_CRL_free(crl->x509_crl);
118 	free(crl);
119 }
120