From patchwork Wed Jun 22 09:15:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12890385 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 05021C433EF for ; Wed, 22 Jun 2022 09:21:51 +0000 (UTC) Received: from localhost ([::1]:54570 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3wYY-0007Xy-Sz for qemu-devel@archiver.kernel.org; Wed, 22 Jun 2022 05:21:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59246) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3wTO-0000Tr-OU for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:30 -0400 Received: from mail-pf1-x431.google.com ([2607:f8b0:4864:20::431]:45692) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3wT9-0007JR-2u for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:27 -0400 Received: by mail-pf1-x431.google.com with SMTP id 128so8530460pfv.12 for ; Wed, 22 Jun 2022 02:16:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bedEv8kPUBwcLd77LuagpTBOJ8uCIJxbwZbwc24pZBQ=; b=kZc3lURBau3IrF8Y0sgcESp3T+QsIujTuKk3VjcbADM8fNSSILsqL2anSIwhNvaJbN du0QO1JEko4BKlUuBAk71eLvRTY2/NI/0sBdIzgqoDiBoCCHGHx2ugwaclxaGWGG2ijY 2/DJG+au/BYQh4LRlYDlu5BLeXdDyDKocdzqVKYXuhPorLp+d+aNBq3IA1NOPDk0s5D0 L1jIjHzsyfjfcjCQ5bMRnVvSY7AgncZSXWZynmtG7uz4E/HhQolRAtqsF9nyKc2pl5r9 FLMct+RjQRCxZqZxhL03E68yHoFeUX72pT0j4qHTpVxUtcYl5+iJ5fHcouQEkZRXnEir e3iw== 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=bedEv8kPUBwcLd77LuagpTBOJ8uCIJxbwZbwc24pZBQ=; b=VQEdOUJEX+Ax/Mj7fwqKAYY/QD5fVo/QhR60YevPL8n71vHQQp0qNcGrEEkMuoYVY/ q8rECzUPS7O5rvYAc2gJLZQZPCn2sAVFEw9iqFMMeZ6w5G4u3KU5Q5Fa0ecdnlEGYhbp rV421OyznLrmewT+pRmCS7tF+5uH4yil8L9Y2sNfr57tI+hn5nNv75dGmgMPBWQ0F65y lBqBO1rtbDQ932TMVw+Khmjz7Nx0lsRGLyWw4CzuI9jNeTqEbE8celeeWLizXgKLo/Rh HV6Sb3jLjjRvLzBC5xnsJOSsK04mnHdgGkXVoomLa8E5Ya7n1FWr7w7oxNimIwuShpfx ykRg== X-Gm-Message-State: AJIora89MKdMB/zcvKY2GrBMIdZ9OeT3IhHGdwkepVgzqzwUqFhFkr5f 45XiYTiSB3sJ3vIGZjVTjUK7hwiklti4Dj43 X-Google-Smtp-Source: AGRyM1u2cSBbUoKFYv01N4y8NSsrKMbavSf7Vr6ZJOZcpZmP0HcJp8irdN4be99liZlc0ShO6TjuHg== X-Received: by 2002:a05:6a00:cc6:b0:525:443f:8e9e with SMTP id b6-20020a056a000cc600b00525443f8e9emr2961069pfv.56.1655889373035; Wed, 22 Jun 2022 02:16:13 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id ja13-20020a170902efcd00b0016a087cfad8sm9833900plb.264.2022.06.22.02.16.10 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 02:16:12 -0700 (PDT) From: Lei He To: qemu-devel@nongnu.org, berrange@redhat.com, f4bug@amsat.org Cc: mst@redhat.com, pizhenwei@bytedance.com, jasowang@redhat.com, helei.sig11@bytedance.com Subject: [PATCH v2 1/7] crypto: Introduce ECDSA algorithm API Date: Wed, 22 Jun 2022 17:15:43 +0800 Message-Id: <20220622091549.31115-2-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20220622091549.31115-1-helei.sig11@bytedance.com> References: <20220622091549.31115-1-helei.sig11@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::431; envelope-from=helei.sig11@bytedance.com; helo=mail-pf1-x431.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Introduce ECDSA related structures to qapi-crypto. Signed-off-by: lei he Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel P. Berrangé --- qapi/crypto.json | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/qapi/crypto.json b/qapi/crypto.json index 653e6e3f3d..c42e281494 100644 --- a/qapi/crypto.json +++ b/qapi/crypto.json @@ -545,7 +545,7 @@ ## { 'enum': 'QCryptoAkCipherAlgorithm', 'prefix': 'QCRYPTO_AKCIPHER_ALG', - 'data': ['rsa']} + 'data': ['rsa', 'ecdsa']} ## # @QCryptoAkCipherKeyType: @@ -587,6 +587,29 @@ 'padding-alg': 'QCryptoRSAPaddingAlgorithm'}} ## +# @QCryptoCurveID: +# +# The known curved for ECC algorithms. +# +# Since: 7.1 +## +{ 'enum': 'QCryptoCurveID', + 'prefix': 'QCRYPTO_CURVE_ID', + 'data': ['nist-p192', 'nist-p256', 'nist-p384']} + +## +# @QCryptoAkCipherOptionsECDSA: +# +# Specific parameters for ECDSA algorithm. +# +# @curve-id: QCryptoCurveId +# +# Since: 7.1 +## +{ 'struct': 'QCryptoAkCipherOptionsECDSA', + 'data': { 'curve-id': 'QCryptoCurveID' }} + +## # @QCryptoAkCipherOptions: # # The options that are available for all asymmetric key algorithms @@ -597,4 +620,5 @@ { 'union': 'QCryptoAkCipherOptions', 'base': { 'alg': 'QCryptoAkCipherAlgorithm' }, 'discriminator': 'alg', - 'data': { 'rsa': 'QCryptoAkCipherOptionsRSA' }} + 'data': { 'rsa': 'QCryptoAkCipherOptionsRSA', + 'ecdsa': 'QCryptoAkCipherOptionsECDSA' }} From patchwork Wed Jun 22 09:15:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12890384 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5F498C433EF for ; Wed, 22 Jun 2022 09:19:10 +0000 (UTC) Received: from localhost ([::1]:48398 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3wVx-0003Ix-Ff for qemu-devel@archiver.kernel.org; Wed, 22 Jun 2022 05:19:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59290) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3wTO-0000U6-St for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:32 -0400 Received: from mail-pf1-x435.google.com ([2607:f8b0:4864:20::435]:45696) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3wTC-0007Ks-DP for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:28 -0400 Received: by mail-pf1-x435.google.com with SMTP id 128so8530566pfv.12 for ; Wed, 22 Jun 2022 02:16:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Pw3nfd8yScn8QmasYYWP6sjcK18fdrxpP+8etMBFPZo=; b=JjkTrWEcn7go3fCfzpv2CEJ1Cp5JE9DCHLmqFVLIoo/quZi8m7xPyk2GzHqK7QYqOF I8DPUcLqPCzzsl4Spr3pz9/PDbxu1snraRA0o/LKjpPgrrqqiMGphn5gjlsjTv0ewOvd +OWRK1tsaAs2u/gGKkA7FUtbn4Cs88nSmb1FHi2lTk8pPTuNqMeW+WuyLjQ6c64yh4R4 pVwILu74kjvO8vul4VlED2raqDQ3N9PgE+7o1AooD40SatXkosKofO2ZBLKU4Y7w/FWy hweWRNEuvFNsOlML/AuzHxuJEICzKSfzjMfsJm0ccE74rdfJ7gp5D85UYybAUWAuCQsq ZCKw== 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=Pw3nfd8yScn8QmasYYWP6sjcK18fdrxpP+8etMBFPZo=; b=QRegHspTdopK6WvA/hTuY1a6OeWyOoBZ21pOEWTXgAUmO+5CR6BK0xvQ4EfUMS6mTA EE/YZe3HBOzfriAhx6qhdf7uaPLiTk5J1ThGEPwdlxSX3elalxOYDv53pNTX8ZBIwuSe PjqWkPSdFRiAEqcUK3VyuTCMsbhkUP+Y6sa9vI65kgxRQoRLXgO3E05lhMPo5utSY3WQ tPss+YBLBMyLOXxZdZS5qPFfBxZp+LyQJTwI741834mC4viDkxSWYL5ZkR+IgFTOupLM VATn2wsRhEe36ZWSQyqpmUxwX/UDEVtmiWyl+CESf20f6cfxFNxMdhuQ8IBUDBqGQ4pw UmHA== X-Gm-Message-State: AJIora9ficF6gEEmkTBEnhYxOWTADK1EHkA8MdmQwmHuSKu6etGcLfsG KW+hSmkW48a8tdBauhwSZ+A6Oo0BcwqLpw== X-Google-Smtp-Source: AGRyM1tNZuVnYFawLZ6rBcMCYLqm626wHRNdwLKgGf+GU7r8uB6S/srcAf6icWGth0N2zin7wTpq5Q== X-Received: by 2002:a63:d013:0:b0:3fc:e50f:8e2a with SMTP id z19-20020a63d013000000b003fce50f8e2amr2154260pgf.283.1655889376519; Wed, 22 Jun 2022 02:16:16 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id ja13-20020a170902efcd00b0016a087cfad8sm9833900plb.264.2022.06.22.02.16.13 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 02:16:16 -0700 (PDT) From: Lei He To: qemu-devel@nongnu.org, berrange@redhat.com, f4bug@amsat.org Cc: mst@redhat.com, pizhenwei@bytedance.com, jasowang@redhat.com, helei.sig11@bytedance.com Subject: [PATCH v2 2/7] crypto: Support more ASN.1 types Date: Wed, 22 Jun 2022 17:15:44 +0800 Message-Id: <20220622091549.31115-3-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20220622091549.31115-1-helei.sig11@bytedance.com> References: <20220622091549.31115-1-helei.sig11@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::435; envelope-from=helei.sig11@bytedance.com; helo=mail-pf1-x435.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 1. support decoding of 'bit string','octet string', 'object id', and 'context specific tag' for DER decoder. 2. support encoding of int and sequence for DER decoder. 3. add test suites for the above changes. Signed-off-by: lei he Reviewed-by: Daniel P. Berrangé --- crypto/der.c | 173 +++++++++++++++++++++++++++++++++++++------ crypto/der.h | 128 +++++++++++++++++++++++++++++++- tests/unit/test-crypto-der.c | 126 +++++++++++++++++++++++++------ 3 files changed, 381 insertions(+), 46 deletions(-) diff --git a/crypto/der.c b/crypto/der.c index f877390bbb..7c643174d6 100644 --- a/crypto/der.c +++ b/crypto/der.c @@ -27,15 +27,67 @@ enum QCryptoDERTypeTag { QCRYPTO_DER_TYPE_TAG_INT = 0x2, QCRYPTO_DER_TYPE_TAG_BIT_STR = 0x3, QCRYPTO_DER_TYPE_TAG_OCT_STR = 0x4, - QCRYPTO_DER_TYPE_TAG_OCT_NULL = 0x5, - QCRYPTO_DER_TYPE_TAG_OCT_OID = 0x6, + QCRYPTO_DER_TYPE_TAG_NULL = 0x5, + QCRYPTO_DER_TYPE_TAG_OID = 0x6, QCRYPTO_DER_TYPE_TAG_SEQ = 0x10, QCRYPTO_DER_TYPE_TAG_SET = 0x11, }; -#define QCRYPTO_DER_CONSTRUCTED_MASK 0x20 +enum QCryptoDERTagClass { + QCRYPTO_DER_TAG_CLASS_UNIV = 0x0, + QCRYPTO_DER_TAG_CLASS_APPL = 0x1, + QCRYPTO_DER_TAG_CLASS_CONT = 0x2, + QCRYPTO_DER_TAG_CLASS_PRIV = 0x3, +}; + +enum QCryptoDERTagEnc { + QCRYPTO_DER_TAG_ENC_PRIM = 0x0, + QCRYPTO_DER_TAG_ENC_CONS = 0x1, +}; + +#define QCRYPTO_DER_TAG_ENC_MASK 0x20 +#define QCRYPTO_DER_TAG_ENC_SHIFT 5 + +#define QCRYPTO_DER_TAG_CLASS_MASK 0xc0 +#define QCRYPTO_DER_TAG_CLASS_SHIFT 6 + +#define QCRYPTO_DER_TAG_VAL_MASK 0x1f #define QCRYPTO_DER_SHORT_LEN_MASK 0x80 +#define QCRYPTO_DER_TAG(class, enc, val) \ + (((class) << QCRYPTO_DER_TAG_CLASS_SHIFT) | \ + ((enc) << QCRYPTO_DER_TAG_ENC_SHIFT) | (val)) + +static void qcrypto_der_encode_data(const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + size_t max_length = 0xFF; + uint8_t length_bytes = 0, header_byte; + + if (src_len < QCRYPTO_DER_SHORT_LEN_MASK) { + header_byte = src_len; + *dst_len = src_len + 1; + } else { + for (length_bytes = 1; max_length < src_len; length_bytes++) { + max_length = (max_length << 8) + max_length; + } + header_byte = length_bytes; + header_byte |= QCRYPTO_DER_SHORT_LEN_MASK; + *dst_len = src_len + length_bytes + 1; + } + if (!dst) { + return; + } + *dst++ = header_byte; + /* Bigendian length bytes */ + while (length_bytes) { + *dst++ = (src_len >> (length_bytes - 1) * 8); + src_len >>= 8; + length_bytes--; + } + memcpy(dst, src, src_len); +} + static uint8_t qcrypto_der_peek_byte(const uint8_t **data, size_t *dlen) { return **data; @@ -150,40 +202,119 @@ static int qcrypto_der_extract_data(const uint8_t **data, size_t *dlen, return qcrypto_der_extract_definite_data(data, dlen, cb, ctx, errp); } -int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen, - QCryptoDERDecodeCb cb, void *ctx, Error **errp) +static int qcrypto_der_decode_tlv(const uint8_t expected_tag, + const uint8_t **data, size_t *dlen, + QCryptoDERDecodeCb cb, + void *ctx, Error **errp) { + const uint8_t *saved_data = *data; + size_t saved_dlen = *dlen; uint8_t tag; + int data_length; + if (*dlen < 1) { error_setg(errp, "Need more data"); return -1; } tag = qcrypto_der_cut_byte(data, dlen); + if (tag != expected_tag) { + error_setg(errp, "Unexpected tag: expected: %u, actual: %u", + expected_tag, tag); + goto error; + } - /* INTEGER must encoded in primitive-form */ - if (tag != QCRYPTO_DER_TYPE_TAG_INT) { - error_setg(errp, "Invalid integer type tag: %u", tag); - return -1; + data_length = qcrypto_der_extract_data(data, dlen, cb, ctx, errp); + if (data_length < 0) { + goto error; } + return data_length; + +error: + *data = saved_data; + *dlen = saved_dlen; + return -1; +} - return qcrypto_der_extract_data(data, dlen, cb, ctx, errp); +int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen, + QCryptoDERDecodeCb cb, void *ctx, Error **errp) +{ + const uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV, + QCRYPTO_DER_TAG_ENC_PRIM, + QCRYPTO_DER_TYPE_TAG_INT); + return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp); } int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen, QCryptoDERDecodeCb cb, void *ctx, Error **errp) { - uint8_t tag; - if (*dlen < 1) { - error_setg(errp, "Need more data"); - return -1; - } - tag = qcrypto_der_cut_byte(data, dlen); + uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV, + QCRYPTO_DER_TAG_ENC_CONS, + QCRYPTO_DER_TYPE_TAG_SEQ); + return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp); +} - /* SEQUENCE must use constructed form */ - if (tag != (QCRYPTO_DER_TYPE_TAG_SEQ | QCRYPTO_DER_CONSTRUCTED_MASK)) { - error_setg(errp, "Invalid type sequence tag: %u", tag); - return -1; +int qcrypto_der_decode_octet_str(const uint8_t **data, size_t *dlen, + QCryptoDERDecodeCb cb, void *ctx, Error **errp) +{ + uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV, + QCRYPTO_DER_TAG_ENC_PRIM, + QCRYPTO_DER_TYPE_TAG_OCT_STR); + return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp); +} + +int qcrypto_der_decode_bit_str(const uint8_t **data, size_t *dlen, + QCryptoDERDecodeCb cb, void *ctx, Error **errp) +{ + uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV, + QCRYPTO_DER_TAG_ENC_PRIM, + QCRYPTO_DER_TYPE_TAG_BIT_STR); + return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp); +} + +int qcrypto_der_decode_oid(const uint8_t **data, size_t *dlen, + QCryptoDERDecodeCb cb, void *ctx, Error **errp) +{ + uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV, + QCRYPTO_DER_TAG_ENC_PRIM, + QCRYPTO_DER_TYPE_TAG_OID); + return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp); +} + +int qcrypto_der_decode_ctx_tag(const uint8_t **data, size_t *dlen, int tag_id, + QCryptoDERDecodeCb cb, void *ctx, Error **errp) +{ + uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_CONT, + QCRYPTO_DER_TAG_ENC_CONS, + tag_id); + return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp); +} + +void qcrypto_der_encode_int(const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + if (!dst) { + qcrypto_der_encode_data(src, src_len, NULL, dst_len); + *dst_len += 1; + return; } + *dst++ = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV, + QCRYPTO_DER_TAG_ENC_PRIM, + QCRYPTO_DER_TYPE_TAG_INT); + qcrypto_der_encode_data(src, src_len, dst, dst_len); + *dst_len += 1; +} - return qcrypto_der_extract_data(data, dlen, cb, ctx, errp); +void qcrypto_der_encode_seq(const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + if (!dst) { + qcrypto_der_encode_data(src, src_len, NULL, dst_len); + *dst_len += 1; + return; + } + *dst++ = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV, + QCRYPTO_DER_TAG_ENC_CONS, + QCRYPTO_DER_TYPE_TAG_SEQ); + qcrypto_der_encode_data(src, src_len, dst, dst_len); + *dst_len += 1; } diff --git a/crypto/der.h b/crypto/der.h index e3d3aeacdc..ec1436d531 100644 --- a/crypto/der.h +++ b/crypto/der.h @@ -47,14 +47,13 @@ typedef int (*QCryptoDERDecodeCb) (void *opaque, const uint8_t *value, * will be set to the rest length of data, if cb is not NULL, must * return 0 to make decode success, at last, the length of the data * part of the decoded INTEGER will be returned. Otherwise, -1 is - * returned. + * returned and the valued of *data and *dlen keep unchanged. */ int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen, QCryptoDERDecodeCb cb, void *opaque, Error **errp); - /** * qcrypto_der_decode_seq: * @@ -70,7 +69,7 @@ int qcrypto_der_decode_int(const uint8_t **data, * will be set to the rest length of data, if cb is not NULL, must * return 0 to make decode success, at last, the length of the data * part of the decoded SEQUENCE will be returned. Otherwise, -1 is - * returned. + * returned and the valued of *data and *dlen keep unchanged. */ int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen, @@ -78,4 +77,127 @@ int qcrypto_der_decode_seq(const uint8_t **data, void *opaque, Error **errp); +/** + * qcrypto_der_decode_oid: + * + * Decode OID from DER-encoded data, similar with der_decode_int. + * + * @data: pointer to address of input data + * @dlen: pointer to length of input data + * @cb: callback invoked when decode succeed, if cb equals NULL, no + * callback will be invoked + * @opaque: parameter passed to cb + * + * Returns: On success, *data points to rest data, and *dlen + * will be set to the rest length of data, if cb is not NULL, must + * return 0 to make decode success, at last, the length of the data + * part of the decoded OID will be returned. Otherwise, -1 is + * returned and the valued of *data and *dlen keep unchanged. + */ +int qcrypto_der_decode_oid(const uint8_t **data, + size_t *dlen, + QCryptoDERDecodeCb cb, + void *opaque, + Error **errp); + +/** + * qcrypto_der_decode_octet_str: + * + * Decode OCTET STRING from DER-encoded data, similar with der_decode_int. + * + * @data: pointer to address of input data + * @dlen: pointer to length of input data + * @cb: callback invoked when decode succeed, if cb equals NULL, no + * callback will be invoked + * @opaque: parameter passed to cb + * + * Returns: On success, *data points to rest data, and *dlen + * will be set to the rest length of data, if cb is not NULL, must + * return 0 to make decode success, at last, the length of the data + * part of the decoded OCTET STRING will be returned. Otherwise, -1 is + * returned and the valued of *data and *dlen keep unchanged. + */ +int qcrypto_der_decode_octet_str(const uint8_t **data, + size_t *dlen, + QCryptoDERDecodeCb cb, + void *opaque, + Error **errp); + +/** + * qcrypto_der_decode_bit_str: + * + * Decode BIT STRING from DER-encoded data, similar with der_decode_int. + * + * @data: pointer to address of input data + * @dlen: pointer to length of input data + * @cb: callback invoked when decode succeed, if cb equals NULL, no + * callback will be invoked + * @opaque: parameter passed to cb + * + * Returns: On success, *data points to rest data, and *dlen + * will be set to the rest length of data, if cb is not NULL, must + * return 0 to make decode success, at last, the length of the data + * part of the decoded BIT STRING will be returned. Otherwise, -1 is + * returned and the valued of *data and *dlen keep unchanged. + */ +int qcrypto_der_decode_bit_str(const uint8_t **data, + size_t *dlen, + QCryptoDERDecodeCb cb, + void *opaque, + Error **errp); + + +/** + * qcrypto_der_decode_ctx_tag: + * + * Decode context specific tag + * + * @data: pointer to address of input data + * @dlen: pointer to length of input data + * @tag: expected value of context specific tag + * @cb: callback invoked when decode succeed, if cb equals NULL, no + * callback will be invoked + * @opaque: parameter passed to cb + * + * Returns: On success, *data points to rest data, and *dlen + * will be set to the rest length of data, if cb is not NULL, must + * return 0 to make decode success, at last, the length of the data + * part of the decoded BIT STRING will be returned. Otherwise, -1 is + * returned and the valued of *data and *dlen keep unchanged. + */ +int qcrypto_der_decode_ctx_tag(const uint8_t **data, + size_t *dlen, int tag_id, + QCryptoDERDecodeCb cb, + void *opaque, + Error **errp); + +/** + * qcrypto_der_encode_seq: + * @src: source data to be encoded + * @src_len: length of source data + * @dest: distination to save the encoded data, if dest is NULL, dst_len is + * set to expected buffer length and nothing more happends. + * @dst_len: output parameter, indicates how many bytes wat wrote to dest. + * + * Encode data as SEQUENCE in DER rules. + * + */ +void qcrypto_der_encode_seq(const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); + +/** + * qcrypto_der_encode_int: + * @src: source data to be encoded + * @src_len: length of source data + * @dest: distination to save the encoded data, if dest is NULL, dst_len is + * set to expected buffer length and nothing more happends. + * @dst_len: output parameter, indicates how many bytes wat wrote to dest. + * + * Encode data as INTEGER in DER rules, the source data MUST be already + * encoded as two's complement in bigendian. + * + */ +void qcrypto_der_encode_int(const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); + #endif /* QCRYPTO_ASN1_DECODER_H */ diff --git a/tests/unit/test-crypto-der.c b/tests/unit/test-crypto-der.c index aed0f28d68..d218a7f170 100644 --- a/tests/unit/test-crypto-der.c +++ b/tests/unit/test-crypto-der.c @@ -147,13 +147,58 @@ static const uint8_t test_rsa2048_priv_key[] = "\x4e\x2f\x4c\xf9\xab\x97\x38\xe4\x20\x32\x32\x96\xc8\x9e\x79\xd3" "\x12"; +static const uint8_t test_ecdsa_p192_priv_key[] = + "\x30\x53" /* SEQUENCE, offset 0, length 83 */ + "\x02\x01\x01" /* INTEGER, offset 2, length 1 */ + "\x04\x18" /* OCTET STRING, offset 5, length 24 */ + "\xcb\xc8\x86\x0e\x66\x3c\xf7\x5a\x44\x13\xb8\xef\xea\x1d\x7b\xa6" + "\x1c\xda\xf4\x1b\xc7\x67\x6b\x35" + "\xa1\x34" /* CONTEXT SPECIFIC 1, offset 31, length 52 */ + "\x03\x32" /* BIT STRING, offset 33, length 50 */ + "\x00\x04\xc4\x16\xb3\xff\xac\xd5\x87\x98\xf7\xd9\x45\xfe\xd3\x5c" + "\x17\x9d\xb2\x36\x22\xcc\x07\xb3\x6d\x3c\x4e\x04\x5f\xeb\xb6\x52" + "\x58\xfb\x36\x10\x52\xb7\x01\x62\x0e\x94\x51\x1d\xe2\xef\x10\x82" + "\x88\x78"; + +static const uint8_t test_ecdsa_p256_priv_key[] = + "\x30\x77" /* SEQUENCE, offset 0, length 119 */ + "\x02\x01\x01" /* INTEGER, offset 2, length 1 */ + "\x04\x20" /* OCTET STRING, offset 5, length 32 */ + "\xf6\x92\xdd\x29\x1c\x6e\xef\xb6\xb2\x73\x9f\x40\x1b\xb3\x2a\x28" + "\xd2\x37\xd6\x4a\x5b\xe4\x40\x4c\x6a\x95\x99\xfa\xf7\x92\x49\xbe" + "\xa0\x0a" /* CONTEXT SPECIFIC 0, offset 39, length 10 */ + "\x06\x08" /* OID, offset 41, length 8 */ + "\x2a\x86\x48\xce\x3d\x03\x01\x07" + "\xa1\x44" /* CONTEXT SPECIFIC 1, offset 51, length 68 */ + "\x03\x42" /* BIT STRING, offset 53, length 66 */ + "\x00\x04\xed\x42\x9c\x67\x79\xbe\x46\x83\x88\x3e\x8c\xc1\x33\xf3" + "\xc3\xf6\x2c\xf3\x13\x6a\x00\xc2\xc9\x3e\x87\x7f\x86\x39\xe6\xae" + "\xe3\xb9\xba\x2f\x58\x63\x32\x62\x62\x54\x07\x27\xf9\x5a\x3a\xc7" + "\x3a\x6b\x5b\xbc\x0d\x33\xba\xbb\xd4\xa3\xff\x4f\x9e\xdd\xf5\x59" + "\xc0\xf6"; + #define MAX_CHECKER_COUNT 32 +static int qcrypto_wrapped_decode_ctx_tag0(const uint8_t **data, size_t *dlen, + QCryptoDERDecodeCb cb, void *opaque, + Error **errp) +{ + return qcrypto_der_decode_ctx_tag(data, dlen, 0, cb, opaque, errp); +} + +static int qcrypto_wrapped_decode_ctx_tag1(const uint8_t **data, size_t *dlen, + QCryptoDERDecodeCb cb, void *opaque, + Error **errp) +{ + return qcrypto_der_decode_ctx_tag(data, dlen, 1, cb, opaque, errp); +} + typedef struct QCryptoAns1DecoderResultChecker QCryptoAns1DecoderResultChecker; struct QCryptoAns1DecoderResultChecker { int (*action) (const uint8_t **data, size_t *dlen, QCryptoDERDecodeCb cb, void *opaque, Error **errp); QCryptoDERDecodeCb cb; + bool constructed; const uint8_t *exp_value; size_t exp_vlen; }; @@ -204,7 +249,7 @@ static void test_ans1(const void *opaque) g_assert(checker->action(&c->data, &c->dlen, checker_callback, (void *)checker, &error_abort) == checker->exp_vlen); - if (checker->action == qcrypto_der_decode_seq) { + if (checker->constructed) { ++seq_depth; ctx[seq_depth].data = checker->exp_value; ctx[seq_depth].dlen = checker->exp_vlen; @@ -225,25 +270,25 @@ static QCryptoAns1DecoderTestData test_data[] = { .test_data = test_rsa512_priv_key, .test_data_len = sizeof(test_rsa512_priv_key) - 1, .checker = { - { qcrypto_der_decode_seq, checker_callback, + { qcrypto_der_decode_seq, checker_callback, true, test_rsa512_priv_key + 4, 313 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 4 + 2, 1 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 7 + 2, 65 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 74 + 2, 3 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 79 + 2, 64 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 145 + 2, 33 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 180 + 2, 33 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 215 + 2, 32 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 249 + 2, 32 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa512_priv_key + 283 + 2, 32 }, }, }, @@ -252,29 +297,66 @@ static QCryptoAns1DecoderTestData test_data[] = { .test_data = test_rsa2048_priv_key, .test_data_len = sizeof(test_rsa2048_priv_key) - 1, .checker = { - { qcrypto_der_decode_seq, checker_callback, + { qcrypto_der_decode_seq, checker_callback, true, test_rsa2048_priv_key + 4, 1190 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 4 + 2, 1 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 7 + 4, 257 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 268 + 2, 3 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 273 + 4, 257 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 534 + 3, 129 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 666 + 3, 129 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 798 + 3, 129 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 930 + 3, 129 }, - { qcrypto_der_decode_int, checker_callback, + { qcrypto_der_decode_int, checker_callback, false, test_rsa2048_priv_key + 1062 + 3, 129 }, }, }, - +{ + .path = "/crypto/der/parse-ecdsa-p192-priv-key", + .test_data = test_ecdsa_p192_priv_key, + .test_data_len = sizeof(test_ecdsa_p192_priv_key) - 1, + .checker = { + { qcrypto_der_decode_seq, checker_callback, true, + test_ecdsa_p192_priv_key + 2, 83 }, + { qcrypto_der_decode_int, checker_callback, false, + test_ecdsa_p192_priv_key + 2 + 2, 1 }, + { qcrypto_der_decode_octet_str, checker_callback, false, + test_ecdsa_p192_priv_key + 5 + 2, 24 }, + { qcrypto_wrapped_decode_ctx_tag1, checker_callback, true, + test_ecdsa_p192_priv_key + 31 + 2, 52 }, + { qcrypto_der_decode_bit_str , checker_callback, false, + test_ecdsa_p192_priv_key + 33 + 2, 50 }, + }, +}, +{ + .path = "/crypto/der/parse-ecdsa-p256-priv-key", + .test_data = test_ecdsa_p256_priv_key, + .test_data_len = sizeof(test_ecdsa_p256_priv_key) - 1, + .checker = { + { qcrypto_der_decode_seq, checker_callback, true, + test_ecdsa_p256_priv_key + 2, 119 }, + { qcrypto_der_decode_int, checker_callback, false, + test_ecdsa_p256_priv_key + 2 + 2, 1 }, + { qcrypto_der_decode_octet_str, checker_callback, false, + test_ecdsa_p256_priv_key + 5 + 2, 32 }, + { qcrypto_wrapped_decode_ctx_tag0, checker_callback, true, + test_ecdsa_p256_priv_key + 39 + 2, 10 }, + { qcrypto_der_decode_oid, checker_callback, false, + test_ecdsa_p256_priv_key + 41 + 2, 8 }, + { qcrypto_wrapped_decode_ctx_tag1, checker_callback, true, + test_ecdsa_p256_priv_key + 51 + 2, 68 }, + { qcrypto_der_decode_bit_str , checker_callback, false, + test_ecdsa_p256_priv_key + 53 + 2, 66 }, + }, +}, }; int main(int argc, char **argv) From patchwork Wed Jun 22 09:15:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12890382 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EEDEAC43334 for ; Wed, 22 Jun 2022 09:19:04 +0000 (UTC) Received: from localhost ([::1]:48068 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3wVr-00036F-S7 for qemu-devel@archiver.kernel.org; Wed, 22 Jun 2022 05:19:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59278) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3wTP-0000Tv-FU for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:32 -0400 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]:38374) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3wTF-0007Ky-Fv for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:28 -0400 Received: by mail-pj1-x102d.google.com with SMTP id p3-20020a17090a428300b001ec865eb4a2so11072055pjg.3 for ; Wed, 22 Jun 2022 02:16:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BIETDIj5tUXeCXT+wMcB0HSQ2K+sKEnNnkyw8+90Xxo=; b=IQSHaYfxFajzbKWN1OhHdX++7rzU97FtQf3xoUM7ztcs+YX51MhDHWQqlyKOb+CeHc Xhpf2rmf7/ezMrHyyNnLZdVSXzpVC76rh0EL9NX9pUDBWymyX/uWwpBzi8DkXnBeVguz GABMXfT/brYdr+EDzk04uRZBCNjpmC0CRHNWLke2mFAJEnTItPTaQnwE9IDhAEKxbfdP 6MJMWQEnUmXw0MethdyB6vYBlX4TUjZnq6DdjfFNMMOgz+hhgel4ALHP3luJDuSmUpK/ 1gWmXe2hMzu5jWWhWNyCorjL5Mu/dFe7Hq3aSyvtBrwMd4Y6ByZ9TqV7NeiYU/zPfEuW qYMQ== 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=BIETDIj5tUXeCXT+wMcB0HSQ2K+sKEnNnkyw8+90Xxo=; b=jxxXloN/LUMDNR7LCWxT/U7ZdEUF2sEbLRYhJNxehYRXwq19rBnoAzZwDU+hg6ht7A andDRRkIIuqdyG07h6DZsY9w/X7myx9PeDcGsgqC4sUa2dizu8/ycbQQyyDfrMTbKNQd qHrxy4UHyVPwoKKra4ze4c+XosK3BeaRIhNsh77GLDFLdpRZz0EZuhyvBZUgOiPJW4vv 2Usdc6jHHyCe7JCy9exOZccgWguYqsDLbRB7/sgrgIqG3O2Ke/XPzfWv6eBV0vRTB5DS YbQZ1q7h3iEgPTdePDTkSYgNlWH5pQRGdAYjRg3t21CHuwkwFBtnYtkLndFq8nfljOYB RIWw== X-Gm-Message-State: AJIora8ii4apCxQGGUtn9NlhZNON56SSHquZExbMWRZDQVlVEpXEcRMa JHhqC4a+i0DVQUXkZ5yRXKfEoj8fTYGrng== X-Google-Smtp-Source: AGRyM1siZf5XMc0UGvUJlizQx4jZEhxeeFD1hZO7VNQ/S37lZY2kvij8QcA6khrT5jUpEudtjaC9iA== X-Received: by 2002:a17:902:8309:b0:167:9a4c:cd58 with SMTP id bd9-20020a170902830900b001679a4ccd58mr32621418plb.166.1655889379992; Wed, 22 Jun 2022 02:16:19 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id ja13-20020a170902efcd00b0016a087cfad8sm9833900plb.264.2022.06.22.02.16.16 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 02:16:19 -0700 (PDT) From: Lei He To: qemu-devel@nongnu.org, berrange@redhat.com, f4bug@amsat.org Cc: mst@redhat.com, pizhenwei@bytedance.com, jasowang@redhat.com, helei.sig11@bytedance.com Subject: [PATCH v2 3/7] crypto: Remove "qemu/osdep.h" in rsakey.h Date: Wed, 22 Jun 2022 17:15:45 +0800 Message-Id: <20220622091549.31115-4-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20220622091549.31115-1-helei.sig11@bytedance.com> References: <20220622091549.31115-1-helei.sig11@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::102d; envelope-from=helei.sig11@bytedance.com; helo=mail-pj1-x102d.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Move 'include "qemu/osdep.h"' from rsakey.h to rsakey.c. Signed-off-by: lei he Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel P. Berrangé --- crypto/rsakey.c | 1 + crypto/rsakey.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/rsakey.c b/crypto/rsakey.c index cc40e072f0..dcdbd9ec57 100644 --- a/crypto/rsakey.c +++ b/crypto/rsakey.c @@ -19,6 +19,7 @@ * */ +#include "qemu/osdep.h" #include "rsakey.h" void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey *rsa_key) diff --git a/crypto/rsakey.h b/crypto/rsakey.h index 974b76f659..ba88974d12 100644 --- a/crypto/rsakey.h +++ b/crypto/rsakey.h @@ -22,7 +22,6 @@ #ifndef QCRYPTO_RSAKEY_H #define QCRYPTO_RSAKEY_H -#include "qemu/osdep.h" #include "qemu/host-utils.h" #include "crypto/akcipher.h" From patchwork Wed Jun 22 09:15:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12890395 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A20C4C43334 for ; Wed, 22 Jun 2022 09:25:01 +0000 (UTC) Received: from localhost ([::1]:32930 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3wbc-0003jt-JJ for qemu-devel@archiver.kernel.org; Wed, 22 Jun 2022 05:25:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59306) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3wTO-0000U9-SY for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:32 -0400 Received: from mail-pj1-x1032.google.com ([2607:f8b0:4864:20::1032]:50710) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3wTJ-0007L7-A7 for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:29 -0400 Received: by mail-pj1-x1032.google.com with SMTP id go6so10641045pjb.0 for ; Wed, 22 Jun 2022 02:16:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=572I4oYLjRNpVir709Lid2pkWYPCDNW67Es8l2Hx0Wg=; b=Ah35hzCZ+7ddse8GgfyPpJ7UfzAiI/3XIi503Z4zNZRvbYp7SETfPWvKCedOODiMep u0JiabQP8vMthjDdlp4JwBqyrEQD5TGp+0hApQd9AzWYRL7/Z/zxtF9OskODP7EikAt+ wJ0w06e6Yyu5USZPbZL95uwcs757TjyuZmden2De2aLELg/BrbiWTbuGSwKO2V+3SvRu T+F3av9FF2SjaBSowPXTcq3fUlGr4xArw7LWHXUuf+GgUmqfXwdiKLLRwvcCdPWw41S4 rm3vUwQhNTHQpgzWGMB7jPqcNzL0h1BhmGHz7JvjleoM3V4Ichc+Qln+/fL0EzDH974J 7mkA== 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=572I4oYLjRNpVir709Lid2pkWYPCDNW67Es8l2Hx0Wg=; b=PC6V+Eq/SQuEM35zSyQphmtkxQfNeEqc/TqQloRs1AwwaEooLIZT+u3Tv3xPOB++kp 4Wlun2i9AMyA1wpd0tDyTz9jF80LwXfvpvfnVkzxPfOSXA1prH07HwNv27Ug/DcVlW/J 4os3AJk9pgVXfICS9S8vHdSIuIZfBWT6ETO09mKC2RmZ+m4am0Dhy3+nfZw48MEGu5DV 8z4DOrT15bXaNYnFUIaRgERrlHAhkpxKOjLuw0sjuzNCCZDknbn9LD8QJX5Jnwo0E0g9 sZWyWUBXwCHWZShVe/U35ZqdXmwPGRcCuuKEeaYgRSmIsBRuZ2AR/KZKsE9bPEvp1lLk +tWA== X-Gm-Message-State: AJIora/IVBiC6UQkE7xkOcS4sXcDg7WmQgQ9NpRBqQsjiYhKUy3r2twq SP/UxB2IyulDw38OAuZlFF1IkFbPhl16rw== X-Google-Smtp-Source: AGRyM1t7zbD9MY7CPDKbp59XY7yI/urbhsyHoUtw9QajxTaAOdvjAby7kWXDAfRGSJeKT1f9/GHnqg== X-Received: by 2002:a17:902:ec06:b0:16a:1877:425 with SMTP id l6-20020a170902ec0600b0016a18770425mr18337089pld.131.1655889383472; Wed, 22 Jun 2022 02:16:23 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id ja13-20020a170902efcd00b0016a087cfad8sm9833900plb.264.2022.06.22.02.16.20 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 02:16:23 -0700 (PDT) From: Lei He To: qemu-devel@nongnu.org, berrange@redhat.com, f4bug@amsat.org Cc: mst@redhat.com, pizhenwei@bytedance.com, jasowang@redhat.com, helei.sig11@bytedance.com Subject: [PATCH v2 4/7] crypto: Add ECDSA key parser Date: Wed, 22 Jun 2022 17:15:46 +0800 Message-Id: <20220622091549.31115-5-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20220622091549.31115-1-helei.sig11@bytedance.com> References: <20220622091549.31115-1-helei.sig11@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1032; envelope-from=helei.sig11@bytedance.com; helo=mail-pj1-x1032.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add ECDSA key parser and ECDSA signature parser. Signed-off-by: lei he Reviewed-by: Daniel P. Berrangé --- crypto/ecdsakey-builtin.c.inc | 248 ++++++++++++++++++++++++++++++++++++++++++ crypto/ecdsakey.c | 118 ++++++++++++++++++++ crypto/ecdsakey.h | 66 +++++++++++ crypto/meson.build | 1 + 4 files changed, 433 insertions(+) create mode 100644 crypto/ecdsakey-builtin.c.inc create mode 100644 crypto/ecdsakey.c create mode 100644 crypto/ecdsakey.h diff --git a/crypto/ecdsakey-builtin.c.inc b/crypto/ecdsakey-builtin.c.inc new file mode 100644 index 0000000000..054f83feba --- /dev/null +++ b/crypto/ecdsakey-builtin.c.inc @@ -0,0 +1,248 @@ +/* + * QEMU Crypto akcipher algorithms + * + * Copyright (c) 2022 Bytedance + * Author: lei he + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "der.h" +#include "ecdsakey.h" + +#define QCRYPTO_ECDSA_PUBKEY_FMT_UNCOMPRESSED 0x04 + +static int extract_mpi(void *ctx, const uint8_t *value, + size_t vlen, Error **errp) +{ + QCryptoAkCipherMPI *mpi = (QCryptoAkCipherMPI *)ctx; + if (vlen == 0) { + error_setg(errp, "Empty mpi field"); + return -1; + } + mpi->data = g_memdup2(value, vlen); + mpi->len = vlen; + return 0; +} + +static int extract_version(void *ctx, const uint8_t *value, + size_t vlen, Error **errp) +{ + uint8_t *version = (uint8_t *)ctx; + if (vlen != 1 || *value > 1) { + error_setg(errp, "Invalid ecdsa key version"); + return -1; + } + *version = *value; + return 0; +} + +static int extract_cons_content(void *ctx, const uint8_t *value, + size_t vlen, Error **errp) +{ + const uint8_t **content = (const uint8_t **)ctx; + if (vlen == 0) { + error_setg(errp, "Empty sequence"); + return -1; + } + *content = value; + return 0; +} + +static int qcrypto_akcipher_builtin_ecdsa_pubkey_parse2( + QCryptoAkCipherECDSAKey *ecdsa, + const uint8_t *key, size_t keylen, Error **errp); + +static int extract_pubkey(void *ctx, const uint8_t *value, + size_t vlen, Error **errp) +{ + QCryptoAkCipherECDSAKey *ecdsa = (QCryptoAkCipherECDSAKey *)ctx; + if (vlen < 4) { + error_setg(errp, "Public key part too short"); + return -1; + } + /* Skip meta byte of BIT STRING */ + if (*value != 0) { + error_setg(errp, "Invalid public key"); + return -1; + } + value++; + vlen--; + return qcrypto_akcipher_builtin_ecdsa_pubkey_parse2( + ecdsa, value, vlen, errp); +} + +/** + * ECDSASignature ::= SEQUENCE { + * r INTEGER + * s INTEGER + * } + */ +QCryptoAkCipherECDSASig *qcrypto_akcipher_ecdsasig_parse( + const uint8_t *signature, size_t len, Error **errp) +{ + g_autoptr(QCryptoAkCipherECDSASig) sig = g_new0(QCryptoAkCipherECDSASig, 1); + const uint8_t *seq; + size_t seq_length; + int decode_ret; + + decode_ret = qcrypto_der_decode_seq(&signature, &len, + extract_cons_content, &seq, errp); + + if (decode_ret < 0) { + return NULL; + } + if (len != 0) { + error_setg(errp, "Invalid ECDSA signature"); + return NULL; + } + seq_length = decode_ret; + + if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, + &sig->r, errp) < 0 || + qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, + &sig->s, errp) < 0) { + return NULL; + } + if (seq_length != 0) { + error_setg(errp, "Invalid ECDSA signature"); + return NULL; + } + + return g_steal_pointer(&sig); +} + +/** + * ECDSAPublicKey: compress-format || x coordinate || y coordinate + */ +static int qcrypto_akcipher_builtin_ecdsa_pubkey_parse2( + QCryptoAkCipherECDSAKey *ecdsa, + const uint8_t *key, size_t keylen, Error **errp) +{ + if (keylen < 3) { + error_setg(errp, "keylen is too short: %zu", keylen); + return -1; + } + if (key[0] != QCRYPTO_ECDSA_PUBKEY_FMT_UNCOMPRESSED) { + error_setg(errp, "Only uncompressed ECDSA public key is supported"); + return -1; + } + + /* Skip format byte */ + key++; + keylen--; + if (keylen % 2 != 0) { + error_setg(errp, "ECDSA public key's length must be odd"); + return -1; + } + + ecdsa->pub_x.data = g_memdup2(key, keylen / 2); + ecdsa->pub_x.len = keylen / 2; + ecdsa->pub_y.data = g_memdup2(key + keylen / 2, keylen / 2); + ecdsa->pub_y.len = keylen / 2; + + return 0; +} + +static QCryptoAkCipherECDSAKey *qcrypto_akcipher_builtin_ecdsa_pubkey_parse( + const uint8_t *key, size_t keylen, Error **errp) +{ + g_autoptr(QCryptoAkCipherECDSAKey) ecdsa = + g_new0(QCryptoAkCipherECDSAKey, 1); + if (qcrypto_akcipher_builtin_ecdsa_pubkey_parse2( + ecdsa, key, keylen, errp) != 0) { + return NULL; + } + return g_steal_pointer(&ecdsa); +} + +/** + * ECDSAPrivateKey ::= SEQUENCE { + * version INTEGER + * k OCTET STRING + * parameters [0] OID OPTIONAL + * publickey [1] BIT STRING OPTIONAL + * } + */ +static QCryptoAkCipherECDSAKey *qcrypto_akcipher_builtin_ecdsa_privkey_parse( + const uint8_t *key, size_t keylen, Error **errp) +{ + g_autoptr(QCryptoAkCipherECDSAKey) ecdsa = + g_new0(QCryptoAkCipherECDSAKey, 1); + uint8_t version; + const uint8_t *seq, *pubkey; + int decode_ret; + size_t seq_length, pubkey_length; + + decode_ret = qcrypto_der_decode_seq(&key, &keylen, extract_cons_content, + &seq, errp); + if (decode_ret < 0) { + return NULL; + } + if (keylen != 0) { + error_setg(errp, "Invalid ECDSA private key"); + return NULL; + } + seq_length = decode_ret; + + if (qcrypto_der_decode_int(&seq, &seq_length, extract_version, + &version, errp) < 0 || + qcrypto_der_decode_octet_str(&seq, &seq_length, extract_mpi, + &ecdsa->priv, errp) < 0) { + return NULL; + } + + /* Here we just ignore curve id */ + qcrypto_der_decode_ctx_tag(&seq, &seq_length, 0, NULL, NULL, NULL); + + decode_ret = qcrypto_der_decode_ctx_tag(&seq, &seq_length, 1, + extract_cons_content, + &pubkey, NULL); + if (decode_ret > 0) { + pubkey_length = decode_ret; + if (qcrypto_der_decode_bit_str(&pubkey, &pubkey_length, + extract_pubkey, ecdsa, errp) < 0) { + return NULL; + } + if (pubkey_length != 0) { + error_setg(errp, "Invalid ECDSA private key"); + return NULL; + } + } + + if (seq_length != 0) { + error_setg(errp, "Invalid ECDSA private key"); + return NULL; + } + + return g_steal_pointer(&ecdsa); +} + +QCryptoAkCipherECDSAKey *qcrypto_akcipher_ecdsakey_parse( + QCryptoAkCipherKeyType type, + const uint8_t *key, size_t keylen, Error **errp) +{ + switch (type) { + case QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE: + return qcrypto_akcipher_builtin_ecdsa_privkey_parse(key, keylen, errp); + + case QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC: + return qcrypto_akcipher_builtin_ecdsa_pubkey_parse(key, keylen, errp); + + default: + error_setg(errp, "Unknown key type: %d", type); + return NULL; + } +} diff --git a/crypto/ecdsakey.c b/crypto/ecdsakey.c new file mode 100644 index 0000000000..466dcffbc7 --- /dev/null +++ b/crypto/ecdsakey.c @@ -0,0 +1,118 @@ +/* + * QEMU Crypto ECDSA key parser + * + * Copyright (c) 2022 Bytedance + * Author: lei he + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "qemu/osdep.h" +#include "ecdsakey.h" +#include "der.h" + +void qcrypto_akcipher_ecdsasig_free(QCryptoAkCipherECDSASig *sig) +{ + if (!sig) { + return; + } + g_free(sig->r.data); + g_free(sig->s.data); + g_free(sig); +} + +void qcrypto_akcipher_ecdsasig_x9_62_encode(QCryptoAkCipherECDSASig *sig, + uint8_t *dst, size_t *dst_len) +{ + size_t r_len, s_len; + uint8_t *r_dst, *s_dst; + g_autofree uint8_t *buff = NULL; + + qcrypto_der_encode_int(NULL, sig->r.len, NULL, &r_len); + qcrypto_der_encode_int(NULL, sig->s.len, NULL, &s_len); + + buff = g_new0(uint8_t, r_len + s_len); + r_dst = buff; + qcrypto_der_encode_int(sig->r.data, sig->r.len, r_dst, &r_len); + s_dst = buff + r_len; + qcrypto_der_encode_int(sig->s.data, sig->s.len, s_dst, &s_len); + + qcrypto_der_encode_seq(buff, r_len + s_len, dst, dst_len); +} + +QCryptoAkCipherECDSASig *qcrypto_akcipher_ecdsasig_alloc( + QCryptoCurveID curve_id, Error **errp) +{ + int keylen; + QCryptoAkCipherECDSASig *sig; + + switch (curve_id) { + case QCRYPTO_CURVE_ID_NIST_P192: + keylen = 192 / 8; + break; + + case QCRYPTO_CURVE_ID_NIST_P256: + keylen = 256 / 8; + break; + + case QCRYPTO_CURVE_ID_NIST_P384: + keylen = 384 / 8; + break; + + default: + error_setg(errp, "Unknown curve id: %d", curve_id); + return NULL; + } + + /* + * Note: when encoding positive bignum in tow'complement, we have to add + * a leading zero if the most significant byte is greater than or + * equal to 0x80. + */ + sig = g_new0(QCryptoAkCipherECDSASig, 1); + sig->r.data = g_new0(uint8_t, keylen + 1); + sig->r.len = keylen + 1; + sig->s.data = g_new0(uint8_t, keylen + 1); + sig->s.len = keylen + 1; + return sig; +} + +size_t qcrypto_akcipher_ecdsasig_x9_62_size(size_t keylen) +{ + size_t integer_len; + size_t seq_len; + + /* + * Note: when encoding positive bignum in tow'complement, we have to add + * a leading zero if the most significant byte is greater than or + * equal to 0x80. + */ + qcrypto_der_encode_int(NULL, keylen + 1, NULL, &integer_len); + qcrypto_der_encode_seq(NULL, integer_len * 2, NULL, &seq_len); + return seq_len; +} + +void qcrypto_akcipher_ecdsakey_free(QCryptoAkCipherECDSAKey *ecdsa) +{ + if (!ecdsa) { + return; + } + g_free(ecdsa->priv.data); + g_free(ecdsa->pub_x.data); + g_free(ecdsa->pub_y.data); + g_free(ecdsa); +} + +#include "ecdsakey-builtin.c.inc" diff --git a/crypto/ecdsakey.h b/crypto/ecdsakey.h new file mode 100644 index 0000000000..a0532a0e75 --- /dev/null +++ b/crypto/ecdsakey.h @@ -0,0 +1,66 @@ +/* + * QEMU Crypto ECDSA signature parser + * + * Copyright (c) 2022 Bytedance + * Author: lei he + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#ifndef QCRYPTO_ECDSASIG_H +#define QCRYPTO_ECDSASIG_H + +#include "qemu/host-utils.h" +#include "crypto/akcipher.h" +#include "crypto/rsakey.h" + +typedef struct QCryptoAkCipherECDSAKey QCryptoAkCipherECDSAKey; +typedef struct QCryptoAkCipherECDSASig QCryptoAkCipherECDSASig; + +struct QCryptoAkCipherECDSASig { + QCryptoAkCipherMPI r; + QCryptoAkCipherMPI s; +}; + +struct QCryptoAkCipherECDSAKey { + QCryptoAkCipherMPI priv; + QCryptoAkCipherMPI pub_x; + QCryptoAkCipherMPI pub_y; +}; + +QCryptoAkCipherECDSASig *qcrypto_akcipher_ecdsasig_parse( + const uint8_t *sig, size_t len, Error **errp); + +QCryptoAkCipherECDSASig *qcrypto_akcipher_ecdsasig_alloc( + QCryptoCurveID curve_id, Error **errp); + +void qcrypto_akcipher_ecdsasig_free(QCryptoAkCipherECDSASig *sig); + +void qcrypto_akcipher_ecdsasig_x9_62_encode( + QCryptoAkCipherECDSASig *sig, uint8_t *dst, size_t *dst_len); + +size_t qcrypto_akcipher_ecdsasig_x9_62_size(size_t keylen); + +QCryptoAkCipherECDSAKey *qcrypto_akcipher_ecdsakey_parse( + QCryptoAkCipherKeyType type, + const uint8_t *key, size_t keylen, Error **errp); + +void qcrypto_akcipher_ecdsakey_free(QCryptoAkCipherECDSAKey *key); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoAkCipherECDSASig, + qcrypto_akcipher_ecdsasig_free); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoAkCipherECDSAKey, + qcrypto_akcipher_ecdsakey_free); +#endif diff --git a/crypto/meson.build b/crypto/meson.build index 5f03a30d34..36e2e08938 100644 --- a/crypto/meson.build +++ b/crypto/meson.build @@ -7,6 +7,7 @@ crypto_ss.add(files( 'block.c', 'cipher.c', 'der.c', + 'ecdsakey.c', 'hash.c', 'hmac.c', 'ivgen-essiv.c', From patchwork Wed Jun 22 09:15:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12890396 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7B552C43334 for ; Wed, 22 Jun 2022 09:27:03 +0000 (UTC) Received: from localhost ([::1]:36824 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3wda-0006VJ-BN for qemu-devel@archiver.kernel.org; Wed, 22 Jun 2022 05:27:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59318) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3wTP-0000UX-TD for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:32 -0400 Received: from mail-pg1-x52a.google.com ([2607:f8b0:4864:20::52a]:46962) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3wTN-0007LT-SD for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:31 -0400 Received: by mail-pg1-x52a.google.com with SMTP id l4so15543975pgh.13 for ; Wed, 22 Jun 2022 02:16:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=yPEIrnTqoADk7L45FDJ9i8TVUiQJQyhzRflA5RokFo0=; b=RsHa6TSJbEx0QCDEeRKjjihNmlTgih0/EToVKtts0Upkiy03r8zT54+SDOK4arQGqB itVywLk7coPvdSRi/cnAzgm8PDkT69N8eHwvK7aoJwB9MYFmu3wUXqJQyPg6dYoxIsM9 VQWU96CIUxxL8AV8QOkQNuy00EhGrRbtcbdvAJCh28Y0dTmq4HaYpFDEnjP7Ydv73+O3 bHqOQnQVgPOoNb+hutD7hmvB7iB/PCelhYXZZAUnP6Q253GRn44kPxl1XqF2eSIWAZqs U1J9N6tlYn5X9lXhcaiX9bM9VNmy05p0mILQLRNY/CKnqOneg+XJhsHKv6/lqPSqw2r4 Si/g== 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=yPEIrnTqoADk7L45FDJ9i8TVUiQJQyhzRflA5RokFo0=; b=wyRVkz0Bt5Ryw0RNulzJyQsg0H12oO1TBOJ8bDeZVSnDDqGm92/uF/ktDpIzbUa2uY oQNcLAUwL4Uglsv2ySibG6sAfHSP/EfGsoYLjuPG+LNKL4SJlK+O/W+PKJcJK/DAgkeQ y3/XqpikvFHA+IKG7A6YMWKdVoXyonQwtxrmiOcP78Mq5We+xQjwCe4VOkHWtT76LloK +LvwuekIqSoNHPR4tnRH6iXT5CuKO9GemXWAjuDsjfitTURoUBdtEYXCJYLcyYeFxgZR 0jQc6qp5fS3Q9Sbb5I2siRM6Er4Wj8yzLETmrR1RZRQ/8xkpuEulIQmG1V14muOxtOK6 27Sg== X-Gm-Message-State: AJIora/7qzxKe+omNLUuJCrMz7FsgxESOqY14+0J3mWYBTOzyPeoPRbP zX4c4y3HwZTxifsFumkQ4yiKmGJ5Anu4Xw== X-Google-Smtp-Source: AGRyM1t9t/yfEBZXxUV8iLAOEpABrFZkdQhrjQUwXuQRi0cmwrc7XLoortNiCpcFE971A0JOsNT2Sg== X-Received: by 2002:a05:6a00:1350:b0:51c:26d2:9ce5 with SMTP id k16-20020a056a00135000b0051c26d29ce5mr34611004pfu.69.1655889387373; Wed, 22 Jun 2022 02:16:27 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id ja13-20020a170902efcd00b0016a087cfad8sm9833900plb.264.2022.06.22.02.16.23 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 02:16:26 -0700 (PDT) From: Lei He To: qemu-devel@nongnu.org, berrange@redhat.com, f4bug@amsat.org Cc: mst@redhat.com, pizhenwei@bytedance.com, jasowang@redhat.com, helei.sig11@bytedance.com Subject: [PATCH v2 5/7] crypto: Implement ECDSA algorithm by hogweed Date: Wed, 22 Jun 2022 17:15:47 +0800 Message-Id: <20220622091549.31115-6-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20220622091549.31115-1-helei.sig11@bytedance.com> References: <20220622091549.31115-1-helei.sig11@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::52a; envelope-from=helei.sig11@bytedance.com; helo=mail-pg1-x52a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Implement ECDSA algorithm by hogweed and nettle. Signed-off-by: lei he Reviewed-by: Daniel P. Berrangé --- crypto/akcipher-nettle.c.inc | 282 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) diff --git a/crypto/akcipher-nettle.c.inc b/crypto/akcipher-nettle.c.inc index 02699e6e6d..b6ba53c5d5 100644 --- a/crypto/akcipher-nettle.c.inc +++ b/crypto/akcipher-nettle.c.inc @@ -20,6 +20,8 @@ */ #include +#include +#include #include "qemu/osdep.h" #include "qemu/host-utils.h" @@ -28,6 +30,7 @@ #include "qapi/error.h" #include "sysemu/cryptodev.h" #include "rsakey.h" +#include "ecdsakey.h" typedef struct QCryptoNettleRSA { QCryptoAkCipher akcipher; @@ -37,6 +40,32 @@ typedef struct QCryptoNettleRSA { QCryptoHashAlgorithm hash_alg; } QCryptoNettleRSA; +typedef struct QCryptoNettleECDSA { + QCryptoAkCipher akcipher; + QCryptoCurveID curve_id; + const struct ecc_curve *curve; + struct ecc_point pubkey; + struct ecc_scalar privkey; +} QCryptoNettleECDSA; + +static int qcrypto_nettle_invalid_encrypt(QCryptoAkCipher *akcipher, + const void *data, size_t data_len, + void *enc, size_t enc_len, + Error **errp) +{ + error_setg(errp, "Invalid operation"); + return -1; +} + +static int qcrypto_nettle_invalid_decrypt(QCryptoAkCipher *akcipher, + const void *enc, size_t enc_len, + void *data, size_t data_len, + Error **errp) +{ + error_setg(errp, "Invalid operation"); + return -1; +} + static void qcrypto_nettle_rsa_free(QCryptoAkCipher *akcipher) { QCryptoNettleRSA *rsa = (QCryptoNettleRSA *)akcipher; @@ -55,6 +84,12 @@ static QCryptoAkCipher *qcrypto_nettle_rsa_new( const uint8_t *key, size_t keylen, Error **errp); +static QCryptoAkCipher *qcrypto_nettle_ecdsa_new( + const QCryptoAkCipherOptionsECDSA *opts, + QCryptoAkCipherKeyType type, + const uint8_t *key, size_t keylen, + Error **errp); + QCryptoAkCipher *qcrypto_akcipher_new(const QCryptoAkCipherOptions *opts, QCryptoAkCipherKeyType type, const uint8_t *key, size_t keylen, @@ -64,6 +99,10 @@ QCryptoAkCipher *qcrypto_akcipher_new(const QCryptoAkCipherOptions *opts, case QCRYPTO_AKCIPHER_ALG_RSA: return qcrypto_nettle_rsa_new(&opts->u.rsa, type, key, keylen, errp); + case QCRYPTO_AKCIPHER_ALG_ECDSA: + return qcrypto_nettle_ecdsa_new(&opts->u.ecdsa, type, + key, keylen, errp); + default: error_setg(errp, "Unsupported algorithm: %u", opts->alg); return NULL; @@ -421,6 +460,238 @@ error: return NULL; } +static int qcrypto_nettle_parse_curve_id( + QCryptoNettleECDSA *ecdsa, + const QCryptoAkCipherOptionsECDSA *opts, Error **errp) +{ + /* ECDSA algorithm can't used for encryption */ + ecdsa->akcipher.max_plaintext_len = 0; + ecdsa->akcipher.max_ciphertext_len = 0; + + switch (opts->curve_id) { + case QCRYPTO_CURVE_ID_NIST_P192: + ecdsa->akcipher.max_signature_len = + qcrypto_akcipher_ecdsasig_x9_62_size(192 / 8); + ecdsa->akcipher.max_dgst_len = 192 / 8; + ecdsa->curve = nettle_get_secp_192r1(); + break; + + case QCRYPTO_CURVE_ID_NIST_P256: + ecdsa->akcipher.max_signature_len = + qcrypto_akcipher_ecdsasig_x9_62_size(256 / 8); + ecdsa->akcipher.max_dgst_len = 256 / 8; + ecdsa->curve = nettle_get_secp_256r1(); + break; + + case QCRYPTO_CURVE_ID_NIST_P384: + ecdsa->akcipher.max_signature_len = + qcrypto_akcipher_ecdsasig_x9_62_size(384 / 8); + ecdsa->akcipher.max_dgst_len = 256 / 8; + ecdsa->curve = nettle_get_secp_384r1(); + break; + + default: + error_setg(errp, "Unknown curve id: %d", opts->curve_id); + return -1; + } + + return 0; +} + +static void qcrypto_nettle_ecdsa_free(QCryptoAkCipher *akcipher) +{ + QCryptoNettleECDSA *ecdsa = (QCryptoNettleECDSA *)akcipher; + if (!ecdsa) { + return; + } + ecc_point_clear(&ecdsa->pubkey); + ecc_scalar_clear(&ecdsa->privkey); + g_free(ecdsa); +} + +static int qcrypt_nettle_parse_ecdsa_private_key( + QCryptoNettleECDSA *ecdsa, + const uint8_t *key, + size_t keylen, + Error **errp) +{ + g_autoptr(QCryptoAkCipherECDSAKey) ecdsa_key = + qcrypto_akcipher_ecdsakey_parse(QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE, + key, keylen, errp); + mpz_t scalar, x, y; + int ret = -1; + + if (!ecdsa_key) { + return ret; + } + + mpz_init(x); + mpz_init(y); + nettle_mpz_init_set_str_256_u( + scalar, ecdsa_key->priv.len, ecdsa_key->priv.data); + if (ecc_scalar_set(&ecdsa->privkey, scalar) != 1) { + goto cleanup; + } + + if (ecdsa_key->pub_x.len && ecdsa_key->pub_y.len) { + nettle_mpz_set_str_256_u(x, + ecdsa_key->pub_x.len, ecdsa_key->pub_x.data); + nettle_mpz_set_str_256_u(y, + ecdsa_key->pub_y.len, ecdsa_key->pub_y.data); + if (ecc_point_set(&ecdsa->pubkey, x, y) != 1) { + goto cleanup; + } + } + ret = 0; + +cleanup: + mpz_clear(scalar); + mpz_clear(x); + mpz_clear(y); + return ret; +} + +static int qcrypt_nettle_parse_ecdsa_public_key( + QCryptoNettleECDSA *ecdsa, + const uint8_t *key, + size_t keylen, + Error **errp) +{ + g_autoptr(QCryptoAkCipherECDSAKey) ecdsa_key = + qcrypto_akcipher_ecdsakey_parse(QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC, + key, keylen, errp); + mpz_t x, y; + int ret = -1; + + if (!ecdsa_key) { + return ret; + } + nettle_mpz_init_set_str_256_u( + x, ecdsa_key->pub_x.len, ecdsa_key->pub_x.data); + nettle_mpz_init_set_str_256_u( + y, ecdsa_key->pub_y.len, ecdsa_key->pub_y.data); + if (ecc_point_set(&ecdsa->pubkey, x, y) != 1) { + goto cleanup; + } + ret = 0; + +cleanup: + mpz_clear(x); + mpz_clear(y); + return ret; +} + +static int qcrypto_nettle_ecdsa_sign(QCryptoAkCipher *akcipher, + const void *data, size_t data_len, + void *sig, size_t sig_len, Error **errp) +{ + QCryptoNettleECDSA *ecdsa = (QCryptoNettleECDSA *)akcipher; + int ret = -1; + size_t actual_len; + struct dsa_signature nettle_sig; + g_autoptr(QCryptoAkCipherECDSASig) qcrypto_sig = NULL; + + if (sig_len < akcipher->max_signature_len) { + error_setg(errp, "Signature buffer should be not less than: %d", + akcipher->max_signature_len); + return ret; + } + dsa_signature_init(&nettle_sig); + qcrypto_sig = qcrypto_akcipher_ecdsasig_alloc(ecdsa->curve_id, errp); + ecdsa_sign(&ecdsa->privkey, NULL, wrap_nettle_random_func, + data_len, data, &nettle_sig); + qcrypto_sig->r.len = nettle_mpz_sizeinbase_256_s(nettle_sig.r); + qcrypto_sig->s.len = nettle_mpz_sizeinbase_256_s(nettle_sig.s); + nettle_mpz_get_str_256( + qcrypto_sig->r.len, qcrypto_sig->r.data, nettle_sig.r); + nettle_mpz_get_str_256( + qcrypto_sig->s.len, qcrypto_sig->s.data, nettle_sig.s); + qcrypto_akcipher_ecdsasig_x9_62_encode(qcrypto_sig, sig, &actual_len); + ret = actual_len; + + dsa_signature_clear(&nettle_sig); + return ret; +} + +static int qcrypto_nettle_ecdsa_verify(QCryptoAkCipher *akcipher, + const void *sig, size_t sig_len, + const void *data, size_t data_len, + Error **errp) +{ + QCryptoNettleECDSA *ecdsa = (QCryptoNettleECDSA *)akcipher; + int ret = -1; + struct dsa_signature nettle_sig; + g_autoptr(QCryptoAkCipherECDSASig) qcrypto_sig = NULL; + + qcrypto_sig = qcrypto_akcipher_ecdsasig_parse(sig, sig_len, errp); + if (!qcrypto_sig) { + return ret; + } + dsa_signature_init(&nettle_sig); + nettle_mpz_init_set_str_256_u( + nettle_sig.r, qcrypto_sig->r.len, qcrypto_sig->r.data); + nettle_mpz_init_set_str_256_u( + nettle_sig.s, qcrypto_sig->s.len, qcrypto_sig->s.data); + if (ecdsa_verify(&ecdsa->pubkey, data_len, data, &nettle_sig) == 1) { + ret = 0; + } else { + error_setg(errp, "Failed to verify signature"); + } + + dsa_signature_clear(&nettle_sig); + return ret; +} + +static QCryptoAkCipherDriver nettle_ecdsa = { + .encrypt = qcrypto_nettle_invalid_encrypt, + .decrypt = qcrypto_nettle_invalid_decrypt, + .sign = qcrypto_nettle_ecdsa_sign, + .verify = qcrypto_nettle_ecdsa_verify, + .free = qcrypto_nettle_ecdsa_free, +}; + +static QCryptoAkCipher *qcrypto_nettle_ecdsa_new( + const QCryptoAkCipherOptionsECDSA *opts, + QCryptoAkCipherKeyType type, + const uint8_t *key, size_t keylen, + Error **errp) +{ + QCryptoNettleECDSA *ecdsa = g_new0(QCryptoNettleECDSA, 1); + if (qcrypto_nettle_parse_curve_id(ecdsa, opts, errp) != 0) { + goto error; + } + + ecdsa->akcipher.driver = &nettle_ecdsa; + ecdsa->curve_id = opts->curve_id; + ecc_scalar_init(&ecdsa->privkey, ecdsa->curve); + ecc_point_init(&ecdsa->pubkey, ecdsa->curve); + + switch (type) { + case QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE: + if (qcrypt_nettle_parse_ecdsa_private_key( + ecdsa, key, keylen, errp) != 0) { + goto error; + } + break; + + case QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC: + if (qcrypt_nettle_parse_ecdsa_public_key( + ecdsa, key, keylen, errp) != 0) { + goto error; + } + break; + + default: + error_setg(errp, "Unknown akcipher key type %d", type); + goto error; + } + + return (QCryptoAkCipher *)ecdsa; + +error: + qcrypto_nettle_ecdsa_free((QCryptoAkCipher *)ecdsa); + return NULL; +} bool qcrypto_akcipher_supports(QCryptoAkCipherOptions *opts) { @@ -445,6 +716,17 @@ bool qcrypto_akcipher_supports(QCryptoAkCipherOptions *opts) } break; + case QCRYPTO_AKCIPHER_ALG_ECDSA: + switch (opts->u.ecdsa.curve_id) { + case QCRYPTO_CURVE_ID_NIST_P192: + case QCRYPTO_CURVE_ID_NIST_P256: + case QCRYPTO_CURVE_ID_NIST_P384: + return true; + + default: + return false; + } + default: return false; } From patchwork Wed Jun 22 09:15:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12890386 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AB386C433EF for ; Wed, 22 Jun 2022 09:22:48 +0000 (UTC) Received: from localhost ([::1]:55944 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3wZS-0008Us-NJ for qemu-devel@archiver.kernel.org; Wed, 22 Jun 2022 05:22:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59334) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3wTS-0000VN-Ti for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:36 -0400 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]:38374) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3wTP-0007Ky-VZ for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:34 -0400 Received: by mail-pj1-x102d.google.com with SMTP id p3-20020a17090a428300b001ec865eb4a2so11072055pjg.3 for ; Wed, 22 Jun 2022 02:16:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Vo3XO71+0j9yCCAaMuStwHp9brRX3FsHuLnnD5WivWg=; b=ksBpFambKD1aeY4PrkR4Y3zLNmMDYIvBIYhKY03sktbB1FZnxi8yKl9lCjqfaHSDoR OgkIGAyzemde+KysUNeyVAE6mCXWeQFuGqI86mQRBsPuKf62TD2seGdvLBU+wV1Y8ijp eXm3OfUu/JaY6DtByCEYzO7pI7HUOa+rfd7U3+oF9lv+oAzVdSqDv7KHYqgCU7xFteKM l8jrENSksCgxUzwUebzZpIM2vd5lGLqh6g/cBYwM/vtFpjF+3OkTLhL16KOPwKuQO8jn CVQ+isj+hoQPQsM6kyCHzH4ukr+lU8yCcp8SeRYI/Wrg8yRr9J6OIHHEde/HZJjkDTkd Vlbg== 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=Vo3XO71+0j9yCCAaMuStwHp9brRX3FsHuLnnD5WivWg=; b=6iZYkG5TqYvLIu2CUlb+9GV+Kv2om5g0WxAUAvvqUzaAFDSousj7RuIBICTwZ7OAMb ry1GdMsaXD8fKQjZalP7J5brWLfyzt9xU2uIPWslQVGwORFWfeedOIwYepbgJRAraXv+ Qahqe2yKWC2/8xPdUP5gKZ3mGVpo+Z3nohUr0L4DLRRxZfdatPlStFn0fnRA5wyQy8h7 GRm1KxRlBIgsrbE0Cs26999qfhsFE4UkvLrY2uDM1FsEQX2dihpQi1ar8slwHHVUVnIz vnXS2xTFMkojauXgSpKauWoYaWEjw/B0S8d9nSKBMT9j5D5fDxdX7M5F9zN6c2sf71jR XlPw== X-Gm-Message-State: AJIora80ClMr/rT20f3IZk1sOpy+RkCiSlo7NV3gn3FlMNxiXW4/xuga unM4x1XbZdn97S6tXCB3YdynBtJ9MLxHOg== X-Google-Smtp-Source: AGRyM1szohMmcS5bPPyLV0QSyLRU++45Q3GiFngSke2prAJ+ApAIS7T1/rretr/fvzmHj4JpiDaJnA== X-Received: by 2002:a17:902:e5cb:b0:165:1500:a69b with SMTP id u11-20020a170902e5cb00b001651500a69bmr32923256plf.29.1655889390842; Wed, 22 Jun 2022 02:16:30 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id ja13-20020a170902efcd00b0016a087cfad8sm9833900plb.264.2022.06.22.02.16.27 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 02:16:30 -0700 (PDT) From: Lei He To: qemu-devel@nongnu.org, berrange@redhat.com, f4bug@amsat.org Cc: mst@redhat.com, pizhenwei@bytedance.com, jasowang@redhat.com, helei.sig11@bytedance.com Subject: [PATCH v2 6/7] crypto: Implement ECDSA algorithm by gcrypt Date: Wed, 22 Jun 2022 17:15:48 +0800 Message-Id: <20220622091549.31115-7-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20220622091549.31115-1-helei.sig11@bytedance.com> References: <20220622091549.31115-1-helei.sig11@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::102d; envelope-from=helei.sig11@bytedance.com; helo=mail-pj1-x102d.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Implement ECDSA algorithm by gcrypt Signed-off-by: lei he Reviewed-by: Daniel P. Berrangé --- crypto/akcipher-gcrypt.c.inc | 409 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) diff --git a/crypto/akcipher-gcrypt.c.inc b/crypto/akcipher-gcrypt.c.inc index abb1fb272e..28dad71deb 100644 --- a/crypto/akcipher-gcrypt.c.inc +++ b/crypto/akcipher-gcrypt.c.inc @@ -28,6 +28,7 @@ #include "qapi/error.h" #include "sysemu/cryptodev.h" #include "rsakey.h" +#include "ecdsakey.h" typedef struct QCryptoGcryptRSA { QCryptoAkCipher akcipher; @@ -36,6 +37,13 @@ typedef struct QCryptoGcryptRSA { QCryptoHashAlgorithm hash_alg; } QCryptoGcryptRSA; +typedef struct QCryptoGcryptECDSA { + QCryptoAkCipher akcipher; + gcry_sexp_t key; + QCryptoCurveID curve_id; + const char *curve_name; +} QCryptoGcryptECDSA; + static void qcrypto_gcrypt_rsa_free(QCryptoAkCipher *akcipher) { QCryptoGcryptRSA *rsa = (QCryptoGcryptRSA *)akcipher; @@ -53,6 +61,12 @@ static QCryptoGcryptRSA *qcrypto_gcrypt_rsa_new( const uint8_t *key, size_t keylen, Error **errp); +static QCryptoGcryptECDSA *qcrypto_gcrypt_ecdsa_new( + const QCryptoAkCipherOptionsECDSA *opts, + QCryptoAkCipherKeyType type, + const uint8_t *key, size_t keylen, + Error **errp); + QCryptoAkCipher *qcrypto_akcipher_new(const QCryptoAkCipherOptions *opts, QCryptoAkCipherKeyType type, const uint8_t *key, size_t keylen, @@ -63,6 +77,10 @@ QCryptoAkCipher *qcrypto_akcipher_new(const QCryptoAkCipherOptions *opts, return (QCryptoAkCipher *)qcrypto_gcrypt_rsa_new( &opts->u.rsa, type, key, keylen, errp); + case QCRYPTO_AKCIPHER_ALG_ECDSA: + return (QCryptoAkCipher *)qcrypto_gcrypt_ecdsa_new( + &opts->u.ecdsa, type, key, keylen, errp); + default: error_setg(errp, "Unsupported algorithm: %u", opts->alg); return NULL; @@ -470,6 +488,7 @@ static int qcrypto_gcrypt_rsa_verify(QCryptoAkCipher *akcipher, gcry_sexp_t sig_sexp = NULL, dgst_sexp = NULL; gcry_error_t err; + if (in_len > akcipher->max_signature_len) { error_setg(errp, "Signature length is greater than key size: %d", akcipher->max_signature_len); @@ -564,6 +583,385 @@ error: return NULL; } +static int qcrypto_gcrypt_parse_curve_id(QCryptoGcryptECDSA *ecdsa, + const QCryptoAkCipherOptionsECDSA *opts, Error **errp) +{ + /* ECDSA algorithm can't used for encryption */ + ecdsa->akcipher.max_plaintext_len = 0; + ecdsa->akcipher.max_ciphertext_len = 0; + + switch (opts->curve_id) { + case QCRYPTO_CURVE_ID_NIST_P192: + ecdsa->curve_name = "nistp192"; + ecdsa->akcipher.max_signature_len = + qcrypto_akcipher_ecdsasig_x9_62_size(192 / 8); + ecdsa->akcipher.max_dgst_len = 192 / 8; + break; + + case QCRYPTO_CURVE_ID_NIST_P256: + ecdsa->curve_name = "nistp256"; + ecdsa->akcipher.max_signature_len = + qcrypto_akcipher_ecdsasig_x9_62_size(256 / 8); + ecdsa->akcipher.max_dgst_len = 256 / 8; + break; + + case QCRYPTO_CURVE_ID_NIST_P384: + ecdsa->curve_name = "nistp384"; + ecdsa->akcipher.max_signature_len = + qcrypto_akcipher_ecdsasig_x9_62_size(384 / 8); + ecdsa->akcipher.max_dgst_len = 256 / 8; + break; + + default: + error_setg(errp, "Unknown curve id: %d", opts->curve_id); + return -1; + } + + return 0; +} + +static int qcrypto_gcrypt_parse_ecdsa_private_key( + QCryptoGcryptECDSA *ecdsa, const char *curve_name, + const uint8_t *key, size_t keylen, + Error **errp) +{ + g_autoptr(QCryptoAkCipherECDSAKey) ecdsa_key = + qcrypto_akcipher_ecdsakey_parse(QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE, + key, keylen, errp); + gcry_mpi_t d = NULL; + gcry_error_t err; + g_autofree uint8_t *pubkey = NULL; + int ret = -1, pubkey_len; + + if (!ecdsa_key) { + return ret; + } + + err = gcry_mpi_scan(&d, GCRYMPI_FMT_USG, ecdsa_key->priv.data, + ecdsa_key->priv.len, NULL); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to parse ECDSA parivate key: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + return ret; + } + + /** + * Note: Gcrypt cannot automatically calculate the public key from the + * private key. If we do not add the public key into private key's + * S-expression, the private key will not be able to used for verification. + */ + if (ecdsa_key->pub_x.len != 0 && ecdsa_key->pub_y.len != 0) { + /* if public key is found, add it into private key's S-expression */ + pubkey_len = ecdsa_key->pub_x.len + ecdsa_key->pub_y.len + 1; + pubkey = g_new0(uint8_t, pubkey_len); + /* 0x04 for uncompressed public key format */ + pubkey[0] = 0x04; + memcpy(pubkey + 1, ecdsa_key->pub_x.data, ecdsa_key->pub_x.len); + memcpy(pubkey + 1 + ecdsa_key->pub_x.len, + ecdsa_key->pub_y.data, ecdsa_key->pub_y.len); + + err = gcry_sexp_build(&ecdsa->key, NULL, + "(private-key (ecc (curve %s) (q %b) (d %m)))", + curve_name, pubkey_len, pubkey, d); + } else { + err = gcry_sexp_build(&ecdsa->key, NULL, + "(private-key (ecc (curve %s) (d %m)))", curve_name, d); + } + + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to build ECDSA parivate key: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + + ret = 0; + +cleanup: + gcry_mpi_release(d); + return ret; +} + +static int qcrypto_gcrypt_parse_ecdsa_public_key( + QCryptoGcryptECDSA *ecdsa, const char *curve_name, + const uint8_t *key, size_t keylen, + Error **errp) +{ + gcry_error_t err; + int ret = -1; + + err = gcry_sexp_build(&ecdsa->key, NULL, + "(public-key (ecc (curve %s) (q %b)))", curve_name, keylen, key); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to build ECDSA public key: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + ret = 0; + +cleanup: + return ret; +} + +static void qcrypto_gcrypt_ecdsa_free(QCryptoAkCipher *akcipher) +{ + QCryptoGcryptECDSA *ecdsa = (QCryptoGcryptECDSA *)akcipher; + if (!ecdsa) { + return; + } + gcry_sexp_release(ecdsa->key); + g_free(ecdsa); +} + +static int qcrypto_gcrypt_invalid_encrypt(QCryptoAkCipher *akcipher, + const void *in, size_t in_len, + void *out, size_t out_len, + Error **errp) +{ + error_setg(errp, "Operation is invalid"); + return -1; +} + +static int qcrypto_gcrypt_invalid_decrypt(QCryptoAkCipher *akcipher, + const void *in, size_t in_len, + void *out, size_t out_len, + Error **errp) +{ + error_setg(errp, "Operation is invalid"); + return -1; +} + +static int qcrypto_gcrypt_ecdsa_sign(QCryptoAkCipher *akcipher, + const void *in, size_t in_len, + void *out, size_t out_len, Error **errp) +{ + QCryptoGcryptECDSA *ecdsa = (QCryptoGcryptECDSA *)akcipher; + int ret = -1; + gcry_mpi_t data = NULL, r_mpi = NULL, s_mpi = NULL; + gcry_sexp_t dgst_sexp = NULL, sig_sexp = NULL; + gcry_sexp_t r_sexp_item = NULL, s_sexp_item = NULL; + size_t actual_len; + gcry_error_t err; + g_autoptr(QCryptoAkCipherECDSASig) sig = NULL; + + if (out_len < akcipher->max_signature_len) { + error_setg(errp, "Signature buffer should be not less than: %d", + akcipher->max_signature_len); + return -1; + } + /** + * Note: + * 1. for ECDSA, digest length less than key length is recommended but not + * required, truncation occurs when digest is too long, see FIPS 186-4: + * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf. + * 2. in order for gcrypt to truncate(if needed) the digest correctly, we + * must use the S-expression '(hash hash-alg block)' to store the digest. + * When the flags is 'raw', gcrypt will ignore the paramter 'hash-alg'( + * in below code, hard encoded as 'sha1'). + */ + err = gcry_sexp_build(&dgst_sexp, NULL, + "(data (flags raw) (hash sha1 %b))", in_len, in); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to build dgst signature: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + + err = gcry_pk_sign(&sig_sexp, dgst_sexp, ecdsa->key); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to make signature: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + + sig = qcrypto_akcipher_ecdsasig_alloc(ecdsa->curve_id, errp); + if (!sig) { + goto cleanup; + } + + /* S-expression of signature: (sig-val (ecdsa (r r-mpi) (s s-mpi))) */ + r_sexp_item = gcry_sexp_find_token(sig_sexp, "r", 0); + if (!r_sexp_item || gcry_sexp_length(r_sexp_item) != 2) { + error_setg(errp, "Invalid signature result"); + goto cleanup; + } + r_mpi = gcry_sexp_nth_mpi(r_sexp_item, 1, GCRYMPI_FMT_USG); + if (!r_mpi) { + error_setg(errp, "Invalid signature result"); + } + err = gcry_mpi_print(GCRYMPI_FMT_STD, sig->r.data, sig->r.len, + &actual_len, r_mpi); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to print MPI: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + if (unlikely(actual_len > sig->r.len)) { + error_setg(errp, "Internal error: signature buffer is too small"); + goto cleanup; + } + sig->r.len = actual_len; + + s_sexp_item = gcry_sexp_find_token(sig_sexp, "s", 0); + if (!s_sexp_item || gcry_sexp_length(s_sexp_item) != 2) { + error_setg(errp, "Invalid signature result"); + goto cleanup; + } + s_mpi = gcry_sexp_nth_mpi(s_sexp_item, 1, GCRYMPI_FMT_USG); + if (!s_mpi) { + error_setg(errp, "Invalid signature result"); + } + err = gcry_mpi_print(GCRYMPI_FMT_STD, sig->s.data, sig->s.len, + &actual_len, s_mpi); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to print MPI: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + if (unlikely(actual_len > sig->s.len)) { + error_setg(errp, "Internal error: signature buffer is too small"); + goto cleanup; + } + sig->s.len = actual_len; + + qcrypto_akcipher_ecdsasig_x9_62_encode(sig, out, &out_len); + ret = out_len; + +cleanup: + gcry_mpi_release(data); + gcry_mpi_release(r_mpi); + gcry_mpi_release(s_mpi); + gcry_sexp_release(dgst_sexp); + gcry_sexp_release(sig_sexp); + gcry_sexp_release(r_sexp_item); + + return ret; +} + +static int qcrypto_gcrypt_ecdsa_verify(QCryptoAkCipher *akcipher, + const void *in, size_t in_len, + const void *in2, size_t in2_len, + Error **errp) +{ + QCryptoGcryptECDSA *ecdsa = (QCryptoGcryptECDSA *)akcipher; + int ret = -1; + QCryptoAkCipherECDSASig *sig; + gcry_mpi_t sig_s = NULL, sig_r = NULL, dgst_mpi = NULL; + gcry_sexp_t sig_sexp = NULL, dgst_sexp = NULL; + gcry_error_t err; + + /* + * We only check the signature length, dgst length will be handled + * by gcrypt, see qcrypto_gcrypt_ecdsa_sign. + */ + if (in_len > akcipher->max_signature_len) { + error_setg(errp, "Signature length is greater than %d", + akcipher->max_signature_len); + return ret; + } + + sig = qcrypto_akcipher_ecdsasig_parse(in, in_len, errp); + if (!sig) { + return ret; + } + + err = gcry_mpi_scan(&sig_r, GCRYMPI_FMT_STD, sig->r.data, sig->r.len, NULL); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to parse ECDSA signature: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + err = gcry_mpi_scan(&sig_s, GCRYMPI_FMT_STD, sig->s.data, sig->s.len, NULL); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to parse ECDSA signature: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + err = gcry_sexp_build(&sig_sexp, NULL, + "(sig-val (ecdsa (r %m) (s %m)))", sig_r, sig_s); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to build signature: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + + /** + * gcrypt will ignore the paremeter 'sha1', see commment in function: + * qcrypto_gcrypt_ecdsa_verify + */ + err = gcry_sexp_build(&dgst_sexp, NULL, + "(data (flags raw) (hash sha1 %b))", in2_len, in2); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to build dgst: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + + err = gcry_pk_verify(sig_sexp, dgst_sexp, ecdsa->key); + if (gcry_err_code(err) != 0) { + error_setg(errp, "Failed to verify signature: %s/%s", + gcry_strsource(err), gcry_strerror(err)); + goto cleanup; + } + ret = 0; + +cleanup: + gcry_mpi_release(sig_s); + gcry_mpi_release(sig_r); + gcry_mpi_release(dgst_mpi); + gcry_sexp_release(dgst_sexp); + gcry_sexp_release(sig_sexp); + qcrypto_akcipher_ecdsasig_free(sig); + + return ret; +} + +static QCryptoAkCipherDriver gcrypt_ecdsa = { + .encrypt = qcrypto_gcrypt_invalid_encrypt, + .decrypt = qcrypto_gcrypt_invalid_decrypt, + .sign = qcrypto_gcrypt_ecdsa_sign, + .verify = qcrypto_gcrypt_ecdsa_verify, + .free = qcrypto_gcrypt_ecdsa_free, +}; + +static QCryptoGcryptECDSA *qcrypto_gcrypt_ecdsa_new( + const QCryptoAkCipherOptionsECDSA *opts, + QCryptoAkCipherKeyType type, + const uint8_t *key, size_t keylen, + Error **errp) +{ + QCryptoGcryptECDSA *ecdsa = g_new0(QCryptoGcryptECDSA, 1); + if (qcrypto_gcrypt_parse_curve_id(ecdsa, opts, errp) != 0) { + goto error; + } + ecdsa->curve_id = opts->curve_id; + ecdsa->akcipher.driver = &gcrypt_ecdsa; + + switch (type) { + case QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE: + if (qcrypto_gcrypt_parse_ecdsa_private_key( + ecdsa, ecdsa->curve_name, key, keylen, errp) != 0) { + goto error; + } + break; + + case QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC: + if (qcrypto_gcrypt_parse_ecdsa_public_key( + ecdsa, ecdsa->curve_name, key, keylen, errp) != 0) { + goto error; + } + break; + + default: + error_setg(errp, "Unknown akcipher key type %d", type); + goto error; + } + + return ecdsa; + +error: + qcrypto_gcrypt_ecdsa_free((QCryptoAkCipher *)ecdsa); + return NULL; +} bool qcrypto_akcipher_supports(QCryptoAkCipherOptions *opts) { @@ -589,6 +987,17 @@ bool qcrypto_akcipher_supports(QCryptoAkCipherOptions *opts) return false; } + case QCRYPTO_AKCIPHER_ALG_ECDSA: + switch (opts->u.ecdsa.curve_id) { + case QCRYPTO_CURVE_ID_NIST_P192: + case QCRYPTO_CURVE_ID_NIST_P256: + case QCRYPTO_CURVE_ID_NIST_P384: + return true; + + default: + return false; + } + default: return true; } From patchwork Wed Jun 22 09:15:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12890383 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 36C29C43334 for ; Wed, 22 Jun 2022 09:19:10 +0000 (UTC) Received: from localhost ([::1]:48420 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o3wVx-0003Jx-4o for qemu-devel@archiver.kernel.org; Wed, 22 Jun 2022 05:19:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59366) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o3wTX-0000WK-28 for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:40 -0400 Received: from mail-pj1-x102c.google.com ([2607:f8b0:4864:20::102c]:40094) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o3wTU-0007MN-IP for qemu-devel@nongnu.org; Wed, 22 Jun 2022 05:16:38 -0400 Received: by mail-pj1-x102c.google.com with SMTP id g16-20020a17090a7d1000b001ea9f820449so16156395pjl.5 for ; Wed, 22 Jun 2022 02:16:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sBVor08NdXhCCzfIIm0IvMraTkqQ6DPScc7YYNMOwWo=; b=B5Y48Y0aqborH4GXIaN5ZDOBc+la5/OGOUT6HblP8+srAkxwO5oM9POU/P/Rcpx6PY r+jBqlk1GtkX+BpJ9U6AR8RZ3NbVFylOJbaw2iDXxTL1AhwTde7V6oWw1YR8iMs5AWVF ymSkrj+sdIVJwN/yC5p45m3q2U1yXJ4aiVpzeGGf2bvQIZ5o7EAhpiqLNGxlprr/5lBC LjkUUoJZj0jlD3r/N/3BQKKFNZe1N5ZznF4zP0pbeu0h2kdUtJc4SwaVWRQvjNjfeRSM MHqCw0UELk1fZGR0obqzOOpdstCw9qJ2ZDXmRxQzZDrIEBcwqam9M/5eor3bxXodf166 EDWQ== 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=sBVor08NdXhCCzfIIm0IvMraTkqQ6DPScc7YYNMOwWo=; b=IATfcIAnICth7HEBiqRu5E/InyWZYj9+m+cHxz/jrw/Po/n+CANM+mV9Pxbx1h+vjy dp4tDSrV8DleTn9Nknfub/lciafkXRgKTS6YYGHnmjYQWAQYQa4AQxxnsH/SWnn5k9aK qJYQD9DafngXhhqIbTFphwnvW2IUHiyxOJV4p5GwBBdQr9hVAJdEd2N29La/Q6yUH3uW VVahD0qtsZqYIUm6QPk6nyG26nD4EAg1hOceOUubJl6itjPajS4FSXjGuSOY6MjXXB2Z itizfsrpiDgdBpFqc60ErcPxexAw6DT9z3E1gv1lTsp2t0l7vy9VreyNRx5yaMhew9jw jgOQ== X-Gm-Message-State: AJIora/AhfaXWLAwCdjkWkz9IOv6SHdGFVG/bkbuBV2nMHXh5UtPw3v6 8dAcbazMqzTahl186kVDjIwDp7k6rQw6ug== X-Google-Smtp-Source: AGRyM1uphq5kUdKQ90jiFJFTTKh9hykqkd1whN5GRviyW2JylILkdBo3RK5IS5NIncMDifuzZxOXsg== X-Received: by 2002:a17:90a:17a6:b0:1ec:74e4:d7a3 with SMTP id q35-20020a17090a17a600b001ec74e4d7a3mr30218602pja.115.1655889394282; Wed, 22 Jun 2022 02:16:34 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id ja13-20020a170902efcd00b0016a087cfad8sm9833900plb.264.2022.06.22.02.16.31 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 02:16:33 -0700 (PDT) From: Lei He To: qemu-devel@nongnu.org, berrange@redhat.com, f4bug@amsat.org Cc: mst@redhat.com, pizhenwei@bytedance.com, jasowang@redhat.com, helei.sig11@bytedance.com Subject: [PATCH v2 7/7] crypto: Add test suite for ECDSA algorithm Date: Wed, 22 Jun 2022 17:15:49 +0800 Message-Id: <20220622091549.31115-8-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20220622091549.31115-1-helei.sig11@bytedance.com> References: <20220622091549.31115-1-helei.sig11@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::102c; envelope-from=helei.sig11@bytedance.com; helo=mail-pj1-x102c.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 1. add test suite for ecdsa algorithm. 2. use qcrypto_akcihper_max_xxx_len to help create buffers in Signed-off-by: lei he Reviewed-by: Daniel P. Berrangé --- tests/unit/test-crypto-akcipher.c | 338 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 323 insertions(+), 15 deletions(-) diff --git a/tests/unit/test-crypto-akcipher.c b/tests/unit/test-crypto-akcipher.c index 4f1f4214dd..414387cfb4 100644 --- a/tests/unit/test-crypto-akcipher.c +++ b/tests/unit/test-crypto-akcipher.c @@ -314,12 +314,117 @@ static const uint8_t rsa2048_public_key[] = { 0xed, 0x02, 0x03, 0x01, 0x00, 0x01 }; +static const uint8_t ecdsa_p192_public_key[] = { + 0x04, 0xc4, 0x16, 0xb3, 0xff, 0xac, 0xd5, 0x87, + 0x98, 0xf7, 0xd9, 0x45, 0xfe, 0xd3, 0x5c, 0x17, + 0x9d, 0xb2, 0x36, 0x22, 0xcc, 0x07, 0xb3, 0x6d, + 0x3c, 0x4e, 0x04, 0x5f, 0xeb, 0xb6, 0x52, 0x58, + 0xfb, 0x36, 0x10, 0x52, 0xb7, 0x01, 0x62, 0x0e, + 0x94, 0x51, 0x1d, 0xe2, 0xef, 0x10, 0x82, 0x88, + 0x78, +}; + +static const uint8_t ecdsa_p192_private_key[] = { + 0x30, 0x53, 0x02, 0x01, 0x01, 0x04, 0x18, 0xcb, + 0xc8, 0x86, 0x0e, 0x66, 0x3c, 0xf7, 0x5a, 0x44, + 0x13, 0xb8, 0xef, 0xea, 0x1d, 0x7b, 0xa6, 0x1c, + 0xda, 0xf4, 0x1b, 0xc7, 0x67, 0x6b, 0x35, 0xa1, + 0x34, 0x03, 0x32, 0x00, 0x04, 0xc4, 0x16, 0xb3, + 0xff, 0xac, 0xd5, 0x87, 0x98, 0xf7, 0xd9, 0x45, + 0xfe, 0xd3, 0x5c, 0x17, 0x9d, 0xb2, 0x36, 0x22, + 0xcc, 0x07, 0xb3, 0x6d, 0x3c, 0x4e, 0x04, 0x5f, + 0xeb, 0xb6, 0x52, 0x58, 0xfb, 0x36, 0x10, 0x52, + 0xb7, 0x01, 0x62, 0x0e, 0x94, 0x51, 0x1d, 0xe2, + 0xef, 0x10, 0x82, 0x88, 0x78, +}; + +static const uint8_t ecdsa_p256_private_key[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, + 0x92, 0xdd, 0x29, 0x1c, 0x6e, 0xef, 0xb6, 0xb2, + 0x73, 0x9f, 0x40, 0x1b, 0xb3, 0x2a, 0x28, 0xd2, + 0x37, 0xd6, 0x4a, 0x5b, 0xe4, 0x40, 0x4c, 0x6a, + 0x95, 0x99, 0xfa, 0xf7, 0x92, 0x49, 0xbe, 0xa0, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, + 0x04, 0xed, 0x42, 0x9c, 0x67, 0x79, 0xbe, 0x46, + 0x83, 0x88, 0x3e, 0x8c, 0xc1, 0x33, 0xf3, 0xc3, + 0xf6, 0x2c, 0xf3, 0x13, 0x6a, 0x00, 0xc2, 0xc9, + 0x3e, 0x87, 0x7f, 0x86, 0x39, 0xe6, 0xae, 0xe3, + 0xb9, 0xba, 0x2f, 0x58, 0x63, 0x32, 0x62, 0x62, + 0x54, 0x07, 0x27, 0xf9, 0x5a, 0x3a, 0xc7, 0x3a, + 0x6b, 0x5b, 0xbc, 0x0d, 0x33, 0xba, 0xbb, 0xd4, + 0xa3, 0xff, 0x4f, 0x9e, 0xdd, 0xf5, 0x59, 0xc0, + 0xf6, +}; + +static const uint8_t ecdsa_p256_public_key[] = { + 0x04, 0xed, 0x42, 0x9c, 0x67, 0x79, 0xbe, 0x46, + 0x83, 0x88, 0x3e, 0x8c, 0xc1, 0x33, 0xf3, 0xc3, + 0xf6, 0x2c, 0xf3, 0x13, 0x6a, 0x00, 0xc2, 0xc9, + 0x3e, 0x87, 0x7f, 0x86, 0x39, 0xe6, 0xae, 0xe3, + 0xb9, 0xba, 0x2f, 0x58, 0x63, 0x32, 0x62, 0x62, + 0x54, 0x07, 0x27, 0xf9, 0x5a, 0x3a, 0xc7, 0x3a, + 0x6b, 0x5b, 0xbc, 0x0d, 0x33, 0xba, 0xbb, 0xd4, + 0xa3, 0xff, 0x4f, 0x9e, 0xdd, 0xf5, 0x59, 0xc0, + 0xf6, +}; + +static const uint8_t ecdsa_p384_public_key[] = { + 0x04, 0xab, 0xd5, 0xf8, 0x87, 0x1d, 0x23, 0x9b, + 0x26, 0xb9, 0x57, 0x7e, 0x97, 0x78, 0x10, 0xcd, + 0x13, 0xe3, 0x98, 0x25, 0xa8, 0xd6, 0xab, 0x66, + 0x35, 0x26, 0x68, 0x8a, 0x0e, 0x49, 0xd9, 0x4a, + 0x91, 0x7d, 0x6c, 0x94, 0x06, 0x06, 0x99, 0xf1, + 0x8d, 0x2a, 0x25, 0x8d, 0xf9, 0xbf, 0x40, 0xfa, + 0xb7, 0xcb, 0xe1, 0x14, 0x22, 0x0a, 0xa7, 0xfb, + 0x0a, 0xb4, 0x02, 0x05, 0x8b, 0x98, 0xaa, 0x78, + 0xcd, 0x53, 0x00, 0x1e, 0xd1, 0x79, 0x6a, 0x5f, + 0x09, 0x01, 0x88, 0xb4, 0xbc, 0x32, 0x62, 0x83, + 0x92, 0x84, 0x2d, 0xc6, 0xf8, 0xda, 0xc4, 0x7f, + 0x10, 0xa3, 0x18, 0x1d, 0xae, 0x0d, 0xa4, 0x41, + 0x9f, +}; + +static const uint8_t ecdsa_p384_private_key[] = { + 0x30, 0x81, 0x9b, 0x02, 0x01, 0x01, 0x04, 0x30, + 0xb6, 0x04, 0xef, 0xb1, 0x2c, 0x98, 0xdf, 0xcf, + 0xd4, 0x16, 0x31, 0xd4, 0x69, 0x0c, 0x27, 0x81, + 0x4a, 0xac, 0x1a, 0x83, 0x3c, 0xe4, 0xef, 0x65, + 0xe1, 0x7a, 0x6a, 0xc6, 0xd6, 0xf7, 0xea, 0x79, + 0xbe, 0xf1, 0x00, 0x3c, 0xdf, 0x6e, 0x9d, 0x10, + 0x22, 0x61, 0x1b, 0x11, 0xcf, 0x49, 0x6e, 0x62, + 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xab, 0xd5, + 0xf8, 0x87, 0x1d, 0x23, 0x9b, 0x26, 0xb9, 0x57, + 0x7e, 0x97, 0x78, 0x10, 0xcd, 0x13, 0xe3, 0x98, + 0x25, 0xa8, 0xd6, 0xab, 0x66, 0x35, 0x26, 0x68, + 0x8a, 0x0e, 0x49, 0xd9, 0x4a, 0x91, 0x7d, 0x6c, + 0x94, 0x06, 0x06, 0x99, 0xf1, 0x8d, 0x2a, 0x25, + 0x8d, 0xf9, 0xbf, 0x40, 0xfa, 0xb7, 0xcb, 0xe1, + 0x14, 0x22, 0x0a, 0xa7, 0xfb, 0x0a, 0xb4, 0x02, + 0x05, 0x8b, 0x98, 0xaa, 0x78, 0xcd, 0x53, 0x00, + 0x1e, 0xd1, 0x79, 0x6a, 0x5f, 0x09, 0x01, 0x88, + 0xb4, 0xbc, 0x32, 0x62, 0x83, 0x92, 0x84, 0x2d, + 0xc6, 0xf8, 0xda, 0xc4, 0x7f, 0x10, 0xa3, 0x18, + 0x1d, 0xae, 0x0d, 0xa4, 0x41, 0x9f, +}; + static const uint8_t test_sha1_dgst[] = { 0x3c, 0x05, 0x19, 0x34, 0x29, 0x19, 0xc7, 0xe0, 0x87, 0xb6, 0x24, 0xf9, 0x58, 0xac, 0xa4, 0xd4, 0xb2, 0xd9, 0x03, 0x9e, }; +static const uint8_t test_sha512_dgst[] = { + 0x8b, 0x79, 0xc0, 0x3c, 0xcb, 0x15, 0x26, 0x51, + 0x50, 0xca, 0xb1, 0xa7, 0xf3, 0xf6, 0x1e, 0x0a, + 0xbb, 0x39, 0x7c, 0x97, 0x7f, 0xad, 0x9e, 0x51, + 0xb4, 0xa0, 0xb0, 0xd8, 0xd6, 0xb9, 0xd8, 0x81, + 0xac, 0x8a, 0xb3, 0x30, 0x07, 0xea, 0x6e, 0x63, + 0x2f, 0xda, 0x8f, 0x2c, 0x4b, 0xa0, 0xee, 0x9a, + 0xda, 0x32, 0x2d, 0x6c, 0xb1, 0x8b, 0xe2, 0xd8, + 0x79, 0x48, 0xd4, 0xf9, 0xb1, 0xfa, 0xf1, 0xa2, +}; + static const uint8_t exp_signature_rsa2048_pkcs1[] = { 0x4e, 0x82, 0x56, 0x4c, 0x84, 0x66, 0xca, 0x1e, 0xc6, 0x92, 0x46, 0x20, 0x02, 0x6b, 0x64, 0x46, @@ -374,6 +479,82 @@ static const uint8_t exp_signature_rsa1024_pkcs1[] = { 0xab, 0x0d, 0xc6, 0x59, 0x1d, 0xc7, 0x33, 0x7b, }; +static const uint8_t exp_signature_ecdsa_p192[] = { + 0x30, 0x35, 0x02, 0x19, 0x00, 0xba, 0xf7, 0xc0, + 0xc1, 0x7e, 0xf5, 0x69, 0xd5, 0xb7, 0x5d, 0x06, + 0xcb, 0x92, 0x28, 0x57, 0x52, 0x96, 0x9a, 0xdc, + 0xc9, 0xf9, 0xd5, 0x2c, 0x51, 0x02, 0x18, 0x26, + 0x21, 0x5d, 0x16, 0xba, 0xff, 0x19, 0x74, 0x56, + 0x8e, 0xdf, 0x51, 0x2b, 0x2c, 0xce, 0xc2, 0x7b, + 0x5b, 0x03, 0x10, 0x56, 0x57, 0x63, 0x47, +}; + +static const uint8_t exp_signature_ecdsa_p192_sha512[] = { + 0x30, 0x35, 0x02, 0x19, 0x00, 0xbb, 0x03, 0x61, + 0x98, 0x28, 0xb3, 0x02, 0xca, 0x61, 0x08, 0xce, + 0x98, 0xfd, 0x57, 0x6e, 0x60, 0xfa, 0xa0, 0x06, + 0x03, 0xe2, 0xb2, 0x07, 0x22, 0x02, 0x18, 0x26, + 0xdc, 0x17, 0x3b, 0xf1, 0x88, 0x0a, 0x2c, 0xd5, + 0x51, 0x23, 0xbc, 0x83, 0x54, 0x05, 0x77, 0x28, + 0xd5, 0x84, 0xdf, 0x16, 0x4f, 0x50, 0x20, +}; + +static const uint8_t exp_signature_ecdsa_p256[] = { + 0x30, 0x45, 0x02, 0x21, 0x00, 0xac, 0x09, 0xf3, + 0x32, 0xb6, 0xf6, 0x7e, 0x12, 0x4f, 0x68, 0xdb, + 0x10, 0x14, 0x61, 0xf6, 0x29, 0xbd, 0xdd, 0x72, + 0x9f, 0x81, 0xf8, 0x83, 0x8a, 0xf3, 0x29, 0x87, + 0x7b, 0xbb, 0xcf, 0xea, 0x64, 0x02, 0x20, 0x14, + 0xfc, 0x2e, 0x2f, 0x3e, 0x06, 0xb1, 0xd0, 0xbb, + 0x91, 0x44, 0xd5, 0x53, 0xb4, 0x72, 0xa1, 0x83, + 0xc7, 0x3a, 0xa8, 0xfc, 0x43, 0x1b, 0x2e, 0xbb, + 0xb0, 0xe9, 0xef, 0x0b, 0x03, 0x32, 0x74, +}; + +static const uint8_t exp_signature_ecdsa_p256_sha512[] = { + 0x30, 0x46, 0x02, 0x21, 0x00, 0xe0, 0x48, 0x74, + 0x65, 0xaa, 0x63, 0x97, 0x68, 0x45, 0x68, 0xfa, + 0xec, 0x51, 0x64, 0xfe, 0x09, 0xc7, 0x5c, 0x65, + 0x5d, 0x93, 0x04, 0x17, 0x23, 0xbe, 0x1b, 0x2f, + 0x89, 0x5e, 0x02, 0xcd, 0x55, 0x02, 0x21, 0x00, + 0xe9, 0x24, 0xbd, 0x7a, 0xbd, 0x05, 0x89, 0x04, + 0x92, 0x2d, 0x67, 0x8d, 0x66, 0xa8, 0x9d, 0x7b, + 0xb1, 0x5b, 0xae, 0xd1, 0xd4, 0x7b, 0xe8, 0x72, + 0xe9, 0xd9, 0x45, 0xfd, 0xd3, 0x76, 0xbe, 0xfb, +}; + +static const uint8_t exp_signature_ecdsa_p384[] = { + 0x30, 0x64, 0x02, 0x30, 0x3c, 0x79, 0x7f, 0x5a, + 0x91, 0x08, 0x79, 0xde, 0x6e, 0x03, 0x19, 0x39, + 0xcb, 0x94, 0x9c, 0xc6, 0x09, 0x12, 0xfa, 0xbd, + 0xa8, 0x35, 0x5e, 0x3f, 0x74, 0x05, 0x12, 0xd1, + 0x8e, 0xd9, 0x3c, 0x79, 0x9d, 0x7c, 0x1a, 0xae, + 0x96, 0x05, 0x0e, 0x35, 0x21, 0x73, 0xd8, 0xfe, + 0x1b, 0x43, 0x06, 0xb9, 0x02, 0x30, 0x11, 0xdf, + 0xa7, 0xba, 0x70, 0x84, 0x4b, 0x74, 0xab, 0x1e, + 0x9e, 0x6a, 0xc1, 0x46, 0xe3, 0x98, 0x0a, 0x25, + 0x82, 0xf5, 0xff, 0xb5, 0x6f, 0x04, 0xda, 0xc3, + 0xfd, 0x3e, 0xea, 0x96, 0x03, 0x0c, 0x22, 0xf2, + 0xda, 0x86, 0xeb, 0x91, 0x2f, 0x36, 0x13, 0xba, + 0x37, 0xcd, 0xe7, 0x91, 0x85, 0xf3, +}; + +static const uint8_t exp_signature_ecdsa_p384_sha512[] = { + 0x30, 0x64, 0x02, 0x30, 0x04, 0xa2, 0x3e, 0xb0, + 0xc0, 0x1f, 0xa0, 0xbb, 0x19, 0x60, 0x56, 0x04, + 0x11, 0x95, 0xa9, 0x34, 0x0d, 0x0a, 0x80, 0x7f, + 0x5b, 0x08, 0xb3, 0xf9, 0x33, 0xc2, 0xd4, 0x6d, + 0x23, 0x0a, 0xed, 0x29, 0xca, 0x93, 0xba, 0x8c, + 0xee, 0xbf, 0x2d, 0xb8, 0x45, 0xda, 0xaf, 0x2f, + 0x2e, 0x5b, 0xda, 0x62, 0x02, 0x30, 0x2e, 0x6f, + 0xa4, 0x24, 0xf7, 0xcf, 0x58, 0xc3, 0xca, 0x29, + 0xd8, 0x0b, 0xe7, 0xb5, 0x88, 0xeb, 0x81, 0xbe, + 0x50, 0x2a, 0xd3, 0x37, 0xeb, 0x23, 0xcc, 0x55, + 0x6f, 0xf5, 0x02, 0xb9, 0xf9, 0xa1, 0x58, 0x2a, + 0x35, 0x00, 0xe9, 0x2f, 0xc8, 0x73, 0x5c, 0x27, + 0xbc, 0x4b, 0x8c, 0x0e, 0x4d, 0xde, +}; + static const uint8_t test_plaintext[] = { 0x00, 0x44, 0xbc, 0x6f, 0x77, 0xfb, 0xe2, 0xa4, 0x98, 0x9e, 0xf5, 0x33, 0xa0, 0xbd, 0x81, 0xb9, @@ -870,7 +1051,114 @@ static QCryptoAkCipherTestData akcipher_test_data[] = { .signature = exp_signature_rsa2048_pkcs1, .slen = sizeof(exp_signature_rsa2048_pkcs1), }, + { + .path = "/crypto/akcipher/ecdsa-nist-p192-with-sha1", + .opt = { + .alg = QCRYPTO_AKCIPHER_ALG_ECDSA, + .u.ecdsa = { + .curve_id = QCRYPTO_CURVE_ID_NIST_P192, + }, + }, + .pub_key = ecdsa_p192_public_key, + .pub_key_len = sizeof(ecdsa_p192_public_key), + .priv_key = ecdsa_p192_private_key, + .priv_key_len = sizeof(ecdsa_p192_private_key), + + .dgst = test_sha1_dgst, + .dlen = sizeof(test_sha1_dgst), + .signature = exp_signature_ecdsa_p192, + .slen = sizeof(exp_signature_ecdsa_p192), + }, + { + .path = "/crypto/akcipher/ecdsa-nist-p192-with-sha512", + .opt = { + .alg = QCRYPTO_AKCIPHER_ALG_ECDSA, + .u.ecdsa = { + .curve_id = QCRYPTO_CURVE_ID_NIST_P192, + }, + }, + .pub_key = ecdsa_p192_public_key, + .pub_key_len = sizeof(ecdsa_p192_public_key), + .priv_key = ecdsa_p192_private_key, + .priv_key_len = sizeof(ecdsa_p192_private_key), + + .dgst = test_sha512_dgst, + .dlen = sizeof(test_sha512_dgst), + .signature = exp_signature_ecdsa_p192_sha512, + .slen = sizeof(exp_signature_ecdsa_p192_sha512), + }, + { + .path = "/crypto/akcipher/ecdsa-nist-p256-with-sha1", + .opt = { + .alg = QCRYPTO_AKCIPHER_ALG_ECDSA, + .u.ecdsa = { + .curve_id = QCRYPTO_CURVE_ID_NIST_P256, + }, + }, + .pub_key = ecdsa_p256_public_key, + .pub_key_len = sizeof(ecdsa_p256_public_key), + .priv_key = ecdsa_p256_private_key, + .priv_key_len = sizeof(ecdsa_p256_private_key), + .dgst = test_sha1_dgst, + .dlen = sizeof(test_sha1_dgst), + .signature = exp_signature_ecdsa_p256, + .slen = sizeof(exp_signature_ecdsa_p256), + }, + { + .path = "/crypto/akcipher/ecdsa-nist-p256-with-sha512", + .opt = { + .alg = QCRYPTO_AKCIPHER_ALG_ECDSA, + .u.ecdsa = { + .curve_id = QCRYPTO_CURVE_ID_NIST_P256, + }, + }, + .pub_key = ecdsa_p256_public_key, + .pub_key_len = sizeof(ecdsa_p256_public_key), + .priv_key = ecdsa_p256_private_key, + .priv_key_len = sizeof(ecdsa_p256_private_key), + + .dgst = test_sha512_dgst, + .dlen = sizeof(test_sha512_dgst), + .signature = exp_signature_ecdsa_p256_sha512, + .slen = sizeof(exp_signature_ecdsa_p256_sha512), + }, + { + .path = "/crypto/akcipher/ecdsa-nist-p384-with-sha1", + .opt = { + .alg = QCRYPTO_AKCIPHER_ALG_ECDSA, + .u.ecdsa = { + .curve_id = QCRYPTO_CURVE_ID_NIST_P384, + }, + }, + .pub_key = ecdsa_p384_public_key, + .pub_key_len = sizeof(ecdsa_p384_public_key), + .priv_key = ecdsa_p384_private_key, + .priv_key_len = sizeof(ecdsa_p384_private_key), + + .dgst = test_sha1_dgst, + .dlen = sizeof(test_sha1_dgst), + .signature = exp_signature_ecdsa_p384, + .slen = sizeof(exp_signature_ecdsa_p384), + }, + { + .path = "/crypto/akcipher/ecdsa-nist-p384-with-sha512", + .opt = { + .alg = QCRYPTO_AKCIPHER_ALG_ECDSA, + .u.ecdsa = { + .curve_id = QCRYPTO_CURVE_ID_NIST_P384, + }, + }, + .pub_key = ecdsa_p384_public_key, + .pub_key_len = sizeof(ecdsa_p384_public_key), + .priv_key = ecdsa_p384_private_key, + .priv_key_len = sizeof(ecdsa_p384_private_key), + + .dgst = test_sha512_dgst, + .dlen = sizeof(test_sha512_dgst), + .signature = exp_signature_ecdsa_p384_sha512, + .slen = sizeof(exp_signature_ecdsa_p384_sha512), + }, }; static void test_akcipher(const void *opaque) @@ -879,6 +1167,8 @@ static void test_akcipher(const void *opaque) g_autofree uint8_t *plaintext = NULL; g_autofree uint8_t *ciphertext = NULL; g_autofree uint8_t *signature = NULL; + int signature_len, ciphertext_len, plaintext_len; + int max_plen, max_slen, max_clen; QCryptoAkCipher *pub_key, *priv_key; if (!qcrypto_akcipher_supports((QCryptoAkCipherOptions *)&data->opt)) { @@ -894,32 +1184,41 @@ static void test_akcipher(const void *opaque) data->priv_key, data->priv_key_len, &error_abort); g_assert(priv_key != NULL); + max_plen = qcrypto_akcipher_max_plaintext_len(pub_key); + max_clen = qcrypto_akcipher_max_plaintext_len(pub_key); + max_slen = qcrypto_akcipher_max_signature_len(priv_key); if (data->plaintext != NULL) { - ciphertext = g_new0(uint8_t, data->clen); - g_assert(qcrypto_akcipher_encrypt(pub_key, data->plaintext, data->plen, - ciphertext, data->clen, - &error_abort) > 0); + ciphertext = g_new0(uint8_t, max_clen); + ciphertext_len = qcrypto_akcipher_encrypt(pub_key, + data->plaintext, data->plen, + ciphertext, max_clen, + &error_abort); + g_assert(ciphertext_len > 0); /** * In the asymmetric encryption algorithms, the ciphertext generated * each time may be different, here only compare the decrypted * plaintext */ - plaintext = g_new0(uint8_t, data->clen); - g_assert(qcrypto_akcipher_decrypt(priv_key, ciphertext, - data->clen, plaintext, - data->plen, - &error_abort) == data->plen); + plaintext = g_new0(uint8_t, max_plen); + plaintext_len = qcrypto_akcipher_decrypt(priv_key, + ciphertext, ciphertext_len, + plaintext, max_plen, + &error_abort); + g_assert(plaintext_len == data->plen); g_assert(!memcmp(plaintext, data->plaintext, data->plen)); } if (data->signature != NULL) { - signature = g_new(uint8_t, data->slen); - g_assert(qcrypto_akcipher_sign(priv_key, data->dgst, data->dlen, - signature, data->slen, - &error_abort) > 0); + signature = g_new(uint8_t, max_slen); + signature_len = qcrypto_akcipher_sign(priv_key, + data->dgst, data->dlen, + signature, max_slen, + &error_abort); + g_assert(signature_len > 0); + /** * The signature generated each time may be different, here only check * the verification. @@ -927,12 +1226,21 @@ static void test_akcipher(const void *opaque) g_assert(qcrypto_akcipher_verify(pub_key, data->signature, data->slen, data->dgst, data->dlen, &error_abort) == 0); - g_assert(qcrypto_akcipher_verify(pub_key, signature, data->slen, + g_assert(qcrypto_akcipher_verify(pub_key, signature, signature_len, + data->dgst, data->dlen, + &error_abort) == 0); + + g_assert(qcrypto_akcipher_verify(priv_key, data->signature, data->slen, + data->dgst, data->dlen, + &error_abort) == 0); + g_assert(qcrypto_akcipher_verify(priv_key, signature, signature_len, data->dgst, data->dlen, &error_abort) == 0); ++signature[0]; /* Here error should be ignored */ - g_assert(qcrypto_akcipher_verify(pub_key, signature, data->slen, + g_assert(qcrypto_akcipher_verify(pub_key, signature, signature_len, + data->dgst, data->dlen, NULL) != 0); + g_assert(qcrypto_akcipher_verify(priv_key, signature, signature_len, data->dgst, data->dlen, NULL) != 0); }