| @@ -45,7 +45,7 @@ typedef struct gf_$(gf_shortname)_s { | |||
| #define $(C_NS)_EDDSA_PRIVATE_BYTES $(C_NS)_EDDSA_PUBLIC_BYTES /* TODO: change name? */ | |||
| /** Number of bytes in an EdDSA private key. */ | |||
| #define $(C_NS)_EDDSA_SIGNATURE_BYTES ($(C_NS)_PUBLIC_BYTES + $(C_NS)_PRIVATE_BYTES) /* TODO: change name? */ | |||
| #define $(C_NS)_EDDSA_SIGNATURE_BYTES ($(C_NS)_EDDSA_PUBLIC_BYTES + $(C_NS)_EDDSA_PRIVATE_BYTES) /* TODO: change name? */ | |||
| /** Number of bytes in an x$(gf_shortname) public key */ | |||
| #define X$(gf_shortname)_PUBLIC_BYTES $((gf_bits-1)/8 + 1) | |||
| @@ -425,6 +425,29 @@ void $(c_ns)_eddsa_derive_public_key ( | |||
| uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
| const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES] | |||
| ) API_VIS NONNULL NOINLINE; | |||
| /** | |||
| * @brief EdDSA signing. | |||
| * | |||
| * @param [out] The signature. | |||
| * @param [in] privkey The private key. | |||
| * @param [in] pubkey The public key. | |||
| * @param [in] context A "context" for this signature of up to 255 bytes. | |||
| * @param [in] context_len Length of the context. | |||
| * @param [in] message The message to sign. | |||
| * @param [in] message_len The length of the message. | |||
| * @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. | |||
| */ | |||
| void $(c_ns)_eddsa_sign ( | |||
| uint8_t signature[$(C_NS)_EDDSA_SIGNATURE_BYTES], | |||
| const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES], | |||
| const uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES], | |||
| const uint8_t *context, | |||
| uint8_t context_len, | |||
| const uint8_t *message, | |||
| size_t message_len, | |||
| uint8_t prehashed | |||
| ) API_VIS NONNULL NOINLINE; | |||
| /** | |||
| * @brief EdDSA point encoding. | |||
| @@ -658,12 +658,37 @@ public: | |||
| /** The size of a private key */ | |||
| static const size_t PRIVATE_BYTES = $(C_NS)_EDDSA_PRIVATE_BYTES; | |||
| /** The size of a private key */ | |||
| static const size_t SIGNATURE_BYTES = $(C_NS)_EDDSA_SIGNATURE_BYTES; | |||
| /* TODO: make into a nice class. Change name. Possibly move to another include file. */ | |||
| static inline SecureBuffer generate_key ( | |||
| const FixedBlock<PRIVATE_BYTES> &secret | |||
| const FixedBlock<PRIVATE_BYTES> &priv | |||
| ) { | |||
| SecureBuffer out(PUBLIC_BYTES); | |||
| $(c_ns)_eddsa_derive_public_key(out.data(), secret.data()); | |||
| $(c_ns)_eddsa_derive_public_key(out.data(), priv.data()); | |||
| return out; | |||
| } | |||
| static inline SecureBuffer sign ( | |||
| const FixedBlock<PRIVATE_BYTES> &priv, | |||
| const FixedBlock<PUBLIC_BYTES> &pub, | |||
| const Block &context, | |||
| const Block &message, | |||
| bool prehashed = false | |||
| ) throw(LengthException) { | |||
| if (context.size() > 255) { throw LengthException(); } | |||
| SecureBuffer out(SIGNATURE_BYTES); | |||
| $(c_ns)_eddsa_sign ( | |||
| out.data(), | |||
| priv.data(), | |||
| pub.data(), | |||
| context.data(), | |||
| context.size(), | |||
| message.data(), | |||
| message.size(), | |||
| prehashed | |||
| ); | |||
| return out; | |||
| } | |||
| }; | |||
| @@ -456,7 +456,7 @@ static void test_cfrg_crypto() { | |||
| } | |||
| } | |||
| static const Block eddsa_sk, eddsa_pk; | |||
| static const Block eddsa_sk, eddsa_pk, eddsa_sig0; | |||
| static void test_cfrg_vectors() { | |||
| Test test("CFRG test vectors"); | |||
| @@ -465,8 +465,6 @@ static void test_cfrg_vectors() { | |||
| int the_ntests = (NTESTS < 1000000) ? 1000 : 1000000; | |||
| /* EdDSA */ | |||
| if (eddsa_sk.size()) { | |||
| SecureBuffer eddsa_pk2 = EdDSA::generate_key(eddsa_sk); | |||
| @@ -477,7 +475,19 @@ static void test_cfrg_vectors() { | |||
| for (unsigned i=0; i<eddsa_pk.size(); i++) printf("%02x", eddsa_pk[i]); | |||
| printf("\n Incorrect: "); | |||
| for (unsigned i=0; i<eddsa_pk.size(); i++) printf("%02x", eddsa_pk2[i]); | |||
| for (unsigned i=0; i<eddsa_pk2.size(); i++) printf("%02x", eddsa_pk2[i]); | |||
| printf("\n"); | |||
| } | |||
| SecureBuffer sig = EdDSA::sign(eddsa_sk,eddsa_pk,Block(NULL,0),Block(NULL,0)); | |||
| if (!memeq(SecureBuffer(eddsa_sig0),sig)) { | |||
| test.fail(); | |||
| printf(" EdDSA vectors disagree."); | |||
| printf("\n Correct: "); | |||
| for (unsigned i=0; i<eddsa_sig0.size(); i++) printf("%02x", eddsa_sig0[i]); | |||
| printf("\n Incorrect: "); | |||
| for (unsigned i=0; i<sig.size(); i++) printf("%02x", sig[i]); | |||
| printf("\n"); | |||
| } | |||
| } | |||
| @@ -619,15 +629,33 @@ const uint8_t ed448_eddsa_pk[57] = { | |||
| 0xd1,0xfa,0x1a,0xbe,0xaf,0xe8,0x25,0x61, | |||
| 0x80 | |||
| }; | |||
| const uint8_t ed448_eddsa_sig0[114] = { | |||
| 0x53,0x3a,0x37,0xf6,0xbb,0xe4,0x57,0x25, | |||
| 0x1f,0x02,0x3c,0x0d,0x88,0xf9,0x76,0xae, | |||
| 0x2d,0xfb,0x50,0x4a,0x84,0x3e,0x34,0xd2, | |||
| 0x07,0x4f,0xd8,0x23,0xd4,0x1a,0x59,0x1f, | |||
| 0x2b,0x23,0x3f,0x03,0x4f,0x62,0x82,0x81, | |||
| 0xf2,0xfd,0x7a,0x22,0xdd,0xd4,0x7d,0x78, | |||
| 0x28,0xc5,0x9b,0xd0,0xa2,0x1b,0xfd,0x39, | |||
| 0x80,0xff,0x0d,0x20,0x28,0xd4,0xb1,0x8a, | |||
| 0x9d,0xf6,0x3e,0x00,0x6c,0x5d,0x1c,0x2d, | |||
| 0x34,0x5b,0x92,0x5d,0x8d,0xc0,0x0b,0x41, | |||
| 0x04,0x85,0x2d,0xb9,0x9a,0xc5,0xc7,0xcd, | |||
| 0xda,0x85,0x30,0xa1,0x13,0xa0,0xf4,0xdb, | |||
| 0xb6,0x11,0x49,0xf0,0x5a,0x73,0x63,0x26, | |||
| 0x8c,0x71,0xd9,0x58,0x08,0xff,0x2e,0x65, | |||
| 0x26,0x00 | |||
| }; | |||
| template<> const Block Tests<Ed448Goldilocks>::eddsa_sk(ed448_eddsa_sk,57); | |||
| template<> const Block Tests<Ed448Goldilocks>::eddsa_pk(ed448_eddsa_pk,57); | |||
| template<> const Block Tests<Ed448Goldilocks>::eddsa_sig0(ed448_eddsa_sig0,114); | |||
| template<> const Block Tests<IsoEd25519>::eddsa_sk(NULL,0); /* TODO */ | |||
| template<> const Block Tests<IsoEd25519>::eddsa_pk(NULL,0); /* TODO */ | |||
| template<> const Block Tests<IsoEd25519>::eddsa_sig0(NULL,0); /* TODO */ | |||
| int main(int argc, char **argv) { | |||
| (void) argc; (void) argv; | |||
| run_for_all_curves<Tests>(); | |||
| if (passing) printf("Passed all tests.\n"); | |||
| return passing ? 0 : 1; | |||