Browse Source

move everything over to more-tolerable templating

master
Michael Hamburg 9 years ago
parent
commit
d94a147194
14 changed files with 429 additions and 562 deletions
  1. +24
    -13
      Makefile
  2. +1
    -0
      src/gen_headers/curve_data.py
  3. +0
    -50
      src/gen_headers/gen_file.py
  4. +0
    -119
      src/gen_headers/main.py
  5. +1
    -1
      src/gen_headers/template.py
  6. +40
    -46
      src/per_curve/crypto.tmpl.h
  7. +38
    -44
      src/per_curve/crypto.tmpl.hxx
  8. +2
    -4
      src/per_curve/decaf.tmpl.c
  9. +176
    -184
      src/per_curve/decaf.tmpl.h
  10. +93
    -101
      src/per_curve/decaf.tmpl.hxx
  11. +18
    -0
      src/public_include/decaf.tmpl.h
  12. +16
    -0
      src/public_include/decaf.tmpl.hxx
  13. +10
    -0
      src/public_include/decaf/crypto.tmpl.h
  14. +10
    -0
      src/public_include/decaf/crypto.tmpl.hxx

+ 24
- 13
Makefile View File

@@ -69,12 +69,10 @@ BUILDPYS= $(SAGES:test/%.sage=$(BUILD_PY)/%.py)
.PHONY: clean all test test_ct bench todo doc lib bat sage sagetest gen_headers
.PRECIOUS: $(BUILD_ASM)/%.s $(BUILD_C)/*/%.c $(BUILD_H)/*/%.h $(BUILD_IBIN)/%

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 \
$( src/public_include/decaf/* : src/public_include = $(BUILD_INC) )
HEADER_SRCS= $(shell find src/public_include -name "*.h*")
GEN_HEADERS_0= $(HEADER_SRCS:src/public_include/%=$(BUILD_INC)/%)
GEN_HEADERS_1= $(GEN_HEADERS_0:%.tmpl.h=%.h)
GEN_HEADERS= $(GEN_HEADERS_1:%.tmpl.hxx=%.hxx)
HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp $(GEN_HEADERS)

# components needed by the lib
@@ -90,7 +88,6 @@ scan: clean
-enable-checker osx -enable-checker security -enable-checker unix \
make all


# Internal test programs, which are not part of the final build/bin directory.
$(BUILD_IBIN)/test: $(BUILD_OBJ)/test_decaf.o lib
ifeq ($(UNAME),Darwin)
@@ -125,10 +122,15 @@ $(BUILD_OBJ)/%.o: $(BUILD_ASM)/%.s
$(ASM) $(ASFLAGS) -c -o $@ $<

gen_headers: $(GEN_HEADERS)

$(BUILD_INC)/%: src/public_include/% $(BUILD_OBJ)/timestamp
cp -f $< $@
$(BUILD_INC)/%.h: src/public_include/%.tmpl.h src/gen_headers/*
python -B src/gen_headers/template.py --per=global --guard=$(@:$(BUILD_INC)/%=%) -o $@ $<
$(GEN_HEADERS): src/gen_headers/*.py src/public_include/decaf/*
python -B src/gen_headers/main.py --hpre=$(BUILD_INC) --ihpre=$(BUILD_H) --cpre=$(BUILD_C)
cp src/public_include/decaf/* $(BUILD_INC)/decaf/
$(BUILD_INC)/%.hxx: src/public_include/%.tmpl.hxx src/gen_headers/*
python -B src/gen_headers/template.py --per=global --guard=$(@:$(BUILD_INC)/%=%) -o $@ $<

################################################################
# Per-field code: call with field, arch
@@ -169,13 +171,22 @@ define define_curve

LIBCOMPONENTS += $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/crypto.o $$(BUILD_OBJ)/$(1)/decaf_tables.o
PER_OBJ_DIRS += $$(BUILD_OBJ)/$(1)
HEADERS_OF_$(1) = $$(HEADERS_OF_$(2))
GLOBAL_HEADERS_OF_$(1) = $(BUILD_INC)/decaf/decaf_$(3).h $(BUILD_INC)/decaf/decaf_$(3).hxx \
$(BUILD_INC)/decaf/crypto_$(3).h $(BUILD_INC)/decaf/crypto_$(3).hxx
HEADERS_OF_$(1) = $$(HEADERS_OF_$(2)) $$(GLOBAL_HEADERS_OF_$(1))
HEADERS += $$(GLOBAL_HEADERS_OF_$(1))

$$(BUILD_C)/$(1)/%.c: src/per_curve/%.tmpl.c src/gen_headers/* $$(HEADERS_OF_$(2))
python -B src/gen_headers/template.py --per=curve --item=$(1) --guard=$(1)/`basename $$@` -o $$@ $$<
$$(BUILD_H)/$(1)/%.h: src/per_curve/%.tmpl.h src/gen_headers/* $$(HEADERS_OF_$(2))
python -B src/gen_headers/template.py --per=curve --item=$(1) --guard=$(1)/`basename $$@` -o $$@ $$<
$$(BUILD_INC)/decaf/decaf_$(3).%: src/per_curve/decaf.tmpl.% src/gen_headers/* $$(HEADERS_OF_$(2))
python -B src/gen_headers/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$<
$$(BUILD_INC)/decaf/crypto_$(3).%: src/per_curve/crypto.tmpl.% src/gen_headers/* $$(HEADERS_OF_$(2))
python -B src/gen_headers/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$<

$$(BUILD_IBIN)/decaf_gen_tables_$(1): $$(BUILD_OBJ)/$(1)/decaf_gen_tables.o \
$$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/utils.o \
@@ -200,9 +211,9 @@ endef
################################################################
# call code above to generate curves and fields
$(eval $(call define_field,p25519,arch_x86_64))
$(eval $(call define_curve,curve25519,p25519))
$(eval $(call define_curve,curve25519,p25519,255))
$(eval $(call define_field,p448,arch_x86_64))
$(eval $(call define_curve,ed448goldilocks,p448))
$(eval $(call define_curve,ed448goldilocks,p448,448))

# The shakesum utility is in the public bin directory.
$(BUILD_BIN)/shakesum: $(BUILD_OBJ)/shakesum.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/utils.o


+ 1
- 0
src/gen_headers/curve_data.py View File

@@ -84,6 +84,7 @@ def ceil_log2(x):
out += 1
return out

# TODO: reduce this because we can now have expressions.
for field,data in field_data.iteritems():
if "modulus" not in data:
data["modulus"] = eval(data["gf_desc"].replace("^","**"))


+ 0
- 50
src/gen_headers/gen_file.py View File

@@ -1,50 +0,0 @@
from curve_data import curve_data, field_data
from textwrap import dedent

def redoc(filename,doc,author):
doc = doc.replace("\n","\n * ")
doc = dedent("""
/**
* @file %(filename)s
* @author %(author)s
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \\n
* Released under the MIT License. See LICENSE.txt for license information.
*
* %(doc)s
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/""") % { "filename": filename, "doc": doc, "author" : author }
doc = doc.replace(" * \n", " *\n")
return doc[1:]

gend_files = {}

per_map = {"field":field_data, "curve":curve_data, "global":{"global":{}} }

def gen_file(public,name,doc,code,per="global",author="Mike Hamburg"):
is_header = name.endswith(".h") or name.endswith(".hxx") or name.endswith(".h++")
for curve,data in per_map[per].iteritems():
ns_name = name % data
_,_,name_base = ns_name.rpartition("/")
header_guard = "__" + ns_name.replace(".","_").replace("/","_").upper() + "__"
ns_doc = dedent(doc).strip().rstrip()
ns_doc = redoc(ns_name, ns_doc % data, author)
ns_code = code % data
ret = ns_doc + "\n"
if is_header:
ns_code = dedent("""\n
#ifndef %(header_guard)s
#define %(header_guard)s 1
%(code)s
#endif /* %(header_guard)s */
""") % { "header_guard" : header_guard, "code": ns_code }
ret += ns_code[1:-1]
gend_files[ns_name] = (public,ret)

+ 0
- 119
src/gen_headers/main.py View File

@@ -1,119 +0,0 @@
from gen_file import gen_file,gend_files

import os
import argparse
import re

parser = argparse.ArgumentParser(description='Generate Decaf headers and other such files.')
parser.add_argument('--hpre', required = True, help = "Where to put the public header files")
parser.add_argument('--ihpre', required = True, help = "Where to put the internal header files")
parser.add_argument('--cpre', required = True, help = "Where to put the C/C++ implementation files")
args = parser.parse_args()

prefixes = { (True,"h") : args.hpre, (True,"hxx") : args.hpre, (False,"c") : args.cpre, (False,"h") : args.ihpre }

from decaf_hxx import decaf_hxx
from decaf_h import decaf_h
from crypto_h import crypto_h
from crypto_hxx import crypto_hxx
from curve_data import curve_data

root_hxx_code = "\n".join((
"#include <%s>" % name
for name in sorted(gend_files)
if re.match("^decaf/decaf_\d+.hxx$",name)
))
root_hxx_code += """

namespace decaf {
template <template<typename Group> class Run>
void run_for_all_curves() {
"""
root_hxx_code += "\n".join((
" Run<%s>::run();" % cd["cxx_ns"]
for cd in sorted(curve_data.values(), key=lambda x:x["c_ns"])
))
root_hxx_code += """
}
}
"""
decaf_root_hxx = gen_file(
public = True,
per = "global",
name = "decaf.hxx",
doc = """@brief Decaf curve metaheader.""",
code = "\n"+root_hxx_code+"\n"
)

crypto_h_code = "\n".join((
"#include <%s>" % name
for name in sorted(gend_files)
if re.match("^decaf/crypto_\d+.h$",name)
))
crypto_h = gen_file(
public = True,
per = "global",
name = "decaf/crypto.h",
doc = """
Example Decaf crypto routines, metaheader.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
""",
code = "\n"+crypto_h_code+"\n"
)

crypto_hxx_code = "\n".join((
"#include <%s>" % name
for name in sorted(gend_files)
if re.match("^decaf/crypto_\d+.hxx$",name)
))
crypto_hxx = gen_file(
public = True,
per = "global",
name = "decaf/crypto.hxx",
doc = """
Example Decaf crypto routines, C++, metaheader.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
""",
code = "\n"+crypto_hxx_code+"\n"
)

root_h_code = "\n".join((
"#include <%s>" % name
for name in sorted(gend_files)
if re.match("^decaf/decaf_\d+.h$",name)
))
decaf_root_hxx = gen_file(
public = True,
per = "global",
name = "decaf.h",
doc = """
Master header for Decaf library.
The Decaf library implements cryptographic operations on a elliptic curve
groups of prime order p. It accomplishes this by using a twisted Edwards
curve (isogenous to Ed448-Goldilocks or Ed25519) and wiping out the cofactor.
The formulas are all complete and have no special cases. However, some
functions can fail. For example, decoding functions can fail because not
every string is the encoding of a valid group element.
The formulas contain no data-dependent branches, timing or memory accesses,
except for decaf_XXX_base_double_scalarmul_non_secret.
""",
code = "\n"+root_h_code+"\n"
)


for name,(public,code) in gend_files.iteritems():
_,_,name_suffix = name.rpartition(".")
prefix = prefixes[(public,name_suffix)]
if not os.path.exists(os.path.dirname(prefix + "/" + name)):
os.makedirs(os.path.dirname(prefix + "/" + name))
with open(prefix + "/" + name,"w") as f:
f.write(code + "\n")

+ 1
- 1
src/gen_headers/template.py View File

@@ -13,7 +13,7 @@ parser.add_argument('--guard', required = False, default = None, help = "header
parser.add_argument('files', metavar='file', type=str, nargs='+', help='a list of files to fill')
args = parser.parse_args()

per_map = {"field":field_data, "curve":curve_data, "global":{"global":{}} }
per_map = {"field":field_data, "curve":curve_data, "global":{"global":{"field":field_data,"curve":curve_data} }}

def redoc(filename,doc,author):
doc = doc.replace("\n","\n * ")


src/gen_headers/crypto_h.py → src/per_curve/crypto.tmpl.h View File

@@ -1,17 +1,12 @@
from gen_file import gen_file
/**
* Example Decaf crypto routines.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*/

crypto_h = gen_file(
public = True,
per = "curve",
name = "decaf/crypto_%(shortname)s.h",
doc = """
Example Decaf crypto routines.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
@warning Experimental! The names, parameter orders etc are likely to change.
""", code = """
#include <decaf/%(c_ns)s.h>
#include <decaf/$(c_ns).h>
#include <decaf/strobe.h>

#ifdef __cplusplus
@@ -19,48 +14,48 @@ extern "C" {
#endif

/** Number of bytes for a symmetric key (expanded to full key) */
#define %(C_NS)s_SYMMETRIC_KEY_BYTES 32
#define $(C_NS)_SYMMETRIC_KEY_BYTES 32

/** A symmetric key, the compressed point of a private key. */
typedef unsigned char %(c_ns)s_symmetric_key_t[%(C_NS)s_SYMMETRIC_KEY_BYTES];
typedef unsigned char $(c_ns)_symmetric_key_t[$(C_NS)_SYMMETRIC_KEY_BYTES];

/** An encoded public key. */
typedef unsigned char %(c_ns)s_public_key_t[%(C_NS)s_SER_BYTES];
typedef unsigned char $(c_ns)_public_key_t[$(C_NS)_SER_BYTES];

/** A signature. */
typedef unsigned char %(c_ns)s_signature_t[%(C_NS)s_SER_BYTES + %(C_NS)s_SCALAR_BYTES];
typedef unsigned char $(c_ns)_signature_t[$(C_NS)_SER_BYTES + $(C_NS)_SCALAR_BYTES];

typedef struct {
/** @cond internal */
/** The symmetric key from which everything is expanded */
%(c_ns)s_symmetric_key_t sym;
$(c_ns)_symmetric_key_t sym;
/** The scalar x */
%(c_ns)s_scalar_t secret_scalar;
$(c_ns)_scalar_t secret_scalar;
/** x*Base */
%(c_ns)s_public_key_t pub;
$(c_ns)_public_key_t pub;
/** @endcond */
} /** Private key structure for pointers. */
%(c_ns)s_private_key_s,
$(c_ns)_private_key_s,
/** A private key (gmp array[1] style). */
%(c_ns)s_private_key_t[1];
$(c_ns)_private_key_t[1];
/**
* Derive a key from its compressed form.
* @param [out] priv The derived private key.
* @param [in] proto The compressed or proto-key, which must be 32 random bytes.
*/
void %(c_ns)s_derive_private_key (
%(c_ns)s_private_key_t priv,
const %(c_ns)s_symmetric_key_t proto
void $(c_ns)_derive_private_key (
$(c_ns)_private_key_t priv,
const $(c_ns)_symmetric_key_t proto
) NONNULL2 API_VIS;

/**
* Destroy a private key.
*/
void %(c_ns)s_destroy_private_key (
%(c_ns)s_private_key_t priv
void $(c_ns)_destroy_private_key (
$(c_ns)_private_key_t priv
) NONNULL1 API_VIS;

/**
@@ -68,9 +63,9 @@ void %(c_ns)s_destroy_private_key (
* @param [out] pub The extracted private key.
* @param [in] priv The private key.
*/
void %(c_ns)s_private_to_public (
%(c_ns)s_public_key_t pub,
const %(c_ns)s_private_key_t priv
void $(c_ns)_private_to_public (
$(c_ns)_public_key_t pub,
const $(c_ns)_private_key_t priv
) NONNULL2 API_VIS;
/**
@@ -89,11 +84,11 @@ void %(c_ns)s_private_to_public (
* @retval DECAF_FAILURE Key exchange failed.
*/
decaf_error_t
%(c_ns)s_shared_secret (
$(c_ns)_shared_secret (
uint8_t *shared,
size_t shared_bytes,
const %(c_ns)s_private_key_t my_privkey,
const %(c_ns)s_public_key_t your_pubkey,
const $(c_ns)_private_key_t my_privkey,
const $(c_ns)_public_key_t your_pubkey,
int me_first
) NONNULL134 WARN_UNUSED API_VIS;
@@ -105,10 +100,10 @@ decaf_error_t
* @param [in] strobe A STROBE context with the message.
*/
void
%(c_ns)s_sign_strobe (
$(c_ns)_sign_strobe (
keccak_strobe_t strobe,
%(c_ns)s_signature_t sig,
const %(c_ns)s_private_key_t priv
$(c_ns)_signature_t sig,
const $(c_ns)_private_key_t priv
) NONNULL3 API_VIS;

/**
@@ -120,9 +115,9 @@ void
* @param [in] message_len The message's length.
*/
void
%(c_ns)s_sign (
%(c_ns)s_signature_t sig,
const %(c_ns)s_private_key_t priv,
$(c_ns)_sign (
$(c_ns)_signature_t sig,
const $(c_ns)_private_key_t priv,
const unsigned char *message,
size_t message_len
) NONNULL3 API_VIS;
@@ -138,10 +133,10 @@ void
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
%(c_ns)s_verify_strobe (
$(c_ns)_verify_strobe (
keccak_strobe_t strobe,
const %(c_ns)s_signature_t sig,
const %(c_ns)s_public_key_t pub
const $(c_ns)_signature_t sig,
const $(c_ns)_public_key_t pub
) NONNULL3 API_VIS WARN_UNUSED;

/**
@@ -156,9 +151,9 @@ decaf_error_t
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
%(c_ns)s_verify (
const %(c_ns)s_signature_t sig,
const %(c_ns)s_public_key_t pub,
$(c_ns)_verify (
const $(c_ns)_signature_t sig,
const $(c_ns)_public_key_t pub,
const unsigned char *message,
size_t message_len
) NONNULL3 API_VIS WARN_UNUSED;
@@ -166,4 +161,3 @@ decaf_error_t
#ifdef __cplusplus
} /* extern "C" */
#endif
""")

src/gen_headers/crypto_hxx.py → src/per_curve/crypto.tmpl.hxx View File

@@ -1,17 +1,12 @@
from gen_file import gen_file
/*
* Example Decaf cyrpto routines, C++ wrapper.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*/

crypto_hxx = gen_file(
public = True,
per = "curve",
name = "decaf/crypto_%(shortname)s.hxx",
doc = """
Example Decaf cyrpto routines, C++ wrapper.
@warning These are merely examples, though they ought to be secure. But real
protocols will decide differently on magic numbers, formats, which items to
hash, etc.
@warning Experimental! The names, parameter orders etc are likely to change.
""", code = """
#include <decaf.hxx>
#include <decaf/decaf_$(gf_bits).hxx>
#include <decaf/shake.hxx>
#include <decaf/strobe.hxx>

@@ -31,21 +26,21 @@ template <typename Group> class PublicKey;
/** A private key for crypto over some Group */
template <typename Group> class PrivateKey;

/** A public key for crypto over %(name)s */
template<> class PublicKey<%(cxx_ns)s>
: public Serializable< PublicKey<%(cxx_ns)s> > {
/** A public key for crypto over $(name) */
template<> class PublicKey<$(cxx_ns)>
: public Serializable< PublicKey<$(cxx_ns)> > {
private:
/** @cond internal */
typedef %(c_ns)s_public_key_t Wrapped;
typedef $(c_ns)_public_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PrivateKey;
/** @endcond */
public:
/** Underlying group */
typedef %(cxx_ns)s Group;
typedef $(cxx_ns) Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof(%(c_ns)s_signature_t);
static const size_t SIG_BYTES = sizeof($(c_ns)_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
@@ -56,7 +51,7 @@ public:
}
/** Read a private key from a string*/
inline explicit PublicKey(const PrivateKey<%(cxx_ns)s> &b) NOEXCEPT;
inline explicit PublicKey(const PrivateKey<$(cxx_ns)> &b) NOEXCEPT;
/** Create but don't initialize */
inline explicit PublicKey(const NOINIT&) NOEXCEPT { }
@@ -74,7 +69,7 @@ public:
const Block &message,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != %(c_ns)s_verify(sig.data(),wrapped,message.data(),message.size())) {
if (DECAF_SUCCESS != $(c_ns)_verify(sig.data(),wrapped,message.data(),message.size())) {
throw(CryptoException());
}
}
@@ -84,33 +79,33 @@ public:
Strobe &context,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != %(c_ns)s_verify_strobe(context.wrapped,sig.data(),wrapped)) {
if (DECAF_SUCCESS != $(c_ns)_verify_strobe(context.wrapped,sig.data(),wrapped)) {
throw(CryptoException());
}
}
};

/** A private key for crypto over %(name)s */
template<> class PrivateKey<%(cxx_ns)s>
: public Serializable< PrivateKey<%(cxx_ns)s> > {
/** A private key for crypto over $(name) */
template<> class PrivateKey<$(cxx_ns)>
: public Serializable< PrivateKey<$(cxx_ns)> > {
private:
/** @cond internal */
typedef %(c_ns)s_private_key_t Wrapped;
typedef $(c_ns)_private_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PublicKey;
/** @endcond */
public:
/** Underlying group */
typedef %(cxx_ns)s Group;
typedef $(cxx_ns) Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof(%(c_ns)s_signature_t);
static const size_t SIG_BYTES = sizeof($(c_ns)_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** Compressed size. */
static const size_t SYM_BYTES = %(C_NS)s_SYMMETRIC_KEY_BYTES;
static const size_t SYM_BYTES = $(C_NS)_SYMMETRIC_KEY_BYTES;
/** Create but don't initialize */
inline explicit PrivateKey(const NOINIT&) NOEXCEPT { }
@@ -122,18 +117,18 @@ public:
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT {
%(c_ns)s_derive_private_key(wrapped, b.data());
$(c_ns)_derive_private_key(wrapped, b.data());
}
/** Create at random */
inline explicit PrivateKey(Rng &r) NOEXCEPT {
FixedArrayBuffer<SYM_BYTES> tmp(r);
%(c_ns)s_derive_private_key(wrapped, tmp.data());
$(c_ns)_derive_private_key(wrapped, tmp.data());
}
/** Secure destructor */
inline ~PrivateKey() NOEXCEPT {
%(c_ns)s_destroy_private_key(wrapped);
$(c_ns)_destroy_private_key(wrapped);
}
/** Serialization size. */
@@ -152,18 +147,18 @@ public:
}
/** Get the public key */
inline PublicKey<%(cxx_ns)s> pub() const NOEXCEPT {
PublicKey<%(cxx_ns)s> ret(*this); return ret;
inline PublicKey<$(cxx_ns)> pub() const NOEXCEPT {
PublicKey<$(cxx_ns)> ret(*this); return ret;
}
/** Derive a shared secret */
inline SecureBuffer sharedSecret(
const PublicKey<%(cxx_ns)s> &pub,
const PublicKey<$(cxx_ns)> &pub,
size_t bytes,
bool me_first
) const throw(CryptoException,std::bad_alloc) {
SecureBuffer ret(bytes);
if (DECAF_SUCCESS != %(c_ns)s_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) {
if (DECAF_SUCCESS != $(c_ns)_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) {
throw(CryptoException());
}
return ret;
@@ -173,33 +168,32 @@ public:
inline decaf_error_t __attribute__((warn_unused_result))
sharedSecretNoexcept(
Buffer ret,
const PublicKey<%(cxx_ns)s> &pub,
const PublicKey<$(cxx_ns)> &pub,
bool me_first
) const NOEXCEPT {
return %(c_ns)s_shared_secret(ret.data(),ret.size(),wrapped,pub.wrapped,me_first);
return $(c_ns)_shared_secret(ret.data(),ret.size(),wrapped,pub.wrapped,me_first);
}

/** Sign a message. */
inline SecureBuffer sign(const Block &message) const {
SecureBuffer sig(SIG_BYTES);
%(c_ns)s_sign(sig.data(), wrapped, message.data(), message.size());
$(c_ns)_sign(sig.data(), wrapped, message.data(), message.size());
return sig;
}

/** Sign a message. */
inline SecureBuffer verify(Strobe &context) const {
SecureBuffer sig(SIG_BYTES);
%(c_ns)s_sign_strobe(context.wrapped, sig.data(), wrapped);
$(c_ns)_sign_strobe(context.wrapped, sig.data(), wrapped);
return sig;
}
};

/** @cond internal */
PublicKey<%(cxx_ns)s>::PublicKey(const PrivateKey<%(cxx_ns)s> &b) NOEXCEPT {
%(c_ns)s_private_to_public(wrapped,b.wrapped);
PublicKey<$(cxx_ns)>::PublicKey(const PrivateKey<$(cxx_ns)> &b) NOEXCEPT {
$(c_ns)_private_to_public(wrapped,b.wrapped);
}
/** @endcond */

#undef NOEXCEPT
} /* namespace decaf */
""")
} /* namespace decaf */

+ 2
- 4
src/per_curve/decaf.tmpl.c View File

@@ -19,7 +19,7 @@
#define IMAGINE_TWIST $(imagine_twist)
#define COFACTOR $(cofactor)

/** Comb config: number of combs, n, t, s. */
/* Comb config: number of combs, n, t, s. */
#define COMBS_N $(combs.n)
#define COMBS_T $(combs.t)
#define COMBS_S $(combs.s)
@@ -39,9 +39,7 @@ static const scalar_t sc_p = {{{
}}};
static const decaf_word_t MONTGOMERY_FACTOR = (decaf_word_t)0x$("%x" % pow(-q,2**64-1,2**64))ull;

const uint8_t API_NS(x_base_point)[SER_BYTES] /* TODO */ = {
$(ser(mont_base,8))
};
const uint8_t API_NS(x_base_point)[SER_BYTES] = { $(ser(mont_base,8)) };

#if COFACTOR==8
static const gf SQRT_ONE_MINUS_D = {FIELD_LITERAL(


src/gen_headers/decaf_h.py → src/per_curve/decaf.tmpl.h View File

@@ -1,11 +1,5 @@
from gen_file import gen_file

decaf_h = gen_file(
public = True,
per = "curve",
name = "decaf/%(c_ns)s.h",
doc = """@brief A group of prime order p, based on %(iso_to)s.""",
code = """
/** @brief A group of prime order p, based on $(iso_to). */

#include <decaf/common.h>

#ifdef __cplusplus
@@ -13,78 +7,78 @@ extern "C" {
#endif

/** @cond internal */
#define %(C_NS)s_SCALAR_LIMBS ((%(scalar_bits)d-1)/DECAF_WORD_BITS+1)
#define $(C_NS)_SCALAR_LIMBS (($(scalar_bits)-1)/DECAF_WORD_BITS+1)
/** @endcond */

/** The number of bits in a scalar */
#define %(C_NS)s_SCALAR_BITS %(scalar_bits)d
#define $(C_NS)_SCALAR_BITS $(scalar_bits)

/** @cond internal */
#ifndef __DECAF_%(gf_shortname)s_GF_DEFINED__
#define __DECAF_%(gf_shortname)s_GF_DEFINED__ 1
#ifndef __DECAF_$(gf_shortname)_GF_DEFINED__
#define __DECAF_$(gf_shortname)_GF_DEFINED__ 1
/** @brief Galois field element internal structure */
typedef struct gf_%(gf_shortname)s_s {
decaf_word_t limb[%(gf_impl_bits)d/DECAF_WORD_BITS];
} __attribute__((aligned(32))) gf_%(gf_shortname)s_s, gf_%(gf_shortname)s_t[1];
#endif /* __DECAF_%(gf_shortname)s_GF_DEFINED__ */
typedef struct gf_$(gf_shortname)_s {
decaf_word_t limb[$(gf_impl_bits)/DECAF_WORD_BITS];
} __attribute__((aligned(32))) gf_$(gf_shortname)_s, gf_$(gf_shortname)_t[1];
#endif /* __DECAF_$(gf_shortname)_GF_DEFINED__ */
/** @endcond */

/** Number of bytes in a serialized point. */
#define %(C_NS)s_SER_BYTES %(ser_bytes)d
#define $(C_NS)_SER_BYTES $(ser_bytes)

/** Number of bytes in a serialized scalar. */
#define %(C_NS)s_SCALAR_BYTES %(scalar_ser_bytes)d
#define $(C_NS)_SCALAR_BYTES $(scalar_ser_bytes)

/** Number of bytes in an x%(gf_shortname)s public key */
#define X%(gf_shortname)s_PUBLIC_BYTES %(x_pub_bytes)d
/** Number of bytes in an x$(gf_shortname) public key */
#define X$(gf_shortname)_PUBLIC_BYTES $(x_pub_bytes)

/** Number of bytes in an x%(gf_shortname)s private key */
#define X%(gf_shortname)s_PRIVATE_BYTES %(x_priv_bytes)d
/** Number of bytes in an x$(gf_shortname) private key */
#define X$(gf_shortname)_PRIVATE_BYTES $(x_priv_bytes)

/** Twisted Edwards extended homogeneous coordinates */
typedef struct %(c_ns)s_point_s {
typedef struct $(c_ns)_point_s {
/** @cond internal */
gf_%(gf_shortname)s_t x,y,z,t;
gf_$(gf_shortname)_t x,y,z,t;
/** @endcond */
} %(c_ns)s_point_t[1];
} $(c_ns)_point_t[1];

/** Precomputed table based on a point. Can be trivial implementation. */
struct %(c_ns)s_precomputed_s;
struct $(c_ns)_precomputed_s;

/** Precomputed table based on a point. Can be trivial implementation. */
typedef struct %(c_ns)s_precomputed_s %(c_ns)s_precomputed_s;
typedef struct $(c_ns)_precomputed_s $(c_ns)_precomputed_s;

/** Size and alignment of precomputed point tables. */
extern const size_t %(c_ns)s_sizeof_precomputed_s API_VIS, %(c_ns)s_alignof_precomputed_s API_VIS;
extern const size_t $(c_ns)_sizeof_precomputed_s API_VIS, $(c_ns)_alignof_precomputed_s API_VIS;

/** Scalar is stored packed, because we don't need the speed. */
typedef struct %(c_ns)s_scalar_s {
typedef struct $(c_ns)_scalar_s {
/** @cond internal */
decaf_word_t limb[%(C_NS)s_SCALAR_LIMBS];
decaf_word_t limb[$(C_NS)_SCALAR_LIMBS];
/** @endcond */
} %(c_ns)s_scalar_t[1];
} $(c_ns)_scalar_t[1];

/** A scalar equal to 1. */
extern const %(c_ns)s_scalar_t %(c_ns)s_scalar_one API_VIS;
extern const $(c_ns)_scalar_t $(c_ns)_scalar_one API_VIS;

/** A scalar equal to 0. */
extern const %(c_ns)s_scalar_t %(c_ns)s_scalar_zero API_VIS;
extern const $(c_ns)_scalar_t $(c_ns)_scalar_zero API_VIS;

/** The identity point on the curve. */
extern const %(c_ns)s_point_t %(c_ns)s_point_identity API_VIS;
extern const $(c_ns)_point_t $(c_ns)_point_identity API_VIS;

/** An arbitrarily chosen base point on the curve.
* @warning TODO: this is subject to change. It is currently
* the preimage of the X%(gf_shortname)s base point. Sometime
* soon, we will merge and finalize support for X%(gf_shortname)s
* and Ed%(gf_shortname)s integration. This might make some
* the preimage of the X$(gf_shortname) base point. Sometime
* soon, we will merge and finalize support for X$(gf_shortname)
* and Ed$(gf_shortname) integration. This might make some
* multiple of the current basepoint (eg twice it, or the cofactor
* times it) more convenient API-wise, and trigger a changeover.
*/
extern const %(c_ns)s_point_t %(c_ns)s_point_base API_VIS;
extern const $(c_ns)_point_t $(c_ns)_point_base API_VIS;

/** Precomputed table for the base point on the curve. */
extern const struct %(c_ns)s_precomputed_s *%(c_ns)s_precomputed_base API_VIS;
extern const struct $(c_ns)_precomputed_s *$(c_ns)_precomputed_base API_VIS;

/**
* @brief Read a scalar from wire format or from bytes.
@@ -96,9 +90,9 @@ extern const struct %(c_ns)s_precomputed_s *%(c_ns)s_precomputed_base API_VIS;
* @retval DECAF_FAILURE The scalar was greater than the modulus,
* and has been reduced modulo that modulus.
*/
decaf_error_t %(c_ns)s_scalar_decode (
%(c_ns)s_scalar_t out,
const unsigned char ser[%(C_NS)s_SCALAR_BYTES]
decaf_error_t $(c_ns)_scalar_decode (
$(c_ns)_scalar_t out,
const unsigned char ser[$(C_NS)_SCALAR_BYTES]
) API_VIS WARN_UNUSED NONNULL2 NOINLINE;

/**
@@ -109,8 +103,8 @@ decaf_error_t %(c_ns)s_scalar_decode (
* @param [in] ser_len Length of serialized form.
* @param [out] out Deserialized form.
*/
void %(c_ns)s_scalar_decode_long (
%(c_ns)s_scalar_t out,
void $(c_ns)_scalar_decode_long (
$(c_ns)_scalar_t out,
const unsigned char *ser,
size_t ser_len
) API_VIS NONNULL2 NOINLINE;
@@ -121,9 +115,9 @@ void %(c_ns)s_scalar_decode_long (
* @param [out] ser Serialized form of a scalar.
* @param [in] s Deserialized scalar.
*/
void %(c_ns)s_scalar_encode (
unsigned char ser[%(C_NS)s_SCALAR_BYTES],
const %(c_ns)s_scalar_t s
void $(c_ns)_scalar_encode (
unsigned char ser[$(C_NS)_SCALAR_BYTES],
const $(c_ns)_scalar_t s
) API_VIS NONNULL2 NOINLINE NOINLINE;
/**
@@ -132,10 +126,10 @@ void %(c_ns)s_scalar_encode (
* @param [in] b Another scalar.
* @param [out] out a+b.
*/
void %(c_ns)s_scalar_add (
%(c_ns)s_scalar_t out,
const %(c_ns)s_scalar_t a,
const %(c_ns)s_scalar_t b
void $(c_ns)_scalar_add (
$(c_ns)_scalar_t out,
const $(c_ns)_scalar_t a,
const $(c_ns)_scalar_t b
) API_VIS NONNULL3 NOINLINE;

/**
@@ -145,9 +139,9 @@ void %(c_ns)s_scalar_add (
* @retval DECAF_TRUE The scalars are equal.
* @retval DECAF_FALSE The scalars are not equal.
*/
decaf_bool_t %(c_ns)s_scalar_eq (
const %(c_ns)s_scalar_t a,
const %(c_ns)s_scalar_t b
decaf_bool_t $(c_ns)_scalar_eq (
const $(c_ns)_scalar_t a,
const $(c_ns)_scalar_t b
) API_VIS WARN_UNUSED NONNULL2 NOINLINE;

/**
@@ -156,10 +150,10 @@ decaf_bool_t %(c_ns)s_scalar_eq (
* @param [in] b Another scalar.
* @param [out] out a-b.
*/
void %(c_ns)s_scalar_sub (
%(c_ns)s_scalar_t out,
const %(c_ns)s_scalar_t a,
const %(c_ns)s_scalar_t b
void $(c_ns)_scalar_sub (
$(c_ns)_scalar_t out,
const $(c_ns)_scalar_t a,
const $(c_ns)_scalar_t b
) API_VIS NONNULL3 NOINLINE;

/**
@@ -168,10 +162,10 @@ void %(c_ns)s_scalar_sub (
* @param [in] b Another scalar.
* @param [out] out a*b.
*/
void %(c_ns)s_scalar_mul (
%(c_ns)s_scalar_t out,
const %(c_ns)s_scalar_t a,
const %(c_ns)s_scalar_t b
void $(c_ns)_scalar_mul (
$(c_ns)_scalar_t out,
const $(c_ns)_scalar_t a,
const $(c_ns)_scalar_t b
) API_VIS NONNULL3 NOINLINE;

/**
@@ -180,9 +174,9 @@ void %(c_ns)s_scalar_mul (
* @param [out] out 1/a.
* @return DECAF_SUCCESS The input is nonzero.
*/
decaf_error_t %(c_ns)s_scalar_invert (
%(c_ns)s_scalar_t out,
const %(c_ns)s_scalar_t a
decaf_error_t $(c_ns)_scalar_invert (
$(c_ns)_scalar_t out,
const $(c_ns)_scalar_t a
) API_VIS WARN_UNUSED NONNULL2 NOINLINE;

/**
@@ -191,9 +185,9 @@ decaf_error_t %(c_ns)s_scalar_invert (
* @param [in] a A scalar.
* @param [out] out Will become a copy of a.
*/
static inline void NONNULL2 %(c_ns)s_scalar_copy (
%(c_ns)s_scalar_t out,
const %(c_ns)s_scalar_t a
static inline void NONNULL2 $(c_ns)_scalar_copy (
$(c_ns)_scalar_t out,
const $(c_ns)_scalar_t a
) {
*out = *a;
}
@@ -203,8 +197,8 @@ static inline void NONNULL2 %(c_ns)s_scalar_copy (
* @param [in] a An integer.
* @param [out] out Will become equal to a.
*/
void %(c_ns)s_scalar_set_unsigned (
%(c_ns)s_scalar_t out,
void $(c_ns)_scalar_set_unsigned (
$(c_ns)_scalar_t out,
uint64_t a
) API_VIS NONNULL1;

@@ -214,9 +208,9 @@ void %(c_ns)s_scalar_set_unsigned (
* @param [out] ser The byte representation of the point.
* @param [in] pt The point to encode.
*/
void %(c_ns)s_point_encode (
uint8_t ser[%(C_NS)s_SER_BYTES],
const %(c_ns)s_point_t pt
void $(c_ns)_point_encode (
uint8_t ser[$(C_NS)_SER_BYTES],
const $(c_ns)_point_t pt
) API_VIS NONNULL2 NOINLINE;

/**
@@ -233,9 +227,9 @@ void %(c_ns)s_point_encode (
* @retval DECAF_FAILURE The decoding didn't succeed, because
* ser does not represent a point.
*/
decaf_error_t %(c_ns)s_point_decode (
%(c_ns)s_point_t pt,
const uint8_t ser[%(C_NS)s_SER_BYTES],
decaf_error_t $(c_ns)_point_decode (
$(c_ns)_point_t pt,
const uint8_t ser[$(C_NS)_SER_BYTES],
decaf_bool_t allow_identity
) API_VIS WARN_UNUSED NONNULL2 NOINLINE;

@@ -246,9 +240,9 @@ decaf_error_t %(c_ns)s_point_decode (
* @param [out] a A copy of the point.
* @param [in] b Any point.
*/
static inline void NONNULL2 %(c_ns)s_point_copy (
%(c_ns)s_point_t a,
const %(c_ns)s_point_t b
static inline void NONNULL2 $(c_ns)_point_copy (
$(c_ns)_point_t a,
const $(c_ns)_point_t b
) {
*a=*b;
}
@@ -262,9 +256,9 @@ static inline void NONNULL2 %(c_ns)s_point_copy (
* @retval DECAF_TRUE The points are equal.
* @retval DECAF_FALSE The points are not equal.
*/
decaf_bool_t %(c_ns)s_point_eq (
const %(c_ns)s_point_t a,
const %(c_ns)s_point_t b
decaf_bool_t $(c_ns)_point_eq (
const $(c_ns)_point_t a,
const $(c_ns)_point_t b
) API_VIS WARN_UNUSED NONNULL2 NOINLINE;

/**
@@ -276,22 +270,22 @@ decaf_bool_t %(c_ns)s_point_eq (
* @param [in] a An addend.
* @param [in] b An addend.
*/
void %(c_ns)s_point_add (
%(c_ns)s_point_t sum,
const %(c_ns)s_point_t a,
const %(c_ns)s_point_t b
void $(c_ns)_point_add (
$(c_ns)_point_t sum,
const $(c_ns)_point_t a,
const $(c_ns)_point_t b
) API_VIS NONNULL3;

/**
* @brief Double a point. Equivalent to
* %(c_ns)s_point_add(two_a,a,a), but potentially faster.
* $(c_ns)_point_add(two_a,a,a), but potentially faster.
*
* @param [out] two_a The sum a+a.
* @param [in] a A point.
*/
void %(c_ns)s_point_double (
%(c_ns)s_point_t two_a,
const %(c_ns)s_point_t a
void $(c_ns)_point_double (
$(c_ns)_point_t two_a,
const $(c_ns)_point_t a
) API_VIS NONNULL2;

/**
@@ -303,10 +297,10 @@ void %(c_ns)s_point_double (
* @param [in] a The minuend.
* @param [in] b The subtrahend.
*/
void %(c_ns)s_point_sub (
%(c_ns)s_point_t diff,
const %(c_ns)s_point_t a,
const %(c_ns)s_point_t b
void $(c_ns)_point_sub (
$(c_ns)_point_t diff,
const $(c_ns)_point_t a,
const $(c_ns)_point_t b
) API_VIS NONNULL3;
/**
@@ -316,9 +310,9 @@ void %(c_ns)s_point_sub (
* @param [out] nega The negated input point
* @param [in] a The input point.
*/
void %(c_ns)s_point_negate (
%(c_ns)s_point_t nega,
const %(c_ns)s_point_t a
void $(c_ns)_point_negate (
$(c_ns)_point_t nega,
const $(c_ns)_point_t a
) API_VIS NONNULL2;

/**
@@ -328,10 +322,10 @@ void %(c_ns)s_point_negate (
* @param [in] base The point to be scaled.
* @param [in] scalar The scalar to multiply by.
*/
void %(c_ns)s_point_scalarmul (
%(c_ns)s_point_t scaled,
const %(c_ns)s_point_t base,
const %(c_ns)s_scalar_t scalar
void $(c_ns)_point_scalarmul (
$(c_ns)_point_t scaled,
const $(c_ns)_point_t base,
const $(c_ns)_scalar_t scalar
) API_VIS NONNULL3 NOINLINE;

/**
@@ -351,10 +345,10 @@ void %(c_ns)s_point_scalarmul (
* @retval DECAF_FAILURE The scalarmul didn't succeed, because
* base does not represent a point.
*/
decaf_error_t %(c_ns)s_direct_scalarmul (
uint8_t scaled[%(C_NS)s_SER_BYTES],
const uint8_t base[%(C_NS)s_SER_BYTES],
const %(c_ns)s_scalar_t scalar,
decaf_error_t $(c_ns)_direct_scalarmul (
uint8_t scaled[$(C_NS)_SER_BYTES],
const uint8_t base[$(C_NS)_SER_BYTES],
const $(c_ns)_scalar_t scalar,
decaf_bool_t allow_identity,
decaf_bool_t short_circuit
) API_VIS NONNULL3 WARN_UNUSED NOINLINE;
@@ -371,14 +365,14 @@ decaf_error_t %(c_ns)s_direct_scalarmul (
* @retval DECAF_FAILURE The scalarmul didn't succeed, because the base
* point is in a small subgroup.
*/
decaf_error_t %(c_ns)s_x_direct_scalarmul ( /* TODO: rename? */
uint8_t out[X%(gf_shortname)s_PUBLIC_BYTES],
const uint8_t base[X%(gf_shortname)s_PUBLIC_BYTES],
const uint8_t scalar[X%(gf_shortname)s_PRIVATE_BYTES]
decaf_error_t $(c_ns)_x_direct_scalarmul ( /* TODO: rename? */
uint8_t out[X$(gf_shortname)_PUBLIC_BYTES],
const uint8_t base[X$(gf_shortname)_PUBLIC_BYTES],
const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES]
) API_VIS NONNULL3 WARN_UNUSED NOINLINE;

/** The base point for X%(gf_shortname)s Diffie-Hellman */
extern const uint8_t %(c_ns)s_x_base_point[X%(gf_shortname)s_PUBLIC_BYTES] API_VIS;
/** The base point for X$(gf_shortname) Diffie-Hellman */
extern const uint8_t $(c_ns)_x_base_point[X$(gf_shortname)_PUBLIC_BYTES] API_VIS;

/**
* @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses
@@ -387,9 +381,9 @@ extern const uint8_t %(c_ns)s_x_base_point[X%(gf_shortname)s_PUBLIC_BYTES] API_V
* @param [out] scaled The scaled point base*scalar
* @param [in] scalar The scalar to multiply by.
*/
void %(c_ns)s_x_base_scalarmul (
uint8_t out[X%(gf_shortname)s_PUBLIC_BYTES],
const uint8_t scalar[X%(gf_shortname)s_PRIVATE_BYTES]
void $(c_ns)_x_base_scalarmul (
uint8_t out[X$(gf_shortname)_PUBLIC_BYTES],
const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES]
) API_VIS NONNULL2 NOINLINE;

/**
@@ -401,9 +395,9 @@ void %(c_ns)s_x_base_scalarmul (
* @param [out] a A precomputed table of multiples of the point.
* @param [in] b Any point.
*/
void %(c_ns)s_precompute (
%(c_ns)s_precomputed_s *a,
const %(c_ns)s_point_t b
void $(c_ns)_precompute (
$(c_ns)_precomputed_s *a,
const $(c_ns)_point_t b
) API_VIS NONNULL2 NOINLINE;

/**
@@ -411,23 +405,23 @@ void %(c_ns)s_precompute (
* scaled = scalar*base.
* Some implementations do not include precomputed points; for
* those implementations, this function is the same as
* %(c_ns)s_point_scalarmul
* $(c_ns)_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 %(c_ns)s_precomputed_scalarmul (
%(c_ns)s_point_t scaled,
const %(c_ns)s_precomputed_s *base,
const %(c_ns)s_scalar_t scalar
void $(c_ns)_precomputed_scalarmul (
$(c_ns)_point_t scaled,
const $(c_ns)_precomputed_s *base,
const $(c_ns)_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 %(c_ns)s_point_scalarmul, but may be
* Equivalent to two calls to $(c_ns)_point_scalarmul, but may be
* faster.
*
* @param [out] combo The linear combination scalar1*base1 + scalar2*base2.
@@ -436,12 +430,12 @@ void %(c_ns)s_precomputed_scalarmul (
* @param [in] base2 A second point to be scaled.
* @param [in] scalar2 A second scalar to multiply by.
*/
void %(c_ns)s_point_double_scalarmul (
%(c_ns)s_point_t combo,
const %(c_ns)s_point_t base1,
const %(c_ns)s_scalar_t scalar1,
const %(c_ns)s_point_t base2,
const %(c_ns)s_scalar_t scalar2
void $(c_ns)_point_double_scalarmul (
$(c_ns)_point_t combo,
const $(c_ns)_point_t base1,
const $(c_ns)_scalar_t scalar1,
const $(c_ns)_point_t base2,
const $(c_ns)_scalar_t scalar2
) API_VIS NONNULL5 NOINLINE;
/**
@@ -450,7 +444,7 @@ void %(c_ns)s_point_double_scalarmul (
* a1 = scalar1 * base
* a2 = scalar2 * base
*
* Equivalent to two calls to %(c_ns)s_point_scalarmul, but may be
* Equivalent to two calls to $(c_ns)_point_scalarmul, but may be
* faster.
*
* @param [out] a1 The first multiple. It may be the same as the input point.
@@ -459,19 +453,19 @@ void %(c_ns)s_point_double_scalarmul (
* @param [in] scalar1 A first scalar to multiply by.
* @param [in] scalar2 A second scalar to multiply by.
*/
void %(c_ns)s_point_dual_scalarmul (
%(c_ns)s_point_t a1,
%(c_ns)s_point_t a2,
const %(c_ns)s_point_t base1,
const %(c_ns)s_scalar_t scalar1,
const %(c_ns)s_scalar_t scalar2
void $(c_ns)_point_dual_scalarmul (
$(c_ns)_point_t a1,
$(c_ns)_point_t a2,
const $(c_ns)_point_t base1,
const $(c_ns)_scalar_t scalar1,
const $(c_ns)_scalar_t scalar2
) API_VIS NONNULL5 NOINLINE;

/**
* @brief Multiply two base points by two scalars:
* scaled = scalar1*%(c_ns)s_point_base + scalar2*base2.
* scaled = scalar1*$(c_ns)_point_base + scalar2*base2.
*
* Otherwise equivalent to %(c_ns)s_point_double_scalarmul, but may be
* Otherwise equivalent to $(c_ns)_point_double_scalarmul, but may be
* faster at the expense of being variable time.
*
* @param [out] combo The linear combination scalar1*base + scalar2*base2.
@@ -482,11 +476,11 @@ void %(c_ns)s_point_dual_scalarmul (
* @warning: This function takes variable time, and may leak the scalars
* used. It is designed for signature verification.
*/
void %(c_ns)s_base_double_scalarmul_non_secret (
%(c_ns)s_point_t combo,
const %(c_ns)s_scalar_t scalar1,
const %(c_ns)s_point_t base2,
const %(c_ns)s_scalar_t scalar2
void $(c_ns)_base_double_scalarmul_non_secret (
$(c_ns)_point_t combo,
const $(c_ns)_scalar_t scalar1,
const $(c_ns)_point_t base2,
const $(c_ns)_scalar_t scalar2
) API_VIS NONNULL4 NOINLINE;

/**
@@ -498,10 +492,10 @@ void %(c_ns)s_base_double_scalarmul_non_secret (
* @param [in] b Any point.
* @param [in] pick_b If nonzero, choose point b.
*/
void %(c_ns)s_point_cond_sel (
%(c_ns)s_point_t out,
const %(c_ns)s_point_t a,
const %(c_ns)s_point_t b,
void $(c_ns)_point_cond_sel (
$(c_ns)_point_t out,
const $(c_ns)_point_t a,
const $(c_ns)_point_t b,
decaf_word_t pick_b
) API_VIS NONNULL3 NOINLINE;

@@ -514,10 +508,10 @@ void %(c_ns)s_point_cond_sel (
* @param [in] b Any scalar.
* @param [in] pick_b If nonzero, choose scalar b.
*/
void %(c_ns)s_scalar_cond_sel (
%(c_ns)s_scalar_t out,
const %(c_ns)s_scalar_t a,
const %(c_ns)s_scalar_t b,
void $(c_ns)_scalar_cond_sel (
$(c_ns)_scalar_t out,
const $(c_ns)_scalar_t a,
const $(c_ns)_scalar_t b,
decaf_word_t pick_b
) API_VIS NONNULL3 NOINLINE;

@@ -528,8 +522,8 @@ void %(c_ns)s_scalar_cond_sel (
* @retval DECAF_TRUE The point is valid.
* @retval DECAF_FALSE The point is invalid.
*/
decaf_bool_t %(c_ns)s_point_valid (
const %(c_ns)s_point_t toTest
decaf_bool_t $(c_ns)_point_valid (
const $(c_ns)_point_t toTest
) API_VIS WARN_UNUSED NONNULL1 NOINLINE;

/**
@@ -539,9 +533,9 @@ decaf_bool_t %(c_ns)s_point_valid (
* @param [out] q The point to torque.
* @param [in] p The point to torque.
*/
void %(c_ns)s_point_debugging_torque (
%(c_ns)s_point_t q,
const %(c_ns)s_point_t p
void $(c_ns)_point_debugging_torque (
$(c_ns)_point_t q,
const $(c_ns)_point_t p
) API_VIS NONNULL2 NOINLINE;

/**
@@ -553,10 +547,10 @@ void %(c_ns)s_point_debugging_torque (
* @param [in] p The point to scale.
* @param [in] factor Serialized GF factor to scale.
*/
void %(c_ns)s_point_debugging_pscale (
%(c_ns)s_point_t q,
const %(c_ns)s_point_t p,
const unsigned char factor[%(C_NS)s_SER_BYTES]
void $(c_ns)_point_debugging_pscale (
$(c_ns)_point_t q,
const $(c_ns)_point_t p,
const unsigned char factor[$(C_NS)_SER_BYTES]
) API_VIS NONNULL2 NOINLINE;

/**
@@ -564,7 +558,7 @@ void %(c_ns)s_point_debugging_pscale (
*
* Call this function with the output of a hash to make a hash to the curve.
*
* This function runs Elligator2 on the %(c_ns)s Jacobi quartic model. It then
* This function runs Elligator2 on the $(c_ns) 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
@@ -588,29 +582,29 @@ void %(c_ns)s_point_debugging_pscale (
* @param [out] pt The data hashed to the curve.
*/
void
%(c_ns)s_point_from_hash_nonuniform (
%(c_ns)s_point_t pt,
const unsigned char hashed_data[%(C_NS)s_SER_BYTES]
$(c_ns)_point_from_hash_nonuniform (
$(c_ns)_point_t pt,
const unsigned char hashed_data[$(C_NS)_SER_BYTES]
) API_VIS NONNULL2 NOINLINE;

/**
* @brief Indifferentiable hash function encoding to curve.
*
* Equivalent to calling %(c_ns)s_point_from_hash_nonuniform twice and adding.
* Equivalent to calling $(c_ns)_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 %(c_ns)s_point_from_hash_uniform (
%(c_ns)s_point_t pt,
const unsigned char hashed_data[2*%(C_NS)s_SER_BYTES]
void $(c_ns)_point_from_hash_uniform (
$(c_ns)_point_t pt,
const unsigned char hashed_data[2*$(C_NS)_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
* %(c_ns)s_point_from_hash_nonuniform(buffer) = pt if
* $(c_ns)_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
@@ -625,9 +619,9 @@ void %(c_ns)s_point_from_hash_uniform (
* @retval DECAF_FAILURE The inverse failed.
*/
decaf_error_t
%(c_ns)s_invert_elligator_nonuniform (
unsigned char recovered_hash[%(C_NS)s_SER_BYTES],
const %(c_ns)s_point_t pt,
$(c_ns)_invert_elligator_nonuniform (
unsigned char recovered_hash[$(C_NS)_SER_BYTES],
const $(c_ns)_point_t pt,
uint16_t which
) API_VIS NONNULL2 NOINLINE WARN_UNUSED;

@@ -635,7 +629,7 @@ decaf_error_t
* @brief Inverse of elligator-like hash to curve.
*
* This function writes to the buffer, to make it so that
* %(c_ns)s_point_from_hash_uniform(buffer) = pt if
* $(c_ns)_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
@@ -650,36 +644,34 @@ decaf_error_t
* @retval DECAF_FAILURE The inverse failed.
*/
decaf_error_t
%(c_ns)s_invert_elligator_uniform (
unsigned char recovered_hash[2*%(C_NS)s_SER_BYTES],
const %(c_ns)s_point_t pt,
$(c_ns)_invert_elligator_uniform (
unsigned char recovered_hash[2*$(C_NS)_SER_BYTES],
const $(c_ns)_point_t pt,
uint16_t which
) API_VIS NONNULL2 NOINLINE WARN_UNUSED;

/**
* @brief Overwrite scalar with zeros.
*/
void %(c_ns)s_scalar_destroy (
%(c_ns)s_scalar_t scalar
void $(c_ns)_scalar_destroy (
$(c_ns)_scalar_t scalar
) NONNULL1 API_VIS;

/**
* @brief Overwrite point with zeros.
* @todo Use this internally.
*/
void %(c_ns)s_point_destroy (
%(c_ns)s_point_t point
void $(c_ns)_point_destroy (
$(c_ns)_point_t point
) NONNULL1 API_VIS;

/**
* @brief Overwrite precomputed table with zeros.
*/
void %(c_ns)s_precomputed_destroy (
%(c_ns)s_precomputed_s *pre
void $(c_ns)_precomputed_destroy (
$(c_ns)_precomputed_s *pre
) NONNULL1 API_VIS;

#ifdef __cplusplus
} /* extern "C" */
#endif
"""
)

src/gen_headers/decaf_hxx.py → src/per_curve/decaf.tmpl.hxx View File

@@ -1,23 +1,18 @@
from gen_file import gen_file

decaf_hxx = gen_file(
public = True,
per = "curve",
name = "decaf/%(c_ns)s.hxx",
doc = """
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 %(iso_to)s) and wiping out the cofactor.

The formulas are all complete and have no special cases, except that
%(c_ns)s_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 %(c_ns)s_base_double_scalarmul_non_secret.
""", code = """
/**
* 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 $(iso_to)) and wiping out the cofactor.
*
* The formulas are all complete and have no special cases, except that
* $(c_ns)_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 $(c_ns)_base_double_scalarmul_non_secret.
*/

/** This code uses posix_memalign. */
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
@@ -25,7 +20,7 @@ decaf_hxx = gen_file(
#include <stdlib.h>
#include <string.h> /* for memcpy */

#include <decaf.h>
#include <decaf/decaf_$(gf_bits).h>
#include <decaf/secure_buffer.hxx>
#include <string>
#include <sys/types.h>
@@ -42,18 +37,18 @@ decaf_hxx = gen_file(
namespace decaf {

/**
* %(iso_to)s/Decaf instantiation of group.
* $(iso_to)/Decaf instantiation of group.
*/
struct %(cxx_ns)s {
struct $(cxx_ns) {

/** The name of the curve */
static inline const char *name() { return "%(name)s"; }
static inline const char *name() { return "$(name)"; }

/** The curve's cofactor (removed, but useful for testing) */
static const int REMOVED_COFACTOR = %(cofactor)d;
static const int REMOVED_COFACTOR = $(cofactor);

/** Residue class of field modulus: p == this mod 2*(this-1) */
static const int FIELD_MODULUS_TYPE = %(modulus_type)d;
static const int FIELD_MODULUS_TYPE = $(modulus_type);

/** @cond internal */
class Point;
@@ -67,10 +62,10 @@ class Precomputed;
class Scalar : public Serializable<Scalar> {
public:
/** wrapped C type */
typedef %(c_ns)s_scalar_t Wrapped;
typedef $(c_ns)_scalar_t Wrapped;
/** Size of a serialized element */
static const size_t SER_BYTES = %(C_NS)s_SCALAR_BYTES;
static const size_t SER_BYTES = $(C_NS)_SCALAR_BYTES;

/** access to the underlying scalar object */
Wrapped s;
@@ -99,7 +94,7 @@ public:
}

/** Construct from decaf_scalar_t object. */
inline Scalar(const Wrapped &t = %(c_ns)s_scalar_zero) NOEXCEPT { %(c_ns)s_scalar_copy(s,t); }
inline Scalar(const Wrapped &t = $(c_ns)_scalar_zero) NOEXCEPT { $(c_ns)_scalar_copy(s,t); }

/** Copy constructor. */
inline Scalar(const Scalar &x) NOEXCEPT { *this = x; }
@@ -112,20 +107,20 @@ public:

/** Serializable instance */
inline void serialize_into(unsigned char *buffer) const NOEXCEPT {
%(c_ns)s_scalar_encode(buffer, s);
$(c_ns)_scalar_encode(buffer, s);
}

/** Assignment. */
inline Scalar& operator=(const Scalar &x) NOEXCEPT { %(c_ns)s_scalar_copy(s,x.s); return *this; }
inline Scalar& operator=(const Scalar &x) NOEXCEPT { $(c_ns)_scalar_copy(s,x.s); return *this; }

/** Assign from unsigned 64-bit integer. */
inline Scalar& operator=(uint64_t w) NOEXCEPT { %(c_ns)s_scalar_set_unsigned(s,w); return *this; }
inline Scalar& operator=(uint64_t w) NOEXCEPT { $(c_ns)_scalar_set_unsigned(s,w); return *this; }


/** Assign from signed int. */
inline Scalar& operator=(int64_t w) NOEXCEPT {
Scalar t(-(uint64_t)INT_MIN);
%(c_ns)s_scalar_set_unsigned(s,(uint64_t)w - (uint64_t)INT_MIN);
$(c_ns)_scalar_set_unsigned(s,(uint64_t)w - (uint64_t)INT_MIN);
*this -= t;
return *this;
}
@@ -137,11 +132,11 @@ public:
inline Scalar& operator=(int w) NOEXCEPT { return *this = (int64_t)w; }

/** Destructor securely zeorizes the scalar. */
inline ~Scalar() NOEXCEPT { %(c_ns)s_scalar_destroy(s); }
inline ~Scalar() NOEXCEPT { $(c_ns)_scalar_destroy(s); }

/** Assign from arbitrary-length little-endian byte sequence in a Block. */
inline Scalar &operator=(const Block &bl) NOEXCEPT {
%(c_ns)s_scalar_decode_long(s,bl.data(),bl.size()); return *this;
$(c_ns)_scalar_decode_long(s,bl.data(),bl.size()); return *this;
}

/**
@@ -151,35 +146,35 @@ public:
static inline decaf_error_t WARN_UNUSED decode (
Scalar &sc, const FixedBlock<SER_BYTES> buffer
) NOEXCEPT {
return %(c_ns)s_scalar_decode(sc.s,buffer.data());
return $(c_ns)_scalar_decode(sc.s,buffer.data());
}

/** Add. */
inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); %(c_ns)s_scalar_add(r.s,s,q.s); return r; }
inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_add(r.s,s,q.s); return r; }

/** Add to this. */
inline Scalar &operator+=(const Scalar &q) NOEXCEPT { %(c_ns)s_scalar_add(s,s,q.s); return *this; }
inline Scalar &operator+=(const Scalar &q) NOEXCEPT { $(c_ns)_scalar_add(s,s,q.s); return *this; }

/** Subtract. */
inline Scalar operator- (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); %(c_ns)s_scalar_sub(r.s,s,q.s); return r; }
inline Scalar operator- (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_sub(r.s,s,q.s); return r; }

/** Subtract from this. */
inline Scalar &operator-=(const Scalar &q) NOEXCEPT { %(c_ns)s_scalar_sub(s,s,q.s); return *this; }
inline Scalar &operator-=(const Scalar &q) NOEXCEPT { $(c_ns)_scalar_sub(s,s,q.s); return *this; }

/** Multiply */
inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); %(c_ns)s_scalar_mul(r.s,s,q.s); return r; }
inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_mul(r.s,s,q.s); return r; }

/** Multiply into this. */
inline Scalar &operator*=(const Scalar &q) NOEXCEPT { %(c_ns)s_scalar_mul(s,s,q.s); return *this; }
inline Scalar &operator*=(const Scalar &q) NOEXCEPT { $(c_ns)_scalar_mul(s,s,q.s); return *this; }

/** Negate */
inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); %(c_ns)s_scalar_sub(r.s,%(c_ns)s_scalar_zero,s); return r; }
inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_sub(r.s,$(c_ns)_scalar_zero,s); return r; }

/** Invert with Fermat's Little Theorem (slow!). If *this == 0,
* throw CryptoException. */
inline Scalar inverse() const throw(CryptoException) {
Scalar r;
if (DECAF_SUCCESS != %(c_ns)s_scalar_invert(r.s,s)) {
if (DECAF_SUCCESS != $(c_ns)_scalar_invert(r.s,s)) {
throw CryptoException();
}
return r;
@@ -189,7 +184,7 @@ public:
* and return DECAF_FAILURE. */
inline decaf_error_t WARN_UNUSED
inverse_noexcept(Scalar &r) const NOEXCEPT {
return %(c_ns)s_scalar_invert(r.s,s);
return $(c_ns)_scalar_invert(r.s,s);
}

/** Divide by inverting q. If q == 0, return 0. */
@@ -202,7 +197,7 @@ public:
inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); }

/** Compare in constant time */
inline bool operator==(const Scalar &q) const NOEXCEPT { return !!%(c_ns)s_scalar_eq(s,q.s); }
inline bool operator==(const Scalar &q) const NOEXCEPT { return !!$(c_ns)_scalar_eq(s,q.s); }

/** Scalarmul with scalar on left. */
inline Point operator* (const Point &q) const NOEXCEPT { return q * (*this); }
@@ -224,10 +219,10 @@ public:
class Point : public Serializable<Point> {
public:
/** wrapped C type */
typedef %(c_ns)s_point_t Wrapped;
typedef $(c_ns)_point_t Wrapped;
/** Size of a serialized element */
static const size_t SER_BYTES = %(C_NS)s_SER_BYTES;
static const size_t SER_BYTES = $(C_NS)_SER_BYTES;

/** Bytes required for hash */
static const size_t HASH_BYTES = SER_BYTES;
@@ -244,16 +239,16 @@ public:
/** @endcond */

/** Constructor sets to identity by default. */
inline Point(const Wrapped &q = %(c_ns)s_point_identity) NOEXCEPT { %(c_ns)s_point_copy(p,q); }
inline Point(const Wrapped &q = $(c_ns)_point_identity) NOEXCEPT { $(c_ns)_point_copy(p,q); }

/** Copy constructor. */
inline Point(const Point &q) NOEXCEPT { *this = q; }

/** Assignment. */
inline Point& operator=(const Point &q) NOEXCEPT { %(c_ns)s_point_copy(p,q.p); return *this; }
inline Point& operator=(const Point &q) NOEXCEPT { $(c_ns)_point_copy(p,q.p); return *this; }

/** Destructor securely zeorizes the point. */
inline ~Point() NOEXCEPT { %(c_ns)s_point_destroy(p); }
inline ~Point() NOEXCEPT { $(c_ns)_point_destroy(p); }

/** Construct from RNG */
inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT {
@@ -291,7 +286,7 @@ public:
static inline decaf_error_t WARN_UNUSED decode (
Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE
) NOEXCEPT {
return %(c_ns)s_point_decode(p.p,buffer.data(),allow_identity);
return $(c_ns)_point_decode(p.p,buffer.data(),allow_identity);
}

/**
@@ -314,15 +309,15 @@ public:
if (s.size() < HASH_BYTES) {
SecureBuffer b(HASH_BYTES);
memcpy(b.data(), s.data(), s.size());
%(c_ns)s_point_from_hash_nonuniform(p,b.data());
$(c_ns)_point_from_hash_nonuniform(p,b.data());
} else if (s.size() == HASH_BYTES) {
%(c_ns)s_point_from_hash_nonuniform(p,s.data());
$(c_ns)_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());
%(c_ns)s_point_from_hash_uniform(p,b.data());
$(c_ns)_point_from_hash_uniform(p,b.data());
} else {
%(c_ns)s_point_from_hash_uniform(p,s.data());
$(c_ns)_point_from_hash_uniform(p,s.data());
}
}

@@ -331,7 +326,7 @@ public:
*/
inline operator SecureBuffer() const {
SecureBuffer buffer(SER_BYTES);
%(c_ns)s_point_encode(buffer.data(), p);
$(c_ns)_point_encode(buffer.data(), p);
return buffer;
}

@@ -340,41 +335,41 @@ public:

/** Serializable instance */
inline void serialize_into(unsigned char *buffer) const NOEXCEPT {
%(c_ns)s_point_encode(buffer, p);
$(c_ns)_point_encode(buffer, p);
}

/** Point add. */
inline Point operator+ (const Point &q) const NOEXCEPT { Point r((NOINIT())); %(c_ns)s_point_add(r.p,p,q.p); return r; }
inline Point operator+ (const Point &q) const NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_add(r.p,p,q.p); return r; }

/** Point add. */
inline Point &operator+=(const Point &q) NOEXCEPT { %(c_ns)s_point_add(p,p,q.p); return *this; }
inline Point &operator+=(const Point &q) NOEXCEPT { $(c_ns)_point_add(p,p,q.p); return *this; }

/** Point subtract. */
inline Point operator- (const Point &q) const NOEXCEPT { Point r((NOINIT())); %(c_ns)s_point_sub(r.p,p,q.p); return r; }
inline Point operator- (const Point &q) const NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_sub(r.p,p,q.p); return r; }

/** Point subtract. */
inline Point &operator-=(const Point &q) NOEXCEPT { %(c_ns)s_point_sub(p,p,q.p); return *this; }
inline Point &operator-=(const Point &q) NOEXCEPT { $(c_ns)_point_sub(p,p,q.p); return *this; }

/** Point negate. */
inline Point operator- () const NOEXCEPT { Point r((NOINIT())); %(c_ns)s_point_negate(r.p,p); return r; }
inline Point operator- () const NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_negate(r.p,p); return r; }

/** Double the point out of place. */
inline Point times_two () const NOEXCEPT { Point r((NOINIT())); %(c_ns)s_point_double(r.p,p); return r; }
inline Point times_two () const NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_double(r.p,p); return r; }

/** Double the point in place. */
inline Point &double_in_place() NOEXCEPT { %(c_ns)s_point_double(p,p); return *this; }
inline Point &double_in_place() NOEXCEPT { $(c_ns)_point_double(p,p); return *this; }

/** Constant-time compare. */
inline bool operator!=(const Point &q) const NOEXCEPT { return ! %(c_ns)s_point_eq(p,q.p); }
inline bool operator!=(const Point &q) const NOEXCEPT { return ! $(c_ns)_point_eq(p,q.p); }

/** Constant-time compare. */
inline bool operator==(const Point &q) const NOEXCEPT { return !!%(c_ns)s_point_eq(p,q.p); }
inline bool operator==(const Point &q) const NOEXCEPT { return !!$(c_ns)_point_eq(p,q.p); }

/** Scalar multiply. */
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r((NOINIT())); %(c_ns)s_point_scalarmul(r.p,p,s.s); return r; }
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_scalarmul(r.p,p,s.s); return r; }

/** Scalar multiply in place. */
inline Point &operator*=(const Scalar &s) NOEXCEPT { %(c_ns)s_point_scalarmul(p,p,s.s); return *this; }
inline Point &operator*=(const Scalar &s) NOEXCEPT { $(c_ns)_point_scalarmul(p,p,s.s); return *this; }

/** Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); }
@@ -383,20 +378,20 @@ public:
inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); }

/** Validate / sanity check */
inline bool validate() const NOEXCEPT { return %(c_ns)s_point_valid(p); }
inline bool validate() const NOEXCEPT { return $(c_ns)_point_valid(p); }

/** 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())); %(c_ns)s_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
Point p((NOINIT())); $(c_ns)_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
}

/** 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 {
%(c_ns)s_point_dual_scalarmul(q1.p,q2.p,p,r1.s,r2.s);
$(c_ns)_point_dual_scalarmul(q1.p,q2.p,p,r1.s,r2.s);
}

/**
@@ -415,20 +410,20 @@ public:
* it doesn't).
*/
inline Point non_secret_combo_with_base(const Scalar &s, const Scalar &s_base) NOEXCEPT {
Point r((NOINIT())); %(c_ns)s_base_double_scalarmul_non_secret(r.p,s_base.s,p,s.s); return r;
Point r((NOINIT())); $(c_ns)_base_double_scalarmul_non_secret(r.p,s_base.s,p,s.s); return r;
}

/** Return a point equal to *this, whose internal data is rotated by a torsion element. */
inline Point debugging_torque() const NOEXCEPT {
Point q;
%(c_ns)s_point_debugging_torque(q.p,p);
$(c_ns)_point_debugging_torque(q.p,p);
return q;
}

/** 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;
%(c_ns)s_point_debugging_pscale(q.p,p,factor.data());
$(c_ns)_point_debugging_pscale(q.p,p,factor.data());
return q;
}

@@ -450,9 +445,9 @@ public:
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(%(c_ns)s_invert_elligator_uniform(buf2, p, hint));
ret = decaf_successful($(c_ns)_invert_elligator_uniform(buf2, p, hint));
} else {
ret = decaf_successful(%(c_ns)s_invert_elligator_nonuniform(buf2, p, hint));
ret = decaf_successful($(c_ns)_invert_elligator_nonuniform(buf2, p, hint));
}
if (buf.size() < HASH_BYTES) {
ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size());
@@ -477,10 +472,10 @@ public:
}

/** Return the base point */
static inline const Point base() NOEXCEPT { return Point(%(c_ns)s_point_base); }
static inline const Point base() NOEXCEPT { return Point($(c_ns)_point_base); }

/** Return the identity point */
static inline const Point identity() NOEXCEPT { return Point(%(c_ns)s_point_identity); }
static inline const Point identity() NOEXCEPT { return Point($(c_ns)_point_identity); }
};

/**
@@ -491,7 +486,7 @@ public:
*/

/** @cond internal */
typedef %(c_ns)s_precomputed_s Precomputed_U;
typedef $(c_ns)_precomputed_s Precomputed_U;
/** @endcond */
class Precomputed
/** @cond internal */
@@ -543,7 +538,7 @@ public:
*/
inline Precomputed &operator=(const Point &it) throw(std::bad_alloc) {
alloc();
%(c_ns)s_precompute(ours.mine,it.p);
$(c_ns)_precompute(ours.mine,it.p);
return *this;
}

@@ -560,7 +555,7 @@ public:
: OwnedOrUnowned<Precomputed,Precomputed_U>() { *this = it; }

/** Fixed base scalarmul. */
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; %(c_ns)s_precomputed_scalarmul(r.p,get(),s.s); return r; }
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; $(c_ns)_precomputed_scalarmul(r.p,get(),s.s); return r; }

/** Multiply by s.inverse(). If s=0, maps to the identity. */
inline Point operator/ (const Scalar &s) const throw(CryptoException) { return (*this) * s.inverse(); }
@@ -571,23 +566,23 @@ public:
public:
/** @cond internal */
friend class OwnedOrUnowned<Precomputed,Precomputed_U>;
static inline size_t size() NOEXCEPT { return %(c_ns)s_sizeof_precomputed_s; }
static inline size_t alignment() NOEXCEPT { return %(c_ns)s_alignof_precomputed_s; }
static inline const Precomputed_U * defaultValue() NOEXCEPT { return %(c_ns)s_precomputed_base; }
static inline size_t size() NOEXCEPT { return $(c_ns)_sizeof_precomputed_s; }
static inline size_t alignment() NOEXCEPT { return $(c_ns)_alignof_precomputed_s; }
static inline const Precomputed_U * defaultValue() NOEXCEPT { return $(c_ns)_precomputed_base; }
/** @endcond */
};

struct DhLadder {
public:
/** Bytes in an X%(gf_shortname)s public key. */
static const size_t PUBLIC_BYTES = X%(gf_shortname)s_PUBLIC_BYTES;
/** Bytes in an X$(gf_shortname) public key. */
static const size_t PUBLIC_BYTES = X$(gf_shortname)_PUBLIC_BYTES;

/** Bytes in an X%(gf_shortname)s private key. */
static const size_t PRIVATE_BYTES = X%(gf_shortname)s_PRIVATE_BYTES;
/** Bytes in an X$(gf_shortname) private key. */
static const size_t PRIVATE_BYTES = X$(gf_shortname)_PRIVATE_BYTES;

/** Base point for a scalar multiplication. */
static const FixedBlock<PUBLIC_BYTES> base_point() NOEXCEPT {
return FixedBlock<PUBLIC_BYTES>(%(c_ns)s_x_base_point);
return FixedBlock<PUBLIC_BYTES>($(c_ns)_x_base_point);
}

/** Generate and return a shared secret with public key. */
@@ -596,7 +591,7 @@ public:
const FixedBlock<PRIVATE_BYTES> &scalar
) throw(std::bad_alloc,CryptoException) {
SecureBuffer out(PUBLIC_BYTES);
if (DECAF_SUCCESS != %(c_ns)s_x_direct_scalarmul(out.data(), pk.data(), scalar.data())) {
if (DECAF_SUCCESS != $(c_ns)_x_direct_scalarmul(out.data(), pk.data(), scalar.data())) {
throw CryptoException();
}
return out;
@@ -609,7 +604,7 @@ public:
const FixedBlock<PUBLIC_BYTES> &pk,
const FixedBlock<PRIVATE_BYTES> &scalar
) NOEXCEPT {
return %(c_ns)s_x_direct_scalarmul(out.data(), pk.data(), scalar.data());
return $(c_ns)_x_direct_scalarmul(out.data(), pk.data(), scalar.data());
}

/** Generate and return a public key; equivalent to shared_secret(base_point(),scalar)
@@ -619,7 +614,7 @@ public:
const FixedBlock<PRIVATE_BYTES> &scalar
) throw(std::bad_alloc) {
SecureBuffer out(PUBLIC_BYTES);
%(c_ns)s_x_base_scalarmul(out.data(), scalar.data());
$(c_ns)_x_base_scalarmul(out.data(), scalar.data());
return out;
}

@@ -631,21 +626,21 @@ public:
FixedBuffer<PUBLIC_BYTES> &out,
const FixedBlock<PRIVATE_BYTES> &scalar
) NOEXCEPT {
%(c_ns)s_x_base_scalarmul(out.data(), scalar.data());
$(c_ns)_x_base_scalarmul(out.data(), scalar.data());
}
};

}; /* struct %(cxx_ns)s */
}; /* struct $(cxx_ns) */

/** @cond internal */
inline SecureBuffer %(cxx_ns)s::Scalar::direct_scalarmul (
inline SecureBuffer $(cxx_ns)::Scalar::direct_scalarmul (
const Block &in,
decaf_bool_t allow_identity,
decaf_bool_t short_circuit
) const throw(CryptoException) {
SecureBuffer out(%(cxx_ns)s::Point::SER_BYTES);
SecureBuffer out($(cxx_ns)::Point::SER_BYTES);
if (DECAF_SUCCESS !=
%(c_ns)s_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit)
$(c_ns)_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit)
) {
throw CryptoException();
}
@@ -655,6 +650,3 @@ inline SecureBuffer %(cxx_ns)s::Scalar::direct_scalarmul (

#undef NOEXCEPT
} /* namespace decaf */
"""
)


+ 18
- 0
src/public_include/decaf.tmpl.h View File

@@ -0,0 +1,18 @@
/**
* Master header for Decaf library.
*
* The Decaf library implements cryptographic operations on a elliptic curve
* groups of prime order p. It accomplishes this by using a twisted Edwards
* curve (isogenous to Ed448-Goldilocks or Ed25519) and wiping out the cofactor.
*
* The formulas are all complete and have no special cases. However, some
* functions can fail. For example, decoding functions can fail because not
* every string is the encoding of a valid group element.
*
* The formulas contain no data-dependent branches, timing or memory accesses,
* except for decaf_XXX_base_double_scalarmul_non_secret.
*/

$("\n".join([
"#include <decaf/decaf_%s.h>" % g for g in sorted([c["bits"] for _,c in curve.iteritems()])
]))

+ 16
- 0
src/public_include/decaf.tmpl.hxx View File

@@ -0,0 +1,16 @@
/** Master header for Decaf library, C++ version. */

$("\n".join([
"#include <decaf/decaf_%s.hxx>" % g for g in sorted([c["bits"] for _,c in curve.iteritems()])
]))

namespace decaf {
template <template<typename Group> class Run>
void run_for_all_curves() {
$("\n".join([
" Run<%s>::run();" % cd["cxx_ns"]
for cd in sorted(curve.values(), key=lambda x:x["c_ns"])
])
)
}
}

+ 10
- 0
src/public_include/decaf/crypto.tmpl.h View File

@@ -0,0 +1,10 @@
/**
* Example Decaf crypto routines, metaheader.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
*/

$("\n".join([
"#include <decaf/crypto_%s.h>" % g for g in sorted([c["bits"] for _,c in curve.iteritems()])
]))

+ 10
- 0
src/public_include/decaf/crypto.tmpl.hxx View File

@@ -0,0 +1,10 @@
/**
* Example Decaf crypto routines, C++ metaheader.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
*/

$("\n".join([
"#include <decaf/crypto_%s.hxx>" % g for g in sorted([c["bits"] for _,c in curve.iteritems()])
]))

Loading…
Cancel
Save