From patchwork Tue Dec 14 05:59:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Selva Nair X-Patchwork-Id: 2169 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.30.191.6]) by backend41.mail.ord1d.rsapps.net with LMTP id EMzrMuPNuGGsWAAAqwncew (envelope-from ) for ; Tue, 14 Dec 2021 12:01:23 -0500 Received: from proxy20.mail.ord1d.rsapps.net ([172.30.191.6]) by director8.mail.ord1d.rsapps.net with LMTP id AF2ZGOTNuGFKVQAAfY0hYg (envelope-from ) for ; Tue, 14 Dec 2021 12:01:24 -0500 Received: from smtp9.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy20.mail.ord1d.rsapps.net with LMTPS id QMoPGOTNuGFeegAAsk8m8w (envelope-from ) for ; Tue, 14 Dec 2021 12:01:24 -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.105.38.7] Authentication-Results: smtp9.gate.ord1d.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: 77199cec-5cff-11ec-9e3a-525400bd3b1f-1-1 Received: from [216.105.38.7] ([216.105.38.7:38840] helo=lists.sourceforge.net) by smtp9.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id DC/0D-23272-3EDC8B16; Tue, 14 Dec 2021 12:01:23 -0500 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.94.2) (envelope-from ) id 1mxB9v-00037U-QY; Tue, 14 Dec 2021 17:00:12 +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.94.2) (envelope-from ) id 1mxB9t-00037H-FY for openvpn-devel@lists.sourceforge.net; Tue, 14 Dec 2021 17:00:10 +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:References: In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=6HIhNfzNS0RJZlfHMZa0N6F0jXCh8GiFkfwpIVl7P2M=; b=O7UKf1yMU0FY/hVRsPtqhstLSk v9foDU3i0PTtpqllL4NTI8qdPT1bn6lsFtO0flQdHtq1dRNjiNUtFzB01BYa96KfN/QYpxqoQEg7B hvrhwAHFYcz4CJKNBDjh4L1YKNJaD6Ybq+8RgBFd/vfO9SMGZ/vvtSTVwA1H0K4XrHJs=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=6HIhNfzNS0RJZlfHMZa0N6F0jXCh8GiFkfwpIVl7P2M=; b=gz/+LREZ6nVsjZBue18E+2JLqe 0/FKwQ8M855fqlc3e5cvqOYuvu6h3TkFSI1S/DCbH5psqYoC2VRqUJ4gclOctezgbElNQr25ciWO4 9oPAZlHW9q5y4K7j1jL0g6vUWcKy+fq08RT1aFT3QsIoQ2xzYnwbMwJYoqD/GFLspS5g=; Received: from mail-io1-f52.google.com ([209.85.166.52]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.92.3) id 1mxB9o-0000bH-E0 for openvpn-devel@lists.sourceforge.net; Tue, 14 Dec 2021 17:00:10 +0000 Received: by mail-io1-f52.google.com with SMTP id q72so25286816iod.12 for ; Tue, 14 Dec 2021 09:00:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6HIhNfzNS0RJZlfHMZa0N6F0jXCh8GiFkfwpIVl7P2M=; b=hRuPDHZgefFdhxVzVQpvUexZj6C6e+2CG3J3MC3jjqZpOt23/c3emTlUH8kbjPVqFm twVHwNsXedYXX3E5IeamyaVdce9aP/d66Ucg170JJONvx+pAsDTsrDQ4T87+ZM3Y0tFZ hbMkupITgk2IfOrbkLgSgsT1h8ruDJc/d6jeDf4Fl3fn0aJKAbzvdbenfBWLNy/tLQB6 WYG/R7OWs3RURn4nV1n+Y0HGmudV01+Rb9gG1Ad3vdhYTerSpk6vUIFlAzKKtzJZr4Ed r0QP5z2K96qc87yzZjk5zXdPL8jaE7kHec3QOc626auyRyV0ERe0I1mtCFFXIaXwSZb3 AJfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6HIhNfzNS0RJZlfHMZa0N6F0jXCh8GiFkfwpIVl7P2M=; b=6NECngYCyAlF754NArAZ60a9NxpwGwCl9zgcVg5cn/OQ4tfBmdBU4bejP9ne77RwcP 8cfkeLzEqgvvoJxft+3SSVKJpGzFeQdRQcTKVHhAcRxAayEuHDPm3EeuxX1aUBXb5T8L 0FBU0z/KvorYhJw/VO4AU7hPTPeW+ZFNvWRldMcrOZGvSdqp2fCvBI/G/0ckA/e0RtY2 6HzHRmoyXBjV2KaXml8VPqcEplW4VLWI8LQufIYVjEBMIreunVH9dac9trO9Qx7ZY3dt 1QhMdIuihrjn1/inw7m/8votT/W+fbYrL1xSuOe0wdfndmgINq/LiMKLyoTuFoXDNCTe YU5w== X-Gm-Message-State: AOAM531ygIRuzctM1ljf2qtyc2b8f5wR2OVdeN4NGZQT+i8GSyM2AbW7 CcsQDTmY0Kfgqd6kwH6KH1v4QX4VP64= X-Google-Smtp-Source: ABdhPJw/jAGFo8w7dfWM7gNzjdAZD9kb190GrjPhoK7xcfgVJ+bN1nHwjT/6nJprSSa66OxQS5s0uQ== X-Received: by 2002:a02:714d:: with SMTP id n13mr3585195jaf.478.1639501197157; Tue, 14 Dec 2021 08:59:57 -0800 (PST) Received: from uranus.home.sansel.ca (bras-vprn-tnhlon4053w-lp130-02-70-51-223-8.dsl.bell.ca. [70.51.223.8]) by smtp.gmail.com with ESMTPSA id e9sm178778ilm.44.2021.12.14.08.59.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Dec 2021 08:59:56 -0800 (PST) From: selva.nair@gmail.com To: openvpn-devel@lists.sourceforge.net Date: Tue, 14 Dec 2021 11:59:18 -0500 Message-Id: <20211214165928.30676-9-selva.nair@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211214165928.30676-1-selva.nair@gmail.com> References: <20211214165928.30676-1-selva.nair@gmail.com> MIME-Version: 1.0 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 The EVP_PKEY interface as well as provider passes the raw digest to the sign() function. In case of RSA_PKCS1, our management interface expects an encoded hash, which has the DigestInfo header added a [...] 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.52 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -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 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.166.52 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_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: 1mxB9o-0000bH-E0 Subject: [Openvpn-devel] [PATCH v3 08/18] Add a function to encode digests with PKCS1 DigestInfo wrapper 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 From: Selva Nair The EVP_PKEY interface as well as provider passes the raw digest to the sign() function. In case of RSA_PKCS1, our management interface expects an encoded hash, which has the DigestInfo header added as per PKCSv1.5 specs, unless the hash algorithm is legacy MD5_SHA1. Fix this by - add a function to perform the pkcs1 encoding before passing the data to sign to the management interface. The implementation is not pretty, but should work. (Unfortunately OpenSSL does not expose a function for this). Note: 1. cryptoki interface used by pkcs11-helper also requires this to be done before calling the Sign op. This will come handy there too. 2. We have a similar function in ssl_mbedtls.c but its not prettier, and require porting. v2 changes: Use hard-coded headers for known hash algorithms instead of assembling it from the ASN.1 objects. Signed-off-by: Selva Nair Acked-By: Arne Schwabe --- src/openvpn/xkey_common.h | 20 ++++++ src/openvpn/xkey_helper.c | 130 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) diff --git a/src/openvpn/xkey_common.h b/src/openvpn/xkey_common.h index 608afe99..c04c9c5c 100644 --- a/src/openvpn/xkey_common.h +++ b/src/openvpn/xkey_common.h @@ -96,6 +96,26 @@ typedef void (XKEY_PRIVKEY_FREE_fn)(void *handle); */ EVP_PKEY *xkey_load_management_key(OSSL_LIB_CTX *libctx, EVP_PKEY *pubkey); +/** + * Add PKCS1 DigestInfo to tbs and return the result in *enc. + * + * @param enc pointer to output buffer + * @param enc_len capacity in bytes of output buffer + * @param mdname name of the hash algorithm (SHA256, SHA1 etc.) + * @param tbs pointer to digest to be encoded + * @param tbslen length of data in bytes + * + * @return false on error, true on success + * + * On return enc_len is set to actual size of the result. + * enc is NULL or enc_len is not enough to store the result, it is set + * to the required size and false is returned. + * + */ +bool +encode_pkcs1(unsigned char *enc, size_t *enc_len, const char *mdname, + const unsigned char *tbs, size_t tbslen); + #endif /* HAVE_XKEY_PROVIDER */ #endif /* XKEY_COMMON_H_ */ diff --git a/src/openvpn/xkey_helper.c b/src/openvpn/xkey_helper.c index aac78a2c..b2546cec 100644 --- a/src/openvpn/xkey_helper.c +++ b/src/openvpn/xkey_helper.c @@ -143,6 +143,9 @@ xkey_management_sign(void *unused, unsigned char *sig, size_t *siglen, unsigned char buf[EVP_MAX_MD_SIZE]; /* for computing digest if required */ size_t buflen = sizeof(buf); + unsigned char enc[EVP_MAX_MD_SIZE + 32]; /* 32 bytes enough for digest inf structure */ + size_t enc_len = sizeof(enc); + if (!strcmp(alg.op, "DigestSign")) { dmsg(D_LOW, "xkey_management_sign: computing digest"); @@ -165,6 +168,14 @@ xkey_management_sign(void *unused, unsigned char *sig, size_t *siglen, /* else assume RSA key */ else if (!strcmp(alg.padmode, "pkcs1")) { + /* management interface expects a pkcs1 encoded digest -- add it */ + if (!encode_pkcs1(enc, &enc_len, alg.mdname, tbs, tbslen)) + { + return 0; + } + tbs = enc; + tbslen = enc_len; + strncpynt(alg_str, "RSA_PKCS1_PADDING", sizeof(alg_str)); } else if (!strcmp(alg.padmode, "none")) @@ -205,4 +216,123 @@ xkey_management_sign(void *unused, unsigned char *sig, size_t *siglen, return (*siglen > 0); } +/** + * Add PKCS1 DigestInfo to tbs and return the result in *enc. + * + * @param enc pointer to output buffer + * @param enc_len capacity in bytes of output buffer + * @param mdname name of the hash algorithm (SHA256, SHA1 etc.) + * @param tbs pointer to digest to be encoded + * @param tbslen length of data in bytes + * + * @return false on error, true on success + * + * On return enc_len is set to actual size of the result. + * enc is NULL or enc_len is not enough to store the result, it is set + * to the required size and false is returned. + */ +bool +encode_pkcs1(unsigned char *enc, size_t *enc_len, const char *mdname, + const unsigned char *tbs, size_t tbslen) +{ + ASSERT(enc_len != NULL); + ASSERT(tbs != NULL); + + /* Tabulate the digest info header for expected hash algorithms + * These were pre-computed using the DigestInfo definition: + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * Also see the table in RFC 8017 section 9.2, Note 1. + */ + + const unsigned char sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, + 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}; + const unsigned char sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; + const unsigned char sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; + const unsigned char sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; + const unsigned char sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}; + const unsigned char sha512_224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05, 0x00, 0x04, 0x1c}; + const unsigned char sha512_256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20}; + + typedef struct { + const int nid; + const unsigned char *header; + size_t sz; + } DIG_INFO; + +#define MAKE_DI(x) {NID_##x, x, sizeof(x)} + + DIG_INFO dinfo[] = {MAKE_DI(sha1), MAKE_DI(sha256), MAKE_DI(sha384), + MAKE_DI(sha512), MAKE_DI(sha224), MAKE_DI(sha512_224), + MAKE_DI(sha512_256), {0,NULL,0}}; + + int out_len = 0; + int ret = 0; + + int nid = OBJ_sn2nid(mdname); + if(nid == NID_undef) + { + /* try harder -- name variants like SHA2-256 doesn't work */ + nid = EVP_MD_type(EVP_get_digestbyname(mdname)); + if(nid == NID_undef) + { + msg(M_WARN, "Error: encode_pkcs11: invalid digest name <%s>", mdname); + goto done; + } + } + + if (tbslen != EVP_MD_size(EVP_get_digestbyname(mdname))) + { + msg(M_WARN, "Error: encode_pkcs11: invalid input length <%d>", (int)tbslen); + goto done; + } + + if (nid == NID_md5_sha1) /* no encoding needed -- just copy */ + { + if (enc && (*enc_len >= tbslen)) + { + memcpy(enc, tbs, tbslen); + ret = true; + } + out_len = tbslen; + goto done; + } + + /* locate entry for nid in dinfo table */ + DIG_INFO *di = dinfo; + while((di->nid != nid) && (di->nid != 0)) + { + di++; + } + if (di->nid != nid) /* not found in our table */ + { + msg(M_WARN, "Error: encode_pkcs11: unsupported hash algorithm <%s>", mdname); + goto done; + } + + out_len = tbslen + di->sz; + + if (enc && (out_len <= (int) *enc_len)) + { + /* combine header and digest */ + memcpy(enc, di->header, di->sz); + memcpy(enc + di->sz, tbs, tbslen); + dmsg(D_LOW, "encode_pkcs1: digest length = %d encoded length = %d", + (int) tbslen, (int) out_len); + ret = true; + } + +done: + *enc_len = out_len; /* assignment safe as out_len is > 0 at this point */ + + return ret; +} + #endif /* HAVE_XKEY_PROVIDER */