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