From patchwork Sat Mar 11 05:24:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Selva Nair X-Patchwork-Id: 3123 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:2310:b0:9f:bfa4:120f with SMTP id r16csp103784dye; Fri, 10 Mar 2023 21:25:20 -0800 (PST) X-Google-Smtp-Source: AK7set+I4tScGTTvfCIerdMusYtGY5tqOY5TGMZS3aVRN1Ud42miN6Ot8pP4VO/CVAXRp3Co7nNJ X-Received: by 2002:a62:1aca:0:b0:5e1:a3b1:966a with SMTP id a193-20020a621aca000000b005e1a3b1966amr22914168pfa.34.1678512320244; Fri, 10 Mar 2023 21:25:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1678512320; cv=none; d=google.com; s=arc-20160816; b=d8a+HmzM33iYgz0W57yRow+XQYJzxHmRMy6l1d3c2HANgsenNOCKdYtnD1BUwd/7Pc hcg3bRipjKNvycPkU/qUAgfT3fJdAPm+HuIwLivWVTa2zhp3HXZb1CgvpEN3QGWSOxWq cDGDbdfBHC/LxkgTEQrKFv4/XzEOpfqzQU7zfIBXgto3V19ZW9kWufGbruSikSlX/fJ/ Yl7LWOI7SFNg/WP+Vdx3DTVfBW1eYg4dzSEBJOgmfUMlpATVuKBkLgmwlOada+OlELO1 pA6kZTm09WhQCxb6MWTpXCUY1JyF10wmR9rlVr/CXy53NMz42Z3V0Z7nl+uYjWkxQn81 5IXw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:date:to:from:dkim-signature:dkim-signature :dkim-signature; bh=WS/89oZmVlptM42jVdyWCEfnhGmIyAcgEF5K8si5eWA=; b=Am4Y5HGYf6ePp3BrvEVoO/CFQiPF/eVzxYvjATnmjUWS+f5f6LYFKXH1Xn1zOUapIw SBcEd+73MZ3SYz3UduZ0SEwq/EvnTP+89cuQabVKCes0FLUmaWaFt9fv33jju/fC38jP dTlB3Sh1S3tPhI/vRb8PijfvEiXdxjcYKMCDr5WLIaR+lxjk9Zle277MGhL9axLETq5N 0Y4TxIDIkiltMG+m/mZzF8LqN4xnHfYviNCSMLPBkcqRn6gA/Hjk82c+Mk+f46HrzjRi KvhWnidYjokMRvn/dQ/4ydD5/OxYXbRcR/ELxcMsK0rQKjpoOch40zf68Usk+DbZEBaK yvRg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=VXAATeym; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=KwiRcrWd; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=kDqGWtUj; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id bc22-20020a656d96000000b005077fe6b943si1412282pgb.806.2023.03.10.21.25.19 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Mar 2023 21:25:20 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=VXAATeym; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=KwiRcrWd; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=kDqGWtUj; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com 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.95) (envelope-from ) id 1pariR-0003kf-Il; Sat, 11 Mar 2023 05:24:24 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pariP-0003kZ-Hh for openvpn-devel@lists.sourceforge.net; Sat, 11 Mar 2023 05:24:22 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=K6QTs0ZkH6PRa2LwMS3aQZaU7a7rVQeC9VP9mUtVHUg=; b=VXAATeymCB3ssqOtNNCtZMrvqV /vSTD9FxDy3baKh/mag6M+KwGLwudxJJOp1hQy0ArFBJMpg1TsLle6vR3gB9FIqO0VXyNUFUNAmS3 k4Eoae6zt1b98TiH3Wkaglngz1BQ5KKv1/0myxYtWyAqmfBcB8UIjq+ueJkQh8Unq41c=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject:Cc:To:From :Sender:Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=K6QTs0ZkH6PRa2LwMS3aQZaU7a7rVQeC9VP9mUtVHUg=; b=K wiRcrWdXENocnP1hIpKRAimjKf6CJ7AYElbQ6o4QcOZVameyWFSiGHVvnTgSs4ujV6x9Msw2dgp0i cMgt3xKzu9M/RuN22IjMMDZHBlu89M7iLBBKEhhCAK7Mu3fuC1lMVI6ExG1ewG3c6Z9ptTzsgjDio I3vYpDD2Fiwn3xJY=; Received: from mail-il1-f170.google.com ([209.85.166.170]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1pariL-0006Hf-KR for openvpn-devel@lists.sourceforge.net; Sat, 11 Mar 2023 05:24:21 +0000 Received: by mail-il1-f170.google.com with SMTP id l9so1113943iln.1 for ; Fri, 10 Mar 2023 21:24:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678512251; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=K6QTs0ZkH6PRa2LwMS3aQZaU7a7rVQeC9VP9mUtVHUg=; b=kDqGWtUjsYJZChcyS9zhEFMb1wCFyWopvO0DtOoTS7iRudNn9gRrdn72eeHSWSb2Bz ygfndFoMJ+Yj7BnTT4cQo2Ie9m7cm3GuD7dhv+Vi/813tpP5+VNpNdeh4jMTkvBI9cVC 3+e/LOJdi1yuzfOz8qFOrOBNpPZDOfCD6ZG18xsMoPn7k/aPioOz3X+KHudL3XBgn3lU zDDpyxVuvVYTiRrcQ6albHfK4nYaO0g/VqF1ggQwEKAx3MpASF6qsa8Q7XkZ/GeUYpn3 nxV/xqP3XIWw/N+7Mf6MGHJ81BN8oKSEN7OgPfegUGkaH7xQr227nRTC070GrD+EytlP u4gQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678512251; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=K6QTs0ZkH6PRa2LwMS3aQZaU7a7rVQeC9VP9mUtVHUg=; b=ybf/+zs7qJ7rXG1XjjhALDu2pPD88AhTwMa8D1LI60tj11sgQWtpVClp9p0j2qlTbC l+62T4rpM4hVfVecWvvBoEz0u/1/HrY6Kl3YFFfABaJrUEgVhSITK//SNrK57xgombQo CeKaoQNayAnAye1CN+JBFqgQrVLo+kCTHyDCIzigG7N+C6YKa7APpwcrzACC0Q10PzSD zYHbYqdClyoTKNaXbWsMj/0uDejM4PpSsbG3kwjMBwsZBsv7qy36QDjXsr4rqP4v5IVb WeKh7eUqE2B50A8a+2lPzO+VLi6G5EvFTBgb2h/MGCf/izex2MXBzVZ0YPKuk0BFrDzQ +8Lg== X-Gm-Message-State: AO0yUKW9jWPG/YBcsBKq20rPQOXdbn4B53LJOCwRanU8a3yrIoVR7NJt XQwxpw8pkJGciZRMioBw9z1Y/eHiycQ= X-Received: by 2002:a05:6e02:5cb:b0:31f:9b6e:2f52 with SMTP id l11-20020a056e0205cb00b0031f9b6e2f52mr2679853ils.0.1678512250840; Fri, 10 Mar 2023 21:24:10 -0800 (PST) Received: from uranus.sansel.ca (bras-vprn-tnhlon4053w-lp130-01-70-51-222-66.dsl.bell.ca. [70.51.222.66]) by smtp.gmail.com with ESMTPSA id t15-20020a02c90f000000b003a60488c1fcsm559577jao.118.2023.03.10.21.24.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Mar 2023 21:24:10 -0800 (PST) From: selva.nair@gmail.com To: openvpn-devel@lists.sourceforge.net Date: Sat, 11 Mar 2023 00:24:03 -0500 Message-Id: <20230311052403.1154030-1-selva.nair@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Selva Nair - With OpenSSL 3.0 and xkey-provider, we use pkcs11h_certificate_signAny_ex() which returns EC signature as raw r|s concatenated. But OpenSSL expects a DER encoded ASN.1 structure. Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.166.170 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [selva.nair[at]gmail.com] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.166.170 listed in wl.mailspike.net] -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from 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.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-Headers-End: 1pariL-0006Hf-KR Subject: [Openvpn-devel] [PATCH] Bugfix: Convert ECDSA signature form pkcs11-helper to DER encoded form 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1760047734662907228?= X-GMAIL-MSGID: =?utf-8?q?1760047734662907228?= From: Selva Nair - With OpenSSL 3.0 and xkey-provider, we use pkcs11h_certificate_signAny_ex() which returns EC signature as raw r|s concatenated. But OpenSSL expects a DER encoded ASN.1 structure. Do this conversion as done in cryptoapi.c. For code re-use, ecdsa_bin2sig() is consolidated with sig to DER conversion as ecdsa_bin2der() and moved to xkey_helper.c In the past when we used OpenSSL hooks installed by pkcs11-helper, such a conversion was not required as it was internally handled by the library. Reported by: Tom Signed-off-by: Selva Nair Tested-by: florian@apolloner.eu --- src/openvpn/cryptoapi.c | 61 +++++------------------------------- src/openvpn/pkcs11_openssl.c | 23 ++++++++++++-- src/openvpn/xkey_common.h | 15 +++++++++ src/openvpn/xkey_helper.c | 45 ++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 56 deletions(-) diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index 136c6ffc..022f53d4 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -146,40 +146,6 @@ CAPI_DATA_free(CAPI_DATA *cd) free(cd); } -/** - * Helper to convert ECDSA signature returned by NCryptSignHash - * to an ECDSA_SIG structure. - * On entry 'buf[]' of length len contains r and s concatenated. - * Returns a newly allocated ECDSA_SIG or NULL (on error). - */ -static ECDSA_SIG * -ecdsa_bin2sig(unsigned char *buf, int len) -{ - ECDSA_SIG *ecsig = NULL; - DWORD rlen = len/2; - BIGNUM *r = BN_bin2bn(buf, rlen, NULL); - BIGNUM *s = BN_bin2bn(buf+rlen, rlen, NULL); - if (!r || !s) - { - goto err; - } - ecsig = ECDSA_SIG_new(); /* in openssl 1.1 this does not allocate r, s */ - if (!ecsig) - { - goto err; - } - if (!ECDSA_SIG_set0(ecsig, r, s)) /* ecsig takes ownership of r and s */ - { - ECDSA_SIG_free(ecsig); - goto err; - } - return ecsig; -err: - BN_free(r); /* it is ok to free NULL BN */ - BN_free(s); - return NULL; -} - /** * Parse a hex string with optional embedded spaces into * a byte array. @@ -287,12 +253,11 @@ static int xkey_cng_ec_sign(CAPI_DATA *cd, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { - BYTE buf[1024]; /* large enough for EC keys upto 1024 bits */ - DWORD len = _countof(buf); + DWORD len = *siglen; msg(D_LOW, "Signing using NCryptSignHash with EC key"); - DWORD status = NCryptSignHash(cd->crypt_prov, NULL, (BYTE *)tbs, tbslen, buf, len, &len, 0); + DWORD status = NCryptSignHash(cd->crypt_prov, NULL, (BYTE *)tbs, tbslen, sig, len, &len, 0); if (status != ERROR_SUCCESS) { @@ -301,26 +266,14 @@ xkey_cng_ec_sign(CAPI_DATA *cd, unsigned char *sig, size_t *siglen, const unsign return 0; } - /* NCryptSignHash returns r|s -- convert to OpenSSL's ECDSA_SIG */ - ECDSA_SIG *ecsig = ecdsa_bin2sig(buf, len); - if (!ecsig) + /* NCryptSignHash returns r|s -- convert to DER encoded buffer expected by OpenSSL */ + int derlen = ecdsa_bin2der(sig, (int) len, *siglen); + if (derlen <= 0) { - msg(M_NONFATAL, "Error in cryptopicert: Failed to convert ECDSA signature"); return 0; } - - /* convert internal signature structure 's' to DER encoded byte array in sig */ - if (i2d_ECDSA_SIG(ecsig, NULL) > EVP_PKEY_size(cd->pubkey)) - { - ECDSA_SIG_free(ecsig); - msg(M_NONFATAL, "Error in cryptoapicert: DER encoded ECDSA signature is too long"); - return 0; - } - - *siglen = i2d_ECDSA_SIG(ecsig, &sig); - ECDSA_SIG_free(ecsig); - - return (*siglen > 0); + *siglen = derlen; + return 1; } /** Sign hash in tbs using RSA key in cd and NCryptSignHash */ diff --git a/src/openvpn/pkcs11_openssl.c b/src/openvpn/pkcs11_openssl.c index 5c1de44e..eee86e17 100644 --- a/src/openvpn/pkcs11_openssl.c +++ b/src/openvpn/pkcs11_openssl.c @@ -168,6 +168,7 @@ xkey_pkcs11h_sign(void *handle, unsigned char *sig, unsigned char buf[EVP_MAX_MD_SIZE]; size_t buflen; + size_t siglen_max = *siglen; unsigned char enc[EVP_MAX_MD_SIZE + 32]; /* 32 bytes enough for DigestInfo header */ size_t enc_len = sizeof(enc); @@ -234,8 +235,26 @@ xkey_pkcs11h_sign(void *handle, unsigned char *sig, ASSERT(0); /* coding error -- we couldnt have created any such key */ } - return CKR_OK == pkcs11h_certificate_signAny_ex(cert, &mech, - tbs, tbslen, sig, siglen); + if (CKR_OK != pkcs11h_certificate_signAny_ex(cert, &mech, + tbs, tbslen, sig, siglen)) + { + return 0; + } + if (strcmp(sigalg.keytype, "EC")) + { + return 1; + } + + /* For EC keys, pkcs11 returns signature as r|s: convert to der encoded */ + int derlen = ecdsa_bin2der(sig, (int) *siglen, siglen_max); + + if (derlen <= 0) + { + return 0; + } + *siglen = derlen; + + return 1; } /* wrapper for handle free */ diff --git a/src/openvpn/xkey_common.h b/src/openvpn/xkey_common.h index 07b70c08..51cdb5b7 100644 --- a/src/openvpn/xkey_common.h +++ b/src/openvpn/xkey_common.h @@ -33,6 +33,7 @@ #define HAVE_XKEY_PROVIDER 1 #include #include +#include /** * Initialization function for OpenVPN external key provider for OpenSSL @@ -170,6 +171,20 @@ xkey_max_saltlen(int modBits, int hLen) return emLen - hLen - 2; } + +/** + * @brief Convert raw ECDSA signature to DER encoded + * This function converts ECDSA signature provided as a buffer + * containing r|s to DER encoded ASN.1 expected by OpenSSL + * @param buf signature containing r|s. + * @param len size of signature in bytes + * @param capacity max space in the buffer buf in bytes + * @returns the size of the converted signature or <= 0 on error. + * On success, buf is overwritten by its DER encoding + */ +int +ecdsa_bin2der(unsigned char *buf, int len, size_t capacity); + #endif /* HAVE_XKEY_PROVIDER */ #endif /* ENABLE_CRYPTO_OPENSSL */ diff --git a/src/openvpn/xkey_helper.c b/src/openvpn/xkey_helper.c index 052c60c4..ee9677ab 100644 --- a/src/openvpn/xkey_helper.c +++ b/src/openvpn/xkey_helper.c @@ -401,4 +401,49 @@ done: return ret; } +/** + * Helper to convert ECDSA signature with r and s concatenated + * to a DER encoded format used by OpenSSL. + * Returns the size of the converted signature or <= 0 on error. + * On success, buf is overwritten by the DER encoded signature. + */ +int +ecdsa_bin2der(unsigned char *buf, int len, size_t capacity) +{ + ECDSA_SIG *ecsig = NULL; + int rlen = len/2; + BIGNUM *r = BN_bin2bn(buf, rlen, NULL); + BIGNUM *s = BN_bin2bn(buf+rlen, rlen, NULL); + if (!r || !s) + { + goto err; + } + ecsig = ECDSA_SIG_new(); /* this does not allocate r, s */ + if (!ecsig) + { + goto err; + } + if (!ECDSA_SIG_set0(ecsig, r, s)) /* ecsig takes ownership of r and s */ + { + ECDSA_SIG_free(ecsig); + goto err; + } + + int derlen = i2d_ECDSA_SIG(ecsig, NULL); + if (derlen > (int) capacity) + { + ECDSA_SIG_free(ecsig); + msg(M_NONFATAL, "Error: DER encoded ECDSA signature is too long (%d)\n", derlen); + return 0; + } + derlen = i2d_ECDSA_SIG(ecsig, &buf); + ECDSA_SIG_free(ecsig); + return derlen; + +err: + BN_free(r); /* it is ok to free NULL BN */ + BN_free(s); + return 0; +} + #endif /* HAVE_XKEY_PROVIDER */