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 55b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <assert.h> 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h> 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 6269939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan#include "../bn/internal.h" 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "../ec/internal.h" 648ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include "../../internal.h" 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* digest_to_bn interprets |digest_len| bytes from |digest| as a big-endian 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * number and sets |out| to that value. It then truncates |out| so that it's, 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * at most, as long as |order|. It returns one on success and zero otherwise. */ 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int digest_to_bn(BIGNUM *out, const uint8_t *digest, size_t digest_len, 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *order) { 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t num_bits; 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num_bits = BN_num_bits(order); 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Need to truncate digest if it is too long: first truncate whole 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * bytes. */ 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (8 * digest_len > num_bits) { 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley digest_len = (num_bits + 7) / 8; 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_bin2bn(digest, digest_len, out)) { 81b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* If still too long truncate remaining bits with a shift */ 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((8 * digest_len > num_bits) && 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !BN_rshift(out, out, 8 - (num_bits & 0x7))) { 88b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 958ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert SloanECDSA_SIG *ECDSA_SIG_new(void) { 968ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG)); 978ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan if (sig == NULL) { 988ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan return NULL; 998ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan } 1008ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan sig->r = BN_new(); 1018ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan sig->s = BN_new(); 1028ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan if (sig->r == NULL || sig->s == NULL) { 1038ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ECDSA_SIG_free(sig); 1048ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan return NULL; 1058ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan } 1068ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan return sig; 1078ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan} 1088ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan 1098ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloanvoid ECDSA_SIG_free(ECDSA_SIG *sig) { 1108ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan if (sig == NULL) { 1118ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan return; 1128ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan } 1138ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan 1148ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan BN_free(sig->r); 1158ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan BN_free(sig->s); 1168ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan OPENSSL_free(sig); 1178ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan} 1188ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan 119d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len, 120a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan const EC_KEY *key) { 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ECDSA_do_sign_ex(digest, digest_len, NULL, NULL, key); 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ECDSA_do_verify(const uint8_t *digest, size_t digest_len, 125a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan const ECDSA_SIG *sig, const EC_KEY *eckey) { 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *ctx; 1284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley BIGNUM *u1, *u2, *m, *X; 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT *point = NULL; 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_GROUP *group; 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_POINT *pub_key; 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* check input values */ 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((group = EC_KEY_get0_group(eckey)) == NULL || 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sig == NULL) { 137b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_MISSING_PARAMETERS); 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = BN_CTX_new(); 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ctx) { 143b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_start(ctx); 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley u1 = BN_CTX_get(ctx); 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley u2 = BN_CTX_get(ctx); 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley m = BN_CTX_get(ctx); 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X = BN_CTX_get(ctx); 1514139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (u1 == NULL || u2 == NULL || m == NULL || X == NULL) { 152b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1564139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley const BIGNUM *order = EC_GROUP_get0_order(group); 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { 160b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* calculate tmp1 = inv(S) mod order */ 164c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin int no_inverse; 165c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if (!BN_mod_inverse_odd(u2, &no_inverse, sig->s, order, ctx)) { 166b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!digest_to_bn(m, digest, digest_len, order)) { 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* u1 = m * tmp mod order */ 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(u1, m, u2, order, ctx)) { 174b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* u2 = r * w mod q */ 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { 179b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley point = EC_POINT_new(group); 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (point == NULL) { 185b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { 189b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { 193b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_nnmod(u1, X, order, ctx)) { 197b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* if the signature is correct u1 is equal to sig->r */ 2012424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan if (BN_ucmp(u1, sig->r) != 0) { 2022424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); 2032424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan goto err; 2042424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan } 2052424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan 2062424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan ret = 1; 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 2094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin BN_CTX_end(ctx); 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_free(ctx); 211e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EC_POINT_free(point); 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 215a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloanstatic int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM **rp, const uint8_t *digest, 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t digest_len) { 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *ctx = NULL; 219572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan BIGNUM *k = NULL, *kinv = NULL, *r = NULL, *tmp = NULL; 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT *tmp_point = NULL; 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_GROUP *group; 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { 225b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx_in == NULL) { 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((ctx = BN_CTX_new()) == NULL) { 231b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = ctx_in; 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 238572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan k = BN_new(); 239572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan kinv = BN_new(); /* this value is later returned in *kinvp */ 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r = BN_new(); /* this value is later returned in *rp */ 241c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin tmp = BN_new(); 242572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan if (k == NULL || kinv == NULL || r == NULL || tmp == NULL) { 243b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley tmp_point = EC_POINT_new(group); 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (tmp_point == NULL) { 248b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 2514139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley 2524139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley const BIGNUM *order = EC_GROUP_get0_order(group); 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 254572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan /* Check that the size of the group order is FIPS compliant (FIPS 186-4 255572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan * B.5.2). */ 256572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan if (BN_num_bits(order) < 160) { 257572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan OPENSSL_PUT_ERROR(ECDSA, EC_R_INVALID_GROUP_ORDER); 258572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan goto err; 259572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan } 260572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley do { 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* If possible, we'll include the private key and message digest in the k 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * being used. */ 2658ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan if (eckey->fixed_k != NULL) { 2668ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan if (!BN_copy(k, eckey->fixed_k)) { 2678ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan goto err; 2688ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan } 2698ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan } else if (digest_len > 0) { 270c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin do { 271c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if (!BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey), 272c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin digest, digest_len, ctx)) { 273c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); 274c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin goto err; 275c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 276c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } while (BN_is_zero(k)); 277c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } else if (!BN_rand_range_ex(k, 1, order)) { 278c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); 279c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin goto err; 280c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin } 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 282572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan /* Compute the inverse of k. The order is a prime, so use Fermat's Little 283572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan * Theorem. Note |ec_group_get_mont_data| may return NULL but 284572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan * |bn_mod_inverse_prime| allows this. */ 285572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan if (!bn_mod_inverse_prime(kinv, k, order, ctx, 286572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan ec_group_get_mont_data(group))) { 287572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 288572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan goto err; 289572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan } 290572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* We do not want timing information to leak the length of k, 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * so we compute G*k using an equivalent scalar of fixed 293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * bit-length. */ 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_add(k, k, order)) { 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_num_bits(k) <= BN_num_bits(order)) { 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_add(k, k, order)) { 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* compute r the x-coordinate of generator * k */ 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { 306b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 309c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, tmp, NULL, 310c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin ctx)) { 311b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 315c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin if (!BN_nnmod(r, tmp, order, ctx)) { 316b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } while (BN_is_zero(r)); 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* clear old values if necessary */ 322e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(*rp); 323e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(*kinvp); 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* save the pre-computed values */ 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *rp = r; 327572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan *kinvp = kinv; 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 331572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan BN_clear_free(k); 332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret) { 333572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan BN_clear_free(kinv); 334e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(r); 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 336e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ctx_in == NULL) { 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_free(ctx); 338e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 339e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EC_POINT_free(tmp_point); 340c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin BN_clear_free(tmp); 341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 344a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloanint ECDSA_sign_setup(const EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, 345a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan BIGNUM **rp) { 346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0); 347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 349d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len, 350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *in_kinv, const BIGNUM *in_r, 351a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan const EC_KEY *eckey) { 352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ok = 0; 3534139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL; 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *ckinv; 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *ctx = NULL; 356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_GROUP *group; 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_SIG *ret; 358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const BIGNUM *priv_key; 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) { 361b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED); 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley group = EC_KEY_get0_group(eckey); 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley priv_key = EC_KEY_get0_private_key(eckey); 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group == NULL || priv_key == NULL) { 369b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = ECDSA_SIG_new(); 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret) { 375b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); 376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley s = ret->s; 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 3804139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if ((ctx = BN_CTX_new()) == NULL || 3814139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley (tmp = BN_new()) == NULL || 3824139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley (m = BN_new()) == NULL) { 383b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); 384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 3874139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley const BIGNUM *order = EC_GROUP_get0_order(group); 3884139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley 389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!digest_to_bn(m, digest, digest_len, order)) { 390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (;;) { 393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in_kinv == NULL || in_r == NULL) { 394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) { 395b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_ECDSA_LIB); 396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ckinv = kinv; 399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ckinv = in_kinv; 401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_copy(ret->r, in_r) == NULL) { 402b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); 403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { 408b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_add_quick(s, tmp, m, order)) { 412b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_mul(s, s, ckinv, order, ctx)) { 416b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); 417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(s)) { 420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* if kinv and r have been supplied by the caller 421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * don't to generate new kinv and r values */ 422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in_kinv != NULL && in_r != NULL) { 423b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NEED_NEW_SETUP_VALUES); 424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* s != 0 => we have a valid signature */ 428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley break; 429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ok = 1; 433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 434d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ok) { 436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ECDSA_SIG_free(ret); 437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = NULL; 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 439e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_CTX_free(ctx); 440e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(m); 441e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(tmp); 442e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_clear_free(kinv); 443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 445