11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
31cb0ef41Sopenharmony_ci * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
41cb0ef41Sopenharmony_ci *
51cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
61cb0ef41Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
71cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at
81cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html
91cb0ef41Sopenharmony_ci */
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci/*
121cb0ef41Sopenharmony_ci * EC_KEY low level APIs are deprecated for public use, but still ok for
131cb0ef41Sopenharmony_ci * internal use.
141cb0ef41Sopenharmony_ci */
151cb0ef41Sopenharmony_ci#include "internal/deprecated.h"
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci#include "internal/cryptlib.h"
181cb0ef41Sopenharmony_ci#include <string.h>
191cb0ef41Sopenharmony_ci#include "ec_local.h"
201cb0ef41Sopenharmony_ci#include "internal/refcount.h"
211cb0ef41Sopenharmony_ci#include <openssl/err.h>
221cb0ef41Sopenharmony_ci#ifndef FIPS_MODULE
231cb0ef41Sopenharmony_ci# include <openssl/engine.h>
241cb0ef41Sopenharmony_ci#endif
251cb0ef41Sopenharmony_ci#include <openssl/self_test.h>
261cb0ef41Sopenharmony_ci#include "prov/providercommon.h"
271cb0ef41Sopenharmony_ci#include "crypto/bn.h"
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cistatic int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
301cb0ef41Sopenharmony_ci                                      void *cbarg);
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#ifndef FIPS_MODULE
331cb0ef41Sopenharmony_ciEC_KEY *EC_KEY_new(void)
341cb0ef41Sopenharmony_ci{
351cb0ef41Sopenharmony_ci    return ossl_ec_key_new_method_int(NULL, NULL, NULL);
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci#endif
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciEC_KEY *EC_KEY_new_ex(OSSL_LIB_CTX *ctx, const char *propq)
401cb0ef41Sopenharmony_ci{
411cb0ef41Sopenharmony_ci    return ossl_ec_key_new_method_int(ctx, propq, NULL);
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciEC_KEY *EC_KEY_new_by_curve_name_ex(OSSL_LIB_CTX *ctx, const char *propq,
451cb0ef41Sopenharmony_ci                                    int nid)
461cb0ef41Sopenharmony_ci{
471cb0ef41Sopenharmony_ci    EC_KEY *ret = EC_KEY_new_ex(ctx, propq);
481cb0ef41Sopenharmony_ci    if (ret == NULL)
491cb0ef41Sopenharmony_ci        return NULL;
501cb0ef41Sopenharmony_ci    ret->group = EC_GROUP_new_by_curve_name_ex(ctx, propq, nid);
511cb0ef41Sopenharmony_ci    if (ret->group == NULL) {
521cb0ef41Sopenharmony_ci        EC_KEY_free(ret);
531cb0ef41Sopenharmony_ci        return NULL;
541cb0ef41Sopenharmony_ci    }
551cb0ef41Sopenharmony_ci    if (ret->meth->set_group != NULL
561cb0ef41Sopenharmony_ci        && ret->meth->set_group(ret, ret->group) == 0) {
571cb0ef41Sopenharmony_ci        EC_KEY_free(ret);
581cb0ef41Sopenharmony_ci        return NULL;
591cb0ef41Sopenharmony_ci    }
601cb0ef41Sopenharmony_ci    return ret;
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci#ifndef FIPS_MODULE
641cb0ef41Sopenharmony_ciEC_KEY *EC_KEY_new_by_curve_name(int nid)
651cb0ef41Sopenharmony_ci{
661cb0ef41Sopenharmony_ci    return EC_KEY_new_by_curve_name_ex(NULL, NULL, nid);
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci#endif
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_civoid EC_KEY_free(EC_KEY *r)
711cb0ef41Sopenharmony_ci{
721cb0ef41Sopenharmony_ci    int i;
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci    if (r == NULL)
751cb0ef41Sopenharmony_ci        return;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci    CRYPTO_DOWN_REF(&r->references, &i, r->lock);
781cb0ef41Sopenharmony_ci    REF_PRINT_COUNT("EC_KEY", r);
791cb0ef41Sopenharmony_ci    if (i > 0)
801cb0ef41Sopenharmony_ci        return;
811cb0ef41Sopenharmony_ci    REF_ASSERT_ISNT(i < 0);
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci    if (r->meth != NULL && r->meth->finish != NULL)
841cb0ef41Sopenharmony_ci        r->meth->finish(r);
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
871cb0ef41Sopenharmony_ci    ENGINE_finish(r->engine);
881cb0ef41Sopenharmony_ci#endif
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci    if (r->group && r->group->meth->keyfinish)
911cb0ef41Sopenharmony_ci        r->group->meth->keyfinish(r);
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci#ifndef FIPS_MODULE
941cb0ef41Sopenharmony_ci    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
951cb0ef41Sopenharmony_ci#endif
961cb0ef41Sopenharmony_ci    CRYPTO_THREAD_lock_free(r->lock);
971cb0ef41Sopenharmony_ci    EC_GROUP_free(r->group);
981cb0ef41Sopenharmony_ci    EC_POINT_free(r->pub_key);
991cb0ef41Sopenharmony_ci    BN_clear_free(r->priv_key);
1001cb0ef41Sopenharmony_ci    OPENSSL_free(r->propq);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci    OPENSSL_clear_free((void *)r, sizeof(EC_KEY));
1031cb0ef41Sopenharmony_ci}
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ciEC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
1061cb0ef41Sopenharmony_ci{
1071cb0ef41Sopenharmony_ci    if (dest == NULL || src == NULL) {
1081cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
1091cb0ef41Sopenharmony_ci        return NULL;
1101cb0ef41Sopenharmony_ci    }
1111cb0ef41Sopenharmony_ci    if (src->meth != dest->meth) {
1121cb0ef41Sopenharmony_ci        if (dest->meth->finish != NULL)
1131cb0ef41Sopenharmony_ci            dest->meth->finish(dest);
1141cb0ef41Sopenharmony_ci        if (dest->group && dest->group->meth->keyfinish)
1151cb0ef41Sopenharmony_ci            dest->group->meth->keyfinish(dest);
1161cb0ef41Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
1171cb0ef41Sopenharmony_ci        if (ENGINE_finish(dest->engine) == 0)
1181cb0ef41Sopenharmony_ci            return 0;
1191cb0ef41Sopenharmony_ci        dest->engine = NULL;
1201cb0ef41Sopenharmony_ci#endif
1211cb0ef41Sopenharmony_ci    }
1221cb0ef41Sopenharmony_ci    dest->libctx = src->libctx;
1231cb0ef41Sopenharmony_ci    /* copy the parameters */
1241cb0ef41Sopenharmony_ci    if (src->group != NULL) {
1251cb0ef41Sopenharmony_ci        /* clear the old group */
1261cb0ef41Sopenharmony_ci        EC_GROUP_free(dest->group);
1271cb0ef41Sopenharmony_ci        dest->group = ossl_ec_group_new_ex(src->libctx, src->propq,
1281cb0ef41Sopenharmony_ci                                           src->group->meth);
1291cb0ef41Sopenharmony_ci        if (dest->group == NULL)
1301cb0ef41Sopenharmony_ci            return NULL;
1311cb0ef41Sopenharmony_ci        if (!EC_GROUP_copy(dest->group, src->group))
1321cb0ef41Sopenharmony_ci            return NULL;
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci        /*  copy the public key */
1351cb0ef41Sopenharmony_ci        if (src->pub_key != NULL) {
1361cb0ef41Sopenharmony_ci            EC_POINT_free(dest->pub_key);
1371cb0ef41Sopenharmony_ci            dest->pub_key = EC_POINT_new(src->group);
1381cb0ef41Sopenharmony_ci            if (dest->pub_key == NULL)
1391cb0ef41Sopenharmony_ci                return NULL;
1401cb0ef41Sopenharmony_ci            if (!EC_POINT_copy(dest->pub_key, src->pub_key))
1411cb0ef41Sopenharmony_ci                return NULL;
1421cb0ef41Sopenharmony_ci        }
1431cb0ef41Sopenharmony_ci        /* copy the private key */
1441cb0ef41Sopenharmony_ci        if (src->priv_key != NULL) {
1451cb0ef41Sopenharmony_ci            if (dest->priv_key == NULL) {
1461cb0ef41Sopenharmony_ci                dest->priv_key = BN_new();
1471cb0ef41Sopenharmony_ci                if (dest->priv_key == NULL)
1481cb0ef41Sopenharmony_ci                    return NULL;
1491cb0ef41Sopenharmony_ci            }
1501cb0ef41Sopenharmony_ci            if (!BN_copy(dest->priv_key, src->priv_key))
1511cb0ef41Sopenharmony_ci                return NULL;
1521cb0ef41Sopenharmony_ci            if (src->group->meth->keycopy
1531cb0ef41Sopenharmony_ci                && src->group->meth->keycopy(dest, src) == 0)
1541cb0ef41Sopenharmony_ci                return NULL;
1551cb0ef41Sopenharmony_ci        }
1561cb0ef41Sopenharmony_ci    }
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci    /* copy the rest */
1601cb0ef41Sopenharmony_ci    dest->enc_flag = src->enc_flag;
1611cb0ef41Sopenharmony_ci    dest->conv_form = src->conv_form;
1621cb0ef41Sopenharmony_ci    dest->version = src->version;
1631cb0ef41Sopenharmony_ci    dest->flags = src->flags;
1641cb0ef41Sopenharmony_ci#ifndef FIPS_MODULE
1651cb0ef41Sopenharmony_ci    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
1661cb0ef41Sopenharmony_ci                            &dest->ex_data, &src->ex_data))
1671cb0ef41Sopenharmony_ci        return NULL;
1681cb0ef41Sopenharmony_ci#endif
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci    if (src->meth != dest->meth) {
1711cb0ef41Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
1721cb0ef41Sopenharmony_ci        if (src->engine != NULL && ENGINE_init(src->engine) == 0)
1731cb0ef41Sopenharmony_ci            return NULL;
1741cb0ef41Sopenharmony_ci        dest->engine = src->engine;
1751cb0ef41Sopenharmony_ci#endif
1761cb0ef41Sopenharmony_ci        dest->meth = src->meth;
1771cb0ef41Sopenharmony_ci    }
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci    if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0)
1801cb0ef41Sopenharmony_ci        return NULL;
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci    dest->dirty_cnt++;
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci    return dest;
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ciEC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
1881cb0ef41Sopenharmony_ci{
1891cb0ef41Sopenharmony_ci    return ossl_ec_key_dup(ec_key, OSSL_KEYMGMT_SELECT_ALL);
1901cb0ef41Sopenharmony_ci}
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ciint EC_KEY_up_ref(EC_KEY *r)
1931cb0ef41Sopenharmony_ci{
1941cb0ef41Sopenharmony_ci    int i;
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci    if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0)
1971cb0ef41Sopenharmony_ci        return 0;
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci    REF_PRINT_COUNT("EC_KEY", r);
2001cb0ef41Sopenharmony_ci    REF_ASSERT_ISNT(i < 2);
2011cb0ef41Sopenharmony_ci    return ((i > 1) ? 1 : 0);
2021cb0ef41Sopenharmony_ci}
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ciENGINE *EC_KEY_get0_engine(const EC_KEY *eckey)
2051cb0ef41Sopenharmony_ci{
2061cb0ef41Sopenharmony_ci    return eckey->engine;
2071cb0ef41Sopenharmony_ci}
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ciint EC_KEY_generate_key(EC_KEY *eckey)
2101cb0ef41Sopenharmony_ci{
2111cb0ef41Sopenharmony_ci    if (eckey == NULL || eckey->group == NULL) {
2121cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
2131cb0ef41Sopenharmony_ci        return 0;
2141cb0ef41Sopenharmony_ci    }
2151cb0ef41Sopenharmony_ci    if (eckey->meth->keygen != NULL) {
2161cb0ef41Sopenharmony_ci        int ret;
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci        ret = eckey->meth->keygen(eckey);
2191cb0ef41Sopenharmony_ci        if (ret == 1)
2201cb0ef41Sopenharmony_ci            eckey->dirty_cnt++;
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci        return ret;
2231cb0ef41Sopenharmony_ci    }
2241cb0ef41Sopenharmony_ci    ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED);
2251cb0ef41Sopenharmony_ci    return 0;
2261cb0ef41Sopenharmony_ci}
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ciint ossl_ec_key_gen(EC_KEY *eckey)
2291cb0ef41Sopenharmony_ci{
2301cb0ef41Sopenharmony_ci    int ret;
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci    ret = eckey->group->meth->keygen(eckey);
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci    if (ret == 1)
2351cb0ef41Sopenharmony_ci        eckey->dirty_cnt++;
2361cb0ef41Sopenharmony_ci    return ret;
2371cb0ef41Sopenharmony_ci}
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci/*
2401cb0ef41Sopenharmony_ci * ECC Key generation.
2411cb0ef41Sopenharmony_ci * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates"
2421cb0ef41Sopenharmony_ci *
2431cb0ef41Sopenharmony_ci * Params:
2441cb0ef41Sopenharmony_ci *     libctx A context containing an optional self test callback.
2451cb0ef41Sopenharmony_ci *     eckey An EC key object that contains domain params. The generated keypair
2461cb0ef41Sopenharmony_ci *           is stored in this object.
2471cb0ef41Sopenharmony_ci *     pairwise_test Set to non zero to perform a pairwise test. If the test
2481cb0ef41Sopenharmony_ci *                   fails then the keypair is not generated,
2491cb0ef41Sopenharmony_ci * Returns 1 if the keypair was generated or 0 otherwise.
2501cb0ef41Sopenharmony_ci */
2511cb0ef41Sopenharmony_cistatic int ec_generate_key(EC_KEY *eckey, int pairwise_test)
2521cb0ef41Sopenharmony_ci{
2531cb0ef41Sopenharmony_ci    int ok = 0;
2541cb0ef41Sopenharmony_ci    BIGNUM *priv_key = NULL;
2551cb0ef41Sopenharmony_ci    const BIGNUM *tmp = NULL;
2561cb0ef41Sopenharmony_ci    BIGNUM *order = NULL;
2571cb0ef41Sopenharmony_ci    EC_POINT *pub_key = NULL;
2581cb0ef41Sopenharmony_ci    const EC_GROUP *group = eckey->group;
2591cb0ef41Sopenharmony_ci    BN_CTX *ctx = BN_CTX_secure_new_ex(eckey->libctx);
2601cb0ef41Sopenharmony_ci    int sm2 = EC_KEY_get_flags(eckey) & EC_FLAG_SM2_RANGE ? 1 : 0;
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci    if (ctx == NULL)
2631cb0ef41Sopenharmony_ci        goto err;
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci    if (eckey->priv_key == NULL) {
2661cb0ef41Sopenharmony_ci        priv_key = BN_secure_new();
2671cb0ef41Sopenharmony_ci        if (priv_key == NULL)
2681cb0ef41Sopenharmony_ci            goto err;
2691cb0ef41Sopenharmony_ci    } else
2701cb0ef41Sopenharmony_ci        priv_key = eckey->priv_key;
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci    /*
2731cb0ef41Sopenharmony_ci     * Steps (1-2): Check domain parameters and security strength.
2741cb0ef41Sopenharmony_ci     * These steps must be done by the user. This would need to be
2751cb0ef41Sopenharmony_ci     * stated in the security policy.
2761cb0ef41Sopenharmony_ci     */
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci    tmp = EC_GROUP_get0_order(group);
2791cb0ef41Sopenharmony_ci    if (tmp == NULL)
2801cb0ef41Sopenharmony_ci        goto err;
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci    /*
2831cb0ef41Sopenharmony_ci     * Steps (3-7): priv_key = DRBG_RAND(order_n_bits) (range [1, n-1]).
2841cb0ef41Sopenharmony_ci     * Although this is slightly different from the standard, it is effectively
2851cb0ef41Sopenharmony_ci     * equivalent as it gives an unbiased result ranging from 1..n-1. It is also
2861cb0ef41Sopenharmony_ci     * faster as the standard needs to retry more often. Also doing
2871cb0ef41Sopenharmony_ci     * 1 + rand[0..n-2] would effect the way that tests feed dummy entropy into
2881cb0ef41Sopenharmony_ci     * rand so the simpler backward compatible method has been used here.
2891cb0ef41Sopenharmony_ci     */
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci    /* range of SM2 private key is [1, n-1) */
2921cb0ef41Sopenharmony_ci    if (sm2) {
2931cb0ef41Sopenharmony_ci        order = BN_new();
2941cb0ef41Sopenharmony_ci        if (order == NULL || !BN_sub(order, tmp, BN_value_one()))
2951cb0ef41Sopenharmony_ci            goto err;
2961cb0ef41Sopenharmony_ci    } else {
2971cb0ef41Sopenharmony_ci        order = BN_dup(tmp);
2981cb0ef41Sopenharmony_ci        if (order == NULL)
2991cb0ef41Sopenharmony_ci            goto err;
3001cb0ef41Sopenharmony_ci    }
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci    do
3031cb0ef41Sopenharmony_ci        if (!BN_priv_rand_range_ex(priv_key, order, 0, ctx))
3041cb0ef41Sopenharmony_ci            goto err;
3051cb0ef41Sopenharmony_ci    while (BN_is_zero(priv_key)) ;
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci    if (eckey->pub_key == NULL) {
3081cb0ef41Sopenharmony_ci        pub_key = EC_POINT_new(group);
3091cb0ef41Sopenharmony_ci        if (pub_key == NULL)
3101cb0ef41Sopenharmony_ci            goto err;
3111cb0ef41Sopenharmony_ci    } else
3121cb0ef41Sopenharmony_ci        pub_key = eckey->pub_key;
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci    /* Step (8) : pub_key = priv_key * G (where G is a point on the curve) */
3151cb0ef41Sopenharmony_ci    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
3161cb0ef41Sopenharmony_ci        goto err;
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci    eckey->priv_key = priv_key;
3191cb0ef41Sopenharmony_ci    eckey->pub_key = pub_key;
3201cb0ef41Sopenharmony_ci    priv_key = NULL;
3211cb0ef41Sopenharmony_ci    pub_key = NULL;
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci    eckey->dirty_cnt++;
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci#ifdef FIPS_MODULE
3261cb0ef41Sopenharmony_ci    pairwise_test = 1;
3271cb0ef41Sopenharmony_ci#endif /* FIPS_MODULE */
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci    ok = 1;
3301cb0ef41Sopenharmony_ci    if (pairwise_test) {
3311cb0ef41Sopenharmony_ci        OSSL_CALLBACK *cb = NULL;
3321cb0ef41Sopenharmony_ci        void *cbarg = NULL;
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci        OSSL_SELF_TEST_get_callback(eckey->libctx, &cb, &cbarg);
3351cb0ef41Sopenharmony_ci        ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg);
3361cb0ef41Sopenharmony_ci    }
3371cb0ef41Sopenharmony_cierr:
3381cb0ef41Sopenharmony_ci    /* Step (9): If there is an error return an invalid keypair. */
3391cb0ef41Sopenharmony_ci    if (!ok) {
3401cb0ef41Sopenharmony_ci        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
3411cb0ef41Sopenharmony_ci        BN_clear(eckey->priv_key);
3421cb0ef41Sopenharmony_ci        if (eckey->pub_key != NULL)
3431cb0ef41Sopenharmony_ci            EC_POINT_set_to_infinity(group, eckey->pub_key);
3441cb0ef41Sopenharmony_ci    }
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci    EC_POINT_free(pub_key);
3471cb0ef41Sopenharmony_ci    BN_clear_free(priv_key);
3481cb0ef41Sopenharmony_ci    BN_CTX_free(ctx);
3491cb0ef41Sopenharmony_ci    BN_free(order);
3501cb0ef41Sopenharmony_ci    return ok;
3511cb0ef41Sopenharmony_ci}
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ciint ossl_ec_key_simple_generate_key(EC_KEY *eckey)
3541cb0ef41Sopenharmony_ci{
3551cb0ef41Sopenharmony_ci    return ec_generate_key(eckey, 0);
3561cb0ef41Sopenharmony_ci}
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ciint ossl_ec_key_simple_generate_public_key(EC_KEY *eckey)
3591cb0ef41Sopenharmony_ci{
3601cb0ef41Sopenharmony_ci    int ret;
3611cb0ef41Sopenharmony_ci    BN_CTX *ctx = BN_CTX_new_ex(eckey->libctx);
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci    if (ctx == NULL)
3641cb0ef41Sopenharmony_ci        return 0;
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci    /*
3671cb0ef41Sopenharmony_ci     * See SP800-56AR3 5.6.1.2.2: Step (8)
3681cb0ef41Sopenharmony_ci     * pub_key = priv_key * G (where G is a point on the curve)
3691cb0ef41Sopenharmony_ci     */
3701cb0ef41Sopenharmony_ci    ret = EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL,
3711cb0ef41Sopenharmony_ci                       NULL, ctx);
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci    BN_CTX_free(ctx);
3741cb0ef41Sopenharmony_ci    if (ret == 1)
3751cb0ef41Sopenharmony_ci        eckey->dirty_cnt++;
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci    return ret;
3781cb0ef41Sopenharmony_ci}
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ciint EC_KEY_check_key(const EC_KEY *eckey)
3811cb0ef41Sopenharmony_ci{
3821cb0ef41Sopenharmony_ci    if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
3831cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
3841cb0ef41Sopenharmony_ci        return 0;
3851cb0ef41Sopenharmony_ci    }
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci    if (eckey->group->meth->keycheck == NULL) {
3881cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
3891cb0ef41Sopenharmony_ci        return 0;
3901cb0ef41Sopenharmony_ci    }
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci    return eckey->group->meth->keycheck(eckey);
3931cb0ef41Sopenharmony_ci}
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci/*
3961cb0ef41Sopenharmony_ci * Check the range of the EC public key.
3971cb0ef41Sopenharmony_ci * See SP800-56A R3 Section 5.6.2.3.3 (Part 2)
3981cb0ef41Sopenharmony_ci * i.e.
3991cb0ef41Sopenharmony_ci *  - If q = odd prime p: Verify that xQ and yQ are integers in the
4001cb0ef41Sopenharmony_ci *    interval[0, p - 1], OR
4011cb0ef41Sopenharmony_ci *  - If q = 2m: Verify that xQ and yQ are bit strings of length m bits.
4021cb0ef41Sopenharmony_ci * Returns 1 if the public key has a valid range, otherwise it returns 0.
4031cb0ef41Sopenharmony_ci */
4041cb0ef41Sopenharmony_cistatic int ec_key_public_range_check(BN_CTX *ctx, const EC_KEY *key)
4051cb0ef41Sopenharmony_ci{
4061cb0ef41Sopenharmony_ci    int ret = 0;
4071cb0ef41Sopenharmony_ci    BIGNUM *x, *y;
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci    BN_CTX_start(ctx);
4101cb0ef41Sopenharmony_ci    x = BN_CTX_get(ctx);
4111cb0ef41Sopenharmony_ci    y = BN_CTX_get(ctx);
4121cb0ef41Sopenharmony_ci    if (y == NULL)
4131cb0ef41Sopenharmony_ci        goto err;
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci    if (!EC_POINT_get_affine_coordinates(key->group, key->pub_key, x, y, ctx))
4161cb0ef41Sopenharmony_ci        goto err;
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci    if (EC_GROUP_get_field_type(key->group) == NID_X9_62_prime_field) {
4191cb0ef41Sopenharmony_ci        if (BN_is_negative(x)
4201cb0ef41Sopenharmony_ci            || BN_cmp(x, key->group->field) >= 0
4211cb0ef41Sopenharmony_ci            || BN_is_negative(y)
4221cb0ef41Sopenharmony_ci            || BN_cmp(y, key->group->field) >= 0) {
4231cb0ef41Sopenharmony_ci            goto err;
4241cb0ef41Sopenharmony_ci        }
4251cb0ef41Sopenharmony_ci    } else {
4261cb0ef41Sopenharmony_ci        int m = EC_GROUP_get_degree(key->group);
4271cb0ef41Sopenharmony_ci        if (BN_num_bits(x) > m || BN_num_bits(y) > m) {
4281cb0ef41Sopenharmony_ci            goto err;
4291cb0ef41Sopenharmony_ci        }
4301cb0ef41Sopenharmony_ci    }
4311cb0ef41Sopenharmony_ci    ret = 1;
4321cb0ef41Sopenharmony_cierr:
4331cb0ef41Sopenharmony_ci    BN_CTX_end(ctx);
4341cb0ef41Sopenharmony_ci    return ret;
4351cb0ef41Sopenharmony_ci}
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci/*
4381cb0ef41Sopenharmony_ci * ECC Partial Public-Key Validation as specified in SP800-56A R3
4391cb0ef41Sopenharmony_ci * Section 5.6.2.3.4 ECC Partial Public-Key Validation Routine.
4401cb0ef41Sopenharmony_ci */
4411cb0ef41Sopenharmony_ciint ossl_ec_key_public_check_quick(const EC_KEY *eckey, BN_CTX *ctx)
4421cb0ef41Sopenharmony_ci{
4431cb0ef41Sopenharmony_ci    if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
4441cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
4451cb0ef41Sopenharmony_ci        return 0;
4461cb0ef41Sopenharmony_ci    }
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci    /* 5.6.2.3.3 (Step 1): Q != infinity */
4491cb0ef41Sopenharmony_ci    if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
4501cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
4511cb0ef41Sopenharmony_ci        return 0;
4521cb0ef41Sopenharmony_ci    }
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ci    /* 5.6.2.3.3 (Step 2) Test if the public key is in range */
4551cb0ef41Sopenharmony_ci    if (!ec_key_public_range_check(ctx, eckey)) {
4561cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
4571cb0ef41Sopenharmony_ci        return 0;
4581cb0ef41Sopenharmony_ci    }
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci    /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */
4611cb0ef41Sopenharmony_ci    if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
4621cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
4631cb0ef41Sopenharmony_ci        return 0;
4641cb0ef41Sopenharmony_ci    }
4651cb0ef41Sopenharmony_ci    return 1;
4661cb0ef41Sopenharmony_ci}
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ci/*
4691cb0ef41Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3.
4701cb0ef41Sopenharmony_ci * Section 5.6.2.3.3 ECC Full Public-Key Validation Routine.
4711cb0ef41Sopenharmony_ci */
4721cb0ef41Sopenharmony_ciint ossl_ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx)
4731cb0ef41Sopenharmony_ci{
4741cb0ef41Sopenharmony_ci    int ret = 0;
4751cb0ef41Sopenharmony_ci    EC_POINT *point = NULL;
4761cb0ef41Sopenharmony_ci    const BIGNUM *order = NULL;
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci    if (!ossl_ec_key_public_check_quick(eckey, ctx))
4791cb0ef41Sopenharmony_ci        return 0;
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci    point = EC_POINT_new(eckey->group);
4821cb0ef41Sopenharmony_ci    if (point == NULL)
4831cb0ef41Sopenharmony_ci        return 0;
4841cb0ef41Sopenharmony_ci
4851cb0ef41Sopenharmony_ci    order = eckey->group->order;
4861cb0ef41Sopenharmony_ci    if (BN_is_zero(order)) {
4871cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
4881cb0ef41Sopenharmony_ci        goto err;
4891cb0ef41Sopenharmony_ci    }
4901cb0ef41Sopenharmony_ci    /* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */
4911cb0ef41Sopenharmony_ci    if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
4921cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
4931cb0ef41Sopenharmony_ci        goto err;
4941cb0ef41Sopenharmony_ci    }
4951cb0ef41Sopenharmony_ci    if (!EC_POINT_is_at_infinity(eckey->group, point)) {
4961cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_WRONG_ORDER);
4971cb0ef41Sopenharmony_ci        goto err;
4981cb0ef41Sopenharmony_ci    }
4991cb0ef41Sopenharmony_ci    ret = 1;
5001cb0ef41Sopenharmony_cierr:
5011cb0ef41Sopenharmony_ci    EC_POINT_free(point);
5021cb0ef41Sopenharmony_ci    return ret;
5031cb0ef41Sopenharmony_ci}
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ci/*
5061cb0ef41Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3.
5071cb0ef41Sopenharmony_ci * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity
5081cb0ef41Sopenharmony_ci * The private key is in the range [1, order-1]
5091cb0ef41Sopenharmony_ci */
5101cb0ef41Sopenharmony_ciint ossl_ec_key_private_check(const EC_KEY *eckey)
5111cb0ef41Sopenharmony_ci{
5121cb0ef41Sopenharmony_ci    if (eckey == NULL || eckey->group == NULL || eckey->priv_key == NULL) {
5131cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
5141cb0ef41Sopenharmony_ci        return 0;
5151cb0ef41Sopenharmony_ci    }
5161cb0ef41Sopenharmony_ci    if (BN_cmp(eckey->priv_key, BN_value_one()) < 0
5171cb0ef41Sopenharmony_ci        || BN_cmp(eckey->priv_key, eckey->group->order) >= 0) {
5181cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
5191cb0ef41Sopenharmony_ci        return 0;
5201cb0ef41Sopenharmony_ci    }
5211cb0ef41Sopenharmony_ci    return 1;
5221cb0ef41Sopenharmony_ci}
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci/*
5251cb0ef41Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3.
5261cb0ef41Sopenharmony_ci * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b)
5271cb0ef41Sopenharmony_ci * Check if generator * priv_key = pub_key
5281cb0ef41Sopenharmony_ci */
5291cb0ef41Sopenharmony_ciint ossl_ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx)
5301cb0ef41Sopenharmony_ci{
5311cb0ef41Sopenharmony_ci    int ret = 0;
5321cb0ef41Sopenharmony_ci    EC_POINT *point = NULL;
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci    if (eckey == NULL
5351cb0ef41Sopenharmony_ci       || eckey->group == NULL
5361cb0ef41Sopenharmony_ci       || eckey->pub_key == NULL
5371cb0ef41Sopenharmony_ci       || eckey->priv_key == NULL) {
5381cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
5391cb0ef41Sopenharmony_ci        return 0;
5401cb0ef41Sopenharmony_ci    }
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci    point = EC_POINT_new(eckey->group);
5431cb0ef41Sopenharmony_ci    if (point == NULL)
5441cb0ef41Sopenharmony_ci        goto err;
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_ci    if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) {
5481cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
5491cb0ef41Sopenharmony_ci        goto err;
5501cb0ef41Sopenharmony_ci    }
5511cb0ef41Sopenharmony_ci    if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
5521cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
5531cb0ef41Sopenharmony_ci        goto err;
5541cb0ef41Sopenharmony_ci    }
5551cb0ef41Sopenharmony_ci    ret = 1;
5561cb0ef41Sopenharmony_cierr:
5571cb0ef41Sopenharmony_ci    EC_POINT_free(point);
5581cb0ef41Sopenharmony_ci    return ret;
5591cb0ef41Sopenharmony_ci}
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ci/*
5631cb0ef41Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3.
5641cb0ef41Sopenharmony_ci *    Section 5.6.2.3.3 ECC Full Public-Key Validation
5651cb0ef41Sopenharmony_ci *    Section 5.6.2.1.2 Owner Assurance of Private-Key Validity
5661cb0ef41Sopenharmony_ci *    Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
5671cb0ef41Sopenharmony_ci * NOTES:
5681cb0ef41Sopenharmony_ci *    Before calling this method in fips mode, there should be an assurance that
5691cb0ef41Sopenharmony_ci *    an approved elliptic-curve group is used.
5701cb0ef41Sopenharmony_ci * Returns 1 if the key is valid, otherwise it returns 0.
5711cb0ef41Sopenharmony_ci */
5721cb0ef41Sopenharmony_ciint ossl_ec_key_simple_check_key(const EC_KEY *eckey)
5731cb0ef41Sopenharmony_ci{
5741cb0ef41Sopenharmony_ci    int ok = 0;
5751cb0ef41Sopenharmony_ci    BN_CTX *ctx = NULL;
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ci    if (eckey == NULL) {
5781cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
5791cb0ef41Sopenharmony_ci        return 0;
5801cb0ef41Sopenharmony_ci    }
5811cb0ef41Sopenharmony_ci    if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL)
5821cb0ef41Sopenharmony_ci        return 0;
5831cb0ef41Sopenharmony_ci
5841cb0ef41Sopenharmony_ci    if (!ossl_ec_key_public_check(eckey, ctx))
5851cb0ef41Sopenharmony_ci        goto err;
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_ci    if (eckey->priv_key != NULL) {
5881cb0ef41Sopenharmony_ci        if (!ossl_ec_key_private_check(eckey)
5891cb0ef41Sopenharmony_ci            || !ossl_ec_key_pairwise_check(eckey, ctx))
5901cb0ef41Sopenharmony_ci            goto err;
5911cb0ef41Sopenharmony_ci    }
5921cb0ef41Sopenharmony_ci    ok = 1;
5931cb0ef41Sopenharmony_cierr:
5941cb0ef41Sopenharmony_ci    BN_CTX_free(ctx);
5951cb0ef41Sopenharmony_ci    return ok;
5961cb0ef41Sopenharmony_ci}
5971cb0ef41Sopenharmony_ci
5981cb0ef41Sopenharmony_ciint EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
5991cb0ef41Sopenharmony_ci                                             BIGNUM *y)
6001cb0ef41Sopenharmony_ci{
6011cb0ef41Sopenharmony_ci    BN_CTX *ctx = NULL;
6021cb0ef41Sopenharmony_ci    BIGNUM *tx, *ty;
6031cb0ef41Sopenharmony_ci    EC_POINT *point = NULL;
6041cb0ef41Sopenharmony_ci    int ok = 0;
6051cb0ef41Sopenharmony_ci
6061cb0ef41Sopenharmony_ci    if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
6071cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
6081cb0ef41Sopenharmony_ci        return 0;
6091cb0ef41Sopenharmony_ci    }
6101cb0ef41Sopenharmony_ci    ctx = BN_CTX_new_ex(key->libctx);
6111cb0ef41Sopenharmony_ci    if (ctx == NULL)
6121cb0ef41Sopenharmony_ci        return 0;
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci    BN_CTX_start(ctx);
6151cb0ef41Sopenharmony_ci    point = EC_POINT_new(key->group);
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ci    if (point == NULL)
6181cb0ef41Sopenharmony_ci        goto err;
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci    tx = BN_CTX_get(ctx);
6211cb0ef41Sopenharmony_ci    ty = BN_CTX_get(ctx);
6221cb0ef41Sopenharmony_ci    if (ty == NULL)
6231cb0ef41Sopenharmony_ci        goto err;
6241cb0ef41Sopenharmony_ci
6251cb0ef41Sopenharmony_ci    if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx))
6261cb0ef41Sopenharmony_ci        goto err;
6271cb0ef41Sopenharmony_ci    if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx))
6281cb0ef41Sopenharmony_ci        goto err;
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci    /*
6311cb0ef41Sopenharmony_ci     * Check if retrieved coordinates match originals. The range check is done
6321cb0ef41Sopenharmony_ci     * inside EC_KEY_check_key().
6331cb0ef41Sopenharmony_ci     */
6341cb0ef41Sopenharmony_ci    if (BN_cmp(x, tx) || BN_cmp(y, ty)) {
6351cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
6361cb0ef41Sopenharmony_ci        goto err;
6371cb0ef41Sopenharmony_ci    }
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci    /* EC_KEY_set_public_key updates dirty_cnt */
6401cb0ef41Sopenharmony_ci    if (!EC_KEY_set_public_key(key, point))
6411cb0ef41Sopenharmony_ci        goto err;
6421cb0ef41Sopenharmony_ci
6431cb0ef41Sopenharmony_ci    if (EC_KEY_check_key(key) == 0)
6441cb0ef41Sopenharmony_ci        goto err;
6451cb0ef41Sopenharmony_ci
6461cb0ef41Sopenharmony_ci    ok = 1;
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci err:
6491cb0ef41Sopenharmony_ci    BN_CTX_end(ctx);
6501cb0ef41Sopenharmony_ci    BN_CTX_free(ctx);
6511cb0ef41Sopenharmony_ci    EC_POINT_free(point);
6521cb0ef41Sopenharmony_ci    return ok;
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_ci}
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ciOSSL_LIB_CTX *ossl_ec_key_get_libctx(const EC_KEY *key)
6571cb0ef41Sopenharmony_ci{
6581cb0ef41Sopenharmony_ci    return key->libctx;
6591cb0ef41Sopenharmony_ci}
6601cb0ef41Sopenharmony_ci
6611cb0ef41Sopenharmony_ciconst char *ossl_ec_key_get0_propq(const EC_KEY *key)
6621cb0ef41Sopenharmony_ci{
6631cb0ef41Sopenharmony_ci    return key->propq;
6641cb0ef41Sopenharmony_ci}
6651cb0ef41Sopenharmony_ci
6661cb0ef41Sopenharmony_civoid ossl_ec_key_set0_libctx(EC_KEY *key, OSSL_LIB_CTX *libctx)
6671cb0ef41Sopenharmony_ci{
6681cb0ef41Sopenharmony_ci    key->libctx = libctx;
6691cb0ef41Sopenharmony_ci    /* Do we need to propagate this to the group? */
6701cb0ef41Sopenharmony_ci}
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ciconst EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
6731cb0ef41Sopenharmony_ci{
6741cb0ef41Sopenharmony_ci    return key->group;
6751cb0ef41Sopenharmony_ci}
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_ciint EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
6781cb0ef41Sopenharmony_ci{
6791cb0ef41Sopenharmony_ci    if (key->meth->set_group != NULL && key->meth->set_group(key, group) == 0)
6801cb0ef41Sopenharmony_ci        return 0;
6811cb0ef41Sopenharmony_ci    EC_GROUP_free(key->group);
6821cb0ef41Sopenharmony_ci    key->group = EC_GROUP_dup(group);
6831cb0ef41Sopenharmony_ci    if (key->group != NULL && EC_GROUP_get_curve_name(key->group) == NID_sm2)
6841cb0ef41Sopenharmony_ci        EC_KEY_set_flags(key, EC_FLAG_SM2_RANGE);
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci    key->dirty_cnt++;
6871cb0ef41Sopenharmony_ci    return (key->group == NULL) ? 0 : 1;
6881cb0ef41Sopenharmony_ci}
6891cb0ef41Sopenharmony_ci
6901cb0ef41Sopenharmony_ciconst BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
6911cb0ef41Sopenharmony_ci{
6921cb0ef41Sopenharmony_ci    return key->priv_key;
6931cb0ef41Sopenharmony_ci}
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ciint EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
6961cb0ef41Sopenharmony_ci{
6971cb0ef41Sopenharmony_ci    int fixed_top;
6981cb0ef41Sopenharmony_ci    const BIGNUM *order = NULL;
6991cb0ef41Sopenharmony_ci    BIGNUM *tmp_key = NULL;
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci    if (key->group == NULL || key->group->meth == NULL)
7021cb0ef41Sopenharmony_ci        return 0;
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_ci    /*
7051cb0ef41Sopenharmony_ci     * Not only should key->group be set, but it should also be in a valid
7061cb0ef41Sopenharmony_ci     * fully initialized state.
7071cb0ef41Sopenharmony_ci     *
7081cb0ef41Sopenharmony_ci     * Specifically, to operate in constant time, we need that the group order
7091cb0ef41Sopenharmony_ci     * is set, as we use its length as the fixed public size of any scalar used
7101cb0ef41Sopenharmony_ci     * as an EC private key.
7111cb0ef41Sopenharmony_ci     */
7121cb0ef41Sopenharmony_ci    order = EC_GROUP_get0_order(key->group);
7131cb0ef41Sopenharmony_ci    if (order == NULL || BN_is_zero(order))
7141cb0ef41Sopenharmony_ci        return 0; /* This should never happen */
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_ci    if (key->group->meth->set_private != NULL
7171cb0ef41Sopenharmony_ci        && key->group->meth->set_private(key, priv_key) == 0)
7181cb0ef41Sopenharmony_ci        return 0;
7191cb0ef41Sopenharmony_ci    if (key->meth->set_private != NULL
7201cb0ef41Sopenharmony_ci        && key->meth->set_private(key, priv_key) == 0)
7211cb0ef41Sopenharmony_ci        return 0;
7221cb0ef41Sopenharmony_ci
7231cb0ef41Sopenharmony_ci    /*
7241cb0ef41Sopenharmony_ci     * Return `0` to comply with legacy behavior for this function, see
7251cb0ef41Sopenharmony_ci     * https://github.com/openssl/openssl/issues/18744#issuecomment-1195175696
7261cb0ef41Sopenharmony_ci     */
7271cb0ef41Sopenharmony_ci    if (priv_key == NULL) {
7281cb0ef41Sopenharmony_ci        BN_clear_free(key->priv_key);
7291cb0ef41Sopenharmony_ci        key->priv_key = NULL;
7301cb0ef41Sopenharmony_ci        return 0; /* intentional for legacy compatibility */
7311cb0ef41Sopenharmony_ci    }
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_ci    /*
7341cb0ef41Sopenharmony_ci     * We should never leak the bit length of the secret scalar in the key,
7351cb0ef41Sopenharmony_ci     * so we always set the `BN_FLG_CONSTTIME` flag on the internal `BIGNUM`
7361cb0ef41Sopenharmony_ci     * holding the secret scalar.
7371cb0ef41Sopenharmony_ci     *
7381cb0ef41Sopenharmony_ci     * This is important also because `BN_dup()` (and `BN_copy()`) do not
7391cb0ef41Sopenharmony_ci     * propagate the `BN_FLG_CONSTTIME` flag from the source `BIGNUM`, and
7401cb0ef41Sopenharmony_ci     * this brings an extra risk of inadvertently losing the flag, even when
7411cb0ef41Sopenharmony_ci     * the caller specifically set it.
7421cb0ef41Sopenharmony_ci     *
7431cb0ef41Sopenharmony_ci     * The propagation has been turned on and off a few times in the past
7441cb0ef41Sopenharmony_ci     * years because in some conditions has shown unintended consequences in
7451cb0ef41Sopenharmony_ci     * some code paths, so at the moment we can't fix this in the BN layer.
7461cb0ef41Sopenharmony_ci     *
7471cb0ef41Sopenharmony_ci     * In `EC_KEY_set_private_key()` we can work around the propagation by
7481cb0ef41Sopenharmony_ci     * manually setting the flag after `BN_dup()` as we know for sure that
7491cb0ef41Sopenharmony_ci     * inside the EC module the `BN_FLG_CONSTTIME` is always treated
7501cb0ef41Sopenharmony_ci     * correctly and should not generate unintended consequences.
7511cb0ef41Sopenharmony_ci     *
7521cb0ef41Sopenharmony_ci     * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
7531cb0ef41Sopenharmony_ci     * to preallocate the BIGNUM internal buffer to a fixed public size big
7541cb0ef41Sopenharmony_ci     * enough that operations performed during the processing never trigger
7551cb0ef41Sopenharmony_ci     * a realloc which would leak the size of the scalar through memory
7561cb0ef41Sopenharmony_ci     * accesses.
7571cb0ef41Sopenharmony_ci     *
7581cb0ef41Sopenharmony_ci     * Fixed Length
7591cb0ef41Sopenharmony_ci     * ------------
7601cb0ef41Sopenharmony_ci     *
7611cb0ef41Sopenharmony_ci     * The order of the large prime subgroup of the curve is our choice for
7621cb0ef41Sopenharmony_ci     * a fixed public size, as that is generally the upper bound for
7631cb0ef41Sopenharmony_ci     * generating a private key in EC cryptosystems and should fit all valid
7641cb0ef41Sopenharmony_ci     * secret scalars.
7651cb0ef41Sopenharmony_ci     *
7661cb0ef41Sopenharmony_ci     * For preallocating the BIGNUM storage we look at the number of "words"
7671cb0ef41Sopenharmony_ci     * required for the internal representation of the order, and we
7681cb0ef41Sopenharmony_ci     * preallocate 2 extra "words" in case any of the subsequent processing
7691cb0ef41Sopenharmony_ci     * might temporarily overflow the order length.
7701cb0ef41Sopenharmony_ci     */
7711cb0ef41Sopenharmony_ci    tmp_key = BN_dup(priv_key);
7721cb0ef41Sopenharmony_ci    if (tmp_key == NULL)
7731cb0ef41Sopenharmony_ci        return 0;
7741cb0ef41Sopenharmony_ci
7751cb0ef41Sopenharmony_ci    BN_set_flags(tmp_key, BN_FLG_CONSTTIME);
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_ci    fixed_top = bn_get_top(order) + 2;
7781cb0ef41Sopenharmony_ci    if (bn_wexpand(tmp_key, fixed_top) == NULL) {
7791cb0ef41Sopenharmony_ci        BN_clear_free(tmp_key);
7801cb0ef41Sopenharmony_ci        return 0;
7811cb0ef41Sopenharmony_ci    }
7821cb0ef41Sopenharmony_ci
7831cb0ef41Sopenharmony_ci    BN_clear_free(key->priv_key);
7841cb0ef41Sopenharmony_ci    key->priv_key = tmp_key;
7851cb0ef41Sopenharmony_ci    key->dirty_cnt++;
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_ci    return 1;
7881cb0ef41Sopenharmony_ci}
7891cb0ef41Sopenharmony_ci
7901cb0ef41Sopenharmony_ciconst EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
7911cb0ef41Sopenharmony_ci{
7921cb0ef41Sopenharmony_ci    return key->pub_key;
7931cb0ef41Sopenharmony_ci}
7941cb0ef41Sopenharmony_ci
7951cb0ef41Sopenharmony_ciint EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
7961cb0ef41Sopenharmony_ci{
7971cb0ef41Sopenharmony_ci    if (key->meth->set_public != NULL
7981cb0ef41Sopenharmony_ci        && key->meth->set_public(key, pub_key) == 0)
7991cb0ef41Sopenharmony_ci        return 0;
8001cb0ef41Sopenharmony_ci    EC_POINT_free(key->pub_key);
8011cb0ef41Sopenharmony_ci    key->pub_key = EC_POINT_dup(pub_key, key->group);
8021cb0ef41Sopenharmony_ci    key->dirty_cnt++;
8031cb0ef41Sopenharmony_ci    return (key->pub_key == NULL) ? 0 : 1;
8041cb0ef41Sopenharmony_ci}
8051cb0ef41Sopenharmony_ci
8061cb0ef41Sopenharmony_ciunsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
8071cb0ef41Sopenharmony_ci{
8081cb0ef41Sopenharmony_ci    return key->enc_flag;
8091cb0ef41Sopenharmony_ci}
8101cb0ef41Sopenharmony_ci
8111cb0ef41Sopenharmony_civoid EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
8121cb0ef41Sopenharmony_ci{
8131cb0ef41Sopenharmony_ci    key->enc_flag = flags;
8141cb0ef41Sopenharmony_ci}
8151cb0ef41Sopenharmony_ci
8161cb0ef41Sopenharmony_cipoint_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
8171cb0ef41Sopenharmony_ci{
8181cb0ef41Sopenharmony_ci    return key->conv_form;
8191cb0ef41Sopenharmony_ci}
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_civoid EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
8221cb0ef41Sopenharmony_ci{
8231cb0ef41Sopenharmony_ci    key->conv_form = cform;
8241cb0ef41Sopenharmony_ci    if (key->group != NULL)
8251cb0ef41Sopenharmony_ci        EC_GROUP_set_point_conversion_form(key->group, cform);
8261cb0ef41Sopenharmony_ci}
8271cb0ef41Sopenharmony_ci
8281cb0ef41Sopenharmony_civoid EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
8291cb0ef41Sopenharmony_ci{
8301cb0ef41Sopenharmony_ci    if (key->group != NULL)
8311cb0ef41Sopenharmony_ci        EC_GROUP_set_asn1_flag(key->group, flag);
8321cb0ef41Sopenharmony_ci}
8331cb0ef41Sopenharmony_ci
8341cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0
8351cb0ef41Sopenharmony_ciint EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
8361cb0ef41Sopenharmony_ci{
8371cb0ef41Sopenharmony_ci    if (key->group == NULL)
8381cb0ef41Sopenharmony_ci        return 0;
8391cb0ef41Sopenharmony_ci    return EC_GROUP_precompute_mult(key->group, ctx);
8401cb0ef41Sopenharmony_ci}
8411cb0ef41Sopenharmony_ci#endif
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ciint EC_KEY_get_flags(const EC_KEY *key)
8441cb0ef41Sopenharmony_ci{
8451cb0ef41Sopenharmony_ci    return key->flags;
8461cb0ef41Sopenharmony_ci}
8471cb0ef41Sopenharmony_ci
8481cb0ef41Sopenharmony_civoid EC_KEY_set_flags(EC_KEY *key, int flags)
8491cb0ef41Sopenharmony_ci{
8501cb0ef41Sopenharmony_ci    key->flags |= flags;
8511cb0ef41Sopenharmony_ci    key->dirty_cnt++;
8521cb0ef41Sopenharmony_ci}
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_civoid EC_KEY_clear_flags(EC_KEY *key, int flags)
8551cb0ef41Sopenharmony_ci{
8561cb0ef41Sopenharmony_ci    key->flags &= ~flags;
8571cb0ef41Sopenharmony_ci    key->dirty_cnt++;
8581cb0ef41Sopenharmony_ci}
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ciint EC_KEY_decoded_from_explicit_params(const EC_KEY *key)
8611cb0ef41Sopenharmony_ci{
8621cb0ef41Sopenharmony_ci    if (key == NULL || key->group == NULL)
8631cb0ef41Sopenharmony_ci        return -1;
8641cb0ef41Sopenharmony_ci    return key->group->decoded_from_explicit_params;
8651cb0ef41Sopenharmony_ci}
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_cisize_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
8681cb0ef41Sopenharmony_ci                        unsigned char **pbuf, BN_CTX *ctx)
8691cb0ef41Sopenharmony_ci{
8701cb0ef41Sopenharmony_ci    if (key == NULL || key->pub_key == NULL || key->group == NULL)
8711cb0ef41Sopenharmony_ci        return 0;
8721cb0ef41Sopenharmony_ci    return EC_POINT_point2buf(key->group, key->pub_key, form, pbuf, ctx);
8731cb0ef41Sopenharmony_ci}
8741cb0ef41Sopenharmony_ci
8751cb0ef41Sopenharmony_ciint EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len,
8761cb0ef41Sopenharmony_ci                   BN_CTX *ctx)
8771cb0ef41Sopenharmony_ci{
8781cb0ef41Sopenharmony_ci    if (key == NULL || key->group == NULL)
8791cb0ef41Sopenharmony_ci        return 0;
8801cb0ef41Sopenharmony_ci    if (key->pub_key == NULL)
8811cb0ef41Sopenharmony_ci        key->pub_key = EC_POINT_new(key->group);
8821cb0ef41Sopenharmony_ci    if (key->pub_key == NULL)
8831cb0ef41Sopenharmony_ci        return 0;
8841cb0ef41Sopenharmony_ci    if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0)
8851cb0ef41Sopenharmony_ci        return 0;
8861cb0ef41Sopenharmony_ci    key->dirty_cnt++;
8871cb0ef41Sopenharmony_ci    /*
8881cb0ef41Sopenharmony_ci     * Save the point conversion form.
8891cb0ef41Sopenharmony_ci     * For non-custom curves the first octet of the buffer (excluding
8901cb0ef41Sopenharmony_ci     * the last significant bit) contains the point conversion form.
8911cb0ef41Sopenharmony_ci     * EC_POINT_oct2point() has already performed sanity checking of
8921cb0ef41Sopenharmony_ci     * the buffer so we know it is valid.
8931cb0ef41Sopenharmony_ci     */
8941cb0ef41Sopenharmony_ci    if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0)
8951cb0ef41Sopenharmony_ci        key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01);
8961cb0ef41Sopenharmony_ci    return 1;
8971cb0ef41Sopenharmony_ci}
8981cb0ef41Sopenharmony_ci
8991cb0ef41Sopenharmony_cisize_t EC_KEY_priv2oct(const EC_KEY *eckey,
9001cb0ef41Sopenharmony_ci                       unsigned char *buf, size_t len)
9011cb0ef41Sopenharmony_ci{
9021cb0ef41Sopenharmony_ci    if (eckey->group == NULL || eckey->group->meth == NULL)
9031cb0ef41Sopenharmony_ci        return 0;
9041cb0ef41Sopenharmony_ci    if (eckey->group->meth->priv2oct == NULL) {
9051cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9061cb0ef41Sopenharmony_ci        return 0;
9071cb0ef41Sopenharmony_ci    }
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ci    return eckey->group->meth->priv2oct(eckey, buf, len);
9101cb0ef41Sopenharmony_ci}
9111cb0ef41Sopenharmony_ci
9121cb0ef41Sopenharmony_cisize_t ossl_ec_key_simple_priv2oct(const EC_KEY *eckey,
9131cb0ef41Sopenharmony_ci                                   unsigned char *buf, size_t len)
9141cb0ef41Sopenharmony_ci{
9151cb0ef41Sopenharmony_ci    size_t buf_len;
9161cb0ef41Sopenharmony_ci
9171cb0ef41Sopenharmony_ci    buf_len = (EC_GROUP_order_bits(eckey->group) + 7) / 8;
9181cb0ef41Sopenharmony_ci    if (eckey->priv_key == NULL)
9191cb0ef41Sopenharmony_ci        return 0;
9201cb0ef41Sopenharmony_ci    if (buf == NULL)
9211cb0ef41Sopenharmony_ci        return buf_len;
9221cb0ef41Sopenharmony_ci    else if (len < buf_len)
9231cb0ef41Sopenharmony_ci        return 0;
9241cb0ef41Sopenharmony_ci
9251cb0ef41Sopenharmony_ci    /* Octetstring may need leading zeros if BN is to short */
9261cb0ef41Sopenharmony_ci
9271cb0ef41Sopenharmony_ci    if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) {
9281cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
9291cb0ef41Sopenharmony_ci        return 0;
9301cb0ef41Sopenharmony_ci    }
9311cb0ef41Sopenharmony_ci
9321cb0ef41Sopenharmony_ci    return buf_len;
9331cb0ef41Sopenharmony_ci}
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_ciint EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len)
9361cb0ef41Sopenharmony_ci{
9371cb0ef41Sopenharmony_ci    int ret;
9381cb0ef41Sopenharmony_ci
9391cb0ef41Sopenharmony_ci    if (eckey->group == NULL || eckey->group->meth == NULL)
9401cb0ef41Sopenharmony_ci        return 0;
9411cb0ef41Sopenharmony_ci    if (eckey->group->meth->oct2priv == NULL) {
9421cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9431cb0ef41Sopenharmony_ci        return 0;
9441cb0ef41Sopenharmony_ci    }
9451cb0ef41Sopenharmony_ci    ret = eckey->group->meth->oct2priv(eckey, buf, len);
9461cb0ef41Sopenharmony_ci    if (ret == 1)
9471cb0ef41Sopenharmony_ci        eckey->dirty_cnt++;
9481cb0ef41Sopenharmony_ci    return ret;
9491cb0ef41Sopenharmony_ci}
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_ciint ossl_ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf,
9521cb0ef41Sopenharmony_ci                                size_t len)
9531cb0ef41Sopenharmony_ci{
9541cb0ef41Sopenharmony_ci    if (eckey->priv_key == NULL)
9551cb0ef41Sopenharmony_ci        eckey->priv_key = BN_secure_new();
9561cb0ef41Sopenharmony_ci    if (eckey->priv_key == NULL) {
9571cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
9581cb0ef41Sopenharmony_ci        return 0;
9591cb0ef41Sopenharmony_ci    }
9601cb0ef41Sopenharmony_ci    if (BN_bin2bn(buf, len, eckey->priv_key) == NULL) {
9611cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
9621cb0ef41Sopenharmony_ci        return 0;
9631cb0ef41Sopenharmony_ci    }
9641cb0ef41Sopenharmony_ci    eckey->dirty_cnt++;
9651cb0ef41Sopenharmony_ci    return 1;
9661cb0ef41Sopenharmony_ci}
9671cb0ef41Sopenharmony_ci
9681cb0ef41Sopenharmony_cisize_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf)
9691cb0ef41Sopenharmony_ci{
9701cb0ef41Sopenharmony_ci    size_t len;
9711cb0ef41Sopenharmony_ci    unsigned char *buf;
9721cb0ef41Sopenharmony_ci
9731cb0ef41Sopenharmony_ci    len = EC_KEY_priv2oct(eckey, NULL, 0);
9741cb0ef41Sopenharmony_ci    if (len == 0)
9751cb0ef41Sopenharmony_ci        return 0;
9761cb0ef41Sopenharmony_ci    if ((buf = OPENSSL_malloc(len)) == NULL) {
9771cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
9781cb0ef41Sopenharmony_ci        return 0;
9791cb0ef41Sopenharmony_ci    }
9801cb0ef41Sopenharmony_ci    len = EC_KEY_priv2oct(eckey, buf, len);
9811cb0ef41Sopenharmony_ci    if (len == 0) {
9821cb0ef41Sopenharmony_ci        OPENSSL_free(buf);
9831cb0ef41Sopenharmony_ci        return 0;
9841cb0ef41Sopenharmony_ci    }
9851cb0ef41Sopenharmony_ci    *pbuf = buf;
9861cb0ef41Sopenharmony_ci    return len;
9871cb0ef41Sopenharmony_ci}
9881cb0ef41Sopenharmony_ci
9891cb0ef41Sopenharmony_ciint EC_KEY_can_sign(const EC_KEY *eckey)
9901cb0ef41Sopenharmony_ci{
9911cb0ef41Sopenharmony_ci    if (eckey->group == NULL || eckey->group->meth == NULL
9921cb0ef41Sopenharmony_ci        || (eckey->group->meth->flags & EC_FLAGS_NO_SIGN))
9931cb0ef41Sopenharmony_ci        return 0;
9941cb0ef41Sopenharmony_ci    return 1;
9951cb0ef41Sopenharmony_ci}
9961cb0ef41Sopenharmony_ci
9971cb0ef41Sopenharmony_ci/*
9981cb0ef41Sopenharmony_ci * FIPS 140-2 IG 9.9 AS09.33
9991cb0ef41Sopenharmony_ci * Perform a sign/verify operation.
10001cb0ef41Sopenharmony_ci *
10011cb0ef41Sopenharmony_ci * NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9
10021cb0ef41Sopenharmony_ci * states that no additional pairwise tests are required (apart from the tests
10031cb0ef41Sopenharmony_ci * specified in SP800-56A) when generating keys. Hence pairwise ECDH tests are
10041cb0ef41Sopenharmony_ci * omitted here.
10051cb0ef41Sopenharmony_ci */
10061cb0ef41Sopenharmony_cistatic int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
10071cb0ef41Sopenharmony_ci                                      void *cbarg)
10081cb0ef41Sopenharmony_ci{
10091cb0ef41Sopenharmony_ci    int ret = 0;
10101cb0ef41Sopenharmony_ci    unsigned char dgst[16] = {0};
10111cb0ef41Sopenharmony_ci    int dgst_len = (int)sizeof(dgst);
10121cb0ef41Sopenharmony_ci    ECDSA_SIG *sig = NULL;
10131cb0ef41Sopenharmony_ci    OSSL_SELF_TEST *st = NULL;
10141cb0ef41Sopenharmony_ci
10151cb0ef41Sopenharmony_ci    st = OSSL_SELF_TEST_new(cb, cbarg);
10161cb0ef41Sopenharmony_ci    if (st == NULL)
10171cb0ef41Sopenharmony_ci        return 0;
10181cb0ef41Sopenharmony_ci
10191cb0ef41Sopenharmony_ci    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
10201cb0ef41Sopenharmony_ci                           OSSL_SELF_TEST_DESC_PCT_ECDSA);
10211cb0ef41Sopenharmony_ci
10221cb0ef41Sopenharmony_ci    sig = ECDSA_do_sign(dgst, dgst_len, eckey);
10231cb0ef41Sopenharmony_ci    if (sig == NULL)
10241cb0ef41Sopenharmony_ci        goto err;
10251cb0ef41Sopenharmony_ci
10261cb0ef41Sopenharmony_ci    OSSL_SELF_TEST_oncorrupt_byte(st, dgst);
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci    if (ECDSA_do_verify(dgst, dgst_len, sig, eckey) != 1)
10291cb0ef41Sopenharmony_ci        goto err;
10301cb0ef41Sopenharmony_ci
10311cb0ef41Sopenharmony_ci    ret = 1;
10321cb0ef41Sopenharmony_cierr:
10331cb0ef41Sopenharmony_ci    OSSL_SELF_TEST_onend(st, ret);
10341cb0ef41Sopenharmony_ci    OSSL_SELF_TEST_free(st);
10351cb0ef41Sopenharmony_ci    ECDSA_SIG_free(sig);
10361cb0ef41Sopenharmony_ci    return ret;
10371cb0ef41Sopenharmony_ci}
1038