Internal changes to allow for relayd engine privsep. sends the hash of the
authorbeck <beck@openbsd.org>
Wed, 5 Apr 2017 03:13:53 +0000 (03:13 +0000)
committerbeck <beck@openbsd.org>
Wed, 5 Apr 2017 03:13:53 +0000 (03:13 +0000)
public key as an identifier to RSA, and adds an function for relayd to
use to disable private key checking when doing engine privsep.
ok jsing@

lib/libtls/Symbols.list
lib/libtls/tls.c
lib/libtls/tls_config.c
lib/libtls/tls_conninfo.c
lib/libtls/tls_internal.h

index eb704ec..98465dd 100644 (file)
@@ -40,6 +40,7 @@ tls_config_set_protocols
 tls_config_set_session_id
 tls_config_set_session_lifetime
 tls_config_set_verify_depth
+tls_config_skip_private_key_check
 tls_config_verify
 tls_config_verify_client
 tls_config_verify_client_optional
index 9b03c2b..4195548 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls.c,v 1.59 2017/01/26 12:56:37 jsing Exp $ */
+/* $OpenBSD: tls.c,v 1.60 2017/04/05 03:13:53 beck Exp $ */
 /*
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
  *
@@ -251,6 +251,55 @@ tls_configure(struct tls *ctx, struct tls_config *config)
        return (0);
 }
 
+int
+tls_cert_hash(X509 *cert, char **hash)
+{
+       char d[EVP_MAX_MD_SIZE], *dhex = NULL;
+       int dlen, rv = -1;
+
+       *hash = NULL;
+       if (X509_digest(cert, EVP_sha256(), d, &dlen) != 1)
+               goto err;
+
+       if (tls_hex_string(d, dlen, &dhex, NULL) != 0)
+               goto err;
+
+       if (asprintf(hash, "SHA256:%s", dhex) == -1) {
+               *hash = NULL;
+               goto err;
+       }
+
+       rv = 0;
+ err:
+       free(dhex);
+
+       return (rv);
+}
+
+static int
+tls_keypair_cert_hash(struct tls_keypair *keypair, char **hash)
+{
+       BIO *membio = NULL;
+       X509 *cert = NULL;
+       int rv = -1;
+
+       *hash = NULL;
+
+       if ((membio = BIO_new_mem_buf(keypair->cert_mem, keypair->cert_len))
+           == NULL)
+               goto err;
+
+       if ((cert = PEM_read_bio_X509_AUX(membio, NULL, NULL, NULL)) == NULL)
+               goto err;
+
+       rv = tls_cert_hash(cert, hash);
+ err:
+       BIO_free(membio);
+
+       return (rv);
+}
+
+
 int
 tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
     struct tls_keypair *keypair, int required)
@@ -275,8 +324,11 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
                        tls_set_errorx(ctx, "failed to load certificate");
                        goto err;
                }
+               if (tls_keypair_cert_hash(keypair, &keypair->cert_hash) == -1)
+                       goto err;
                cert = NULL;
        }
+
        if (keypair->key_mem != NULL) {
                if (keypair->key_len > INT_MAX) {
                        tls_set_errorx(ctx, "key too long");
@@ -293,6 +345,16 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
                        tls_set_errorx(ctx, "failed to read private key");
                        goto err;
                }
+
+               if (keypair->cert_hash != NULL) {
+                       RSA *rsa;
+                       /* XXX only RSA for now for relayd privsep */
+                       if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
+                               RSA_set_ex_data(rsa, 0, keypair->cert_hash);
+                               RSA_free(rsa);
+                       }
+               }
+
                if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) {
                        tls_set_errorx(ctx, "failed to load private key");
                        goto err;
@@ -303,7 +365,8 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
                pkey = NULL;
        }
 
