X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fec%2Fecdsa_ossl.c;h=a405d38b69eaea81aae080c234f7bedc1a46f70b;hp=b4e37adccefb7f7c582a6794e66b331be7de5bcf;hb=eb7916960bf50f436593abe3d5f2e0592d291017;hpb=349807608f31b20af01a342d0072bb92e0b036e2 diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c index b4e37adcce..a405d38b69 100644 --- a/crypto/ec/ecdsa_ossl.c +++ b/crypto/ec/ecdsa_ossl.c @@ -1,58 +1,10 @@ /* - * Written by Nils Larsch for the OpenSSL project - */ -/* ==================================================================== - * Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2002-2017 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include @@ -68,7 +20,7 @@ int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) { ECDSA_SIG *s; - RAND_seed(dgst, dlen); + s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); if (s == NULL) { *siglen = 0; @@ -84,16 +36,23 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, const unsigned char *dgst, int dlen) { BN_CTX *ctx = NULL; - BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; + BIGNUM *k = NULL, *r = NULL, *X = NULL; + const BIGNUM *order; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; + int order_bits; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } + if (!EC_KEY_can_sign(eckey)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return 0; + } + if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); @@ -104,9 +63,8 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ - order = BN_new(); X = BN_new(); - if (k == NULL || r == NULL || order == NULL || X == NULL) { + if (k == NULL || r == NULL || X == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } @@ -114,11 +72,19 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } - if (!EC_GROUP_get_order(group, order, ctx)) { + order = EC_GROUP_get0_order(group); + if (order == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } + /* Preallocate space */ + order_bits = BN_num_bits(order); + if (!BN_set_bit(k, order_bits) + || !BN_set_bit(r, order_bits) + || !BN_set_bit(X, order_bits)) + goto err; + do { /* get random k */ do @@ -131,7 +97,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, goto err; } } else { - if (!BN_rand_range(k, order)) { + if (!BN_priv_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; @@ -142,13 +108,19 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, /* * We do not want timing information to leak the length of k, so we * compute G*k using an equivalent scalar of fixed bit-length. + * + * We unconditionally perform both of these additions to prevent a + * small timing information leakage. We then choose the sum that is + * one bit longer than the order. This guarantees the code + * path used in the constant time implementations elsewhere. + * + * TODO: revisit the BN_copy aiming for a memory access agnostic + * conditional copy. */ - - if (!BN_add(k, k, order)) + if (!BN_add(r, k, order) + || !BN_add(X, r, order) + || !BN_copy(k, BN_num_bits(r) > order_bits ? r : X)) goto err; - if (BN_num_bits(k) <= BN_num_bits(order)) - if (!BN_add(k, k, order)) - goto err; /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { @@ -181,30 +153,33 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, } while (BN_is_zero(r)); - /* compute the inverse of k */ - if (EC_GROUP_get_mont_data(group) != NULL) { - /* - * We want inverse in constant time, therefore we utilize the fact - * order must be prime and use Fermats Little Theorem instead. - */ - if (!BN_set_word(X, 2)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); - goto err; - } - if (!BN_mod_sub(X, order, X, order, ctx)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); - goto err; - } - BN_set_flags(X, BN_FLG_CONSTTIME); - if (!BN_mod_exp_mont_consttime - (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); - goto err; - } - } else { - if (!BN_mod_inverse(k, k, order, ctx)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); - goto err; + /* Check if optimized inverse is implemented */ + if (EC_GROUP_do_inverse_ord(group, k, k, ctx) == 0) { + /* compute the inverse of k */ + if (group->mont_data != NULL) { + /* + * We want inverse in constant time, therefore we utilize the fact + * order must be prime and use Fermats Little Theorem instead. + */ + if (!BN_set_word(X, 2)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + goto err; + } + if (!BN_mod_sub(X, order, X, order, ctx)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + goto err; + } + BN_set_flags(X, BN_FLG_CONSTTIME); + if (!BN_mod_exp_mont_consttime(k, k, X, order, ctx, + group->mont_data)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + goto err; + } + } else { + if (!BN_mod_inverse(k, k, order, ctx)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + goto err; + } } } @@ -222,10 +197,9 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, } if (ctx != ctx_in) BN_CTX_free(ctx); - BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); - return (ret); + return ret; } int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, @@ -239,8 +213,8 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, EC_KEY *eckey) { int ok = 0, i; - BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL; - const BIGNUM *ckinv; + BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL; + const BIGNUM *order, *ckinv; BN_CTX *ctx = NULL; const EC_GROUP *group; ECDSA_SIG *ret; @@ -254,20 +228,32 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, return NULL; } + if (!EC_KEY_can_sign(eckey)) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return NULL; + } + ret = ECDSA_SIG_new(); if (ret == NULL) { ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); return NULL; } + ret->r = BN_new(); + ret->s = BN_new(); + if (ret->r == NULL || ret->s == NULL) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + goto err; + } s = ret->s; - if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || + if ((ctx = BN_CTX_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); goto err; } - if (!EC_GROUP_get_order(group, order, ctx)) { + order = EC_GROUP_get0_order(group); + if (order == NULL) { ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_EC_LIB); goto err; } @@ -315,7 +301,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, } if (BN_is_zero(s)) { /* - * if kinv and r have been supplied by the caller don't to + * if kinv and r have been supplied by the caller, don't * generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { @@ -337,7 +323,6 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, BN_CTX_free(ctx); BN_clear_free(m); BN_clear_free(tmp); - BN_free(order); BN_clear_free(kinv); return ret; } @@ -359,7 +344,7 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, s = ECDSA_SIG_new(); if (s == NULL) - return (ret); + return ret; if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) goto err; /* Ensure signature uses DER and doesn't have trailing garbage */ @@ -370,7 +355,7 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, err: OPENSSL_clear_free(der, derlen); ECDSA_SIG_free(s); - return (ret); + return ret; } int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, @@ -378,7 +363,8 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, { int ret = -1, i; BN_CTX *ctx; - BIGNUM *order, *u1, *u2, *m, *X; + const BIGNUM *order; + BIGNUM *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; @@ -390,13 +376,17 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, return -1; } + if (!EC_KEY_can_sign(eckey)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return -1; + } + ctx = BN_CTX_new(); if (ctx == NULL) { ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); - order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); @@ -406,7 +396,8 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, goto err; } - if (!EC_GROUP_get_order(group, order, ctx)) { + order = EC_GROUP_get0_order(group); + if (order == NULL) { ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); goto err; } @@ -419,9 +410,12 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, goto err; } /* calculate tmp1 = inv(S) mod order */ - if (!BN_mod_inverse(u2, sig->s, order, ctx)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); - goto err; + /* Check if optimized inverse is implemented */ + if (EC_GROUP_do_inverse_ord(group, u2, sig->s, ctx) == 0) { + if (!BN_mod_inverse(u2, sig->s, order, ctx)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } } /* digest -> m */ i = BN_num_bits(order);