Switch to single-file targets, target_descriptor struct for target data, rework target handling to accomodate
This commit is contained in:
parent
391fa5659d
commit
e0d2bd3e4c
4 changed files with 90 additions and 168 deletions
230
ctm.c
230
ctm.c
|
@ -27,126 +27,71 @@ void print_help(char* name){
|
||||||
printf("%s keygen [targ] [tfs] - create a new target keypair [targ] using token format [tfs] and the system true randomness source\n", name);
|
printf("%s keygen [targ] [tfs] - create a new target keypair [targ] using token format [tfs] and the system true randomness source\n", name);
|
||||||
printf("%s keygen [targ] [tfs] [ikm] - create a new target keypair [targ] using token format specifier [tfs] and 32-byte hexadecimal seed [ikm]\n", name);
|
printf("%s keygen [targ] [tfs] [ikm] - create a new target keypair [targ] using token format specifier [tfs] and 32-byte hexadecimal seed [ikm]\n", name);
|
||||||
printf("%s keydump [targ] - dump Public and, if available, Secret Keys for target [targ]\n", name);
|
printf("%s keydump [targ] - dump Public and, if available, Secret Keys for target [targ]\n", name);
|
||||||
printf("%s keyrepair [targ] - regenerate a missing Public Key for a target [targ] for which a Secret Key is available\n", name);
|
//printf("%s keyrepair [targ] - regenerate a missing Public Key for a target [targ] for which a Secret Key is available\n", name);
|
||||||
printf("%s req [targ] - generate a token request for target [targ]\n", name);
|
printf("%s req [targ] - generate a token request for target [targ]\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_key_paths(char* target, char** sk_path, char** pk_path, char** tfs_path){
|
int get_targ_path(char* target, char** targ_path){
|
||||||
int key_path_len;
|
int path_len;
|
||||||
|
|
||||||
key_path_len = strlen(token_path) + strlen(target) + 13;
|
path_len = strlen(token_path) + strlen(target) + 17;
|
||||||
|
|
||||||
*sk_path = malloc(key_path_len);
|
*targ_path = malloc(path_len);
|
||||||
if(*sk_path == NULL) return 1;
|
if(*targ_path == NULL) return 1;
|
||||||
|
|
||||||
*pk_path = malloc(key_path_len);
|
strcpy(*targ_path, token_path);
|
||||||
if(*pk_path == NULL) return 1;
|
strcat(*targ_path, "/targets/");
|
||||||
|
strcat(*targ_path, target);
|
||||||
|
strcat(*targ_path, ".target");
|
||||||
|
|
||||||
*tfs_path = malloc(key_path_len + 1);
|
|
||||||
if(*tfs_path == NULL) return 1;
|
|
||||||
|
|
||||||
strcpy(*sk_path, token_path);
|
|
||||||
strcat(*sk_path, "/targets/");
|
|
||||||
strcat(*sk_path, target);
|
|
||||||
strcpy(*pk_path, *sk_path);
|
|
||||||
strcpy(*tfs_path, *sk_path);
|
|
||||||
strcat(*sk_path, ".sk");
|
|
||||||
strcat(*pk_path, ".pk");
|
|
||||||
strcat(*tfs_path, ".tfs");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_keys(char* target, byte* sk, byte* pk, int* idbits, int* hashbits){ // pk/sk/idbits/hasbits pointers can be NULL if you don't want to read those
|
int get_target(char* targ_name, target_descriptor* target){ // pk/sk/idbits/hasbits pointers can be NULL if you don't want to read those
|
||||||
FILE *targ_file;
|
FILE *targ_file;
|
||||||
char *sk_path;
|
char *targ_path;
|
||||||
char *pk_path;
|
|
||||||
char *tfs_path;
|
|
||||||
bool sk_available, pk_available, tfs_available;
|
|
||||||
int idbits_buf, hashbits_buf;
|
|
||||||
|
|
||||||
get_key_paths(target, &sk_path, &pk_path, &tfs_path);
|
get_targ_path(targ_name, &targ_path);
|
||||||
|
|
||||||
sk_available = (access(sk_path, R_OK) == 0);
|
targ_file = fopen(targ_path, "r");
|
||||||
pk_available = (access(pk_path, R_OK) == 0);
|
|
||||||
tfs_available = (access(tfs_path, R_OK) == 0);
|
|
||||||
|
|
||||||
if(sk_available && sk != NULL){
|
|
||||||
targ_file = fopen(sk_path, "r");
|
|
||||||
if(!targ_file){
|
if(!targ_file){
|
||||||
printf("Could not open Secret Key file. Exiting.\n");
|
return 0;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
fread(sk, 32, 1, targ_file);
|
fread(target, sizeof(target_descriptor), 1, targ_file);
|
||||||
fclose(targ_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pk_available && pk != NULL){
|
|
||||||
targ_file = fopen(pk_path, "r");
|
|
||||||
if(!targ_file){
|
|
||||||
printf("Could not open Public Key file. Exiting.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fread(pk, 96, 1, targ_file);
|
|
||||||
fclose(targ_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(idbits != NULL || hashbits != NULL){
|
|
||||||
if(tfs_available){
|
|
||||||
targ_file = fopen(tfs_path, "r");
|
|
||||||
if(!targ_file){
|
|
||||||
printf("Could not open Token Format Specifier file. Exiting.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fscanf(targ_file, "%i/%i", &idbits_buf, &hashbits_buf);
|
|
||||||
fclose(targ_file);
|
fclose(targ_file);
|
||||||
|
|
||||||
if(idbits != NULL) *idbits = idbits_buf;
|
// 0 = no keys (bad target), 1 = PK only, 2 = PK+SK
|
||||||
if(hashbits != NULL) *hashbits = hashbits_buf;
|
return target->sk_available + 1;
|
||||||
}else{
|
|
||||||
printf("WARNING: Token Format Specifier not set, this is a broken state. Using default (128/256) - please add a .tfs file for the target\n");
|
|
||||||
if(idbits != NULL) *idbits = IDBITS_DEFAULT;
|
|
||||||
if(hashbits != NULL) *hashbits = HASHBITS_DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 = no keys (bad target), 1 = PK only, 2 = SK only (broken state), 3 = PK+SK (can sign)
|
int keydump(char* targ_name){
|
||||||
return (2 * sk_available) + pk_available;
|
int targ_status;
|
||||||
}
|
target_descriptor target;
|
||||||
|
|
||||||
int keydump(char* target){
|
targ_status = get_target(targ_name, &target);
|
||||||
byte sk[32];
|
|
||||||
byte pk[96];
|
|
||||||
int key_status;
|
|
||||||
int idbits, hashbits;
|
|
||||||
|
|
||||||
key_status = get_keys(target, sk, pk, &idbits, &hashbits);
|
switch(targ_status){
|
||||||
|
|
||||||
switch(key_status){
|
|
||||||
case 0:
|
case 0:
|
||||||
printf("No keys found - target unknown.\n");
|
printf("No target file found - target unknown.\n");
|
||||||
break;
|
return 1;
|
||||||
case 1:
|
case 1:
|
||||||
printf("Public Key available - can verify and request for this target\n");
|
printf("Public Key available - can verify and request for this target\n");
|
||||||
print_bytes("Public Key: ", pk, 96);
|
print_bytes("Public Key: ", target.pk, 96);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
printf("Secret Key ONLY available - this is a broken state, please keyrepair this keypair (see help)\n");
|
|
||||||
print_bytes("Secret Key: ", sk, 32);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
printf("Secret Key and Public Key available - can verify, request, and sign for this target.\n");
|
printf("Secret Key and Public Key available - can verify, request, and sign for this target.\n");
|
||||||
print_bytes("Secret Key: ", sk, 32);
|
print_bytes("Secret Key: ", target.sk, 32);
|
||||||
print_bytes("Public Key: ", pk, 96);
|
print_bytes("Public Key: ", target.pk, 96);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Token Format Specifier: %i/%i (%i ID bits, %i hash bits)\n", idbits, hashbits, idbits, hashbits);
|
printf("Token Format Specifier: %i/%i (%i ID bits, %i hash bits)\n", target.idbits, target.hashbits, target.idbits, target.hashbits);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int keyrepair(char* target){
|
/*int keyrepair(char* target){
|
||||||
FILE *key_file;
|
FILE *key_file;
|
||||||
byte sk[32];
|
byte sk[32];
|
||||||
byte pk[96];
|
byte pk[96];
|
||||||
|
@ -180,53 +125,35 @@ int keyrepair(char* target){
|
||||||
printf("Saved to %s\n", pk_path);
|
printf("Saved to %s\n", pk_path);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
int keygen(char* target, byte* ikm, int idbits, int hashbits){
|
int keygen(char* target, byte* ikm, int idbits, int hashbits){
|
||||||
char *sk_path;
|
char *targ_path;
|
||||||
char *pk_path;
|
|
||||||
char* tfs_path;
|
|
||||||
FILE *targ_file;
|
FILE *targ_file;
|
||||||
byte sk_byte[32];
|
target_descriptor targ;
|
||||||
byte pk_byte[96];
|
|
||||||
|
|
||||||
debug_print_bytes("IKM: ", ikm, 32);
|
debug_print_bytes("IKM: ", ikm, 32);
|
||||||
|
|
||||||
fstoken_keygen(ikm, sk_byte, pk_byte);
|
fstoken_keygen(ikm, targ.sk, targ.pk);
|
||||||
|
|
||||||
debug_print_bytes("Secret Key: ", sk_byte, 32);
|
debug_print_bytes("Secret Key: ", targ.sk, 32);
|
||||||
debug_print_bytes("Public Key: ", pk_byte, 96);
|
debug_print_bytes("Public Key: ", targ.pk, 96);
|
||||||
|
|
||||||
if(get_key_paths(target, &sk_path, &pk_path, &tfs_path)) return 1;
|
targ.idbits = idbits;
|
||||||
|
targ.hashbits = hashbits;
|
||||||
|
targ.target_descriptor_version = 0x00;
|
||||||
|
targ.sk_available = true;
|
||||||
|
|
||||||
printf("Writing Secret Key to %s\n", sk_path);
|
debug_print_bytes("Target Struct: ", &targ, sizeof(targ));
|
||||||
|
|
||||||
targ_file = fopen(sk_path, "w");
|
if(get_targ_path(target, &targ_path)) return 1;
|
||||||
|
|
||||||
|
targ_file = fopen(targ_path, "w");
|
||||||
if(!targ_file){
|
if(!targ_file){
|
||||||
printf("Could not open Secret Key file. Exiting.\n");
|
printf("Could not open target file. Exiting.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fwrite(sk_byte, 32, 1, targ_file);
|
fwrite(&targ, sizeof(targ), 1, targ_file);
|
||||||
fclose(targ_file);
|
|
||||||
|
|
||||||
printf("Writing Public Key to %s\n", pk_path);
|
|
||||||
|
|
||||||
targ_file = fopen(pk_path, "w");
|
|
||||||
if(!targ_file){
|
|
||||||
printf("Could not open Public Key file. Exiting.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fwrite(pk_byte, 96, 1, targ_file);
|
|
||||||
fclose(targ_file);
|
|
||||||
|
|
||||||
printf("Writing Token Format Specifier to %s\n", tfs_path);
|
|
||||||
|
|
||||||
targ_file = fopen(tfs_path, "w");
|
|
||||||
if(!targ_file){
|
|
||||||
printf("Could not open Token Format Specifier file. Exiting.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fprintf(targ_file, "%i/%i", idbits, hashbits);
|
|
||||||
fclose(targ_file);
|
fclose(targ_file);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -246,22 +173,22 @@ bool string_endswith(const char *str, const char *suffix){
|
||||||
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
|
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is awful because strings in C. It should probably be improved.
|
// Believe it or not, this function used to be WORSE, and substantially so. It could still do to be cleaned up.
|
||||||
int list_targets(bool verbose){
|
int list_targets(bool verbose){
|
||||||
printf("Listing all targets - you have secret keys for, and can issue tokens for, targets marked with (*)\n\n");
|
printf("Listing all targets - you have secret keys for, and can issue tokens for, targets marked with (*)\n\n");
|
||||||
int n, keyname_len;
|
int n, targname_len;
|
||||||
struct dirent **files;
|
struct dirent **files;
|
||||||
char *keydir_path, *key_path, *key_name;
|
char *targdir_path, *targ_path, *targ_name;
|
||||||
bool sk_available;
|
target_descriptor targ;
|
||||||
|
|
||||||
keydir_path = malloc(strlen(token_path) + 9);
|
targdir_path = malloc(strlen(token_path) + 9);
|
||||||
if(keydir_path == NULL) return 1;
|
if(targdir_path == NULL) return 1;
|
||||||
|
|
||||||
strcpy(keydir_path, token_path);
|
strcpy(targdir_path, token_path);
|
||||||
strcat(keydir_path, "/targets");
|
strcat(targdir_path, "/targets");
|
||||||
|
|
||||||
#ifndef __INTELLISENSE__ // VSCodium doesn't know where alphasort is and highlights an error
|
#ifndef __INTELLISENSE__ // VSCodium doesn't know where alphasort is and highlights an error
|
||||||
n = scandir(keydir_path, &files, NULL, alphasort);
|
n = scandir(targdir_path, &files, NULL, alphasort);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(n == -1){
|
if(n == -1){
|
||||||
|
@ -270,45 +197,30 @@ int list_targets(bool verbose){
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0;i<n;i++){
|
for(int i=0;i<n;i++){
|
||||||
if(string_endswith(files[i]->d_name, ".pk")){
|
if(string_endswith(files[i]->d_name, ".target")){
|
||||||
keyname_len = strlen(files[i]->d_name);
|
targname_len = strlen(files[i]->d_name);
|
||||||
|
|
||||||
key_name = malloc(keyname_len + 1);
|
targ_name = malloc(targname_len + 1);
|
||||||
if(key_name == NULL) return 1;
|
if(targ_name == NULL) return 1;
|
||||||
|
|
||||||
strcpy(key_name, files[i]->d_name);
|
strcpy(targ_name, files[i]->d_name);
|
||||||
key_name[keyname_len - 3] = '\0';
|
targ_name[targname_len - 7] = '\0';
|
||||||
|
|
||||||
printf("%s", key_name);
|
printf("%s", targ_name);
|
||||||
|
|
||||||
key_path = malloc(strlen(token_path) + 9 + strlen(files[i]->d_name));
|
get_target(targ_name, &targ);
|
||||||
if(key_path == NULL) return 1;
|
if(targ.sk_available) printf(" (*)");
|
||||||
|
|
||||||
strcpy(key_path, token_path);
|
if(verbose){
|
||||||
strcat(key_path, "/targets/");
|
get_targ_path(targ_name, &targ_path);
|
||||||
strcat(key_path, files[i]->d_name);
|
printf(" (Path: %s, Token Format Specifier: %i/%i)", targ_path, targ.idbits, targ.hashbits);
|
||||||
|
|
||||||
if(verbose) printf(" (PK: %s", key_path);
|
|
||||||
|
|
||||||
key_path[strlen(key_path) - 2] = 's';
|
|
||||||
|
|
||||||
if(access(key_path, R_OK) == 0){
|
|
||||||
sk_available = true;
|
|
||||||
|
|
||||||
if(verbose) printf(", SK: %s", key_path);
|
|
||||||
}else{
|
|
||||||
sk_available = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose) printf(")");
|
|
||||||
if(sk_available) printf(" (*)");
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
free(key_path);
|
free(targ_name);
|
||||||
free(key_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(keydir_path);
|
free(targdir_path);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -392,7 +304,7 @@ int main(int argc, char *argv[]){
|
||||||
}
|
}
|
||||||
|
|
||||||
return keydump(argv[2]);
|
return keydump(argv[2]);
|
||||||
}else if(strcmp(argv[1], "keyrepair") == 0){
|
}/*else if(strcmp(argv[1], "keyrepair") == 0){
|
||||||
// Make sure there's a target name
|
// Make sure there's a target name
|
||||||
if(argc < 3){
|
if(argc < 3){
|
||||||
fprintf(stderr, "A target name must be provided, e.g. %s keyrepair [targ]\n", argv[0]);
|
fprintf(stderr, "A target name must be provided, e.g. %s keyrepair [targ]\n", argv[0]);
|
||||||
|
@ -400,5 +312,5 @@ int main(int argc, char *argv[]){
|
||||||
}
|
}
|
||||||
|
|
||||||
return keyrepair(argv[2]);
|
return keyrepair(argv[2]);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
|
@ -2,15 +2,15 @@
|
||||||
#include "debugprint.h"
|
#include "debugprint.h"
|
||||||
#include "blst/blst.h"
|
#include "blst/blst.h"
|
||||||
|
|
||||||
void print_bytes(const char* label, byte *toprint, int length){
|
void print_bytes(const char* label, void *toprint, int length){
|
||||||
printf("%s", label);
|
printf("%s", label);
|
||||||
for(int i=0;i<length;i++){
|
for(int i=0;i<length;i++){
|
||||||
printf("%.2x ", toprint[i]);
|
printf("%.2x ", ((byte *) toprint)[i]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug_print_bytes(__attribute__((unused)) const char* label, __attribute__((unused)) byte *toprint, __attribute__((unused)) int length){
|
void debug_print_bytes(__attribute__((unused)) const char* label, __attribute__((unused)) void *toprint, __attribute__((unused)) int length){
|
||||||
#ifdef INSECURE_CTM_DEBUG_PRINT
|
#ifdef INSECURE_CTM_DEBUG_PRINT
|
||||||
print_bytes(label, toprint, length);
|
print_bytes(label, toprint, length);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
// Uncomment the line below to enable debug prints (including private keys!) - use for development only, this is insecure
|
// Uncomment the line below to enable debug prints (including private keys!) - use for development only, this is insecure
|
||||||
#define INSECURE_CTM_DEBUG_PRINT
|
#define INSECURE_CTM_DEBUG_PRINT
|
||||||
|
|
||||||
void print_bytes(const char* label, byte *toprint, int length);
|
void print_bytes(const char* label, void *toprint, int length);
|
||||||
void debug_print_bytes(__attribute__((unused)) const char* label, __attribute__((unused)) byte *toprint, __attribute__((unused)) int length);
|
void debug_print_bytes(__attribute__((unused)) const char* label, __attribute__((unused)) void *toprint, __attribute__((unused)) int length);
|
||||||
void print_scalar(const char* label, blst_scalar *toprint);
|
void print_scalar(const char* label, blst_scalar *toprint);
|
||||||
void debug_print_scalar(__attribute__((unused)) const char* label, __attribute__((unused)) blst_scalar *toprint);
|
void debug_print_scalar(__attribute__((unused)) const char* label, __attribute__((unused)) blst_scalar *toprint);
|
||||||
|
|
||||||
|
|
14
fstoken.h
14
fstoken.h
|
@ -1,17 +1,27 @@
|
||||||
#ifndef __FSTOKEN_H__
|
#ifndef __FSTOKEN_H__
|
||||||
#define __FSTOKEN_H__
|
#define __FSTOKEN_H__
|
||||||
#include "blst/blst.h"
|
#include "blst/blst.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define IDBITS_DEFAULT 128
|
#define IDBITS_DEFAULT 128
|
||||||
#define IDBITS_MAX 256
|
#define IDBITS_MAX 256
|
||||||
#define HASHBITS_DEFAULT 256
|
#define HASHBITS_DEFAULT 256
|
||||||
#define HASHBITS_MAX 256
|
#define HASHBITS_MAX 256
|
||||||
|
|
||||||
|
// For efficiency's sake, structs intended for use with the FemtoStar Protocol must be strictly-aligned without padding, with little-endian byte ordering.
|
||||||
|
// This avoids wasting network capacity on padding, and avoids the performance impact of reordering on most modern platforms (most importantly x86 and RISC-V)
|
||||||
|
// while ensuring compatibility with strict-alignment architectures. Take note: This is NOT typical network-order!
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
|
#pragma scalar_storage_order little-endian
|
||||||
|
|
||||||
|
uint8_t target_descriptor_version;
|
||||||
|
bool sk_available;
|
||||||
|
uint16_t idbits;
|
||||||
|
uint16_t hashbits;
|
||||||
byte sk[32];
|
byte sk[32];
|
||||||
byte pk[96];
|
byte pk[96];
|
||||||
uint8_t idbits;
|
|
||||||
uint8_t hashbits;
|
|
||||||
} target_descriptor;
|
} target_descriptor;
|
||||||
|
|
||||||
void fstoken_keygen(byte* ikm, byte* sk_byte, byte* pk_byte);
|
void fstoken_keygen(byte* ikm, byte* sk_byte, byte* pk_byte);
|
||||||
|
|
Loading…
Reference in a new issue