From patchwork Mon Mar 26 23:03:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 10308957 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2BB2C60353 for ; Mon, 26 Mar 2018 23:03:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2195127C05 for ; Mon, 26 Mar 2018 23:03:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 161742992F; Mon, 26 Mar 2018 23:03:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B1EA27C05 for ; Mon, 26 Mar 2018 23:03:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752210AbeCZXDd (ORCPT ); Mon, 26 Mar 2018 19:03:33 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:42761 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752077AbeCZXDd (ORCPT ); Mon, 26 Mar 2018 19:03:33 -0400 Received: by mail-pg0-f65.google.com with SMTP id f10so7690508pgs.9 for ; Mon, 26 Mar 2018 16:03:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition; bh=NBd/gYGc/Ey3aVVDNkLyHNsLx8HwRFl/m3s5cmEkhbw=; b=MZDiWSLNnbEepRNqsh1PdbXNzdQexQveJ5zewt/Bmm59U1uaWNDIY9b3TDZbd3zlpn hJquP3hNe2O0Y0piMItAdnHHaOjgJQDV19Q+PuXpBX+QsriWf0UQrrnVKKPve23dpANu 83kXzfNbaAF/75GCp1KAIvMjQdjRbQt93O5nk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition; bh=NBd/gYGc/Ey3aVVDNkLyHNsLx8HwRFl/m3s5cmEkhbw=; b=bvhSOgsybMZ5SXRa54PKBsc11nYGt9C9oHfS/xa+9w/4g9GLkzwWYBhuSuRa3yu/5D 9jmtW6BU7XftqOqCSWkzL41iEP3we9FIp9nA3UwcePsusN+t06OS0fiwFq7pIa3jpGfl nUv0kvQzww/2AZGjuEfVqC5Qpd2VxBNHBSd9WP2JKC/8ttdYPVaDs/H4dfuII/cdHST/ EFoO2ma0mUL746rhtRV9rZ3Y4fYMB/aHK3OBWwVt6LpANNDYBG3POdxaNBErIuFeoU45 2owJNUB4VI8+5c2We0KoELH873YlIr4rzr3n685LuJVUUNGzfD16k88EvBOVGkhZw7IA ypPA== X-Gm-Message-State: AElRT7FIOxQGNZOMbKRLB29fQBi8JYn6ZRYb6lgTcVXBloP2v1gz5Fum YokdRkmchtlYCGPj+wJxmCK06A== X-Google-Smtp-Source: AG47ELuE3KqALBRMm7EiaG0fSN3NgxYwdEOgk6UJo0zzAWJZq+15ztEcfP9YG4pkNo+th1mTF7mfWQ== X-Received: by 10.98.76.68 with SMTP id z65mr31306397pfa.181.1522105412453; Mon, 26 Mar 2018 16:03:32 -0700 (PDT) Received: from www.outflux.net (173-164-112-133-Oregon.hfc.comcastbusiness.net. [173.164.112.133]) by smtp.gmail.com with ESMTPSA id a28sm650522pgd.38.2018.03.26.16.03.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Mar 2018 16:03:31 -0700 (PDT) Date: Mon, 26 Mar 2018 16:03:30 -0700 From: Kees Cook To: Herbert Xu Cc: Tudor Ambarus , "David S. Miller" , linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3] crypto: ecc: Remove stack VLA usage Message-ID: <20180326230330.GA27127@beast> MIME-Version: 1.0 Content-Disposition: inline Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On the quest to remove all VLAs from the kernel[1], this avoids VLAs by just using the maximum allocation size (4 bytes) for stack arrays. All the VLAs in ecc were either 3 or 4 bytes (or a multiple), so just make it 4 bytes all the time. Initialization routines are adjusted to check that ndigits does not end up larger than the arrays. [1] https://lkml.org/lkml/2018/3/7/621 Signed-off-by: Kees Cook --- This expects 14de52112ee70ca289fa77bf2d9cbc79fd2c811f to be reverted. --- crypto/ecc.c | 47 ++++++++++++++++++++++++----------------------- crypto/ecc.h | 4 +++- crypto/ecdh.c | 4 ++-- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/crypto/ecc.c b/crypto/ecc.c index 18f32f2a5e1c..815541309a95 100644 --- a/crypto/ecc.c +++ b/crypto/ecc.c @@ -515,7 +515,7 @@ static void vli_mmod_fast_256(u64 *result, const u64 *product, static bool vli_mmod_fast(u64 *result, u64 *product, const u64 *curve_prime, unsigned int ndigits) { - u64 tmp[2 * ndigits]; + u64 tmp[2 * ECC_MAX_DIGITS]; switch (ndigits) { case 3: @@ -536,7 +536,7 @@ static bool vli_mmod_fast(u64 *result, u64 *product, static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right, const u64 *curve_prime, unsigned int ndigits) { - u64 product[2 * ndigits]; + u64 product[2 * ECC_MAX_DIGITS]; vli_mult(product, left, right, ndigits); vli_mmod_fast(result, product, curve_prime, ndigits); @@ -546,7 +546,7 @@ static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right, static void vli_mod_square_fast(u64 *result, const u64 *left, const u64 *curve_prime, unsigned int ndigits) { - u64 product[2 * ndigits]; + u64 product[2 * ECC_MAX_DIGITS]; vli_square(product, left, ndigits); vli_mmod_fast(result, product, curve_prime, ndigits); @@ -560,8 +560,8 @@ static void vli_mod_square_fast(u64 *result, const u64 *left, static void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod, unsigned int ndigits) { - u64 a[ndigits], b[ndigits]; - u64 u[ndigits], v[ndigits]; + u64 a[ECC_MAX_DIGITS], b[ECC_MAX_DIGITS]; + u64 u[ECC_MAX_DIGITS], v[ECC_MAX_DIGITS]; u64 carry; int cmp_result; @@ -649,8 +649,8 @@ static void ecc_point_double_jacobian(u64 *x1, u64 *y1, u64 *z1, u64 *curve_prime, unsigned int ndigits) { /* t1 = x, t2 = y, t3 = z */ - u64 t4[ndigits]; - u64 t5[ndigits]; + u64 t4[ECC_MAX_DIGITS]; + u64 t5[ECC_MAX_DIGITS]; if (vli_is_zero(z1, ndigits)) return; @@ -711,7 +711,7 @@ static void ecc_point_double_jacobian(u64 *x1, u64 *y1, u64 *z1, static void apply_z(u64 *x1, u64 *y1, u64 *z, u64 *curve_prime, unsigned int ndigits) { - u64 t1[ndigits]; + u64 t1[ECC_MAX_DIGITS]; vli_mod_square_fast(t1, z, curve_prime, ndigits); /* z^2 */ vli_mod_mult_fast(x1, x1, t1, curve_prime, ndigits); /* x1 * z^2 */ @@ -724,7 +724,7 @@ static void xycz_initial_double(u64 *x1, u64 *y1, u64 *x2, u64 *y2, u64 *p_initial_z, u64 *curve_prime, unsigned int ndigits) { - u64 z[ndigits]; + u64 z[ECC_MAX_DIGITS]; vli_set(x2, x1, ndigits); vli_set(y2, y1, ndigits); @@ -750,7 +750,7 @@ static void xycz_add(u64 *x1, u64 *y1, u64 *x2, u64 *y2, u64 *curve_prime, unsigned int ndigits) { /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - u64 t5[ndigits]; + u64 t5[ECC_MAX_DIGITS]; /* t5 = x2 - x1 */ vli_mod_sub(t5, x2, x1, curve_prime, ndigits); @@ -791,9 +791,9 @@ static void xycz_add_c(u64 *x1, u64 *y1, u64 *x2, u64 *y2, u64 *curve_prime, unsigned int ndigits) { /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - u64 t5[ndigits]; - u64 t6[ndigits]; - u64 t7[ndigits]; + u64 t5[ECC_MAX_DIGITS]; + u64 t6[ECC_MAX_DIGITS]; + u64 t7[ECC_MAX_DIGITS]; /* t5 = x2 - x1 */ vli_mod_sub(t5, x2, x1, curve_prime, ndigits); @@ -846,9 +846,9 @@ static void ecc_point_mult(struct ecc_point *result, unsigned int ndigits) { /* R0 and R1 */ - u64 rx[2][ndigits]; - u64 ry[2][ndigits]; - u64 z[ndigits]; + u64 rx[2][ECC_MAX_DIGITS]; + u64 ry[2][ECC_MAX_DIGITS]; + u64 z[ECC_MAX_DIGITS]; int i, nb; int num_bits = vli_num_bits(scalar, ndigits); @@ -943,13 +943,13 @@ int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits, int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey) { const struct ecc_curve *curve = ecc_get_curve(curve_id); - u64 priv[ndigits]; + u64 priv[ECC_MAX_DIGITS]; unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT; unsigned int nbits = vli_num_bits(curve->n, ndigits); int err; /* Check that N is included in Table 1 of FIPS 186-4, section 6.1.1 */ - if (nbits < 160) + if (nbits < 160 || ndigits > ARRAY_SIZE(priv)) return -EINVAL; /* @@ -988,10 +988,10 @@ int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits, { int ret = 0; struct ecc_point *pk; - u64 priv[ndigits]; + u64 priv[ECC_MAX_DIGITS]; const struct ecc_curve *curve = ecc_get_curve(curve_id); - if (!private_key || !curve) { + if (!private_key || !curve || ndigits > ARRAY_SIZE(priv)) { ret = -EINVAL; goto out; } @@ -1025,12 +1025,13 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits, { int ret = 0; struct ecc_point *product, *pk; - u64 priv[ndigits]; - u64 rand_z[ndigits]; + u64 priv[ECC_MAX_DIGITS]; + u64 rand_z[ECC_MAX_DIGITS]; unsigned int nbytes; const struct ecc_curve *curve = ecc_get_curve(curve_id); - if (!private_key || !public_key || !curve) { + if (!private_key || !public_key || !curve || + ndigits > ARRAY_SIZE(priv) || ndigits > ARRAY_SIZE(rand_z)) { ret = -EINVAL; goto out; } diff --git a/crypto/ecc.h b/crypto/ecc.h index e4fd4492c765..f75a86baa3bd 100644 --- a/crypto/ecc.h +++ b/crypto/ecc.h @@ -26,7 +26,9 @@ #ifndef _CRYPTO_ECC_H #define _CRYPTO_ECC_H -#define ECC_MAX_DIGITS 4 /* 256 */ +#define ECC_CURVE_NIST_P192_DIGITS 3 +#define ECC_CURVE_NIST_P256_DIGITS 4 +#define ECC_MAX_DIGITS ECC_CURVE_NIST_P256_DIGITS #define ECC_DIGITS_TO_BYTES_SHIFT 3 diff --git a/crypto/ecdh.c b/crypto/ecdh.c index 3aca0933ec44..3f91ef13c8c6 100644 --- a/crypto/ecdh.c +++ b/crypto/ecdh.c @@ -30,8 +30,8 @@ static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm) static unsigned int ecdh_supported_curve(unsigned int curve_id) { switch (curve_id) { - case ECC_CURVE_NIST_P192: return 3; - case ECC_CURVE_NIST_P256: return 4; + case ECC_CURVE_NIST_P192: return ECC_CURVE_NIST_P192_DIGITS; + case ECC_CURVE_NIST_P256: return ECC_CURVE_NIST_P256_DIGITS; default: return 0; } }