commit 0cd54e2ee4f7fc860defffcbc7cd93652051bb12
parent 2999de5cd79be7e539e16ec91764678740c94c51
Author: Robin Bron <robin.bron@yourhosting.nl>
Date: Sun, 13 Sep 2026 19:48:31 +0200
Fix compiler warnings and add pub-only key support
Diffstat:
11 files changed, 97 insertions(+), 33 deletions(-)
diff --git a/src/cli/command/generate.c b/src/cli/command/generate.c
@@ -17,7 +17,7 @@ static int cmd_generate(int argc, const char **argv) {
};
struct argparse_option options[] = {
OPT_HELP(),
- OPT_STRING('k', "key-file", &keyFile, "Key file to write (defaults to stdout)"),
+ OPT_STRING('k', "key-file", &keyFile, "Key file to write (defaults to stdout)", NULL, 0, 0),
OPT_END(),
};
@@ -51,8 +51,13 @@ static int cmd_generate(int argc, const char **argv) {
// Encode in the last-registered format
// TODO: allow format selection
- int encoded_length;
+ size_t encoded_length;
char *encoded = supercop_formats->encode(&kp, &encoded_length);
+ if (!encoded) {
+ fprintf(stderr, "Error while encoding key\n");
+ if (keyFile) fclose(fout);
+ return 1;
+ }
fwrite(encoded, 1, encoded_length, fout);
free(encoded);
diff --git a/src/cli/command/printkey.c b/src/cli/command/printkey.c
@@ -16,7 +16,7 @@ static int cmd_printkey(int argc, const char **argv) {
};
struct argparse_option options[] = {
OPT_HELP(),
- OPT_STRING('k', "key-file", &keyFile, "Select key file to use for the operation"),
+ OPT_STRING('k', "key-file", &keyFile, "Select key file to use for the operation", NULL, 0, 0),
OPT_END(),
};
@@ -32,11 +32,20 @@ static int cmd_printkey(int argc, const char **argv) {
}
kp = readKeyFile(keyFile);
+ if (!kp || !kp->public_key) {
+ fprintf(stderr, "Could not decode key file: unknown or invalid format\n");
+ if (kp) keypair_free(kp);
+ return 1;
+ }
fprintf(stdout, "public-key: ");
for(i=0;i<32;i++) fprintf(stdout, "%02x", kp->public_key[i]);
- fprintf(stdout, "\nprivate-key: ");
- for(i=0;i<64;i++) fprintf(stdout, "%02x", kp->private_key[i]);
+ if (kp->private_key) {
+ fprintf(stdout, "\nprivate-key: ");
+ for(i=0;i<64;i++) fprintf(stdout, "%02x", kp->private_key[i]);
+ } else {
+ fprintf(stdout, "\nprivate-key: (no private key in file)");
+ }
fprintf(stdout, "\n");
result = 0;
diff --git a/src/cli/command/sign.c b/src/cli/command/sign.c
@@ -20,9 +20,9 @@ static int cmd_sign(int argc, const char **argv) {
};
struct argparse_option options[] = {
OPT_HELP(),
- OPT_STRING('k', "key-file", &keyFile, "Select key file to use for the operation"),
- OPT_STRING('m', "message", &message, "Message to sign (defaults to stdin)"),
- OPT_STRING('M', "message-file", &messageFile, "Message file to sign (defaults to stdin)"),
+ OPT_STRING('k', "key-file", &keyFile, "Select key file to use for the operation", NULL, 0, 0),
+ OPT_STRING('m', "message", &message, "Message to sign (defaults to stdin)", NULL, 0, 0),
+ OPT_STRING('M', "message-file", &messageFile, "Message file to sign (defaults to stdin)", NULL, 0, 0),
OPT_END(),
};
@@ -39,6 +39,16 @@ static int cmd_sign(int argc, const char **argv) {
fmessage = supercop_open_message(message, messageFile);
kp = readKeyFile(keyFile);
+ if (!kp || !kp->public_key) {
+ fprintf(stderr, "Could not decode key file: unknown or invalid format\n");
+ if (kp) keypair_free(kp);
+ return 1;
+ }
+ if (!kp->private_key) {
+ fprintf(stderr, "Key file contains no private key: signing requires a full key\n");
+ keypair_free(kp);
+ return 1;
+ }
long message_len = fremaining(fmessage);
const unsigned char *msg = calloc(1, message_len);
diff --git a/src/cli/command/verify.c b/src/cli/command/verify.c
@@ -22,10 +22,10 @@ static int cmd_verify(int argc, const char **argv) {
};
struct argparse_option options[] = {
OPT_HELP(),
- OPT_STRING('k', "key-file", &keyFile, "Select key file to use for the operation"),
- OPT_STRING('m', "message", &message, "Message to verify (defaults to stdin)"),
- OPT_STRING('M', "message-file", &messageFile, "Message file to verify (defaults to stdin)"),
- OPT_STRING('s', "signature", &verifySignature, "Signature to verify"),
+ OPT_STRING('k', "key-file", &keyFile, "Select key file to use for the operation", NULL, 0, 0),
+ OPT_STRING('m', "message", &message, "Message to verify (defaults to stdin)", NULL, 0, 0),
+ OPT_STRING('M', "message-file", &messageFile, "Message file to verify (defaults to stdin)", NULL, 0, 0),
+ OPT_STRING('s', "signature", &verifySignature, "Signature to verify", NULL, 0, 0),
OPT_END(),
};
@@ -65,6 +65,14 @@ static int cmd_verify(int argc, const char **argv) {
}
kp = readKeyFile(keyFile);
+ if (!kp || !kp->public_key) {
+ fprintf(stderr, "Could not decode key file: unknown or invalid format\n");
+ free((void *)sig);
+ free((void *)msg);
+ fclose(fsignature);
+ if (kp) keypair_free(kp);
+ return 1;
+ }
isValid = ed25519_verify(sig, msg, message_len, kp->public_key);
free((void *)sig);
diff --git a/src/cli/common.c b/src/cli/common.c
@@ -34,16 +34,22 @@ struct KeyPair *readKeyFile(const char *filename) {
// Auto-detect format
while(fmt) {
- if (!fmt->detect(buf)) {
+ if (!fmt->detect(buf, fsize)) {
+ fmt = fmt->next;
+ continue;
+ }
+ kp = fmt->decode(buf, fsize);
+ if (!kp) {
fmt = fmt->next;
continue;
}
- kp = fmt->decode(buf);
free(buf);
fclose(fd);
return kp;
}
+ free(buf);
+ fclose(fd);
return NULL;
}
diff --git a/src/fmt/0x00/common.h b/src/fmt/0x00/common.h
@@ -4,8 +4,8 @@
#ifndef __SUPERCOP_FMT_0X00_COMMON_H__
#define __SUPERCOP_FMT_0X00_COMMON_H__
-char fmt_0x00_detect(unsigned char *cipherdata);
-char * fmt_0x00_encode(struct KeyPair *keypair, int *len);
-struct KeyPair * fmt_0x00_decode(unsigned char *cipherdata);
+char fmt_0x00_detect(unsigned char *cipherdata, size_t len);
+char * fmt_0x00_encode(struct KeyPair *keypair, size_t *len);
+struct KeyPair * fmt_0x00_decode(unsigned char *cipherdata, size_t len);
#endif // __SUPERCOP_FMT_0X00_COMMON_H__
diff --git a/src/fmt/0x00/decode.c b/src/fmt/0x00/decode.c
@@ -7,12 +7,27 @@
extern "C" {
#endif
-struct KeyPair * fmt_0x00_decode(unsigned char *cipherdata) {
- struct KeyPair *kp = calloc(1, sizeof(struct KeyPair));
+struct KeyPair * fmt_0x00_decode(unsigned char *cipherdata, size_t len) {
+ struct KeyPair *kp;
+ // Pub-only (33 bytes) or full (97 bytes), anything else is invalid
+ if (len != 33 && len != 97) return NULL;
+ kp = calloc(1, sizeof(struct KeyPair));
+ if (!kp) return NULL;
kp->public_key = calloc(1, 32);
- kp->private_key = calloc(1, 64);
+ if (!kp->public_key) {
+ free(kp);
+ return NULL;
+ }
memcpy(kp->public_key , cipherdata + 1, 32);
- memcpy(kp->private_key, cipherdata + 33, 64);
+ if (len == 97) {
+ kp->private_key = calloc(1, 64);
+ if (!kp->private_key) {
+ free(kp->public_key);
+ free(kp);
+ return NULL;
+ }
+ memcpy(kp->private_key, cipherdata + 33, 64);
+ }
return kp;
}
diff --git a/src/fmt/0x00/detect.c b/src/fmt/0x00/detect.c
@@ -1,10 +1,15 @@
+#include <stddef.h>
+
#include "common.h"
#ifdef __cplusplus
extern "C" {
#endif
-char fmt_0x00_detect(unsigned char *cipherdata) {
+char fmt_0x00_detect(unsigned char *cipherdata, size_t len) {
+ // Only claim 0x00-prefixed payloads of a known size, so a future format
+ // sharing the leading null-byte but with a different length won't collide
+ if (len != 33 && len != 97) return 0;
if ((*cipherdata) == '\0') return 1;
return 0;
}
diff --git a/src/fmt/0x00/encode.c b/src/fmt/0x00/encode.c
@@ -7,12 +7,18 @@
extern "C" {
#endif
-char * fmt_0x00_encode(struct KeyPair *kp, int *len) {
- *len = 1 + 32 + 64;
- char *result = malloc(*len);
- result[0] = 0;
- memcpy(result + 1, kp->public_key , 32);
- memcpy(result + 33, kp->private_key, 64);
+char * fmt_0x00_encode(struct KeyPair *kp, size_t *len) {
+ char *result;
+ if (!kp || !kp->public_key || !len) return NULL;
+ result = malloc(1 + 32 + 64);
+ if (!result) return NULL;
+ result[0] = 0;
+ memcpy(result + 1, kp->public_key, 32);
+ *len = 1 + 32;
+ if (kp->private_key) {
+ memcpy(result + 33, kp->private_key, 64);
+ *len = 1 + 32 + 64;
+ }
return result;
}
diff --git a/src/fmt/0x00/register.c b/src/fmt/0x00/register.c
@@ -10,14 +10,14 @@ extern "C" {
extern struct Format *supercop_formats;
void __attribute__ ((constructor)) fmt_0x00_register() {
- struct Format *fmt = calloc(sizeof(struct Format), 1);
+ struct Format *fmt = calloc(1, sizeof(struct Format));
fmt->next = supercop_formats;
fmt->name = calloc(1,5);
fmt->detect = fmt_0x00_detect;
fmt->encode = fmt_0x00_encode;
fmt->decode = fmt_0x00_decode;
supercop_formats = fmt;
- strncpy(fmt->name, "0x00", 4);
+ strcpy(fmt->name, "0x00");
}
#ifdef __cplusplus
diff --git a/src/fmt/common.h b/src/fmt/common.h
@@ -12,9 +12,9 @@ extern "C" {
struct Format {
void *next;
char *name;
- char (*detect)(unsigned char *);
- char *(*encode)(struct KeyPair *, int*);
- struct KeyPair *(*decode)(unsigned char *);
+ char (*detect)(unsigned char *, size_t);
+ char *(*encode)(struct KeyPair *, size_t*);
+ struct KeyPair *(*decode)(unsigned char *, size_t);
};
#ifdef __cplusplus