From patchwork Sun Jan 7 15:21:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Selva Nair X-Patchwork-Id: 171 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director3.mail.ord1d.rsapps.net ([172.30.191.6]) by backend31.mail.ord1d.rsapps.net (Dovecot) with LMTP id g2HxBOfVUlrEMAAAgoeIoA for ; Sun, 07 Jan 2018 21:22:31 -0500 Received: from proxy1.mail.ord1d.rsapps.net ([172.30.191.6]) by director3.mail.ord1d.rsapps.net (Dovecot) with LMTP id 0zLGBOfVUlrsCAAAkXNnRw ; Sun, 07 Jan 2018 21:22:31 -0500 Received: from smtp13.gate.ord1c ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy1.mail.ord1d.rsapps.net (Dovecot) with LMTP id QgCFA+fVUlqEOAAAasrz9Q ; Sun, 07 Jan 2018 21:22:31 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.34.181.88] Authentication-Results: smtp13.gate.ord1c.rsapps.net; iprev=pass policy.iprev="216.34.181.88"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=gmail.com; dmarc=fail (p=none; dis=none) header.from=gmail.com X-Classification-ID: c7484300-f41a-11e7-86fe-bc305bf03494-1-1 Received: from [216.34.181.88] ([216.34.181.88:58480] helo=lists.sourceforge.net) by smtp13.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 00/14-28371-6E5D25A5; Sun, 07 Jan 2018 21:22:30 -0500 Received: from localhost ([127.0.0.1] helo=sfs-ml-4.v29.ch3.sourceforge.com) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.89) (envelope-from ) id 1eYN4H-0001Q3-1i; Mon, 08 Jan 2018 02:21:41 +0000 Received: from sfi-mx-2.v28.ch3.sourceforge.com ([172.29.28.192] helo=mx.sourceforge.net) by sfs-ml-4.v29.ch3.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89) (envelope-from ) id 1eYN4G-0001Pu-2W for openvpn-devel@lists.sourceforge.net; Mon, 08 Jan 2018 02:21:40 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=vaJ9GiYDJq2IHp8S/TP/ruM3zCSloYZJfV19tOco7Ak=; b=AiLz28BFSismDfCDYlfROKL+0r 8DSZPyuPKJ6xWurE++c4kirFIRryASP2EA5McD0KkHEFUpOU7lyzhMeEOoRrjn9j19dIGS1G3/7oQ KMMt/QVxc7WTzdZABMeiBQm1Iwkxroz41NvOG+Mm0DHVIiRGcVZxZ4n3MTDbdjbsLBgI=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=vaJ9GiYDJq2IHp8S/TP/ruM3zCSloYZJfV19tOco7Ak=; b=hsR/2pCQz1g9nLGCp2wcAl/va0 9dGfH5LE6OXMElPFPsbjGt09Thx2UlVAvq/TDxEi9fSy5T/zxwDOi8bJ/vYzhvWfG5hAtAAW6dA7c CcYXtTO19umi/yi82HRuQEi8JNdy0dejKX3PyY9fgv9+i4iShwupi56MkCNzh+5Aj2ng=; Received: from mail-io0-f196.google.com ([209.85.223.196]) by sfi-mx-2.v28.ch3.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.89) id 1eYN4E-0002Er-0y for openvpn-devel@lists.sourceforge.net; Mon, 08 Jan 2018 02:21:40 +0000 Received: by mail-io0-f196.google.com with SMTP id v30so11395620iov.7 for ; Sun, 07 Jan 2018 18:21:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vaJ9GiYDJq2IHp8S/TP/ruM3zCSloYZJfV19tOco7Ak=; b=eCTuXlw2qaBz8uEHemOquT1BQ3v+NQYfcmEXYbfYIvGcauUALLt5evmtoKETpFkFNE djFhuq+S/p2TxaksD/TP57bmPfbNuZ39AcBLGOgoNYmwF5pcrznUDTtplfPqv3H/fj/D E51Nl06fEN2hpeWYLGuU2DmPsZsWHED0uYVpowC17hoW4BKoLw2S9zIQ7kd49tuDjyjU kUS7J9jka71aYMGFecXbqFk3e9ITHioYB5MkmK6WVSGcNvYgWA62klk2rp9B0oTZaLr8 tC7Xtkrpf/+bcbFWld7OfdQ1npSo0n1RB/TQ+5DMUS06c1fTW0ladmYaS/y3uXghz9kV +BDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vaJ9GiYDJq2IHp8S/TP/ruM3zCSloYZJfV19tOco7Ak=; b=lEPx5thJ2XTbtM4pQt4b+3z3bhZY6ZREdYVpyG1i7Kp9triOmRQY7z7oa+YL87xKPz r4M1/sNJlDukXHc5tw3odc95QRIfQ98bO0EfgU5Ib2h/st2qKlO8T7fnBisEG7QNknMM OthRLEC4fg28skflZa/DtqhIA6azUQWFE5/36pJSX7vIu1Gl+fq6deObqAKK+HITs3T5 DvPa0sbK39kBC9tKFKes0tPSuFYdwTqb+CL+Y/2IpyHId8INrfoYo+UD/t0pXgY3NSoD ZRc4asmiRo6Dufx3CZArntSN57CIJcTA1Y47luTcnCBDOqdwVKmN3TPpSKtRd7VBGQQW NhIg== X-Gm-Message-State: AKwxytdkYVOadrtmArNk+jL4HQY7iM6hDYQ4kbndVlgf8uH8Wrtt6ROc eyk5mZ8HohmqjvXDDZEmXTqS2gV0 X-Google-Smtp-Source: ACJfBose9hJuVkjx9xidRHskeDG/Pjy1aBbfIHswv5pNo+RUneRQQNt0BpSIHvDobTVmOCty66BchA== X-Received: by 10.107.53.99 with SMTP id c96mr9770922ioa.143.1515378092443; Sun, 07 Jan 2018 18:21:32 -0800 (PST) Received: from saturn.home.sansel.ca (CPE40167ea0e1c2-CM788df74daaa0.cpe.net.cable.rogers.com. [99.228.215.92]) by smtp.gmail.com with ESMTPSA id 202sm6312959ioz.84.2018.01.07.18.21.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 07 Jan 2018 18:21:31 -0800 (PST) From: selva.nair@gmail.com To: openvpn-devel@lists.sourceforge.net Date: Sun, 7 Jan 2018 21:21:15 -0500 Message-Id: <1515378076-5774-2-git-send-email-selva.nair@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1515378076-5774-1-git-send-email-selva.nair@gmail.com> References: <1515378076-5774-1-git-send-email-selva.nair@gmail.com> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (selva.nair[at]gmail.com) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.223.196 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-Headers-End: 1eYN4E-0002Er-0y Subject: [Openvpn-devel] [PATCH 1/2] Bring cryptoapi.c upto speed with openssl 1.1 X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Selva Nair - Replace direct access to internals of openssl structs by corresponding methods. Signed-off-by: Selva Nair --- Tested on Windows 10 with openssl 1.0.1r and 1.1.0g configure.ac | 1 + src/openvpn/cryptoapi.c | 69 +++++++++++++++++++++++++++----------------- src/openvpn/openssl_compat.h | 14 +++++++++ 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/configure.ac b/configure.ac index b4fd1b3..2c1937e 100644 --- a/configure.ac +++ b/configure.ac @@ -944,6 +944,7 @@ if test "${with_crypto_library}" = "openssl"; then RSA_meth_set_init \ RSA_meth_set_finish \ RSA_meth_set0_app_data \ + RSA_meth_get0_app_data \ EC_GROUP_order_bits ] ) diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index d90cc5d..7052e4e 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -47,6 +47,7 @@ #include #include "buffer.h" +#include "openssl_compat.h" /* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while * MinGW32-w64 defines all macros used. This is a hack around that problem. @@ -213,20 +214,20 @@ rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, in static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data; + CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(RSA_get_method(rsa)); HCRYPTHASH hash; DWORD hash_size, len, i; unsigned char *buf; if (cd == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (padding != RSA_PKCS1_PADDING) { /* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */ - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would @@ -236,7 +237,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i /* For now, we only support NID_md5_sha1 */ if (flen != SSL_SIG_LENGTH) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) @@ -253,7 +254,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i } if ((int) hash_size != flen) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); CryptDestroyHash(hash); return 0; } @@ -268,7 +269,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i buf = malloc(len); if (buf == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); CryptDestroyHash(hash); return 0; } @@ -312,7 +313,8 @@ init(RSA *rsa) static int finish(RSA *rsa) { - CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data; + const RSA_METHOD *rsa_meth = RSA_get_method(rsa); + CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(rsa_meth); if (cd == NULL) { @@ -326,9 +328,8 @@ finish(RSA *rsa) { CertFreeCertificateContext(cd->cert_context); } - free(rsa->meth->app_data); - free((char *) rsa->meth); - rsa->meth = NULL; + free(cd); + RSA_meth_free((RSA_METHOD*) rsa_meth); return 1; } @@ -412,9 +413,9 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) X509 *cert = NULL; RSA *rsa = NULL, *pub_rsa; CAPI_DATA *cd = calloc(1, sizeof(*cd)); - RSA_METHOD *my_rsa_method = calloc(1, sizeof(*my_rsa_method)); + RSA_METHOD *my_rsa_method = NULL; - if (cd == NULL || my_rsa_method == NULL) + if (cd == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); goto err; @@ -469,15 +470,16 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) /* here we don't need to do CryptGetUserKey() or anything; all necessary key * info is in cd->cert_context, and then, in cd->crypt_prov. */ - my_rsa_method->name = "Microsoft CryptoAPI RSA Method"; - my_rsa_method->rsa_pub_enc = rsa_pub_enc; - my_rsa_method->rsa_pub_dec = rsa_pub_dec; - my_rsa_method->rsa_priv_enc = rsa_priv_enc; - my_rsa_method->rsa_priv_dec = rsa_priv_dec; - /* my_rsa_method->init = init; */ - my_rsa_method->finish = finish; - my_rsa_method->flags = RSA_METHOD_FLAG_NO_CHECK; - my_rsa_method->app_data = (char *) cd; + my_rsa_method = RSA_meth_new("Microsoft Cryptography API RSA Method", + RSA_METHOD_FLAG_NO_CHECK); + check_malloc_return(my_rsa_method); + RSA_meth_set_pub_enc(my_rsa_method, rsa_pub_enc); + RSA_meth_set_pub_dec(my_rsa_method, rsa_pub_dec); + RSA_meth_set_priv_enc(my_rsa_method, rsa_priv_enc); + RSA_meth_set_priv_dec(my_rsa_method, rsa_priv_dec); + RSA_meth_set_init(my_rsa_method, NULL); + RSA_meth_set_finish(my_rsa_method, finish); + RSA_meth_set0_app_data(my_rsa_method, cd); rsa = RSA_new(); if (rsa == NULL) @@ -486,23 +488,36 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) goto err; } - /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(), + /* Public key in cert is NULL until we call SSL_CTX_use_certificate(), * so we do it here then... */ if (!SSL_CTX_use_certificate(ssl_ctx, cert)) { goto err; } /* the public key */ - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + EVP_PKEY *pkey = X509_get0_pubkey(cert); + /* SSL_CTX_use_certificate() increased the reference count in 'cert', so * we decrease it here with X509_free(), or it will never be cleaned up. */ X509_free(cert); cert = NULL; - /* I'm not sure about what we have to fill in in the RSA, trying out stuff... */ - /* rsa->n indicates the key size */ - rsa->n = BN_dup(pub_rsa->n); - rsa->flags |= RSA_FLAG_EXT_PKEY; + if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) + { + msg(M_WARN, "cryptoapicert requires an RSA certificate"); + goto err; + } + pub_rsa = EVP_PKEY_get0_RSA(pkey); + + /* Our private key is external, so we fill in only n and e from the public key */ + const BIGNUM *n = NULL; + const BIGNUM *e = NULL; + RSA_get0_key(pub_rsa, &n, &e, NULL); + if (!RSA_set0_key(rsa, BN_dup(n), BN_dup(e), NULL)) + { + goto err; + } + RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY); if (!RSA_set_method(rsa, my_rsa_method)) { goto err; diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h index 70b19ae..bc7dbdd 100644 --- a/src/openvpn/openssl_compat.h +++ b/src/openvpn/openssl_compat.h @@ -624,6 +624,20 @@ RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data) } #endif +#if !defined(HAVE_RSA_METH_GET0_APP_DATA) +/** + * Get the application data of an RSA_METHOD object + * + * @param meth The RSA_METHOD object + * @return pointer to application data, may be NULL + */ +static inline void * +RSA_meth_get0_app_data(const RSA_METHOD *meth) +{ + return meth ? meth->app_data : NULL; +} +#endif + #if !defined(HAVE_EC_GROUP_ORDER_BITS) && !defined(OPENSSL_NO_EC) /** * Gets the number of bits of the order of an EC_GROUP From patchwork Sun Jan 7 15:21:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Selva Nair X-Patchwork-Id: 170 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director6.mail.ord1d.rsapps.net ([172.30.191.6]) by backend31.mail.ord1d.rsapps.net (Dovecot) with LMTP id w64eGOXVUlombQAAgoeIoA for ; Sun, 07 Jan 2018 21:22:29 -0500 Received: from proxy3.mail.ord1d.rsapps.net ([172.30.191.6]) by director6.mail.ord1d.rsapps.net (Dovecot) with LMTP id J4AlC+XVUloRbQAAhgvE6Q ; Sun, 07 Jan 2018 21:22:29 -0500 Received: from smtp15.gate.ord1c ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy3.mail.ord1d.rsapps.net (Dovecot) with LMTP id 2o2XFuXVUlpjIgAA7WKfLA ; Sun, 07 Jan 2018 21:22:29 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.34.181.88] Authentication-Results: smtp15.gate.ord1c.rsapps.net; iprev=pass policy.iprev="216.34.181.88"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=gmail.com; dmarc=fail (p=none; dis=none) header.from=gmail.com X-Classification-ID: c642e140-f41a-11e7-97f7-bc305bf03694-1-1 Received: from [216.34.181.88] ([216.34.181.88:51746] helo=lists.sourceforge.net) by smtp15.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 92/E8-18552-5E5D25A5; Sun, 07 Jan 2018 21:22:29 -0500 Received: from localhost ([127.0.0.1] helo=sfs-ml-1.v29.ch3.sourceforge.com) by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.89) (envelope-from ) id 1eYN4I-0007bj-DA; Mon, 08 Jan 2018 02:21:42 +0000 Received: from sfi-mx-4.v28.ch3.sourceforge.com ([172.29.28.194] helo=mx.sourceforge.net) by sfs-ml-1.v29.ch3.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89) (envelope-from ) id 1eYN4H-0007bc-NQ for openvpn-devel@lists.sourceforge.net; Mon, 08 Jan 2018 02:21:41 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=cesttFwAuxwO+1BEQ/gIBg3ZgmIJgMaYUBfkZgd3tSc=; b=XCGgY9inHIN87ynSqnIugp5W8s LoWkofvtebx6Ghb9tRA9LncPElZz4UVR7tefwpd7kpWBY5/rYmYMpU6c5/NwJj9QmOE6/NfeOxKWl 0t5hHgGrGL7L8gSkjy/kDaF2se5pBuwcaW8ars3GYqS4IW4FcC6d9bRlqrLOe0UKGL+I=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=cesttFwAuxwO+1BEQ/gIBg3ZgmIJgMaYUBfkZgd3tSc=; b=T6HStWPpkcZBsAhOjyHh8R79j6 dVxpwvvmul9qRqvH497fZ43RGOmGaQg9xnilUMcNy2zV9QoosSs6oJRExFSrYMM4kYHvBZuJd/zhU iJXil3RfH5cRQOg48LCybyiO9C0faG/uYg05gtZY4hnLQ2nehgxEd3oNLsqjD18AIYg4=; Received: from mail-io0-f194.google.com ([209.85.223.194]) by sfi-mx-4.v28.ch3.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.89) id 1eYN4F-0000Na-UN for openvpn-devel@lists.sourceforge.net; Mon, 08 Jan 2018 02:21:41 +0000 Received: by mail-io0-f194.google.com with SMTP id k18so11391592ioc.11 for ; Sun, 07 Jan 2018 18:21:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=cesttFwAuxwO+1BEQ/gIBg3ZgmIJgMaYUBfkZgd3tSc=; b=Eu8xqn+73ONfiUU7q0uB7jke1AB3QGYkUSlNatrNKYqVRNTVU+WiVR0wC7TA+0jqm+ 11DbGEPdgNFTfmaPx8rFntPYCLL1ROGc/A5/zoeJYYpuA7XVBvtBbFSpSmjf98BLkPNB 4jUHO0Xi42Odx7NoTfxpYDLc2Ua0siPZN86Gs6vmG0RcGFwTNMrwtD+HKZYkILv0s2iu zB/3K11hCe/WNJeHcyAI9jFWuZR2Od+Wi7ANW273V/oOtDb//mFbPJN3DA9meTGnzEl8 8g92SzEU+d/GZNv07SxIGJCs7/WZP2XI0ra+eQNMW0WQZ0Qw7ITalWGYKfVydu1UDWbP 5ksg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cesttFwAuxwO+1BEQ/gIBg3ZgmIJgMaYUBfkZgd3tSc=; b=BpmXHTylD4zymvc3a3dHq3OrTd+e63FCHawqrkzn7LPnlgcSHX4oZytM/XkffxpjHT 1EDAdb6ccW4UFj+iUnoWf3xKW3PDjELizp0pEM5AhR19pXIsUTQbRLsyoipCSGH4G4ND RfvGa9Xag645ason33LZzSccAUKLoFX9H+kAUl8Jxz5U+SWjUzCunt4/GPf+RAA428aE PJ3yb0B8iAuRi21st3sbwnupyPYwleqQw/fy7Pa0RekHxS0o9vY+LE2jaf+HUxGk/f7I qEeSb48CUELCvb1FbnUMaPDHHlOvU7+21OJtZW3UQu5Pw6wg706Nffeim7L0fc25onO+ 4jMw== X-Gm-Message-State: AKGB3mJ7KDQ+eNwBqwgoPRMM6UDD9QdUpf6r8cgGLafZMhHm9lASD/h6 +Nck8MPNB2nPhclO2FpaoxOTeHoo X-Google-Smtp-Source: ACJfBosQ+0uLKtxoZ2zMltqQPc4Eg8dn0fMK9cBHgjeI+X0Li1xaTbRMnEZA+EoLk7D7mzoHde8BDw== X-Received: by 10.107.134.39 with SMTP id i39mr9821446iod.233.1515378094368; Sun, 07 Jan 2018 18:21:34 -0800 (PST) Received: from saturn.home.sansel.ca (CPE40167ea0e1c2-CM788df74daaa0.cpe.net.cable.rogers.com. [99.228.215.92]) by smtp.gmail.com with ESMTPSA id 202sm6312959ioz.84.2018.01.07.18.21.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 07 Jan 2018 18:21:33 -0800 (PST) From: selva.nair@gmail.com To: openvpn-devel@lists.sourceforge.net Date: Sun, 7 Jan 2018 21:21:16 -0500 Message-Id: <1515378076-5774-3-git-send-email-selva.nair@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1515378076-5774-1-git-send-email-selva.nair@gmail.com> References: <1515378076-5774-1-git-send-email-selva.nair@gmail.com> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (selva.nair[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.223.194 listed in list.dnswl.org] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1eYN4F-0000Na-UN Subject: [Openvpn-devel] [PATCH 2/2] TLS v1.2 support for cryptoapicert -- RSA only X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Selva Nair - If an NCRYPT handle for the private key can be obtained, use NCryptSignHash from the Cryptography NG API to sign the hash. This should work for all keys in the Windows certifiate stores but may fail for keys in a legacy token, for example. In such cases, we disable TLS v1.2 and fall back to the current behaviour. A warning is logged unless TLS version is already restricted to <= 1.1 Signed-off-by: Selva Nair --- Tested on Windows 10 with openssl 1.0.1r and 1.1.0g with certificate/key in Windows user store src/openvpn/Makefile.am | 2 +- src/openvpn/cryptoapi.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++--- src/openvpn/options.c | 18 ----------- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index fcc22d6..1a2f42e 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -132,5 +132,5 @@ openvpn_LDADD = \ $(OPTIONAL_DL_LIBS) if WIN32 openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h -openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 +openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 -lncrypt endif diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index 7052e4e..cd3f023 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,14 @@ #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 #endif /* Size of an SSL signature: MD5+SHA1 */ #define SSL_SIG_LENGTH 36 @@ -83,6 +92,7 @@ #define CRYPTOAPI_F_CRYPT_SIGN_HASH 106 #define CRYPTOAPI_F_LOAD_LIBRARY 107 #define CRYPTOAPI_F_GET_PROC_ADDRESS 108 +#define CRYPTOAPI_F_NCRYPT_SIGN_HASH 109 static ERR_STRING_DATA CRYPTOAPI_str_functs[] = { { ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0), "microsoft cryptoapi"}, @@ -95,12 +105,13 @@ static ERR_STRING_DATA CRYPTOAPI_str_functs[] = { { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), "CryptSignHash" }, { ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0), "LoadLibrary" }, { ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0), "GetProcAddress" }, + { ERR_PACK(0, CRYPTOAPI_F_NCRYPT_SIGN_HASH, 0), "NCryptSignHash" }, { 0, NULL } }; typedef struct _CAPI_DATA { const CERT_CONTEXT *cert_context; - HCRYPTPROV crypt_prov; + HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov; DWORD key_spec; BOOL free_crypt_prov; } CAPI_DATA; @@ -210,6 +221,41 @@ rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, in return 0; } +/** + * Sign the hash in 'from' using NCryptSignHash(). This requires an NCRYPT + * key handle in cd->crypt_prov. On return the signature is in 'to'. Returns + * the length of the signature or 0 on error. + * For now we support only RSA and the padding is assumed to be PKCS1 v1.5 + */ +static int +priv_enc_CNG(const CAPI_DATA *cd, const unsigned char *from, int flen, + unsigned char *to, int tlen, int padding) +{ + NCRYPT_KEY_HANDLE hkey = cd->crypt_prov; + DWORD len; + ASSERT(cd->key_spec == CERT_NCRYPT_KEY_SPEC); + + msg(M_INFO, "Signing hash using CNG: data size = %d", flen); + + /* The hash OID is already in 'from'. So set the hash algorithm + * in the padding info struct to NULL. + */ + BCRYPT_PKCS1_PADDING_INFO padinfo = {NULL}; + DWORD status; + + status = NCryptSignHash(hkey, padding? &padinfo : NULL, (BYTE*) from, flen, + to, tlen, &len, padding? BCRYPT_PAD_PKCS1 : 0); + if (status != ERROR_SUCCESS) + { + SetLastError(status); + CRYPTOAPIerr(CRYPTOAPI_F_NCRYPT_SIGN_HASH); + len = 0; + } + + /* Unlike CAPI, CNG signature is in big endian order. No reversing needed. */ + return len; +} + /* sign arbitrary data */ static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) @@ -230,6 +276,11 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + return priv_enc_CNG(cd, from, flen, to, RSA_size(rsa), padding); + } + /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would * be way to straightforward for M$, I guess... So we have to do it this * tricky way instead, by creating a "Hash", and load the already-made hash @@ -322,7 +373,14 @@ finish(RSA *rsa) } if (cd->crypt_prov && cd->free_crypt_prov) { - CryptReleaseContext(cd->crypt_prov, 0); + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + NCryptFreeObject(cd->crypt_prov); + } + else + { + CryptReleaseContext(cd->crypt_prov, 0); + } } if (cd->cert_context) { @@ -458,7 +516,9 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) } /* set up stuff to use the private key */ - if (!CryptAcquireCertificatePrivateKey(cd->cert_context, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, + /* We prefer to get an NCRYPT key handle so that TLS1.2 can be supported */ + DWORD flags = CRYPT_ACQUIRE_COMPARE_KEY_FLAG|CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG; + if (!CryptAcquireCertificatePrivateKey(cd->cert_context, flags, NULL, &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov)) { /* if we don't have a smart card reader here, and we try to access a @@ -470,6 +530,17 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) /* here we don't need to do CryptGetUserKey() or anything; all necessary key * info is in cd->cert_context, and then, in cd->crypt_prov. */ + /* If we do not have an NCRYPT key handle disable TLS v1.2 */ + if (cd->key_spec != CERT_NCRYPT_KEY_SPEC) + { + if (!(SSL_CTX_get_options(ssl_ctx) & SSL_OP_NO_TLSv1_2)) + { + msg(M_WARN, "WARNING: cryptapicert: only legacy private key handle is available." + "Disabling TLS v1.2"); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2); + } + } + my_rsa_method = RSA_meth_new("Microsoft Cryptography API RSA Method", RSA_METHOD_FLAG_NO_CHECK); check_malloc_return(my_rsa_method); @@ -551,7 +622,14 @@ err: { if (cd->free_crypt_prov && cd->crypt_prov) { - CryptReleaseContext(cd->crypt_prov, 0); + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + NCryptFreeObject(cd->crypt_prov); + } + else + { + CryptReleaseContext(cd->crypt_prov, 0); + } } if (cd->cert_context) { diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 7be5f38..e4fbade 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -3018,24 +3018,6 @@ options_postprocess_mutate(struct options *o) } #endif -#ifdef ENABLE_CRYPTOAPI - if (o->cryptoapi_cert) - { - const int tls_version_max = - (o->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) - &SSLF_TLS_VERSION_MAX_MASK; - - if (tls_version_max == TLS_VER_UNSPEC || tls_version_max > TLS_VER_1_1) - { - msg(M_WARN, "Warning: cryptapicert used, setting maximum TLS " - "version to 1.1."); - o->ssl_flags &= ~(SSLF_TLS_VERSION_MAX_MASK - <ssl_flags |= (TLS_VER_1_1 << SSLF_TLS_VERSION_MAX_SHIFT); - } - } -#endif /* ENABLE_CRYPTOAPI */ - #if P2MP /* * Save certain parms before modifying options via --pull