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