1 /* $OpenBSD: tls_keypair.c,v 1.5 2018/02/10 04:57:35 jsing Exp $ */ 2 /* 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 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 <openssl/bio.h> 19 #include <openssl/err.h> 20 #include <openssl/pem.h> 21 22 #include <tls.h> 23 24 #include "tls_internal.h" 25 26 struct tls_keypair * 27 tls_keypair_new(void) 28 { 29 return calloc(1, sizeof(struct tls_keypair)); 30 } 31 32 static void 33 tls_keypair_clear_key(struct tls_keypair *keypair) 34 { 35 freezero(keypair->key_mem, keypair->key_len); 36 keypair->key_mem = NULL; 37 keypair->key_len = 0; 38 } 39 40 static int 41 tls_keypair_pubkey_hash(struct tls_keypair *keypair, struct tls_error *error) 42 { 43 X509 *cert = NULL; 44 int rv = -1; 45 46 free(keypair->pubkey_hash); 47 keypair->pubkey_hash = NULL; 48 49 if (keypair->cert_mem == NULL) { 50 rv = 0; 51 goto done; 52 } 53 54 if (tls_keypair_load_cert(keypair, error, &cert) == -1) 55 goto err; 56 if (tls_cert_pubkey_hash(cert, &keypair->pubkey_hash) == -1) 57 goto err; 58 59 rv = 0; 60 61 err: 62 X509_free(cert); 63 done: 64 return (rv); 65 } 66 67 int 68 tls_keypair_set_cert_file(struct tls_keypair *keypair, struct tls_error *error, 69 const char *cert_file) 70 { 71 if (tls_config_load_file(error, "certificate", cert_file, 72 &keypair->cert_mem, &keypair->cert_len) == -1) 73 return -1; 74 return tls_keypair_pubkey_hash(keypair, error); 75 } 76 77 int 78 tls_keypair_set_cert_mem(struct tls_keypair *keypair, struct tls_error *error, 79 const uint8_t *cert, size_t len) 80 { 81 if (tls_set_mem(&keypair->cert_mem, &keypair->cert_len, cert, len) == -1) 82 return -1; 83 return tls_keypair_pubkey_hash(keypair, error); 84 } 85 86 int 87 tls_keypair_set_key_file(struct tls_keypair *keypair, struct tls_error *error, 88 const char *key_file) 89 { 90 tls_keypair_clear_key(keypair); 91 return tls_config_load_file(error, "key", key_file, 92 &keypair->key_mem, &keypair->key_len); 93 } 94 95 int 96 tls_keypair_set_key_mem(struct tls_keypair *keypair, struct tls_error *error, 97 const uint8_t *key, size_t len) 98 { 99 tls_keypair_clear_key(keypair); 100 return tls_set_mem(&keypair->key_mem, &keypair->key_len, key, len); 101 } 102 103 int 104 tls_keypair_set_ocsp_staple_file(struct tls_keypair *keypair, 105 struct tls_error *error, const char *ocsp_file) 106 { 107 return tls_config_load_file(error, "ocsp", ocsp_file, 108 &keypair->ocsp_staple, &keypair->ocsp_staple_len); 109 } 110 111 int 112 tls_keypair_set_ocsp_staple_mem(struct tls_keypair *keypair, 113 struct tls_error *error, const uint8_t *staple, size_t len) 114 { 115 return tls_set_mem(&keypair->ocsp_staple, &keypair->ocsp_staple_len, 116 staple, len); 117 } 118 119 void 120 tls_keypair_clear(struct tls_keypair *keypair) 121 { 122 struct tls_error error; 123 124 tls_keypair_set_cert_mem(keypair, &error, NULL, 0); 125 tls_keypair_set_key_mem(keypair, &error, NULL, 0); 126 tls_keypair_set_ocsp_staple_mem(keypair, &error, NULL, 0); 127 128 free(keypair->pubkey_hash); 129 keypair->pubkey_hash = NULL; 130 } 131 132 void 133 tls_keypair_free(struct tls_keypair *keypair) 134 { 135 if (keypair == NULL) 136 return; 137 138 tls_keypair_clear(keypair); 139 140 free(keypair); 141 } 142 143 int 144 tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error, 145 X509 **cert) 146 { 147 char *errstr = "unknown"; 148 BIO *cert_bio = NULL; 149 int ssl_err; 150 int rv = -1; 151 152 X509_free(*cert); 153 *cert = NULL; 154 155 if (keypair->cert_mem == NULL) { 156 tls_error_set(error, "keypair has no certificate"); 157 goto err; 158 } 159 if ((cert_bio = BIO_new_mem_buf(keypair->cert_mem, 160 keypair->cert_len)) == NULL) { 161 tls_error_set(error, "failed to create certificate bio"); 162 goto err; 163 } 164 if ((*cert = PEM_read_bio_X509(cert_bio, NULL, tls_password_cb, 165 NULL)) == NULL) { 166 if ((ssl_err = ERR_peek_error()) != 0) 167 errstr = ERR_error_string(ssl_err, NULL); 168 tls_error_set(error, "failed to load certificate: %s", errstr); 169 goto err; 170 } 171 172 rv = 0; 173 174 err: 175 BIO_free(cert_bio); 176 177 return (rv); 178 } 179