From patchwork Thu Jun 23 06:14:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lei He X-Patchwork-Id: 12891816 X-Patchwork-Delegate: herbert@gondor.apana.org.au 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EDBA8C433EF for ; Thu, 23 Jun 2022 06:15:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229747AbiFWGPQ (ORCPT ); Thu, 23 Jun 2022 02:15:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49702 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229625AbiFWGPP (ORCPT ); Thu, 23 Jun 2022 02:15:15 -0400 Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C36A713CF0 for ; Wed, 22 Jun 2022 23:15:14 -0700 (PDT) Received: by mail-pj1-x1035.google.com with SMTP id h9-20020a17090a648900b001ecb8596e43so1576683pjj.5 for ; Wed, 22 Jun 2022 23:15: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:mime-version :content-transfer-encoding; bh=oTdRX4nzzh5XnScdkMS8ZCJNByGLkKSHjz8cEvYbU9o=; b=D497u8ltIwHyH0cjmk5+9ujb4d8BsmOVJEVh1DplnRz36O6jiHh+AfEKpvRNDxEU5h NbbDB6IvDv6xUYX2qwu2RtqSToEMUKVMCundGguJ/kmyUh+eu/WIQBROeEObcGn72wbm lS+eFwFqWNqHRpvApI8kqW4o9m9coViBB/YB2xsPbBUHvHUpgE1MmWxaFRcuRM3ROmZj yN/kZtDhrm7cQ2F1dHtsuIIrvf3JPmlnYo7xbE95IItIV+wLo2w86DXBMXxAWsge3jg4 6YAyzMdDwQcNNB+EF4UKJIfvgJ0nemxIXdIjAjWrIFxcKkb0VFrQHbWGg+of4kRp0vTu QE1A== 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:mime-version :content-transfer-encoding; bh=oTdRX4nzzh5XnScdkMS8ZCJNByGLkKSHjz8cEvYbU9o=; b=cmpZsqgx3hEgWOfUzCttYPNhXsRsvQ+dxaU7OJRsVQEmQD/WTS4m6yleIzwGvP4SLM sGeOiwvlVb4qQjVyIaSX5RAaWnsaZnkmdOreBO9PqjvVEtaINyMmPvFGQkFhUzEbKTYX eO8FBEdtrEzMGTQ/iGOt6WZlwznn+HwwyCGAQNmVUhGVNnQ1TmHCQFm0ADmSH17acnnN B8CZm0kxWCY02RtQmrW2GwvFMR7pXqUiN7GyGkxzJyVN2tH6hRL2B8dLE1xfxl7Am39J MVNpGq7t0oNLloWGAW+S5iZBWhBbvRFFE2fmgFk3M6hDUNXwGRWj0kFp9zW6UHWo/4Yd KuAw== X-Gm-Message-State: AJIora9kU5S9nRzqOwc+aIoQN43jOkJftHM3M+EQoca/yqGExrbU91G2 +9ZabmFfgunZdUD5G6Hx5LCYxw== X-Google-Smtp-Source: AGRyM1u+kUriTQ+YpHfPIMLDHaJOtv19+9y3fQAqtSvu0h+Q6l2ikp3Z8qM1TdZ39IiBnYldQlDIkg== X-Received: by 2002:a17:902:d5c3:b0:168:f037:98d7 with SMTP id g3-20020a170902d5c300b00168f03798d7mr37421289plh.117.1655964914258; Wed, 22 Jun 2022 23:15:14 -0700 (PDT) Received: from FVFDK26JP3YV.bytedance.net ([139.177.225.234]) by smtp.gmail.com with ESMTPSA id y22-20020a17090264d600b0015e8d4eb1b6sm350992pli.0.2022.06.22.23.15.10 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2022 23:15:13 -0700 (PDT) From: Lei He To: davem@davemloft.net, herbert@gondor.apana.org.au, dhowells@redhat.com Cc: mst@redhat.com, linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, berrange@redhat.com, pizhenwei@bytedance.com, lei he Subject: [PATCH v2 1/4] crypto: fix the calculation of max_size for ECDSA Date: Thu, 23 Jun 2022 14:14:57 +0800 Message-Id: <20220623061500.78331-1-helei.sig11@bytedance.com> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org From: lei he The signature of ECDSA is consists of two big integers up to the size of keylen, and is DER encoded into one SEQUENCE. Calculate max_size of ECDSA signature more accurately according to the DER encoding rules. Signed-off-by: lei he --- crypto/Kconfig | 1 + crypto/Makefile | 2 ++ crypto/ecdsa.c | 3 ++- crypto/ecdsa_helper.c | 45 +++++++++++++++++++++++++++++++++ include/crypto/internal/ecdsa.h | 15 +++++++++++ include/linux/asn1_encoder.h | 2 ++ lib/asn1_encoder.c | 3 ++- 7 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 crypto/ecdsa_helper.c create mode 100644 include/crypto/internal/ecdsa.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 19197469cfab..3e82c7bc8424 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -254,6 +254,7 @@ config CRYPTO_ECDSA select CRYPTO_ECC select CRYPTO_AKCIPHER select ASN1 + select ASN1_ENCODER help Elliptic Curve Digital Signature Algorithm (NIST P192, P256 etc.) is A NIST cryptographic standard algorithm. Only signature verification diff --git a/crypto/Makefile b/crypto/Makefile index 43bc33e247d1..226bc2cfb9b7 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -52,8 +52,10 @@ obj-$(CONFIG_CRYPTO_SM2) += sm2_generic.o $(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h $(obj)/ecdsa.o: $(obj)/ecdsasignature.asn1.h + ecdsa_generic-y += ecdsa.o ecdsa_generic-y += ecdsasignature.asn1.o +ecdsa_generic-y += ecdsa_helper.o obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o crypto_acompress-y := acompress.o diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c index b3a8a6b572ba..2ba44c92d271 100644 --- a/crypto/ecdsa.c +++ b/crypto/ecdsa.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -262,7 +263,7 @@ static unsigned int ecdsa_max_size(struct crypto_akcipher *tfm) { struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); - return ctx->pub_key.ndigits << ECC_DIGITS_TO_BYTES_SHIFT; + return ecdsa_max_signature_size(ctx->curve); } static int ecdsa_nist_p384_init_tfm(struct crypto_akcipher *tfm) diff --git a/crypto/ecdsa_helper.c b/crypto/ecdsa_helper.c new file mode 100644 index 000000000000..487c4e9c0f67 --- /dev/null +++ b/crypto/ecdsa_helper.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * RSA key extract helper + * + * Copyright 2022 Bytedance CO., LTD. + * + * Authors: lei he + */ +#include +#include +#include +#include +#include +#include + +unsigned int ecdsa_max_signature_size(const struct ecc_curve *curve) +{ + unsigned int keylen = curve->g.ndigits * sizeof(u64); + /* Up to one extra byte to indicate the format */ + unsigned char buffer[sizeof(size_t) + 1], *data = buffer; + int buffer_len = sizeof(buffer); + unsigned int coordinate_length, sequence_length; + + asn1_encode_length(&data, &buffer_len, keylen); + /** + * The extra cost for encoding keylen bytes as INTEGER in ASN.1: + * 1. one byte for tag + * 2. sizeof(buffer) - buffer_len bytes for length + * 3. one leading zero byte for integers whose leftmost bit is 1 + */ + coordinate_length = 1 + sizeof(buffer) - buffer_len + 1 + keylen; + + /** + * The extra cost for encoding coordinate_length * 2 bytes as SEQUENCE in ASN.1: + * 1. one byte for tag + * 2. sizeof(buffer) - buffer_len bytes for length + */ + buffer_len = sizeof(buffer); + data = buffer; + asn1_encode_length(&data, &buffer_len, coordinate_length * 2); + sequence_length = 1 + sizeof(buffer) - buffer_len + coordinate_length * 2; + + return sequence_length; +} +EXPORT_SYMBOL_GPL(ecdsa_max_signature_size); diff --git a/include/crypto/internal/ecdsa.h b/include/crypto/internal/ecdsa.h new file mode 100644 index 000000000000..e35638a35dc2 --- /dev/null +++ b/include/crypto/internal/ecdsa.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * ECDSA internal helpers + * + * Copyright (c) 2022 lei he + */ + + #ifndef _CRYPTO_ECDSA_H + #define _CRYPTO_ECDSA_H + +#include + +unsigned int ecdsa_max_signature_size(const struct ecc_curve *curve); + +#endif diff --git a/include/linux/asn1_encoder.h b/include/linux/asn1_encoder.h index 08cd0c2ad34f..fe439c9a73e3 100644 --- a/include/linux/asn1_encoder.h +++ b/include/linux/asn1_encoder.h @@ -29,4 +29,6 @@ unsigned char * asn1_encode_boolean(unsigned char *data, const unsigned char *end_data, bool val); +int asn1_encode_length(unsigned char **data, int *data_len, int len); + #endif diff --git a/lib/asn1_encoder.c b/lib/asn1_encoder.c index 0fd3c454a468..644af3055ebb 100644 --- a/lib/asn1_encoder.c +++ b/lib/asn1_encoder.c @@ -188,7 +188,7 @@ EXPORT_SYMBOL_GPL(asn1_encode_oid); * encoder primitives to accept negative lengths as singalling the * sequence will be re-encoded when the length is known. */ -static int asn1_encode_length(unsigned char **data, int *data_len, int len) +int asn1_encode_length(unsigned char **data, int *data_len, int len) { if (*data_len < 1) return -EINVAL; @@ -239,6 +239,7 @@ static int asn1_encode_length(unsigned char **data, int *data_len, int len) return 0; } +EXPORT_SYMBOL_GPL(asn1_encode_length); /** * asn1_encode_tag() - add a tag for optional or explicit value