Commit | Line | Data |
---|---|---|
eac0a45f MW |
1 | /* |
2 | * ed25519-test.c: test harness for elliptic curve signatures | |
3 | * | |
4 | * (The implementations originally came with different test arrangements, | |
5 | * with complicated external dependencies. This file replicates the original | |
6 | * tests, but without the dependencies.) | |
7 | */ | |
8 | /* | |
9 | * This file is Free Software. It was originally written for secnet. | |
10 | * | |
11 | * Copyright 2019 Mark Wooding | |
12 | * | |
13 | * You may redistribute secnet as a whole and/or modify it under the | |
14 | * terms of the GNU General Public License as published by the Free | |
15 | * Software Foundation; either version 3, or (at your option) any | |
16 | * later version. | |
17 | * | |
18 | * You may redistribute this file and/or modify it under the terms of | |
19 | * the GNU General Public License as published by the Free Software | |
20 | * Foundation; either version 2, or (at your option) any later | |
21 | * version. | |
22 | * | |
23 | * This software is distributed in the hope that it will be useful, | |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
26 | * GNU General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this software; if not, see | |
30 | * https://www.gnu.org/licenses/gpl.html. | |
31 | */ | |
32 | ||
33 | #include <stdio.h> | |
34 | ||
35 | #include "secnet.h" | |
36 | ||
37 | #include "sha512.h" | |
38 | #include "ed25519.h" | |
39 | ||
40 | #define GLUE(x, y) GLUE_(x, y) | |
41 | #define GLUE_(x, y) x##y | |
42 | #define XDHOP(op) GLUE(XDH, _##op) | |
43 | ||
44 | #include "crypto-test.h" | |
45 | ||
46 | enum { | |
47 | RSIGOUT, RAOUT = RSIGOUT, RRC = RSIGOUT, NROUT, | |
48 | RA = NROUT, RPH, RCTX, RM, RSIGIN, NREG | |
49 | }; | |
50 | ||
51 | static void test_pubkey(struct reg *out, const struct reg *in, void *ctx) | |
52 | { | |
53 | allocate_bytes(&out[RAOUT].v, ED25519_PUBSZ); | |
54 | ed25519_pubkey(out[RAOUT].v.bytes.p, | |
55 | in[RA].v.bytes.p, in[RA].v.bytes.sz); | |
56 | } | |
57 | ||
58 | static void test_sign(struct reg *out, const struct reg *in, void *ctx) | |
59 | { | |
60 | octet K[ED25519_PUBSZ]; | |
61 | ||
62 | allocate_bytes(&out[RSIGOUT].v, ED25519_SIGSZ); | |
63 | ed25519_pubkey(K, in[RA].v.bytes.p, in[RA].v.bytes.sz); | |
64 | ed25519_sign(out[RSIGOUT].v.bytes.p, | |
65 | in[RA].v.bytes.p, in[RA].v.bytes.sz, K, | |
66 | in[RM].v.bytes.p, in[RM].v.bytes.sz); | |
67 | } | |
68 | ||
69 | static void test_sign_ctx(struct reg *out, const struct reg *in, void *ctx) | |
70 | { | |
71 | octet K[ED25519_PUBSZ]; | |
72 | const octet *m = in[RM].v.bytes.p; size_t msz = in[RM].v.bytes.sz; | |
73 | octet h[SHA512_DIGEST_SIZE]; | |
74 | struct sha512_ctx hctx; | |
75 | ||
76 | if (in[RPH].v.i) { | |
77 | sha512_init_ctx(&hctx); | |
78 | sha512_process_bytes(m, msz, &hctx); | |
79 | sha512_finish_ctx(&hctx, h); | |
80 | m = h; msz = sizeof(h); | |
81 | } | |
82 | ||
83 | allocate_bytes(&out[RSIGOUT].v, ED25519_SIGSZ); | |
84 | ed25519_pubkey(K, in[RA].v.bytes.p, in[RA].v.bytes.sz); | |
85 | ed25519ctx_sign(out[RSIGOUT].v.bytes.p, | |
86 | in[RA].v.bytes.p, in[RA].v.bytes.sz, K, | |
87 | in[RPH].v.i, | |
88 | in[RCTX].v.bytes.p, in[RCTX].v.bytes.sz, | |
89 | m, msz); | |
90 | } | |
91 | ||
92 | static void test_verify(struct reg *out, const struct reg *in, void *ctx) | |
93 | { | |
94 | out[RRC].v.i = ed25519_verify(in[RA].v.bytes.p, | |
95 | in[RM].v.bytes.p, in[RM].v.bytes.sz, | |
96 | in[RSIGIN].v.bytes.p); | |
97 | } | |
98 | ||
99 | static void test_verify_ctx(struct reg *out, const struct reg *in, void *ctx) | |
100 | { | |
101 | const octet *m = in[RM].v.bytes.p; size_t msz = in[RM].v.bytes.sz; | |
102 | octet h[SHA512_DIGEST_SIZE]; | |
103 | struct sha512_ctx hctx; | |
104 | ||
105 | if (in[RPH].v.i) { | |
106 | sha512_init_ctx(&hctx); | |
107 | sha512_process_bytes(m, msz, &hctx); | |
108 | sha512_finish_ctx(&hctx, h); | |
109 | m = h; msz = sizeof(h); | |
110 | } | |
111 | ||
112 | out[RRC].v.i = ed25519ctx_verify(in[RA].v.bytes.p, | |
113 | in[RPH].v.i, | |
114 | in[RCTX].v.bytes.p, in[RCTX].v.bytes.sz, | |
115 | m, msz, in[RSIGIN].v.bytes.p); | |
116 | } | |
117 | ||
118 | #define REG_A { "a", RA, ®ty_bytes, 0 } | |
119 | #define REG_BIGA { "A", RA, ®ty_bytes, 0 } | |
120 | #define REG_PH { "ph", RPH, ®ty_int, 0 } | |
121 | #define REG_CTX { "ctx", RCTX, ®ty_bytes, 0 } | |
122 | #define REG_M { "m", RM, ®ty_bytes, 0 } | |
123 | #define REG_SIGIN { "sig", RSIGIN, ®ty_bytes, 0 } | |
124 | ||
125 | #define REG_SIGOUT { "sig", RSIGOUT, ®ty_bytes, 0 } | |
126 | #define REG_AOUT { "A", RAOUT, ®ty_bytes, 0 } | |
127 | #define REG_RC { "rc", RRC, ®ty_int, 0 } | |
128 | static const struct regdef | |
129 | pubkey_regs[] = { REG_A, REG_AOUT, REGLIST_END }, | |
130 | sign_regs[] = { REG_A, REG_M, REG_SIGOUT, REGLIST_END }, | |
131 | sign_ctx_regs[] = { REG_A, REG_PH, REG_CTX, | |
132 | REG_M, REG_SIGOUT, REGLIST_END }, | |
133 | verify_regs[] = { REG_BIGA, REG_M, REG_SIGIN, REG_RC, REGLIST_END }, | |
134 | verify_ctx_regs[] = { REG_BIGA, REG_PH, REG_CTX, | |
135 | REG_M, REG_SIGIN, REG_RC, REGLIST_END }; | |
136 | ||
137 | static const struct test tests[] = { | |
138 | { "pubkey", run_test, pubkey_regs, test_pubkey }, | |
139 | { "sign", run_test, sign_regs, test_sign }, | |
140 | { "sign-ctx", run_test, sign_ctx_regs, test_sign_ctx }, | |
141 | { "verify", run_test, verify_regs, test_verify }, | |
142 | { "verify-ctx", run_test, verify_ctx_regs, test_verify_ctx }, | |
143 | { 0 } | |
144 | }; | |
145 | ||
146 | int main(void) | |
147 | { return run_test_suite(NROUT, NREG, sizeof(struct reg), tests, stdin); } |