/* * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2014 Cryptography Research, Inc. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html * * Originally written by Mike Hamburg */ #ifndef OSSL_CRYPTO_EC_CURVE448_FIELD_H # define OSSL_CRYPTO_EC_CURVE448_FIELD_H # include "internal/constant_time.h" # include # include # include "word.h" # define NLIMBS (64/sizeof(word_t)) # define X_SER_BYTES 56 # define SER_BYTES 56 # if defined(__GNUC__) || defined(__clang__) # define INLINE_UNUSED __inline__ __attribute__((__unused__,__always_inline__)) # define RESTRICT __restrict__ # define ALIGNED __attribute__((__aligned__(16))) # else # define INLINE_UNUSED ossl_inline # define RESTRICT # define ALIGNED # endif typedef struct gf_s { word_t limb[NLIMBS]; } ALIGNED gf_s, gf[1]; /* RFC 7748 support */ # define X_PUBLIC_BYTES X_SER_BYTES # define X_PRIVATE_BYTES X_PUBLIC_BYTES # define X_PRIVATE_BITS 448 static INLINE_UNUSED void gf_copy(gf out, const gf a) { *out = *a; } static INLINE_UNUSED void gf_add_RAW(gf out, const gf a, const gf b); static INLINE_UNUSED void gf_sub_RAW(gf out, const gf a, const gf b); static INLINE_UNUSED void gf_bias(gf inout, int amount); static INLINE_UNUSED void gf_weak_reduce(gf inout); void gf_strong_reduce(gf inout); void gf_add(gf out, const gf a, const gf b); void gf_sub(gf out, const gf a, const gf b); void gf_mul(gf_s * RESTRICT out, const gf a, const gf b); void gf_mulw_unsigned(gf_s * RESTRICT out, const gf a, uint32_t b); void gf_sqr(gf_s * RESTRICT out, const gf a); mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ mask_t gf_eq(const gf x, const gf y); mask_t gf_lobit(const gf x); mask_t gf_hibit(const gf x); void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_highbit); mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit, uint8_t hi_nmask); # include "f_impl.h" /* Bring in the inline implementations */ # define LIMBPERM(i) (i) # define LIMB_MASK(i) (((1)< 0); if (n & 1) { gf_sqr(y, x); n--; } else { gf_sqr(tmp, x); gf_sqr(y, tmp); n -= 2; } for (; n; n -= 2) { gf_sqr(tmp, y); gf_sqr(y, tmp); } } # define gf_add_nr gf_add_RAW /* Subtract mod p. Bias by 2 and don't reduce */ static ossl_inline void gf_sub_nr(gf c, const gf a, const gf b) { gf_sub_RAW(c, a, b); gf_bias(c, 2); if (GF_HEADROOM < 3) gf_weak_reduce(c); } /* Subtract mod p. Bias by amt but don't reduce. */ static ossl_inline void gf_subx_nr(gf c, const gf a, const gf b, int amt) { gf_sub_RAW(c, a, b); gf_bias(c, amt); if (GF_HEADROOM < amt + 1) gf_weak_reduce(c); } /* Mul by signed int. Not constant-time WRT the sign of that int. */ static ossl_inline void gf_mulw(gf c, const gf a, int32_t w) { if (w > 0) { gf_mulw_unsigned(c, a, w); } else { gf_mulw_unsigned(c, a, -w); gf_sub(c, ZERO, c); } } /* Constant time, x = is_z ? z : y */ static ossl_inline void gf_cond_sel(gf x, const gf y, const gf z, mask_t is_z) { size_t i; for (i = 0; i < NLIMBS; i++) { #if ARCH_WORD_BITS == 32 x[0].limb[i] = constant_time_select_32(is_z, z[0].limb[i], y[0].limb[i]); #else /* Must be 64 bit */ x[0].limb[i] = constant_time_select_64(is_z, z[0].limb[i], y[0].limb[i]); #endif } } /* Constant time, if (neg) x=-x; */ static ossl_inline void gf_cond_neg(gf x, mask_t neg) { gf y; gf_sub(y, ZERO, x); gf_cond_sel(x, x, y, neg); } /* Constant time, if (swap) (x,y) = (y,x); */ static ossl_inline void gf_cond_swap(gf x, gf_s * RESTRICT y, mask_t swap) { size_t i; for (i = 0; i < NLIMBS; i++) { #if ARCH_WORD_BITS == 32 constant_time_cond_swap_32(swap, &(x[0].limb[i]), &(y->limb[i])); #else /* Must be 64 bit */ constant_time_cond_swap_64(swap, &(x[0].limb[i]), &(y->limb[i])); #endif } } #endif /* OSSL_CRYPTO_EC_CURVE448_FIELD_H */