1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
12 #include <libubox/utils.h>
15 #include "curve25519.h"
16 #include "auth-data.h"
18 static uint8_t pubkey
[EDSIGN_PUBLIC_KEY_SIZE
];
19 static uint8_t seckey
[EDSIGN_PUBLIC_KEY_SIZE
];
20 static FILE *out_file
;
30 static void print_key(const uint8_t *key
)
32 char keystr
[B64_ENCODE_LEN(EDSIGN_PUBLIC_KEY_SIZE
)];
34 if (b64_encode(key
, EDSIGN_PUBLIC_KEY_SIZE
, keystr
, sizeof(keystr
)) < 0)
37 fprintf(out_file
, "%s\n", keystr
);
40 static int usage(const char *progname
)
42 fprintf(stderr
, "Usage: %s [command|options] [<file>]\n"
46 " -P Get pulic signing key from secret key\n"
47 " -H Get pulic host key from secret key\n"
48 " -G Generate new private key\n"
51 " -o <file>: Set output file to <file> (defaults to stdout)\n"
52 " -k <keyfile>|-: Set public key from file or stdin\n"
53 " -K <keyfile>|-: Set secret key from file or stdin\n"
58 static int cmd_sign(int argc
, char **argv
)
60 struct unet_auth_hdr hdr
= {
61 .magic
= cpu_to_be32(UNET_AUTH_MAGIC
),
63 struct unet_auth_data
*data
;
70 fprintf(stderr
, "Missing filename\n");
74 if (gettimeofday(&tv
, NULL
)) {
75 perror("gettimeofday");
79 if (stat(argv
[0], &st
) ||
80 (f
= fopen(argv
[0], "r")) == NULL
) {
81 fprintf(stderr
, "Input file not found\n");
85 data
= calloc(1, sizeof(*data
) + st
.st_size
+ 1);
86 data
->timestamp
= cpu_to_be64(tv
.tv_sec
);
87 len
= fread(data
+ 1, 1, st
.st_size
, f
);
90 if (len
!= st
.st_size
) {
91 fprintf(stderr
, "Error reading from input file\n");
97 memcpy(data
->pubkey
, pubkey
, sizeof(pubkey
));
98 edsign_sign(hdr
.signature
, pubkey
, seckey
, (const void *)data
, len
);
100 fwrite(&hdr
, sizeof(hdr
), 1, out_file
);
101 fwrite(data
, len
, 1, out_file
);
108 static int cmd_verify(int argc
, char **argv
)
110 struct unet_auth_data
*data
;
111 struct unet_auth_hdr
*hdr
;
118 fprintf(stderr
, "Missing filename\n");
122 if (stat(argv
[0], &st
) ||
123 (f
= fopen(argv
[0], "r")) == NULL
) {
124 fprintf(stderr
, "Input file not found\n");
128 if (st
.st_size
<= sizeof(*hdr
) + sizeof(*data
)) {
129 fprintf(stderr
, "Input file too small\n");
134 hdr
= calloc(1, st
.st_size
);
135 len
= fread(hdr
, 1, st
.st_size
, f
);
138 if (len
!= st
.st_size
) {
139 fprintf(stderr
, "Error reading from input file\n");
143 ret
= unet_auth_data_validate(pubkey
, hdr
, len
, NULL
);
146 fprintf(stderr
, "Invalid input data\n");
149 fprintf(stderr
, "Public key does not match\n");
152 fprintf(stderr
, "Signature verification failed\n");
160 static int cmd_host_pubkey(int argc
, char **argv
)
162 curve25519_generate_public(pubkey
, seckey
);
168 static int cmd_pubkey(int argc
, char **argv
)
175 static int cmd_generate(int argc
, char **argv
)
180 f
= fopen("/dev/urandom", "r");
182 fprintf(stderr
, "Can't open /dev/urandom\n");
186 ret
= fread(seckey
, sizeof(seckey
), 1, f
);
190 fprintf(stderr
, "Can't read data from /dev/urandom\n");
194 ed25519_prepare(seckey
);
200 static bool parse_key(uint8_t *dest
, const char *str
)
202 char keystr
[B64_ENCODE_LEN(EDSIGN_PUBLIC_KEY_SIZE
) + 2];
206 if (!strcmp(str
, "-"))
212 fprintf(stderr
, "Can't open key file for reading\n");
216 len
= fread(keystr
, 1, sizeof(keystr
) - 1, f
);
222 if (b64_decode(keystr
, dest
, EDSIGN_PUBLIC_KEY_SIZE
) != EDSIGN_PUBLIC_KEY_SIZE
) {
223 fprintf(stderr
, "Failed to parse key data\n");
230 static bool cmd_needs_pubkey(void)
240 static bool cmd_needs_key(void)
245 case CMD_HOST_PUBKEY
:
252 int main(int argc
, char **argv
)
254 const char *progname
= argv
[0];
255 const char *out_filename
= NULL
;
256 bool has_key
= false, has_pubkey
= false;
259 while ((ch
= getopt(argc
, argv
, "o:k:K:GHPSV")) != -1) {
262 out_filename
= optarg
;
266 return usage(progname
);
268 if (!parse_key(pubkey
, optarg
)) {
276 return usage(progname
);
278 if (!parse_key(seckey
, optarg
)) {
284 edsign_sec_to_pub(pubkey
, seckey
);
288 if (cmd
!= CMD_UNKNOWN
)
289 return usage(progname
);
294 if (cmd
!= CMD_UNKNOWN
)
295 return usage(progname
);
300 if (cmd
!= CMD_UNKNOWN
)
301 return usage(progname
);
306 if (cmd
!= CMD_UNKNOWN
)
307 return usage(progname
);
309 cmd
= CMD_HOST_PUBKEY
;
312 if (cmd
!= CMD_UNKNOWN
)
313 return usage(progname
);
318 return usage(progname
);
322 if (!has_key
&& cmd_needs_key()) {
323 fprintf(stderr
, "Missing -K <key> argument\n");
327 if (!has_pubkey
&& cmd_needs_pubkey()) {
328 fprintf(stderr
, "Missing -k <key> argument\n");
336 out_file
= fopen(out_filename
, "w");
338 fprintf(stderr
, "Failed to open output file\n");
348 ret
= cmd_generate(argc
, argv
);
351 ret
= cmd_sign(argc
, argv
);
354 ret
= cmd_pubkey(argc
, argv
);
356 case CMD_HOST_PUBKEY
:
357 ret
= cmd_host_pubkey(argc
, argv
);
360 ret
= cmd_verify(argc
, argv
);
363 ret
= usage(progname
);
367 if (out_file
!= stdout
) {
370 unlink(out_filename
);