1 /* $NetBSD: tls_certkey.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* tls_certkey 3 6 /* SUMMARY 7 /* public key certificate and private key loader 8 /* SYNOPSIS 9 /* #define TLS_INTERNAL 10 /* #include <tls.h> 11 /* 12 /* int tls_set_ca_certificate_info(ctx, CAfile, CApath) 13 /* SSL_CTX *ctx; 14 /* const char *CAfile; 15 /* const char *CApath; 16 /* 17 /* int tls_set_my_certificate_key_info(ctx, cert_file, key_file, 18 /* dcert_file, dkey_file, 19 /* eccert_file, eckey_file) 20 /* SSL_CTX *ctx; 21 /* const char *cert_file; 22 /* const char *key_file; 23 /* const char *dcert_file; 24 /* const char *dkey_file; 25 /* const char *eccert_file; 26 /* const char *eckey_file; 27 /* DESCRIPTION 28 /* OpenSSL supports two options to specify CA certificates: 29 /* either one file CAfile that contains all CA certificates, 30 /* or a directory CApath with separate files for each 31 /* individual CA, with symbolic links named after the hash 32 /* values of the certificates. The second option is not 33 /* convenient with a chrooted process. 34 /* 35 /* tls_set_ca_certificate_info() loads the CA certificate 36 /* information for the specified TLS server or client context. 37 /* The result is -1 on failure, 0 on success. 38 /* 39 /* tls_set_my_certificate_key_info() loads the public key 40 /* certificates and private keys for the specified TLS server 41 /* or client context. Up to 3 pairs of key pairs (RSA, DSA and 42 /* ECDSA) may be specified; each certificate and key pair must 43 /* match. The result is -1 on failure, 0 on success. 44 /* LICENSE 45 /* .ad 46 /* .fi 47 /* This software is free. You can do with it whatever you want. 48 /* The original author kindly requests that you acknowledge 49 /* the use of his software. 50 /* AUTHOR(S) 51 /* Originally written by: 52 /* Lutz Jaenicke 53 /* BTU Cottbus 54 /* Allgemeine Elektrotechnik 55 /* Universitaetsplatz 3-4 56 /* D-03044 Cottbus, Germany 57 /* 58 /* Updated by: 59 /* Wietse Venema 60 /* IBM T.J. Watson Research 61 /* P.O. Box 704 62 /* Yorktown Heights, NY 10598, USA 63 /*--*/ 64 65 /* System library. */ 66 67 #include <sys_defs.h> 68 69 #ifdef USE_TLS 70 71 /* Utility library. */ 72 73 #include <msg.h> 74 75 /* Global library. */ 76 77 #include <mail_params.h> 78 79 /* TLS library. */ 80 81 #define TLS_INTERNAL 82 #include <tls.h> 83 84 /* tls_set_ca_certificate_info - load Certification Authority certificates */ 85 86 int tls_set_ca_certificate_info(SSL_CTX *ctx, const char *CAfile, 87 const char *CApath) 88 { 89 if (*CAfile == 0) 90 CAfile = 0; 91 if (*CApath == 0) 92 CApath = 0; 93 94 #define CA_PATH_FMT "%s%s%s" 95 #define CA_PATH_ARGS(var, nextvar) \ 96 var ? #var "=\"" : "", \ 97 var ? var : "", \ 98 var ? (nextvar ? "\", " : "\"") : "" 99 100 if (CAfile || CApath) { 101 if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) { 102 msg_info("cannot load Certification Authority data, " 103 CA_PATH_FMT CA_PATH_FMT ": disabling TLS support", 104 CA_PATH_ARGS(CAfile, CApath), 105 CA_PATH_ARGS(CApath, 0)); 106 tls_print_errors(); 107 return (-1); 108 } 109 if (var_tls_append_def_CA && !SSL_CTX_set_default_verify_paths(ctx)) { 110 msg_info("cannot set default OpenSSL certificate verification " 111 "paths: disabling TLS support"); 112 tls_print_errors(); 113 return (-1); 114 } 115 } 116 return (0); 117 } 118 119 /* set_cert_stuff - specify certificate and key information */ 120 121 static int set_cert_stuff(SSL_CTX *ctx, const char *cert_type, 122 const char *cert_file, 123 const char *key_file) 124 { 125 126 /* 127 * We need both the private key (in key_file) and the public key 128 * certificate (in cert_file). Both may specify the same file. 129 * 130 * Code adapted from OpenSSL apps/s_cb.c. 131 */ 132 ERR_clear_error(); 133 if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) { 134 msg_warn("cannot get %s certificate from file \"%s\": " 135 "disabling TLS support", cert_type, cert_file); 136 tls_print_errors(); 137 return (0); 138 } 139 if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { 140 msg_warn("cannot get %s private key from file \"%s\": " 141 "disabling TLS support", cert_type, key_file); 142 tls_print_errors(); 143 return (0); 144 } 145 146 /* 147 * Sanity check. 148 */ 149 if (!SSL_CTX_check_private_key(ctx)) { 150 msg_warn("%s private key in %s does not match public key in %s: " 151 "disabling TLS support", cert_type, key_file, cert_file); 152 return (0); 153 } 154 return (1); 155 } 156 157 /* tls_set_my_certificate_key_info - load client or server certificates/keys */ 158 159 int tls_set_my_certificate_key_info(SSL_CTX *ctx, 160 const char *cert_file, 161 const char *key_file, 162 const char *dcert_file, 163 const char *dkey_file, 164 const char *eccert_file, 165 const char *eckey_file) 166 { 167 168 /* 169 * Lack of certificates is fine so long as we are prepared to use 170 * anonymous ciphers. 171 */ 172 if (*cert_file && !set_cert_stuff(ctx, "RSA", cert_file, key_file)) 173 return (-1); /* logged */ 174 if (*dcert_file && !set_cert_stuff(ctx, "DSA", dcert_file, dkey_file)) 175 return (-1); /* logged */ 176 #if OPENSSL_VERSION_NUMBER >= 0x1000000fL && !defined(OPENSSL_NO_ECDH) 177 if (*eccert_file && !set_cert_stuff(ctx, "ECDSA", eccert_file, eckey_file)) 178 return (-1); /* logged */ 179 #else 180 if (*eccert_file) 181 msg_warn("ECDSA not supported. Ignoring ECDSA certificate file \"%s\"", 182 eccert_file); 183 #endif 184 return (0); 185 } 186 187 #endif 188