Browse Source

now generating some headers for real

master
Michael Hamburg 9 years ago
parent
commit
98be9a0820
5 changed files with 13 additions and 2455 deletions
  1. +13
    -4
      Makefile
  2. +0
    -640
      src/public_include/decaf/decaf_255.h
  3. +0
    -586
      src/public_include/decaf/decaf_255.hxx
  4. +0
    -641
      src/public_include/decaf/decaf_448.h
  5. +0
    -584
      src/public_include/decaf/decaf_448.hxx

+ 13
- 4
Makefile View File

@@ -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 $@ $^


+ 0
- 640
src/public_include/decaf/decaf_255.h View File

@@ -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 <decaf/common.h>

#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__ */

+ 0
- 586
src/public_include/decaf/decaf_255.hxx View File

@@ -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 <stdlib.h>
#include <string.h> /* for memcpy */

#include <decaf.h>
#include <decaf/secure_buffer.hxx>
#include <string>
#include <sys/types.h>
#include <limits.h>

/** @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<Scalar> {
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<SER_BYTES> 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<SER_BYTES> 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<Point> {
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<HASH_BYTES> 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<SER_BYTES> &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<SER_BYTES> &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<SER_BYTES> 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<SER_BYTES> 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<Precomputed,Precomputed_U>
/** @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<Precomputed,Precomputed_U>(yours) {}


#if __cplusplus >= 201103L
/** @brief Move-assign operator */
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT {
OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it);
return *this;
}

/** @brief Move constructor */
inline Precomputed(Precomputed &&it) NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>() {
*this = it;
}

/** @brief Undelete copy operator */
inline Precomputed &operator=(const Precomputed &it) NOEXCEPT {
OwnedOrUnowned<Precomputed,Precomputed_U>::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<Precomputed,Precomputed_U>() { *this = it; }

/**
* @brief Constructor which initializes from point.
*/
inline explicit Precomputed(const Point &it) throw(std::bad_alloc)
: OwnedOrUnowned<Precomputed,Precomputed_U>() { *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<Precomputed,Precomputed_U>;
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__ */

+ 0
- 641
src/public_include/decaf/decaf_448.h View File

@@ -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 <decaf/common.h>

#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__ */

+ 0
- 584
src/public_include/decaf/decaf_448.hxx View File

@@ -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 <stdlib.h>
#include <string.h> /* for memcpy */

#include <decaf.h>
#include <decaf/secure_buffer.hxx>
#include <string>
#include <sys/types.h>
#include <limits.h>

/** @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<Scalar> {
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<SER_BYTES> 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<SER_BYTES> 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<Point> {
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<HASH_BYTES> 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<SER_BYTES> &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<SER_BYTES> &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<SER_BYTES> 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<SER_BYTES> 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<Precomputed,Precomputed_U>
/** @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<Precomputed,Precomputed_U>(yours) {}


#if __cplusplus >= 201103L
/** @brief Move-assign operator */
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT {
OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it);
return *this;
}

/** @brief Move constructor */
inline Precomputed(Precomputed &&it) NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>() {
*this = it;
}

/** @brief Undelete copy operator */
inline Precomputed &operator=(const Precomputed &it) NOEXCEPT {
OwnedOrUnowned<Precomputed,Precomputed_U>::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<Precomputed,Precomputed_U>() { *this = it; }

/**
* @brief Constructor which initializes from point.
*/
inline explicit Precomputed(const Point &it) throw(std::bad_alloc)
: OwnedOrUnowned<Precomputed,Precomputed_U>() { *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<Precomputed,Precomputed_U>;
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__ */

Loading…
Cancel
Save