1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ==================================================================== 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the documentation and/or other materials provided with the 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * distribution. 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * software must display the following acknowledgment: 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * endorse or promote products derived from this software without 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * prior written permission. For written permission, please contact 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * openssl-core@OpenSSL.org. 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL" 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * nor may "OpenSSL" appear in their names without prior written 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * permission of the OpenSSL Project. 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * acknowledgment: 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ==================================================================== 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com). This product includes software written by Tim 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). */ 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ecdsa.h> 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h> 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "../ec/internal.h" 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig, 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unsigned int *sig_len, EC_KEY *eckey) { 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len, eckey); 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ECDSA_sign_ex(type, digest, digest_len, sig, sig_len, NULL, NULL, 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley eckey); 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ECDSA_verify(int type, const uint8_t *digest, size_t digest_len, 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *sig, size_t sig_len, EC_KEY *eckey) { 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_SIG *s; 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *der = NULL; 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) { 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return eckey->ecdsa_meth->verify(digest, digest_len, sig, sig_len, eckey); 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley s = ECDSA_SIG_new(); 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *sigp = sig; 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (s == NULL || d2i_ECDSA_SIG(&s, &sigp, sig_len) == NULL || 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sigp != sig + sig_len) { 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Ensure that the signature uses DER and doesn't have trailing garbage. */ 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const int der_len = i2d_ECDSA_SIG(s, &der); 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (der_len < 0 || (size_t) der_len != sig_len || memcmp(sig, der, sig_len)) { 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = ECDSA_do_verify(digest, digest_len, s, eckey); 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 100e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(der); 101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ECDSA_SIG_free(s); 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* digest_to_bn interprets |digest_len| bytes from |digest| as a big-endian 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * number and sets |out| to that value. It then truncates |out| so that it's, 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * at most, as long as |order|. It returns one on success and zero otherwise. */ 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int digest_to_bn(BIGNUM *out, const uint8_t *digest, size_t digest_len, 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *order) { 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t num_bits; 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num_bits = BN_num_bits(order); 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Need to truncate digest if it is too long: first truncate whole 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * bytes. */ 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (8 * digest_len > num_bits) { 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley digest_len = (num_bits + 7) / 8; 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_bin2bn(digest, digest_len, out)) { 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, digest_to_bn, ERR_R_BN_LIB); 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* If still too long truncate remaining bits with a shift */ 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((8 * digest_len > num_bits) && 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !BN_rshift(out, out, 8 - (num_bits & 0x7))) { 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, digest_to_bn, ERR_R_BN_LIB); 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 133d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len, 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_KEY *key) { 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ECDSA_do_sign_ex(digest, digest_len, NULL, NULL, key); 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ECDSA_do_verify(const uint8_t *digest, size_t digest_len, 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const ECDSA_SIG *sig, EC_KEY *eckey) { 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *ctx; 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *order, *u1, *u2, *m, *X; 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT *point = NULL; 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_GROUP *group; 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_POINT *pub_key; 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) { 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* check input values */ 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((group = EC_KEY_get0_group(eckey)) == NULL || 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sig == NULL) { 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_MISSING_PARAMETERS); 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = BN_CTX_new(); 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ctx) { 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_MALLOC_FAILURE); 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_start(ctx); 166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley order = BN_CTX_get(ctx); 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley u1 = BN_CTX_get(ctx); 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley u2 = BN_CTX_get(ctx); 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley m = BN_CTX_get(ctx); 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X = BN_CTX_get(ctx); 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!X) { 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB); 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_GROUP_get_order(group, order, ctx)) { 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_EC_LIB); 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_BAD_SIGNATURE); 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 0; /* signature is invalid */ 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* calculate tmp1 = inv(S) mod order */ 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_inverse(u2, sig->s, order, ctx)) { 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB); 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!digest_to_bn(m, digest, digest_len, order)) { 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* u1 = m * tmp mod order */ 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(u1, m, u2, order, ctx)) { 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB); 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* u2 = r * w mod q */ 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { 203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB); 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley point = EC_POINT_new(group); 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (point == NULL) { 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_MALLOC_FAILURE); 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_EC_LIB); 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_EC_LIB); 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_nnmod(u1, X, order, ctx)) { 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB); 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* if the signature is correct u1 is equal to sig->r */ 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = (BN_ucmp(u1, sig->r) == 0); 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 227d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_end(ctx); 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_free(ctx); 230e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EC_POINT_free(point); 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM **rp, const uint8_t *digest, 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t digest_len) { 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *ctx = NULL; 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; 239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT *tmp_point = NULL; 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_GROUP *group; 241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_PASSED_NULL_PARAMETER); 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx_in == NULL) { 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((ctx = BN_CTX_new()) == NULL) { 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_MALLOC_FAILURE); 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = ctx_in; 255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley k = BN_new(); /* this value is later returned in *kinvp */ 258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r = BN_new(); /* this value is later returned in *rp */ 259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley order = BN_new(); 260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X = BN_new(); 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!k || !r || !order || !X) { 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_MALLOC_FAILURE); 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley tmp_point = EC_POINT_new(group); 266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (tmp_point == NULL) { 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB); 268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_GROUP_get_order(group, order, ctx)) { 271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB); 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley do { 276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* If possible, we'll include the private key and message digest in the k 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is 278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * being used. */ 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley do { 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ok; 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (digest_len > 0) { 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey), 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley digest, digest_len, ctx); 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ok = BN_rand_range(k, order); 287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ok) { 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, 290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } while (BN_is_zero(k)); 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* We do not want timing information to leak the length of k, 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * so we compute G*k using an equivalent scalar of fixed 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * bit-length. */ 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_add(k, k, order)) { 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_num_bits(k) <= BN_num_bits(order)) { 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_add(k, k, order)) { 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* compute r the x-coordinate of generator * k */ 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB); 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB); 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_nnmod(r, X, order, ctx)) { 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_BN_LIB); 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } while (BN_is_zero(r)); 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* compute the inverse of k */ 325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_inverse(k, k, order, ctx)) { 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_BN_LIB); 327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* clear old values if necessary */ 330e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(*rp); 331e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(*kinvp); 332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* save the pre-computed values */ 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *rp = r; 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *kinvp = k; 336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 338d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret) { 340e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(k); 341e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(r); 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 343e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ctx_in == NULL) { 344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_free(ctx); 345e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 346e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_free(order); 347e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EC_POINT_free(tmp_point); 348e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(X); 349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 352d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp) { 353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0); 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 356d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len, 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *in_kinv, const BIGNUM *in_r, 358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_KEY *eckey) { 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ok = 0; 360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL; 361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *ckinv; 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *ctx = NULL; 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_GROUP *group; 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_SIG *ret; 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *priv_key; 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ECDSA_R_NOT_IMPLEMENTED); 369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley group = EC_KEY_get0_group(eckey); 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley priv_key = EC_KEY_get0_private_key(eckey); 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group == NULL || priv_key == NULL) { 376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_PASSED_NULL_PARAMETER); 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = ECDSA_SIG_new(); 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret) { 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_MALLOC_FAILURE); 383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley s = ret->s; 386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || 388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { 389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_MALLOC_FAILURE); 390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_GROUP_get_order(group, order, ctx)) { 394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_EC_LIB); 395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!digest_to_bn(m, digest, digest_len, order)) { 398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (;;) { 401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in_kinv == NULL || in_r == NULL) { 402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) { 403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_ECDSA_LIB); 404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ckinv = kinv; 407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ckinv = in_kinv; 409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_copy(ret->r, in_r) == NULL) { 410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_MALLOC_FAILURE); 411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { 416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_BN_LIB); 417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_add_quick(s, tmp, m, order)) { 420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_BN_LIB); 421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(s, s, ckinv, order, ctx)) { 424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_BN_LIB); 425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(s)) { 428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* if kinv and r have been supplied by the caller 429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * don't to generate new kinv and r values */ 430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in_kinv != NULL && in_r != NULL) { 431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ECDSA_R_NEED_NEW_SETUP_VALUES); 432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* s != 0 => we have a valid signature */ 436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley break; 437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ok = 1; 441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 442d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ok) { 444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_SIG_free(ret); 445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = NULL; 446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 447e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_CTX_free(ctx); 448e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(m); 449e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(tmp); 450e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_free(order); 451e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(kinv); 452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 455d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len, 456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv, 457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *r, EC_KEY *eckey) { 458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_SIG *s = NULL; 459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { 461d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_ex, ECDSA_R_NOT_IMPLEMENTED); 462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *sig_len = 0; 463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey); 467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (s == NULL) { 468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *sig_len = 0; 469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *sig_len = i2d_ECDSA_SIG(s, &sig); 472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_SIG_free(s); 473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 475