From patchwork Wed Sep 22 11:12:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Selva Nair X-Patchwork-Id: 1971 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director13.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id yC3UNqycS2GLCQAAIUCqbw (envelope-from ) for ; Wed, 22 Sep 2021 17:14:20 -0400 Received: from proxy16.mail.iad3b.rsapps.net ([172.31.255.6]) by director13.mail.ord1d.rsapps.net with LMTP id aGwsNqycS2FHXwAA91zNiA (envelope-from ) for ; Wed, 22 Sep 2021 17:14:20 -0400 Received: from smtp32.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy16.mail.iad3b.rsapps.net with LMTPS id +LRGL6ycS2EtEAAAPj+4aA (envelope-from ) for ; Wed, 22 Sep 2021 17:14:20 -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: smtp32.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: 0d22e2d6-1bea-11ec-8d97-5254006a2e70-1-1 Received: from [216.105.38.7] ([216.105.38.7:51044] helo=lists.sourceforge.net) by smtp32.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 42/5D-06898-CAC9B416; Wed, 22 Sep 2021 17:14:20 -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 1mT9YW-0007BO-2i; Wed, 22 Sep 2021 21:13: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 1mT9YM-00079y-Ld for openvpn-devel@lists.sourceforge.net; Wed, 22 Sep 2021 21:13:18 +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=lcAgHugMmOBwOl4Q7tieqwAD9mSI425n6ReCoSWD7nk=; b=QI/us/+m48OIJGt6jNDQohliVJ nelM7BQT5qG1umlsEWXCpwce7Pbc1aCSmQ5Tewi4syIl+KXmcO0SSub3vb9Ly7Lx0EbsREBARMd0r Y+xxUaCbWCNpqVOqJpEFRjIID1dZ3aTNBo0f71apY59ZVbdIwrx29aOrRyZdobPbCtj8=; 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=lcAgHugMmOBwOl4Q7tieqwAD9mSI425n6ReCoSWD7nk=; b=hO7yyyQXmLaY9Rj0iNM/7BYRik KDkEnYzySrWNhq4peq8QsuyI6cBTzqpAWjOGjsLSQR5Ir+dSDkq7ke1dTpax3tggBbvSMf0oybn0B Q2padcRAMl+4PIT+MxLBkRCREGT8Mu6xXP7sewCHNWa+LZfC5vq7tqO5mKPIBZAayxsE=; Received: from mail-qt1-f176.google.com ([209.85.160.176]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.92.3) id 1mT9YL-00060Q-Rk for openvpn-devel@lists.sourceforge.net; Wed, 22 Sep 2021 21:13:18 +0000 Received: by mail-qt1-f176.google.com with SMTP id c19so4147353qte.7 for ; Wed, 22 Sep 2021 14:13:17 -0700 (PDT) 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=lcAgHugMmOBwOl4Q7tieqwAD9mSI425n6ReCoSWD7nk=; b=P5jMVOUE2+pqbdqicpPI4rG7ZmcUwLP58TGOgPEaYEAZJ6WrXeF2LEoGsTeNwRSFAH h/gX0KEvo/3KKm6B9ITd7mnnw3fH1uviqxeMW376k1qazJQ3NToqAVdpG6qUk3NHf7YA l9NMmZnAE2EG7jc4tcva9e1kc3NDXD5OKQKykBT6ONCijduHe7XtVkVqaSMz1n9ek8it llofJ4PKL2svP6D3Fhd+5/U9GOIU1MGE/Kgospofc2d0b2qu0KOL6NyyWGZk4pQDh3ev EkpoKgyGjhINR9MkumFxGc48VGf8Fo2Xu/qRF5W93v2yQ8g1QHssvXvSpuHHFd6R/B5p z0oA== 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=lcAgHugMmOBwOl4Q7tieqwAD9mSI425n6ReCoSWD7nk=; b=Wf3HpzTUrHUOVkPnoTmtnM8ex+ba98Ckb27CVR2IbJGrFWQLgpY7+DoN71iLjkbhVI vHSecw597oZV10ye7ZvIobjAno7JLDkKirlQfvlCZPQ8dbmj2qfbllZWXkBXzlARp8Wu EXDsG+uWa9T/e5cf6XzhCYJOVKdNCnkF7znjpA9TS18l6VvZ/dsg8MTgYbMDzLok5KbU DQxBixBAKU3/W2Q13JXV2+9KB6wU5nQf4JkhPikD5EvcPHPnTJ57zW2LK7GFzsUiP5xV nzpDFSjkwReZxnrGwu9YZqNpcEXewnBF14yWQOZ0wb3xSqSF/EP3fRF/cdoTXJZSk5dW keYw== X-Gm-Message-State: AOAM532CFJtpesjnq6FkP6J9pSFe8K0mEiECghRwVGKa+X95/2bGr44J Ny1t435kOLgbc7s9XyYOzXxGiLsNVa8= X-Google-Smtp-Source: ABdhPJztlzrOU2M1y/hyaBWdKk1dH52KQu8r6U2ckjgiu7KNU4VQmaplgcuV/GG13wkhIhsmWErjoQ== X-Received: by 2002:ac8:5c44:: with SMTP id j4mr793949qtj.164.1632345190247; Wed, 22 Sep 2021 14:13:10 -0700 (PDT) Received: from uranus.home.sansel.ca (bras-vprn-tnhlon4053w-lp130-02-70-51-223-227.dsl.bell.ca. [70.51.223.227]) by smtp.gmail.com with ESMTPSA id l7sm2185243qth.19.2021.09.22.14.13.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Sep 2021 14:13:09 -0700 (PDT) From: selva.nair@gmail.com To: openvpn-devel@lists.sourceforge.net Date: Wed, 22 Sep 2021 17:12:53 -0400 Message-Id: <20210922211254.7570-9-selva.nair@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210922211254.7570-1-selva.nair@gmail.com> References: <20210922211254.7570-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 provides the raw digest to the sign() function. In case of RSA_PKCS1, our management interface expects expects an encoded hash, which has the DigestInfo head [...] 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.160.176 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 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_MSPIKE_H2 RBL: Average reputation (+2) [209.85.160.176 listed in wl.mailspike.net] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -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 X-Headers-End: 1mT9YL-00060Q-Rk Subject: [Openvpn-devel] [PATCH 8/9] 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 provides the raw digest to the sign() function. In case of RSA_PKCS1, our management interface expects 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. Signed-off-by: Selva Nair --- src/openvpn/xkey_common.h | 20 ++++++ src/openvpn/xkey_helper.c | 127 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/src/openvpn/xkey_common.h b/src/openvpn/xkey_common.h index 6a00c382..e92d4868 100644 --- a/src/openvpn/xkey_common.h +++ b/src/openvpn/xkey_common.h @@ -97,4 +97,24 @@ 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 /* XKEY_PUBLIC_H_ */ diff --git a/src/openvpn/xkey_helper.c b/src/openvpn/xkey_helper.c index c9e8d218..4d41631b 100644 --- a/src/openvpn/xkey_helper.c +++ b/src/openvpn/xkey_helper.c @@ -115,6 +115,17 @@ 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 */ + unsigned char enc[EVP_MAX_MD_SIZE + 32]; /* 32 bytes enough for digest inf structure */ + size_t enc_len = sizeof(enc); + + if (!encode_pkcs1((unsigned char **)&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")) @@ -155,4 +166,120 @@ 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) +{ + bool ret = false; + unsigned char *ptr; + int out_len = 0; + int tmp_len; + X509_ALGOR *algor = NULL; + ASN1_STRING *digest = NULL; + + ASSERT(enc_len != NULL); + ASSERT(tbs != NULL); + + int nid = OBJ_sn2nid(mdname); + if(nid == NID_undef) + { + msg(M_WARN, "Error: encode_pkcs11: invalid digest name <%s>", mdname); + return false; + } + + if (nid == NID_md5_sha1) /* no encoding needed -- just copy */ + { + out_len = (int) tbslen; + if (enc && (*enc_len >= out_len)) + { + memcpy(*enc, tbs, out_len); + } + *enc_len = tbslen; + ret = 1; + goto cleanup; + } + + if((algor = X509_ALGOR_new()) == NULL + || X509_ALGOR_set0(algor, OBJ_nid2obj(nid), V_ASN1_NULL, NULL) <= 0 + || (digest = ASN1_STRING_type_new(V_ASN1_OCTET_STRING)) == NULL + || ASN1_STRING_set(digest, tbs, tbslen) <= 0) + { + msg(M_WARN, "Error: encode_pkcs11: failed to create ASN1 strings"); + goto cleanup; + } + + if(algor->algorithm == NULL || OBJ_length(algor->algorithm) == 0) + { + msg(M_WARN, "Error: encode_pkcs11: invalide digest type(nid = %d)", nid); + goto cleanup; + } + + /* We want DER encoding of X509_SIG = {algor, digest} which could be + * computed as i2d_X509_SIG(), but, unfortunately, the X509_SIG struct + * is opaque and has no constructor. Hence we combine the two elements + * into a sequence ourselves -- not pretty + */ + + /* find required size for the buffer */ + if((tmp_len = i2d_X509_ALGOR(algor, NULL)) < 0) + { + goto cleanup; + } + out_len = tmp_len; + + if((tmp_len = i2d_ASN1_OCTET_STRING(digest, NULL)) < 0) + { + goto cleanup; + } + out_len += tmp_len + 2 ; /* extra 2 bytes for sequence header added below */ + + if ((out_len > (int) *enc_len) || !enc) + { + *enc_len = out_len; + goto cleanup; + } + + ptr = *enc; + *ptr++ = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; + *ptr++ = out_len - 2; + + /* compute and append the DER of algor and digest to ptr */ + i2d_X509_ALGOR(algor, &ptr); /* this advances ptr */ + i2d_ASN1_OCTET_STRING(digest, &ptr); + + *enc_len = out_len; /* assignment safe as out_len is > 0 at this point */ + ret = 1; + + dmsg(D_LOW, "encode_pkcs1: digest length = %d encoded length = %d", + (int) tbslen, out_len); + +cleanup: + if(digest) + { + ASN1_STRING_free(digest); + } + if(algor) + { + X509_ALGOR_free(algor); + } + + return ret; +} + #endif /* HAVE_XKEY_PROVIDER */