move sign_data() function to library
This commit is contained in:
@@ -33,6 +33,7 @@ libykpiv_la_SOURCES = ykpiv.c version.c ykpiv.pc.in ykpiv.map internal.h
|
|||||||
libykpiv_la_SOURCES += error.c
|
libykpiv_la_SOURCES += error.c
|
||||||
libykpiv_la_includedir = $(includedir)/ykpiv
|
libykpiv_la_includedir = $(includedir)/ykpiv
|
||||||
libykpiv_la_include_HEADERS = ykpiv.h ykpiv-version.h
|
libykpiv_la_include_HEADERS = ykpiv.h ykpiv-version.h
|
||||||
|
EXTRA_libykpiv_la_DEPENDENCIES = ykpiv.map
|
||||||
|
|
||||||
libykpiv_la_LIBADD = $(OPENSSL_LIBS) $(PCSC_LIBS)
|
libykpiv_la_LIBADD = $(OPENSSL_LIBS) $(PCSC_LIBS)
|
||||||
libykpiv_la_LIBADD += $(LTLIBWINSCARD) $(PCSC_MACOSX_LIBS)
|
libykpiv_la_LIBADD += $(LTLIBWINSCARD) $(PCSC_MACOSX_LIBS)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ static const err_t errors[] = {
|
|||||||
ERR (YKPIV_RANDOMNESS_ERROR, "Error getting randomness"),
|
ERR (YKPIV_RANDOMNESS_ERROR, "Error getting randomness"),
|
||||||
ERR (YKPIV_GENERIC_ERROR, "Something went wrong."),
|
ERR (YKPIV_GENERIC_ERROR, "Something went wrong."),
|
||||||
ERR (YKPIV_KEY_ERROR, "Error in key"),
|
ERR (YKPIV_KEY_ERROR, "Error in key"),
|
||||||
|
ERR (YKPIV_PARSE_ERROR, "Parse error"),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+107
@@ -45,6 +45,36 @@ static void dump_hex(const unsigned char *buf, unsigned int len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_length(unsigned char *buffer, int length) {
|
||||||
|
if(length < 0x80) {
|
||||||
|
*buffer++ = length;
|
||||||
|
return 1;
|
||||||
|
} else if(length < 0xff) {
|
||||||
|
*buffer++ = 0x81;
|
||||||
|
*buffer++ = length;
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
*buffer++ = 0x82;
|
||||||
|
*buffer++ = (length >> 8) & 0xff;
|
||||||
|
*buffer++ = length & 0xff;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_length(unsigned char *buffer, int *len) {
|
||||||
|
if(buffer[0] < 0x81) {
|
||||||
|
*len = buffer[0];
|
||||||
|
return 1;
|
||||||
|
} else if((*buffer & 0x7f) == 1) {
|
||||||
|
*len = buffer[1];
|
||||||
|
return 2;
|
||||||
|
} else if((*buffer & 0x7f) == 2) {
|
||||||
|
*len = (buffer[1] << 8) + buffer[2];
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose) {
|
ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose) {
|
||||||
ykpiv_state *s = malloc(sizeof(ykpiv_state));
|
ykpiv_state *s = malloc(sizeof(ykpiv_state));
|
||||||
if(s == NULL) {
|
if(s == NULL) {
|
||||||
@@ -428,3 +458,80 @@ ykpiv_rc ykpiv_parse_key(ykpiv_state *state,
|
|||||||
}
|
}
|
||||||
return YKPIV_OK;
|
return YKPIV_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ykpiv_rc ykpiv_sign_data(ykpiv_state *state,
|
||||||
|
const unsigned char *sign_in, int in_len,
|
||||||
|
unsigned char *sign_out, int *out_len,
|
||||||
|
unsigned char algorithm, unsigned char key) {
|
||||||
|
|
||||||
|
unsigned char indata[1024];
|
||||||
|
unsigned char *dataptr = indata;
|
||||||
|
unsigned char data[1024];
|
||||||
|
unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key};
|
||||||
|
unsigned long recv_len = sizeof(data);
|
||||||
|
int sw;
|
||||||
|
int bytes;
|
||||||
|
int len = 0;
|
||||||
|
ykpiv_rc res;
|
||||||
|
|
||||||
|
if(in_len > 1000) {
|
||||||
|
return YKPIV_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in_len < 0x80) {
|
||||||
|
bytes = 1;
|
||||||
|
} else if(in_len < 0xff) {
|
||||||
|
bytes = 2;
|
||||||
|
} else {
|
||||||
|
bytes = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dataptr++ = 0x7c;
|
||||||
|
dataptr += set_length(dataptr, in_len + bytes + 3);
|
||||||
|
*dataptr++ = 0x82;
|
||||||
|
*dataptr++ = 0x00;
|
||||||
|
*dataptr++ = 0x81;
|
||||||
|
dataptr += set_length(dataptr, in_len);
|
||||||
|
memcpy(dataptr, sign_in, (size_t)in_len);
|
||||||
|
dataptr += in_len;
|
||||||
|
|
||||||
|
if((res = ykpiv_transfer_data(state, templ, indata, dataptr - indata, data,
|
||||||
|
&recv_len, &sw)) != YKPIV_OK) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "Sign command failed to communicate.\n");
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
} else if(sw != 0x9000) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "Failed sign command with code %x.\n", sw);
|
||||||
|
}
|
||||||
|
return YKPIV_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
/* skip the first 7c tag */
|
||||||
|
if(data[0] != 0x7c) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "Failed parsing signature reply.\n");
|
||||||
|
}
|
||||||
|
return YKPIV_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
dataptr = data + 1;
|
||||||
|
dataptr += get_length(dataptr, &len);
|
||||||
|
/* skip the 82 tag */
|
||||||
|
if(*dataptr != 0x82) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "Failed parsing signature reply.\n");
|
||||||
|
}
|
||||||
|
return YKPIV_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
dataptr++;
|
||||||
|
dataptr += get_length(dataptr, &len);
|
||||||
|
if(len > *out_len) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "Wrong size on output buffer.\n");
|
||||||
|
}
|
||||||
|
return YKPIV_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
*out_len = len;
|
||||||
|
memcpy(sign_out, dataptr, len);
|
||||||
|
return YKPIV_OK;
|
||||||
|
}
|
||||||
|
|||||||
+15
-11
@@ -50,6 +50,7 @@ extern "C"
|
|||||||
YKPIV_RANDOMNESS_ERROR = -6,
|
YKPIV_RANDOMNESS_ERROR = -6,
|
||||||
YKPIV_GENERIC_ERROR = -7,
|
YKPIV_GENERIC_ERROR = -7,
|
||||||
YKPIV_KEY_ERROR = -8,
|
YKPIV_KEY_ERROR = -8,
|
||||||
|
YKPIV_PARSE_ERROR = -9,
|
||||||
} ykpiv_rc;
|
} ykpiv_rc;
|
||||||
|
|
||||||
const char *ykpiv_strerror(ykpiv_rc err);
|
const char *ykpiv_strerror(ykpiv_rc err);
|
||||||
@@ -68,22 +69,25 @@ extern "C"
|
|||||||
ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key);
|
ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key);
|
||||||
ykpiv_rc ykpiv_parse_key(ykpiv_state *state,
|
ykpiv_rc ykpiv_parse_key(ykpiv_state *state,
|
||||||
const char *key_in, unsigned char *key_out);
|
const char *key_in, unsigned char *key_out);
|
||||||
|
ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in,
|
||||||
|
int in_len,unsigned char *sign_out, int *out_len,
|
||||||
|
unsigned char algorithm, unsigned char key);
|
||||||
|
|
||||||
#define YKPIV_ALGO_3DES 0x03;
|
#define YKPIV_ALGO_3DES 0x03
|
||||||
#define YKPIV_ALGO_RSA1024 0x06;
|
#define YKPIV_ALGO_RSA1024 0x06
|
||||||
#define YKPIV_ALGO_RSA2048 0x07;
|
#define YKPIV_ALGO_RSA2048 0x07
|
||||||
#define YKPIV_ALGO_ECCP256 0x11;
|
#define YKPIV_ALGO_ECCP256 0x11
|
||||||
|
|
||||||
#define YKPIV_KEY_AUTHENTICATION 0x9a;
|
#define YKPIV_KEY_AUTHENTICATION 0x9a
|
||||||
#define YKPIV_KEY_CARDMGM 0x9b;
|
#define YKPIV_KEY_CARDMGM 0x9b
|
||||||
#define YKPIV_KEY_SIGNATURE 0x9c;
|
#define YKPIV_KEY_SIGNATURE 0x9c
|
||||||
#define YKPIV_KEY_KEYMGM 0x9d;
|
#define YKPIV_KEY_KEYMGM 0x9d
|
||||||
#define YKPIV_KEY_CARDAUTH 0x9e;
|
#define YKPIV_KEY_CARDAUTH 0x9e
|
||||||
|
|
||||||
#define YKPIV_INS_AUTHENTICATE 0x87;
|
#define YKPIV_INS_AUTHENTICATE 0x87
|
||||||
|
|
||||||
/* Yubico vendor specific instructions */
|
/* Yubico vendor specific instructions */
|
||||||
#define YKPIV_INS_SET_MGMKEY 0xff;
|
#define YKPIV_INS_SET_MGMKEY 0xff
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ global:
|
|||||||
ykpiv_authenticate;
|
ykpiv_authenticate;
|
||||||
ykpiv_set_mgmkey;
|
ykpiv_set_mgmkey;
|
||||||
ykpiv_parse_key;
|
ykpiv_parse_key;
|
||||||
|
ykpiv_sign_data;
|
||||||
|
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
|
|||||||
+16
-60
@@ -90,8 +90,6 @@ static int get_length(unsigned char*, int*);
|
|||||||
static X509_NAME *parse_name(char*);
|
static X509_NAME *parse_name(char*);
|
||||||
static unsigned char get_algorithm(EVP_PKEY*);
|
static unsigned char get_algorithm(EVP_PKEY*);
|
||||||
static FILE *open_file(const char*, int);
|
static FILE *open_file(const char*, int);
|
||||||
static bool sign_data(ykpiv_state*, unsigned char*, int, unsigned char, unsigned char,
|
|
||||||
ASN1_BIT_STRING*);
|
|
||||||
static int get_object_id(enum enum_slot slot);
|
static int get_object_id(enum enum_slot slot);
|
||||||
|
|
||||||
static void print_version(ykpiv_state *state) {
|
static void print_version(ykpiv_state *state) {
|
||||||
@@ -634,8 +632,14 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
|||||||
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
||||||
goto request_out;
|
goto request_out;
|
||||||
}
|
}
|
||||||
if(sign_data(state, signinput, len, algorithm, key, req->signature) == false) {
|
{
|
||||||
goto request_out;
|
unsigned char signature[1024];
|
||||||
|
int sig_len = sizeof(signature);
|
||||||
|
if(ykpiv_sign_data(state, signinput, len, signature, &sig_len, algorithm, key)
|
||||||
|
!= YKPIV_OK) {
|
||||||
|
goto request_out;
|
||||||
|
}
|
||||||
|
M_ASN1_BIT_STRING_set(req->signature, signature, sig_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(key_format == key_format_arg_PEM) {
|
if(key_format == key_format_arg_PEM) {
|
||||||
@@ -764,8 +768,14 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
|||||||
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
||||||
goto selfsign_out;
|
goto selfsign_out;
|
||||||
}
|
}
|
||||||
if(sign_data(state, signinput, len, algorithm, key, x509->signature)) {
|
{
|
||||||
goto selfsign_out;
|
unsigned char signature[1024];
|
||||||
|
int sig_len = sizeof(signature);
|
||||||
|
if(ykpiv_sign_data(state, signinput, len, signature, &sig_len, algorithm, key)
|
||||||
|
!= YKPIV_OK) {
|
||||||
|
goto selfsign_out;
|
||||||
|
}
|
||||||
|
M_ASN1_BIT_STRING_set(x509->signature, signature, sig_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(key_format == key_format_arg_PEM) {
|
if(key_format == key_format_arg_PEM) {
|
||||||
@@ -913,60 +923,6 @@ static bool delete_certificate(ykpiv_state *state, enum enum_slot slot) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sign_data(ykpiv_state *state, unsigned char *signinput, int in_len,
|
|
||||||
unsigned char algorithm, unsigned char key, ASN1_BIT_STRING *sig) {
|
|
||||||
unsigned char indata[1024];
|
|
||||||
unsigned char *dataptr = indata;
|
|
||||||
unsigned char data[1024];
|
|
||||||
unsigned char templ[] = {0, 0x87, algorithm, key};
|
|
||||||
unsigned long recv_len = sizeof(data);
|
|
||||||
int sw;
|
|
||||||
int bytes;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if(in_len < 0x80) {
|
|
||||||
bytes = 1;
|
|
||||||
} else if(in_len < 0xff) {
|
|
||||||
bytes = 2;
|
|
||||||
} else {
|
|
||||||
bytes = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
*dataptr++ = 0x7c;
|
|
||||||
dataptr += set_length(dataptr, in_len + bytes + 3);
|
|
||||||
*dataptr++ = 0x82;
|
|
||||||
*dataptr++ = 0x00;
|
|
||||||
*dataptr++ = 0x81;
|
|
||||||
dataptr += set_length(dataptr, in_len);
|
|
||||||
memcpy(dataptr, signinput, (size_t)in_len);
|
|
||||||
dataptr += in_len;
|
|
||||||
|
|
||||||
if(ykpiv_transfer_data(state, templ, indata, dataptr - indata, data,
|
|
||||||
&recv_len, &sw) != YKPIV_OK) {
|
|
||||||
fprintf(stderr, "Sign command failed to communicate.\n");
|
|
||||||
return false;
|
|
||||||
} else if(sw != 0x9000) {
|
|
||||||
fprintf(stderr, "Failed sign command with code %x.\n", sw);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* skip the first 7c tag */
|
|
||||||
if(data[0] != 0x7c) {
|
|
||||||
fprintf(stderr, "Failed parsing signature reply.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
dataptr = data + 1;
|
|
||||||
dataptr += get_length(dataptr, &len);
|
|
||||||
/* skip the 82 tag */
|
|
||||||
if(*dataptr != 0x82) {
|
|
||||||
fprintf(stderr, "Failed parsing signature reply.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
dataptr++;
|
|
||||||
dataptr += get_length(dataptr, &len);
|
|
||||||
M_ASN1_BIT_STRING_set(sig, dataptr, len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FILE *open_file(const char *file_name, int mode) {
|
static FILE *open_file(const char *file_name, int mode) {
|
||||||
FILE *file;
|
FILE *file;
|
||||||
if(!strcmp(file_name, "-")) {
|
if(!strcmp(file_name, "-")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user