-       if (SSL_CTX_check_private_key(ssl_ctx) != 1) {
+       if (!ctx->config->skip_private_key_check &&
+           SSL_CTX_check_private_key(ssl_ctx) != 1) {
                tls_set_errorx(ctx, "private/public key mismatch");
                goto err;
        }
index 87c2166..f5e0bf5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_config.c,v 1.36 2017/01/31 16:18:57 beck Exp $ */
+/* $OpenBSD: tls_config.c,v 1.37 2017/04/05 03:13:53 beck Exp $ */
 /*
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
  *
@@ -135,6 +135,7 @@ tls_keypair_free(struct tls_keypair *keypair)
        free(keypair->cert_mem);
        free(keypair->key_mem);
        free(keypair->ocsp_staple);
+       free(keypair->cert_hash);
 
        free(keypair);
 }
@@ -761,6 +762,12 @@ tls_config_verify_client_optional(struct tls_config *config)
        config->verify_client = 2;
 }
 
+void
+tls_config_skip_private_key_check(struct tls_config *config)
+{
+       config->skip_private_key_check = 1;
+}
+
 int
 tls_config_set_ocsp_staple_file(struct tls_config *config, const char *staple_file)
 {
index 5cdd0f7..c4d23c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_conninfo.c,v 1.13 2017/01/09 15:31:20 jsing Exp $ */
+/* $OpenBSD: tls_conninfo.c,v 1.14 2017/04/05 03:13:53 beck Exp $ */
 /*
  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
  * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
@@ -23,7 +23,7 @@
 #include <tls.h>
 #include "tls_internal.h"
 
-static int
+int
 tls_hex_string(const unsigned char *in, size_t inlen, char **out,
     size_t *outlen)
 {
@@ -56,35 +56,16 @@ tls_hex_string(const unsigned char *in, size_t inlen, char **out,
 static int
 tls_get_peer_cert_hash(struct tls *ctx, char **hash)
 {
-       char d[EVP_MAX_MD_SIZE], *dhex = NULL;
-       int dlen, rv = -1;
-
        *hash = NULL;
        if (ctx->ssl_peer_cert == NULL)
                return (0);
 
-       if (X509_digest(ctx->ssl_peer_cert, EVP_sha256(), d, &dlen) != 1) {
-               tls_set_errorx(ctx, "digest failed");
-               goto err;
-       }
-
-       if (tls_hex_string(d, dlen, &dhex, NULL) != 0) {
-               tls_set_errorx(ctx, "digest hex string failed");
-               goto err;
-       }
-
-       if (asprintf(hash, "SHA256:%s", dhex) == -1) {
-               tls_set_errorx(ctx, "out of memory");
+       if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) {
+               tls_set_errorx(ctx, "unable to compute peer certificate hash - out of memory");
                *hash = NULL;
-               goto err;
+               return -1;
        }
-
-       rv = 0;
-
-err:
-       free(dhex);
-
-       return (rv);
+       return 0;
 }
 
 static int
@@ -294,3 +275,4 @@ tls_conn_version(struct tls *ctx)
                return (NULL);
        return (ctx->conninfo->version);
 }
+
index fbb139c..b1d53c8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_internal.h,v 1.53 2017/01/29 17:52:11 beck Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.54 2017/04/05 03:13:53 beck Exp $ */
 /*
  * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -53,6 +53,7 @@ struct tls_keypair {
        size_t key_len;
        char *ocsp_staple;
        size_t ocsp_staple_len;
+       char *cert_hash;
 };
 
 #define TLS_MIN_SESSION_TIMEOUT (4)
@@ -96,6 +97,7 @@ struct tls_config {
        int verify_depth;
        int verify_name;
        int verify_time;
+       int skip_private_key_check;
 };
 
 struct tls_conninfo {
@@ -232,6 +234,9 @@ int tls_ocsp_verify_cb(SSL *ssl, void *arg);
 int tls_ocsp_stapling_cb(SSL *ssl, void *arg);
 void tls_ocsp_free(struct tls_ocsp *ctx);
 struct tls_ocsp *tls_ocsp_setup_from_peer(struct tls *ctx);
+int tls_hex_string(const unsigned char *_in, size_t _inlen, char **_out,
+    size_t *_outlen);
+int tls_cert_hash(X509 *_cert, char **_hash);
 
 __END_HIDDEN_DECLS