From patchwork Fri Oct 5 14:08: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: 490 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id IJKlLz39t1tABwAAIUCqbw for ; Fri, 05 Oct 2018 20:09:33 -0400 Received: from proxy8.mail.iad3b.rsapps.net ([172.31.255.6]) by director7.mail.ord1d.rsapps.net with LMTP id mEjALD39t1vREAAAovjBpQ ; Fri, 05 Oct 2018 20:09:33 -0400 Received: from smtp21.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy8.mail.iad3b.rsapps.net with LMTP id OFf/JT39t1thDgAAoCsc3g ; Fri, 05 Oct 2018 20:09:33 -0400 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.105.38.7] Authentication-Results: smtp21.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; 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-Suspicious-Flag: YES X-Classification-ID: 19e51244-c8fc-11e8-8e35-525400cdc90a-1-1 Received: from [216.105.38.7] ([216.105.38.7:2344] helo=lists.sourceforge.net) by smtp21.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 75/C4-29799-D3DF7BB5; Fri, 05 Oct 2018 20:09:33 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1g8a8y-0005kM-UT; Sat, 06 Oct 2018 00:08:28 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1g8a8x-0005kF-Mp for openvpn-devel@lists.sourceforge.net; Sat, 06 Oct 2018 00:08:27 +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=Mjq8d6IrwUhWwnDIqivqkyYvkgk0d+BKU0Cjz0GTaqI=; b=XMSB4mdbb4EEJVVQRnJ1jTKpBq U8o+su576tgZeG6pLhkYwYEDFQoMHLrUvB5o7VCUAqvGAbFXgIF8dSpVGx1s8z+uNuQqMd2fAekOt Xy/tNG5ZQzABdYNY/WQWYY6/mQjz34SUTSFOQssMWj9L6GVM4jjGp9tbwwNUtbi6llXg=; 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=Mjq8d6IrwUhWwnDIqivqkyYvkgk0d+BKU0Cjz0GTaqI=; b=KscjZjcz+wtzkbWzzecQSNgATx jrPoF33UMLXCVmaaO0+dJQK38AB/9w9ktven9Pkv8ZEBTpPJxzh7Wt4xSjvio/Au0UjjiB5fP/0ty Cgcxvrd3Ry8lG6qI6m5jehfNq2dpabE20nl6v/iB3zooAR/w9RQ26eeLpEvsEhFuE2y4=; Received: from mail-io1-f68.google.com ([209.85.166.68]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.90_1) id 1g8a8v-00Cot3-Vq for openvpn-devel@lists.sourceforge.net; Sat, 06 Oct 2018 00:08:27 +0000 Received: by mail-io1-f68.google.com with SMTP id w16-v6so11959128iom.7 for ; Fri, 05 Oct 2018 17:08:25 -0700 (PDT) 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=Mjq8d6IrwUhWwnDIqivqkyYvkgk0d+BKU0Cjz0GTaqI=; b=VxO1MdboLeSc6kK7tUyDuDfrHpH172SToFw73tvN6rBH1OS0aya8+ynsLjUPpryPJ1 T/JNtdnR6a8sk7TN8JhMYDO+6VsCt6Qm18Mvei8KXiy7Qmt++6oAvPhLMZDK0pL8YhI9 mxUWmbNd6kJq8pnMd9Fdb3z/y3TqHitl0+0Q7A3RsvQdz75+OV0U5MbuG5FVRS0Y1y/+ oTy0LEzBjoGzkI/j8psRoGTbRsml6uaE+pwtwf3h+EuongWZ8DDroRGtkSE87m+H4jTR fwuWKilerAamhYEu6Hfun6DsWZJvB89Ykaf/Ur8RiqyuQA7HEnk9VFIQLinAVeUdvgiK zVVw== 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=Mjq8d6IrwUhWwnDIqivqkyYvkgk0d+BKU0Cjz0GTaqI=; b=D6Wfy6ZWxsM4AK73Qh5/pVIiFhheBRq/89wNBGdgZXtwQwQx+YhShEWaukR0bo2r9+ Q2j1Z0bhuS4JxRRhI96JdGGownWdp7tExetlPN/G/KZ3WMtUY24/7AFn1lhzu4GLgDUD MoLznxZWMXToQR9QamBnOUBN6/SHuJYSVFB/je+2+PgolnHZMMv8QnfAxgKJrTjNt36M SIMlj2dpVcz8vVC/hyMPwvRV+f8bo0jWGrUWWcm1gVaCV35mOU9Z26hfgNW8uk1RxEd4 p441aIMbuymio7HZ9goVv3g4mqN3b4+LGEZ6JAN3pQHFZZgv0Amf8P0l3T9e14XLHWr8 ihxw== X-Gm-Message-State: ABuFfoi4Am0Lz0iI5E2lY2Ib/UdMU1UZUPc6DMnFuI/dqAgjWRjqirhA iav4P34rOImAuQ2xNVBm87rZ/vbk X-Google-Smtp-Source: ACcGV60V+o/dGxEgoVtx8P6exE0z2492Rg4zKWzioAiIdC/PlIU+kbTjJ9kWG+4YQaaDAIWeRXF4kg== X-Received: by 2002:a6b:dc0c:: with SMTP id s12-v6mr8786996ioc.139.1538784499886; Fri, 05 Oct 2018 17:08:19 -0700 (PDT) Received: from saturn.home.sansel.ca (CPE40167ea0e1c2-CM788df74daaa0.cpe.net.cable.rogers.com. [99.228.215.92]) by smtp.gmail.com with ESMTPSA id z13-v6sm3069897ioj.86.2018.10.05.17.08.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 05 Oct 2018 17:08:19 -0700 (PDT) From: selva.nair@gmail.com To: openvpn-devel@lists.sourceforge.net Date: Fri, 5 Oct 2018 20:08:15 -0400 Message-Id: <1538784495-24988-1-git-send-email-selva.nair@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1524752664-27946-1-git-send-email-selva.nair@gmail.com> References: <1524752664-27946-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 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.166.68 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (selva.nair[at]gmail.com) -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.166.68 listed in wl.mailspike.net] -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_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1g8a8v-00Cot3-Vq Subject: [Openvpn-devel] [PATCH release-2.4] Pass the hash without the DigestInfo header to NCryptSignHash() 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 In case of TLS 1.2 signatures, the callback rsa_priv_enc() gets the hash with the DigestInfo prepended. Signing this using NCryptSignHash() with hash algorithm id set to NULL works in most cases. But when using some hardware tokens, the data gets interpreted as the pre TLS 1.2 MD5+SHA1 hash and is silently truncated to 36 bytes. Avoid this by passing the raw hash to NCryptSignHash() and let it add the DigestInfo. To get the raw hash we set the RSA_sign() method in the rsa_method structure. This callback bypasses rsa_priv_enc() and gets called with the hash type and the hash. Fixes Trac #1050 Cherry-picked from master 6b495dc4c5cfc118091ddc9c19330b3c9e3e3dff and conflicts resolved manually Changes: - Move setting RSA_sign method from ssl_ctx_set_rsakey() to its right place in SSL_CTX_use_CryptoAPI_certificate(). The former function is only in master and appeared when the code was refactored for EC cert support. - Remove the stale comment about NULL hash algorithm pointed out by Gert. Except for the context change of one hunk, the patch is the same as for master and nothing extra is pulled-in. Signed-off-by: Selva Nair Acked-by: Gert Doering --- src/openvpn/cryptoapi.c | 87 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index 89d253c..720fce0 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -217,22 +217,21 @@ rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, in * 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. + * If the hash_algo is not NULL, PKCS #1 DigestInfo header gets added + * to 'from', else it is signed as is. * 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) +priv_enc_CNG(const CAPI_DATA *cd, const wchar_t *hash_algo, const unsigned char *from, + int flen, unsigned char *to, int tlen, int padding) { NCRYPT_KEY_HANDLE hkey = cd->crypt_prov; - DWORD len; + DWORD len = 0; ASSERT(cd->key_spec == CERT_NCRYPT_KEY_SPEC); msg(D_LOW, "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}; + BCRYPT_PKCS1_PADDING_INFO padinfo = {hash_algo}; DWORD status; status = NCryptSignHash(hkey, padding? &padinfo : NULL, (BYTE*) from, flen, @@ -270,7 +269,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i } if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) { - return priv_enc_CNG(cd, from, flen, to, RSA_size(rsa), padding); + return priv_enc_CNG(cd, NULL, from, flen, to, RSA_size(rsa), padding); } /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would @@ -334,6 +333,69 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i return len; } +/* + * Sign the hash in |m| and return the signature in |sig|. + * Returns 1 on success, 0 on error. + * NCryptSignHash() is used to sign and it is instructed to add the + * the PKCS #1 DigestInfo header to |m| unless the hash algorithm is + * the MD5/SHA1 combination used in TLS 1.1 and earlier versions. + */ +static int +rsa_sign_CNG(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sig, unsigned int *siglen, const RSA *rsa) +{ + CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(RSA_get_method(rsa)); + const wchar_t *alg = NULL; + int padding = RSA_PKCS1_PADDING; + + *siglen = 0; + if (cd == NULL) + { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + switch (type) + { + case NID_md5: + alg = BCRYPT_MD5_ALGORITHM; + break; + + case NID_sha1: + alg = BCRYPT_SHA1_ALGORITHM; + break; + + case NID_sha256: + alg = BCRYPT_SHA256_ALGORITHM; + break; + + case NID_sha384: + alg = BCRYPT_SHA384_ALGORITHM; + break; + + case NID_sha512: + alg = BCRYPT_SHA512_ALGORITHM; + break; + + case NID_md5_sha1: + if (m_len != SSL_SIG_LENGTH) + { + RSAerr(RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH); + return 0; + } + /* No DigestInfo header is required -- set alg-name to NULL */ + alg = NULL; + break; + default: + msg(M_WARN, "cryptoapicert: Unknown hash type NID=0x%x", type); + RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return 0; + } + + *siglen = priv_enc_CNG(cd, alg, m, (int)m_len, sig, RSA_size(rsa), padding); + return (siglen == 0) ? 0 : 1; +} + /* decrypt */ static int rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) @@ -555,6 +617,15 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) RSA_meth_set_finish(my_rsa_method, finish); RSA_meth_set0_app_data(my_rsa_method, cd); + /* For CNG, set the RSA_sign method which gets priority over priv_enc(). + * This method is called with the raw hash without the digestinfo + * header and works better when using NCryptSignHash() with some tokens. + */ + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + RSA_meth_set_sign(my_rsa_method, rsa_sign_CNG); + } + rsa = RSA_new(); if (rsa == NULL) {