Tokens work now, proper verification. Working on shortening.
This commit is contained in:
parent
f35923ab74
commit
0cabf2536b
6 changed files with 281 additions and 4 deletions
22
base64.c
22
base64.c
|
@ -3,6 +3,7 @@ This is derived from the libb64 project, which has been placed in the public dom
|
||||||
For details, see http://sourceforge.net/projects/libb64
|
For details, see http://sourceforge.net/projects/libb64
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
|
||||||
int base64_decode_value(char value_in)
|
int base64_decode_value(char value_in)
|
||||||
|
@ -212,3 +213,24 @@ void base64_decode_oneshot(char* input, int input_len, char* output){
|
||||||
base64_init_decodestate(&s);
|
base64_init_decodestate(&s);
|
||||||
base64_decode_block(input, input_len, output, &s);
|
base64_decode_block(input, input_len, output, &s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provides the length of the binary you would get if you decoded base64 string b64, accounting for padding
|
||||||
|
int base64_binlength(char* b64){
|
||||||
|
int length, padding;
|
||||||
|
length = strlen(b64);
|
||||||
|
|
||||||
|
if(length % 4 != 0) return -1; // return -1 if length is not divisible by four (i.e. if invalid base64)
|
||||||
|
|
||||||
|
// somewhat messy way to determine how many bytes of padding are at the end of a base64 string
|
||||||
|
if(b64[length - 1] == '=' && b64[length - 2] == '=' && b64[length - 3] == '='){padding = 3;}
|
||||||
|
else if(b64[length - 1] == '=' && b64[length - 2] == '='){padding = 2;}
|
||||||
|
else if(b64[length - 1] == '='){padding = 1;}
|
||||||
|
else{padding = 0;}
|
||||||
|
|
||||||
|
return(((length / 4) * 3) - padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provides the base64 length of a binary of length binlength bytes
|
||||||
|
int base64_base64length(int binlength){
|
||||||
|
return(((binlength + 2) / 3) * 4);
|
||||||
|
}
|
2
base64.h
2
base64.h
|
@ -48,5 +48,7 @@ int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
|
||||||
|
|
||||||
void base64_encode_oneshot(char* input, int input_len, char* output);
|
void base64_encode_oneshot(char* input, int input_len, char* output);
|
||||||
void base64_decode_oneshot(char* input, int input_len, char* output);
|
void base64_decode_oneshot(char* input, int input_len, char* output);
|
||||||
|
int base64_binlength(char* b64);
|
||||||
|
int base64_base64length(int binlength);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
223
ctm.c
223
ctm.c
|
@ -35,12 +35,16 @@ void print_help(char* name){
|
||||||
printf("%s ireq [targ] [id] [factor] - interactively generate a Token Request Code for target [targ] using a set Token ID [id] and Blinding Factor [factor]\n", name);
|
printf("%s ireq [targ] [id] [factor] - interactively generate a Token Request Code for target [targ] using a set Token ID [id] and Blinding Factor [factor]\n", name);
|
||||||
printf("%s sign [targ] [req] - generate a signature for Token Request Code [req], on target [targ]\n", name);
|
printf("%s sign [targ] [req] - generate a signature for Token Request Code [req], on target [targ]\n", name);
|
||||||
printf("%s bsign [targ] - bulk-sign token requests, accepting Token Request Codes on stdin and outputting signatures to stdout\n", name);
|
printf("%s bsign [targ] - bulk-sign token requests, accepting Token Request Codes on stdin and outputting signatures to stdout\n", name);
|
||||||
|
printf("%s verify [targ] [token] - verify token [token] against target [targ], as base64 - returns 0 on verified\n", name);
|
||||||
|
printf("%s bverify [targ] - bulk-verify tokens against target [targ], accepting base64 tokens on stdin and outputting 0 (verified) or 1 to stdout\n", name);
|
||||||
|
printf("%s inspect [targ] [token] - inpect a token [token] for target [targ], to see its token ID and signature\n", name);
|
||||||
|
printf("%s shorten [targ] [token] - shorten a token [token] for target [targ], generating a symmetrically-verifiable short token\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_targ_path(char* target, char** targ_path){
|
int get_targ_path(char* target, char** targ_path){
|
||||||
int path_len;
|
int path_len;
|
||||||
|
|
||||||
path_len = strlen(token_path) + strlen(target) + 17;
|
path_len = strlen(token_path) + strlen(target) + 17; //string length of "/targets/", ".target", and null terminator
|
||||||
|
|
||||||
*targ_path = malloc(path_len);
|
*targ_path = malloc(path_len);
|
||||||
if(*targ_path == NULL) return 1;
|
if(*targ_path == NULL) return 1;
|
||||||
|
@ -53,7 +57,7 @@ int get_targ_path(char* target, char** targ_path){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_target(char* targ_name, fstoken_target_descriptor* target){ // pk/sk/idbits/hasbits pointers can be NULL if you don't want to read those
|
int get_target(char* targ_name, fstoken_target_descriptor* target){
|
||||||
FILE *targ_file;
|
FILE *targ_file;
|
||||||
char *targ_path;
|
char *targ_path;
|
||||||
|
|
||||||
|
@ -81,6 +85,154 @@ int get_fixed_length(char* dest, size_t dest_size){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int decode_base64_token(fstoken_target_descriptor* target, fstoken_token* token, char* token_b64){
|
||||||
|
int token_length, target_token_length;
|
||||||
|
|
||||||
|
target_token_length = fstoken_target_token_length(target);
|
||||||
|
token_length = base64_binlength(token_b64);
|
||||||
|
|
||||||
|
if(token_length == -1){
|
||||||
|
fprintf(stderr, "Invalid base64 provided\n");
|
||||||
|
return 3; // should be an enum
|
||||||
|
}
|
||||||
|
|
||||||
|
if(token_length != target_token_length){
|
||||||
|
fprintf(stderr, "Provided token (%i bytes) of incorrect length for specified target (%i bytes).\n", token_length, target_token_length);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
base64_decode_oneshot(token_b64, strlen(token_b64), (char*) token);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int inspect_token(char* targ_name, char* token_b64){
|
||||||
|
fstoken_target_descriptor target;
|
||||||
|
fstoken_token token;
|
||||||
|
int targ_idbytes;
|
||||||
|
|
||||||
|
if(!get_target(targ_name, &target)){
|
||||||
|
printf("Invalid target %s\n", targ_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(decode_base64_token(&target, &token, token_b64)){
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fstoken_verify_token(&token, &target) == 0){
|
||||||
|
printf("Token is valid for target %s.\n", targ_name);
|
||||||
|
}else{
|
||||||
|
printf("Token is not valid for target!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
targ_idbytes = (target.idbits + 7) / 8;
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
print_bytes("Signature (hex): ", token.signature, 48, ' ');
|
||||||
|
printf("Signature (base64): ");
|
||||||
|
print_base64(token.signature, 48);
|
||||||
|
printf("\n");
|
||||||
|
print_bytes("Token ID (hex): ", token.token_id, targ_idbytes, ' ');
|
||||||
|
printf("Token ID (base64): ");
|
||||||
|
print_base64(token.token_id, targ_idbytes);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receives tokens on stdin and provides 0 (valid), 1 (invalid), or 2/3/4 (various bad input) to stdout, with additional messages on stderr in case of error
|
||||||
|
int verify_bulk(char* targ_name){
|
||||||
|
char token_b64[((((HASHBYTES_MAX + IDBYTES_MAX) + 2) / 3) * 4) + 2]; // maximum possible base64 length + 2 characters for get_fixed_length
|
||||||
|
fstoken_target_descriptor target;
|
||||||
|
fstoken_token token;
|
||||||
|
int target_token_b64_length, result;
|
||||||
|
|
||||||
|
if(!get_target(targ_name, &target)){
|
||||||
|
fprintf(stderr, "Invalid target %s\n", targ_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_token_b64_length = base64_base64length(fstoken_target_token_length(&target));
|
||||||
|
|
||||||
|
printf("Target token length %i\n", target_token_b64_length);
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
if(get_fixed_length(token_b64, target_token_b64_length + 2)){ // +2 because of get_fixed_length, I should probably change that to be not stupid
|
||||||
|
printf("2");
|
||||||
|
fprintf(stderr, "Provided token base64 incorrect length for target (should be %i characters).\n", target_token_b64_length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = decode_base64_token(&target, &token, token_b64);
|
||||||
|
|
||||||
|
if(result){
|
||||||
|
printf("%i", result);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fstoken_verify_token(&token, &target) == 0){
|
||||||
|
printf("0");
|
||||||
|
}else{
|
||||||
|
printf("1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int verify_single(char* targ_name, char* token_b64){
|
||||||
|
fstoken_target_descriptor target;
|
||||||
|
fstoken_token token;
|
||||||
|
|
||||||
|
if(!get_target(targ_name, &target)){
|
||||||
|
printf("Invalid target %s\n", targ_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
decode_base64_token(&target, &token, token_b64);
|
||||||
|
|
||||||
|
if(fstoken_verify_token(&token, &target) == 0){
|
||||||
|
printf("Verified!\n");
|
||||||
|
return 0;
|
||||||
|
}else{
|
||||||
|
printf("Not verified!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sign_bulk(char* targ_name){
|
||||||
|
char req_b64[66];
|
||||||
|
fstoken_request req;
|
||||||
|
fstoken_target_descriptor targ;
|
||||||
|
fstoken_signature sig;
|
||||||
|
|
||||||
|
if(get_target(targ_name, &targ) != 2){
|
||||||
|
printf("Target or private key unavailable. Are you sure you have a private key for this target?\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Bulk signing started. Enter token requests\n");
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
if(get_fixed_length(req_b64, sizeof(req_b64))){
|
||||||
|
fprintf(stderr, "Invalid request length\n");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
base64_decode_oneshot((char*) req_b64, 64, (char*) req.id_blind);
|
||||||
|
|
||||||
|
//debug_print_bytes("Signature hex: ", req.id_blind, 48);
|
||||||
|
|
||||||
|
if(fstoken_sign_request(&req, &sig, &targ)){
|
||||||
|
fprintf(stderr, "Signing failed. Is the token request valid?\n");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
print_base64(sig.signature, 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sign_single(char* targ_name, char* req_b64){
|
int sign_single(char* targ_name, char* req_b64){
|
||||||
fstoken_request req;
|
fstoken_request req;
|
||||||
fstoken_target_descriptor targ;
|
fstoken_target_descriptor targ;
|
||||||
|
@ -105,6 +257,19 @@ int sign_single(char* targ_name, char* req_b64){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*int verify_token(char* targ_name, byte* token_bytes){
|
||||||
|
fstoken_target_descriptor target;
|
||||||
|
fstoken_token token;
|
||||||
|
int token_length;
|
||||||
|
|
||||||
|
if(!get_target(targ_name, &target)){
|
||||||
|
printf("Invalid target %s\n", targ_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//base64_decode_oneshot(token_bytes, )
|
||||||
|
}*/
|
||||||
|
|
||||||
int interactive_request(char* targ_name, byte* token_id, byte* blinding_factor){
|
int interactive_request(char* targ_name, byte* token_id, byte* blinding_factor){
|
||||||
fstoken_request req;
|
fstoken_request req;
|
||||||
fstoken_request_descriptor reqdesc;
|
fstoken_request_descriptor reqdesc;
|
||||||
|
@ -150,6 +315,20 @@ int interactive_request(char* targ_name, byte* token_id, byte* blinding_factor){
|
||||||
printf("\nToken: ");
|
printf("\nToken: ");
|
||||||
print_base64(&token, token_length);
|
print_base64(&token, token_length);
|
||||||
|
|
||||||
|
//token.token_id[3] = '\0';
|
||||||
|
|
||||||
|
switch(fstoken_verify_token(&token, &target)){
|
||||||
|
case 0:
|
||||||
|
printf("Verified!\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf("Signature does not match Token ID for target. Did the signer sign for the wrong target or sign the wrong request?\n");
|
||||||
|
return 1;
|
||||||
|
case 2:
|
||||||
|
printf("Invalid signature (not in G1 group - either something has gone very wrong or the signer is attempting to do something malicious)\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,6 +679,44 @@ int main(int argc, char *argv[]){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sign_single(argv[2], argv[3]);
|
return sign_single(argv[2], argv[3]);
|
||||||
|
}else if(strcmp(argv[1], "bsign") == 0){
|
||||||
|
if(argc != 3){
|
||||||
|
fprintf(stderr, "Please provide a target [targ]. See help.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sign_bulk(argv[2]);
|
||||||
|
}else if(strcmp(argv[1], "verify") == 0){
|
||||||
|
if(argc != 4){
|
||||||
|
fprintf(stderr, "Please provide a target [targ] and a token [token]. See help.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(argv[3]) < 68){
|
||||||
|
fprintf(stderr, "Token must be at least 49 bytes (68 base64 characters).\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(verify_single(argv[2], argv[3]));
|
||||||
|
}else if(strcmp(argv[1], "bverify") == 0){
|
||||||
|
if(argc != 3){
|
||||||
|
fprintf(stderr, "Please provide a target [targ]. See help.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_bulk(argv[2]);
|
||||||
|
}else if(strcmp(argv[1], "inspect") == 0){
|
||||||
|
if(argc != 4){
|
||||||
|
fprintf(stderr, "Please provide a target [targ] and a token [token]. See help.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(argv[3]) < 68){
|
||||||
|
fprintf(stderr, "Token must be at least 49 bytes (68 base64 characters).\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(inspect_token(argv[2], argv[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,6 +20,7 @@ void print_base64(void *toprint, int input_len){
|
||||||
buffer_size = (((input_len + 2) / 3) * 4) + 1;
|
buffer_size = (((input_len + 2) / 3) * 4) + 1;
|
||||||
|
|
||||||
output = malloc(buffer_size); //create a buffer large enough for the base64'd input, including with padding if need be
|
output = malloc(buffer_size); //create a buffer large enough for the base64'd input, including with padding if need be
|
||||||
|
if(output == NULL) return;
|
||||||
|
|
||||||
base64_encode_oneshot(toprint, input_len, output);
|
base64_encode_oneshot(toprint, input_len, output);
|
||||||
printf("%s\n", output);
|
printf("%s\n", output);
|
||||||
|
|
25
fstoken.c
25
fstoken.c
|
@ -117,6 +117,26 @@ int fstoken_gen_token(fstoken_request_descriptor* req, fstoken_signature* sig, f
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0 = valid token, 1 = signature check failed, 2 = signature point invalid
|
||||||
|
int fstoken_verify_token(fstoken_token* token, fstoken_target_descriptor* targ){
|
||||||
|
int targ_idbytes;
|
||||||
|
blst_p1_affine sig;
|
||||||
|
blst_p2_affine pk;
|
||||||
|
|
||||||
|
blst_p1_uncompress(&sig, token->signature);
|
||||||
|
blst_p2_uncompress(&pk, targ->pk);
|
||||||
|
|
||||||
|
BLST_ERROR returned;
|
||||||
|
|
||||||
|
if(!blst_p1_affine_in_g1(&sig)) return 2;
|
||||||
|
|
||||||
|
targ_idbytes = (targ->idbits + 7) / 8;
|
||||||
|
|
||||||
|
returned = blst_core_verify_pk_in_g2(&pk, &sig, 1, token->token_id, targ_idbytes, FSTOKEN_DST, strlen((char *) FSTOKEN_DST), targ->pk, 96);
|
||||||
|
|
||||||
|
return (returned != BLST_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
void bit_truncated_copy(byte* src, byte* dest, size_t destlen, int bits){
|
void bit_truncated_copy(byte* src, byte* dest, size_t destlen, int bits){
|
||||||
uint8_t bitmask;
|
uint8_t bitmask;
|
||||||
int bytes;
|
int bytes;
|
||||||
|
@ -131,3 +151,8 @@ void bit_truncated_copy(byte* src, byte* dest, size_t destlen, int bits){
|
||||||
//printf("mask: 0x%0x\n", bitmask);
|
//printf("mask: 0x%0x\n", bitmask);
|
||||||
dest[bytes - 1] = dest[bytes - 1] & bitmask;
|
dest[bytes - 1] = dest[bytes - 1] & bitmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to get the length (in bytes) of an (unshortened) token for the target
|
||||||
|
int fstoken_target_token_length(fstoken_target_descriptor* target){
|
||||||
|
return 48 + (target->idbits + 7) / 8;
|
||||||
|
}
|
12
fstoken.h
12
fstoken.h
|
@ -25,7 +25,7 @@
|
||||||
// This avoids wasting network capacity on padding, and avoids the performance impact of reordering on most modern platforms (most importantly x86 and RISC-V)
|
// 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!
|
// while ensuring compatibility with strict-alignment architectures. Take note: This is NOT typical network-order!
|
||||||
|
|
||||||
// Additionally, note that most structs do not explicitly include what target they are for (even the target descriptor!). Keeping what is for what target is
|
// Additionally, note that most structs do not explicitly include what target they are for (even the target descriptor!). Tracking what is for what target is
|
||||||
// not a core part of fstoken, and is the responsibility of the software using fstoken (e.g. ctm or an implementation of fsp). This keeps tokens light in
|
// not a core part of fstoken, and is the responsibility of the software using fstoken (e.g. ctm or an implementation of fsp). This keeps tokens light in
|
||||||
// situations where which target is relevant is unambiguous (e.g. in the session setup with a satellite, where the satellite is always the same target).
|
// situations where which target is relevant is unambiguous (e.g. in the session setup with a satellite, where the satellite is always the same target).
|
||||||
|
|
||||||
|
@ -70,11 +70,21 @@ typedef struct{
|
||||||
byte token_id[IDBYTES_MAX];
|
byte token_id[IDBYTES_MAX];
|
||||||
} fstoken_token;
|
} fstoken_token;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
#pragma scalar_storage_order little-endian
|
||||||
|
|
||||||
|
byte hash[HASHBYTES_MAX];
|
||||||
|
byte token_id[IDBYTES_MAX];
|
||||||
|
} fstoken_short_token;
|
||||||
|
|
||||||
void fstoken_keygen(byte* ikm, byte* sk_byte, byte* pk_byte);
|
void fstoken_keygen(byte* ikm, byte* sk_byte, byte* pk_byte);
|
||||||
void fstoken_get_pk_from_sk(byte* sk_byte, byte* pk_byte);
|
void fstoken_get_pk_from_sk(byte* sk_byte, byte* pk_byte);
|
||||||
void bit_truncated_copy(byte* src, byte* dest, size_t destlen, int bits);
|
void bit_truncated_copy(byte* src, byte* dest, size_t destlen, int bits);
|
||||||
void fstoken_gen_request(fstoken_request* req, fstoken_request_descriptor* reqdesc, fstoken_target_descriptor* target, byte* token_id, byte* blinding_factor);
|
void fstoken_gen_request(fstoken_request* req, fstoken_request_descriptor* reqdesc, fstoken_target_descriptor* target, byte* token_id, byte* blinding_factor);
|
||||||
int fstoken_sign_request(fstoken_request* req, fstoken_signature* sig, fstoken_target_descriptor* targ);
|
int fstoken_sign_request(fstoken_request* req, fstoken_signature* sig, fstoken_target_descriptor* targ);
|
||||||
int fstoken_gen_token(fstoken_request_descriptor* req, fstoken_signature* sig, fstoken_token* token);
|
int fstoken_gen_token(fstoken_request_descriptor* req, fstoken_signature* sig, fstoken_token* token);
|
||||||
|
int fstoken_verify_token(fstoken_token* token, fstoken_target_descriptor* targ);
|
||||||
|
int fstoken_shorten_token(fstoken_token* token, fstoken_short_token short_token);
|
||||||
|
int fstoken_target_token_length(fstoken_target_descriptor* target);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue