From 98be9a0820e4ab74b30e0e3f5489e35a88618a3b Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Thu, 7 Jan 2016 16:53:41 -0800 Subject: [PATCH] now generating some headers for real --- Makefile | 17 +- src/public_include/decaf/decaf_255.h | 640 ------------------------ src/public_include/decaf/decaf_255.hxx | 586 ---------------------- src/public_include/decaf/decaf_448.h | 641 ------------------------- src/public_include/decaf/decaf_448.hxx | 584 ---------------------- 5 files changed, 13 insertions(+), 2455 deletions(-) delete mode 100644 src/public_include/decaf/decaf_255.h delete mode 100644 src/public_include/decaf/decaf_255.hxx delete mode 100644 src/public_include/decaf/decaf_448.h delete mode 100644 src/public_include/decaf/decaf_448.hxx diff --git a/Makefile b/Makefile index 0a27616..8b71c25 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ endif WARNFLAGS = -pedantic -Wall -Wextra -Werror -Wunreachable-code \ -Wmissing-declarations -Wunused-function -Wno-overlength-strings $(EXWARN) -INCFLAGS = -Isrc/include -Isrc/public_include +INCFLAGS = -Isrc/include -Isrc/public_include -Ibuild/include LANGFLAGS = -std=c99 -fno-strict-aliasing LANGXXFLAGS = -fno-strict-aliasing GENFLAGS = -ffunction-sections -fdata-sections -fvisibility=hidden -fomit-frame-pointer -fPIC @@ -79,10 +79,15 @@ SAGE ?= sage SAGES= $(shell ls test/*.sage) BUILDPYS= $(SAGES:test/%.sage=$(BUILD_PY)/%.py) -.PHONY: clean all test bench todo doc lib bat sage sagetest +.PHONY: clean all test bench todo doc lib bat sage sagetest gen_headers .PRECIOUS: $(BUILD_ASM)/%.s $(BUILD_C)/%.c $(BUILD_IBIN)/% -HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp +GEN_HEADERS=\ + $(BUILD_INC)/decaf/decaf_255.h \ + $(BUILD_INC)/decaf/decaf_448.h \ + $(BUILD_INC)/decaf/decaf_255.hxx \ + $(BUILD_INC)/decaf/decaf_448.hxx +HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp $(GEN_HEADERS) HEADERSXX = $(HEADERS) $(shell find . -name "*.hxx") # components needed by the lib @@ -123,6 +128,11 @@ $(BUILD_OBJ)/timestamp: $(BUILD_OBJ)/%.o: $(BUILD_ASM)/%.s $(ASM) $(ASFLAGS) -c -o $@ $< +$(GEN_HEADERS): gen_headers + +gen_headers: src/gen_headers/*.py + python -B src/gen_headers/main.py --hpre=$(BUILD_INC) --cpre=$(BUILD_C) + ################################################################ # Per-field code: call with field, arch ################################################################ @@ -178,7 +188,6 @@ $(eval $(call define_curve,ed25519,p25519)) $(eval $(call define_field,p448,arch_x86_64)) $(eval $(call define_curve,ed448goldilocks,p448)) - # The shakesum utility is in the public bin directory. $(BUILD_BIN)/shakesum: $(BUILD_OBJ)/shakesum.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/utils.o $(LD) $(LDFLAGS) -o $@ $^ diff --git a/src/public_include/decaf/decaf_255.h b/src/public_include/decaf/decaf_255.h deleted file mode 100644 index 09968ab..0000000 --- a/src/public_include/decaf/decaf_255.h +++ /dev/null @@ -1,640 +0,0 @@ -/** - * @file decaf/decaf_255.h - * @author Mike Hamburg - * - * @copyright - * Copyright (c) 2015 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * - * @brief A group of prime order p, based on Ed25519. - */ -#ifndef __DECAF_255_H__ -#define __DECAF_255_H__ 1 - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define DECAF_255_LIMBS (320/DECAF_WORD_BITS) -#define DECAF_255_SCALAR_BITS 253 -#define DECAF_255_SCALAR_LIMBS (256/DECAF_WORD_BITS) - -/** Galois field element internal structure */ -#ifndef __DECAF_255_GF_DEFINED__ -#define __DECAF_255_GF_DEFINED__ 1 -typedef struct gf_25519_s { - /** @cond internal */ - decaf_word_t limb[DECAF_255_LIMBS]; - /** @endcond */ -} __attribute__((aligned(32))) gf_25519_s, gf_25519_t[1]; -#endif /* __DECAF_255_GF_DEFINED__ */ - -/** Number of bytes in a serialized point. */ -#define DECAF_255_SER_BYTES 32 - -/** Number of bytes in a serialized scalar. */ -#define DECAF_255_SCALAR_BYTES 32 - -/** Twisted Edwards (-1,d-1) extended homogeneous coordinates */ -typedef struct decaf_255_point_s { - /** @cond internal */ - gf_25519_t x,y,z,t; - /** @endcond */ -} decaf_255_point_t[1]; - -/** Precomputed table based on a point. Can be trivial implementation. */ -struct decaf_255_precomputed_s; - -/** Precomputed table based on a point. Can be trivial implementation. */ -typedef struct decaf_255_precomputed_s decaf_255_precomputed_s; - -/** Size and alignment of precomputed point tables. */ -extern const size_t sizeof_decaf_255_precomputed_s API_VIS, alignof_decaf_255_precomputed_s API_VIS; - -/** Scalar is stored packed, because we don't need the speed. */ -typedef struct decaf_255_scalar_s { - /** @cond internal */ - decaf_word_t limb[DECAF_255_SCALAR_LIMBS]; - /** @endcond */ -} decaf_255_scalar_t[1]; - -/** A scalar equal to 1. */ -extern const decaf_255_scalar_t decaf_255_scalar_one API_VIS; - -/** A scalar equal to 0. */ -extern const decaf_255_scalar_t decaf_255_scalar_zero API_VIS; - -/** The identity point on the curve. */ -extern const decaf_255_point_t decaf_255_point_identity API_VIS; - -/** An arbitrarily chosen base point on the curve. */ -extern const decaf_255_point_t decaf_255_point_base API_VIS; - -/** Precomputed table for the base point on the curve. */ -extern const struct decaf_255_precomputed_s *decaf_255_precomputed_base API_VIS; - -/** - * @brief Read a scalar from wire format or from bytes. - * - * @param [in] ser Serialized form of a scalar. - * @param [out] out Deserialized form. - * - * @retval DECAF_SUCCESS The scalar was correctly encoded. - * @retval DECAF_FAILURE The scalar was greater than the modulus, - * and has been reduced modulo that modulus. - */ -decaf_error_t decaf_255_scalar_decode ( - decaf_255_scalar_t out, - const unsigned char ser[DECAF_255_SCALAR_BYTES] -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Read a scalar from wire format or from bytes. Reduces mod - * scalar prime. - * - * @param [in] ser Serialized form of a scalar. - * @param [in] ser_len Length of serialized form. - * @param [out] out Deserialized form. - */ -void decaf_255_scalar_decode_long ( - decaf_255_scalar_t out, - const unsigned char *ser, - size_t ser_len -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Serialize a scalar to wire format. - * - * @param [out] ser Serialized form of a scalar. - * @param [in] s Deserialized scalar. - */ -void decaf_255_scalar_encode ( - unsigned char ser[DECAF_255_SCALAR_BYTES], - const decaf_255_scalar_t s -) API_VIS NONNULL2 NOINLINE NOINLINE; - -/** - * @brief Add two scalars. The scalars may use the same memory. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @param [out] out a+b. - */ -void decaf_255_scalar_add ( - decaf_255_scalar_t out, - const decaf_255_scalar_t a, - const decaf_255_scalar_t b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Compare two scalars. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @retval DECAF_TRUE The scalars are equal. - * @retval DECAF_FALSE The scalars are not equal. - */ -decaf_bool_t decaf_255_scalar_eq ( - const decaf_255_scalar_t a, - const decaf_255_scalar_t b -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Subtract two scalars. The scalars may use the same memory. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @param [out] out a-b. - */ -void decaf_255_scalar_sub ( - decaf_255_scalar_t out, - const decaf_255_scalar_t a, - const decaf_255_scalar_t b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Multiply two scalars. The scalars may use the same memory. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @param [out] out a*b. - */ -void decaf_255_scalar_mul ( - decaf_255_scalar_t out, - const decaf_255_scalar_t a, - const decaf_255_scalar_t b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Invert a scalar. When passed zero, return 0. The input and output may alias. - * @param [in] a A scalar. - * @param [out] out 1/a. - * @return DECAF_SUCCESS The input is nonzero. - */ -decaf_error_t decaf_255_scalar_invert ( - decaf_255_scalar_t out, - const decaf_255_scalar_t a -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Copy a scalar. The scalars may use the same memory, in which - * case this function does nothing. - * @param [in] a A scalar. - * @param [out] out Will become a copy of a. - */ -static inline void NONNULL2 decaf_255_scalar_copy ( - decaf_255_scalar_t out, - const decaf_255_scalar_t a -) { - *out = *a; -} - -/** - * @brief Set a scalar to an unsigned integer. - * @param [in] a An integer. - * @param [out] out Will become equal to a. - */ -void decaf_255_scalar_set_unsigned ( - decaf_255_scalar_t out, - decaf_word_t a -) API_VIS NONNULL1; - -/** - * @brief Encode a point as a sequence of bytes. - * - * @param [out] ser The byte representation of the point. - * @param [in] pt The point to encode. - */ -void decaf_255_point_encode ( - uint8_t ser[DECAF_255_SER_BYTES], - const decaf_255_point_t pt -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Decode a point from a sequence of bytes. - * - * Every point has a unique encoding, so not every - * sequence of bytes is a valid encoding. If an invalid - * encoding is given, the output is undefined. - * - * @param [out] pt The decoded point. - * @param [in] ser The serialized version of the point. - * @param [in] allow_identity DECAF_TRUE if the identity is a legal input. - * @retval DECAF_SUCCESS The decoding succeeded. - * @retval DECAF_FAILURE The decoding didn't succeed, because - * ser does not represent a point. - */ -decaf_error_t decaf_255_point_decode ( - decaf_255_point_t pt, - const uint8_t ser[DECAF_255_SER_BYTES], - decaf_bool_t allow_identity -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Copy a point. The input and output may alias, - * in which case this function does nothing. - * - * @param [out] a A copy of the point. - * @param [in] b Any point. - */ -static inline void NONNULL2 decaf_255_point_copy ( - decaf_255_point_t a, - const decaf_255_point_t b -) { - *a=*b; -} - -/** - * @brief Test whether two points are equal. If yes, return - * DECAF_TRUE, else return DECAF_FALSE. - * - * @param [in] a A point. - * @param [in] b Another point. - * @retval DECAF_TRUE The points are equal. - * @retval DECAF_FALSE The points are not equal. - */ -decaf_bool_t decaf_255_point_eq ( - const decaf_255_point_t a, - const decaf_255_point_t b -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Add two points to produce a third point. The - * input points and output point can be pointers to the same - * memory. - * - * @param [out] sum The sum a+b. - * @param [in] a An addend. - * @param [in] b An addend. - */ -void decaf_255_point_add ( - decaf_255_point_t sum, - const decaf_255_point_t a, - const decaf_255_point_t b -) API_VIS NONNULL3; - -/** - * @brief Double a point. Equivalent to - * decaf_255_point_add(two_a,a,a), but potentially faster. - * - * @param [out] two_a The sum a+a. - * @param [in] a A point. - */ -void decaf_255_point_double ( - decaf_255_point_t two_a, - const decaf_255_point_t a -) API_VIS NONNULL2; - -/** - * @brief Subtract two points to produce a third point. The - * input points and output point can be pointers to the same - * memory. - * - * @param [out] diff The difference a-b. - * @param [in] a The minuend. - * @param [in] b The subtrahend. - */ -void decaf_255_point_sub ( - decaf_255_point_t diff, - const decaf_255_point_t a, - const decaf_255_point_t b -) API_VIS NONNULL3; - -/** - * @brief Negate a point to produce another point. The input - * and output points can use the same memory. - * - * @param [out] nega The negated input point - * @param [in] a The input point. - */ -void decaf_255_point_negate ( - decaf_255_point_t nega, - const decaf_255_point_t a -) API_VIS NONNULL2; - -/** - * @brief Multiply a base point by a scalar: scaled = scalar*base. - * - * @param [out] scaled The scaled point base*scalar - * @param [in] base The point to be scaled. - * @param [in] scalar The scalar to multiply by. - */ -void decaf_255_point_scalarmul ( - decaf_255_point_t scaled, - const decaf_255_point_t base, - const decaf_255_scalar_t scalar -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Multiply a base point by a scalar: scaled = scalar*base. - * This function operates directly on serialized forms. - * - * @warning This function is experimental. It may not be supported - * long-term. - * - * @param [out] scaled The scaled point base*scalar - * @param [in] base The point to be scaled. - * @param [in] scalar The scalar to multiply by. - * @param [in] allow_identity Allow the input to be the identity. - * @param [in] short_circuit Allow a fast return if the input is illegal. - * - * @retval DECAF_SUCCESS The scalarmul succeeded. - * @retval DECAF_FAILURE The scalarmul didn't succeed, because - * base does not represent a point. - */ -decaf_error_t decaf_255_direct_scalarmul ( - uint8_t scaled[DECAF_255_SER_BYTES], - const uint8_t base[DECAF_255_SER_BYTES], - const decaf_255_scalar_t scalar, - decaf_bool_t allow_identity, - decaf_bool_t short_circuit -) API_VIS NONNULL3 WARN_UNUSED NOINLINE; - -/** - * @brief Precompute a table for fast scalar multiplication. - * Some implementations do not include precomputed points; for - * those implementations, this implementation simply copies the - * point. - * - * @param [out] a A precomputed table of multiples of the point. - * @param [in] b Any point. - */ -void decaf_255_precompute ( - decaf_255_precomputed_s *a, - const decaf_255_point_t b -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Multiply a precomputed base point by a scalar: - * scaled = scalar*base. - * Some implementations do not include precomputed points; for - * those implementations, this function is the same as - * decaf_255_point_scalarmul - * - * @param [out] scaled The scaled point base*scalar - * @param [in] base The point to be scaled. - * @param [in] scalar The scalar to multiply by. - */ -void decaf_255_precomputed_scalarmul ( - decaf_255_point_t scaled, - const decaf_255_precomputed_s *base, - const decaf_255_scalar_t scalar -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Multiply two base points by two scalars: - * scaled = scalar1*base1 + scalar2*base2. - * - * Equivalent to two calls to decaf_255_point_scalarmul, but may be - * faster. - * - * @param [out] combo The linear combination scalar1*base1 + scalar2*base2. - * @param [in] base1 A first point to be scaled. - * @param [in] scalar1 A first scalar to multiply by. - * @param [in] base2 A second point to be scaled. - * @param [in] scalar2 A second scalar to multiply by. - */ -void decaf_255_point_double_scalarmul ( - decaf_255_point_t combo, - const decaf_255_point_t base1, - const decaf_255_scalar_t scalar1, - const decaf_255_point_t base2, - const decaf_255_scalar_t scalar2 -) API_VIS NONNULL5 NOINLINE; - -/* - * @brief Multiply one base point by two scalars: - * a1 = scalar1 * base - * a2 = scalar2 * base - * - * Equivalent to two calls to decaf_255_point_scalarmul, but may be - * faster. - * - * @param [out] a1 The first multiple - * @param [out] a2 The second multiple - * @param [in] base1 A point to be scaled. - * @param [in] scalar1 A first scalar to multiply by. - * @param [in] scalar2 A second scalar to multiply by. - */ -void decaf_255_point_dual_scalarmul ( - decaf_255_point_t a1, - decaf_255_point_t a2, - const decaf_255_point_t b, - const decaf_255_scalar_t scalar1, - const decaf_255_scalar_t scalar2 -) API_VIS NONNULL5 NOINLINE; - -/** - * @brief Multiply two base points by two scalars: - * scaled = scalar1*decaf_255_point_base + scalar2*base2. - * - * Otherwise equivalent to decaf_255_point_double_scalarmul, but may be - * faster at the expense of being variable time. - * - * @param [out] combo The linear combination scalar1*base + scalar2*base2. - * @param [in] scalar1 A first scalar to multiply by. - * @param [in] base2 A second point to be scaled. - * @param [in] scalar2 A second scalar to multiply by. - * - * @warning: This function takes variable time, and may leak the scalars - * used. It is designed for signature verification. - */ -void decaf_255_base_double_scalarmul_non_secret ( - decaf_255_point_t combo, - const decaf_255_scalar_t scalar1, - const decaf_255_point_t base2, - const decaf_255_scalar_t scalar2 -) API_VIS NONNULL4 NOINLINE; - -/** - * @brief Constant-time decision between two points. If pick_b - * is zero, out = a; else out = b. - * - * @param [out] q The output. It may be the same as either input. - * @param [in] a Any point. - * @param [in] b Any point. - * @param [in] pick_b If nonzero, choose point b. - */ -void decaf_255_point_cond_sel ( - decaf_255_point_t out, - const decaf_255_point_t a, - const decaf_255_point_t b, - decaf_word_t pick_b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Constant-time decision between two scalars. If pick_b - * is zero, out = a; else out = b. - * - * @param [out] q The output. It may be the same as either input. - * @param [in] a Any scalar. - * @param [in] b Any scalar. - * @param [in] pick_b If nonzero, choose scalar b. - */ -void decaf_255_scalar_cond_sel ( - decaf_255_scalar_t out, - const decaf_255_scalar_t a, - const decaf_255_scalar_t b, - decaf_word_t pick_b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Test that a point is valid, for debugging purposes. - * - * @param [in] toTest The point to test. - * @retval DECAF_TRUE The point is valid. - * @retval DECAF_FALSE The point is invalid. - */ -decaf_bool_t decaf_255_point_valid ( - const decaf_255_point_t toTest -) API_VIS WARN_UNUSED NONNULL1 NOINLINE; - -/** - * @brief Torque a point, for debugging purposes. The output - * will be equal to the input. - * - * @param [out] q The point to torque. - * @param [in] p The point to torque. - */ -void decaf_255_point_debugging_torque ( - decaf_255_point_t q, - const decaf_255_point_t p -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Projectively scale a point, for debugging purposes. - * The output will be equal to the input, and will be valid - * even if the factor is zero. - * - * @param [out] q The point to scale. - * @param [in] p The point to scale. - * @param [in] factor Serialized GF factor to scale. - */ -void decaf_255_point_debugging_pscale ( - decaf_255_point_t q, - const decaf_255_point_t p, - const unsigned char factor[DECAF_255_SER_BYTES] -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Almost-Elligator-like hash to curve. - * - * Call this function with the output of a hash to make a hash to the curve. - * - * This function runs Elligator2 on the decaf_255 Jacobi quartic model. It then - * uses the isogeny to put the result in twisted Edwards form. As a result, - * it is safe (cannot produce points of order 4), and would be compatible with - * hypothetical other implementations of Decaf using a Montgomery or untwisted - * Edwards model. - * - * Unlike Elligator, this function may be up to 4:1 on [0,(p-1)/2]: - * A factor of 2 due to the isogeny. - * A factor of 2 because we quotient out the 2-torsion. - * - * This makes it about 8:1 overall, or 16:1 overall on curves with cofactor 8. - * - * Negating the input (mod q) results in the same point. Inverting the input - * (mod q) results in the negative point. This is the same as Elligator. - * - * This function isn't quite indifferentiable from a random oracle. - * However, it is suitable for many protocols, including SPEKE and SPAKE2 EE. - * Furthermore, calling it twice with independent seeds and adding the results - * is indifferentiable from a random oracle. - * - * @param [in] hashed_data Output of some hash function. - * @param [out] pt The data hashed to the curve. - */ -void -decaf_255_point_from_hash_nonuniform ( - decaf_255_point_t pt, - const unsigned char hashed_data[DECAF_255_SER_BYTES] -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Indifferentiable hash function encoding to curve. - * - * Equivalent to calling decaf_255_point_from_hash_nonuniform twice and adding. - * - * @param [in] hashed_data Output of some hash function. - * @param [out] pt The data hashed to the curve. - */ -void decaf_255_point_from_hash_uniform ( - decaf_255_point_t pt, - const unsigned char hashed_data[2*DECAF_255_SER_BYTES] -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Inverse of elligator-like hash to curve. - * - * This function writes to the buffer, to make it so that - * decaf_255_point_from_hash_nonuniform(buffer) = pt if - * possible. Since there may be multiple preimages, the - * "which" parameter chooses between them. To ensure uniform - * inverse sampling, this function succeeds or fails - * independently for different "which" values. - * - * @param [out] recovered_hash Encoded data. - * @param [in] pt The point to encode. - * @param [in] which A value determining which inverse point - * to return. - * - * @retval DECAF_SUCCESS The inverse succeeded. - * @retval DECAF_FAILURE The inverse failed. - */ -decaf_error_t -decaf_255_invert_elligator_nonuniform ( - unsigned char recovered_hash[DECAF_255_SER_BYTES], - const decaf_255_point_t pt, - uint16_t which -) API_VIS NONNULL2 NOINLINE WARN_UNUSED; - -/** - * @brief Inverse of elligator-like hash to curve. - * - * This function writes to the buffer, to make it so that - * decaf_255_point_from_hash_uniform(buffer) = pt if - * possible. Since there may be multiple preimages, the - * "which" parameter chooses between them. To ensure uniform - * inverse sampling, this function succeeds or fails - * independently for different "which" values. - * - * @param [out] recovered_hash Encoded data. - * @param [in] pt The point to encode. - * @param [in] which A value determining which inverse point - * to return. - * - * @retval DECAF_SUCCESS The inverse succeeded. - * @retval DECAF_FAILURE The inverse failed. - */ -decaf_error_t -decaf_255_invert_elligator_uniform ( - unsigned char recovered_hash[2*DECAF_255_SER_BYTES], - const decaf_255_point_t pt, - uint16_t which -) API_VIS NONNULL2 NOINLINE WARN_UNUSED; - -/** - * @brief Overwrite scalar with zeros. - */ -void decaf_255_scalar_destroy ( - decaf_255_scalar_t scalar -) NONNULL1 API_VIS; - -/** - * @brief Overwrite point with zeros. - * @todo Use this internally. - */ -void decaf_255_point_destroy ( - decaf_255_point_t point -) NONNULL1 API_VIS; - -/** - * @brief Overwrite precomputed table with zeros. - */ -void decaf_255_precomputed_destroy ( - decaf_255_precomputed_s *pre -) NONNULL1 API_VIS; - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __DECAF_255_H__ */ diff --git a/src/public_include/decaf/decaf_255.hxx b/src/public_include/decaf/decaf_255.hxx deleted file mode 100644 index 6a9a77d..0000000 --- a/src/public_include/decaf/decaf_255.hxx +++ /dev/null @@ -1,586 +0,0 @@ -/** - * @file decaf/decaf_255.hxx - * @author Mike Hamburg - * - * @copyright - * Copyright (c) 2015 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * - * @brief A group of prime order p, C++ wrapper. - * - * The Decaf library implements cryptographic operations on a an elliptic curve - * group of prime order p. It accomplishes this by using a twisted Edwards - * curve (isogenous to Curve25519) and wiping out the cofactor. - * - * The formulas are all complete and have no special cases, except that - * decaf_255_decode can fail because not every sequence of bytes is a valid group - * element. - * - * The formulas contain no data-dependent branches, timing or memory accesses, - * except for decaf_255_base_double_scalarmul_non_secret. - */ -#ifndef __DECAF_255_HXX__ -#define __DECAF_255_HXX__ 1 - -/** This code uses posix_memalign. */ -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 600 -#endif -#include -#include /* for memcpy */ - -#include -#include -#include -#include -#include - -/** @cond internal */ -#if __cplusplus >= 201103L -#define NOEXCEPT noexcept -#else -#define NOEXCEPT throw() -#endif -/** @endcond */ - -namespace decaf { - -/** - * @brief Curve25519/Decaf instantiation of group. - */ -struct IsoEd25519 { - -/** The name of the curve */ -static inline const char *name() { return "IsoEd25519"; } - -/** The curve's cofactor (removed, but useful for testing) */ -static const int REMOVED_COFACTOR = 8; - -/** Residue class of field modulus: p == this mod 2*(this-1) */ -static const int FIELD_MODULUS_TYPE = 5; - -/** @cond internal */ -class Point; -class Precomputed; -/** @endcond */ - -/** - * @brief A scalar modulo the curve order. - * Supports the usual arithmetic operations, all in constant time. - * FIXME: make it clearer which init-from-buffer operations reject scalars that are too big. - */ -class Scalar : public Serializable { -private: - /** @brief wrapped C type */ - typedef decaf_255_scalar_t Wrapped; - -public: - /** @brief Size of a serialized element */ - static const size_t SER_BYTES = DECAF_255_SCALAR_BYTES; - - /** @brief access to the underlying scalar object */ - Wrapped s; - - /** @brief Don't initialize. */ - inline Scalar(const NOINIT &) NOEXCEPT {} - - /** @brief Set to an unsigned word */ - inline Scalar(const decaf_word_t w) NOEXCEPT { *this = w; } - - /** @brief Set to a signed word */ - inline Scalar(const int w) NOEXCEPT { *this = w; } - - /** @brief Construct from RNG */ - inline explicit Scalar(Rng &rng) NOEXCEPT { - FixedArrayBuffer sb(rng); - *this = sb; - } - - /** @brief Construct from decaf_scalar_t object. */ - inline Scalar(const Wrapped &t = decaf_255_scalar_zero) NOEXCEPT { decaf_255_scalar_copy(s,t); } - - /** @brief Copy constructor. */ - inline Scalar(const Scalar &x) NOEXCEPT { *this = x; } - - /** @brief Construct from arbitrary-length little-endian byte sequence. */ - inline Scalar(const Block &buffer) NOEXCEPT { *this = buffer; } - - /** @brief Serializable instance */ - inline size_t serSize() const NOEXCEPT { return SER_BYTES; } - - /** @brief Serializable instance */ - inline void serializeInto(unsigned char *buffer) const NOEXCEPT { - decaf_255_scalar_encode(buffer, s); - } - - /** @brief Assignment. */ - inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_255_scalar_copy(s,x.s); return *this; } - - /** @brief Assign from unsigned word. */ - inline Scalar& operator=(decaf_word_t w) NOEXCEPT { decaf_255_scalar_set_unsigned(s,w); return *this; } - - /** @brief Assign from signed int. */ - inline Scalar& operator=(int w) NOEXCEPT { - Scalar t(-(decaf_word_t)INT_MIN); - decaf_255_scalar_set_unsigned(s,(decaf_word_t)w - (decaf_word_t)INT_MIN); - *this -= t; - return *this; - } - - /** Destructor securely zeorizes the scalar. */ - inline ~Scalar() NOEXCEPT { decaf_255_scalar_destroy(s); } - - /** @brief Assign from arbitrary-length little-endian byte sequence in a Block. */ - inline Scalar &operator=(const Block &bl) NOEXCEPT { - decaf_255_scalar_decode_long(s,bl.data(),bl.size()); return *this; - } - - /** - * @brief Decode from correct-length little-endian byte sequence. - * @return DECAF_FAILURE if the scalar is greater than or equal to the group order q. - */ - static inline decaf_error_t __attribute__((warn_unused_result)) decode ( - Scalar &sc, const FixedBlock buffer - ) NOEXCEPT { - return decaf_255_scalar_decode(sc.s,buffer.data()); - } - - /** Add. */ - inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_add(r.s,s,q.s); return r; } - - /** Add to this. */ - inline Scalar &operator+=(const Scalar &q) NOEXCEPT { decaf_255_scalar_add(s,s,q.s); return *this; } - - /** Subtract. */ - inline Scalar operator- (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,s,q.s); return r; } - - /** Subtract from this. */ - inline Scalar &operator-=(const Scalar &q) NOEXCEPT { decaf_255_scalar_sub(s,s,q.s); return *this; } - - /** Multiply */ - inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_mul(r.s,s,q.s); return r; } - - /** Multiply into this. */ - inline Scalar &operator*=(const Scalar &q) NOEXCEPT { decaf_255_scalar_mul(s,s,q.s); return *this; } - - /** Negate */ - inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,decaf_255_scalar_zero,s); return r; } - - /** @brief Invert with Fermat's Little Theorem (slow!). If *this == 0, return 0. */ - inline Scalar inverse() const throw(CryptoException) { - Scalar r; - if (DECAF_SUCCESS != decaf_255_scalar_invert(r.s,s)) { - throw CryptoException(); - } - return r; - } - - /** @brief Divide by inverting q. If q == 0, return 0. */ - inline Scalar operator/ (const Scalar &q) const throw(CryptoException) { return *this * q.inverse(); } - - /** @brief Divide by inverting q. If q == 0, return 0. */ - inline Scalar &operator/=(const Scalar &q) throw(CryptoException) { return *this *= q.inverse(); } - - /** @brief Compare in constant time */ - inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); } - - /** @brief Compare in constant time */ - inline bool operator==(const Scalar &q) const NOEXCEPT { return !!decaf_255_scalar_eq(s,q.s); } - - /** @brief Scalarmul with scalar on left. */ - inline Point operator* (const Point &q) const NOEXCEPT { return q * (*this); } - - /** @brief Scalarmul-precomputed with scalar on left. */ - inline Point operator* (const Precomputed &q) const NOEXCEPT { return q * (*this); } - - /** @brief Direct scalar multiplication. */ - inline SecureBuffer direct_scalarmul( - const Block &in, - decaf_bool_t allow_identity=DECAF_FALSE, - decaf_bool_t short_circuit=DECAF_TRUE - ) const throw(CryptoException); -}; - -/** - * @brief Element of prime-order group. - */ -class Point : public Serializable { -private: - /** @brief wrapped C type */ - typedef decaf_255_point_t Wrapped; - -public: - /** @brief Size of a serialized element */ - static const size_t SER_BYTES = DECAF_255_SER_BYTES; - - /** @brief Bytes required for hash */ - static const size_t HASH_BYTES = SER_BYTES; - - /** @brief Size of a stegged element */ - static const size_t STEG_BYTES = HASH_BYTES * 2; - - /** The c-level object. */ - Wrapped p; - - /** @brief Don't initialize. */ - inline Point(const NOINIT &) NOEXCEPT {} - - /** @brief Constructor sets to identity by default. */ - inline Point(const Wrapped &q = decaf_255_point_identity) NOEXCEPT { decaf_255_point_copy(p,q); } - - /** @brief Copy constructor. */ - inline Point(const Point &q) NOEXCEPT { *this = q; } - - /** @brief Assignment. */ - inline Point& operator=(const Point &q) NOEXCEPT { decaf_255_point_copy(p,q.p); return *this; } - - /** @brief Destructor securely zeorizes the point. */ - inline ~Point() NOEXCEPT { decaf_255_point_destroy(p); } - - /** @brief Construct from RNG */ - inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT { - if (uniform) { - FixedArrayBuffer<2*HASH_BYTES> b(rng); - set_to_hash(b); - } else { - FixedArrayBuffer b(rng); - set_to_hash(b); - } - } - - /** - * @brief Initialize from a fixed-length byte string. - * The all-zero string maps to the identity. - * - * @throw CryptoException the string was the wrong length, or wasn't the encoding of a point, - * or was the identity and allow_identity was DECAF_FALSE. - */ - inline explicit Point(const FixedBlock &buffer, decaf_bool_t allow_identity=DECAF_TRUE) - throw(CryptoException) { - if (DECAF_SUCCESS != decode(*this,buffer,allow_identity)) { - throw CryptoException(); - } - } - - /** - * @brief Initialize from C++ fixed-length byte string. - * The all-zero string maps to the identity. - * - * @retval DECAF_SUCCESS the string was successfully decoded. - * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point, - * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. - */ - static inline decaf_error_t __attribute__((warn_unused_result)) decode ( - Point &p, const FixedBlock &buffer, decaf_bool_t allow_identity=DECAF_TRUE - ) NOEXCEPT { - return decaf_255_point_decode(p.p,buffer.data(),allow_identity); - } - - /** - * @brief Map uniformly to the curve from a hash buffer. - * The empty or all-zero string maps to the identity, as does the string "\x01". - * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, - * but the buffer will be zero-padded on the right. - */ - static inline Point from_hash ( const Block &s ) NOEXCEPT { - Point p((NOINIT())); p.set_to_hash(s); return p; - } - - /** - * @brief Map to the curve from a hash buffer. - * The empty or all-zero string maps to the identity, as does the string "\x01". - * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, - * but the buffer will be zero-padded on the right. - */ - inline void set_to_hash( const Block &s ) NOEXCEPT { - if (s.size() < HASH_BYTES) { - SecureBuffer b(HASH_BYTES); - memcpy(b.data(), s.data(), s.size()); - decaf_255_point_from_hash_nonuniform(p,b.data()); - } else if (s.size() == HASH_BYTES) { - decaf_255_point_from_hash_nonuniform(p,s.data()); - } else if (s.size() < 2*HASH_BYTES) { - SecureBuffer b(2*HASH_BYTES); - memcpy(b.data(), s.data(), s.size()); - decaf_255_point_from_hash_uniform(p,b.data()); - } else { - decaf_255_point_from_hash_uniform(p,s.data()); - } - } - - /** - * @brief Encode to string. The identity encodes to the all-zero string. - */ - inline operator SecureBuffer() const { - SecureBuffer buffer(SER_BYTES); - decaf_255_point_encode(buffer.data(), p); - return buffer; - } - - /** @brief Serializable instance */ - inline size_t serSize() const NOEXCEPT { return SER_BYTES; } - - /** @brief Serializable instance */ - inline void serializeInto(unsigned char *buffer) const NOEXCEPT { - decaf_255_point_encode(buffer, p); - } - - /** @brief Point add. */ - inline Point operator+ (const Point &q) const NOEXCEPT { Point r((NOINIT())); decaf_255_point_add(r.p,p,q.p); return r; } - - /** @brief Point add. */ - inline Point &operator+=(const Point &q) NOEXCEPT { decaf_255_point_add(p,p,q.p); return *this; } - - /** @brief Point subtract. */ - inline Point operator- (const Point &q) const NOEXCEPT { Point r((NOINIT())); decaf_255_point_sub(r.p,p,q.p); return r; } - - /** @brief Point subtract. */ - inline Point &operator-=(const Point &q) NOEXCEPT { decaf_255_point_sub(p,p,q.p); return *this; } - - /** @brief Point negate. */ - inline Point operator- () const NOEXCEPT { Point r((NOINIT())); decaf_255_point_negate(r.p,p); return r; } - - /** @brief Double the point out of place. */ - inline Point times_two () const NOEXCEPT { Point r((NOINIT())); decaf_255_point_double(r.p,p); return r; } - - /** @brief Double the point in place. */ - inline Point &double_in_place() NOEXCEPT { decaf_255_point_double(p,p); return *this; } - - /** @brief Constant-time compare. */ - inline bool operator!=(const Point &q) const NOEXCEPT { return ! decaf_255_point_eq(p,q.p); } - - /** @brief Constant-time compare. */ - inline bool operator==(const Point &q) const NOEXCEPT { return !!decaf_255_point_eq(p,q.p); } - - /** @brief Scalar multiply. */ - inline Point operator* (const Scalar &s) const NOEXCEPT { Point r((NOINIT())); decaf_255_point_scalarmul(r.p,p,s.s); return r; } - - /** @brief Scalar multiply in place. */ - inline Point &operator*=(const Scalar &s) NOEXCEPT { decaf_255_point_scalarmul(p,p,s.s); return *this; } - - /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ - inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); } - - /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ - inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); } - - /** @brief Validate / sanity check */ - inline bool validate() const NOEXCEPT { return decaf_255_point_valid(p); } - - /** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ - static inline Point double_scalarmul ( - const Point &q, const Scalar &qs, const Point &r, const Scalar &rs - ) NOEXCEPT { - Point p((NOINIT())); decaf_255_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p; - } - - /** @brief Dual-scalar multiply, equivalent to this*r1, this*r2 but faster. */ - inline void dual_scalarmul ( - Point &q1, Point &q2, const Scalar &r1, const Scalar &r2 - ) const NOEXCEPT { - decaf_255_point_dual_scalarmul(q1.p,q2.p,p,r1.s,r2.s); - } - - /** - * @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. - * For those who like their scalars before the point. - */ - static inline Point double_scalarmul ( - const Scalar &qs, const Point &q, const Scalar &rs, const Point &r - ) NOEXCEPT { - return double_scalarmul(q,qs,r,rs); - } - - /** - * @brief Double-scalar multiply: this point by the first scalar and base by the second scalar. - * @warning This function takes variable time, and may leak the scalars (or points, but currently - * it doesn't). - */ - inline Point non_secret_combo_with_base(const Scalar &s, const Scalar &s_base) NOEXCEPT { - Point r((NOINIT())); decaf_255_base_double_scalarmul_non_secret(r.p,s_base.s,p,s.s); return r; - } - - /** @brief Return a point equal to *this, whose internal data is rotated by a torsion element. */ - inline Point debugging_torque() const NOEXCEPT { - Point q; - decaf_255_point_debugging_torque(q.p,p); - return q; - } - - /** @brief Return a point equal to *this, whose internal data has a modified representation. */ - inline Point debugging_pscale(const FixedBlock factor) const NOEXCEPT { - Point q; - decaf_255_point_debugging_pscale(q.p,p,factor.data()); - return q; - } - - /** @brief Return a point equal to *this, whose internal data has a randomized representation. */ - inline Point debugging_pscale(Rng &r) const NOEXCEPT { - FixedArrayBuffer sb(r); - return debugging_pscale(sb); - } - - /** - * Modify buffer so that Point::from_hash(Buffer) == *this, and return DECAF_SUCCESS; - * or leave buf unmodified and return DECAF_FAILURE. - */ - inline decaf_error_t invert_elligator ( - Buffer buf, uint16_t hint - ) const NOEXCEPT { - unsigned char buf2[2*HASH_BYTES]; - memset(buf2,0,sizeof(buf2)); - memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size()); - decaf_bool_t ret; - if (buf.size() > HASH_BYTES) { - ret = decaf_successful(decaf_255_invert_elligator_uniform(buf2, p, hint)); - } else { - ret = decaf_successful(decaf_255_invert_elligator_nonuniform(buf2, p, hint)); - } - if (buf.size() < HASH_BYTES) { - ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); - } - if (ret) { - /* TODO: make this constant time?? */ - memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); - } - decaf_bzero(buf2,sizeof(buf2)); - return decaf_succeed_if(ret); - } - - /** @brief Steganographically encode this */ - inline SecureBuffer steg_encode(Rng &rng, size_t size=STEG_BYTES) const throw(std::bad_alloc, LengthException) { - if (size <= HASH_BYTES + 4 || size > 2*HASH_BYTES) throw LengthException(); - SecureBuffer out(STEG_BYTES); - decaf_error_t done; - do { - rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1)); - done = invert_elligator(out, out[HASH_BYTES-1]); - } while (!decaf_successful(done)); - return out; - } - - /** @brief Return the base point */ - static inline const Point base() NOEXCEPT { return Point(decaf_255_point_base); } - - /** @brief Return the identity point */ - static inline const Point identity() NOEXCEPT { return Point(decaf_255_point_identity); } -}; - -/** - * @brief Precomputed table of points. - * Minor difficulties arise here because the decaf API doesn't expose, as a constant, how big such an object is. - * Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to - * stack-allocate a 15kiB object anyway. - */ - -/** @cond internal */ -typedef decaf_255_precomputed_s Precomputed_U; -/** @endcond */ -class Precomputed - /** @cond internal */ - : protected OwnedOrUnowned - /** @endcond */ -{ -public: - - /** Destructor securely zeorizes the memory. */ - inline ~Precomputed() NOEXCEPT { clear(); } - - /** - * @brief Initialize from underlying type, declared as a reference to prevent - * it from being called with 0, thereby breaking override. - * - * The underlying object must remain valid throughout the lifetime of this one. - * - * By default, initializes to the table for the base point. - * - * @warning The empty initializer makes this equal to base, unlike the empty - * initializer for points which makes this equal to the identity. - */ - inline Precomputed ( - const Precomputed_U &yours = *defaultValue() - ) NOEXCEPT : OwnedOrUnowned(yours) {} - - -#if __cplusplus >= 201103L - /** @brief Move-assign operator */ - inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { - OwnedOrUnowned::operator= (it); - return *this; - } - - /** @brief Move constructor */ - inline Precomputed(Precomputed &&it) NOEXCEPT : OwnedOrUnowned() { - *this = it; - } - - /** @brief Undelete copy operator */ - inline Precomputed &operator=(const Precomputed &it) NOEXCEPT { - OwnedOrUnowned::operator= (it); - return *this; - } -#endif - - /** - * @brief Initilaize from point. Must allocate memory, and may throw. - */ - inline Precomputed &operator=(const Point &it) throw(std::bad_alloc) { - alloc(); - decaf_255_precompute(ours.mine,it.p); - return *this; - } - - /** - * @brief Copy constructor. - */ - inline Precomputed(const Precomputed &it) throw(std::bad_alloc) - : OwnedOrUnowned() { *this = it; } - - /** - * @brief Constructor which initializes from point. - */ - inline explicit Precomputed(const Point &it) throw(std::bad_alloc) - : OwnedOrUnowned() { *this = it; } - - /** @brief Fixed base scalarmul. */ - inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_255_precomputed_scalarmul(r.p,get(),s.s); return r; } - - /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ - inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); } - - /** @brief Return the table for the base point. */ - static inline const Precomputed base() NOEXCEPT { return Precomputed(); } - -public: - /** @cond internal */ - friend class OwnedOrUnowned; - static inline size_t size() NOEXCEPT { return sizeof_decaf_255_precomputed_s; } - static inline size_t alignment() NOEXCEPT { return alignof_decaf_255_precomputed_s; } - static inline const Precomputed_U * defaultValue() NOEXCEPT { return decaf_255_precomputed_base; } - /** @endcond */ -}; - -}; /* struct IsoEd25519 */ - - - -/** @cond internal */ -inline SecureBuffer IsoEd25519::Scalar::direct_scalarmul ( - const Block &in, - decaf_bool_t allow_identity, - decaf_bool_t short_circuit -) const throw(CryptoException) { - SecureBuffer out(IsoEd25519::Point::SER_BYTES); - if (DECAF_SUCCESS != - decaf_255_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit) - ) { - throw CryptoException(); - } - return out; -} -/** endcond */ - -#undef NOEXCEPT -} /* namespace decaf */ - -#endif /* __DECAF_255_HXX__ */ diff --git a/src/public_include/decaf/decaf_448.h b/src/public_include/decaf/decaf_448.h deleted file mode 100644 index 6a7ca20..0000000 --- a/src/public_include/decaf/decaf_448.h +++ /dev/null @@ -1,641 +0,0 @@ -/** - * @file decaf/decaf_448.h - * @author Mike Hamburg - * - * @copyright - * Copyright (c) 2015 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * - * @brief A group of prime order p, based on Ed448. - */ -#ifndef __DECAF_448_H__ -#define __DECAF_448_H__ 1 - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define DECAF_448_LIMBS (512/DECAF_WORD_BITS) -#define DECAF_448_SCALAR_BITS 446 -#define DECAF_448_SCALAR_LIMBS (448/DECAF_WORD_BITS) - -/** Galois field element internal structure */ -#ifndef __DECAF_448_GF_DEFINED__ -#define __DECAF_448_GF_DEFINED__ 1 -typedef struct gf_448_s { - /** @cond internal */ - decaf_word_t limb[DECAF_448_LIMBS]; - /** @endcond */ -} __attribute__((aligned(32))) gf_448_s, gf_448_t[1]; -#endif /* __DECAF_448_GF_DEFINED__ */ - -/** Number of bytes in a serialized point. */ -#define DECAF_448_SER_BYTES 56 - -/** Number of bytes in a serialized scalar. */ -#define DECAF_448_SCALAR_BYTES 56 - -/** Twisted Edwards (-1,d-1) extended homogeneous coordinates */ -typedef struct decaf_448_point_s { - /** @cond internal */ - gf_448_t x,y,z,t; - /** @endcond */ -} decaf_448_point_t[1]; - -/** Precomputed table based on a point. Can be trivial implementation. */ -struct decaf_448_precomputed_s; - -/** Precomputed table based on a point. Can be trivial implementation. */ -typedef struct decaf_448_precomputed_s decaf_448_precomputed_s; - -/** Size and alignment of precomputed point tables. */ -extern const size_t sizeof_decaf_448_precomputed_s API_VIS, alignof_decaf_448_precomputed_s API_VIS; - -/** Scalar is stored packed, because we don't need the speed. */ -typedef struct decaf_448_scalar_s { - /** @cond internal */ - decaf_word_t limb[DECAF_448_SCALAR_LIMBS]; - /** @endcond */ -} decaf_448_scalar_t[1]; - -/** A scalar equal to 1. */ -extern const decaf_448_scalar_t decaf_448_scalar_one API_VIS; - -/** A scalar equal to 0. */ -extern const decaf_448_scalar_t decaf_448_scalar_zero API_VIS; - -/** The identity point on the curve. */ -extern const decaf_448_point_t decaf_448_point_identity API_VIS; - -/** An arbitrarily chosen base point on the curve. */ -extern const decaf_448_point_t decaf_448_point_base API_VIS; - -/** Precomputed table for the base point on the curve. */ -extern const struct decaf_448_precomputed_s *decaf_448_precomputed_base API_VIS; - -/** - * @brief Read a scalar from wire format or from bytes. - * - * @param [in] ser Serialized form of a scalar. - * @param [out] out Deserialized form. - * - * @retval DECAF_SUCCESS The scalar was correctly encoded. - * @retval DECAF_FAILURE The scalar was greater than the modulus, - * and has been reduced modulo that modulus. - */ -decaf_error_t decaf_448_scalar_decode ( - decaf_448_scalar_t out, - const unsigned char ser[DECAF_448_SCALAR_BYTES] -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Read a scalar from wire format or from bytes. Reduces mod - * scalar prime. - * - * @param [in] ser Serialized form of a scalar. - * @param [in] ser_len Length of serialized form. - * @param [out] out Deserialized form. - */ -void decaf_448_scalar_decode_long ( - decaf_448_scalar_t out, - const unsigned char *ser, - size_t ser_len -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Serialize a scalar to wire format. - * - * @param [out] ser Serialized form of a scalar. - * @param [in] s Deserialized scalar. - */ -void decaf_448_scalar_encode ( - unsigned char ser[DECAF_448_SCALAR_BYTES], - const decaf_448_scalar_t s -) API_VIS NONNULL2 NOINLINE NOINLINE; - -/** - * @brief Add two scalars. The scalars may use the same memory. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @param [out] out a+b. - */ -void decaf_448_scalar_add ( - decaf_448_scalar_t out, - const decaf_448_scalar_t a, - const decaf_448_scalar_t b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Compare two scalars. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @retval DECAF_TRUE The scalars are equal. - * @retval DECAF_FALSE The scalars are not equal. - */ -decaf_bool_t decaf_448_scalar_eq ( - const decaf_448_scalar_t a, - const decaf_448_scalar_t b -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Subtract two scalars. The scalars may use the same memory. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @param [out] out a-b. - */ -void decaf_448_scalar_sub ( - decaf_448_scalar_t out, - const decaf_448_scalar_t a, - const decaf_448_scalar_t b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Multiply two scalars. The scalars may use the same memory. - * @param [in] a One scalar. - * @param [in] b Another scalar. - * @param [out] out a*b. - */ -void decaf_448_scalar_mul ( - decaf_448_scalar_t out, - const decaf_448_scalar_t a, - const decaf_448_scalar_t b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Invert a scalar. When passed zero, return 0. The input and output may alias. - * @param [in] a A scalar. - * @param [out] out 1/a. - * @return DECAF_SUCCESS The input is nonzero. - */ -decaf_error_t decaf_448_scalar_invert ( - decaf_448_scalar_t out, - const decaf_448_scalar_t a -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Copy a scalar. The scalars may use the same memory, in which - * case this function does nothing. - * @param [in] a A scalar. - * @param [out] out Will become a copy of a. - */ -static inline void NONNULL2 decaf_448_scalar_copy ( - decaf_448_scalar_t out, - const decaf_448_scalar_t a -) { - *out = *a; -} - -/** - * @brief Set a scalar to an unsigned integer. - * @param [in] a An integer. - * @param [out] out Will become equal to a. - */ -void decaf_448_scalar_set_unsigned ( - decaf_448_scalar_t out, - decaf_word_t a -) API_VIS NONNULL1; - -/** - * @brief Encode a point as a sequence of bytes. - * - * @param [out] ser The byte representation of the point. - * @param [in] pt The point to encode. - */ -void decaf_448_point_encode ( - uint8_t ser[DECAF_448_SER_BYTES], - const decaf_448_point_t pt -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Decode a point from a sequence of bytes. - * - * Every point has a unique encoding, so not every - * sequence of bytes is a valid encoding. If an invalid - * encoding is given, the output is undefined. - * - * @param [out] pt The decoded point. - * @param [in] ser The serialized version of the point. - * @param [in] allow_identity DECAF_TRUE if the identity is a legal input. - * @retval DECAF_SUCCESS The decoding succeeded. - * @retval DECAF_FAILURE The decoding didn't succeed, because - * ser does not represent a point. - */ -decaf_error_t decaf_448_point_decode ( - decaf_448_point_t pt, - const uint8_t ser[DECAF_448_SER_BYTES], - decaf_bool_t allow_identity -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Copy a point. The input and output may alias, - * in which case this function does nothing. - * - * @param [out] a A copy of the point. - * @param [in] b Any point. - */ -static inline void NONNULL2 decaf_448_point_copy ( - decaf_448_point_t a, - const decaf_448_point_t b -) { - *a=*b; -} - -/** - * @brief Test whether two points are equal. If yes, return - * DECAF_TRUE, else return DECAF_FALSE. - * - * @param [in] a A point. - * @param [in] b Another point. - * @retval DECAF_TRUE The points are equal. - * @retval DECAF_FALSE The points are not equal. - */ -decaf_bool_t decaf_448_point_eq ( - const decaf_448_point_t a, - const decaf_448_point_t b -) API_VIS WARN_UNUSED NONNULL2 NOINLINE; - -/** - * @brief Add two points to produce a third point. The - * input points and output point can be pointers to the same - * memory. - * - * @param [out] sum The sum a+b. - * @param [in] a An addend. - * @param [in] b An addend. - */ -void decaf_448_point_add ( - decaf_448_point_t sum, - const decaf_448_point_t a, - const decaf_448_point_t b -) API_VIS NONNULL3; - -/** - * @brief Double a point. Equivalent to - * decaf_448_point_add(two_a,a,a), but potentially faster. - * - * @param [out] two_a The sum a+a. - * @param [in] a A point. - */ -void decaf_448_point_double ( - decaf_448_point_t two_a, - const decaf_448_point_t a -) API_VIS NONNULL2; - -/** - * @brief Subtract two points to produce a third point. The - * input points and output point can be pointers to the same - * memory. - * - * @param [out] diff The difference a-b. - * @param [in] a The minuend. - * @param [in] b The subtrahend. - */ -void decaf_448_point_sub ( - decaf_448_point_t diff, - const decaf_448_point_t a, - const decaf_448_point_t b -) API_VIS NONNULL3; - -/** - * @brief Negate a point to produce another point. The input - * and output points can use the same memory. - * - * @param [out] nega The negated input point - * @param [in] a The input point. - */ -void decaf_448_point_negate ( - decaf_448_point_t nega, - const decaf_448_point_t a -) API_VIS NONNULL2; - -/** - * @brief Multiply a base point by a scalar: scaled = scalar*base. - * - * @param [out] scaled The scaled point base*scalar - * @param [in] base The point to be scaled. - * @param [in] scalar The scalar to multiply by. - */ -void decaf_448_point_scalarmul ( - decaf_448_point_t scaled, - const decaf_448_point_t base, - const decaf_448_scalar_t scalar -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Multiply a base point by a scalar: scaled = scalar*base. - * This function operates directly on serialized forms. - * - * @warning This function is experimental. It may not be supported - * long-term. - * - * @param [out] scaled The scaled point base*scalar - * @param [in] base The point to be scaled. - * @param [in] scalar The scalar to multiply by. - * @param [in] allow_identity Allow the input to be the identity. - * @param [in] short_circuit Allow a fast return if the input is illegal. - * - * @retval DECAF_SUCCESS The scalarmul succeeded. - * @retval DECAF_FAILURE The scalarmul didn't succeed, because - * base does not represent a point. - */ -decaf_error_t decaf_448_direct_scalarmul ( - uint8_t scaled[DECAF_448_SER_BYTES], - const uint8_t base[DECAF_448_SER_BYTES], - const decaf_448_scalar_t scalar, - decaf_bool_t allow_identity, - decaf_bool_t short_circuit -) API_VIS NONNULL3 WARN_UNUSED NOINLINE; - -/** - * @brief Precompute a table for fast scalar multiplication. - * Some implementations do not include precomputed points; for - * those implementations, this implementation simply copies the - * point. - * - * @param [out] a A precomputed table of multiples of the point. - * @param [in] b Any point. - */ -void decaf_448_precompute ( - decaf_448_precomputed_s *a, - const decaf_448_point_t b -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Multiply a precomputed base point by a scalar: - * scaled = scalar*base. - * Some implementations do not include precomputed points; for - * those implementations, this function is the same as - * decaf_448_point_scalarmul - * - * @param [out] scaled The scaled point base*scalar - * @param [in] base The point to be scaled. - * @param [in] scalar The scalar to multiply by. - */ -void decaf_448_precomputed_scalarmul ( - decaf_448_point_t scaled, - const decaf_448_precomputed_s *base, - const decaf_448_scalar_t scalar -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Multiply two base points by two scalars: - * scaled = scalar1*base1 + scalar2*base2. - * - * Equivalent to two calls to decaf_448_point_scalarmul, but may be - * faster. - * - * @param [out] combo The linear combination scalar1*base1 + scalar2*base2. - * @param [in] base1 A first point to be scaled. - * @param [in] scalar1 A first scalar to multiply by. - * @param [in] base2 A second point to be scaled. - * @param [in] scalar2 A second scalar to multiply by. - */ -void decaf_448_point_double_scalarmul ( - decaf_448_point_t combo, - const decaf_448_point_t base1, - const decaf_448_scalar_t scalar1, - const decaf_448_point_t base2, - const decaf_448_scalar_t scalar2 -) API_VIS NONNULL5 NOINLINE; - -/* - * @brief Multiply one base point by two scalars: - * a1 = scalar1 * base - * a2 = scalar2 * base - * - * Equivalent to two calls to decaf_448_point_scalarmul, but may be - * faster. - * - * @param [out] a1 The first multiple - * @param [out] a2 The second multiple - * @param [in] base1 A point to be scaled. - * @param [in] scalar1 A first scalar to multiply by. - * @param [in] scalar2 A second scalar to multiply by. - */ -void decaf_448_point_dual_scalarmul ( - decaf_448_point_t a1, - decaf_448_point_t a2, - const decaf_448_point_t b, - const decaf_448_scalar_t scalar1, - const decaf_448_scalar_t scalar2 -) API_VIS NONNULL5 NOINLINE; - -/** - * @brief Multiply two base points by two scalars: - * scaled = scalar1*decaf_448_point_base + scalar2*base2. - * - * Otherwise equivalent to decaf_448_point_double_scalarmul, but may be - * faster at the expense of being variable time. - * - * @param [out] combo The linear combination scalar1*base + scalar2*base2. - * @param [in] scalar1 A first scalar to multiply by. - * @param [in] base2 A second point to be scaled. - * @param [in] scalar2 A second scalar to multiply by. - * - * @warning: This function takes variable time, and may leak the scalars - * used. It is designed for signature verification. - */ -void decaf_448_base_double_scalarmul_non_secret ( - decaf_448_point_t combo, - const decaf_448_scalar_t scalar1, - const decaf_448_point_t base2, - const decaf_448_scalar_t scalar2 -) API_VIS NONNULL4 NOINLINE; - - -/** - * @brief Constant-time decision between two points. If pick_b - * is zero, out = a; else out = b. - * - * @param [out] q The output. It may be the same as either input. - * @param [in] a Any point. - * @param [in] b Any point. - * @param [in] pick_b If nonzero, choose point b. - */ -void decaf_448_point_cond_sel ( - decaf_448_point_t out, - const decaf_448_point_t a, - const decaf_448_point_t b, - decaf_word_t pick_b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Constant-time decision between two scalars. If pick_b - * is zero, out = a; else out = b. - * - * @param [out] q The output. It may be the same as either input. - * @param [in] a Any scalar. - * @param [in] b Any scalar. - * @param [in] pick_b If nonzero, choose scalar b. - */ -void decaf_448_scalar_cond_sel ( - decaf_448_scalar_t out, - const decaf_448_scalar_t a, - const decaf_448_scalar_t b, - decaf_word_t pick_b -) API_VIS NONNULL3 NOINLINE; - -/** - * @brief Test that a point is valid, for debugging purposes. - * - * @param [in] toTest The point to test. - * @retval DECAF_TRUE The point is valid. - * @retval DECAF_FALSE The point is invalid. - */ -decaf_bool_t decaf_448_point_valid ( - const decaf_448_point_t toTest -) API_VIS WARN_UNUSED NONNULL1 NOINLINE; - -/** - * @brief Torque a point, for debugging purposes. The output - * will be equal to the input. - * - * @param [out] q The point to torque. - * @param [in] p The point to torque. - */ -void decaf_448_point_debugging_torque ( - decaf_448_point_t q, - const decaf_448_point_t p -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Projectively scale a point, for debugging purposes. - * The output will be equal to the input, and will be valid - * even if the factor is zero. - * - * @param [out] q The point to scale. - * @param [in] p The point to scale. - * @param [in] factor Serialized GF factor to scale. - */ -void decaf_448_point_debugging_pscale ( - decaf_448_point_t q, - const decaf_448_point_t p, - const unsigned char factor[DECAF_448_SER_BYTES] -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Almost-Elligator-like hash to curve. - * - * Call this function with the output of a hash to make a hash to the curve. - * - * This function runs Elligator2 on the decaf_448 Jacobi quartic model. It then - * uses the isogeny to put the result in twisted Edwards form. As a result, - * it is safe (cannot produce points of order 4), and would be compatible with - * hypothetical other implementations of Decaf using a Montgomery or untwisted - * Edwards model. - * - * Unlike Elligator, this function may be up to 4:1 on [0,(p-1)/2]: - * A factor of 2 due to the isogeny. - * A factor of 2 because we quotient out the 2-torsion. - * - * This makes it about 8:1 overall, or 16:1 overall on curves with cofactor 8. - * - * Negating the input (mod q) results in the same point. Inverting the input - * (mod q) results in the negative point. This is the same as Elligator. - * - * This function isn't quite indifferentiable from a random oracle. - * However, it is suitable for many protocols, including SPEKE and SPAKE2 EE. - * Furthermore, calling it twice with independent seeds and adding the results - * is indifferentiable from a random oracle. - * - * @param [in] hashed_data Output of some hash function. - * @param [out] pt The data hashed to the curve. - */ -void -decaf_448_point_from_hash_nonuniform ( - decaf_448_point_t pt, - const unsigned char hashed_data[DECAF_448_SER_BYTES] -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Indifferentiable hash function encoding to curve. - * - * Equivalent to calling decaf_448_point_from_hash_nonuniform twice and adding. - * - * @param [in] hashed_data Output of some hash function. - * @param [out] pt The data hashed to the curve. - */ -void decaf_448_point_from_hash_uniform ( - decaf_448_point_t pt, - const unsigned char hashed_data[2*DECAF_448_SER_BYTES] -) API_VIS NONNULL2 NOINLINE; - -/** - * @brief Inverse of elligator-like hash to curve. - * - * This function writes to the buffer, to make it so that - * decaf_448_point_from_hash_nonuniform(buffer) = pt if - * possible. Since there may be multiple preimages, the - * "which" parameter chooses between them. To ensure uniform - * inverse sampling, this function succeeds or fails - * independently for different "which" values. - * - * @param [out] recovered_hash Encoded data. - * @param [in] pt The point to encode. - * @param [in] which A value determining which inverse point - * to return. - * - * @retval DECAF_SUCCESS The inverse succeeded. - * @retval DECAF_FAILURE The inverse failed. - */ -decaf_error_t -decaf_448_invert_elligator_nonuniform ( - unsigned char recovered_hash[DECAF_448_SER_BYTES], - const decaf_448_point_t pt, - uint16_t which -) API_VIS NONNULL2 NOINLINE WARN_UNUSED; - -/** - * @brief Inverse of elligator-like hash to curve. - * - * This function writes to the buffer, to make it so that - * decaf_448_point_from_hash_uniform(buffer) = pt if - * possible. Since there may be multiple preimages, the - * "which" parameter chooses between them. To ensure uniform - * inverse sampling, this function succeeds or fails - * independently for different "which" values. - * - * @param [out] recovered_hash Encoded data. - * @param [in] pt The point to encode. - * @param [in] which A value determining which inverse point - * to return. - * - * @retval DECAF_SUCCESS The inverse succeeded. - * @retval DECAF_FAILURE The inverse failed. - */ -decaf_error_t -decaf_448_invert_elligator_uniform ( - unsigned char recovered_hash[2*DECAF_448_SER_BYTES], - const decaf_448_point_t pt, - uint16_t which -) API_VIS NONNULL2 NOINLINE WARN_UNUSED; - -/** - * @brief Overwrite scalar with zeros. - */ -void decaf_448_scalar_destroy ( - decaf_448_scalar_t scalar -) NONNULL1 API_VIS; - -/** - * @brief Overwrite point with zeros. - * @todo Use this internally. - */ -void decaf_448_point_destroy ( - decaf_448_point_t point -) NONNULL1 API_VIS; - -/** - * @brief Overwrite precomputed table with zeros. - */ -void decaf_448_precomputed_destroy ( - decaf_448_precomputed_s *pre -) NONNULL1 API_VIS; - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __DECAF_448_H__ */ diff --git a/src/public_include/decaf/decaf_448.hxx b/src/public_include/decaf/decaf_448.hxx deleted file mode 100644 index 75d5426..0000000 --- a/src/public_include/decaf/decaf_448.hxx +++ /dev/null @@ -1,584 +0,0 @@ -/** - * @file decaf/decaf_448.hxx - * @author Mike Hamburg - * - * @copyright - * Copyright (c) 2015 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * - * @brief A group of prime order p, C++ wrapper. - * - * The Decaf library implements cryptographic operations on a an elliptic curve - * group of prime order p. It accomplishes this by using a twisted Edwards - * curve (isogenous to Ed448-Goldilocks) and wiping out the cofactor. - * - * The formulas are all complete and have no special cases, except that - * decaf_448_decode can fail because not every sequence of bytes is a valid group - * element. - * - * The formulas contain no data-dependent branches, timing or memory accesses, - * except for decaf_448_base_double_scalarmul_non_secret. - */ -#ifndef __DECAF_448_HXX__ -#define __DECAF_448_HXX__ 1 - -/** This code uses posix_memalign. */ -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 600 -#endif -#include -#include /* for memcpy */ - -#include -#include -#include -#include -#include - -/** @cond internal */ -#if __cplusplus >= 201103L -#define NOEXCEPT noexcept -#else -#define NOEXCEPT throw() -#endif -/** @endcond */ - -namespace decaf { - -/** - * @brief Ed448-Goldilocks/Decaf instantiation of group. - */ -struct Ed448Goldilocks { - -/** The name of the curve */ -static inline const char *name() { return "Ed448-Goldilocks"; } - -/** The curve's cofactor (removed, but useful for testing) */ -static const int REMOVED_COFACTOR = 4; - -/** Residue class of field modulus: p == this mod 2*(this-1) */ -static const int FIELD_MODULUS_TYPE = 3; - -/** @cond internal */ -class Point; -class Precomputed; -/** @endcond */ - -/** - * @brief A scalar modulo the curve order. - * Supports the usual arithmetic operations, all in constant time. - */ -class Scalar : public Serializable { -private: - /** @brief wrapped C type */ - typedef decaf_448_scalar_t Wrapped; - -public: - /** @brief Size of a serialized element */ - static const size_t SER_BYTES = DECAF_448_SCALAR_BYTES; - - /** @brief access to the underlying scalar object */ - Wrapped s; - - /** @brief Don't initialize. */ - inline Scalar(const NOINIT &) NOEXCEPT {} - - /** @brief Set to an unsigned word */ - inline Scalar(const decaf_word_t w) NOEXCEPT { *this = w; } - - /** @brief Set to a signed word */ - inline Scalar(const int w) NOEXCEPT { *this = w; } - - /** @brief Construct from RNG */ - inline explicit Scalar(Rng &rng) NOEXCEPT { - FixedArrayBuffer sb(rng); - *this = sb; - } - - /** @brief Construct from decaf_scalar_t object. */ - inline Scalar(const Wrapped &t = decaf_448_scalar_zero) NOEXCEPT { decaf_448_scalar_copy(s,t); } - - /** @brief Copy constructor. */ - inline Scalar(const Scalar &x) NOEXCEPT { *this = x; } - - /** @brief Construct from arbitrary-length little-endian byte sequence. */ - inline Scalar(const Block &buffer) NOEXCEPT { *this = buffer; } - - /** @brief Serializable instance */ - inline size_t serSize() const NOEXCEPT { return SER_BYTES; } - - /** @brief Serializable instance */ - inline void serializeInto(unsigned char *buffer) const NOEXCEPT { - decaf_448_scalar_encode(buffer, s); - } - - /** @brief Assignment. */ - inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); return *this; } - - /** @brief Assign from unsigned word. */ - inline Scalar& operator=(decaf_word_t w) NOEXCEPT { decaf_448_scalar_set_unsigned(s,w); return *this; } - - - /** @brief Assign from signed int. */ - inline Scalar& operator=(int w) NOEXCEPT { - Scalar t(-(decaf_word_t)INT_MIN); - decaf_448_scalar_set_unsigned(s,(decaf_word_t)w - (decaf_word_t)INT_MIN); - *this -= t; - return *this; - } - - /** Destructor securely zeorizes the scalar. */ - inline ~Scalar() NOEXCEPT { decaf_448_scalar_destroy(s); } - - /** @brief Assign from arbitrary-length little-endian byte sequence in a Block. */ - inline Scalar &operator=(const Block &bl) NOEXCEPT { - decaf_448_scalar_decode_long(s,bl.data(),bl.size()); return *this; - } - - /** - * @brief Decode from correct-length little-endian byte sequence. - * @return DECAF_FAILURE if the scalar is greater than or equal to the group order q. - */ - static inline decaf_error_t __attribute__((warn_unused_result)) decode ( - Scalar &sc, const FixedBlock buffer - ) NOEXCEPT { - return decaf_448_scalar_decode(sc.s,buffer.data()); - } - - /** Add. */ - inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_add(r.s,s,q.s); return r; } - - /** Add to this. */ - inline Scalar &operator+=(const Scalar &q) NOEXCEPT { decaf_448_scalar_add(s,s,q.s); return *this; } - - /** Subtract. */ - inline Scalar operator- (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_sub(r.s,s,q.s); return r; } - - /** Subtract from this. */ - inline Scalar &operator-=(const Scalar &q) NOEXCEPT { decaf_448_scalar_sub(s,s,q.s); return *this; } - - /** Multiply */ - inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_mul(r.s,s,q.s); return r; } - - /** Multiply into this. */ - inline Scalar &operator*=(const Scalar &q) NOEXCEPT { decaf_448_scalar_mul(s,s,q.s); return *this; } - - /** Negate */ - inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; } - - /** @brief Invert with Fermat's Little Theorem (slow!). If *this == 0, return 0. */ - inline Scalar inverse() const throw(CryptoException) { - Scalar r; - if (DECAF_SUCCESS != decaf_448_scalar_invert(r.s,s)) { - throw CryptoException(); - } - return r; - } - - /** @brief Divide by inverting q. If q == 0, return 0. */ - inline Scalar operator/ (const Scalar &q) const throw(CryptoException) { return *this * q.inverse(); } - - /** @brief Divide by inverting q. If q == 0, return 0. */ - inline Scalar &operator/=(const Scalar &q) throw(CryptoException) { return *this *= q.inverse(); } - - /** @brief Compare in constant time */ - inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); } - - /** @brief Compare in constant time */ - inline bool operator==(const Scalar &q) const NOEXCEPT { return !!decaf_448_scalar_eq(s,q.s); } - - /** @brief Scalarmul with scalar on left. */ - inline Point operator* (const Point &q) const NOEXCEPT { return q * (*this); } - - /** @brief Scalarmul-precomputed with scalar on left. */ - inline Point operator* (const Precomputed &q) const NOEXCEPT { return q * (*this); } - - /** @brief Direct scalar multiplication. */ - inline SecureBuffer direct_scalarmul( - const Block &in, - decaf_bool_t allow_identity=DECAF_FALSE, - decaf_bool_t short_circuit=DECAF_TRUE - ) const throw(CryptoException); -}; - -/** - * @brief Element of prime-order group. - */ -class Point : public Serializable { -private: - /** @brief wrapped C type */ - typedef decaf_448_point_t Wrapped; - -public: - /** @brief Size of a serialized element */ - static const size_t SER_BYTES = DECAF_448_SER_BYTES; - - /** @brief Bytes required for hash */ - static const size_t HASH_BYTES = SER_BYTES; - - /** @brief Size of a stegged element */ - static const size_t STEG_BYTES = HASH_BYTES * 2; - - /** The c-level object. */ - Wrapped p; - - /** @brief Don't initialize. */ - inline Point(const NOINIT &) NOEXCEPT {} - - /** @brief Constructor sets to identity by default. */ - inline Point(const Wrapped &q = decaf_448_point_identity) NOEXCEPT { decaf_448_point_copy(p,q); } - - /** @brief Copy constructor. */ - inline Point(const Point &q) NOEXCEPT { *this = q; } - - /** @brief Assignment. */ - inline Point& operator=(const Point &q) NOEXCEPT { decaf_448_point_copy(p,q.p); return *this; } - - /** @brief Destructor securely zeorizes the point. */ - inline ~Point() NOEXCEPT { decaf_448_point_destroy(p); } - - /** @brief Construct from RNG */ - inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT { - if (uniform) { - FixedArrayBuffer<2*HASH_BYTES> b(rng); - set_to_hash(b); - } else { - FixedArrayBuffer b(rng); - set_to_hash(b); - } - } - - /** - * @brief Initialize from a fixed-length byte string. - * The all-zero string maps to the identity. - * - * @throw CryptoException the string was the wrong length, or wasn't the encoding of a point, - * or was the identity and allow_identity was DECAF_FALSE. - */ - inline explicit Point(const FixedBlock &buffer, decaf_bool_t allow_identity=DECAF_TRUE) - throw(CryptoException) { - if (DECAF_SUCCESS != decode(*this,buffer,allow_identity)) { - throw CryptoException(); - } - } - - /** - * @brief Initialize from C++ fixed-length byte string. - * The all-zero string maps to the identity. - * - * @retval DECAF_SUCCESS the string was successfully decoded. - * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point, - * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. - */ - static inline decaf_error_t __attribute__((warn_unused_result)) decode ( - Point &p, const FixedBlock &buffer, decaf_bool_t allow_identity=DECAF_TRUE - ) NOEXCEPT { - return decaf_448_point_decode(p.p,buffer.data(),allow_identity); - } - - /** - * @brief Map uniformly to the curve from a hash buffer. - * The empty or all-zero string maps to the identity, as does the string "\x01". - * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, - * but the buffer will be zero-padded on the right. - */ - static inline Point from_hash ( const Block &s ) NOEXCEPT { - Point p((NOINIT())); p.set_to_hash(s); return p; - } - - /** - * @brief Map to the curve from a hash buffer. - * The empty or all-zero string maps to the identity, as does the string "\x01". - * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, - * but the buffer will be zero-padded on the right. - */ - inline void set_to_hash( const Block &s ) NOEXCEPT { - if (s.size() < HASH_BYTES) { - SecureBuffer b(HASH_BYTES); - memcpy(b.data(), s.data(), s.size()); - decaf_448_point_from_hash_nonuniform(p,b.data()); - } else if (s.size() == HASH_BYTES) { - decaf_448_point_from_hash_nonuniform(p,s.data()); - } else if (s.size() < 2*HASH_BYTES) { - SecureBuffer b(2*HASH_BYTES); - memcpy(b.data(), s.data(), s.size()); - decaf_448_point_from_hash_uniform(p,b.data()); - } else { - decaf_448_point_from_hash_uniform(p,s.data()); - } - } - - /** - * @brief Encode to string. The identity encodes to the all-zero string. - */ - inline operator SecureBuffer() const { - SecureBuffer buffer(SER_BYTES); - decaf_448_point_encode(buffer.data(), p); - return buffer; - } - - /** @brief Serializable instance */ - inline size_t serSize() const NOEXCEPT { return SER_BYTES; } - - /** @brief Serializable instance */ - inline void serializeInto(unsigned char *buffer) const NOEXCEPT { - decaf_448_point_encode(buffer, p); - } - - /** @brief Point add. */ - inline Point operator+ (const Point &q) const NOEXCEPT { Point r((NOINIT())); decaf_448_point_add(r.p,p,q.p); return r; } - - /** @brief Point add. */ - inline Point &operator+=(const Point &q) NOEXCEPT { decaf_448_point_add(p,p,q.p); return *this; } - - /** @brief Point subtract. */ - inline Point operator- (const Point &q) const NOEXCEPT { Point r((NOINIT())); decaf_448_point_sub(r.p,p,q.p); return r; } - - /** @brief Point subtract. */ - inline Point &operator-=(const Point &q) NOEXCEPT { decaf_448_point_sub(p,p,q.p); return *this; } - - /** @brief Point negate. */ - inline Point operator- () const NOEXCEPT { Point r((NOINIT())); decaf_448_point_negate(r.p,p); return r; } - - /** @brief Double the point out of place. */ - inline Point times_two () const NOEXCEPT { Point r((NOINIT())); decaf_448_point_double(r.p,p); return r; } - - /** @brief Double the point in place. */ - inline Point &double_in_place() NOEXCEPT { decaf_448_point_double(p,p); return *this; } - - /** @brief Constant-time compare. */ - inline bool operator!=(const Point &q) const NOEXCEPT { return ! decaf_448_point_eq(p,q.p); } - - /** @brief Constant-time compare. */ - inline bool operator==(const Point &q) const NOEXCEPT { return !!decaf_448_point_eq(p,q.p); } - - /** @brief Scalar multiply. */ - inline Point operator* (const Scalar &s) const NOEXCEPT { Point r((NOINIT())); decaf_448_point_scalarmul(r.p,p,s.s); return r; } - - /** @brief Scalar multiply in place. */ - inline Point &operator*=(const Scalar &s) NOEXCEPT { decaf_448_point_scalarmul(p,p,s.s); return *this; } - - /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ - inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); } - - /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ - inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); } - - /** @brief Validate / sanity check */ - inline bool validate() const NOEXCEPT { return decaf_448_point_valid(p); } - - /** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ - static inline Point double_scalarmul ( - const Point &q, const Scalar &qs, const Point &r, const Scalar &rs - ) NOEXCEPT { - Point p((NOINIT())); decaf_448_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p; - } - - /** @brief Dual-scalar multiply, equivalent to this*r1, this*r2 but faster. */ - inline void dual_scalarmul ( - Point &q1, Point &q2, const Scalar &r1, const Scalar &r2 - ) const NOEXCEPT { - decaf_448_point_dual_scalarmul(q1.p,q2.p,p,r1.s,r2.s); - } - - /** - * @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. - * For those who like their scalars before the point. - */ - static inline Point double_scalarmul ( - const Scalar &qs, const Point &q, const Scalar &rs, const Point &r - ) NOEXCEPT { - return double_scalarmul(q,qs,r,rs); - } - - /** - * @brief Double-scalar multiply: this point by the first scalar and base by the second scalar. - * @warning This function takes variable time, and may leak the scalars (or points, but currently - * it doesn't). - */ - inline Point non_secret_combo_with_base(const Scalar &s, const Scalar &s_base) NOEXCEPT { - Point r((NOINIT())); decaf_448_base_double_scalarmul_non_secret(r.p,s_base.s,p,s.s); return r; - } - - /** @brief Return a point equal to *this, whose internal data is rotated by a torsion element. */ - inline Point debugging_torque() const NOEXCEPT { - Point q; - decaf_448_point_debugging_torque(q.p,p); - return q; - } - - /** @brief Return a point equal to *this, whose internal data has a modified representation. */ - inline Point debugging_pscale(const FixedBlock factor) const NOEXCEPT { - Point q; - decaf_448_point_debugging_pscale(q.p,p,factor.data()); - return q; - } - - /** @brief Return a point equal to *this, whose internal data has a randomized representation. */ - inline Point debugging_pscale(Rng &r) const NOEXCEPT { - FixedArrayBuffer sb(r); - return debugging_pscale(sb); - } - - /** - * Modify buffer so that Point::from_hash(Buffer) == *this, and return DECAF_SUCCESS; - * or leave buf unmodified and return DECAF_FAILURE. - */ - inline decaf_error_t invert_elligator ( - Buffer buf, uint16_t hint - ) const NOEXCEPT { - unsigned char buf2[2*HASH_BYTES]; - memset(buf2,0,sizeof(buf2)); - memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size()); - decaf_bool_t ret; - if (buf.size() > HASH_BYTES) { - ret = decaf_successful(decaf_448_invert_elligator_uniform(buf2, p, hint)); - } else { - ret = decaf_successful(decaf_448_invert_elligator_nonuniform(buf2, p, hint)); - } - if (buf.size() < HASH_BYTES) { - ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); - } - if (ret) { - /* TODO: make this constant time?? */ - memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); - } - decaf_bzero(buf2,sizeof(buf2)); - return decaf_succeed_if(ret); - } - - /** @brief Steganographically encode this */ - inline SecureBuffer steg_encode(Rng &rng, size_t size=STEG_BYTES) const throw(std::bad_alloc, LengthException) { - if (size <= HASH_BYTES + 4 || size > 2*HASH_BYTES) throw LengthException(); - SecureBuffer out(STEG_BYTES); - decaf_error_t done; - do { - rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1)); - done = invert_elligator(out, out[HASH_BYTES-1]); - } while (!decaf_successful(done)); - return out; - } - - /** @brief Return the base point */ - static inline const Point base() NOEXCEPT { return Point(decaf_448_point_base); } - - /** @brief Return the identity point */ - static inline const Point identity() NOEXCEPT { return Point(decaf_448_point_identity); } -}; - -/** - * @brief Precomputed table of points. - * Minor difficulties arise here because the decaf API doesn't expose, as a constant, how big such an object is. - * Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to - * stack-allocate a 15kiB object anyway. - */ - -/** @cond internal */ -typedef decaf_448_precomputed_s Precomputed_U; -/** @endcond */ -class Precomputed - /** @cond internal */ - : protected OwnedOrUnowned - /** @endcond */ -{ -public: - - /** Destructor securely zeorizes the memory. */ - inline ~Precomputed() NOEXCEPT { clear(); } - - /** - * @brief Initialize from underlying type, declared as a reference to prevent - * it from being called with 0, thereby breaking override. - * - * The underlying object must remain valid throughout the lifetime of this one. - * - * By default, initializes to the table for the base point. - * - * @warning The empty initializer makes this equal to base, unlike the empty - * initializer for points which makes this equal to the identity. - */ - inline Precomputed ( - const Precomputed_U &yours = *defaultValue() - ) NOEXCEPT : OwnedOrUnowned(yours) {} - - -#if __cplusplus >= 201103L - /** @brief Move-assign operator */ - inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { - OwnedOrUnowned::operator= (it); - return *this; - } - - /** @brief Move constructor */ - inline Precomputed(Precomputed &&it) NOEXCEPT : OwnedOrUnowned() { - *this = it; - } - - /** @brief Undelete copy operator */ - inline Precomputed &operator=(const Precomputed &it) NOEXCEPT { - OwnedOrUnowned::operator= (it); - return *this; - } -#endif - - /** - * @brief Initilaize from point. Must allocate memory, and may throw. - */ - inline Precomputed &operator=(const Point &it) throw(std::bad_alloc) { - alloc(); - decaf_448_precompute(ours.mine,it.p); - return *this; - } - - /** - * @brief Copy constructor. - */ - inline Precomputed(const Precomputed &it) throw(std::bad_alloc) - : OwnedOrUnowned() { *this = it; } - - /** - * @brief Constructor which initializes from point. - */ - inline explicit Precomputed(const Point &it) throw(std::bad_alloc) - : OwnedOrUnowned() { *this = it; } - - /** @brief Fixed base scalarmul. */ - inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_precomputed_scalarmul(r.p,get(),s.s); return r; } - - /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */ - inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); } - - /** @brief Return the table for the base point. */ - static inline const Precomputed base() NOEXCEPT { return Precomputed(); } - -public: - /** @cond internal */ - friend class OwnedOrUnowned; - static inline size_t size() NOEXCEPT { return sizeof_decaf_448_precomputed_s; } - static inline size_t alignment() NOEXCEPT { return alignof_decaf_448_precomputed_s; } - static inline const Precomputed_U * defaultValue() NOEXCEPT { return decaf_448_precomputed_base; } - /** @endcond */ -}; - -}; /* struct Ed448Goldilocks */ - -/** @cond internal */ -inline SecureBuffer Ed448Goldilocks::Scalar::direct_scalarmul ( - const Block &in, - decaf_bool_t allow_identity, - decaf_bool_t short_circuit -) const throw(CryptoException) { - SecureBuffer out(Ed448Goldilocks::Point::SER_BYTES); - if (DECAF_SUCCESS != - decaf_448_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit) - ) { - throw CryptoException(); - } - return out; -} -/** endcond */ - -#undef NOEXCEPT -} /* namespace decaf */ - -#endif /* __DECAF_448_HXX__ */