Edit

IABSD.fr/src/lib/libcrypto/ec/ec_field.c

Branch :

  • Show log

    Commit

  • Author : jsing
    Date : 2025-08-02 16:20:00
    Hash : f79ff0cc
    Message : Provide bn_mod_sqr_words() and call it from ec_field_element_sqr(). For now this still calls bn_montgomery_multiply_words(), however it can be optimised further in the future.

  • lib/libcrypto/ec/ec_field.c
  • /*	$OpenBSD: ec_field.c,v 1.3 2025/08/02 16:20:00 jsing Exp $	*/
    /*
     * Copyright (c) 2024 Joel Sing <jsing@openbsd.org>
     *
     * Permission to use, copy, modify, and distribute this software for any
     * purpose with or without fee is hereby granted, provided that the above
     * copyright notice and this permission notice appear in all copies.
     *
     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     */
    
    #include <string.h>
    
    #include <openssl/ec.h>
    
    #include "bn_local.h"
    #include "bn_internal.h"
    #include "ec_local.h"
    #include "ec_internal.h"
    
    int
    ec_field_modulus_from_bn(EC_FIELD_MODULUS *fm, const BIGNUM *bn, BN_CTX *ctx)
    {
    	BN_MONT_CTX *mctx = NULL;
    	size_t i;
    	int ret = 0;
    
    	if (BN_is_negative(bn))
    		goto err;
    	if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS)
    		goto err;
    
    	memset(fm, 0, sizeof(*fm));
    
    	fm->n = (BN_num_bits(bn) + BN_BITS2 - 1) / BN_BITS2;
    
    	for (i = 0; i < bn->top; i++)
    		fm->m.w[i] = bn->d[i];
    
    	/* XXX - implement this without BN_MONT_CTX. */
    	if ((mctx = BN_MONT_CTX_new()) == NULL)
    		goto err;
    	if (!BN_MONT_CTX_set(mctx, bn, ctx))
    		goto err;
    
    	for (i = 0; i < mctx->RR.top; i++)
    		fm->rr.w[i] = mctx->RR.d[i];
    
    	fm->minv0 = mctx->n0[0];
    
    	ret = 1;
    
     err:
    	BN_MONT_CTX_free(mctx);
    
    	return ret;
    }
    
    int
    ec_field_element_from_bn(const EC_FIELD_MODULUS *fm, const EC_GROUP *group,
        EC_FIELD_ELEMENT *fe, const BIGNUM *bn, BN_CTX *ctx)
    {
    	BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
    	BIGNUM *tmp;
    	size_t i;
    	int ret = 0;
    
    	BN_CTX_start(ctx);
    
    	if ((tmp = BN_CTX_get(ctx)) == NULL)
    		goto err;
    
    	/* XXX - enforce 0 <= n < p. */
    
    	if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS)
    		goto err;
    
    	/* XXX - do this without BN. */
    	if (!BN_nnmod(tmp, bn, group->p, ctx))
    		goto err;
    
    	if (BN_num_bits(tmp) > EC_FIELD_ELEMENT_MAX_BITS)
    		abort();
    
    	memset(fe->w, 0, sizeof(fe->w));
    
    	for (i = 0; i < tmp->top; i++)
    		fe->w[i] = tmp->d[i];
    
    	bn_mod_mul_words(fe->w, fe->w, fm->rr.w, fm->m.w, t, fm->minv0, fm->n);
    
    	ret = 1;
    
     err:
    	BN_CTX_end(ctx);
    
    	return ret;
    }
    
    int
    ec_field_element_to_bn(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe,
        BIGNUM *bn, BN_CTX *ctx)
    {
    	BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
    	size_t i;
    
    	if (!bn_wexpand(bn, fm->n))
    		return 0;
    
    	memset(t, 0, sizeof(t));
    	for (i = 0; i < fm->n; i++)
    		t[i] = fe->w[i];
    
    	bn_montgomery_reduce_words(bn->d, t, fm->m.w, fm->minv0, fm->n);
    
    	bn->top = fm->n;
    	bn_correct_top(bn);
    
    	return 1;
    }
    
    void
    ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src)
    {
    	memcpy(dst, src, sizeof(EC_FIELD_ELEMENT));
    }
    
    void
    ec_field_element_select(const EC_FIELD_MODULUS *fm, EC_FIELD_ELEMENT *r,
        const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b, int conditional)
    {
    	BN_ULONG mask;
    	int i;
    
    	mask = bn_ct_eq_zero_mask(conditional);
    
    	for (i = 0; i < fm->n; i++)
    		r->w[i] = (a->w[i] & mask) | (b->w[i] & ~mask);
    }
    
    int
    ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a,
        const EC_FIELD_ELEMENT *b)
    {
    	BN_ULONG v = 0;
    	int i;
    
    	for (i = 0; i < fm->n; i++)
    		v |= a->w[i] ^ b->w[i];
    
    	return bn_ct_eq_zero(v);
    }
    
    int
    ec_field_element_is_zero(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe)
    {
    	BN_ULONG v = 0;
    	int i;
    
    	for (i = 0; i < fm->n; i++)
    		v |= fe->w[i];
    
    	return bn_ct_eq_zero(v);
    }
    
    void
    ec_field_element_add(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
        const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
    {
    	bn_mod_add_words(r->w, a->w, b->w, m->m.w, m->n);
    }
    
    void
    ec_field_element_sub(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
        const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
    {
    	bn_mod_sub_words(r->w, a->w, b->w, m->m.w, m->n);
    }
    
    void
    ec_field_element_mul(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
        const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
    {
    	BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
    
    	bn_mod_mul_words(r->w, a->w, b->w, m->m.w, t, m->minv0, m->n);
    }
    
    void
    ec_field_element_sqr(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
        const EC_FIELD_ELEMENT *a)
    {
    	BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
    
    	bn_mod_sqr_words(r->w, a->w, m->m.w, t, m->minv0, m->n);
    }