chiark / gitweb /
@@@ testing
[secnet] / x448.c
1 /*
2  * x448.c: Hamburg's X448 key-exchange function
3  */
4 /*
5  * This file is Free Software.  It has been modified to as part of its
6  * incorporation into secnet.
7  *
8  * Copyright 2017 Mark Wooding
9  *
10  * You may redistribute this file and/or modify it under the terms of
11  * the permissive licence shown below.
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  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, see
25  * https://www.gnu.org/licenses/gpl.html.
26  */
27 /*
28  * Imported from Catacomb, and modified for Secnet (2017-04-30):
29  *
30  *   * Use `fake-mLib-bits.h' in place of the real <mLib/bits.h>.
31  *
32  *   * Remove the test rig code: a replacement is in a separate source file.
33  *
34  *   * Strip out the key-management definitions.
35  *
36  * The file's original comment headers are preserved below.
37  */
38 /* -*-c-*-
39  *
40  * The X448 key-agreement algorithm
41  *
42  * (c) 2017 Straylight/Edgeware
43  */
44
45 /*----- Licensing notice --------------------------------------------------*
46  *
47  * This file is part of Catacomb.
48  *
49  * Catacomb is free software; you can redistribute it and/or modify
50  * it under the terms of the GNU Library General Public License as
51  * published by the Free Software Foundation; either version 2 of the
52  * License, or (at your option) any later version.
53  *
54  * Catacomb is distributed in the hope that it will be useful,
55  * but WITHOUT ANY WARRANTY; without even the implied warranty of
56  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
57  * GNU Library General Public License for more details.
58  *
59  * You should have received a copy of the GNU Library General Public
60  * License along with Catacomb; if not, write to the Free
61  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
62  * MA 02111-1307, USA.
63  */
64
65 /*----- Header files ------------------------------------------------------*/
66
67 #include "fake-mLib-bits.h"
68
69 #include "montladder.h"
70 #include "fgoldi.h"
71 #include "x448.h"
72
73 /*----- Important constants -----------------------------------------------*/
74
75 const octet x448_base[56] = { 5, 0, /* ... */ };
76
77 #define A0 39081
78
79 /*----- Main code ---------------------------------------------------------*/
80
81 /* --- @x448@ --- *
82  *
83  * Arguments:   @octet zz[X448_OUTSZ]@ = where to put the result
84  *              @const octet k[X448_KEYSZ]@ = pointer to private key
85  *              @const octet qx[X448_PUBSZ]@ = pointer to public value
86  *
87  * Returns:     ---
88  *
89  * Use:         Calculates X448 of @k@ and @qx@.
90  */
91
92 void x448(octet zz[X448_OUTSZ],
93           const octet k[X448_KEYSZ],
94           const octet qx[X448_PUBSZ])
95 {
96   uint32 kw[14];
97   fgoldi x1;
98   unsigned i;
99
100   /* Load and clamp the key.  The low bits are cleared to kill the small
101    * subgroups on the curve and its twist, and a high bit is set to guard
102    * against careless implementations, though this isn't one of those.
103    */
104   for (i = 0; i < 14; i++) kw[i] = LOAD32_L(k + 4*i);
105   kw[0] &= 0xfffffffc; kw[13] |= 0x80000000;
106
107   /* And run the ladder. */
108   fgoldi_load(&x1, qx);
109 #define MULA0(z, x) do { fgoldi_mulconst((z), (x), A0); } while (0)
110   MONT_LADDER(fgoldi, MULA0, kw, 14, 32, &x1, &x1);
111 #undef MULA0
112   fgoldi_store(zz, &x1);
113 }
114
115 /*----- Test rig ----------------------------------------------------------*/
116
117 #ifdef TEST_RIG
118
119 #include <mLib/report.h>
120 #include <mLib/str.h>
121 #include <mLib/testrig.h>
122
123 static int vrf_x448(dstr dv[])
124 {
125   dstr dz = DSTR_INIT;
126   int ok = 1;
127
128   if (dv[0].len != 56) die(1, "bad key length");
129   if (dv[1].len != 56) die(1, "bad public length");
130   if (dv[2].len != 56) die(1, "bad result length");
131
132   dstr_ensure(&dz, 56); dz.len = 56;
133   x448((octet *)dz.buf,
134        (const octet *)dv[0].buf,
135        (const octet *)dv[1].buf);
136   if (memcmp(dz.buf, dv[2].buf, 56) != 0) {
137     ok = 0;
138     fprintf(stderr, "failed!");
139     fprintf(stderr, "\n\t   k = "); type_hex.dump(&dv[0], stderr);
140     fprintf(stderr, "\n\t   p = "); type_hex.dump(&dv[1], stderr);
141     fprintf(stderr, "\n\twant = "); type_hex.dump(&dv[2], stderr);
142     fprintf(stderr, "\n\tcalc = "); type_hex.dump(&dz, stderr);
143     fprintf(stderr, "\n");
144   }
145
146   dstr_destroy(&dz);
147   return (ok);
148 }
149
150 static int vrf_mct(dstr dv[])
151 {
152   octet b0[56], b1[56], *k = b0, *x = b1, *t;
153   unsigned long i, niter;
154   dstr d = DSTR_INIT;
155   int ok = 1;
156
157   if (dv[0].len != sizeof(b0)) { fprintf(stderr, "k len\n"); exit(2); }
158   if (dv[1].len != sizeof(b1)) { fprintf(stderr, "x len\n"); exit(2); }
159   if (dv[3].len != sizeof(b0)) { fprintf(stderr, "result len\n"); exit(2); }
160   memcpy(b0, dv[0].buf, sizeof(b0));
161   memcpy(b1, dv[1].buf, sizeof(b1));
162   niter = *(unsigned long *)dv[2].buf;
163   dstr_ensure(&d, 56); d.len = 56; t = (octet *)d.buf;
164
165   for (i = 0; i < niter; i++) {
166     x448(x, k, x);
167     t = x; x = k; k = t;
168   }
169   memcpy(d.buf, k, d.len);
170
171   if (memcmp(d.buf, dv[3].buf, d.len) != 0) {
172     ok = 0;
173     fprintf(stderr, "failed...");
174     fprintf(stderr, "\n\tinitial k = "); type_hex.dump(&dv[0], stderr);
175     fprintf(stderr, "\n\tinitial x = "); type_hex.dump(&dv[1], stderr);
176     fprintf(stderr, "\n\titerations = %lu", niter);
177     fprintf(stderr, "\n\texpected = "); type_hex.dump(&dv[3], stderr);
178     fprintf(stderr, "\n\tcalculated = "); type_hex.dump(&d, stderr);
179     fputc('\n', stderr);
180   }
181
182   dstr_destroy(&d);
183   return (ok);
184 }
185
186 static test_chunk tests[] = {
187   { "x448", vrf_x448, { &type_hex, &type_hex, &type_hex } },
188   { "x448-mct", vrf_mct,
189     { &type_hex, &type_hex, &type_ulong, &type_hex } },
190   { 0, 0, { 0 } }
191 };
192
193 int main(int argc, char *argv[])
194 {
195   test_run(argc, argv, tests, SRCDIR "/t/x448");
196   return (0);
197 }
198
199 #endif
200
201 /*----- That's all, folks -------------------------------------------------*/