| @@ -1,3 +1,11 @@ | |||||
| April 22, 2017: | |||||
| Remove STROBE in preparation for 1.0 release. STROBE has its own | |||||
| repo now at https://strobe.sourceforge.io. I might re-integrate | |||||
| it into Decaf once I have produced a version that matches the | |||||
| STROBE v1 spec, but it's just confusing to keep v0.2 in here. | |||||
| Change x{25519,448}_generate_key to _derive_public_key. | |||||
| January 15, 2016: | January 15, 2016: | ||||
| Lots of changes since the last entry in HISTORY.TXT. | Lots of changes since the last entry in HISTORY.TXT. | ||||
| @@ -1,4 +1,4 @@ | |||||
| # Copyright (c) 2014 Cryptography Research, Inc. | |||||
| # Copyright (c) 2014-2017 Cryptography Research, Inc. | |||||
| # Released under the MIT License. See LICENSE.txt for license information. | # Released under the MIT License. See LICENSE.txt for license information. | ||||
| @@ -77,9 +77,9 @@ GEN_CODE= $(GEN_CODE_1:%.tmpl.hxx=%.hxx) | |||||
| HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp $(GEN_CODE) | HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp $(GEN_CODE) | ||||
| # components needed by the lib | # components needed by the lib | ||||
| LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/strobe.o $(BUILD_OBJ)/sha512.o # and per-field components | |||||
| LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/sha512.o $(BUILD_OBJ)/spongerng.o # and per-field components | |||||
| BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/strobe.o | |||||
| BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o | |||||
| all: lib $(BUILD_IBIN)/test $(BUILD_IBIN)/bench $(BUILD_BIN)/shakesum | all: lib $(BUILD_IBIN)/test $(BUILD_IBIN)/bench $(BUILD_BIN)/shakesum | ||||
| @@ -174,10 +174,9 @@ endef | |||||
| define define_curve | define define_curve | ||||
| LIBCOMPONENTS += $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/elligator.o $$(BUILD_OBJ)/$(1)/scalar.o \ | LIBCOMPONENTS += $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/elligator.o $$(BUILD_OBJ)/$(1)/scalar.o \ | ||||
| $$(BUILD_OBJ)/$(1)/crypto.o $$(BUILD_OBJ)/$(1)/eddsa.o $$(BUILD_OBJ)/$(1)/decaf_tables.o | |||||
| $$(BUILD_OBJ)/$(1)/eddsa.o $$(BUILD_OBJ)/$(1)/decaf_tables.o | |||||
| PER_OBJ_DIRS += $$(BUILD_OBJ)/$(1) | PER_OBJ_DIRS += $$(BUILD_OBJ)/$(1) | ||||
| GLOBAL_HEADERS_OF_$(1) = $(BUILD_INC)/decaf/point_$(3).h $(BUILD_INC)/decaf/point_$(3).hxx \ | GLOBAL_HEADERS_OF_$(1) = $(BUILD_INC)/decaf/point_$(3).h $(BUILD_INC)/decaf/point_$(3).hxx \ | ||||
| $(BUILD_C)/decaf/crypto_$(3).h $(BUILD_C)/decaf/crypto_$(3).hxx \ | |||||
| $(BUILD_INC)/decaf/ed$(3).h $(BUILD_INC)/decaf/ed$(3).hxx | $(BUILD_INC)/decaf/ed$(3).h $(BUILD_INC)/decaf/ed$(3).hxx | ||||
| HEADERS_OF_$(1) = $$(HEADERS_OF_$(2)) $$(GLOBAL_HEADERS_OF_$(1)) | HEADERS_OF_$(1) = $$(HEADERS_OF_$(2)) $$(GLOBAL_HEADERS_OF_$(1)) | ||||
| HEADERS += $$(GLOBAL_HEADERS_OF_$(1)) | HEADERS += $$(GLOBAL_HEADERS_OF_$(1)) | ||||
| @@ -199,9 +198,6 @@ $$(BUILD_INC)/decaf/elligator_$(3).%: src/per_curve/elligator.tmpl.% src/generat | |||||
| $$(BUILD_INC)/decaf/scalar_$(3).%: src/per_curve/scalar.tmpl.% src/generator/* Makefile | $$(BUILD_INC)/decaf/scalar_$(3).%: src/per_curve/scalar.tmpl.% src/generator/* Makefile | ||||
| python -B src/generator/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$< | python -B src/generator/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$< | ||||
| $$(BUILD_C)/decaf/crypto_$(3).%: src/per_curve/crypto.tmpl.% src/generator/* Makefile | |||||
| python -B src/generator/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$< | |||||
| $$(BUILD_IBIN)/decaf_gen_tables_$(1): $$(BUILD_OBJ)/$(1)/decaf_gen_tables.o \ | $$(BUILD_IBIN)/decaf_gen_tables_$(1): $$(BUILD_OBJ)/$(1)/decaf_gen_tables.o \ | ||||
| $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/scalar.o $$(BUILD_OBJ)/utils.o \ | $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/scalar.o $$(BUILD_OBJ)/utils.o \ | ||||
| @@ -60,19 +60,6 @@ The Decaf library doesn't implement much symmetric crypto, but it does | |||||
| contain the hash functions required by the CFRG cryptosystems: SHA512, | contain the hash functions required by the CFRG cryptosystems: SHA512, | ||||
| SHA-3 and SHAKE. | SHA-3 and SHAKE. | ||||
| The library also includes some work on an experimental protocol framework | |||||
| called STROBE (based on Markku-Juhani Saarinen's BLINKER). This | |||||
| framework is incomplete and will change in the future! There's also a | |||||
| significant chance that it's insecure in its current form. Therefore, | |||||
| all the STROBE interfaces have been marked as TOY for this version. | |||||
| Please don't use them for anything serious. | |||||
| The Decaf library contains a random number generator, SpongeRNG, which | |||||
| uses STROBE internally. This is used in the test suite to generate | |||||
| random tests. It's probably secure, but since STROBE is not final, | |||||
| its internals will almost certainly change. I recommend using your own | |||||
| RNG instead for now. For example, consider libottery. | |||||
| ## Internals | ## Internals | ||||
| The "decaf" technique is described in https://eprint.iacr.org/2015/673 | The "decaf" technique is described in https://eprint.iacr.org/2015/673 | ||||
| @@ -1,231 +0,0 @@ | |||||
| /** | |||||
| * @file curve25519/crypto.c | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * @cond internal | |||||
| * @brief Example Decaf crypto routines | |||||
| * | |||||
| * @warning This file was automatically generated in Python. | |||||
| * Please do not edit it. | |||||
| */ | |||||
| #include <decaf/crypto.h> | |||||
| #include <string.h> | |||||
| #define API_NAME "decaf_255" | |||||
| #define API_NS(_id) decaf_255_##_id | |||||
| #define API_NS_TOY(_id) decaf_255_TOY_##_id | |||||
| #define SCALAR_BITS DECAF_255_SCALAR_BITS | |||||
| #define SCALAR_BYTES ((SCALAR_BITS + 7)/8) | |||||
| #define SER_BYTES DECAF_255_SER_BYTES | |||||
| /* TODO: canonicalize and freeze the STROBE constants in this file | |||||
| * (and STROBE itself for that matter) | |||||
| */ | |||||
| static const char *DERIVE_MAGIC = API_NAME"::derive_private_key"; | |||||
| static const char *SIGN_MAGIC = API_NAME"::sign"; | |||||
| static const char *SHARED_SECRET_MAGIC = API_NAME"::shared_secret"; | |||||
| static const uint16_t SHARED_SECRET_MAX_BLOCK_SIZE = 1<<12; | |||||
| static const unsigned int SCALAR_OVERKILL_BYTES = SCALAR_BYTES + 8; | |||||
| void API_NS_TOY(derive_private_key) ( | |||||
| API_NS_TOY(private_key_t) priv, | |||||
| const API_NS_TOY(symmetric_key_t) proto | |||||
| ) { | |||||
| uint8_t encoded_scalar[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) pub; | |||||
| keccak_decaf_TOY_strobe_t strobe; | |||||
| decaf_TOY_strobe_init(strobe, &STROBE_256, DERIVE_MAGIC, 0); | |||||
| decaf_TOY_strobe_fixed_key(strobe, proto, sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| decaf_TOY_strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar)); | |||||
| decaf_TOY_strobe_destroy(strobe); | |||||
| memcpy(priv->sym, proto, sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| API_NS(scalar_decode_long)(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar)); | |||||
| API_NS(precomputed_scalarmul)(pub, API_NS(precomputed_base), priv->secret_scalar); | |||||
| API_NS(point_encode)(priv->pub, pub); | |||||
| decaf_bzero(encoded_scalar, sizeof(encoded_scalar)); | |||||
| } | |||||
| void API_NS_TOY(destroy_private_key) ( | |||||
| API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| decaf_bzero((void*)priv, sizeof(API_NS_TOY(private_key_t))); | |||||
| } | |||||
| void API_NS_TOY(private_to_public) ( | |||||
| API_NS_TOY(public_key_t) pub, | |||||
| const API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| memcpy(pub, priv->pub, sizeof(API_NS_TOY(public_key_t))); | |||||
| } | |||||
| /* Performance vs consttime tuning. | |||||
| * Specifying true here might give better DOS resistance in certain corner | |||||
| * cases. Specifying false gives a tighter result in test_ct. | |||||
| */ | |||||
| #ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
| #define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE | |||||
| #endif | |||||
| decaf_error_t API_NS_TOY(shared_secret) ( | |||||
| uint8_t *shared, | |||||
| size_t shared_bytes, | |||||
| const API_NS_TOY(private_key_t) my_privkey, | |||||
| const API_NS_TOY(public_key_t) your_pubkey, | |||||
| int me_first | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t strobe; | |||||
| decaf_TOY_strobe_init(strobe, &STROBE_256, SHARED_SECRET_MAGIC, 0); | |||||
| uint8_t ss_ser[SER_BYTES]; | |||||
| if (me_first) { | |||||
| decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t))); | |||||
| decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t))); | |||||
| } else { | |||||
| decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t))); | |||||
| decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t))); | |||||
| } | |||||
| decaf_error_t ret = API_NS(direct_scalarmul)( | |||||
| ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, | |||||
| DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
| ); | |||||
| decaf_TOY_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; | |||||
| decaf_TOY_strobe_prng(strobe,shared,cando); | |||||
| shared_bytes -= cando; | |||||
| shared += cando; | |||||
| } | |||||
| decaf_TOY_strobe_destroy(strobe); | |||||
| decaf_bzero(ss_ser, sizeof(ss_ser)); | |||||
| return ret; | |||||
| } | |||||
| void API_NS_TOY(sign_strobe) ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| uint8_t overkill[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) point; | |||||
| API_NS(scalar_t) nonce, challenge; | |||||
| /* Stir pubkey */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,priv->pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK); | |||||
| /* Derive nonce */ | |||||
| keccak_decaf_TOY_strobe_t strobe2; | |||||
| memcpy(strobe2,strobe,sizeof(strobe2)); | |||||
| decaf_TOY_strobe_fixed_key(strobe2,priv->sym,sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| decaf_TOY_strobe_prng(strobe2,overkill,sizeof(overkill)); | |||||
| decaf_TOY_strobe_destroy(strobe2); | |||||
| API_NS(scalar_decode_long)(nonce, overkill, sizeof(overkill)); | |||||
| API_NS(precomputed_scalarmul)(point, API_NS(precomputed_base), nonce); | |||||
| API_NS(point_encode)(sig, point); | |||||
| /* Derive challenge */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH); | |||||
| decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL); | |||||
| API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill)); | |||||
| /* Respond */ | |||||
| API_NS(scalar_mul)(challenge, challenge, priv->secret_scalar); | |||||
| API_NS(scalar_sub)(nonce, nonce, challenge); | |||||
| /* Save results */ | |||||
| API_NS(scalar_encode)(overkill, nonce); | |||||
| decaf_TOY_strobe_transact(strobe,&sig[SER_BYTES],overkill,SCALAR_BYTES,STROBE_CW_SIG_RESP); | |||||
| /* Clean up */ | |||||
| API_NS(scalar_destroy)(nonce); | |||||
| API_NS(scalar_destroy)(challenge); | |||||
| decaf_bzero(overkill,sizeof(overkill)); | |||||
| } | |||||
| decaf_error_t API_NS_TOY(verify_strobe) ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(public_key_t) pub | |||||
| ) { | |||||
| decaf_bool_t ret; | |||||
| uint8_t overkill[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) point, pubpoint; | |||||
| API_NS(scalar_t) challenge, response; | |||||
| /* Stir pubkey */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK); | |||||
| /* Derive nonce */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH); | |||||
| ret = decaf_successful( API_NS(point_decode)(point, sig, DECAF_TRUE) ); | |||||
| /* Derive challenge */ | |||||
| decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL); | |||||
| API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill)); | |||||
| /* Decode response */ | |||||
| decaf_TOY_strobe_transact(strobe,overkill,&sig[SER_BYTES],SCALAR_BYTES,STROBE_CW_SIG_RESP); | |||||
| ret &= decaf_successful( API_NS(scalar_decode)(response, overkill) ); | |||||
| ret &= decaf_successful( API_NS(point_decode)(pubpoint, pub, DECAF_FALSE) ); | |||||
| API_NS(base_double_scalarmul_non_secret) ( | |||||
| pubpoint, response, pubpoint, challenge | |||||
| ); | |||||
| ret &= API_NS(point_eq)(pubpoint, point); | |||||
| /* Nothing here is secret, so don't do these things: | |||||
| decaf_bzero(overkill,sizeof(overkill)); | |||||
| API_NS(point_destroy)(point); | |||||
| API_NS(point_destroy)(pubpoint); | |||||
| API_NS(scalar_destroy)(challenge); | |||||
| API_NS(scalar_destroy)(response); | |||||
| */ | |||||
| return decaf_succeed_if(ret); | |||||
| } | |||||
| void | |||||
| API_NS_TOY(sign) ( | |||||
| API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(private_key_t) priv, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t ctx; | |||||
| decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0); | |||||
| decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT); | |||||
| API_NS_TOY(sign_strobe)(ctx, sig, priv); | |||||
| decaf_TOY_strobe_destroy(ctx); | |||||
| } | |||||
| decaf_error_t | |||||
| API_NS_TOY(verify) ( | |||||
| const API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(public_key_t) pub, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t ctx; | |||||
| decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0); | |||||
| decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT); | |||||
| decaf_error_t ret = API_NS_TOY(verify_strobe)(ctx, sig, pub); | |||||
| decaf_TOY_strobe_destroy(ctx); | |||||
| return ret; | |||||
| } | |||||
| @@ -1,24 +0,0 @@ | |||||
| /** | |||||
| * @file decaf/crypto.h | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * 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. | |||||
| * | |||||
| * @warning This file was automatically generated in Python. | |||||
| * Please do not edit it. | |||||
| */ | |||||
| #ifndef __DECAF_CRYPTO_H__ | |||||
| #define __DECAF_CRYPTO_H__ 1 | |||||
| #include <decaf/crypto_255.h> | |||||
| #include <decaf/crypto_448.h> | |||||
| #endif /* __DECAF_CRYPTO_H__ */ | |||||
| @@ -1,178 +0,0 @@ | |||||
| /** | |||||
| * @file src/GENERATED/c/decaf/crypto_255.h | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * 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. | |||||
| * | |||||
| * @warning This file was automatically generated in Python. | |||||
| * Please do not edit it. | |||||
| */ | |||||
| #ifndef __SRC_GENERATED_C_DECAF_CRYPTO_255_H__ | |||||
| #define __SRC_GENERATED_C_DECAF_CRYPTO_255_H__ 1 | |||||
| #include <decaf/point_255.h> | |||||
| #include <decaf/strobe.h> | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #endif | |||||
| /** Number of bytes for a symmetric key (expanded to full key) */ | |||||
| #define DECAF_255_SYMMETRIC_KEY_BYTES 32 | |||||
| /** A symmetric key, the compressed point of a private key. */ | |||||
| typedef unsigned char decaf_255_TOY_symmetric_key_t[DECAF_255_SYMMETRIC_KEY_BYTES]; | |||||
| /** An encoded public key. */ | |||||
| typedef unsigned char decaf_255_TOY_public_key_t[DECAF_255_SER_BYTES]; | |||||
| /** A signature. */ | |||||
| typedef unsigned char decaf_255_TOY_signature_t[DECAF_255_SER_BYTES + DECAF_255_SCALAR_BYTES]; | |||||
| typedef struct { | |||||
| /** @cond internal */ | |||||
| /** The symmetric key from which everything is expanded */ | |||||
| decaf_255_TOY_symmetric_key_t sym; | |||||
| /** The scalar x */ | |||||
| decaf_255_scalar_t secret_scalar; | |||||
| /** x*Base */ | |||||
| decaf_255_TOY_public_key_t pub; | |||||
| /** @endcond */ | |||||
| } /** Private key structure for pointers. */ | |||||
| decaf_255_TOY_private_key_s, | |||||
| /** A private key (gmp array[1] style). */ | |||||
| decaf_255_TOY_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 decaf_255_TOY_derive_private_key ( | |||||
| decaf_255_TOY_private_key_t priv, | |||||
| const decaf_255_TOY_symmetric_key_t proto | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * Destroy a private key. | |||||
| */ | |||||
| void decaf_255_TOY_destroy_private_key ( | |||||
| decaf_255_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * Convert a private key to a public one. | |||||
| * @param [out] pub The extracted private key. | |||||
| * @param [in] priv The private key. | |||||
| */ | |||||
| void decaf_255_TOY_private_to_public ( | |||||
| decaf_255_TOY_public_key_t pub, | |||||
| const decaf_255_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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_255_TOY_shared_secret ( | |||||
| uint8_t *shared, | |||||
| size_t shared_bytes, | |||||
| const decaf_255_TOY_private_key_t my_privkey, | |||||
| const decaf_255_TOY_public_key_t your_pubkey, | |||||
| int me_first | |||||
| ) NONNULL WARN_UNUSED API_VIS; | |||||
| /** | |||||
| * 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_255_TOY_sign_strobe ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| decaf_255_TOY_signature_t sig, | |||||
| const decaf_255_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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_255_TOY_sign ( | |||||
| decaf_255_TOY_signature_t sig, | |||||
| const decaf_255_TOY_private_key_t priv, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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_255_TOY_verify_strobe ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const decaf_255_TOY_signature_t sig, | |||||
| const decaf_255_TOY_public_key_t pub | |||||
| ) NONNULL API_VIS WARN_UNUSED; | |||||
| /** | |||||
| * 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_255_TOY_verify ( | |||||
| const decaf_255_TOY_signature_t sig, | |||||
| const decaf_255_TOY_public_key_t pub, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) NONNULL API_VIS WARN_UNUSED; | |||||
| #ifdef __cplusplus | |||||
| } /* extern "C" */ | |||||
| #endif | |||||
| #endif /* __SRC_GENERATED_C_DECAF_CRYPTO_255_H__ */ | |||||
| @@ -1,216 +0,0 @@ | |||||
| /** | |||||
| * @file src/GENERATED/c/decaf/crypto_255.hxx | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * | |||||
| * | |||||
| * @warning This file was automatically generated in Python. | |||||
| * Please do not edit it. | |||||
| */ | |||||
| #ifndef __SRC_GENERATED_C_DECAF_CRYPTO_255_HXX__ | |||||
| #define __SRC_GENERATED_C_DECAF_CRYPTO_255_HXX__ 1 | |||||
| /* | |||||
| * 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. | |||||
| */ | |||||
| #include <decaf/point_255.hxx> | |||||
| #include <decaf/shake.hxx> | |||||
| #include <decaf/strobe.hxx> | |||||
| /** @cond internal */ | |||||
| #if __cplusplus >= 201103L | |||||
| #define NOEXCEPT noexcept | |||||
| #else | |||||
| #define NOEXCEPT throw() | |||||
| #endif | |||||
| /** @endcond */ | |||||
| namespace decaf { namespace TOY { | |||||
| /** A public key for crypto over some Group */ | |||||
| template <typename Group> class PublicKey; | |||||
| /** A private key for crypto over some Group */ | |||||
| template <typename Group> class PrivateKey; | |||||
| /** A public key for crypto over Iso-Ed25519 */ | |||||
| template<> class PublicKey<IsoEd25519> | |||||
| : public Serializable< PublicKey<IsoEd25519> > { | |||||
| private: | |||||
| /** @cond internal */ | |||||
| typedef decaf_255_TOY_public_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PrivateKey; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** Underlying group */ | |||||
| typedef IsoEd25519 Group; | |||||
| /** Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof(decaf_255_TOY_signature_t); | |||||
| /** Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PublicKey(const PrivateKey<IsoEd25519> &b) NOEXCEPT; | |||||
| /** Create but don't initialize */ | |||||
| inline explicit PublicKey(const NOINIT&) NOEXCEPT { } | |||||
| /** Serialize into a buffer. */ | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** Serialization size. */ | |||||
| inline size_t ser_size() const NOEXCEPT { return SER_BYTES; } | |||||
| /** Verify a message */ | |||||
| inline void verify( | |||||
| const Block &message, | |||||
| const FixedBlock<SIG_BYTES> &sig | |||||
| ) const throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != decaf_255_TOY_verify(sig.data(),wrapped,message.data(),message.size())) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| } | |||||
| /** Verify a message */ | |||||
| inline void verify( | |||||
| Strobe &context, | |||||
| const FixedBlock<SIG_BYTES> &sig | |||||
| ) const throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != decaf_255_TOY_verify_strobe(context.wrapped,sig.data(),wrapped)) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| } | |||||
| }; | |||||
| /** A private key for crypto over Iso-Ed25519 */ | |||||
| template<> class PrivateKey<IsoEd25519> | |||||
| : public Serializable< PrivateKey<IsoEd25519> > { | |||||
| private: | |||||
| /** @cond internal */ | |||||
| typedef decaf_255_TOY_private_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PublicKey; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** Underlying group */ | |||||
| typedef IsoEd25519 Group; | |||||
| /** Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof(decaf_255_TOY_signature_t); | |||||
| /** Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /** Compressed size. */ | |||||
| static const size_t SYM_BYTES = DECAF_255_SYMMETRIC_KEY_BYTES; | |||||
| /** Create but don't initialize */ | |||||
| inline explicit PrivateKey(const NOINIT&) NOEXCEPT { } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT { | |||||
| decaf_255_TOY_derive_private_key(wrapped, b.data()); | |||||
| } | |||||
| /** Create at random */ | |||||
| inline explicit PrivateKey(Rng &r) NOEXCEPT { | |||||
| FixedArrayBuffer<SYM_BYTES> tmp(r); | |||||
| decaf_255_TOY_derive_private_key(wrapped, tmp.data()); | |||||
| } | |||||
| /** Secure destructor */ | |||||
| inline ~PrivateKey() NOEXCEPT { | |||||
| decaf_255_TOY_destroy_private_key(wrapped); | |||||
| } | |||||
| /** Serialization size. */ | |||||
| inline size_t ser_size() const NOEXCEPT { return SER_BYTES; } | |||||
| /** Serialize into a buffer. */ | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** Compressed serialize. */ | |||||
| inline SecureBuffer compress() const throw(std::bad_alloc) { | |||||
| SecureBuffer ret(sizeof(wrapped->sym)); | |||||
| memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym)); | |||||
| return ret; | |||||
| } | |||||
| /** Get the public key */ | |||||
| inline PublicKey<IsoEd25519> pub() const NOEXCEPT { | |||||
| PublicKey<IsoEd25519> ret(*this); return ret; | |||||
| } | |||||
| /** Derive a shared secret */ | |||||
| inline SecureBuffer shared_secret( | |||||
| const PublicKey<IsoEd25519> &pub, | |||||
| size_t bytes, | |||||
| bool me_first | |||||
| ) const throw(CryptoException,std::bad_alloc) { | |||||
| SecureBuffer ret(bytes); | |||||
| if (DECAF_SUCCESS != decaf_255_TOY_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| /** Derive a shared secret */ | |||||
| inline decaf_error_t __attribute__((warn_unused_result)) | |||||
| shared_secret_noexcept( | |||||
| Buffer ret, | |||||
| const PublicKey<IsoEd25519> &pub, | |||||
| bool me_first | |||||
| ) const NOEXCEPT { | |||||
| return decaf_255_TOY_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); | |||||
| decaf_255_TOY_sign(sig.data(), wrapped, message.data(), message.size()); | |||||
| return sig; | |||||
| } | |||||
| /** Sign a message. */ | |||||
| inline SecureBuffer verify(Strobe &context) const { | |||||
| SecureBuffer sig(SIG_BYTES); | |||||
| decaf_255_TOY_sign_strobe(context.wrapped, sig.data(), wrapped); | |||||
| return sig; | |||||
| } | |||||
| }; | |||||
| /** @cond internal */ | |||||
| PublicKey<IsoEd25519>::PublicKey(const PrivateKey<IsoEd25519> &b) NOEXCEPT { | |||||
| decaf_255_TOY_private_to_public(wrapped,b.wrapped); | |||||
| } | |||||
| /** @endcond */ | |||||
| #undef NOEXCEPT | |||||
| }} /* namespace decaf::TOY */ | |||||
| #endif /* __SRC_GENERATED_C_DECAF_CRYPTO_255_HXX__ */ | |||||
| @@ -1,178 +0,0 @@ | |||||
| /** | |||||
| * @file src/GENERATED/c/decaf/crypto_448.h | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * 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. | |||||
| * | |||||
| * @warning This file was automatically generated in Python. | |||||
| * Please do not edit it. | |||||
| */ | |||||
| #ifndef __SRC_GENERATED_C_DECAF_CRYPTO_448_H__ | |||||
| #define __SRC_GENERATED_C_DECAF_CRYPTO_448_H__ 1 | |||||
| #include <decaf/point_448.h> | |||||
| #include <decaf/strobe.h> | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #endif | |||||
| /** Number of bytes for a symmetric key (expanded to full key) */ | |||||
| #define DECAF_448_SYMMETRIC_KEY_BYTES 32 | |||||
| /** A symmetric key, the compressed point of a private key. */ | |||||
| typedef unsigned char decaf_448_TOY_symmetric_key_t[DECAF_448_SYMMETRIC_KEY_BYTES]; | |||||
| /** An encoded public key. */ | |||||
| typedef unsigned char decaf_448_TOY_public_key_t[DECAF_448_SER_BYTES]; | |||||
| /** A signature. */ | |||||
| typedef unsigned char decaf_448_TOY_signature_t[DECAF_448_SER_BYTES + DECAF_448_SCALAR_BYTES]; | |||||
| typedef struct { | |||||
| /** @cond internal */ | |||||
| /** The symmetric key from which everything is expanded */ | |||||
| decaf_448_TOY_symmetric_key_t sym; | |||||
| /** The scalar x */ | |||||
| decaf_448_scalar_t secret_scalar; | |||||
| /** x*Base */ | |||||
| decaf_448_TOY_public_key_t pub; | |||||
| /** @endcond */ | |||||
| } /** Private key structure for pointers. */ | |||||
| decaf_448_TOY_private_key_s, | |||||
| /** A private key (gmp array[1] style). */ | |||||
| decaf_448_TOY_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 decaf_448_TOY_derive_private_key ( | |||||
| decaf_448_TOY_private_key_t priv, | |||||
| const decaf_448_TOY_symmetric_key_t proto | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * Destroy a private key. | |||||
| */ | |||||
| void decaf_448_TOY_destroy_private_key ( | |||||
| decaf_448_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * Convert a private key to a public one. | |||||
| * @param [out] pub The extracted private key. | |||||
| * @param [in] priv The private key. | |||||
| */ | |||||
| void decaf_448_TOY_private_to_public ( | |||||
| decaf_448_TOY_public_key_t pub, | |||||
| const decaf_448_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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_TOY_shared_secret ( | |||||
| uint8_t *shared, | |||||
| size_t shared_bytes, | |||||
| const decaf_448_TOY_private_key_t my_privkey, | |||||
| const decaf_448_TOY_public_key_t your_pubkey, | |||||
| int me_first | |||||
| ) NONNULL WARN_UNUSED API_VIS; | |||||
| /** | |||||
| * 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_TOY_sign_strobe ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| decaf_448_TOY_signature_t sig, | |||||
| const decaf_448_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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_TOY_sign ( | |||||
| decaf_448_TOY_signature_t sig, | |||||
| const decaf_448_TOY_private_key_t priv, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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_TOY_verify_strobe ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const decaf_448_TOY_signature_t sig, | |||||
| const decaf_448_TOY_public_key_t pub | |||||
| ) NONNULL API_VIS WARN_UNUSED; | |||||
| /** | |||||
| * 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_TOY_verify ( | |||||
| const decaf_448_TOY_signature_t sig, | |||||
| const decaf_448_TOY_public_key_t pub, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) NONNULL API_VIS WARN_UNUSED; | |||||
| #ifdef __cplusplus | |||||
| } /* extern "C" */ | |||||
| #endif | |||||
| #endif /* __SRC_GENERATED_C_DECAF_CRYPTO_448_H__ */ | |||||
| @@ -1,216 +0,0 @@ | |||||
| /** | |||||
| * @file src/GENERATED/c/decaf/crypto_448.hxx | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * | |||||
| * | |||||
| * @warning This file was automatically generated in Python. | |||||
| * Please do not edit it. | |||||
| */ | |||||
| #ifndef __SRC_GENERATED_C_DECAF_CRYPTO_448_HXX__ | |||||
| #define __SRC_GENERATED_C_DECAF_CRYPTO_448_HXX__ 1 | |||||
| /* | |||||
| * 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. | |||||
| */ | |||||
| #include <decaf/point_448.hxx> | |||||
| #include <decaf/shake.hxx> | |||||
| #include <decaf/strobe.hxx> | |||||
| /** @cond internal */ | |||||
| #if __cplusplus >= 201103L | |||||
| #define NOEXCEPT noexcept | |||||
| #else | |||||
| #define NOEXCEPT throw() | |||||
| #endif | |||||
| /** @endcond */ | |||||
| namespace decaf { namespace TOY { | |||||
| /** A public key for crypto over some Group */ | |||||
| template <typename Group> class PublicKey; | |||||
| /** A private key for crypto over some Group */ | |||||
| template <typename Group> class PrivateKey; | |||||
| /** A public key for crypto over Ed448-Goldilocks */ | |||||
| template<> class PublicKey<Ed448Goldilocks> | |||||
| : public Serializable< PublicKey<Ed448Goldilocks> > { | |||||
| private: | |||||
| /** @cond internal */ | |||||
| typedef decaf_448_TOY_public_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PrivateKey; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** Underlying group */ | |||||
| typedef Ed448Goldilocks Group; | |||||
| /** Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof(decaf_448_TOY_signature_t); | |||||
| /** Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PublicKey(const PrivateKey<Ed448Goldilocks> &b) NOEXCEPT; | |||||
| /** Create but don't initialize */ | |||||
| inline explicit PublicKey(const NOINIT&) NOEXCEPT { } | |||||
| /** Serialize into a buffer. */ | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** Serialization size. */ | |||||
| inline size_t ser_size() const NOEXCEPT { return SER_BYTES; } | |||||
| /** Verify a message */ | |||||
| inline void verify( | |||||
| const Block &message, | |||||
| const FixedBlock<SIG_BYTES> &sig | |||||
| ) const throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != decaf_448_TOY_verify(sig.data(),wrapped,message.data(),message.size())) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| } | |||||
| /** Verify a message */ | |||||
| inline void verify( | |||||
| Strobe &context, | |||||
| const FixedBlock<SIG_BYTES> &sig | |||||
| ) const throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != decaf_448_TOY_verify_strobe(context.wrapped,sig.data(),wrapped)) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| } | |||||
| }; | |||||
| /** A private key for crypto over Ed448-Goldilocks */ | |||||
| template<> class PrivateKey<Ed448Goldilocks> | |||||
| : public Serializable< PrivateKey<Ed448Goldilocks> > { | |||||
| private: | |||||
| /** @cond internal */ | |||||
| typedef decaf_448_TOY_private_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PublicKey; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** Underlying group */ | |||||
| typedef Ed448Goldilocks Group; | |||||
| /** Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof(decaf_448_TOY_signature_t); | |||||
| /** Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /** Compressed size. */ | |||||
| static const size_t SYM_BYTES = DECAF_448_SYMMETRIC_KEY_BYTES; | |||||
| /** Create but don't initialize */ | |||||
| inline explicit PrivateKey(const NOINIT&) NOEXCEPT { } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT { | |||||
| decaf_448_TOY_derive_private_key(wrapped, b.data()); | |||||
| } | |||||
| /** Create at random */ | |||||
| inline explicit PrivateKey(Rng &r) NOEXCEPT { | |||||
| FixedArrayBuffer<SYM_BYTES> tmp(r); | |||||
| decaf_448_TOY_derive_private_key(wrapped, tmp.data()); | |||||
| } | |||||
| /** Secure destructor */ | |||||
| inline ~PrivateKey() NOEXCEPT { | |||||
| decaf_448_TOY_destroy_private_key(wrapped); | |||||
| } | |||||
| /** Serialization size. */ | |||||
| inline size_t ser_size() const NOEXCEPT { return SER_BYTES; } | |||||
| /** Serialize into a buffer. */ | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** Compressed serialize. */ | |||||
| inline SecureBuffer compress() const throw(std::bad_alloc) { | |||||
| SecureBuffer ret(sizeof(wrapped->sym)); | |||||
| memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym)); | |||||
| return ret; | |||||
| } | |||||
| /** Get the public key */ | |||||
| inline PublicKey<Ed448Goldilocks> pub() const NOEXCEPT { | |||||
| PublicKey<Ed448Goldilocks> ret(*this); return ret; | |||||
| } | |||||
| /** Derive a shared secret */ | |||||
| inline SecureBuffer shared_secret( | |||||
| const PublicKey<Ed448Goldilocks> &pub, | |||||
| size_t bytes, | |||||
| bool me_first | |||||
| ) const throw(CryptoException,std::bad_alloc) { | |||||
| SecureBuffer ret(bytes); | |||||
| if (DECAF_SUCCESS != decaf_448_TOY_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| /** Derive a shared secret */ | |||||
| inline decaf_error_t __attribute__((warn_unused_result)) | |||||
| shared_secret_noexcept( | |||||
| Buffer ret, | |||||
| const PublicKey<Ed448Goldilocks> &pub, | |||||
| bool me_first | |||||
| ) const NOEXCEPT { | |||||
| return decaf_448_TOY_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); | |||||
| decaf_448_TOY_sign(sig.data(), wrapped, message.data(), message.size()); | |||||
| return sig; | |||||
| } | |||||
| /** Sign a message. */ | |||||
| inline SecureBuffer verify(Strobe &context) const { | |||||
| SecureBuffer sig(SIG_BYTES); | |||||
| decaf_448_TOY_sign_strobe(context.wrapped, sig.data(), wrapped); | |||||
| return sig; | |||||
| } | |||||
| }; | |||||
| /** @cond internal */ | |||||
| PublicKey<Ed448Goldilocks>::PublicKey(const PrivateKey<Ed448Goldilocks> &b) NOEXCEPT { | |||||
| decaf_448_TOY_private_to_public(wrapped,b.wrapped); | |||||
| } | |||||
| /** @endcond */ | |||||
| #undef NOEXCEPT | |||||
| }} /* namespace decaf::TOY */ | |||||
| #endif /* __SRC_GENERATED_C_DECAF_CRYPTO_448_HXX__ */ | |||||
| @@ -1,231 +0,0 @@ | |||||
| /** | |||||
| * @file ed448goldilocks/crypto.c | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * @cond internal | |||||
| * @brief Example Decaf crypto routines | |||||
| * | |||||
| * @warning This file was automatically generated in Python. | |||||
| * Please do not edit it. | |||||
| */ | |||||
| #include <decaf/crypto.h> | |||||
| #include <string.h> | |||||
| #define API_NAME "decaf_448" | |||||
| #define API_NS(_id) decaf_448_##_id | |||||
| #define API_NS_TOY(_id) decaf_448_TOY_##_id | |||||
| #define SCALAR_BITS DECAF_448_SCALAR_BITS | |||||
| #define SCALAR_BYTES ((SCALAR_BITS + 7)/8) | |||||
| #define SER_BYTES DECAF_448_SER_BYTES | |||||
| /* TODO: canonicalize and freeze the STROBE constants in this file | |||||
| * (and STROBE itself for that matter) | |||||
| */ | |||||
| static const char *DERIVE_MAGIC = API_NAME"::derive_private_key"; | |||||
| static const char *SIGN_MAGIC = API_NAME"::sign"; | |||||
| static const char *SHARED_SECRET_MAGIC = API_NAME"::shared_secret"; | |||||
| static const uint16_t SHARED_SECRET_MAX_BLOCK_SIZE = 1<<12; | |||||
| static const unsigned int SCALAR_OVERKILL_BYTES = SCALAR_BYTES + 8; | |||||
| void API_NS_TOY(derive_private_key) ( | |||||
| API_NS_TOY(private_key_t) priv, | |||||
| const API_NS_TOY(symmetric_key_t) proto | |||||
| ) { | |||||
| uint8_t encoded_scalar[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) pub; | |||||
| keccak_decaf_TOY_strobe_t strobe; | |||||
| decaf_TOY_strobe_init(strobe, &STROBE_256, DERIVE_MAGIC, 0); | |||||
| decaf_TOY_strobe_fixed_key(strobe, proto, sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| decaf_TOY_strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar)); | |||||
| decaf_TOY_strobe_destroy(strobe); | |||||
| memcpy(priv->sym, proto, sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| API_NS(scalar_decode_long)(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar)); | |||||
| API_NS(precomputed_scalarmul)(pub, API_NS(precomputed_base), priv->secret_scalar); | |||||
| API_NS(point_encode)(priv->pub, pub); | |||||
| decaf_bzero(encoded_scalar, sizeof(encoded_scalar)); | |||||
| } | |||||
| void API_NS_TOY(destroy_private_key) ( | |||||
| API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| decaf_bzero((void*)priv, sizeof(API_NS_TOY(private_key_t))); | |||||
| } | |||||
| void API_NS_TOY(private_to_public) ( | |||||
| API_NS_TOY(public_key_t) pub, | |||||
| const API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| memcpy(pub, priv->pub, sizeof(API_NS_TOY(public_key_t))); | |||||
| } | |||||
| /* Performance vs consttime tuning. | |||||
| * Specifying true here might give better DOS resistance in certain corner | |||||
| * cases. Specifying false gives a tighter result in test_ct. | |||||
| */ | |||||
| #ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
| #define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE | |||||
| #endif | |||||
| decaf_error_t API_NS_TOY(shared_secret) ( | |||||
| uint8_t *shared, | |||||
| size_t shared_bytes, | |||||
| const API_NS_TOY(private_key_t) my_privkey, | |||||
| const API_NS_TOY(public_key_t) your_pubkey, | |||||
| int me_first | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t strobe; | |||||
| decaf_TOY_strobe_init(strobe, &STROBE_256, SHARED_SECRET_MAGIC, 0); | |||||
| uint8_t ss_ser[SER_BYTES]; | |||||
| if (me_first) { | |||||
| decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t))); | |||||
| decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t))); | |||||
| } else { | |||||
| decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t))); | |||||
| decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t))); | |||||
| } | |||||
| decaf_error_t ret = API_NS(direct_scalarmul)( | |||||
| ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, | |||||
| DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
| ); | |||||
| decaf_TOY_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; | |||||
| decaf_TOY_strobe_prng(strobe,shared,cando); | |||||
| shared_bytes -= cando; | |||||
| shared += cando; | |||||
| } | |||||
| decaf_TOY_strobe_destroy(strobe); | |||||
| decaf_bzero(ss_ser, sizeof(ss_ser)); | |||||
| return ret; | |||||
| } | |||||
| void API_NS_TOY(sign_strobe) ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| uint8_t overkill[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) point; | |||||
| API_NS(scalar_t) nonce, challenge; | |||||
| /* Stir pubkey */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,priv->pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK); | |||||
| /* Derive nonce */ | |||||
| keccak_decaf_TOY_strobe_t strobe2; | |||||
| memcpy(strobe2,strobe,sizeof(strobe2)); | |||||
| decaf_TOY_strobe_fixed_key(strobe2,priv->sym,sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| decaf_TOY_strobe_prng(strobe2,overkill,sizeof(overkill)); | |||||
| decaf_TOY_strobe_destroy(strobe2); | |||||
| API_NS(scalar_decode_long)(nonce, overkill, sizeof(overkill)); | |||||
| API_NS(precomputed_scalarmul)(point, API_NS(precomputed_base), nonce); | |||||
| API_NS(point_encode)(sig, point); | |||||
| /* Derive challenge */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH); | |||||
| decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL); | |||||
| API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill)); | |||||
| /* Respond */ | |||||
| API_NS(scalar_mul)(challenge, challenge, priv->secret_scalar); | |||||
| API_NS(scalar_sub)(nonce, nonce, challenge); | |||||
| /* Save results */ | |||||
| API_NS(scalar_encode)(overkill, nonce); | |||||
| decaf_TOY_strobe_transact(strobe,&sig[SER_BYTES],overkill,SCALAR_BYTES,STROBE_CW_SIG_RESP); | |||||
| /* Clean up */ | |||||
| API_NS(scalar_destroy)(nonce); | |||||
| API_NS(scalar_destroy)(challenge); | |||||
| decaf_bzero(overkill,sizeof(overkill)); | |||||
| } | |||||
| decaf_error_t API_NS_TOY(verify_strobe) ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(public_key_t) pub | |||||
| ) { | |||||
| decaf_bool_t ret; | |||||
| uint8_t overkill[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) point, pubpoint; | |||||
| API_NS(scalar_t) challenge, response; | |||||
| /* Stir pubkey */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK); | |||||
| /* Derive nonce */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH); | |||||
| ret = decaf_successful( API_NS(point_decode)(point, sig, DECAF_TRUE) ); | |||||
| /* Derive challenge */ | |||||
| decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL); | |||||
| API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill)); | |||||
| /* Decode response */ | |||||
| decaf_TOY_strobe_transact(strobe,overkill,&sig[SER_BYTES],SCALAR_BYTES,STROBE_CW_SIG_RESP); | |||||
| ret &= decaf_successful( API_NS(scalar_decode)(response, overkill) ); | |||||
| ret &= decaf_successful( API_NS(point_decode)(pubpoint, pub, DECAF_FALSE) ); | |||||
| API_NS(base_double_scalarmul_non_secret) ( | |||||
| pubpoint, response, pubpoint, challenge | |||||
| ); | |||||
| ret &= API_NS(point_eq)(pubpoint, point); | |||||
| /* Nothing here is secret, so don't do these things: | |||||
| decaf_bzero(overkill,sizeof(overkill)); | |||||
| API_NS(point_destroy)(point); | |||||
| API_NS(point_destroy)(pubpoint); | |||||
| API_NS(scalar_destroy)(challenge); | |||||
| API_NS(scalar_destroy)(response); | |||||
| */ | |||||
| return decaf_succeed_if(ret); | |||||
| } | |||||
| void | |||||
| API_NS_TOY(sign) ( | |||||
| API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(private_key_t) priv, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t ctx; | |||||
| decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0); | |||||
| decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT); | |||||
| API_NS_TOY(sign_strobe)(ctx, sig, priv); | |||||
| decaf_TOY_strobe_destroy(ctx); | |||||
| } | |||||
| decaf_error_t | |||||
| API_NS_TOY(verify) ( | |||||
| const API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(public_key_t) pub, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t ctx; | |||||
| decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0); | |||||
| decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT); | |||||
| decaf_error_t ret = API_NS_TOY(verify_strobe)(ctx, sig, pub); | |||||
| decaf_TOY_strobe_destroy(ctx); | |||||
| return ret; | |||||
| } | |||||
| @@ -1,10 +0,0 @@ | |||||
| /** | |||||
| * 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()]) | |||||
| ])) | |||||
| @@ -1,341 +0,0 @@ | |||||
| /** | |||||
| * @file decaf/strobe.h | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * @author Mike Hamburg | |||||
| * @brief STROBE experimental protocol framework. | |||||
| * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change. | |||||
| */ | |||||
| #ifndef __DECAF_STROBE_H__ | |||||
| #define __DECAF_STROBE_H__ | |||||
| #include <decaf/shake.h> | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #endif | |||||
| /** Keccak STROBE structure as struct. */ | |||||
| typedef struct { | |||||
| decaf_keccak_sponge_t sponge; /**< Internal sponge object. */ | |||||
| } keccak_decaf_TOY_strobe_s; | |||||
| /** Keccak STROBE structure as one-element array */ | |||||
| typedef keccak_decaf_TOY_strobe_s keccak_decaf_TOY_strobe_t[1]; | |||||
| /** STROBE parameters, 128-bit estimated security for hashing and encryption */ | |||||
| extern const struct decaf_kparams_s STROBE_128 API_VIS; | |||||
| /** STROBE parameters, 256-bit estimated security for hashing and encryption */ | |||||
| extern const struct decaf_kparams_s STROBE_256 API_VIS; | |||||
| /** STROBE parameters, 128-bit estimated security for encryption only (not hashing) */ | |||||
| extern const struct decaf_kparams_s STROBE_KEYED_128 API_VIS; | |||||
| /** STROBE parameters, 256-bit estimated security for encryption only (not hashing) */ | |||||
| extern const struct decaf_kparams_s STROBE_KEYED_256 API_VIS; | |||||
| /** Initialize Strobe protocol context. */ | |||||
| void decaf_TOY_strobe_init ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [out] The uninitialized strobe object. */ | |||||
| const struct decaf_kparams_s *params, /**< [in] Parameter set descriptor. */ | |||||
| const char *proto, /**< [in] Unique identifier for the protocol. TODO: define namespaces for this */ | |||||
| uint8_t am_client /**< [in] Nonzero if this party. */ | |||||
| ) NONNULL API_VIS; | |||||
| /** Run a transaction against a STROBE state. */ | |||||
| void decaf_TOY_strobe_transact ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized STROBE object. */ | |||||
| unsigned char *out, /**< [out] The output. */ | |||||
| const unsigned char *in, /**< [in] The input. */ | |||||
| size_t len, /**< [in] The length of the input/output. */ | |||||
| uint32_t cw_flags /**< [in] The control word with flags. */ | |||||
| ) __attribute__((nonnull(1))) API_VIS; | |||||
| /** Record a message sent in plaintext */ | |||||
| static INLINE UNUSED NONNULL void decaf_TOY_strobe_plaintext ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The STROBE object */ | |||||
| const unsigned char *in, /**< [in] The message. */ | |||||
| uint16_t len, /**< [in] The length of the message. */ | |||||
| uint8_t iSent /**< [in] If nonzero, I sent the message. */ | |||||
| ); | |||||
| /** Report authenticated data in strobe context. */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_ad ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The strobe object. */ | |||||
| const unsigned char *in, /**< [in] The plaintext. */ | |||||
| size_t len /**< [in] The length of the ad. */ | |||||
| ); | |||||
| /** Set nonce in strobe context. */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_nonce ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe object. */ | |||||
| const unsigned char *in, /**< [in] The nonce. */ | |||||
| uint16_t len /**< [in] The length of the nonce. */ | |||||
| ); | |||||
| /** Set fixed key in strobe context. */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_fixed_key ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe object. */ | |||||
| const unsigned char *in, /**< [in] The key. */ | |||||
| uint16_t len /**< [in] The length of the key. */ | |||||
| ); | |||||
| /** Set Diffie-Hellman key in strobe context. */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_dh_key ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe object. */ | |||||
| const unsigned char *in, /**< [in] The key. */ | |||||
| uint16_t len /**< [in] The length of the key. */ | |||||
| ); | |||||
| /** The maximum number of bytes that decaf_TOY_strobe_produce_auth can spit out. */ | |||||
| #define STROBE_MAX_AUTH_BYTES 32 | |||||
| /** Produce an authenticator. */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_produce_auth ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context. */ | |||||
| unsigned char *out, /**< [out] The authenticator. */ | |||||
| uint16_t len /**< [in] The length, at most STROBE_MAX_AUTH_BYTES. */ | |||||
| ); | |||||
| /** | |||||
| * @brief Verify an authenticator. | |||||
| * @retval DECAF_SUCCESS The operation applied successfully. | |||||
| * @retval DECAF_FAILURE The operation failed because of a | |||||
| * bad validator (or because you aren't keyed) | |||||
| */ | |||||
| decaf_error_t decaf_TOY_strobe_verify_auth ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context */ | |||||
| const unsigned char *in, /**< [in] The authenticator */ | |||||
| uint16_t len /**< [in] The length, at most STROBE_MAX_AUTH_BYTES. */ | |||||
| ) WARN_UNUSED NONNULL API_VIS; | |||||
| /** | |||||
| * @brief Encrypt bytes from in to out. | |||||
| * @warning Doesn't produce an auth tag. | |||||
| */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_encrypt ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] strobe The Strobe protocol context. */ | |||||
| unsigned char *out, /**< [out] The ciphertext. */ | |||||
| const unsigned char *in, /**< [in] The plaintext. */ | |||||
| uint16_t len /**< [in] The length of plaintext and ciphertext. */ | |||||
| ); | |||||
| /** | |||||
| * Decrypt bytes from in to out. | |||||
| * @warning Doesn't check an auth tag. | |||||
| */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_decrypt ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context. */ | |||||
| unsigned char *out, /**< [out] The plaintext. */ | |||||
| const unsigned char *in, /**< [in] The ciphertext. */ | |||||
| uint16_t len /**< [in] The length of plaintext and ciphertext. */ | |||||
| ); | |||||
| /** | |||||
| * @brief Produce a session-bound pseudorandom value. | |||||
| * | |||||
| * @warning This "prng" value is NOT suitable for | |||||
| * refreshing forward secrecy! It's to replace things | |||||
| * like TCP session hash. | |||||
| */ | |||||
| static inline void NONNULL decaf_TOY_strobe_prng ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context */ | |||||
| unsigned char *out, /**< [out] The output random data. */ | |||||
| uint16_t len /**< The length. */ | |||||
| ); | |||||
| /** Respecify Strobe protocol object's crypto. */ | |||||
| void decaf_TOY_strobe_respec ( | |||||
| keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe context. */ | |||||
| const struct decaf_kparams_s *params /**< [in] Strobe parameter descriptor. */ | |||||
| ) NONNULL API_VIS; | |||||
| /** Securely destroy a STROBE object by overwriting it. */ | |||||
| static INLINE UNUSED NONNULL void | |||||
| decaf_TOY_strobe_destroy ( | |||||
| keccak_decaf_TOY_strobe_t doomed /**< [in] The object to destroy. */ | |||||
| ); | |||||
| /** @cond internal */ | |||||
| /************************************************************************/ | |||||
| /* Declarations of various constants and operating modes, for extension */ | |||||
| /************************************************************************/ | |||||
| /** STROBE modes of operation */ | |||||
| typedef enum { | |||||
| STROBE_MODE_ABSORB = 0, | |||||
| STROBE_MODE_DUPLEX = 1, | |||||
| STROBE_MODE_ABSORB_R = 2, | |||||
| STROBE_MODE_DUPLEX_R = 3, | |||||
| /* FIXME: no bits allocated in .py version */ | |||||
| STROBE_MODE_PLAINTEXT = 4, | |||||
| STROBE_MODE_SQUEEZE = 5, | |||||
| STROBE_MODE_FORGET = 6, | |||||
| STROBE_MODE_SQUEEZE_R = 7 | |||||
| } decaf_TOY_strobe_mode_t; | |||||
| #define STROBE_FLAG_CLIENT_SENT (1<<8) /**< Set if the client this message. */ | |||||
| #define STROBE_FLAG_IMPLICIT (1<<9) /**< Set if nobody set this message. */ | |||||
| #define STROBE_FLAG_FORGET (1<<12) /**< After this operation, destroy bytes to prevent rollback. */ | |||||
| /* TODO: maybe just make STROBE heavy non-invertible? */ | |||||
| #define STROBE_FLAG_NO_LENGTH (1<<15) /**< This operation has an unknown length (for streaming). */ | |||||
| /* After 1<<16, flags don't go to the sponge anymore, they just affect the handling */ | |||||
| #define STROBE_FLAG_RECV (1<<16) /**< I received this packet, so reverse directions. */ | |||||
| #define STROBE_FLAG_RUN_F (1<<17) /**< Must run F between control word and data. */ | |||||
| #define STROBE_FLAG_MORE (1<<18) /**< Set for all operations in an unknown-length streaming operation after the first */ | |||||
| #define STROBE_FLAG_LENGTH_64 (1<<19) /**< Length is a 64-bit word instead of a 16-bit one. */ | |||||
| #define STROBE_FLAG_NONDIR (STROBE_FLAG_IMPLICIT) | |||||
| /** Automatic flags implied by the mode */ | |||||
| /* NB: SQUEEZE_R is treated as directional because its' MAC. | |||||
| * can of course override by orring in IMPLICIT|NONDIR | |||||
| */ | |||||
| #define STROBE_AUTO_FLAGS(_mode) \ | |||||
| ( (((_mode)&1) ? STROBE_FLAG_RUN_F : 0) \ | |||||
| | (( ((_mode) & ~2) == STROBE_MODE_ABSORB \ | |||||
| || (_mode) == STROBE_MODE_SQUEEZE \ | |||||
| || (_mode) == STROBE_MODE_FORGET \ | |||||
| ) ? STROBE_FLAG_IMPLICIT|STROBE_FLAG_NONDIR : 0) \ | |||||
| ) | |||||
| /**@ Define a control word for STROBE protocols. */ | |||||
| #define STROBE_CONTROL_WORD(_name,_id,_mode,_flags) \ | |||||
| static const uint32_t _name = _id | (_mode<<10) | (_mode<<29) | _flags | STROBE_AUTO_FLAGS(_mode) | |||||
| STROBE_CONTROL_WORD(STROBE_CW_INIT, 0x00, STROBE_MODE_ABSORB, 0); /**< Initialization with protocol name */ | |||||
| /* Ciphers */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_FIXED_KEY, 0x10, STROBE_MODE_ABSORB, 0); /**< Fixed symmetric/preshared key */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_STATIC_PUB, 0x11, STROBE_MODE_PLAINTEXT, 0); /**< Static public key of other party */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_DH_EPH, 0x12, STROBE_MODE_PLAINTEXT, 0); /**< DH ephemeral key on the wire */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_DH_KEY, 0x13, STROBE_MODE_ABSORB, 0); /**< DH shared secret key */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PRNG, 0x18, STROBE_MODE_SQUEEZE, STROBE_FLAG_FORGET); /**< Generate random bits (for PRNG) */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_SESSION_HASH, 0x19, STROBE_MODE_SQUEEZE, 0); /**< Generate session hash */ | |||||
| /* Reuse for PRNG */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PRNG_INITIAL_SEED, 0x10, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); /**< Initial seeding for PRNG */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PRNG_RESEED, 0x11, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); /**< Later seeding for PRNG */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PRNG_CPU_SEED, 0x12, STROBE_MODE_ABSORB, 0); /**< Seed from CPU-builin RNG */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PRNG_USER_SEED, 0x13, STROBE_MODE_ABSORB, STROBE_FLAG_LENGTH_64); /**< Seed from user */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PRNG_PRNG, 0x14, STROBE_MODE_SQUEEZE, STROBE_FLAG_LENGTH_64 | STROBE_FLAG_FORGET); /**< Call to generate bits */ | |||||
| /* Signatures */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_SIG_SCHEME, 0x20, STROBE_MODE_ABSORB, 0); /**< Name of the signature scheme we're using. */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_SIG_PK, 0x21, STROBE_MODE_ABSORB, 0); /**< Public (verification key) */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_SIG_EPH, 0x22, STROBE_MODE_PLAINTEXT, 0); /**< Schnorr ephemeral. */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_SIG_CHAL, 0x23, STROBE_MODE_SQUEEZE, 0); /**< Schnorr challenge. */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_SIG_RESP, 0x24, STROBE_MODE_DUPLEX, 0); /**< Schnoll response. */ | |||||
| /* Payloads and encrypted data */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PAYLOAD_PLAINTEXT, 0x30, STROBE_MODE_PLAINTEXT, 0); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_PAYLOAD_CIPHERTEXT, 0x31, STROBE_MODE_DUPLEX, 0); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_MAC, 0x32, STROBE_MODE_SQUEEZE_R, STROBE_FLAG_FORGET); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_AD_EXPLICIT, 0x34, STROBE_MODE_PLAINTEXT, 0); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_AD_IMPLICIT, 0x35, STROBE_MODE_ABSORB, 0); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_NONCE_EXPLICIT, 0x36, STROBE_MODE_PLAINTEXT, 0); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_NONCE_IMPLICIT, 0x37, STROBE_MODE_ABSORB, 0); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_STREAMING_PLAINTEXT,0x30, STROBE_MODE_PLAINTEXT, STROBE_FLAG_NO_LENGTH); /* TODO: orly? */ | |||||
| /* Change spec, control flow, etc */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_COMPRESS, 0x40, STROBE_MODE_ABSORB_R, 0); | |||||
| /* FIXME: adjust this respec logic */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_RESPEC_INFO, 0x41, STROBE_MODE_ABSORB, STROBE_FLAG_RUN_F | STROBE_FLAG_FORGET); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_RESPEC, 0x42, STROBE_MODE_ABSORB_R, STROBE_FLAG_RUN_F); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_FORK, 0x43, STROBE_MODE_ABSORB_R, STROBE_FLAG_RUN_F | STROBE_FLAG_FORGET); | |||||
| /* FIXME: instance can be rolled back to recover other INSTANCEs */ | |||||
| STROBE_CONTROL_WORD(STROBE_CW_INSTANCE, 0x44, STROBE_MODE_ABSORB_R, STROBE_FLAG_FORGET); | |||||
| STROBE_CONTROL_WORD(STROBE_CW_ACKNOWLEDGE, 0x45, STROBE_MODE_PLAINTEXT, 0); | |||||
| /** Reverse a keyword because it's being received instead of sent */ | |||||
| static INLINE UNUSED WARN_UNUSED uint32_t | |||||
| decaf_TOY_strobe_cw_recv(uint32_t cw) { | |||||
| uint32_t recv_toggle = (cw & STROBE_FLAG_NONDIR) ? 0 : STROBE_FLAG_RECV; | |||||
| if (cw & STROBE_FLAG_IMPLICIT) { | |||||
| return cw ^ recv_toggle; | |||||
| } else { | |||||
| uint32_t modes_2[8] = { | |||||
| /* Note: most of these really shouldn't happen... */ | |||||
| STROBE_MODE_ABSORB, | |||||
| STROBE_MODE_DUPLEX_R, | |||||
| STROBE_MODE_ABSORB_R, | |||||
| STROBE_MODE_DUPLEX, | |||||
| STROBE_MODE_PLAINTEXT, | |||||
| STROBE_MODE_SQUEEZE, | |||||
| STROBE_MODE_FORGET, | |||||
| STROBE_MODE_ABSORB | |||||
| }; | |||||
| return ((cw & ((1<<29)-1)) | (modes_2[cw>>29]<<29)) ^ recv_toggle; | |||||
| } | |||||
| } | |||||
| /***************************************/ | |||||
| /* Implementations of inline functions */ | |||||
| /***************************************/ | |||||
| void decaf_TOY_strobe_plaintext(keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len, uint8_t iSent) { | |||||
| decaf_TOY_strobe_transact( | |||||
| strobe, NULL, in, len, | |||||
| iSent ? STROBE_CW_PAYLOAD_PLAINTEXT | |||||
| : decaf_TOY_strobe_cw_recv(STROBE_CW_PAYLOAD_PLAINTEXT) | |||||
| ); | |||||
| } | |||||
| void decaf_TOY_strobe_ad(keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, size_t len) { | |||||
| decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_AD_EXPLICIT ); | |||||
| } | |||||
| void decaf_TOY_strobe_nonce (keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len) { | |||||
| decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_NONCE_EXPLICIT ); | |||||
| } | |||||
| void decaf_TOY_strobe_fixed_key (keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len) { | |||||
| decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_FIXED_KEY ); | |||||
| } | |||||
| void decaf_TOY_strobe_dh_key (keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len) { | |||||
| decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_DH_KEY ); | |||||
| } | |||||
| void decaf_TOY_strobe_produce_auth (keccak_decaf_TOY_strobe_t strobe, unsigned char *out, uint16_t len) { | |||||
| decaf_TOY_strobe_transact( strobe, out, NULL, len, STROBE_CW_MAC ); | |||||
| } | |||||
| void decaf_TOY_strobe_encrypt (keccak_decaf_TOY_strobe_t strobe, unsigned char *out, const unsigned char *in, uint16_t len) { | |||||
| decaf_TOY_strobe_transact(strobe, out, in, len, STROBE_CW_PAYLOAD_CIPHERTEXT); | |||||
| } | |||||
| void decaf_TOY_strobe_decrypt(keccak_decaf_TOY_strobe_t strobe, unsigned char *out, const unsigned char *in, uint16_t len) { | |||||
| decaf_TOY_strobe_transact(strobe, out, in, len, decaf_TOY_strobe_cw_recv(STROBE_CW_PAYLOAD_CIPHERTEXT)); | |||||
| } | |||||
| void decaf_TOY_strobe_prng(keccak_decaf_TOY_strobe_t strobe, unsigned char *out, uint16_t len) { | |||||
| decaf_TOY_strobe_transact( strobe, out, NULL, len, STROBE_CW_PRNG ); | |||||
| } | |||||
| void decaf_TOY_strobe_destroy (keccak_decaf_TOY_strobe_t doomed) { | |||||
| decaf_sponge_destroy(doomed->sponge); | |||||
| } | |||||
| /** @endcond */ /* internal */ | |||||
| #ifdef __cplusplus | |||||
| } /* extern "C" */ | |||||
| #endif | |||||
| #endif /* __DECAF_STROBE_H__ */ | |||||
| @@ -1,239 +0,0 @@ | |||||
| /** | |||||
| * @file decaf/strobe.hxx | |||||
| * @copyright | |||||
| * Based on CC0 code by David Leon Gil, 2015 \n | |||||
| * Copyright (c) 2015 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * @author Mike Hamburg | |||||
| * @brief STROBE instances, C++ wrapper. | |||||
| * @warning This protocol framework is entirely experimental, and shouldn't be | |||||
| * relied on for anything serious yet. | |||||
| */ | |||||
| #ifndef __DECAF_STROBE_HXX__ | |||||
| #define __DECAF_STROBE_HXX__ | |||||
| #include <decaf/strobe.h> | |||||
| #include <sys/types.h> | |||||
| /** @cond internal */ | |||||
| #if __cplusplus >= 201103L | |||||
| #define NOEXCEPT noexcept | |||||
| #define DELETE = delete | |||||
| #else | |||||
| #define NOEXCEPT throw() | |||||
| #define DELETE | |||||
| #endif | |||||
| /** @endcond */ | |||||
| namespace decaf { | |||||
| /** @brief An exception for misused protocol, eg encrypt with no key. */ | |||||
| class ProtocolException : public std::exception { | |||||
| public: | |||||
| /** @return "ProtocolException" */ | |||||
| virtual const char * what() const NOEXCEPT { return "ProtocolException"; } | |||||
| }; | |||||
| /** STROBE protocol framework object */ | |||||
| class Strobe { | |||||
| public: | |||||
| /** The wrapped object */ | |||||
| keccak_decaf_TOY_strobe_t wrapped; | |||||
| /** Number of bytes in a default authentication size. */ | |||||
| static const uint16_t DEFAULT_AUTH_SIZE = 16; | |||||
| /** Am I a server or a client? */ | |||||
| enum client_or_server { SERVER, CLIENT }; | |||||
| /** Create protocol object. */ | |||||
| inline Strobe ( | |||||
| const char *description, /**< Description of this protocol. */ | |||||
| client_or_server whoami, /**< Am I client or server? */ | |||||
| const decaf_kparams_s ¶ms = STROBE_256 /**< Strength parameters */ | |||||
| ) NOEXCEPT { | |||||
| decaf_TOY_strobe_init(wrapped, ¶ms, description, whoami == CLIENT); | |||||
| keyed = false; | |||||
| } | |||||
| /** Securely destroy by overwriting state. */ | |||||
| inline ~Strobe() NOEXCEPT { decaf_TOY_strobe_destroy(wrapped); } | |||||
| /** Stir in fixed key, from a C++ block. */ | |||||
| inline void fixed_key ( | |||||
| const Block &data /**< The key. */ | |||||
| ) throw(ProtocolException) { | |||||
| decaf_TOY_strobe_fixed_key(wrapped, data.data(), data.size()); | |||||
| keyed = true; | |||||
| } | |||||
| /** Stir in fixed key, from a serializeable object. */ | |||||
| template<class T> inline void fixed_key ( | |||||
| const Serializable<T> &data /**< The key. */ | |||||
| ) throw(ProtocolException) { | |||||
| fixed_key(data.serialize()); | |||||
| } | |||||
| /** Stir in DH key, from a C++ block. */ | |||||
| inline void dh_key ( | |||||
| const Block &data /**< The key. */ | |||||
| ) throw(ProtocolException) { | |||||
| decaf_TOY_strobe_dh_key(wrapped, data.data(), data.size()); | |||||
| keyed = true; | |||||
| } | |||||
| /** Stir in DH key, from a serializeable object. */ | |||||
| template<class T> inline void dh_key ( | |||||
| const Serializable<T> &data /**< The key. */ | |||||
| ) throw(ProtocolException) { | |||||
| dh_key(data.serialize()); | |||||
| } | |||||
| /** Stir in an explicit nonce. */ | |||||
| inline void nonce(const Block &data) NOEXCEPT { | |||||
| decaf_TOY_strobe_nonce(wrapped, data.data(), data.size()); | |||||
| } | |||||
| /** Stir in data we sent as plaintext. NB This doesn't actually send anything. */ | |||||
| inline void send_plaintext(const Block &data) NOEXCEPT { | |||||
| decaf_TOY_strobe_plaintext(wrapped, data.data(), data.size(), true); | |||||
| } | |||||
| /** Stir in serializeable data we sent as plaintext. NB This doesn't actually send anything. */ | |||||
| template<class T> inline void send_plaintext(const Serializable<T> &data) NOEXCEPT { | |||||
| send_plaintext(data.serialize()); | |||||
| } | |||||
| /** Stir in data we received as plaintext. NB This doesn't actually receive anything. */ | |||||
| inline void recv_plaintext(const Block &data) NOEXCEPT { | |||||
| decaf_TOY_strobe_plaintext(wrapped, data.data(), data.size(), false); | |||||
| } | |||||
| /** Stir in associated data. */ | |||||
| inline void ad(const Block &data) { | |||||
| decaf_TOY_strobe_ad(wrapped, data.data(), data.size()); | |||||
| } | |||||
| /** Stir in associated serializable data. */ | |||||
| template<class T> inline void ad(const Serializable<T> &data) NOEXCEPT { | |||||
| ad(data.serialize()); | |||||
| } | |||||
| /** Encrypt into a buffer, without appending authentication data */ | |||||
| inline void encrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) { | |||||
| if (!keyed) throw ProtocolException(); | |||||
| if (out.size() != data.size()) throw LengthException(); | |||||
| decaf_TOY_strobe_encrypt(wrapped, out.data(), data.data(), data.size()); | |||||
| } | |||||
| /** Encrypt, without appending authentication data */ | |||||
| inline SecureBuffer encrypt_no_auth(const Block &data) throw(ProtocolException) { | |||||
| SecureBuffer out(data.size()); encrypt_no_auth(out, data); return out; | |||||
| } | |||||
| /** Encrypt a serializable object, without appending authentication data */ | |||||
| template<class T> inline SecureBuffer encrypt_no_auth(const Serializable<T> &data) throw(ProtocolException) { | |||||
| return encrypt_no_auth(data.serialize()); | |||||
| } | |||||
| /** Decrypt into a buffer, without checking authentication data. */ | |||||
| inline void decrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) { | |||||
| if (!keyed) throw ProtocolException(); | |||||
| if (out.size() != data.size()) throw LengthException(); | |||||
| decaf_TOY_strobe_decrypt(wrapped, out.data(), data.data(), data.size()); | |||||
| } | |||||
| /** Decrypt, without checking authentication data. */ | |||||
| inline SecureBuffer decrypt_no_auth(const Block &data) throw(ProtocolException) { | |||||
| SecureBuffer out(data.size()); decrypt_no_auth(out, data); return out; | |||||
| } | |||||
| /** Produce an authenticator into a buffer. */ | |||||
| inline void produce_auth(Buffer out, bool even_though_unkeyed = false) throw(LengthException,ProtocolException) { | |||||
| if (!keyed && !even_though_unkeyed) throw ProtocolException(); | |||||
| if (out.size() > STROBE_MAX_AUTH_BYTES) throw LengthException(); | |||||
| decaf_TOY_strobe_produce_auth(wrapped, out.data(), out.size()); | |||||
| } | |||||
| /** Produce an authenticator. */ | |||||
| inline SecureBuffer produce_auth(uint8_t bytes = DEFAULT_AUTH_SIZE) throw(ProtocolException) { | |||||
| SecureBuffer out(bytes); produce_auth(out); return out; | |||||
| } | |||||
| /** Encrypt into a buffer and append authentication data */ | |||||
| inline void encrypt( | |||||
| Buffer out, const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE | |||||
| ) throw(LengthException,ProtocolException) { | |||||
| if (out.size() < data.size() || out.size() != data.size() + auth) throw LengthException(); | |||||
| encrypt_no_auth(out.slice(0,data.size()), data); | |||||
| produce_auth(out.slice(data.size(),auth)); | |||||
| } | |||||
| /** Encrypt and append authentication data */ | |||||
| inline SecureBuffer encrypt ( | |||||
| const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE | |||||
| ) throw(LengthException,ProtocolException,std::bad_alloc ){ | |||||
| SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out; | |||||
| } | |||||
| /** Encrypt a serializable object and append authentication data */ | |||||
| template<class T> inline SecureBuffer encrypt ( | |||||
| const Serializable<T> &data, uint8_t auth = DEFAULT_AUTH_SIZE | |||||
| ) throw(LengthException,ProtocolException,std::bad_alloc ){ | |||||
| return encrypt(data.serialize(), auth); | |||||
| } | |||||
| /** Decrypt into a buffer and check authentication data */ | |||||
| inline void decrypt ( | |||||
| Buffer out, const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE | |||||
| ) throw(LengthException, CryptoException, ProtocolException) { | |||||
| if (out.size() > data.size() || out.size() != data.size() - bytes) throw LengthException(); | |||||
| decrypt_no_auth(out, data.slice(0,out.size())); | |||||
| verify_auth(data.slice(out.size(),bytes)); | |||||
| } | |||||
| /** Decrypt and check authentication data */ | |||||
| inline SecureBuffer decrypt ( | |||||
| const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE | |||||
| ) throw(LengthException,CryptoException,ProtocolException,std::bad_alloc) { | |||||
| if (data.size() < bytes) throw LengthException(); | |||||
| SecureBuffer out(data.size() - bytes); decrypt(out, data, bytes); return out; | |||||
| } | |||||
| /** Check authentication data */ | |||||
| inline void verify_auth(const Block &auth) throw(LengthException,CryptoException) { | |||||
| if (auth.size() == 0 || auth.size() > STROBE_MAX_AUTH_BYTES) throw LengthException(); | |||||
| if (decaf_TOY_strobe_verify_auth(wrapped, auth.data(), auth.size()) != DECAF_SUCCESS) throw CryptoException(); | |||||
| } | |||||
| /** Fill pseudorandom data into a buffer */ | |||||
| inline void prng(Buffer out) NOEXCEPT { | |||||
| (void)decaf_TOY_strobe_prng(wrapped, out.data(), out.size()); | |||||
| } | |||||
| /** Return pseudorandom data */ | |||||
| inline SecureBuffer prng(size_t bytes) { | |||||
| SecureBuffer out(bytes); prng(out); return out; | |||||
| } | |||||
| /** Change specs, perhaps to a faster spec that takes advantage of being keyed. | |||||
| * @warning Experimental. | |||||
| */ | |||||
| inline void respec(const decaf_kparams_s ¶ms) throw(ProtocolException) { | |||||
| if (!keyed) throw(ProtocolException()); | |||||
| decaf_TOY_strobe_respec(wrapped, ¶ms); | |||||
| } | |||||
| private: | |||||
| bool keyed; | |||||
| }; | |||||
| } /* namespace decaf */ | |||||
| #undef NOEXCEPT | |||||
| #undef DELETE | |||||
| #endif /* __DECAF_STROBE_HXX__ */ | |||||
| @@ -5,7 +5,7 @@ | |||||
| * Copyright (c) 2016 Cryptography Research, Inc. \n | * Copyright (c) 2016 Cryptography Research, Inc. \n | ||||
| * Released under the MIT License. See LICENSE.txt for license information. | * Released under the MIT License. See LICENSE.txt for license information. | ||||
| * @author Mike Hamburg | * @author Mike Hamburg | ||||
| * @brief Keccak internal interfaces, used by STROBE. | |||||
| * @brief Keccak internal interfaces. Will be used by STROBE once reintegrated. | |||||
| */ | */ | ||||
| #ifndef __DECAF_KECCAK_INTERNAL_H__ | #ifndef __DECAF_KECCAK_INTERNAL_H__ | ||||
| #define __DECAF_KECCAK_INTERNAL_H__ 1 | #define __DECAF_KECCAK_INTERNAL_H__ 1 | ||||
| @@ -18,8 +18,8 @@ typedef union { | |||||
| } kdomain_t[1]; | } kdomain_t[1]; | ||||
| typedef struct decaf_kparams_s { | typedef struct decaf_kparams_s { | ||||
| uint8_t position, flags, rate, start_round, pad, rate_pad, max_out, client; /* client = max_outRemaining for decaf_sha3 */ | |||||
| } decaf_kparams_t[1]; | |||||
| uint8_t position, flags, rate, start_round, pad, rate_pad, max_out, remaining; | |||||
| } decaf_kparams_s, decaf_kparams_t[1]; | |||||
| typedef struct decaf_keccak_sponge_s { | typedef struct decaf_keccak_sponge_s { | ||||
| kdomain_t state; | kdomain_t state; | ||||
| @@ -1,222 +0,0 @@ | |||||
| /** | |||||
| * @cond internal | |||||
| * @brief Example Decaf crypto routines | |||||
| */ | |||||
| #include <decaf/crypto.h> | |||||
| #include <string.h> | |||||
| #define API_NAME "$(c_ns)" | |||||
| #define API_NS(_id) $(c_ns)_##_id | |||||
| #define API_NS_TOY(_id) $(c_ns)_TOY_##_id | |||||
| #define SCALAR_BITS $(C_NS)_SCALAR_BITS | |||||
| #define SCALAR_BYTES ((SCALAR_BITS + 7)/8) | |||||
| #define SER_BYTES $(C_NS)_SER_BYTES | |||||
| /* TODO: canonicalize and freeze the STROBE constants in this file | |||||
| * (and STROBE itself for that matter) | |||||
| */ | |||||
| static const char *DERIVE_MAGIC = API_NAME"::derive_private_key"; | |||||
| static const char *SIGN_MAGIC = API_NAME"::sign"; | |||||
| static const char *SHARED_SECRET_MAGIC = API_NAME"::shared_secret"; | |||||
| static const uint16_t SHARED_SECRET_MAX_BLOCK_SIZE = 1<<12; | |||||
| static const unsigned int SCALAR_OVERKILL_BYTES = SCALAR_BYTES + 8; | |||||
| void API_NS_TOY(derive_private_key) ( | |||||
| API_NS_TOY(private_key_t) priv, | |||||
| const API_NS_TOY(symmetric_key_t) proto | |||||
| ) { | |||||
| uint8_t encoded_scalar[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) pub; | |||||
| keccak_decaf_TOY_strobe_t strobe; | |||||
| decaf_TOY_strobe_init(strobe, &STROBE_256, DERIVE_MAGIC, 0); | |||||
| decaf_TOY_strobe_fixed_key(strobe, proto, sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| decaf_TOY_strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar)); | |||||
| decaf_TOY_strobe_destroy(strobe); | |||||
| memcpy(priv->sym, proto, sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| API_NS(scalar_decode_long)(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar)); | |||||
| API_NS(precomputed_scalarmul)(pub, API_NS(precomputed_base), priv->secret_scalar); | |||||
| API_NS(point_encode)(priv->pub, pub); | |||||
| decaf_bzero(encoded_scalar, sizeof(encoded_scalar)); | |||||
| } | |||||
| void API_NS_TOY(destroy_private_key) ( | |||||
| API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| decaf_bzero((void*)priv, sizeof(API_NS_TOY(private_key_t))); | |||||
| } | |||||
| void API_NS_TOY(private_to_public) ( | |||||
| API_NS_TOY(public_key_t) pub, | |||||
| const API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| memcpy(pub, priv->pub, sizeof(API_NS_TOY(public_key_t))); | |||||
| } | |||||
| /* Performance vs consttime tuning. | |||||
| * Specifying true here might give better DOS resistance in certain corner | |||||
| * cases. Specifying false gives a tighter result in test_ct. | |||||
| */ | |||||
| #ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
| #define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE | |||||
| #endif | |||||
| decaf_error_t API_NS_TOY(shared_secret) ( | |||||
| uint8_t *shared, | |||||
| size_t shared_bytes, | |||||
| const API_NS_TOY(private_key_t) my_privkey, | |||||
| const API_NS_TOY(public_key_t) your_pubkey, | |||||
| int me_first | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t strobe; | |||||
| decaf_TOY_strobe_init(strobe, &STROBE_256, SHARED_SECRET_MAGIC, 0); | |||||
| uint8_t ss_ser[SER_BYTES]; | |||||
| if (me_first) { | |||||
| decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t))); | |||||
| decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t))); | |||||
| } else { | |||||
| decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t))); | |||||
| decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t))); | |||||
| } | |||||
| decaf_error_t ret = API_NS(direct_scalarmul)( | |||||
| ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, | |||||
| DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
| ); | |||||
| decaf_TOY_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; | |||||
| decaf_TOY_strobe_prng(strobe,shared,cando); | |||||
| shared_bytes -= cando; | |||||
| shared += cando; | |||||
| } | |||||
| decaf_TOY_strobe_destroy(strobe); | |||||
| decaf_bzero(ss_ser, sizeof(ss_ser)); | |||||
| return ret; | |||||
| } | |||||
| void API_NS_TOY(sign_strobe) ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(private_key_t) priv | |||||
| ) { | |||||
| uint8_t overkill[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) point; | |||||
| API_NS(scalar_t) nonce, challenge; | |||||
| /* Stir pubkey */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,priv->pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK); | |||||
| /* Derive nonce */ | |||||
| keccak_decaf_TOY_strobe_t strobe2; | |||||
| memcpy(strobe2,strobe,sizeof(strobe2)); | |||||
| decaf_TOY_strobe_fixed_key(strobe2,priv->sym,sizeof(API_NS_TOY(symmetric_key_t))); | |||||
| decaf_TOY_strobe_prng(strobe2,overkill,sizeof(overkill)); | |||||
| decaf_TOY_strobe_destroy(strobe2); | |||||
| API_NS(scalar_decode_long)(nonce, overkill, sizeof(overkill)); | |||||
| API_NS(precomputed_scalarmul)(point, API_NS(precomputed_base), nonce); | |||||
| API_NS(point_encode)(sig, point); | |||||
| /* Derive challenge */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH); | |||||
| decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL); | |||||
| API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill)); | |||||
| /* Respond */ | |||||
| API_NS(scalar_mul)(challenge, challenge, priv->secret_scalar); | |||||
| API_NS(scalar_sub)(nonce, nonce, challenge); | |||||
| /* Save results */ | |||||
| API_NS(scalar_encode)(overkill, nonce); | |||||
| decaf_TOY_strobe_transact(strobe,&sig[SER_BYTES],overkill,SCALAR_BYTES,STROBE_CW_SIG_RESP); | |||||
| /* Clean up */ | |||||
| API_NS(scalar_destroy)(nonce); | |||||
| API_NS(scalar_destroy)(challenge); | |||||
| decaf_bzero(overkill,sizeof(overkill)); | |||||
| } | |||||
| decaf_error_t API_NS_TOY(verify_strobe) ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(public_key_t) pub | |||||
| ) { | |||||
| decaf_bool_t ret; | |||||
| uint8_t overkill[SCALAR_OVERKILL_BYTES]; | |||||
| API_NS(point_t) point, pubpoint; | |||||
| API_NS(scalar_t) challenge, response; | |||||
| /* Stir pubkey */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK); | |||||
| /* Derive nonce */ | |||||
| decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH); | |||||
| ret = decaf_successful( API_NS(point_decode)(point, sig, DECAF_TRUE) ); | |||||
| /* Derive challenge */ | |||||
| decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL); | |||||
| API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill)); | |||||
| /* Decode response */ | |||||
| decaf_TOY_strobe_transact(strobe,overkill,&sig[SER_BYTES],SCALAR_BYTES,STROBE_CW_SIG_RESP); | |||||
| ret &= decaf_successful( API_NS(scalar_decode)(response, overkill) ); | |||||
| ret &= decaf_successful( API_NS(point_decode)(pubpoint, pub, DECAF_FALSE) ); | |||||
| API_NS(base_double_scalarmul_non_secret) ( | |||||
| pubpoint, response, pubpoint, challenge | |||||
| ); | |||||
| ret &= API_NS(point_eq)(pubpoint, point); | |||||
| /* Nothing here is secret, so don't do these things: | |||||
| decaf_bzero(overkill,sizeof(overkill)); | |||||
| API_NS(point_destroy)(point); | |||||
| API_NS(point_destroy)(pubpoint); | |||||
| API_NS(scalar_destroy)(challenge); | |||||
| API_NS(scalar_destroy)(response); | |||||
| */ | |||||
| return decaf_succeed_if(ret); | |||||
| } | |||||
| void | |||||
| API_NS_TOY(sign) ( | |||||
| API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(private_key_t) priv, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t ctx; | |||||
| decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0); | |||||
| decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT); | |||||
| API_NS_TOY(sign_strobe)(ctx, sig, priv); | |||||
| decaf_TOY_strobe_destroy(ctx); | |||||
| } | |||||
| decaf_error_t | |||||
| API_NS_TOY(verify) ( | |||||
| const API_NS_TOY(signature_t) sig, | |||||
| const API_NS_TOY(public_key_t) pub, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) { | |||||
| keccak_decaf_TOY_strobe_t ctx; | |||||
| decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0); | |||||
| decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT); | |||||
| decaf_error_t ret = API_NS_TOY(verify_strobe)(ctx, sig, pub); | |||||
| decaf_TOY_strobe_destroy(ctx); | |||||
| return ret; | |||||
| } | |||||
| @@ -1,163 +0,0 @@ | |||||
| /** | |||||
| * 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. | |||||
| */ | |||||
| #include <decaf/point_$(gf_bits).h> | |||||
| #include <decaf/strobe.h> | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #endif | |||||
| /** Number of bytes for a symmetric key (expanded to full key) */ | |||||
| #define $(C_NS)_SYMMETRIC_KEY_BYTES 32 | |||||
| /** A symmetric key, the compressed point of a private key. */ | |||||
| typedef unsigned char $(c_ns)_TOY_symmetric_key_t[$(C_NS)_SYMMETRIC_KEY_BYTES]; | |||||
| /** An encoded public key. */ | |||||
| typedef unsigned char $(c_ns)_TOY_public_key_t[$(C_NS)_SER_BYTES]; | |||||
| /** A signature. */ | |||||
| typedef unsigned char $(c_ns)_TOY_signature_t[$(C_NS)_SER_BYTES + $(C_NS)_SCALAR_BYTES]; | |||||
| typedef struct { | |||||
| /** @cond internal */ | |||||
| /** The symmetric key from which everything is expanded */ | |||||
| $(c_ns)_TOY_symmetric_key_t sym; | |||||
| /** The scalar x */ | |||||
| $(c_ns)_scalar_t secret_scalar; | |||||
| /** x*Base */ | |||||
| $(c_ns)_TOY_public_key_t pub; | |||||
| /** @endcond */ | |||||
| } /** Private key structure for pointers. */ | |||||
| $(c_ns)_TOY_private_key_s, | |||||
| /** A private key (gmp array[1] style). */ | |||||
| $(c_ns)_TOY_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)_TOY_derive_private_key ( | |||||
| $(c_ns)_TOY_private_key_t priv, | |||||
| const $(c_ns)_TOY_symmetric_key_t proto | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * Destroy a private key. | |||||
| */ | |||||
| void $(c_ns)_TOY_destroy_private_key ( | |||||
| $(c_ns)_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * Convert a private key to a public one. | |||||
| * @param [out] pub The extracted private key. | |||||
| * @param [in] priv The private key. | |||||
| */ | |||||
| void $(c_ns)_TOY_private_to_public ( | |||||
| $(c_ns)_TOY_public_key_t pub, | |||||
| const $(c_ns)_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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 | |||||
| $(c_ns)_TOY_shared_secret ( | |||||
| uint8_t *shared, | |||||
| size_t shared_bytes, | |||||
| const $(c_ns)_TOY_private_key_t my_privkey, | |||||
| const $(c_ns)_TOY_public_key_t your_pubkey, | |||||
| int me_first | |||||
| ) NONNULL WARN_UNUSED API_VIS; | |||||
| /** | |||||
| * 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 | |||||
| $(c_ns)_TOY_sign_strobe ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| $(c_ns)_TOY_signature_t sig, | |||||
| const $(c_ns)_TOY_private_key_t priv | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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 | |||||
| $(c_ns)_TOY_sign ( | |||||
| $(c_ns)_TOY_signature_t sig, | |||||
| const $(c_ns)_TOY_private_key_t priv, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) NONNULL API_VIS; | |||||
| /** | |||||
| * 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 | |||||
| $(c_ns)_TOY_verify_strobe ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const $(c_ns)_TOY_signature_t sig, | |||||
| const $(c_ns)_TOY_public_key_t pub | |||||
| ) NONNULL API_VIS WARN_UNUSED; | |||||
| /** | |||||
| * 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 | |||||
| $(c_ns)_TOY_verify ( | |||||
| const $(c_ns)_TOY_signature_t sig, | |||||
| const $(c_ns)_TOY_public_key_t pub, | |||||
| const unsigned char *message, | |||||
| size_t message_len | |||||
| ) NONNULL API_VIS WARN_UNUSED; | |||||
| #ifdef __cplusplus | |||||
| } /* extern "C" */ | |||||
| #endif | |||||
| @@ -1,199 +0,0 @@ | |||||
| /* | |||||
| * 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. | |||||
| */ | |||||
| #include <decaf/point_$(gf_bits).hxx> | |||||
| #include <decaf/shake.hxx> | |||||
| #include <decaf/strobe.hxx> | |||||
| /** @cond internal */ | |||||
| #if __cplusplus >= 201103L | |||||
| #define NOEXCEPT noexcept | |||||
| #else | |||||
| #define NOEXCEPT throw() | |||||
| #endif | |||||
| /** @endcond */ | |||||
| namespace decaf { namespace TOY { | |||||
| /** A public key for crypto over some Group */ | |||||
| 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) */ | |||||
| template<> class PublicKey<$(cxx_ns)> | |||||
| : public Serializable< PublicKey<$(cxx_ns)> > { | |||||
| private: | |||||
| /** @cond internal */ | |||||
| typedef $(c_ns)_TOY_public_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PrivateKey; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** Underlying group */ | |||||
| typedef $(cxx_ns) Group; | |||||
| /** Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof($(c_ns)_TOY_signature_t); | |||||
| /** Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PublicKey(const PrivateKey<$(cxx_ns)> &b) NOEXCEPT; | |||||
| /** Create but don't initialize */ | |||||
| inline explicit PublicKey(const NOINIT&) NOEXCEPT { } | |||||
| /** Serialize into a buffer. */ | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** Serialization size. */ | |||||
| inline size_t ser_size() const NOEXCEPT { return SER_BYTES; } | |||||
| /** Verify a message */ | |||||
| inline void verify( | |||||
| const Block &message, | |||||
| const FixedBlock<SIG_BYTES> &sig | |||||
| ) const throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != $(c_ns)_TOY_verify(sig.data(),wrapped,message.data(),message.size())) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| } | |||||
| /** Verify a message */ | |||||
| inline void verify( | |||||
| Strobe &context, | |||||
| const FixedBlock<SIG_BYTES> &sig | |||||
| ) const throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != $(c_ns)_TOY_verify_strobe(context.wrapped,sig.data(),wrapped)) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| } | |||||
| }; | |||||
| /** A private key for crypto over $(name) */ | |||||
| template<> class PrivateKey<$(cxx_ns)> | |||||
| : public Serializable< PrivateKey<$(cxx_ns)> > { | |||||
| private: | |||||
| /** @cond internal */ | |||||
| typedef $(c_ns)_TOY_private_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PublicKey; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** Underlying group */ | |||||
| typedef $(cxx_ns) Group; | |||||
| /** Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof($(c_ns)_TOY_signature_t); | |||||
| /** Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /** Compressed size. */ | |||||
| static const size_t SYM_BYTES = $(C_NS)_SYMMETRIC_KEY_BYTES; | |||||
| /** Create but don't initialize */ | |||||
| inline explicit PrivateKey(const NOINIT&) NOEXCEPT { } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT { | |||||
| $(c_ns)_TOY_derive_private_key(wrapped, b.data()); | |||||
| } | |||||
| /** Create at random */ | |||||
| inline explicit PrivateKey(Rng &r) NOEXCEPT { | |||||
| FixedArrayBuffer<SYM_BYTES> tmp(r); | |||||
| $(c_ns)_TOY_derive_private_key(wrapped, tmp.data()); | |||||
| } | |||||
| /** Secure destructor */ | |||||
| inline ~PrivateKey() NOEXCEPT { | |||||
| $(c_ns)_TOY_destroy_private_key(wrapped); | |||||
| } | |||||
| /** Serialization size. */ | |||||
| inline size_t ser_size() const NOEXCEPT { return SER_BYTES; } | |||||
| /** Serialize into a buffer. */ | |||||
| inline void serialize_into(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** Compressed serialize. */ | |||||
| inline SecureBuffer compress() const throw(std::bad_alloc) { | |||||
| SecureBuffer ret(sizeof(wrapped->sym)); | |||||
| memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym)); | |||||
| return ret; | |||||
| } | |||||
| /** Get the public key */ | |||||
| inline PublicKey<$(cxx_ns)> pub() const NOEXCEPT { | |||||
| PublicKey<$(cxx_ns)> ret(*this); return ret; | |||||
| } | |||||
| /** Derive a shared secret */ | |||||
| inline SecureBuffer shared_secret( | |||||
| 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)_TOY_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| /** Derive a shared secret */ | |||||
| inline decaf_error_t __attribute__((warn_unused_result)) | |||||
| shared_secret_noexcept( | |||||
| Buffer ret, | |||||
| const PublicKey<$(cxx_ns)> &pub, | |||||
| bool me_first | |||||
| ) const NOEXCEPT { | |||||
| return $(c_ns)_TOY_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)_TOY_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)_TOY_sign_strobe(context.wrapped, sig.data(), wrapped); | |||||
| return sig; | |||||
| } | |||||
| }; | |||||
| /** @cond internal */ | |||||
| PublicKey<$(cxx_ns)>::PublicKey(const PrivateKey<$(cxx_ns)> &b) NOEXCEPT { | |||||
| $(c_ns)_TOY_private_to_public(wrapped,b.wrapped); | |||||
| } | |||||
| /** @endcond */ | |||||
| #undef NOEXCEPT | |||||
| }} /* namespace decaf::TOY */ | |||||
| @@ -119,10 +119,10 @@ decaf_error_t decaf_sha3_output ( | |||||
| assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); | assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); | ||||
| if (decaf_sponge->params->max_out != 0xFF) { | if (decaf_sponge->params->max_out != 0xFF) { | ||||
| if (decaf_sponge->params->client >= len) { | |||||
| decaf_sponge->params->client -= len; | |||||
| if (decaf_sponge->params->remaining >= len) { | |||||
| decaf_sponge->params->remaining -= len; | |||||
| } else { | } else { | ||||
| decaf_sponge->params->client = 0; | |||||
| decaf_sponge->params->remaining = 0; | |||||
| ret = DECAF_FAILURE; | ret = DECAF_FAILURE; | ||||
| } | } | ||||
| } | } | ||||
| @@ -172,7 +172,7 @@ void decaf_sha3_reset ( | |||||
| decaf_keccak_sponge_t decaf_sponge | decaf_keccak_sponge_t decaf_sponge | ||||
| ) { | ) { | ||||
| decaf_sponge_init(decaf_sponge, decaf_sponge->params); | decaf_sponge_init(decaf_sponge, decaf_sponge->params); | ||||
| decaf_sponge->params->client = decaf_sponge->params->max_out; | |||||
| decaf_sponge->params->remaining = decaf_sponge->params->max_out; | |||||
| } | } | ||||
| void decaf_sponge_destroy (decaf_keccak_sponge_t decaf_sponge) { decaf_bzero(decaf_sponge, sizeof(decaf_keccak_sponge_t)); } | void decaf_sponge_destroy (decaf_keccak_sponge_t decaf_sponge) { decaf_bzero(decaf_sponge, sizeof(decaf_keccak_sponge_t)); } | ||||
| @@ -0,0 +1,164 @@ | |||||
| /** | |||||
| * @cond internal | |||||
| * @file spongerng.c | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2017 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * @author Mike Hamburg | |||||
| * @brief Spongerng instances (STROBE removed) | |||||
| * @warning The SpongeRNG code isn't stable. Future versions are likely to | |||||
| * have different outputs. Of course, this only matters in deterministic mode. | |||||
| */ | |||||
| #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ | |||||
| #include <assert.h> | |||||
| #include <stdint.h> | |||||
| #include <string.h> | |||||
| #include "keccak_internal.h" | |||||
| #include <decaf/spongerng.h> | |||||
| /* to open and read from /dev/urandom */ | |||||
| #include <sys/types.h> | |||||
| #include <sys/stat.h> | |||||
| #include <fcntl.h> | |||||
| #include <unistd.h> | |||||
| /** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */ | |||||
| static void get_cpu_entropy(uint8_t *entropy, size_t len) { | |||||
| # if (defined(__i386__) || defined(__x86_64__)) | |||||
| static char tested = 0, have_rdrand = 0; | |||||
| if (!tested) { | |||||
| uint32_t a,b,c,d; | |||||
| a=1; __asm__("cpuid" : "+a"(a), "=b"(b), "=c"(c), "=d"(d)); | |||||
| have_rdrand = (c>>30)&1; | |||||
| tested = 1; | |||||
| } | |||||
| if (have_rdrand) { | |||||
| # if defined(__x86_64__) | |||||
| uint64_t out, a=0, *eo = (uint64_t *)entropy; | |||||
| # elif defined(__i386__) | |||||
| uint32_t out, a=0, *eo = (uint32_t *)entropy; | |||||
| #endif | |||||
| len /= sizeof(out); | |||||
| uint32_t tries; | |||||
| for (tries = 100+len; tries && len; len--, eo++) { | |||||
| for (a = 0; tries && !a; tries--) { | |||||
| __asm__ __volatile__ ("rdrand %0\n\tsetc %%al" : "=r"(out), "+a"(a) :: "cc" ); | |||||
| } | |||||
| *eo ^= out; | |||||
| } | |||||
| } else if (len>=8) { | |||||
| #ifndef __has_builtin | |||||
| #define __has_builtin(X) 0 | |||||
| #endif | |||||
| #if defined(__clang__) && __has_builtin(__builtin_readcyclecounter) | |||||
| *(uint64_t*) entropy ^= __builtin_readcyclecounter(); | |||||
| #elif defined(__x86_64__) | |||||
| uint32_t lobits, hibits; | |||||
| __asm__ __volatile__ ("rdtsc" : "=a"(lobits), "=d"(hibits)); | |||||
| *(uint64_t*) entropy ^= (lobits | ((uint64_t)(hibits) << 32)); | |||||
| #elif defined(__i386__) | |||||
| uint64_t __value; | |||||
| __asm__ __volatile__ ("rdtsc" : "=A"(__value)); | |||||
| *(uint64_t*) entropy ^= __value; | |||||
| #endif | |||||
| } | |||||
| #else | |||||
| (void) entropy; | |||||
| (void) len; | |||||
| #endif | |||||
| } | |||||
| void decaf_spongerng_next ( | |||||
| decaf_keccak_prng_t prng, | |||||
| uint8_t * __restrict__ out, | |||||
| size_t len | |||||
| ) { | |||||
| if (prng->sponge->params->remaining) { | |||||
| /* nondet */ | |||||
| uint8_t cpu_entropy[32]; | |||||
| get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy)); | |||||
| decaf_spongerng_stir(prng,cpu_entropy,sizeof(cpu_entropy)); | |||||
| decaf_bzero(cpu_entropy,sizeof(cpu_entropy)); | |||||
| } | |||||
| uint8_t lenx[8]; | |||||
| size_t len1 = len; | |||||
| for (unsigned i=0; i<sizeof(lenx); i++) { | |||||
| lenx[i] = len1; | |||||
| len1 >>= 8; | |||||
| } | |||||
| decaf_sha3_update(prng->sponge,lenx,sizeof(lenx)); | |||||
| decaf_sha3_output(prng->sponge,out,len); | |||||
| const uint8_t nope; | |||||
| decaf_spongerng_stir(prng,&nope,0); | |||||
| } | |||||
| void decaf_spongerng_stir ( | |||||
| decaf_keccak_prng_t prng, | |||||
| const uint8_t * __restrict__ in, | |||||
| size_t len | |||||
| ) { | |||||
| uint8_t seed[32]; | |||||
| decaf_sha3_output(prng->sponge,seed,sizeof(seed)); | |||||
| uint8_t nondet = prng->sponge->params->remaining; | |||||
| decaf_sha3_reset(prng->sponge); | |||||
| decaf_sha3_update(prng->sponge,seed,sizeof(seed)); | |||||
| decaf_sha3_update(prng->sponge,in,len); | |||||
| prng->sponge->params->remaining = nondet; | |||||
| decaf_bzero(seed,sizeof(seed)); | |||||
| } | |||||
| void decaf_spongerng_init_from_buffer ( | |||||
| decaf_keccak_prng_t prng, | |||||
| const uint8_t * __restrict__ in, | |||||
| size_t len, | |||||
| int deterministic | |||||
| ) { | |||||
| decaf_sponge_init(prng->sponge,&DECAF_SHAKE256_params_s); | |||||
| prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */ | |||||
| decaf_spongerng_stir(prng, in, len); | |||||
| } | |||||
| decaf_error_t decaf_spongerng_init_from_file ( | |||||
| decaf_keccak_prng_t prng, | |||||
| const char *file, | |||||
| size_t len, | |||||
| int deterministic | |||||
| ) { | |||||
| decaf_sponge_init(prng->sponge,&DECAF_SHAKE256_params_s); | |||||
| prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */ | |||||
| if (!len) return DECAF_FAILURE; | |||||
| int fd = open(file, O_RDONLY); | |||||
| if (fd < 0) return DECAF_FAILURE; | |||||
| uint8_t buffer[128]; | |||||
| while (len) { | |||||
| ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len); | |||||
| if (red <= 0) { | |||||
| close(fd); | |||||
| return DECAF_FAILURE; | |||||
| } | |||||
| decaf_sha3_update(prng->sponge,buffer,red); | |||||
| len -= red; | |||||
| }; | |||||
| close(fd); | |||||
| const uint8_t nope; | |||||
| decaf_spongerng_stir(prng,&nope,0); | |||||
| return DECAF_SUCCESS; | |||||
| } | |||||
| decaf_error_t decaf_spongerng_init_from_dev_urandom ( | |||||
| decaf_keccak_prng_t decaf_sponge | |||||
| ) { | |||||
| return decaf_spongerng_init_from_file(decaf_sponge, "/dev/urandom", 64, 0); | |||||
| } | |||||
| @@ -1,412 +0,0 @@ | |||||
| /** | |||||
| * @cond internal | |||||
| * @file strobe.c | |||||
| * @copyright | |||||
| * Copyright (c) 2015-2016 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * @author Mike Hamburg | |||||
| * @brief STROBE and spongerng instances. | |||||
| * @warning All APIs in here are toys. They will change behavior and probably also API. | |||||
| * Do not use them for anything serious. | |||||
| */ | |||||
| #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ | |||||
| #include <assert.h> | |||||
| #include <stdint.h> | |||||
| #include <string.h> | |||||
| #include "keccak_internal.h" | |||||
| #include <decaf/strobe.h> | |||||
| #include <decaf/spongerng.h> | |||||
| /* to open and read from /dev/urandom */ | |||||
| #include <sys/types.h> | |||||
| #include <sys/stat.h> | |||||
| #include <fcntl.h> | |||||
| #include <unistd.h> | |||||
| /** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */ | |||||
| static void get_cpu_entropy(uint8_t *entropy, size_t len) { | |||||
| # if (defined(__i386__) || defined(__x86_64__)) | |||||
| static char tested = 0, have_rdrand = 0; | |||||
| if (!tested) { | |||||
| uint32_t a,b,c,d; | |||||
| a=1; __asm__("cpuid" : "+a"(a), "=b"(b), "=c"(c), "=d"(d)); | |||||
| have_rdrand = (c>>30)&1; | |||||
| tested = 1; | |||||
| } | |||||
| if (have_rdrand) { | |||||
| # if defined(__x86_64__) | |||||
| uint64_t out, a=0, *eo = (uint64_t *)entropy; | |||||
| # elif defined(__i386__) | |||||
| uint32_t out, a=0, *eo = (uint32_t *)entropy; | |||||
| #endif | |||||
| len /= sizeof(out); | |||||
| uint32_t tries; | |||||
| for (tries = 100+len; tries && len; len--, eo++) { | |||||
| for (a = 0; tries && !a; tries--) { | |||||
| __asm__ __volatile__ ("rdrand %0\n\tsetc %%al" : "=r"(out), "+a"(a) :: "cc" ); | |||||
| } | |||||
| *eo ^= out; | |||||
| } | |||||
| } else if (len>=8) { | |||||
| #ifndef __has_builtin | |||||
| #define __has_builtin(X) 0 | |||||
| #endif | |||||
| #if defined(__clang__) && __has_builtin(__builtin_readcyclecounter) | |||||
| *(uint64_t*) entropy ^= __builtin_readcyclecounter(); | |||||
| #elif defined(__x86_64__) | |||||
| uint32_t lobits, hibits; | |||||
| __asm__ __volatile__ ("rdtsc" : "=a"(lobits), "=d"(hibits)); | |||||
| *(uint64_t*) entropy ^= (lobits | ((uint64_t)(hibits) << 32)); | |||||
| #elif defined(__i386__) | |||||
| uint64_t __value; | |||||
| __asm__ __volatile__ ("rdtsc" : "=A"(__value)); | |||||
| *(uint64_t*) entropy ^= __value; | |||||
| #endif | |||||
| } | |||||
| #else | |||||
| (void) entropy; | |||||
| (void) len; | |||||
| #endif | |||||
| } | |||||
| static const char *SPONGERNG_NAME = "strobe::decaf_spongerng"; /* TODO: canonicalize name */ | |||||
| void decaf_spongerng_next ( | |||||
| decaf_keccak_prng_t prng, | |||||
| uint8_t * __restrict__ out, | |||||
| size_t len | |||||
| ) { | |||||
| decaf_keccak_sponge_s *decaf_sponge = prng->sponge; | |||||
| if (decaf_sponge->params->client) { | |||||
| /* nondet */ | |||||
| uint8_t cpu_entropy[32]; | |||||
| get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy)); | |||||
| decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_sponge,NULL,cpu_entropy,sizeof(cpu_entropy),STROBE_CW_PRNG_CPU_SEED); | |||||
| } | |||||
| decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_sponge,out,NULL,len,STROBE_CW_PRNG); | |||||
| } | |||||
| void decaf_spongerng_stir ( | |||||
| decaf_keccak_prng_t decaf_sponge, | |||||
| const uint8_t * __restrict__ in, | |||||
| size_t len | |||||
| ) { | |||||
| decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_sponge,NULL,in,len,STROBE_CW_PRNG_USER_SEED); | |||||
| } | |||||
| static const struct decaf_kparams_s decaf_spongerng_params = { | |||||
| 0, 0, 200-256/4, 0, 0x06, 0x80, 0xFF, 0 | |||||
| }; | |||||
| void decaf_spongerng_init_from_buffer ( | |||||
| decaf_keccak_prng_t prng, | |||||
| const uint8_t * __restrict__ in, | |||||
| size_t len, | |||||
| int deterministic | |||||
| ) { | |||||
| decaf_keccak_sponge_s *decaf_sponge = prng->sponge; | |||||
| decaf_TOY_strobe_init((keccak_decaf_TOY_strobe_s*)decaf_sponge, &decaf_spongerng_params, SPONGERNG_NAME, !deterministic); | |||||
| decaf_spongerng_stir(prng, in, len); | |||||
| } | |||||
| decaf_error_t decaf_spongerng_init_from_file ( | |||||
| decaf_keccak_prng_t prng, | |||||
| const char *file, | |||||
| size_t len, | |||||
| int deterministic | |||||
| ) { | |||||
| decaf_keccak_sponge_s *decaf_sponge = prng->sponge; | |||||
| decaf_TOY_strobe_init((keccak_decaf_TOY_strobe_s*)decaf_sponge, &decaf_spongerng_params, SPONGERNG_NAME, !deterministic); | |||||
| if (!len) return DECAF_FAILURE; | |||||
| int fd = open(file, O_RDONLY); | |||||
| if (fd < 0) return DECAF_FAILURE; | |||||
| uint8_t buffer[128]; | |||||
| int first = 1; | |||||
| while (len) { | |||||
| ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len); | |||||
| if (red <= 0) { | |||||
| close(fd); | |||||
| return DECAF_FAILURE; | |||||
| } | |||||
| decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_sponge,NULL,buffer,red, | |||||
| first ? STROBE_CW_PRNG_USER_SEED : (STROBE_CW_PRNG_USER_SEED | STROBE_FLAG_MORE)); | |||||
| len -= red; | |||||
| first = 0; | |||||
| }; | |||||
| close(fd); | |||||
| return DECAF_SUCCESS; | |||||
| } | |||||
| decaf_error_t decaf_spongerng_init_from_dev_urandom ( | |||||
| decaf_keccak_prng_t decaf_sponge | |||||
| ) { | |||||
| return decaf_spongerng_init_from_file(decaf_sponge, "/dev/urandom", 64, 0); | |||||
| } | |||||
| const struct decaf_kparams_s STROBE_128 = { 0, 0, 200-128/4, 0, 0, 0, 0, 0 }; | |||||
| const struct decaf_kparams_s STROBE_256 = { 0, 0, 200-256/4, 0, 0, 0, 0, 0 }; | |||||
| const struct decaf_kparams_s STROBE_KEYED_256 = { 0, 0, 200-256/4, 12, 0, 0, 0, 0 }; | |||||
| const struct decaf_kparams_s STROBE_KEYED_128 = { 0, 0, 200-128/4, 12, 0, 0, 0, 0 }; | |||||
| /* Strobe is different in that its rate is padded by one byte. */ | |||||
| void decaf_TOY_strobe_init( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const struct decaf_kparams_s *params, | |||||
| const char *proto, | |||||
| uint8_t am_client | |||||
| ) { | |||||
| decaf_keccak_sponge_s *decaf_sponge = strobe->sponge; | |||||
| decaf_sponge_init(decaf_sponge,params); | |||||
| const char *a_string = "STROBE full v0.2"; | |||||
| unsigned len = strlen(a_string); | |||||
| memcpy ( | |||||
| &decaf_sponge->state->b[sizeof(decaf_sponge->state)-len], | |||||
| a_string, | |||||
| len | |||||
| ); | |||||
| decaf_TOY_strobe_transact(strobe, NULL, (const unsigned char *)proto, strlen(proto), STROBE_CW_INIT); | |||||
| decaf_sponge->state->b[decaf_sponge->params->rate+1] = 1; | |||||
| decaf_sponge->params->client = !!am_client; | |||||
| } | |||||
| static const uint8_t EXCEEDED_RATE_PAD = 0x2; | |||||
| static __inline__ uint8_t CONTROL_WORD_PAD(int cw_size) { | |||||
| assert(cw_size >= 0 && cw_size <= 31); | |||||
| return 0xC0 | cw_size; | |||||
| } | |||||
| /* PERF vectorize */ | |||||
| static void decaf_TOY_strobe_duplex ( | |||||
| struct decaf_keccak_sponge_s *__restrict__ decaf_sponge, | |||||
| unsigned char *out, | |||||
| const unsigned char *in, | |||||
| size_t len, | |||||
| mode_t mode | |||||
| ) { | |||||
| unsigned int j, r = decaf_sponge->params->rate, p = decaf_sponge->params->position; | |||||
| uint8_t* __restrict__ state = &decaf_sponge->state->b[0]; | |||||
| /* sanity */ | |||||
| assert(r < sizeof(decaf_sponge->state) && r >= p); | |||||
| switch (mode) { | |||||
| case STROBE_MODE_PLAINTEXT: | |||||
| assert(in || len==0); | |||||
| break; | |||||
| case STROBE_MODE_ABSORB: | |||||
| case STROBE_MODE_ABSORB_R: | |||||
| assert((in||len==0) && !out); | |||||
| break; | |||||
| case STROBE_MODE_DUPLEX: | |||||
| case STROBE_MODE_DUPLEX_R: | |||||
| assert((in && out) || len==0); | |||||
| break; | |||||
| case STROBE_MODE_SQUEEZE: | |||||
| case STROBE_MODE_SQUEEZE_R: | |||||
| assert((out || len==0) && !in); | |||||
| break; | |||||
| case STROBE_MODE_FORGET: | |||||
| assert(!in && !out); | |||||
| break; | |||||
| default: | |||||
| assert(0); | |||||
| } | |||||
| while(1) { | |||||
| unsigned int cando = r - p; | |||||
| unsigned int last = (cando >= len); | |||||
| if (last) { | |||||
| cando = len; | |||||
| } | |||||
| if (cando) { | |||||
| switch (mode) { | |||||
| case STROBE_MODE_PLAINTEXT: | |||||
| for (j=0; j<cando; j++) state[p+j] ^= in[j]; | |||||
| if (out) { | |||||
| assert(in != NULL); | |||||
| memcpy(out, in, cando); | |||||
| out += cando; | |||||
| } | |||||
| in += cando; | |||||
| break; | |||||
| case STROBE_MODE_ABSORB: | |||||
| for (j=0; j<cando; j++) state[p+j] ^= in[j]; | |||||
| in += cando; | |||||
| break; | |||||
| case STROBE_MODE_ABSORB_R: | |||||
| assert(in != NULL); | |||||
| memcpy(state+p, in, cando); | |||||
| in += cando; | |||||
| break; | |||||
| case STROBE_MODE_SQUEEZE: | |||||
| assert(out != NULL); | |||||
| memcpy(out, state+p, cando); | |||||
| out += cando; | |||||
| break; | |||||
| case STROBE_MODE_SQUEEZE_R: | |||||
| assert(out != NULL); | |||||
| memcpy(out, state+p, cando); | |||||
| out += cando; | |||||
| memset(state+p, 0, cando); | |||||
| break; | |||||
| case STROBE_MODE_FORGET: | |||||
| memset(state+p, 0, cando); | |||||
| break; | |||||
| case STROBE_MODE_DUPLEX: | |||||
| for (j=0; j<cando; j++) { | |||||
| state[p+j] ^= in[j]; | |||||
| out[j] = state[p+j]; | |||||
| } | |||||
| in += cando; | |||||
| out += cando; | |||||
| break; | |||||
| case STROBE_MODE_DUPLEX_R: | |||||
| for (j=0; j<cando; j++) { | |||||
| unsigned char c = in[j]; | |||||
| out[j] = c ^ state[p+j]; | |||||
| state[p+j] = c; | |||||
| } | |||||
| in += cando; | |||||
| out += cando; | |||||
| break; | |||||
| default: | |||||
| assert(0); | |||||
| }; | |||||
| } | |||||
| if (last) { | |||||
| decaf_sponge->params->position = p+len; | |||||
| return; | |||||
| } else { | |||||
| state[r] ^= EXCEEDED_RATE_PAD; | |||||
| keccakf(decaf_sponge->state, decaf_sponge->params->start_round); | |||||
| len -= cando; | |||||
| p = 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| static inline mode_t get_mode ( uint32_t cw_flags ) { | |||||
| return (mode_t)((cw_flags >> 29) & 7); | |||||
| } | |||||
| static const int STROBE_FORGET_BYTES = 32; | |||||
| static const uint8_t FLAG_NOPARSE = 1; | |||||
| void decaf_TOY_strobe_transact ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| unsigned char *out, | |||||
| const unsigned char *in, | |||||
| size_t len, | |||||
| uint32_t cw_flags | |||||
| ) { | |||||
| decaf_keccak_sponge_s *decaf_sponge = strobe->sponge; | |||||
| if ( (cw_flags & STROBE_FLAG_NONDIR) == 0 | |||||
| /* extraneous nots to change ints to bools :-/ */ | |||||
| && !(cw_flags & STROBE_FLAG_RECV) != !(decaf_sponge->params->client) ) { | |||||
| cw_flags ^= STROBE_FLAG_CLIENT_SENT; | |||||
| } | |||||
| uint64_t my_len = len, len_cw = (cw_flags & STROBE_FLAG_LENGTH_64) ? 10 : 4; | |||||
| if (cw_flags & STROBE_FLAG_NO_LENGTH) { | |||||
| my_len = 0; | |||||
| } else if ((cw_flags & STROBE_FLAG_LENGTH_64)==0) { | |||||
| assert(my_len < 1<<16); | |||||
| } | |||||
| if (cw_flags & STROBE_FLAG_MORE) { | |||||
| assert(cw_flags & STROBE_FLAG_NO_LENGTH); /* FUTURE */ | |||||
| } else { | |||||
| uint8_t cwb[10] = { | |||||
| cw_flags, | |||||
| cw_flags>>8, | |||||
| my_len, | |||||
| my_len>>8, | |||||
| my_len>>16, | |||||
| my_len>>24, | |||||
| my_len>>32, | |||||
| my_len>>40, | |||||
| my_len>>48, | |||||
| my_len>>56 | |||||
| }; | |||||
| decaf_TOY_strobe_duplex(decaf_sponge, NULL, cwb, len_cw, STROBE_MODE_ABSORB_R); | |||||
| if ((cw_flags & STROBE_FLAG_RUN_F) || (decaf_sponge->params->flags & FLAG_NOPARSE)) { | |||||
| decaf_sponge->state->b[decaf_sponge->params->position] ^= CONTROL_WORD_PAD(len_cw); | |||||
| dokeccak(decaf_sponge); | |||||
| } | |||||
| decaf_sponge->params->flags &= ~FLAG_NOPARSE; | |||||
| if (cw_flags & STROBE_FLAG_NO_LENGTH) { | |||||
| decaf_sponge->params->flags |= FLAG_NOPARSE; | |||||
| } | |||||
| } | |||||
| decaf_TOY_strobe_duplex(decaf_sponge, out, in, len, get_mode(cw_flags)); | |||||
| if (cw_flags & STROBE_FLAG_FORGET) { | |||||
| uint32_t len = decaf_sponge->params->rate - decaf_sponge->params->position; | |||||
| if (len < STROBE_FORGET_BYTES + len_cw) len += decaf_sponge->params->rate; | |||||
| len -= len_cw; /* HACK */ | |||||
| if (cw_flags & STROBE_FLAG_NO_LENGTH) len = 2*STROBE_FORGET_BYTES; | |||||
| assert(!(cw_flags & STROBE_FLAG_MORE)); | |||||
| decaf_TOY_strobe_duplex( | |||||
| decaf_sponge, NULL, NULL, len, | |||||
| STROBE_MODE_FORGET | |||||
| ); | |||||
| } | |||||
| } | |||||
| decaf_error_t decaf_TOY_strobe_verify_auth ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const unsigned char *in, | |||||
| uint16_t len | |||||
| ) { | |||||
| decaf_keccak_sponge_s *decaf_sponge = strobe->sponge; | |||||
| if (len > decaf_sponge->params->rate) return DECAF_FAILURE; | |||||
| decaf_TOY_strobe_transact(strobe, NULL, in, len, decaf_TOY_strobe_cw_recv(STROBE_CW_MAC)); | |||||
| int32_t residue = 0; | |||||
| int i; | |||||
| for (i=0; i<len; i++) { | |||||
| residue |= decaf_sponge->state->b[i]; | |||||
| } | |||||
| return decaf_succeed_if((residue-1)>>8); | |||||
| } | |||||
| void decaf_TOY_strobe_respec ( | |||||
| keccak_decaf_TOY_strobe_t strobe, | |||||
| const struct decaf_kparams_s *params | |||||
| ) { | |||||
| decaf_keccak_sponge_s *decaf_sponge = strobe->sponge; | |||||
| uint8_t in[] = { params->rate, params->start_round }; | |||||
| decaf_TOY_strobe_transact( strobe, NULL, in, sizeof(in), STROBE_CW_RESPEC_INFO ); | |||||
| decaf_TOY_strobe_transact( strobe, NULL, NULL, 0, STROBE_CW_RESPEC ); | |||||
| assert(decaf_sponge->params->position == 0); | |||||
| decaf_sponge->params->rate = params->rate; | |||||
| decaf_sponge->params->start_round = params->start_round; | |||||
| } | |||||
| @@ -12,11 +12,7 @@ | |||||
| #include <decaf.hxx> | #include <decaf.hxx> | ||||
| #include <decaf/shake.hxx> | #include <decaf/shake.hxx> | ||||
| #include <decaf/sha512.hxx> | #include <decaf/sha512.hxx> | ||||
| #include <decaf/strobe.hxx> | |||||
| #include <decaf/spongerng.hxx> | #include <decaf/spongerng.hxx> | ||||
| #include <decaf/crypto_255.h> | |||||
| #include <decaf/crypto_448.h> | |||||
| #include <decaf/crypto.hxx> | |||||
| #include <decaf/eddsa.hxx> | #include <decaf/eddsa.hxx> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <sys/time.h> | #include <sys/time.h> | ||||
| @@ -26,7 +22,6 @@ | |||||
| #include <algorithm> | #include <algorithm> | ||||
| using namespace decaf; | using namespace decaf; | ||||
| using namespace decaf::TOY; | |||||
| static __inline__ void __attribute__((unused)) ignore_result ( int result ) { (void)result; } | static __inline__ void __attribute__((unused)) ignore_result ( int result ) { (void)result; } | ||||
| @@ -157,146 +152,6 @@ typedef typename Group::Scalar Scalar; | |||||
| typedef typename Group::Point Point; | typedef typename Group::Point Point; | ||||
| typedef typename Group::Precomputed Precomputed; | typedef typename Group::Precomputed Precomputed; | ||||
| static void tdh ( | |||||
| SpongeRng &clientRng, | |||||
| SpongeRng &serverRng, | |||||
| Scalar x, const Block &gx, | |||||
| Scalar y, const Block &gy | |||||
| ) { | |||||
| /* "TripleDH". A bit of a hack, really: the real TripleDH | |||||
| * sends gx and gy and certs over the channel, but its goal | |||||
| * is actually the opposite of STROBE in this case: it doesn't | |||||
| * hash gx and gy into the session secret (only into the MAC | |||||
| * and AD) because of IPR concerns. | |||||
| */ | |||||
| Strobe client("example::tripleDH",Strobe::CLIENT), server("example::tripleDH",Strobe::SERVER); | |||||
| Scalar xe(clientRng); | |||||
| SecureBuffer gxe((Precomputed::base() * xe).serialize()); | |||||
| client.send_plaintext(gxe); | |||||
| server.recv_plaintext(gxe); | |||||
| Scalar ye(serverRng); | |||||
| SecureBuffer gye((Precomputed::base() * ye).serialize()); | |||||
| server.send_plaintext(gye); | |||||
| client.recv_plaintext(gye); | |||||
| Point pgxe(gxe); | |||||
| server.dh_key(pgxe*ye); | |||||
| SecureBuffer tag1 = server.produce_auth(); | |||||
| //SecureBuffer ct = server.encrypt(gy); | |||||
| server.dh_key(pgxe*y); | |||||
| SecureBuffer tag2 = server.produce_auth(); | |||||
| Point pgye(gye); | |||||
| client.dh_key(pgye*xe); | |||||
| client.verify_auth(tag1); | |||||
| client.dh_key(Point(gy) * xe); | |||||
| client.verify_auth(tag2); | |||||
| // ct = client.encrypt(gx); | |||||
| client.dh_key(pgye * x); | |||||
| tag1 = client.produce_auth(); | |||||
| client.respec(STROBE_KEYED_128); | |||||
| server.dh_key(Point(gx) * ye); | |||||
| server.verify_auth(tag1); | |||||
| server.respec(STROBE_KEYED_128); | |||||
| } | |||||
| static void fhmqv ( | |||||
| SpongeRng &clientRng, | |||||
| SpongeRng &serverRng, | |||||
| Scalar x, const Block &gx, | |||||
| Scalar y, const Block &gy | |||||
| ) { | |||||
| /* Don't use this, it's probably patented */ | |||||
| Strobe client("example::fhmqv",Strobe::CLIENT), server("example::fhmqv",Strobe::SERVER); | |||||
| Scalar xe(clientRng); | |||||
| client.send_plaintext(gx); | |||||
| server.recv_plaintext(gx); | |||||
| SecureBuffer gxe((Precomputed::base() * xe).serialize()); | |||||
| server.send_plaintext(gxe); | |||||
| client.recv_plaintext(gxe); | |||||
| Scalar ye(serverRng); | |||||
| server.send_plaintext(gy); | |||||
| client.recv_plaintext(gy); | |||||
| SecureBuffer gye((Precomputed::base() * ye).serialize()); | |||||
| server.send_plaintext(gye); | |||||
| Scalar schx(server.prng(Scalar::SER_BYTES)); | |||||
| Scalar schy(server.prng(Scalar::SER_BYTES)); | |||||
| Scalar yec = y + ye*schy; | |||||
| server.dh_key(Point::double_scalarmul(Point(gx),yec,Point(gxe),yec*schx)); | |||||
| SecureBuffer as = server.produce_auth(); | |||||
| client.recv_plaintext(gye); | |||||
| Scalar cchx(client.prng(Scalar::SER_BYTES)); | |||||
| Scalar cchy(client.prng(Scalar::SER_BYTES)); | |||||
| Scalar xec = x + xe*schx; | |||||
| client.dh_key(Point::double_scalarmul(Point(gy),xec,Point(gye),xec*schy)); | |||||
| client.verify_auth(as); | |||||
| SecureBuffer ac = client.produce_auth(); | |||||
| client.respec(STROBE_KEYED_128); | |||||
| server.verify_auth(ac); | |||||
| server.respec(STROBE_KEYED_128); | |||||
| } | |||||
| static void spake2ee( | |||||
| SpongeRng &clientRng, | |||||
| SpongeRng &serverRng, | |||||
| const Block &hashed_password, | |||||
| bool aug | |||||
| ) { | |||||
| Strobe client("example::spake2ee",Strobe::CLIENT), server("example::spake2ee",Strobe::SERVER); | |||||
| Scalar x(clientRng); | |||||
| SHAKE<256> shake; | |||||
| shake.update(hashed_password); | |||||
| SecureBuffer h0 = shake.output(Point::HASH_BYTES); | |||||
| SecureBuffer h1 = shake.output(Point::HASH_BYTES); | |||||
| SecureBuffer h2 = shake.output(Scalar::SER_BYTES); | |||||
| Scalar gs(h2); | |||||
| Point hc = Point::from_hash(h0); | |||||
| hc = Point::from_hash(h0); // double-count | |||||
| Point hs = Point::from_hash(h1); | |||||
| hs = Point::from_hash(h1); // double-count | |||||
| SecureBuffer gx((Precomputed::base() * x + hc).serialize()); | |||||
| client.send_plaintext(gx); | |||||
| server.recv_plaintext(gx); | |||||
| Scalar y(serverRng); | |||||
| SecureBuffer gy((Precomputed::base() * y + hs).serialize()); | |||||
| server.send_plaintext(gy); | |||||
| client.recv_plaintext(gy); | |||||
| server.dh_key(h1); | |||||
| server.dh_key((Point(gx) - hc)*y); | |||||
| if(aug) { | |||||
| /* This step isn't actually online but whatever, it's fastish */ | |||||
| SecureBuffer serverAug((Precomputed::base() * gs).serialize()); | |||||
| server.dh_key(Point(serverAug)*y); | |||||
| } | |||||
| SecureBuffer tag = server.produce_auth(); | |||||
| client.dh_key(h1); | |||||
| Point pgy(gy); pgy -= hs; | |||||
| client.dh_key(pgy*x); | |||||
| if (aug) client.dh_key(pgy * gs); | |||||
| client.verify_auth(tag); | |||||
| tag = client.produce_auth(); | |||||
| client.respec(STROBE_KEYED_128); | |||||
| /* A real protocol would continue with fork etc here... */ | |||||
| server.verify_auth(tag); | |||||
| server.respec(STROBE_KEYED_128); | |||||
| } | |||||
| static void cfrg() { | static void cfrg() { | ||||
| SpongeRng rng(Block("bench_cfrg_crypto"),SpongeRng::DETERMINISTIC); | SpongeRng rng(Block("bench_cfrg_crypto"),SpongeRng::DETERMINISTIC); | ||||
| FixedArrayBuffer<Group::DhLadder::PUBLIC_BYTES> base(rng); | FixedArrayBuffer<Group::DhLadder::PUBLIC_BYTES> base(rng); | ||||
| @@ -318,57 +173,6 @@ static void macro() { | |||||
| printf("\nMacro-benchmarks for %s:\n", Group::name()); | printf("\nMacro-benchmarks for %s:\n", Group::name()); | ||||
| printf("CFRG crypto benchmarks:\n"); | printf("CFRG crypto benchmarks:\n"); | ||||
| cfrg(); | cfrg(); | ||||
| printf("\nToy crypto benchmarks:\n"); | |||||
| SpongeRng rng(Block("macro rng seed"),SpongeRng::DETERMINISTIC); | |||||
| PrivateKey<Group> s1((NOINIT())), s2(rng); | |||||
| PublicKey<Group> p1((NOINIT())), p2(s2); | |||||
| SecureBuffer message = rng.read(5), sig, ss; | |||||
| for (Benchmark b("Create private key",1); b.iter(); ) { | |||||
| s1 = PrivateKey<Group>(rng); | |||||
| SecureBuffer bb = s1.serialize(); | |||||
| } | |||||
| for (Benchmark b("Sign",1); b.iter(); ) { | |||||
| sig = s1.sign(message); | |||||
| } | |||||
| p1 = s1.pub(); | |||||
| for (Benchmark b("Verify",1); b.iter(); ) { | |||||
| rng.read(Buffer(message)); | |||||
| try { p1.verify(message, sig); } catch (CryptoException) {} | |||||
| } | |||||
| for (Benchmark b("SharedSecret",1); b.iter(); ) { | |||||
| ss = s1.shared_secret(p2,32,true); | |||||
| } | |||||
| printf("\nToy protocol benchmarks:\n"); | |||||
| SpongeRng clientRng(Block("client rng seed"),SpongeRng::DETERMINISTIC); | |||||
| SpongeRng serverRng(Block("server rng seed"),SpongeRng::DETERMINISTIC); | |||||
| SecureBuffer hashedPassword(Block("hello world")); | |||||
| for (Benchmark b("Spake2ee c+s",0.1); b.iter(); ) { | |||||
| spake2ee(clientRng, serverRng, hashedPassword,false); | |||||
| } | |||||
| for (Benchmark b("Spake2ee c+s aug",0.1); b.iter(); ) { | |||||
| spake2ee(clientRng, serverRng, hashedPassword,true); | |||||
| } | |||||
| Scalar x(clientRng); | |||||
| SecureBuffer gx((Precomputed::base() * x).serialize()); | |||||
| Scalar y(serverRng); | |||||
| SecureBuffer gy((Precomputed::base() * y).serialize()); | |||||
| for (Benchmark b("FHMQV c+s",0.1); b.iter(); ) { | |||||
| fhmqv(clientRng, serverRng,x,gx,y,gy); | |||||
| } | |||||
| for (Benchmark b("TripleDH anon c+s",0.1); b.iter(); ) { | |||||
| tdh(clientRng, serverRng, x,gx,y,gy); | |||||
| } | |||||
| } | } | ||||
| static void micro() { | static void micro() { | ||||
| @@ -421,29 +225,11 @@ int main(int argc, char **argv) { | |||||
| SHAKE<256> shake2; | SHAKE<256> shake2; | ||||
| SHA3<512> sha5; | SHA3<512> sha5; | ||||
| SHA512 sha2; | SHA512 sha2; | ||||
| Strobe strobe("example::bench",Strobe::CLIENT); | |||||
| unsigned char b1024[1024] = {1}; | unsigned char b1024[1024] = {1}; | ||||
| for (Benchmark b("SHAKE128 1kiB", 30); b.iter(); ) { shake1 += Buffer(b1024,1024); } | for (Benchmark b("SHAKE128 1kiB", 30); b.iter(); ) { shake1 += Buffer(b1024,1024); } | ||||
| for (Benchmark b("SHAKE256 1kiB", 30); b.iter(); ) { shake2 += Buffer(b1024,1024); } | for (Benchmark b("SHAKE256 1kiB", 30); b.iter(); ) { shake2 += Buffer(b1024,1024); } | ||||
| for (Benchmark b("SHA3-512 1kiB", 30); b.iter(); ) { sha5 += Buffer(b1024,1024); } | for (Benchmark b("SHA3-512 1kiB", 30); b.iter(); ) { sha5 += Buffer(b1024,1024); } | ||||
| for (Benchmark b("SHA512 1kiB", 30); b.iter(); ) { sha2 += Buffer(b1024,1024); } | for (Benchmark b("SHA512 1kiB", 30); b.iter(); ) { sha2 += Buffer(b1024,1024); } | ||||
| strobe.dh_key(Buffer(b1024,1024)); | |||||
| strobe.respec(STROBE_128); | |||||
| for (Benchmark b("STROBE128 1kiB", 10); b.iter(); ) { | |||||
| strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024)); | |||||
| } | |||||
| strobe.respec(STROBE_256); | |||||
| for (Benchmark b("STROBE256 1kiB", 10); b.iter(); ) { | |||||
| strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024)); | |||||
| } | |||||
| strobe.respec(STROBE_KEYED_128); | |||||
| for (Benchmark b("STROBEk128 1kiB", 10); b.iter(); ) { | |||||
| strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024)); | |||||
| } | |||||
| strobe.respec(STROBE_KEYED_256); | |||||
| for (Benchmark b("STROBEk256 1kiB", 10); b.iter(); ) { | |||||
| strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024)); | |||||
| } | |||||
| run_for_all_curves<Micro>(); | run_for_all_curves<Micro>(); | ||||
| } | } | ||||
| @@ -11,13 +11,10 @@ | |||||
| #include <decaf.hxx> | #include <decaf.hxx> | ||||
| #include <decaf/spongerng.hxx> | #include <decaf/spongerng.hxx> | ||||
| #include <decaf/crypto.h> | |||||
| #include <decaf/crypto.hxx> | |||||
| #include <decaf/eddsa.hxx> | #include <decaf/eddsa.hxx> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| using namespace decaf; | using namespace decaf; | ||||
| using namespace decaf::TOY; | |||||
| static bool passing = true; | static bool passing = true; | ||||
| static const long NTESTS = 10000; | static const long NTESTS = 10000; | ||||
| @@ -410,33 +407,6 @@ static void test_ec() { | |||||
| } | } | ||||
| } | } | ||||
| static void test_toy_crypto() { | |||||
| Test test("Toy crypto"); | |||||
| SpongeRng rng(Block("test_decaf_crypto"),SpongeRng::DETERMINISTIC); | |||||
| for (int i=0; i<NTESTS && test.passing_now; i++) { | |||||
| try { | |||||
| PrivateKey<Group> priv1(rng), priv2(rng); | |||||
| PublicKey<Group> pub1(priv1), pub2(priv2); | |||||
| SecureBuffer message = rng.read(i); | |||||
| SecureBuffer sig(priv1.sign(message)); | |||||
| pub1.verify(message, sig); | |||||
| SecureBuffer s1(priv1.shared_secret(pub2,32,true)); | |||||
| SecureBuffer s2(priv2.shared_secret(pub1,32,false)); | |||||
| if (!memeq(s1,s2)) { | |||||
| test.fail(); | |||||
| printf(" Shared secrets disagree on iteration %d.\n",i); | |||||
| } | |||||
| } catch (CryptoException) { | |||||
| test.fail(); | |||||
| printf(" Threw CryptoException.\n"); | |||||
| } | |||||
| } | |||||
| } | |||||
| static const uint8_t rfc7748_1[DhLadder::PUBLIC_BYTES]; | static const uint8_t rfc7748_1[DhLadder::PUBLIC_BYTES]; | ||||
| static const uint8_t rfc7748_1000[DhLadder::PUBLIC_BYTES]; | static const uint8_t rfc7748_1000[DhLadder::PUBLIC_BYTES]; | ||||
| static const uint8_t rfc7748_1000000[DhLadder::PUBLIC_BYTES]; | static const uint8_t rfc7748_1000000[DhLadder::PUBLIC_BYTES]; | ||||
| @@ -572,16 +542,63 @@ static void run() { | |||||
| test_eddsa(); | test_eddsa(); | ||||
| test_cfrg_crypto(); | test_cfrg_crypto(); | ||||
| test_cfrg_vectors(); | test_cfrg_vectors(); | ||||
| test_toy_crypto(); | |||||
| printf("\n"); | printf("\n"); | ||||
| } | } | ||||
| }; /* template<GroupId GROUP> struct Tests */ | }; /* template<GroupId GROUP> struct Tests */ | ||||
| static void test_rng() { | |||||
| Test test("RNG"); | |||||
| SpongeRng rng_d1(Block("test_rng"),SpongeRng::DETERMINISTIC); | |||||
| SpongeRng rng_d2(Block("test_rng"),SpongeRng::DETERMINISTIC); | |||||
| SpongeRng rng_d3(Block("best_rng"),SpongeRng::DETERMINISTIC); | |||||
| SpongeRng rng_n1; | |||||
| SpongeRng rng_n2; | |||||
| SecureBuffer s1,s2,s3; | |||||
| for (int i=0; i<5; i++) { | |||||
| s1 = rng_d1.read(16<<i); | |||||
| s2 = rng_d2.read(16<<i); | |||||
| s3 = rng_d3.read(16<<i); | |||||
| if (s1 != s2) { | |||||
| test.fail(); | |||||
| printf(" Deterministic RNG didn't match!\n"); | |||||
| } | |||||
| if (s1 == s3) { | |||||
| test.fail(); | |||||
| printf(" Deterministic matched with different data!\n"); | |||||
| } | |||||
| rng_d1.stir("hello"); | |||||
| rng_d2.stir("hello"); | |||||
| rng_d3.stir("hello"); | |||||
| s1 = rng_n1.read(16<<i); | |||||
| s2 = rng_n2.read(16<<i); | |||||
| if (s1 == s2) { | |||||
| test.fail(); | |||||
| printf(" Nondeterministic RNG matched!\n"); | |||||
| } | |||||
| } | |||||
| rng_d1.stir("hello"); | |||||
| rng_d2.stir("jello"); | |||||
| s1 = rng_d1.read(16); | |||||
| s2 = rng_d2.read(16); | |||||
| if (s1 == s2) { | |||||
| test.fail(); | |||||
| printf(" Deterministic matched with different data!\n"); | |||||
| } | |||||
| } | |||||
| #include "vectors.inc.cxx" | #include "vectors.inc.cxx" | ||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||
| (void) argc; (void) argv; | (void) argc; (void) argv; | ||||
| test_rng(); | |||||
| printf("\n"); | |||||
| run_for_all_curves<Tests>(); | run_for_all_curves<Tests>(); | ||||
| if (passing) printf("Passed all tests.\n"); | if (passing) printf("Passed all tests.\n"); | ||||
| return passing ? 0 : 1; | return passing ? 0 : 1; | ||||