Commit 64adbd10 authored by Michael Hamburg's avatar Michael Hamburg

split c crypto routines for now (a bit of a hack :-/)

parent 27f1b4f6
......@@ -88,7 +88,7 @@ HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp
HEADERSXX = $(HEADERS) $(shell find . -name "*.hxx")
# components needed by the lib
LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/decaf_crypto.o # and per-field components
LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/decaf_crypto_255.o $(BUILD_OBJ)/decaf_crypto_448.o # and per-field components
BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o
......
/**
* @cond internal
* @file decaf_crypto.c
* @file decaf_crypto_255.c
* @copyright
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief Example Decaf cyrpto routines.
* @brief Example Decaf crypto routines, 255-bit version.
*/
#include <decaf/crypto.h>
#include <decaf/crypto_255.h>
#include <string.h>
static const unsigned int DECAF_255_SCALAR_OVERKILL_BYTES = DECAF_255_SCALAR_BYTES + 8;
......
/**
* @cond internal
* @file decaf_crypto_448.c
* @copyright
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief Example Decaf crypto routines, 448-bit version
* @todo TODO don't copy-paste.
*/
#include <decaf/crypto_448.h>
#include <string.h>
static const unsigned int DECAF_448_SCALAR_OVERKILL_BYTES = DECAF_448_SCALAR_BYTES + 8;
void decaf_448_derive_private_key (
decaf_448_private_key_t priv,
const decaf_448_symmetric_key_t proto
) {
const char *magic = "decaf::derive_448_private_key"; /* TODO: canonicalize and freeze */
uint8_t encoded_scalar[DECAF_448_SCALAR_OVERKILL_BYTES];
decaf_448_point_t pub;
keccak_strobe_t strobe;
strobe_init(strobe, &STROBE_256, magic, 0);
strobe_key(strobe, proto, sizeof(decaf_448_symmetric_key_t));
strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar));
strobe_destroy(strobe);
memcpy(priv->sym, proto, sizeof(decaf_448_symmetric_key_t));
decaf_448_scalar_decode_long(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar));
decaf_448_precomputed_scalarmul(pub, decaf_448_precomputed_base, priv->secret_scalar);
decaf_448_point_encode(priv->pub, pub);
decaf_bzero(encoded_scalar, sizeof(encoded_scalar));
}
void
decaf_448_destroy_private_key (
decaf_448_private_key_t priv
) {
decaf_bzero((void*)priv, sizeof(decaf_448_private_key_t));
}
void decaf_448_private_to_public (
decaf_448_public_key_t pub,
const decaf_448_private_key_t priv
) {
memcpy(pub, priv->pub, sizeof(decaf_448_public_key_t));
}
static const uint16_t SHARED_SECRET_MAX_BLOCK_SIZE = 1<<12; /* TODO: standardize and freeze */
decaf_error_t
decaf_448_shared_secret (
uint8_t *shared,
size_t shared_bytes,
const decaf_448_private_key_t my_privkey,
const decaf_448_public_key_t your_pubkey,
int me_first
) {
const char *magic = "decaf::decaf_448_shared_secret"; /* TODO: canonicalize and freeze */
keccak_strobe_t strobe;
strobe_init(strobe, &STROBE_256, magic, 0);
uint8_t ss_ser[DECAF_448_SER_BYTES];
if (me_first) {
strobe_ad(strobe,my_privkey->pub,sizeof(decaf_448_public_key_t));
strobe_ad(strobe,your_pubkey,sizeof(decaf_448_public_key_t));
} else {
strobe_ad(strobe,your_pubkey,sizeof(decaf_448_public_key_t));
strobe_ad(strobe,my_privkey->pub,sizeof(decaf_448_public_key_t));
}
decaf_error_t ret = decaf_448_direct_scalarmul(
ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, DECAF_TRUE
);
strobe_transact(strobe,NULL,ss_ser,sizeof(ss_ser),STROBE_CW_DH_KEY);
while (shared_bytes) {
uint16_t cando = (shared_bytes > SHARED_SECRET_MAX_BLOCK_SIZE)
? SHARED_SECRET_MAX_BLOCK_SIZE : shared_bytes;
strobe_prng(strobe,shared,cando);
shared_bytes -= cando;
shared += cando;
}
strobe_destroy(strobe);
decaf_bzero(ss_ser, sizeof(ss_ser));
return ret;
}
void
decaf_448_sign_strobe (
keccak_strobe_t strobe,
decaf_448_signature_t sig,
const decaf_448_private_key_t priv
) {
uint8_t overkill[DECAF_448_SCALAR_OVERKILL_BYTES];
decaf_448_point_t point;
decaf_448_scalar_t nonce, challenge;
/* Stir pubkey */
strobe_transact(strobe,NULL,priv->pub,sizeof(decaf_448_public_key_t),STROBE_CW_SIG_PK);
/* Derive nonce */
keccak_strobe_t strobe2;
memcpy(strobe2,strobe,sizeof(strobe2));
strobe_key(strobe2,priv->sym,sizeof(decaf_448_symmetric_key_t));
strobe_prng(strobe2,overkill,sizeof(overkill));
strobe_destroy(strobe2);
decaf_448_scalar_decode_long(nonce, overkill, sizeof(overkill));
decaf_448_precomputed_scalarmul(point, decaf_448_precomputed_base, nonce);
decaf_448_point_encode(sig, point);
/* Derive challenge */
strobe_transact(strobe,NULL,sig,DECAF_448_SER_BYTES,STROBE_CW_SIG_EPH);
strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
decaf_448_scalar_decode_long(challenge, overkill, sizeof(overkill));
/* Respond */
decaf_448_scalar_mul(challenge, challenge, priv->secret_scalar);
decaf_448_scalar_sub(nonce, nonce, challenge);
/* Save results */
decaf_448_scalar_encode(overkill, nonce);
strobe_transact(strobe,&sig[DECAF_448_SER_BYTES],overkill,DECAF_448_SCALAR_BYTES,STROBE_CW_SIG_RESP);
/* Clean up */
decaf_448_scalar_destroy(nonce);
decaf_448_scalar_destroy(challenge);
decaf_bzero(overkill,sizeof(overkill));
}
decaf_error_t
decaf_448_verify_strobe (
keccak_strobe_t strobe,
const decaf_448_signature_t sig,
const decaf_448_public_key_t pub
) {
decaf_bool_t ret;
uint8_t overkill[DECAF_448_SCALAR_OVERKILL_BYTES];
decaf_448_point_t point, pubpoint;
decaf_448_scalar_t challenge, response;
/* Stir pubkey */
strobe_transact(strobe,NULL,pub,sizeof(decaf_448_public_key_t),STROBE_CW_SIG_PK);
/* Derive nonce */
strobe_transact(strobe,NULL,sig,DECAF_448_SER_BYTES,STROBE_CW_SIG_EPH);
ret = decaf_successful( decaf_448_point_decode(point, sig, DECAF_TRUE) );
/* Derive challenge */
strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
decaf_448_scalar_decode_long(challenge, overkill, sizeof(overkill));
/* Decode response */
strobe_transact(strobe,overkill,&sig[DECAF_448_SER_BYTES],DECAF_448_SCALAR_BYTES,STROBE_CW_SIG_RESP);
ret &= decaf_successful( decaf_448_scalar_decode(response, overkill) );
ret &= decaf_successful( decaf_448_point_decode(pubpoint, pub, DECAF_FALSE) );
decaf_448_base_double_scalarmul_non_secret (
pubpoint, response, pubpoint, challenge
);
ret &= decaf_448_point_eq(pubpoint, point);
/* Nothing here is secret, so don't do these things:
decaf_bzero(overkill,sizeof(overkill));
decaf_448_point_destroy(point);
decaf_448_point_destroy(pubpoint);
decaf_448_scalar_destroy(challenge);
decaf_448_scalar_destroy(response);
*/
return decaf_succeed_if(ret);
}
void
decaf_448_sign (
decaf_448_signature_t sig,
const decaf_448_private_key_t priv,
const unsigned char *message,
size_t message_len
) {
keccak_strobe_t ctx;
strobe_init(ctx,&STROBE_256,"decaf::decaf_448_sign",0); /* TODO: canonicalize and freeze */
strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
decaf_448_sign_strobe(ctx, sig, priv);
strobe_destroy(ctx);
}
decaf_error_t
decaf_448_verify (
const decaf_448_signature_t sig,
const decaf_448_public_key_t pub,
const unsigned char *message,
size_t message_len
) {
keccak_strobe_t ctx;
strobe_init(ctx,&STROBE_256,"decaf::decaf_448_sign",0); /* TODO: canonicalize and freeze */
strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
decaf_error_t ret = decaf_448_verify_strobe(ctx, sig, pub);
strobe_destroy(ctx);
return ret;
}
......@@ -6,7 +6,8 @@
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* @brief Example cryptography using Decaf
* @brief Example cryptography using Decaf.
* @warning FIXME: this is out of sync with crypto_*.h
*/
#ifndef __DECAF_CRYPTO_HXX__
#define __DECAF_CRYPTO_HXX__ 1
......
/**
* @file decaf/crypto.h
* @file decaf/crypto_255.h
* @copyright
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
......@@ -11,10 +11,10 @@
* @warning Experimental! The names, parameter orders etc are likely to change.
*/
#ifndef __DECAF_CRYPTO_H__
#define __DECAF_CRYPTO_H__ 1
#ifndef __DECAF_CRYPTO_255_H__
#define __DECAF_CRYPTO_255_H__ 1
#include <decaf.h>
#include <decaf/decaf_255.h>
#include <decaf/shake.h>
/** Number of bytes for a symmetric key (expanded to full key) */
......@@ -188,6 +188,6 @@ decaf_255_verify (
} /* extern "C" */
#endif
#endif /* __DECAF_CRYPTO_H__ */
#endif /* __DECAF_CRYPTO_255_H__ */
/**
* @file decaf/crypto_448.h
* @copyright
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief Example Decaf cyrpto 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.
*/
#ifndef __DECAF_CRYPTO_448_H__
#define __DECAF_CRYPTO_448_H__ 1
#include <decaf/decaf_448.h>
#include <decaf/shake.h>
/** Number of bytes for a symmetric key (expanded to full key) */
#define DECAF_448_SYMMETRIC_KEY_BYTES 32
/** @cond internal */
#define API_VIS __attribute__((visibility("default"))) __attribute__((noinline)) // TODO: synergize with decaf.h
#define WARN_UNUSED __attribute__((warn_unused_result))
#define NONNULL1 __attribute__((nonnull(1)))
#define NONNULL2 __attribute__((nonnull(1,2)))
#define NONNULL3 __attribute__((nonnull(1,2,3)))
#define NONNULL134 __attribute__((nonnull(1,3,4)))
#define NONNULL5 __attribute__((nonnull(1,2,3,4,5)))
/** @endcond */
/** A symmetric key, the compressed point of a private key. */
typedef unsigned char decaf_448_symmetric_key_t[DECAF_448_SYMMETRIC_KEY_BYTES];
/** An encoded public key. */
typedef unsigned char decaf_448_public_key_t[DECAF_448_SER_BYTES];
/** A signature. */
typedef unsigned char decaf_448_signature_t[DECAF_448_SER_BYTES + DECAF_448_SCALAR_BYTES];
typedef struct {
/** @cond intetrnal */
/** The symmetric key from which everything is expanded */
decaf_448_symmetric_key_t sym;
/** The scalar x */
decaf_448_scalar_t secret_scalar;
/** x*Base */
decaf_448_public_key_t pub;
/** @endcond */
} /** Private key structure for pointers. */
decaf_448_private_key_s,
/** A private key (gmp array[1] style). */
decaf_448_private_key_t[1];
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 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 decaf_448_derive_private_key (
decaf_448_private_key_t priv,
const decaf_448_symmetric_key_t proto
) NONNULL2 API_VIS;
/**
* @brief Destroy a private key.
*/
void decaf_448_destroy_private_key (
decaf_448_private_key_t priv
) NONNULL1 API_VIS;
/**
* @brief Convert a private key to a public one.
* @param [out] pub The extracted private key.
* @param [in] priv The private key.
*/
void decaf_448_private_to_public (
decaf_448_public_key_t pub,
const decaf_448_private_key_t priv
) NONNULL2 API_VIS;
/**
* @brief Compute a Diffie-Hellman shared secret.
*
* This is an example routine; real protocols would use something
* protocol-specific.
*
* @param [out] shared A buffer to store the shared secret.
* @param [in] shared_bytes The size of the buffer.
* @param [in] my_privkey My private key.
* @param [in] your_pubkey Your public key.
* @param [in] me_first Direction flag to break symmetry.
*
* @retval DECAF_SUCCESS Key exchange was successful.
* @retval DECAF_FAILURE Key exchange failed.
*/
decaf_error_t
decaf_448_shared_secret (
uint8_t *shared,
size_t shared_bytes,
const decaf_448_private_key_t my_privkey,
const decaf_448_public_key_t your_pubkey,
int me_first
) NONNULL134 WARN_UNUSED API_VIS;
/**
* @brief Sign a message from a STROBE context.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] strobe A STROBE context with the message.
*/
void
decaf_448_sign_strobe (
keccak_strobe_t strobe,
decaf_448_signature_t sig,
const decaf_448_private_key_t priv
) NONNULL3 API_VIS;
/**
* @brief Sign a message.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*/
void
decaf_448_sign (
decaf_448_signature_t sig,
const decaf_448_private_key_t priv,
const unsigned char *message,
size_t message_len
) NONNULL3 API_VIS;
/**
* @brief Verify a signed message from its STROBE context.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] strobe A STROBE context with the message.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
decaf_448_verify_strobe (
keccak_strobe_t strobe,
const decaf_448_signature_t sig,
const decaf_448_public_key_t pub
) NONNULL3 API_VIS WARN_UNUSED;
/**
* @brief Verify a signed message.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
decaf_448_verify (
const decaf_448_signature_t sig,
const decaf_448_public_key_t pub,
const unsigned char *message,
size_t message_len
) NONNULL3 API_VIS WARN_UNUSED;
#undef API_VIS
#undef WARN_UNUSED
#undef NONNULL1
#undef NONNULL2
#undef NONNULL3
#undef NONNULL134
#undef NONNULL5
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __DECAF_CRYPTO_448_H__ */
......@@ -583,7 +583,7 @@ void strobe_transact (
uint32_t len = sponge->params->rate - sponge->params->position;
if (len < STROBE_FORGET_BYTES + len_cw) len += sponge->params->rate;
len -= len_cw;
len -= len_cw; /* HACK */
if (cw_flags & STROBE_FLAG_NO_LENGTH) len = 2*STROBE_FORGET_BYTES;
......
......@@ -11,7 +11,8 @@
#include <decaf.hxx>
#include <decaf/shake.hxx>
#include <decaf/crypto.h>
#include <decaf/crypto_255.h>
#include <decaf/crypto_448.h>
#include <decaf/crypto.hxx>
#include <stdio.h>
#include <sys/time.h>
......@@ -374,13 +375,8 @@ int main(int argc, char **argv) {
bool micro = false;
if (argc >= 2 && !strcmp(argv[1], "--micro"))
micro = true;
decaf_255_public_key_t p1,p2;
decaf_255_private_key_t s1,s2;
decaf_255_symmetric_key_t r1,r2;
decaf_255_signature_t sig1;
unsigned char ss[32];
memset(r1,1,sizeof(r1));
memset(r2,2,sizeof(r2));
......@@ -421,32 +417,72 @@ int main(int argc, char **argv) {
Benches<Ed448Goldilocks>::micro();
}
/* TODO: 255->448 */
printf("\nMacro-benchmarks:\n");
for (Benchmark b("Keygen"); b.iter(); ) {
decaf_255_derive_private_key(s1,r1);
}
{
decaf_255_public_key_t p1,p2;
decaf_255_private_key_t s1,s2;
decaf_255_signature_t sig1;
unsigned char ss[32];
printf("\nMacro-benchmarks for IsoEd25519:\n");
for (Benchmark b("Keygen"); b.iter(); ) {
decaf_255_derive_private_key(s1,r1);
}
decaf_255_private_to_public(p1,s1);
decaf_255_derive_private_key(s2,r2);
decaf_255_private_to_public(p2,s2);
decaf_255_private_to_public(p1,s1);
decaf_255_derive_private_key(s2,r2);
decaf_255_private_to_public(p2,s2);
for (Benchmark b("Shared secret"); b.iter(); ) {
decaf_bool_t ret = decaf_255_shared_secret(ss,sizeof(ss),s1,p2,1);
ignore_result(ret);
assert(ret);
}
for (Benchmark b("Shared secret"); b.iter(); ) {
decaf_bool_t ret = decaf_255_shared_secret(ss,sizeof(ss),s1,p2,1);
ignore_result(ret);
assert(ret);
}
for (Benchmark b("Sign"); b.iter(); ) {
decaf_255_sign(sig1,s1,umessage,lmessage);
}
for (Benchmark b("Sign"); b.iter(); ) {
decaf_255_sign(sig1,s1,umessage,lmessage);
for (Benchmark b("Verify"); b.iter(); ) {
decaf_bool_t ret = decaf_255_verify(sig1,p1,umessage,lmessage);
rng.read(Buffer(umessage,lmessage));
// umessage[0]++;
// umessage[1]^=umessage[0];
ignore_result(ret);
}
}
{
decaf_448_public_key_t p1,p2;
decaf_448_private_key_t s1,s2;
decaf_448_signature_t sig1;
unsigned char ss[32];
printf("\nMacro-benchmarks for Ed448-Goldilocks:\n");
for (Benchmark b("Keygen"); b.iter(); ) {
decaf_448_derive_private_key(s1,r1);
}
for (Benchmark b("Verify"); b.iter(); ) {
decaf_bool_t ret = decaf_255_verify(sig1,p1,umessage,lmessage);
rng.read(Buffer(umessage,lmessage));
// umessage[0]++;
// umessage[1]^=umessage[0];
ignore_result(ret);
decaf_448_private_to_public(p1,s1);
decaf_448_derive_private_key(s2,r2);
decaf_448_private_to_public(p2,s2);
for (Benchmark b("Shared secret"); b.iter(); ) {
decaf_bool_t ret = decaf_448_shared_secret(ss,sizeof(ss),s1,p2,1);
ignore_result(ret);
assert(ret);
}
for (Benchmark b("Sign"); b.iter(); ) {
decaf_448_sign(sig1,s1,umessage,lmessage);
}
for (Benchmark b("Verify"); b.iter(); ) {
decaf_bool_t ret = decaf_448_verify(sig1,p1,umessage,lmessage);
rng.read(Buffer(umessage,lmessage));
// umessage[0]++;
// umessage[1]^=umessage[0];
ignore_result(ret);
}
}
Benches<IsoEd25519>::macro();
......
......@@ -11,7 +11,8 @@
#include <decaf.hxx>
#include <decaf/shake.hxx>
#include <decaf/crypto.h>
#include <decaf/crypto_255.h>
#include <decaf/crypto_448.h>
#include <decaf/crypto.hxx>
#include <stdio.h>
......@@ -341,8 +342,7 @@ static void test_crypto() {
}; // template<GroupId GROUP>
// TODO cross-field
static void test_decaf() {
static void test_decaf_255() {
Test test("Sample crypto");
SpongeRng rng(Block("test_decaf"));
......@@ -376,6 +376,41 @@ static void test_decaf() {
}
}
/* TODO: don't copy-paste */
static void test_decaf_448() {
Test test("Sample crypto");
SpongeRng rng(Block("test_decaf"));
decaf_448_symmetric_key_t proto1,proto2;
decaf_448_private_key_t s1,s2;
decaf_448_public_key_t p1,p2;
decaf_448_signature_t sig;
unsigned char shared1[1234],shared2[1234];
const char *message = "Hello, world!";
for (int i=0; i<NTESTS && test.passing_now; i++) {
rng.read(Buffer(proto1,sizeof(proto1)));
rng.read(Buffer(proto2,sizeof(proto2)));
decaf_448_derive_private_key(s1,proto1);
decaf_448_private_to_public(p1,s1);
decaf_448_derive_private_key(s2,proto2);
decaf_448_private_to_public(p2,s2);
if (DECAF_SUCCESS != decaf_448_shared_secret (shared1,sizeof(shared1),s1,p2,0)) {
test.fail(); printf("Fail ss12\n");
}
if (DECAF_SUCCESS != decaf_448_shared_secret (shared2,sizeof(shared2),s2,p1,1)) {
test.fail(); printf("Fail ss21\n");
}
if (memcmp(shared1,shared2,sizeof(shared1))) {
test.fail(); printf("Fail ss21 == ss12\n");
}
decaf_448_sign (sig,s1,(const unsigned char *)message,strlen(message));
if (DECAF_SUCCESS != decaf_448_verify (sig,p1,(const unsigned char *)message,strlen(message))) {
test.fail(); printf("Fail sig ver\n");
}
}
}
int main(int argc, char **argv) {
(void) argc; (void) argv;
......@@ -384,7 +419,7 @@ int main(int argc, char **argv) {
Tests<IsoEd25519>::test_elligator();
Tests<IsoEd25519>::test_ec();
Tests<IsoEd25519>::test_crypto();
test_decaf();
test_decaf_255();
printf("\n");
printf("Testing %s:\n", Ed448Goldilocks::name());
......@@ -392,6 +427,7 @@ int main(int argc, char **argv) {
Tests<Ed448Goldilocks>::test_elligator();
Tests<Ed448Goldilocks>::test_ec();
Tests<Ed448Goldilocks>::test_crypto();
test_decaf_448();
if (passing) printf("Passed all tests.\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment