diff --git a/tool/util.c b/tool/util.c index f08af50..deb2ee9 100644 --- a/tool/util.c +++ b/tool/util.c @@ -205,6 +205,28 @@ int get_object_id(enum enum_slot slot) { return object; } +int key_to_object_id(int key) { + int object; + + switch(key) { + case 0x9a: + object = YKPIV_OBJ_AUTHENTICATION; + break; + case 0x9c: + object = YKPIV_OBJ_SIGNATURE; + break; + case 0x9d: + object = YKPIV_OBJ_KEY_MANAGEMENT; + break; + case 0x9e: + object = YKPIV_OBJ_CARD_AUTH; + break; + default: + object = 0; + } + return object; +} + bool set_component_with_len(unsigned char **in_ptr, const BIGNUM *bn, int element_len) { int real_len = BN_num_bytes(bn); *in_ptr += set_length(*in_ptr, element_len); diff --git a/tool/util.h b/tool/util.h index 2e619be..b6e4e21 100644 --- a/tool/util.h +++ b/tool/util.h @@ -44,6 +44,7 @@ X509_NAME *parse_name(const char*); unsigned char get_algorithm(EVP_PKEY*); FILE *open_file(const char*, int); int get_object_id(enum enum_slot slot); +int key_to_object_id(int key); bool set_component_with_len(unsigned char**, const BIGNUM*, int); bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*, unsigned int*, int); diff --git a/ykcs11/debug.h b/ykcs11/debug.h index 5debc5d..a89f49c 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -1,7 +1,7 @@ #ifndef DEBUG_H #define DEBUG_H -#define YKCS11_DBG 0 // General debug, must be either 1 or 0 +#define YKCS11_DBG 1 // General debug, must be either 1 or 0 #define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 #define D(x) do { \ diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index f4e8964..cea47c8 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -33,7 +33,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { return CKR_OK; } -#include "debug.h" + CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ULONG key_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { @@ -69,7 +69,6 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ goto create_empty_cert_cleanup; data_ptr = in + 5; - dump_hex(in, in_len, stderr, CK_TRUE); if (*data_ptr != 0x81) goto create_empty_cert_cleanup; @@ -132,10 +131,6 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ if (X509_set_pubkey(cert, key) == 0) // TODO: there is also X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); goto create_empty_cert_cleanup; - p = in; - if ((*out_len = i2d_X509(cert, &p)) == 0) - goto create_empty_cert_cleanup; - // TODO: add more info like issuer? tm = ASN1_TIME_new(); if (tm == NULL) @@ -145,6 +140,19 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ X509_set_notBefore(cert, tm); X509_set_notAfter(cert, tm); + len = i2d_X509(cert, NULL); + if (len < 0) + goto create_empty_cert_cleanup; + + if (len > *out_len) { + rv = CKR_BUFFER_TOO_SMALL; + goto create_empty_cert_cleanup; + } + + p = in; + if ((*out_len = i2d_X509(cert, &p)) == 0) + goto create_empty_cert_cleanup; + /* TODO REMOVE THIS */ BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE); @@ -152,7 +160,7 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ BIO_free(STDout); /********************/ - + rv = CKR_OK; create_empty_cert_cleanup: diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index f6b285e..1571182 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -1,13 +1,15 @@ #include "token_vendors.h" #include "yubico_token.h" - +#include +#include "debug.h" static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE key, CK_ULONG key_len) { // TODO: make a function in ykpiv for this unsigned char in_data[5]; unsigned char data[1024]; unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0}; + unsigned char *certptr; unsigned long recv_len = sizeof(data); - unsigned long received = 0; + int len_bytes; int sw; CK_RV rv; @@ -21,15 +23,27 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE switch(key_len) { case 2048: - in_data[4] = YKPIV_ALGO_RSA2048; + if (rsa == CK_TRUE) + in_data[4] = YKPIV_ALGO_RSA2048; + else + return CKR_FUNCTION_FAILED; + break; case 1024: - in_data[4] = YKPIV_ALGO_RSA1024; + if (rsa == CK_TRUE) + in_data[4] = YKPIV_ALGO_RSA1024; + else + return CKR_FUNCTION_FAILED; + break; case 256: - in_data[4] = YKPIV_ALGO_ECCP256; + if (rsa == CK_FALSE) + in_data[4] = YKPIV_ALGO_ECCP256; + else + return CKR_FUNCTION_FAILED; + break; default: @@ -40,15 +54,36 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE sw != 0x9000) return CKR_DEVICE_ERROR; - - /* to drop the 90 00 and the 7f 49 at the start */ - received += recv_len - 4; - - - /* Create a new empty certificate for the key */ - if ((rv = do_create_empty_cert(data, recv_len, rsa, key_len, in_data, &recv_len)) != CKR_OK) + // Create a new empty certificate for the key + recv_len = sizeof(data); + if ((rv = do_create_empty_cert(data, recv_len, rsa, key_len, data, &recv_len)) != CKR_OK) return rv; - + + if (recv_len < 0x80) + len_bytes = 1; + else if (recv_len < 0xff) + len_bytes = 2; + else + len_bytes = 3; + + certptr = data; + memmove(data + len_bytes + 1, data, recv_len); + + *certptr++ = 0x70; + certptr += set_length(certptr, recv_len); + certptr += recv_len; + *certptr++ = 0x71; + *certptr++ = 1; + *certptr++ = 0; /* certinfo (gzip etc) */ + *certptr++ = 0xfe; /* LRC */ + *certptr++ = 0; + + dump_hex(data, (size_t)(certptr - data), stderr, CK_TRUE); + + // Store the certificate into the token + if (ykpiv_save_object(state, key_to_object_id(key), data, (size_t)(certptr - data)) != YKPIV_OK) + return CKR_DEVICE_ERROR; + return CKR_OK; }