From f17d09f19c03900c21a63ac089287c77ca440235 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 27 May 2015 21:01:58 +0200 Subject: [PATCH 001/134] start adding secp384r1 --- lib/ykpiv.c | 25 ++++++++++++--------- lib/ykpiv.h | 1 + tool/cmdline.ggo | 2 +- tool/util.c | 2 ++ tool/yubico-piv-tool.c | 49 +++++++++++++++++++++++++++++++----------- 5 files changed, 56 insertions(+), 23 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index a02edd8..e907b19 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -508,7 +508,7 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key}; unsigned long recv_len = sizeof(data); unsigned char sign_in[256]; - size_t pad_len = 0; + size_t key_len = 0; int sw; size_t bytes; size_t len = 0; @@ -516,28 +516,33 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, switch(algorithm) { case YKPIV_ALGO_RSA1024: - pad_len = 128; + key_len = 128; case YKPIV_ALGO_RSA2048: - if(pad_len == 0) { - pad_len = 256; + if(key_len == 0) { + key_len = 256; } if(!decipher) { - if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) { + if(in_len + RSA_PKCS1_PADDING_SIZE > key_len) { return YKPIV_SIZE_ERROR; } - RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len); - in_len = pad_len; + RSA_padding_add_PKCS1_type_1(sign_in, key_len, raw_in, in_len); + in_len = key_len; } else { - if(in_len != pad_len) { + if(in_len != key_len) { return YKPIV_SIZE_ERROR; } memcpy(sign_in, raw_in, in_len); } break; case YKPIV_ALGO_ECCP256: - if(!decipher && in_len > 32) { + key_len = 32; + case YKPIV_ALGO_ECCP384: + if(key_len == 0) { + key_len = 48; + } + if(!decipher && in_len > key_len) { return YKPIV_SIZE_ERROR; - } else if(decipher && in_len != 65) { + } else if(decipher && in_len != (key_len * 2) + 1) { return YKPIV_SIZE_ERROR; } memcpy(sign_in, raw_in, in_len); diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 26a4a93..8333a86 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -89,6 +89,7 @@ extern "C" #define YKPIV_ALGO_RSA1024 0x06 #define YKPIV_ALGO_RSA2048 0x07 #define YKPIV_ALGO_ECCP256 0x11 +#define YKPIV_ALGO_ECCP384 0x14 #define YKPIV_KEY_AUTHENTICATION 0x9a #define YKPIV_KEY_CARDMGM 0x9b diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 16fbff6..2696b39 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -41,7 +41,7 @@ text " 9c is for Digital Signature (PIN always checked) 9d is for Key Management 9e is for Card Authentication (PIN never checked)\n" -option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256" enum optional default="RSA2048" +option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256","ECCP384" enum optional default="RSA2048" option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA512" enum optional default="SHA256" option "new-key" n "New authentication key to use" string optional option "pin-retries" - "Number of retries before the pin code is blocked" int optional dependon="puk-retries" diff --git a/tool/util.c b/tool/util.c index f08af50..f46b27d 100644 --- a/tool/util.c +++ b/tool/util.c @@ -80,6 +80,8 @@ unsigned char get_algorithm(EVP_PKEY *key) { int curve = EC_GROUP_get_curve_name(group); if(curve == NID_X9_62_prime256v1) { return YKPIV_ALGO_ECCP256; + } else if(curve == NID_secp384r1) { + return YKPIV_ALGO_ECCP384; } else { fprintf(stderr, "Unknown EC curve %d\n", curve); return 0; diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index a9b6139..fd7036d 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -138,6 +138,9 @@ static bool generate_key(ykpiv_state *state, const char *slot, case algorithm_arg_ECCP256: in_data[4] = YKPIV_ALGO_ECCP256; break; + case algorithm_arg_ECCP384: + in_data[4] = YKPIV_ALGO_ECCP384; + break; case algorithm__NULL: default: fprintf(stderr, "Unexepcted algorithm.\n"); @@ -189,24 +192,34 @@ static bool generate_key(ykpiv_state *state, const char *slot, rsa->n = bignum_n; rsa->e = bignum_e; EVP_PKEY_set1_RSA(public_key, rsa); - } else if(algorithm == algorithm_arg_ECCP256) { + } else if(algorithm == algorithm_arg_ECCP256 || algorithm == algorithm_arg_ECCP384) { EC_GROUP *group; unsigned char *data_ptr = data + 3; + int nid; + size_t len; + + if(algorithm == algorithm_arg_ECCP256) { + nid = NID_X9_62_prime256v1; + len = 65; + } else { + nid = NID_secp384r1; + len = 97; + } eckey = EC_KEY_new(); - group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - EC_GROUP_set_asn1_flag(group, NID_X9_62_prime256v1); + group = EC_GROUP_new_by_curve_name(nid); + EC_GROUP_set_asn1_flag(group, nid); EC_KEY_set_group(eckey, group); point = EC_POINT_new(group); if(*data_ptr++ != 0x86) { fprintf(stderr, "Failed to parse public key structure.\n"); goto generate_out; } - if(*data_ptr++ != 65) { /* the curve point should always be 65 bytes */ + if(*data_ptr++ != len) { /* the curve point should always be 65 bytes */ fprintf(stderr, "Unexpected length.\n"); goto generate_out; } - if(!EC_POINT_oct2point(group, point, data_ptr, 65, NULL)) { + if(!EC_POINT_oct2point(group, point, data_ptr, len, NULL)) { fprintf(stderr, "Failed to load public point.\n"); goto generate_out; } @@ -674,6 +687,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for } break; case YKPIV_ALGO_ECCP256: + case YKPIV_ALGO_ECCP384: signinput = digest + oid_len; len = digest_len; switch(hash) { @@ -866,6 +880,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo } break; case YKPIV_ALGO_ECCP256: + case YKPIV_ALGO_ECCP384: signinput = digest + oid_len; len = md_len; switch(hash) { @@ -1577,20 +1592,30 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot, } else { fprintf(stderr, "Failed unwrapping PKCS1 envelope.\n"); } - } else { - unsigned char secret[32]; - unsigned char secret2[32]; - unsigned char public_key[65]; + } else if(algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) { + unsigned char secret[48]; + unsigned char secret2[48]; + unsigned char public_key[97]; unsigned char *ptr = public_key; size_t len = sizeof(secret); EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pubkey); + int nid; + size_t key_len; - tmpkey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if(algorithm == YKPIV_ALGO_ECCP256) { + nid = NID_X9_62_prime256v1; + key_len = 32; + } else { + nid = NID_secp384r1; + key_len = 48; + } + + tmpkey = EC_KEY_new_by_curve_name(nid); EC_KEY_generate_key(tmpkey); ECDH_compute_key(secret, len, EC_KEY_get0_public_key(ec), tmpkey, NULL); i2o_ECPublicKey(tmpkey, &ptr); - if(ykpiv_decipher_data(state, public_key, sizeof(public_key), secret2, &len, algorithm, key) != YKPIV_OK) { + if(ykpiv_decipher_data(state, public_key, (key_len * 2) + 1, secret2, &len, algorithm, key) != YKPIV_OK) { fprintf(stderr, "Failed ECDH exchange!\n"); goto decipher_out; } @@ -1600,7 +1625,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot, fprintf(stderr, "ECDH card generated: "); dump_hex(secret2, len, stderr, true); } - if(memcmp(secret, secret2, 32) == 0) { + if(memcmp(secret, secret2, key_len) == 0) { fprintf(stderr, "Successfully performed ECDH exchange with card.\n"); ret = true; } else { From d06852959cf6fcb0d0fa496edead1de4cc716f40 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 27 May 2015 21:38:46 +0200 Subject: [PATCH 002/134] add sha384 hash and refactor some common patterns --- tool/cmdline.ggo | 2 +- tool/util.c | 105 +++++++++++++++++ tool/util.h | 3 + tool/yubico-piv-tool.c | 252 ++++++++--------------------------------- 4 files changed, 155 insertions(+), 207 deletions(-) diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 2696b39..25b606f 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -42,7 +42,7 @@ text " 9d is for Key Management 9e is for Card Authentication (PIN never checked)\n" option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256","ECCP384" enum optional default="RSA2048" -option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA512" enum optional default="SHA256" +option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA384","SHA512" enum optional default="SHA256" option "new-key" n "New authentication key to use" string optional option "pin-retries" - "Number of retries before the pin code is blocked" int optional dependon="puk-retries" option "puk-retries" - "Number of retries before the puk code is blocked" int optional dependon="pin-retries" diff --git a/tool/util.c b/tool/util.c index f46b27d..ac1654e 100644 --- a/tool/util.c +++ b/tool/util.c @@ -239,3 +239,108 @@ bool prepare_rsa_signature(const unsigned char *in, unsigned int in_len, unsigne *out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out); return true; } + +static unsigned const char sha1oid[] = { + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, + 0x04, 0x14 +}; + +static unsigned const char sha256oid[] = { + 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 +}; + +static unsigned const char sha384oid[] = { + 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 +}; + +static unsigned const char sha512oid[] = { + 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 +}; + +const EVP_MD *get_hash(enum enum_hash hash, const unsigned char **oid, size_t *oid_len) { + switch(hash) { + case hash_arg_SHA1: + if(oid) { + *oid = sha1oid; + *oid_len = sizeof(sha1oid); + } + return EVP_sha1(); + case hash_arg_SHA256: + if(oid) { + *oid = sha256oid; + *oid_len = sizeof(sha256oid); + } + return EVP_sha256(); + case hash_arg_SHA384: + if(oid) { + *oid = sha384oid; + *oid_len = sizeof(sha384oid); + } + return EVP_sha384(); + case hash_arg_SHA512: + if(oid) { + *oid = sha512oid; + *oid_len = sizeof(sha512oid); + } + return EVP_sha512(); + case hash__NULL: + default: + return NULL; + } +} + +int get_hashnid(enum enum_hash hash, unsigned char algorithm) { + switch(algorithm) { + case YKPIV_ALGO_RSA1024: + case YKPIV_ALGO_RSA2048: + switch(hash) { + case hash_arg_SHA1: + return NID_sha1WithRSAEncryption; + case hash_arg_SHA256: + return NID_sha256WithRSAEncryption; + case hash_arg_SHA384: + return NID_sha384WithRSAEncryption; + case hash_arg_SHA512: + return NID_sha512WithRSAEncryption; + case hash__NULL: + default: + return 0; + } + case YKPIV_ALGO_ECCP256: + case YKPIV_ALGO_ECCP384: + switch(hash) { + case hash_arg_SHA1: + return NID_ecdsa_with_SHA1; + case hash_arg_SHA256: + return NID_ecdsa_with_SHA256; + case hash_arg_SHA384: + return NID_ecdsa_with_SHA384; + case hash_arg_SHA512: + return NID_ecdsa_with_SHA512; + case hash__NULL: + default: + return 0; + } + default: + return 0; + } +} + +unsigned char get_piv_algorithm(enum enum_algorithm algorithm) { + switch(algorithm) { + case algorithm_arg_RSA2048: + return YKPIV_ALGO_RSA2048; + case algorithm_arg_RSA1024: + return YKPIV_ALGO_RSA1024; + case algorithm_arg_ECCP256: + return YKPIV_ALGO_ECCP256; + case algorithm_arg_ECCP384: + return YKPIV_ALGO_ECCP384; + case algorithm__NULL: + default: + return 0; + } +} diff --git a/tool/util.h b/tool/util.h index 2e619be..066d389 100644 --- a/tool/util.h +++ b/tool/util.h @@ -47,5 +47,8 @@ int get_object_id(enum enum_slot slot); bool set_component_with_len(unsigned char**, const BIGNUM*, int); bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*, unsigned int*, int); +const EVP_MD *get_hash(enum enum_hash, const unsigned char**, size_t*); +int get_hashnid(enum enum_hash, unsigned char); +unsigned char get_piv_algorithm(enum enum_algorithm); #endif diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index fd7036d..e781c75 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -62,20 +62,7 @@ unsigned const char chuid_tmpl[] = { }; #define CHUID_GUID_OFFS 29 -unsigned const char sha1oid[] = { - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, - 0x04, 0x14 -}; - -unsigned const char sha256oid[] = { - 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, - 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 -}; - -unsigned const char sha512oid[] = { - 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, - 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 -}; +#define MAX_OID_LEN 19 #define KEY_LEN 24 @@ -128,23 +115,10 @@ static bool generate_key(ykpiv_state *state, const char *slot, in_data[1] = 3; in_data[2] = 0x80; in_data[3] = 1; - switch(algorithm) { - case algorithm_arg_RSA2048: - in_data[4] = YKPIV_ALGO_RSA2048; - break; - case algorithm_arg_RSA1024: - in_data[4] = YKPIV_ALGO_RSA1024; - break; - case algorithm_arg_ECCP256: - in_data[4] = YKPIV_ALGO_ECCP256; - break; - case algorithm_arg_ECCP384: - in_data[4] = YKPIV_ALGO_ECCP384; - break; - case algorithm__NULL: - default: - fprintf(stderr, "Unexepcted algorithm.\n"); - goto generate_out; + in_data[4] = get_piv_algorithm(algorithm); + if(in_data[4] == 0) { + fprintf(stderr, "Unexepcted algorithm.\n"); + goto generate_out; } if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, &recv_len, &sw) != YKPIV_OK) { @@ -574,7 +548,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for EVP_PKEY *public_key = NULL; const EVP_MD *md; bool ret = false; - unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)]; // maximum.. + unsigned char digest[EVP_MAX_MD_SIZE + MAX_OID_LEN]; unsigned int digest_len; unsigned int md_len; unsigned char algorithm; @@ -612,25 +586,9 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for goto request_out; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - oid = sha1oid; - oid_len = sizeof(sha1oid); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - oid = sha256oid; - oid_len = sizeof(sha256oid); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - oid = sha512oid; - oid_len = sizeof(sha512oid); - break; - case hash__NULL: - default: - goto request_out; + md = get_hash(hash, &oid, &oid_len); + if(md == NULL) { + goto request_out; } md_len = (unsigned int)EVP_MD_size(md); @@ -666,49 +624,19 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for goto request_out; } - switch(algorithm) { - case YKPIV_ALGO_RSA1024: - case YKPIV_ALGO_RSA2048: - signinput = digest; - len = oid_len + digest_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_sha1WithRSAEncryption; - break; - case hash_arg_SHA256: - nid = NID_sha256WithRSAEncryption; - break; - case hash_arg_SHA512: - nid = NID_sha512WithRSAEncryption; - break; - case hash__NULL: - default: - goto request_out; - } - break; - case YKPIV_ALGO_ECCP256: - case YKPIV_ALGO_ECCP384: + nid = get_hashnid(hash, algorithm); + if(nid == 0) { + fprintf(stderr, "Unsupported algorithm %x or hash %x\n", algorithm, hash); + goto request_out; + } + if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + signinput = digest; + len = oid_len + digest_len; + } else { signinput = digest + oid_len; len = digest_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_ecdsa_with_SHA1; - break; - case hash_arg_SHA256: - nid = NID_ecdsa_with_SHA256; - break; - case hash_arg_SHA512: - nid = NID_ecdsa_with_SHA512; - break; - case hash__NULL: - default: - goto request_out; - } - break; - default: - fprintf(stderr, "Unsupported algorithm %x.\n", algorithm); - goto request_out; } + req->sig_alg->algorithm = OBJ_nid2obj(nid); { unsigned char signature[1024]; @@ -759,7 +687,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo X509 *x509 = NULL; X509_NAME *name = NULL; const EVP_MD *md; - unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)]; + unsigned char digest[EVP_MAX_MD_SIZE + MAX_OID_LEN]; unsigned int digest_len; unsigned char algorithm; int key = 0; @@ -797,27 +725,10 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo goto selfsign_out; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - oid = sha1oid; - oid_len = sizeof(sha1oid); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - oid = sha256oid; - oid_len = sizeof(sha256oid); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - oid = sha512oid; - oid_len = sizeof(sha512oid); - break; - case hash__NULL: - default: - goto selfsign_out; + md = get_hash(hash, &oid, &oid_len); + if(md == NULL) { + goto selfsign_out; } - md_len = (unsigned int)EVP_MD_size(md); digest_len = sizeof(digest) - md_len; @@ -859,49 +770,18 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo fprintf(stderr, "Failed setting certificate issuer.\n"); goto selfsign_out; } - switch(algorithm) { - case YKPIV_ALGO_RSA1024: - case YKPIV_ALGO_RSA2048: - signinput = digest; - len = oid_len + md_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_sha1WithRSAEncryption; - break; - case hash_arg_SHA256: - nid = NID_sha256WithRSAEncryption; - break; - case hash_arg_SHA512: - nid = NID_sha512WithRSAEncryption; - break; - case hash__NULL: - default: - goto selfsign_out; - } - break; - case YKPIV_ALGO_ECCP256: - case YKPIV_ALGO_ECCP384: - signinput = digest + oid_len; - len = md_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_ecdsa_with_SHA1; - break; - case hash_arg_SHA256: - nid = NID_ecdsa_with_SHA256; - break; - case hash_arg_SHA512: - nid = NID_ecdsa_with_SHA512; - break; - case hash__NULL: - default: - goto selfsign_out; - } - break; - default: - fprintf(stderr, "Unsupported algorithm %x.\n", algorithm); - goto selfsign_out; + nid = get_hashnid(hash, algorithm); + if(nid == 0) { + goto selfsign_out; } + if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + signinput = digest; + len = oid_len + md_len; + } else { + signinput = digest + oid_len; + len = md_len; + } + x509->sig_alg->algorithm = OBJ_nid2obj(nid); x509->cert_info->signature->algorithm = x509->sig_alg->algorithm; memcpy(digest, oid, oid_len); @@ -1128,37 +1008,17 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, return false; } - switch(algorithm) { - case algorithm_arg_RSA2048: - algo = YKPIV_ALGO_RSA2048; - break; - case algorithm_arg_RSA1024: - algo = YKPIV_ALGO_RSA1024; - break; - case algorithm_arg_ECCP256: - algo = YKPIV_ALGO_ECCP256; - break; - case algorithm__NULL: - default: - goto out; + algo = get_piv_algorithm(algorithm); + if(algo == 0) { + goto out; } { EVP_MD_CTX *mdctx; - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - break; - case hash__NULL: - default: - goto out; + md = get_hash(hash, NULL, NULL); + if(md == NULL) { + goto out; } mdctx = EVP_MD_CTX_create(); @@ -1318,19 +1178,9 @@ static bool status(ykpiv_state *state, enum enum_hash hash, return false; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - break; - case hash__NULL: - default: - return false; + md = get_hash(hash, NULL, NULL); + if(md == NULL) { + return false; } fprintf(output_file, "CHUID:\t"); @@ -1394,19 +1244,9 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, goto test_out; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - break; - case hash__NULL: - default: - return false; + md = get_hash(hash, NULL, NULL); + if(md == NULL) { + return false; } { From 15413628661f157dbc9e6fc18fda8c81c1795692 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 24 Jun 2015 13:03:14 +0200 Subject: [PATCH 003/134] add macros for IS_ECKEY and IS_RSAKEY, also fix tag on ECCP384 --- lib/ykpiv.c | 2 +- lib/ykpiv.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index e907b19..89fbe55 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -563,7 +563,7 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, dataptr += set_length(dataptr, in_len + bytes + 3); *dataptr++ = 0x82; *dataptr++ = 0x00; - *dataptr++ = algorithm == YKPIV_ALGO_ECCP256 && decipher ? 0x85 : 0x81; + *dataptr++ = IS_ECKEY(algorithm) && decipher ? 0x85 : 0x81; dataptr += set_length(dataptr, in_len); memcpy(dataptr, sign_in, (size_t)in_len); dataptr += in_len; diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 8333a86..d213f5c 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -126,6 +126,9 @@ extern "C" #define YKPIV_INS_RESET 0xfb #define YKPIV_INS_SET_PIN_RETRIES 0xfa +#define IS_ECKEY(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384)) +#define IS_RSAKEY(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048)) + #ifdef __cplusplus } #endif From c2621960a9747d6ff43577511b4cd3812ca3843c Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 24 Jun 2015 13:04:06 +0200 Subject: [PATCH 004/134] use IS_RSAKEY and IS_ECKEY macros, fix minor stuff for ECCP384 --- tool/yubico-piv-tool.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index e781c75..382a889 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -325,7 +325,7 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, unsigned char *in_ptr = in_data; unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key}; int sw; - if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + if(IS_RSAKEY(algorithm)) { RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key); unsigned char e[4]; unsigned char *e_ptr = e; @@ -369,12 +369,17 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, fprintf(stderr, "Failed setting iqmp component.\n"); goto import_out; } - } else if(algorithm == YKPIV_ALGO_ECCP256) { + } else if(IS_ECKEY(algorithm)) { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(private_key); const BIGNUM *s = EC_KEY_get0_private_key(ec); + int element_len = 32; + + if(algorithm == YKPIV_ALGO_ECCP384) { + element_len = 48; + } *in_ptr++ = 0x06; - if(set_component_with_len(&in_ptr, s, 32) == false) { + if(set_component_with_len(&in_ptr, s, element_len) == false) { fprintf(stderr, "Failed setting ec private key.\n"); goto import_out; } @@ -629,7 +634,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for fprintf(stderr, "Unsupported algorithm %x or hash %x\n", algorithm, hash); goto request_out; } - if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + if(IS_RSAKEY(algorithm)) { signinput = digest; len = oid_len + digest_len; } else { @@ -774,7 +779,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo if(nid == 0) { goto selfsign_out; } - if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + if(IS_RSAKEY(algorithm)) { signinput = digest; len = oid_len + md_len; } else { @@ -1037,7 +1042,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, EVP_MD_CTX_destroy(mdctx); } - if(algo == YKPIV_ALGO_RSA1024 || algo == YKPIV_ALGO_RSA2048) { + if(IS_RSAKEY(algo)) { prepare_rsa_signature(hashed, hash_len, hashed, &hash_len, EVP_MD_type(md)); } @@ -1118,6 +1123,9 @@ static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_M case YKPIV_ALGO_ECCP256: fprintf(output, "ECCP256\n"); break; + case YKPIV_ALGO_ECCP384: + fprintf(output, "ECCP384\n"); + break; default: fprintf(output, "Unknown\n"); } @@ -1286,7 +1294,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, goto test_out; } sscanf(cmdline_parser_slot_values[slot], "%2x", &key); - if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + if(IS_RSAKEY(algorithm)) { prepare_rsa_signature(data, data_len, encoded, &enc_len, EVP_MD_type(md)); ptr = encoded; } else { @@ -1320,6 +1328,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, break; case YKPIV_ALGO_ECCP256: + case YKPIV_ALGO_ECCP384: { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pubkey); if(ECDSA_verify(0, data, (int)data_len, signature, (int)sig_len, ec) == 1) { @@ -1391,7 +1400,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot, goto decipher_out; } sscanf(cmdline_parser_slot_values[slot], "%2x", &key); - if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + if(IS_RSAKEY(algorithm)) { unsigned char secret[32]; unsigned char secret2[32]; unsigned char data[256]; @@ -1432,7 +1441,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot, } else { fprintf(stderr, "Failed unwrapping PKCS1 envelope.\n"); } - } else if(algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) { + } else if(IS_ECKEY(algorithm)) { unsigned char secret[48]; unsigned char secret2[48]; unsigned char public_key[97]; From a73d708c2555cadf5a2f27fd8d3efcbb4d08f29a Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 23 Jun 2015 14:12:39 +0200 Subject: [PATCH 005/134] add support for retired key objects slots 82-95 --- lib/ykpiv.h | 21 +++++++++++++++++ tool/cmdline.ggo | 5 ++-- tool/util.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/lib/ykpiv.h b/lib/ykpiv.h index d213f5c..56c0081 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -111,6 +111,27 @@ extern "C" #define YKPIV_OBJ_KEY_HISTORY 0x5fc10c #define YKPIV_OBJ_IRIS 0x5fc121 +#define YKPIV_OBJ_RETIRED1 0x5fc10d +#define YKPIV_OBJ_RETIRED2 0x5fc10e +#define YKPIV_OBJ_RETIRED3 0x5fc10f +#define YKPIV_OBJ_RETIRED4 0x5fc110 +#define YKPIV_OBJ_RETIRED5 0x5fc111 +#define YKPIV_OBJ_RETIRED6 0x5fc112 +#define YKPIV_OBJ_RETIRED7 0x5fc113 +#define YKPIV_OBJ_RETIRED8 0x5fc114 +#define YKPIV_OBJ_RETIRED9 0x5fc115 +#define YKPIV_OBJ_RETIRED10 0x5fc116 +#define YKPIV_OBJ_RETIRED11 0x5fc117 +#define YKPIV_OBJ_RETIRED12 0x5fc118 +#define YKPIV_OBJ_RETIRED13 0x5fc119 +#define YKPIV_OBJ_RETIRED14 0x5fc11a +#define YKPIV_OBJ_RETIRED15 0x5fc11b +#define YKPIV_OBJ_RETIRED16 0x5fc11c +#define YKPIV_OBJ_RETIRED17 0x5fc11d +#define YKPIV_OBJ_RETIRED18 0x5fc11e +#define YKPIV_OBJ_RETIRED19 0x5fc11f +#define YKPIV_OBJ_RETIRED20 0x5fc120 + #define YKPIV_INS_VERIFY 0x20 #define YKPIV_INS_CHANGE_REFERENCE 0x24 #define YKPIV_INS_RESET_RETRY 0x2c diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 25b606f..6439419 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -35,12 +35,13 @@ option "action" a "Action to take" values="version","generate","set-mgm-key", text " Multiple actions may be given at once and will be executed in order for example --action=verify-pin --action=request-certificate\n" -option "slot" s "What key slot to operate on" values="9a","9c","9d","9e" enum optional +option "slot" s "What key slot to operate on" values="9a","9c","9d","9e","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f","90","91","92","93","94","95" enum optional text " 9a is for PIV Authentication 9c is for Digital Signature (PIN always checked) 9d is for Key Management - 9e is for Card Authentication (PIN never checked)\n" + 9e is for Card Authentication (PIN never checked) + 82-95 is for Retired Key Management\n" option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256","ECCP384" enum optional default="RSA2048" option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA384","SHA512" enum optional default="SHA256" option "new-key" n "New authentication key to use" string optional diff --git a/tool/util.c b/tool/util.c index ac1654e..61e749f 100644 --- a/tool/util.c +++ b/tool/util.c @@ -200,6 +200,66 @@ int get_object_id(enum enum_slot slot) { case slot_arg_9e: object = YKPIV_OBJ_CARD_AUTH; break; + case slot_arg_82: + object = YKPIV_OBJ_RETIRED1; + break; + case slot_arg_83: + object = YKPIV_OBJ_RETIRED2; + break; + case slot_arg_84: + object = YKPIV_OBJ_RETIRED3; + break; + case slot_arg_85: + object = YKPIV_OBJ_RETIRED4; + break; + case slot_arg_86: + object = YKPIV_OBJ_RETIRED5; + break; + case slot_arg_87: + object = YKPIV_OBJ_RETIRED6; + break; + case slot_arg_88: + object = YKPIV_OBJ_RETIRED7; + break; + case slot_arg_89: + object = YKPIV_OBJ_RETIRED8; + break; + case slot_arg_8a: + object = YKPIV_OBJ_RETIRED9; + break; + case slot_arg_8b: + object = YKPIV_OBJ_RETIRED10; + break; + case slot_arg_8c: + object = YKPIV_OBJ_RETIRED11; + break; + case slot_arg_8d: + object = YKPIV_OBJ_RETIRED12; + break; + case slot_arg_8e: + object = YKPIV_OBJ_RETIRED13; + break; + case slot_arg_8f: + object = YKPIV_OBJ_RETIRED14; + break; + case slot_arg_90: + object = YKPIV_OBJ_RETIRED15; + break; + case slot_arg_91: + object = YKPIV_OBJ_RETIRED16; + break; + case slot_arg_92: + object = YKPIV_OBJ_RETIRED17; + break; + case slot_arg_93: + object = YKPIV_OBJ_RETIRED18; + break; + case slot_arg_94: + object = YKPIV_OBJ_RETIRED19; + break; + case slot_arg_95: + object = YKPIV_OBJ_RETIRED20; + break; case slot__NULL: default: object = 0; From bc27d98bf78ffe12c1bad5d9978448b437ad7b65 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 24 Jun 2015 13:22:02 +0200 Subject: [PATCH 006/134] better errors for generate on non-supported algorithm or slot --- tool/yubico-piv-tool.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 382a889..6e92caa 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -125,7 +125,14 @@ static bool generate_key(ykpiv_state *state, const char *slot, fprintf(stderr, "Failed to communicate.\n"); goto generate_out; } else if(sw != 0x9000) { - fprintf(stderr, "Failed to generate new key.\n"); + fprintf(stderr, "Failed to generate new key ("); + if(sw == 0x6b00) { + fprintf(stderr, "slot not supported?)\n"); + } else if(sw == 0x6a80) { + fprintf(stderr, "algorithm not supported?)\n"); + } else { + fprintf(stderr, "error %x)\n", sw); + } goto generate_out; } /* to drop the 90 00 and the 7f 49 at the start */ From be8f37924d10d2723cc43a6e7e883675b975716c Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 24 Jun 2015 15:25:59 +0200 Subject: [PATCH 007/134] pin policy code for generate and import-key --- lib/ykpiv.h | 5 +++++ tool/cmdline.ggo | 1 + tool/util.c | 14 ++++++++++++++ tool/util.h | 1 + tool/yubico-piv-tool.c | 40 +++++++++++++++++++++++++++++----------- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 56c0081..a14b0e9 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -147,6 +147,11 @@ extern "C" #define YKPIV_INS_RESET 0xfb #define YKPIV_INS_SET_PIN_RETRIES 0xfa +#define YKPIV_PINPOLICY_TAG 0xaa +#define YKPIV_PINPOLICY_NEVER 1 +#define YKPIV_PINPOLICY_ONCE 2 +#define YKPIV_PINPOLICY_ALWAYS 3 + #define IS_ECKEY(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384)) #define IS_RSAKEY(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048)) diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 6439419..50d346c 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -58,3 +58,4 @@ text " option "pin" P "Pin/puk code for verification" string optional option "new-pin" N "New pin/puk code for changing" string optional dependon="pin" option "sign" - "Sign data" flag off hidden +option "pin-policy" - "Set pin policy for action generate or import-key" values="never","once","always" enum optional diff --git a/tool/util.c b/tool/util.c index 61e749f..464b9ef 100644 --- a/tool/util.c +++ b/tool/util.c @@ -404,3 +404,17 @@ unsigned char get_piv_algorithm(enum enum_algorithm algorithm) { return 0; } } + +unsigned char get_pin_policy(enum enum_pin_policy policy) { + switch(policy) { + case pin_policy_arg_never: + return YKPIV_PINPOLICY_NEVER; + case pin_policy_arg_once: + return YKPIV_PINPOLICY_ONCE; + case pin_policy_arg_always: + return YKPIV_PINPOLICY_ALWAYS; + case pin_policy__NULL: + default: + return 0; + } +} diff --git a/tool/util.h b/tool/util.h index 066d389..ea29d87 100644 --- a/tool/util.h +++ b/tool/util.h @@ -50,5 +50,6 @@ bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*, const EVP_MD *get_hash(enum enum_hash, const unsigned char**, size_t*); int get_hashnid(enum enum_hash, unsigned char); unsigned char get_piv_algorithm(enum enum_algorithm); +unsigned char get_pin_policy(enum enum_pin_policy); #endif diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 6e92caa..055cdbd 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -86,8 +86,9 @@ static void print_version(ykpiv_state *state, const char *output_file_name) { static bool generate_key(ykpiv_state *state, const char *slot, enum enum_algorithm algorithm, const char *output_file_name, - enum enum_key_format key_format) { - unsigned char in_data[5]; + enum enum_key_format key_format, enum enum_pin_policy pin_policy) { + unsigned char in_data[8]; + unsigned char *in_ptr = in_data; unsigned char data[1024]; unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0}; unsigned long recv_len = sizeof(data); @@ -111,16 +112,22 @@ static bool generate_key(ykpiv_state *state, const char *slot, return false; } - in_data[0] = 0xac; - in_data[1] = 3; - in_data[2] = 0x80; - in_data[3] = 1; - in_data[4] = get_piv_algorithm(algorithm); + *in_ptr++ = 0xac; + *in_ptr++ = 3; + *in_ptr++ = 0x80; + *in_ptr++ = 1; + *in_ptr++ = get_piv_algorithm(algorithm); if(in_data[4] == 0) { fprintf(stderr, "Unexepcted algorithm.\n"); goto generate_out; } - if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, + if(pin_policy != pin_policy__NULL) { + in_data[1] += 3; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 1; + *in_ptr++ = get_pin_policy(pin_policy); + } + if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK) { fprintf(stderr, "Failed to communicate.\n"); goto generate_out; @@ -279,7 +286,8 @@ static bool set_pin_retries(ykpiv_state *state, int pin_retries, int puk_retries } static bool import_key(ykpiv_state *state, enum enum_key_format key_format, - const char *input_file_name, const char *slot, char *password) { + const char *input_file_name, const char *slot, char *password, + enum enum_pin_policy pin_policy) { int key = 0; FILE *input_file = NULL; EVP_PKEY *private_key = NULL; @@ -392,9 +400,17 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, } } + if(pin_policy != pin_policy__NULL) { + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 1; + *in_ptr++ = get_pin_policy(pin_policy); + } + if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK) { return false; + } else if(pin_policy != pin_policy__NULL && sw == 0x6a80) { + fprintf(stderr, "Failed import. Maybe pin-policy is not supported on this key?\n"); } else if(sw != 0x9000) { fprintf(stderr, "Failed import command with code %x.\n", sw); } else { @@ -1657,7 +1673,8 @@ int main(int argc, char *argv[]) { print_version(state, args_info.output_arg); break; case action_arg_generate: - if(generate_key(state, args_info.slot_orig, args_info.algorithm_arg, args_info.output_arg, args_info.key_format_arg) == false) { + if(generate_key(state, args_info.slot_orig, args_info.algorithm_arg, args_info.output_arg, args_info.key_format_arg, + args_info.pin_policy_arg) == false) { ret = EXIT_FAILURE; } else { fprintf(stderr, "Successfully generated a new private key.\n"); @@ -1698,7 +1715,8 @@ int main(int argc, char *argv[]) { } break; case action_arg_importMINUS_key: - if(import_key(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_orig, args_info.password_arg) == false) { + if(import_key(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_orig, args_info.password_arg, + args_info.pin_policy_arg) == false) { ret = EXIT_FAILURE; } else { fprintf(stderr, "Successfully imported a new private key.\n"); From ca6a355b5dd78b46edea9852440b27a098628524 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Thu, 25 Jun 2015 12:04:05 +0200 Subject: [PATCH 008/134] add touch tlv for generate and import-key --- lib/ykpiv.h | 4 ++++ tool/cmdline.ggo | 1 + tool/util.c | 12 ++++++++++++ tool/util.h | 1 + tool/yubico-piv-tool.c | 22 +++++++++++++++++----- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lib/ykpiv.h b/lib/ykpiv.h index a14b0e9..0edf065 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -152,6 +152,10 @@ extern "C" #define YKPIV_PINPOLICY_ONCE 2 #define YKPIV_PINPOLICY_ALWAYS 3 +#define YKPIV_TOUCHPOLICY_TAG 0xab +#define YKPIV_TOUCHPOLICY_NEVER 1 +#define YKPIV_TOUCHPOLICY_ALWAYS 2 + #define IS_ECKEY(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384)) #define IS_RSAKEY(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048)) diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 50d346c..40aa65e 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -59,3 +59,4 @@ option "pin" P "Pin/puk code for verification" string optional option "new-pin" N "New pin/puk code for changing" string optional dependon="pin" option "sign" - "Sign data" flag off hidden option "pin-policy" - "Set pin policy for action generate or import-key" values="never","once","always" enum optional +option "touch-policy" - "Set touch policy for action generate or import-key" values="never","always" enum optional diff --git a/tool/util.c b/tool/util.c index 464b9ef..82e5126 100644 --- a/tool/util.c +++ b/tool/util.c @@ -418,3 +418,15 @@ unsigned char get_pin_policy(enum enum_pin_policy policy) { return 0; } } + +unsigned char get_touch_policy(enum enum_touch_policy policy) { + switch(policy) { + case touch_policy_arg_never: + return YKPIV_TOUCHPOLICY_NEVER; + case touch_policy_arg_always: + return YKPIV_TOUCHPOLICY_ALWAYS; + case touch_policy__NULL: + default: + return 0; + } +} diff --git a/tool/util.h b/tool/util.h index ea29d87..c7c9ccb 100644 --- a/tool/util.h +++ b/tool/util.h @@ -51,5 +51,6 @@ const EVP_MD *get_hash(enum enum_hash, const unsigned char**, size_t*); int get_hashnid(enum enum_hash, unsigned char); unsigned char get_piv_algorithm(enum enum_algorithm); unsigned char get_pin_policy(enum enum_pin_policy); +unsigned char get_touch_policy(enum enum_touch_policy); #endif diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 055cdbd..92301b1 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -86,8 +86,9 @@ static void print_version(ykpiv_state *state, const char *output_file_name) { static bool generate_key(ykpiv_state *state, const char *slot, enum enum_algorithm algorithm, const char *output_file_name, - enum enum_key_format key_format, enum enum_pin_policy pin_policy) { - unsigned char in_data[8]; + enum enum_key_format key_format, enum enum_pin_policy pin_policy, + enum enum_touch_policy touch_policy) { + unsigned char in_data[11]; unsigned char *in_ptr = in_data; unsigned char data[1024]; unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0}; @@ -127,6 +128,12 @@ static bool generate_key(ykpiv_state *state, const char *slot, *in_ptr++ = 1; *in_ptr++ = get_pin_policy(pin_policy); } + if(touch_policy != touch_policy__NULL) { + in_data[1] += 3; + *in_ptr++ = YKPIV_TOUCHPOLICY_TAG; + *in_ptr++ = 1; + *in_ptr++ = get_touch_policy(touch_policy); + } if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK) { fprintf(stderr, "Failed to communicate.\n"); @@ -287,7 +294,7 @@ static bool set_pin_retries(ykpiv_state *state, int pin_retries, int puk_retries static bool import_key(ykpiv_state *state, enum enum_key_format key_format, const char *input_file_name, const char *slot, char *password, - enum enum_pin_policy pin_policy) { + enum enum_pin_policy pin_policy, enum enum_touch_policy touch_policy) { int key = 0; FILE *input_file = NULL; EVP_PKEY *private_key = NULL; @@ -405,6 +412,11 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, *in_ptr++ = 1; *in_ptr++ = get_pin_policy(pin_policy); } + if(touch_policy != touch_policy__NULL) { + *in_ptr++ = YKPIV_TOUCHPOLICY_TAG; + *in_ptr++ = 1; + *in_ptr++ = get_touch_policy(touch_policy); + } if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK) { @@ -1674,7 +1686,7 @@ int main(int argc, char *argv[]) { break; case action_arg_generate: if(generate_key(state, args_info.slot_orig, args_info.algorithm_arg, args_info.output_arg, args_info.key_format_arg, - args_info.pin_policy_arg) == false) { + args_info.pin_policy_arg, args_info.touch_policy_arg) == false) { ret = EXIT_FAILURE; } else { fprintf(stderr, "Successfully generated a new private key.\n"); @@ -1716,7 +1728,7 @@ int main(int argc, char *argv[]) { break; case action_arg_importMINUS_key: if(import_key(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_orig, args_info.password_arg, - args_info.pin_policy_arg) == false) { + args_info.pin_policy_arg, args_info.touch_policy_arg) == false) { ret = EXIT_FAILURE; } else { fprintf(stderr, "Successfully imported a new private key.\n"); From 600b302c1d720cfa717223bf59953e3f2013e565 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Thu, 25 Jun 2015 12:04:20 +0200 Subject: [PATCH 009/134] add touch for set-mgm-key --- configure.ac | 8 ++++---- lib/ykpiv.c | 12 +++++++++++- lib/ykpiv.h | 2 ++ lib/ykpiv.map | 6 ++++++ tool/cmdline.ggo | 2 +- tool/yubico-piv-tool.c | 2 +- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 2cf4764..5ad286d 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ # non-source form of such a combination shall include the source code # for the parts of OpenSSL used as well as that of the covered work. -AC_INIT([yubico-piv-tool], [1.0.1]) +AC_INIT([yubico-piv-tool], [1.1.0]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) @@ -32,9 +32,9 @@ AC_CONFIG_MACRO_DIR([m4]) # Interfaces changed/added/removed: CURRENT++ REVISION=0 # Interfaces added: AGE++ # Interfaces removed: AGE=0 -AC_SUBST([LT_CURRENT], 1) -AC_SUBST([LT_REVISION], 6) -AC_SUBST([LT_AGE], 0) +AC_SUBST([LT_CURRENT], 2) +AC_SUBST([LT_REVISION], 0) +AC_SUBST([LT_AGE], 1) AM_INIT_AUTOMAKE([-Wall -Werror foreign]) AM_SILENT_RULES([yes]) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 89fbe55..bf7d4a0 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -427,6 +427,10 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) { } ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key) { + return ykpiv_set_mgmkey2(state, new_key, 0); +} + +ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, const unsigned char touch) { APDU apdu; unsigned char data[0xff]; unsigned long recv_len = sizeof(data); @@ -453,7 +457,13 @@ ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key) { memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_SET_MGMKEY; apdu.st.p1 = 0xff; - apdu.st.p2 = 0xff; + if(touch == 0) { + apdu.st.p2 = 0xff; + } else if(touch == 1) { + apdu.st.p2 = 0xfe; + } else { + return YKPIV_GENERIC_ERROR; + } apdu.st.lc = DES_KEY_SZ * 3 + 3; apdu.st.data[0] = YKPIV_ALGO_3DES; apdu.st.data[1] = YKPIV_KEY_CARDMGM; diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 0edf065..4585d4c 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -70,6 +70,8 @@ extern "C" unsigned char *out_data, unsigned long *out_len, int *sw); ykpiv_rc ykpiv_authenticate(ykpiv_state *state, const unsigned char *key); ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key); + ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, + const unsigned char touch); ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, unsigned char *hex_out, size_t *out_len); ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in, diff --git a/lib/ykpiv.map b/lib/ykpiv.map index 19969cc..0e262f4 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -53,3 +53,9 @@ YKPIV_0.2.0 global: ykpiv_decipher_data; } YKPIV_0.1.0; + +YKPIV_1.1.0 +{ +global: + ykpiv_set_mgmkey2; +} YKPIV_0.1.0; diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 40aa65e..848db95 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -59,4 +59,4 @@ option "pin" P "Pin/puk code for verification" string optional option "new-pin" N "New pin/puk code for changing" string optional dependon="pin" option "sign" - "Sign data" flag off hidden option "pin-policy" - "Set pin policy for action generate or import-key" values="never","once","always" enum optional -option "touch-policy" - "Set touch policy for action generate or import-key" values="never","always" enum optional +option "touch-policy" - "Set touch policy for action generatem, import-key or set-mgm-key" values="never","always" enum optional diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 92301b1..443402a 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -1699,7 +1699,7 @@ int main(int argc, char *argv[]) { if(ykpiv_hex_decode(args_info.new_key_arg, strlen(args_info.new_key_arg), new_key, &new_key_len) != YKPIV_OK) { fprintf(stderr, "Failed decoding new key!\n"); ret = EXIT_FAILURE; - } else if(ykpiv_set_mgmkey(state, new_key) != YKPIV_OK) { + } else if(ykpiv_set_mgmkey2(state, new_key, args_info.touch_policy_arg == touch_policy_arg_always ? 1 : 0) != YKPIV_OK) { fprintf(stderr, "Failed setting the new key!\n"); ret = EXIT_FAILURE; } else { From 6f5870d884ea09cdf4ea72061bdfcde37da42921 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Thu, 25 Jun 2015 12:37:06 +0200 Subject: [PATCH 010/134] better errors for fail on pin-policy and touch-policy --- tool/yubico-piv-tool.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 443402a..7d3d463 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -143,7 +143,13 @@ static bool generate_key(ykpiv_state *state, const char *slot, if(sw == 0x6b00) { fprintf(stderr, "slot not supported?)\n"); } else if(sw == 0x6a80) { - fprintf(stderr, "algorithm not supported?)\n"); + if(pin_policy != pin_policy__NULL) { + fprintf(stderr, "pin policy not supported?)\n"); + } else if(touch_policy != touch_policy__NULL) { + fprintf(stderr, "touch policy not supported?)\n"); + } else { + fprintf(stderr, "algorithm not supported?)\n"); + } } else { fprintf(stderr, "error %x)\n", sw); } @@ -421,8 +427,15 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK) { return false; - } else if(pin_policy != pin_policy__NULL && sw == 0x6a80) { - fprintf(stderr, "Failed import. Maybe pin-policy is not supported on this key?\n"); + } else if(sw == 0x6a80) { + fprintf(stderr, "Failed import."); + if(pin_policy != pin_policy__NULL) { + fprintf(stderr, "Maybe pin-policy is not supported on this key?\n"); + } else if(touch_policy != touch_policy__NULL) { + fprintf(stderr, "Maybe touch-policy is not supported on this key?\n"); + } else { + fprintf(stderr, "Maybe algorithm is not supported on this key?\n"); + } } else if(sw != 0x9000) { fprintf(stderr, "Failed import command with code %x.\n", sw); } else { @@ -1700,7 +1713,11 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Failed decoding new key!\n"); ret = EXIT_FAILURE; } else if(ykpiv_set_mgmkey2(state, new_key, args_info.touch_policy_arg == touch_policy_arg_always ? 1 : 0) != YKPIV_OK) { - fprintf(stderr, "Failed setting the new key!\n"); + fprintf(stderr, "Failed setting the new key!"); + if(args_info.touch_policy_arg != touch_policy__NULL) { + fprintf(stderr, " Maybe touch policy is not supported on this key?"); + } + fprintf(stderr, "\n"); ret = EXIT_FAILURE; } else { fprintf(stderr, "Successfully set new management key.\n"); From 642891e2b30a84c0a25d04441df196af4a0b493e Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 26 Jun 2015 11:03:08 +0200 Subject: [PATCH 011/134] move padding for signing to ykpiv_sign_data() and only pad if in_len != key_len --- lib/ykpiv.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index bf7d4a0..7dec9e5 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -509,7 +509,7 @@ ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, } static ykpiv_rc _general_authenticate(ykpiv_state *state, - const unsigned char *raw_in, size_t in_len, + const unsigned char *sign_in, size_t in_len, unsigned char *out, size_t *out_len, unsigned char algorithm, unsigned char key, bool decipher) { unsigned char indata[1024]; @@ -517,7 +517,6 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, unsigned char data[1024]; unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key}; unsigned long recv_len = sizeof(data); - unsigned char sign_in[256]; size_t key_len = 0; int sw; size_t bytes; @@ -531,17 +530,8 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, if(key_len == 0) { key_len = 256; } - if(!decipher) { - if(in_len + RSA_PKCS1_PADDING_SIZE > key_len) { - return YKPIV_SIZE_ERROR; - } - RSA_padding_add_PKCS1_type_1(sign_in, key_len, raw_in, in_len); - in_len = key_len; - } else { - if(in_len != key_len) { - return YKPIV_SIZE_ERROR; - } - memcpy(sign_in, raw_in, in_len); + if(in_len != key_len) { + return YKPIV_SIZE_ERROR; } break; case YKPIV_ALGO_ECCP256: @@ -555,7 +545,6 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, } else if(decipher && in_len != (key_len * 2) + 1) { return YKPIV_SIZE_ERROR; } - memcpy(sign_in, raw_in, in_len); break; default: return YKPIV_ALGORITHM_ERROR; @@ -624,7 +613,24 @@ ykpiv_rc ykpiv_sign_data(ykpiv_state *state, unsigned char *sign_out, size_t *out_len, unsigned char algorithm, unsigned char key) { - return _general_authenticate(state, raw_in, in_len, sign_out, out_len, + unsigned char sign_in[256]; + size_t key_len = 0; + if(IS_RSAKEY(algorithm)) { + key_len = 128; + if(algorithm == YKPIV_ALGO_RSA2048) { + key_len = 256; + } + } + if(IS_RSAKEY(algorithm) && key_len != in_len) { + if(in_len + RSA_PKCS1_PADDING_SIZE > key_len) { + return YKPIV_SIZE_ERROR; + } + RSA_padding_add_PKCS1_type_1(sign_in, key_len, raw_in, in_len); + in_len = key_len; + } else { + memcpy(sign_in, raw_in, in_len); + } + return _general_authenticate(state, sign_in, in_len, sign_out, out_len, algorithm, key, false); } From f43c5781b90d0ebc87683e10dc36a9da83de8ea0 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 26 Jun 2015 13:00:21 +0200 Subject: [PATCH 012/134] fix indentation --- tool/yubico-piv-tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 7d3d463..601dcf6 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -686,8 +686,8 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for signinput = digest; len = oid_len + digest_len; } else { - signinput = digest + oid_len; - len = digest_len; + signinput = digest + oid_len; + len = digest_len; } req->sig_alg->algorithm = OBJ_nid2obj(nid); From 5e50401a0a5ae665ae8ab204e3f1a9a6350ed0e7 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 26 Jun 2015 17:12:14 +0200 Subject: [PATCH 013/134] Initial commit for ykcs11. --- .gitignore | 5 + Makefile.am | 2 +- configure.ac | 5 + ykcs11/Makefile.am | 64 ++ ykcs11/pkcs11.h | 324 +++++++++++ ykcs11/pkcs11f.h | 933 +++++++++++++++++++++++++++++ ykcs11/pkcs11t.h | 1134 ++++++++++++++++++++++++++++++++++++ ykcs11/version.c | 142 +++++ ykcs11/ykcs11-version.h | 91 +++ ykcs11/ykcs11-version.h.in | 91 +++ ykcs11/ykcs11.c | 875 ++++++++++++++++++++++++++++ ykcs11/ykcs11.map | 34 ++ ykcs11/ykcs11.pc | 12 + ykcs11/ykcs11.pc.in | 12 + 14 files changed, 3723 insertions(+), 1 deletion(-) create mode 100644 ykcs11/Makefile.am create mode 100644 ykcs11/pkcs11.h create mode 100644 ykcs11/pkcs11f.h create mode 100644 ykcs11/pkcs11t.h create mode 100644 ykcs11/version.c create mode 100644 ykcs11/ykcs11-version.h create mode 100644 ykcs11/ykcs11-version.h.in create mode 100644 ykcs11/ykcs11.c create mode 100644 ykcs11/ykcs11.map create mode 100644 ykcs11/ykcs11.pc create mode 100644 ykcs11/ykcs11.pc.in diff --git a/.gitignore b/.gitignore index 5f30be0..315c81a 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,8 @@ lib/ykpiv.gcno tool/util.gcno tool/yubico-piv-tool.gcda tool/yubico-piv-tool.gcno +ykcs11/.libs/ +ykcs11/*.o +ykcs11/*.lo +ykcs11/ykcs11.pc +ykcs11/libykcs11.la \ No newline at end of file diff --git a/Makefile.am b/Makefile.am index df7561f..1474885 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ # non-source form of such a combination shall include the source code # for the parts of OpenSSL used as well as that of the covered work. -SUBDIRS = lib tool +SUBDIRS = lib tool ykcs11 ACLOCAL_AMFLAGS = -I m4 diff --git a/configure.ac b/configure.ac index 2cf4764..a0aba0c 100644 --- a/configure.ac +++ b/configure.ac @@ -49,6 +49,8 @@ PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES(OPENSSL, openssl) +PKG_CHECK_MODULES([LIBNSPR], [nspr], [], []) + gl_LD_VERSION_SCRIPT gl_VALGRIND_TESTS @@ -182,6 +184,9 @@ AC_CONFIG_FILES([ tool/tests/Makefile lib/ykpiv-version.h lib/ykpiv.pc + ykcs11/Makefile + ykcs11/ykcs11-version.h + ykcs11/ykcs11.pc ]) AC_OUTPUT diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am new file mode 100644 index 0000000..f0b1879 --- /dev/null +++ b/ykcs11/Makefile.am @@ -0,0 +1,64 @@ +# Copyright (c) 2015 Yubico AB +# All rights reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Additional permission under GNU GPL version 3 section 7 +# +# If you modify this program, or any covered work, by linking or +# combining it with the OpenSSL project's OpenSSL library (or a +# modified version of that library), containing parts covered by the +# terms of the OpenSSL or SSLeay licenses, We grant you additional +# permission to convey the resulting work. Corresponding Source for a +# non-source form of such a combination shall include the source code +# for the parts of OpenSSL used as well as that of the covered work. + +SUBDIRS = . +#tests + +AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) +AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS) $(LIBNSPR_CFLAGS) + +lib_LTLIBRARIES = libykcs11.la + +libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map +#internal.h +#libykcs11_la_SOURCES += error.c +#libykcs11_la_LDADD = ../lib/libykpiv.la +#$(OPENSSL_LIBS) +libykcs11_la_includedir = $(includedir)/ykcs11 +libykcs11_la_include_HEADERS = ykcs11-version.h +#ykcs11.h +EXTRA_libykcs11_la_DEPENDENCIES = ykcs11.map + +#libykcs11_la_LIBADD = $(OPENSSL_LIBS) $(PCSC_LIBS) +#libykcs11_la_LIBADD += $(PCSC_WIN_LIBS) $(PCSC_MACOSX_LIBS) +libykcs11_la_LIBADD = $(LIBNSPR) ../lib/libykpiv.la + +libykcs11_la_LDFLAGS = -no-undefined +libykcs11_la_LDFLAGS += -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) + +if HAVE_LD_VERSION_SCRIPT +libykcs11_la_LDFLAGS += -Wl,--version-script=$(srcdir)/ykcs11.map +else +libykcs11_la_LDFLAGS += -export-symbols-regex '^ykcs11_.*' +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = ykcs11.pc + +if ENABLE_COV +AM_CFLAGS += --coverage +AM_LDFLAGS = --coverage +endif diff --git a/ykcs11/pkcs11.h b/ykcs11/pkcs11.h new file mode 100644 index 0000000..3d7e166 --- /dev/null +++ b/ykcs11/pkcs11.h @@ -0,0 +1,324 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document + * is granted provided that it is identified as "RSA Security In.c Public-Key + * Cryptography Standards (PKCS)" in all material mentioning or referencing + * this document. + */ +#ifndef _PKCS11_H_ +#define _PKCS11_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Before including this file (pkcs11.h) (or pkcs11t.h by + * itself), 6 platform-specific macros must be defined. These + * macros are described below, and typical definitions for them + * are also given. Be advised that these definitions can depend + * on both the platform and the compiler used (and possibly also + * on whether a PKCS #11 library is linked statically or + * dynamically). + * + * In addition to defining these 6 macros, the packing convention + * for PKCS #11 structures should be set. The PKCS #11 + * convention on packing is that structures should be 1-byte + * aligned. + * + * In a Win32 environment, this might be done by using the + * following preprocessor directive before including pkcs11.h + * or pkcs11t.h: + * + * #pragma pack(push, cryptoki, 1) + * + * and using the following preprocessor directive after including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(pop, cryptoki) + * + * In a Win16 environment, this might be done by using the + * following preprocessor directive before including pkcs11.h + * or pkcs11t.h: + * + * #pragma pack(1) + * + * In a UNIX environment, you're on your own here. You might + * not need to do anything. + * + * + * Now for the macros: + * + * + * 1. CK_PTR: The indirection string for making a pointer to an + * object. It can be used like this: + * + * typedef CK_BYTE CK_PTR CK_BYTE_PTR; + * + * In a Win32 environment, it might be defined by + * + * #define CK_PTR * + * + * In a Win16 environment, it might be defined by + * + * #define CK_PTR far * + * + * In a UNIX environment, it might be defined by + * + * #define CK_PTR * + * + * + * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes + * an exportable PKCS #11 library function definition out of a + * return type and a function name. It should be used in the + * following fashion to define the exposed PKCS #11 functions in + * a PKCS #11 library: + * + * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ) + * { + * ... + * } + * + * For defining a function in a Win32 PKCS #11 .dll, it might be + * defined by + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __declspec(dllexport) name + * + * For defining a function in a Win16 PKCS #11 .dll, it might be + * defined by + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes + * an importable PKCS #11 library function declaration out of a + * return type and a function name. It should be used in the + * following fashion: + * + * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ); + * + * For declaring a function in a Win32 PKCS #11 .dll, it might + * be defined by + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __declspec(dllimport) name + * + * For declaring a function in a Win16 PKCS #11 .dll, it might + * be defined by + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro + * which makes a PKCS #11 API function pointer declaration or + * function pointer type declaration out of a return type and a + * function name. It should be used in the following fashion: + * + * // Define funcPtr to be a pointer to a PKCS #11 API function + * // taking arguments args and returning CK_RV. + * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args); + * + * or + * + * // Define funcPtrType to be the type of a pointer to a + * // PKCS #11 API function taking arguments args and returning + * // CK_RV, and then define funcPtr to be a variable of type + * // funcPtrType. + * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); + * funcPtrType funcPtr; + * + * For accessing functions in a Win32 PKCS #11 .dll, in might be + * defined by + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __declspec(dllimport) (* name) + * + * For accessing functions in a Win16 PKCS #11 .dll, it might be + * defined by + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __export _far _pascal (* name) + * + * In a UNIX environment, it might be defined by + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType (* name) + * + * + * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes + * a function pointer type for an application callback out of + * a return type for the callback and a name for the callback. + * It should be used in the following fashion: + * + * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args); + * + * to declare a function pointer, myCallback, to a callback + * which takes arguments args and returns a CK_RV. It can also + * be used like this: + * + * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); + * myCallbackType myCallback; + * + * In a Win32 environment, it might be defined by + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * In a Win16 environment, it might be defined by + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType _far _pascal (* name) + * + * In a UNIX environment, it might be defined by + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * + * 6. NULL_PTR: This macro is the value of a NULL pointer. + * + * In any ANSI/ISO C environment (and in many others as well), + * this should be defined by + * + * #ifndef NULL_PTR + * #define NULL_PTR 0 + * #endif + */ + + +/* All the various PKCS #11 types and #define'd values are in the + * file pkcs11t.h. */ +#include "pkcs11t.h" + +#define __PASTE(x,y) x##y + + +/* packing defines */ +//#include "pkcs11p.h" // TODO: msc specific? +/* ============================================================== + * Define the "extern" form of all the entry points. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + CK_DECLARE_FUNCTION(CK_RV, name) + +/* pkcs11f.h has all the information about the PKCS #11 + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define the typedef form of all the entry points. That is, for + * each PKCS #11 function C_XXX, define a type CK_C_XXX which is + * a pointer to that kind of function. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name)) + +/* pkcs11f.h has all the information about the PKCS #11 + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define structed vector of entry points. A CK_FUNCTION_LIST + * contains a CK_VERSION indicating a library's PKCS #11 version + * and then a whole slew of function pointers to the routines in + * the library. This type was declared, but not defined, in + * pkcs11t.h. + * ============================================================== + */ + +#define CK_PKCS11_FUNCTION_INFO(name) \ + __PASTE(CK_,name) name; + +struct CK_FUNCTION_LIST { + + CK_VERSION version; /* PKCS #11 version */ + +/* Pile all the function pointers into the CK_FUNCTION_LIST. */ +/* pkcs11f.h has all the information about the PKCS #11 + * function prototypes. */ +#include "pkcs11f.h" + +}; + +#undef CK_PKCS11_FUNCTION_INFO + + +#undef __PASTE + +/* unpack */ +//#include "pkcs11u.h" // TODO: msc specific? + +#ifdef __cplusplus +} +#endif + +/* +** Functions called directly by applications to configure the FIPS token. +*/ +extern void PK11_ConfigurePKCS11(char *man, char *libdes, char *tokdes, + char *ptokdes, char *slotdes, char *pslotdes, char *fslotdes, + char *fpslotdes, int minPwd, int pwdRequired); +extern void PK11_ConfigureFIPS(char *slotdes, char *pslotdes); + +#endif diff --git a/ykcs11/pkcs11f.h b/ykcs11/pkcs11f.h new file mode 100644 index 0000000..9f71d49 --- /dev/null +++ b/ykcs11/pkcs11f.h @@ -0,0 +1,933 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document + * is granted provided that it is identified as "RSA Security In.c Public-Key + * Cryptography Standards (PKCS)" in all material mentioning or referencing + * this document. + */ +/* This function contains pretty much everything about all the */ +/* PKCS #11 function prototypes. Because this information is */ +/* used for more than just declaring function prototypes, the */ +/* order of the functions appearing herein is important, and */ +/* should not be altered. */ + + + +/* General-purpose */ + +/* C_Initialize initializes the PKCS #11 library. */ +CK_PKCS11_FUNCTION_INFO(C_Initialize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets + * cast to CK_C_INITIALIZE_ARGS_PTR + * and dereferenced */ +); +#endif + + +/* C_Finalize indicates that an application is done with the + * PKCS #11 library. */ +CK_PKCS11_FUNCTION_INFO(C_Finalize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */ +); +#endif + + +/* C_GetInfo returns general information about PKCS #11. */ +CK_PKCS11_FUNCTION_INFO(C_GetInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pInfo /* location that receives information */ +); +#endif + + +/* C_GetFunctionList returns the function list. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionList) +#ifdef CK_NEED_ARG_LIST +( + CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to + * function list */ +); +#endif + + + +/* Slot and token management */ + +/* C_GetSlotList obtains a list of slots in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotList) +#ifdef CK_NEED_ARG_LIST +( + CK_BBOOL tokenPresent, /* only slots with tokens? */ + CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ + CK_ULONG_PTR pulCount /* receives number of slots */ +); +#endif + + +/* C_GetSlotInfo obtains information about a particular slot in + * the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the ID of the slot */ + CK_SLOT_INFO_PTR pInfo /* receives the slot information */ +); +#endif + + +/* C_GetTokenInfo obtains information about a particular token + * in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_TOKEN_INFO_PTR pInfo /* receives the token information */ +); +#endif + + +/* C_GetMechanismList obtains a list of mechanism types + * supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismList) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of token's slot */ + CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */ + CK_ULONG_PTR pulCount /* gets # of mechs. */ +); +#endif + + +/* C_GetMechanismInfo obtains information about a particular + * mechanism possibly supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_MECHANISM_TYPE type, /* type of mechanism */ + CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */ +); +#endif + + +/* C_InitToken initializes a token. */ +CK_PKCS11_FUNCTION_INFO(C_InitToken) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_CHAR_PTR pPin, /* the SO's initial PIN */ + CK_ULONG ulPinLen, /* length in bytes of the PIN */ + CK_CHAR_PTR pLabel /* 32-byte token label (blank padded) */ +); +#endif + + +/* C_InitPIN initializes the normal user's PIN. */ +CK_PKCS11_FUNCTION_INFO(C_InitPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_CHAR_PTR pPin, /* the normal user's PIN */ + CK_ULONG ulPinLen /* length in bytes of the PIN */ +); +#endif + + +/* C_SetPIN modifies the PIN of the user who is logged in. */ +CK_PKCS11_FUNCTION_INFO(C_SetPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_CHAR_PTR pOldPin, /* the old PIN */ + CK_ULONG ulOldLen, /* length of the old PIN */ + CK_CHAR_PTR pNewPin, /* the new PIN */ + CK_ULONG ulNewLen /* length of the new PIN */ +); +#endif + + + +/* Session management */ + +/* C_OpenSession opens a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_OpenSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the slot's ID */ + CK_FLAGS flags, /* from CK_SESSION_INFO */ + CK_VOID_PTR pApplication, /* passed to callback */ + CK_NOTIFY Notify, /* callback function */ + CK_SESSION_HANDLE_PTR phSession /* gets session handle */ +); +#endif + + +/* C_CloseSession closes a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CloseAllSessions closes all sessions with a token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID /* the token's slot */ +); +#endif + + +/* C_GetSessionInfo obtains information about the session. */ +CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_SESSION_INFO_PTR pInfo /* receives session info */ +); +#endif + + +/* C_GetOperationState obtains the state of the cryptographic operation + * in a session. */ +CK_PKCS11_FUNCTION_INFO(C_GetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* gets state */ + CK_ULONG_PTR pulOperationStateLen /* gets state length */ +); +#endif + + +/* C_SetOperationState restores the state of the cryptographic + * operation in a session. */ +CK_PKCS11_FUNCTION_INFO(C_SetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* holds state */ + CK_ULONG ulOperationStateLen, /* holds state length */ + CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */ + CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */ +); +#endif + + +/* C_Login logs a user into a token. */ +CK_PKCS11_FUNCTION_INFO(C_Login) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_USER_TYPE userType, /* the user type */ + CK_CHAR_PTR pPin, /* the user's PIN */ + CK_ULONG ulPinLen /* the length of the PIN */ +); +#endif + + +/* C_Logout logs a user out from a token. */ +CK_PKCS11_FUNCTION_INFO(C_Logout) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Object management */ + +/* C_CreateObject creates a new object. */ +CK_PKCS11_FUNCTION_INFO(C_CreateObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */ +); +#endif + + +/* C_CopyObject copies an object, creating a new object for the + * copy. */ +CK_PKCS11_FUNCTION_INFO(C_CopyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new object */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */ +); +#endif + + +/* C_DestroyObject destroys an object. */ +CK_PKCS11_FUNCTION_INFO(C_DestroyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject /* the object's handle */ +); +#endif + + +/* C_GetObjectSize gets the size of an object in bytes. */ +CK_PKCS11_FUNCTION_INFO(C_GetObjectSize) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ULONG_PTR pulSize /* receives size of object */ +); +#endif + + +/* C_GetAttributeValue obtains the value of one or more object + * attributes. */ +CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_SetAttributeValue modifies the value of one or more object + * attributes */ +CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_FindObjectsInit initializes a search for token and session + * objects that match a template. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ + CK_ULONG ulCount /* attrs in search template */ +); +#endif + + +/* C_FindObjects continues a search for token and session + * objects that match a template, obtaining additional object + * handles. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjects) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ + CK_ULONG ulMaxObjectCount, /* max handles to get */ + CK_ULONG_PTR pulObjectCount /* actual # returned */ +); +#endif + + +/* C_FindObjectsFinal finishes a search for token and session + * objects. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Encryption and decryption */ + +/* C_EncryptInit initializes an encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of encryption key */ +); +#endif + + +/* C_Encrypt encrypts single-part data. */ +CK_PKCS11_FUNCTION_INFO(C_Encrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pData, /* the plaintext data */ + CK_ULONG ulDataLen, /* bytes of plaintext */ + CK_BYTE_PTR pEncryptedData, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */ +); +#endif + + +/* C_EncryptUpdate continues a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext data len */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */ +); +#endif + + +/* C_EncryptFinal finishes a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session handle */ + CK_BYTE_PTR pLastEncryptedPart, /* last c-text */ + CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */ +); +#endif + + +/* C_DecryptInit initializes a decryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of decryption key */ +); +#endif + + +/* C_Decrypt decrypts encrypted data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Decrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedData, /* ciphertext */ + CK_ULONG ulEncryptedDataLen, /* ciphertext length */ + CK_BYTE_PTR pData, /* gets plaintext */ + CK_ULONG_PTR pulDataLen /* gets p-text size */ +); +#endif + + +/* C_DecryptUpdate continues a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* encrypted data */ + CK_ULONG ulEncryptedPartLen, /* input length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* p-text size */ +); +#endif + + +/* C_DecryptFinal finishes a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pLastPart, /* gets plaintext */ + CK_ULONG_PTR pulLastPartLen /* p-text size */ +); +#endif + + + +/* Message digesting */ + +/* C_DigestInit initializes a message-digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism /* the digesting mechanism */ +); +#endif + + +/* C_Digest digests data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Digest) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* data to be digested */ + CK_ULONG ulDataLen, /* bytes of data to digest */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets digest length */ +); +#endif + + +/* C_DigestUpdate continues a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* data to be digested */ + CK_ULONG ulPartLen /* bytes of data to be digested */ +); +#endif + + +/* C_DigestKey continues a multi-part message-digesting + * operation, by digesting the value of a secret key as part of + * the data already digested. */ +CK_PKCS11_FUNCTION_INFO(C_DigestKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hKey /* secret key to digest */ +); +#endif + + +/* C_DigestFinal finishes a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets byte count of digest */ +); +#endif + + + +/* Signing and MACing */ + +/* C_SignInit initializes a signature (private key encryption) + * operation, where the signature is (will be) an appendix to + * the data, and plaintext cannot be recovered from the + *signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of signature key */ +); +#endif + + +/* C_Sign signs (encrypts with private key) data in a single + * part, where the signature is (will be) an appendix to the + * data, and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Sign) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignUpdate continues a multiple-part signature operation, + * where the signature is (will be) an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* the data to sign */ + CK_ULONG ulPartLen /* count of bytes to sign */ +); +#endif + + +/* C_SignFinal finishes a multiple-part signature operation, + * returning the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignRecoverInit initializes a signature operation, where + * the data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of the signature key */ +); +#endif + + +/* C_SignRecover signs data in a single operation, where the + * data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + + +/* Verifying signatures and MACs */ + +/* C_VerifyInit initializes a verification operation, where the + * signature is an appendix to the data, and plaintext cannot + * cannot be recovered from the signature (e.g. DSA). */ +CK_PKCS11_FUNCTION_INFO(C_VerifyInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_Verify verifies a signature in a single-part operation, + * where the signature is an appendix to the data, and plaintext + * cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Verify) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* signed data */ + CK_ULONG ulDataLen, /* length of signed data */ + CK_BYTE_PTR pSignature, /* signature */ + CK_ULONG ulSignatureLen /* signature length*/ +); +#endif + + +/* C_VerifyUpdate continues a multiple-part verification + * operation, where the signature is an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* signed data */ + CK_ULONG ulPartLen /* length of signed data */ +); +#endif + + +/* C_VerifyFinal finishes a multiple-part verification + * operation, checking the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen /* signature length */ +); +#endif + + +/* C_VerifyRecoverInit initializes a signature verification + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_VerifyRecover verifies a signature in a single-part + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen, /* signature length */ + CK_BYTE_PTR pData, /* gets signed data */ + CK_ULONG_PTR pulDataLen /* gets signed data len */ +); +#endif + + + +/* Dual-function cryptographic operations */ + +/* C_DigestEncryptUpdate continues a multiple-part digesting + * and encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptDigestUpdate continues a multiple-part decryption and + * digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets plaintext len */ +); +#endif + + +/* C_SignEncryptUpdate continues a multiple-part signing and + * encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptVerifyUpdate continues a multiple-part decryption and + * verify operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets p-text length */ +); +#endif + + + +/* Key management */ + +/* C_GenerateKey generates a secret key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* key generation mech. */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new key */ + CK_ULONG ulCount, /* # of attrs in template */ + CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */ +); +#endif + + +/* C_GenerateKeyPair generates a public-key/private-key pair, + * creating new key objects. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session + * handle */ + CK_MECHANISM_PTR pMechanism, /* key-gen + * mech. */ + CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template + * for pub. + * key */ + CK_ULONG ulPublicKeyAttributeCount, /* # pub. + * attrs. */ + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template + * for priv. + * key */ + CK_ULONG ulPrivateKeyAttributeCount, /* # priv. + * attrs. */ + CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. + * key + * handle */ + CK_OBJECT_HANDLE_PTR phPrivateKey /* gets + * priv. key + * handle */ +); +#endif + + +/* C_WrapKey wraps (i.e., encrypts) a key. */ +CK_PKCS11_FUNCTION_INFO(C_WrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */ + CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */ + CK_OBJECT_HANDLE hKey, /* key to be wrapped */ + CK_BYTE_PTR pWrappedKey, /* gets wrapped key */ + CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */ +); +#endif + + +/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new + * key object. */ +CK_PKCS11_FUNCTION_INFO(C_UnwrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */ + CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */ + CK_BYTE_PTR pWrappedKey, /* the wrapped key */ + CK_ULONG ulWrappedKeyLen, /* wrapped key len */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + +/* C_DeriveKey derives a key from a base key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_DeriveKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */ + CK_OBJECT_HANDLE hBaseKey, /* base key */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + + +/* Random number generation */ + +/* C_SeedRandom mixes additional seed material into the token's + * random number generator. */ +CK_PKCS11_FUNCTION_INFO(C_SeedRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSeed, /* the seed material */ + CK_ULONG ulSeedLen /* length of seed material */ +); +#endif + + +/* C_GenerateRandom generates random data. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR RandomData, /* receives the random data */ + CK_ULONG ulRandomLen /* # of bytes to generate */ +); +#endif + + + +/* Parallel function management */ + +/* C_GetFunctionStatus is a legacy function; it obtains an + * updated status of a function running in parallel with an + * application. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CancelFunction is a legacy function; it cancels a function + * running in parallel. */ +CK_PKCS11_FUNCTION_INFO(C_CancelFunction) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Functions added in for PKCS #11 Version 2.01 or later */ + +/* C_WaitForSlotEvent waits for a slot event (token insertion, + * removal, etc.) to occur. */ +CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) +#ifdef CK_NEED_ARG_LIST +( + CK_FLAGS flags, /* blocking/nonblocking flag */ + CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ + CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */ +); +#endif diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h new file mode 100644 index 0000000..497dfe0 --- /dev/null +++ b/ykcs11/pkcs11t.h @@ -0,0 +1,1134 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +/* + * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document + * is granted provided that it is identified as "RSA Security In.c Public-Key + * Cryptography Standards (PKCS)" in all material mentioning or referencing + * this document. + */ +/* See top of pkcs11.h for information about the macros that + * must be defined and the structure-packing conventions that + * must be set before including this file. + */ + +#ifndef _PKCS11T_H_ +#define _PKCS11T_H_ 1 + +#ifndef CK_FALSE +#define CK_FALSE 0 +#endif + +#ifndef CK_TRUE +#define CK_TRUE (!CK_FALSE) +#endif + +#include "prtypes.h" + +#define CK_PTR * +#define CK_NULL_PTR 0 +#define NULL_PTR 0 +#define CK_CALLBACK_FUNCTION(rv,func) rv (PR_CALLBACK * func) +#define CK_DECLARE_FUNCTION(rv,func) PR_EXTERN(rv) func +#define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (PR_CALLBACK * func) +#define CK_DEFINE_FUNCTION(rv, func) rv func + +/* an unsigned 8-bit value */ +typedef unsigned char CK_BYTE; + +/* an unsigned 8-bit character */ +typedef CK_BYTE CK_CHAR; + +/* an 8-bit UTF-8 character */ +typedef CK_BYTE CK_UTF8CHAR; + +/* a BYTE-sized Boolean flag */ +typedef CK_BYTE CK_BBOOL; + +/* an unsigned value, at least 32 bits long */ +typedef unsigned long int CK_ULONG; + +/* a signed value, the same size as a CK_ULONG */ +/* CK_LONG is new for v2.0 */ +typedef long int CK_LONG; + +/* at least 32 bits; each bit is a Boolean flag */ +typedef CK_ULONG CK_FLAGS; + + +/* some special values for certain CK_ULONG variables */ +#define CK_UNAVAILABLE_INFORMATION (~0UL) +#define CK_EFFECTIVELY_INFINITE 0 + + +typedef CK_BYTE CK_PTR CK_BYTE_PTR; +typedef CK_CHAR CK_PTR CK_CHAR_PTR; +typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; +typedef CK_ULONG CK_PTR CK_ULONG_PTR; +typedef void CK_PTR CK_VOID_PTR; + +/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ +typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; + + +/* The following value is always invalid if used as a session */ +/* handle or object handle */ +#define CK_INVALID_HANDLE 0 + + +/* pack */ +//#include "pkcs11p.h" // TODO: msc specific? + +typedef struct CK_VERSION { + CK_BYTE major; /* integer portion of version number */ + CK_BYTE minor; /* 1/100ths portion of version number */ +} CK_VERSION; + +typedef CK_VERSION CK_PTR CK_VERSION_PTR; + + +typedef struct CK_INFO { + CK_VERSION cryptokiVersion; /* PKCS #11 interface ver */ + CK_CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; /* must be zero */ + + /* libraryDescription and libraryVersion are new for v2.0 */ + CK_CHAR libraryDescription[32]; /* blank padded */ + CK_VERSION libraryVersion; /* version of library */ +} CK_INFO; + +typedef CK_INFO CK_PTR CK_INFO_PTR; + + +/* CK_NOTIFICATION enumerates the types of notifications that + * PKCS #11 provides to an application */ +/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_NOTIFICATION; +#define CKN_SURRENDER 0 + + +typedef CK_ULONG CK_SLOT_ID; + +typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; + + +/* CK_SLOT_INFO provides information about a slot */ +typedef struct CK_SLOT_INFO { + CK_CHAR slotDescription[64]; /* blank padded */ + CK_CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; + + /* hardwareVersion and firmwareVersion are new for v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ +} CK_SLOT_INFO; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ +#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ +#define CKF_HW_SLOT 0x00000004 /* hardware slot */ + +typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; + + +/* CK_TOKEN_INFO provides information about a token */ +typedef struct CK_TOKEN_INFO { + CK_CHAR label[32]; /* blank padded */ + CK_CHAR manufacturerID[32]; /* blank padded */ + CK_CHAR model[16]; /* blank padded */ + CK_CHAR serialNumber[16]; /* blank padded */ + CK_FLAGS flags; /* see below */ + + /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, + * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been + * changed from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulMaxSessionCount; /* max open sessions */ + CK_ULONG ulSessionCount; /* sess. now open */ + CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ + CK_ULONG ulRwSessionCount; /* R/W sess. now open */ + CK_ULONG ulMaxPinLen; /* in bytes */ + CK_ULONG ulMinPinLen; /* in bytes */ + CK_ULONG ulTotalPublicMemory; /* in bytes */ + CK_ULONG ulFreePublicMemory; /* in bytes */ + CK_ULONG ulTotalPrivateMemory; /* in bytes */ + CK_ULONG ulFreePrivateMemory; /* in bytes */ + + /* hardwareVersion, firmwareVersion, and time are new for + * v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ + CK_CHAR utcTime[16]; /* time */ +} CK_TOKEN_INFO; + +/* The flags parameter is defined as follows: + * Bit Flag Mask Meaning + */ +#define CKF_RNG 0x00000001 /* has random # + * generator */ +#define CKF_WRITE_PROTECTED 0x00000002 /* token is + * write- + * protected */ +#define CKF_LOGIN_REQUIRED 0x00000004 /* user must + * login */ +#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's + * PIN is set */ + +/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, + * that means that *every* time the state of cryptographic + * operations of a session is successfully saved, all keys + * needed to continue those operations are stored in the state */ +#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 + +/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means + * that the token has some sort of clock. The time on that + * clock is returned in the token info structure */ +#define CKF_CLOCK_ON_TOKEN 0x00000040 + +/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is + * set, that means that there is some way for the user to login + * without sending a PIN through the PKCS #11 library itself */ +#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 + +/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, + * that means that a single session with the token can perform + * dual simultaneous cryptographic operations (digest and + * encrypt; decrypt and digest; sign and encrypt; and decrypt + * and sign) */ +#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 + +typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; + + +/* CK_SESSION_HANDLE is a PKCS #11-assigned value that + * identifies a session */ +typedef CK_ULONG CK_SESSION_HANDLE; + +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; + + +/* CK_USER_TYPE enumerates the types of PKCS #11 users */ +/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_USER_TYPE; +/* Security Officer */ +#define CKU_SO 0 +/* Normal user */ +#define CKU_USER 1 + + +/* CK_STATE enumerates the session states */ +/* CK_STATE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_STATE; +#define CKS_RO_PUBLIC_SESSION 0 +#define CKS_RO_USER_FUNCTIONS 1 +#define CKS_RW_PUBLIC_SESSION 2 +#define CKS_RW_USER_FUNCTIONS 3 +#define CKS_RW_SO_FUNCTIONS 4 + + +/* CK_SESSION_INFO provides information about a session */ +typedef struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; /* see below */ + + /* ulDeviceError was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulDeviceError; /* device-dependent error code */ +} CK_SESSION_INFO; + +/* The flags are defined in the following table: + * Bit Flag Mask Meaning + */ +#define CKF_RW_SESSION 0x00000002 /* session is r/w */ +#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ + +typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; + + +/* CK_OBJECT_HANDLE is a token-specific identifier for an + * object */ +typedef CK_ULONG CK_OBJECT_HANDLE; + +typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; + + +/* CK_OBJECT_CLASS is a value that identifies the classes (or + * types) of objects that PKCS #11 recognizes. It is defined + * as follows: */ +/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_OBJECT_CLASS; + +/* The following classes of objects are defined: */ +#define CKO_DATA 0x00000000 +#define CKO_CERTIFICATE 0x00000001 +#define CKO_PUBLIC_KEY 0x00000002 +#define CKO_PRIVATE_KEY 0x00000003 +#define CKO_SECRET_KEY 0x00000004 +#define CKO_VENDOR_DEFINED 0x80000000 + +typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; + + +/* CK_KEY_TYPE is a value that identifies a key type */ +/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_KEY_TYPE; + +/* the following key types are defined: */ +#define CKK_RSA 0x00000000 +#define CKK_DSA 0x00000001 +#define CKK_DH 0x00000002 + +/* CKK_ECDSA and CKK_KEA are new for v2.0 */ + +/* PKCS #11 V2.01 probably won't actually have ECDSA in it */ +#define CKK_ECDSA 0x00000003 + +#define CKK_KEA 0x00000005 + +#define CKK_GENERIC_SECRET 0x00000010 +#define CKK_RC2 0x00000011 +#define CKK_RC4 0x00000012 +#define CKK_DES 0x00000013 +#define CKK_DES2 0x00000014 +#define CKK_DES3 0x00000015 + +/* all these key types are new for v2.0 */ +#define CKK_CAST 0x00000016 +#define CKK_CAST3 0x00000017 +#define CKK_CAST5 0x00000018 +#define CKK_CAST128 0x00000018 /* CAST128=CAST5 */ +#define CKK_RC5 0x00000019 +#define CKK_IDEA 0x0000001A +#define CKK_SKIPJACK 0x0000001B +#define CKK_BATON 0x0000001C +#define CKK_JUNIPER 0x0000001D +#define CKK_CDMF 0x0000001E + +/* all these key types are new for v2.11 */ +#define CKK_AES 0x0000001F + +#define CKK_VENDOR_DEFINED 0x80000000 + + +/* CK_CERTIFICATE_TYPE is a value that identifies a certificate + * type */ +/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_CERTIFICATE_TYPE; + +/* The following certificate types are defined: */ +#define CKC_X_509 0x00000000 +#define CKC_VENDOR_DEFINED 0x80000000 + + +/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute + * type */ +/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +/* The following attribute types are defined: */ +#define CKA_CLASS 0x00000000 +#define CKA_TOKEN 0x00000001 +#define CKA_PRIVATE 0x00000002 +#define CKA_LABEL 0x00000003 +#define CKA_APPLICATION 0x00000010 +#define CKA_VALUE 0x00000011 +#define CKA_CERTIFICATE_TYPE 0x00000080 +#define CKA_ISSUER 0x00000081 +#define CKA_SERIAL_NUMBER 0x00000082 +#define CKA_KEY_TYPE 0x00000100 +#define CKA_SUBJECT 0x00000101 +#define CKA_ID 0x00000102 +#define CKA_SENSITIVE 0x00000103 +#define CKA_ENCRYPT 0x00000104 +#define CKA_DECRYPT 0x00000105 +#define CKA_WRAP 0x00000106 +#define CKA_UNWRAP 0x00000107 +#define CKA_SIGN 0x00000108 +#define CKA_SIGN_RECOVER 0x00000109 +#define CKA_VERIFY 0x0000010A +#define CKA_VERIFY_RECOVER 0x0000010B +#define CKA_DERIVE 0x0000010C +#define CKA_START_DATE 0x00000110 +#define CKA_END_DATE 0x00000111 +#define CKA_MODULUS 0x00000120 +#define CKA_MODULUS_BITS 0x00000121 +#define CKA_PUBLIC_EXPONENT 0x00000122 +#define CKA_PRIVATE_EXPONENT 0x00000123 +#define CKA_PRIME_1 0x00000124 +#define CKA_PRIME_2 0x00000125 +#define CKA_EXPONENT_1 0x00000126 +#define CKA_EXPONENT_2 0x00000127 +#define CKA_COEFFICIENT 0x00000128 +#define CKA_PRIME 0x00000130 +#define CKA_SUBPRIME 0x00000131 +#define CKA_BASE 0x00000132 +#define CKA_VALUE_BITS 0x00000160 +#define CKA_VALUE_LEN 0x00000161 + +/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, + * CKA_ALWAYS_SENSITIVE, and CKA_MODIFIABLE are new for v2.0 */ +#define CKA_EXTRACTABLE 0x00000162 +#define CKA_LOCAL 0x00000163 +#define CKA_NEVER_EXTRACTABLE 0x00000164 +#define CKA_ALWAYS_SENSITIVE 0x00000165 +#define CKA_MODIFIABLE 0x00000170 + +#define CKA_VENDOR_DEFINED 0x80000000 + + +/* CK_ATTRIBUTE is a structure that includes the type, length + * and value of an attribute */ +typedef struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + + /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulValueLen; /* in bytes */ +} CK_ATTRIBUTE; + +typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; + + +/* CK_DATE is a structure that defines a date */ +typedef struct CK_DATE{ + CK_CHAR year[4]; /* the year ("1900" - "9999") */ + CK_CHAR month[2]; /* the month ("01" - "12") */ + CK_CHAR day[2]; /* the day ("01" - "31") */ +} CK_DATE; + + +/* CK_MECHANISM_TYPE is a value that identifies a mechanism + * type */ +/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_MECHANISM_TYPE; + +/* the following mechanism types are defined: */ +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 +#define CKM_RSA_PKCS 0x00000001 +#define CKM_RSA_9796 0x00000002 +#define CKM_RSA_X_509 0x00000003 + +/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS + * are new for v2.0. They are mechanisms which hash and sign */ +#define CKM_MD2_RSA_PKCS 0x00000004 +#define CKM_MD5_RSA_PKCS 0x00000005 +#define CKM_SHA1_RSA_PKCS 0x00000006 + +#define CKM_DSA_KEY_PAIR_GEN 0x00000010 +#define CKM_DSA 0x00000011 +#define CKM_DSA_SHA1 0x00000012 +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 +#define CKM_DH_PKCS_DERIVE 0x00000021 +#define CKM_RC2_KEY_GEN 0x00000100 +#define CKM_RC2_ECB 0x00000101 +#define CKM_RC2_CBC 0x00000102 +#define CKM_RC2_MAC 0x00000103 + +/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ +#define CKM_RC2_MAC_GENERAL 0x00000104 +#define CKM_RC2_CBC_PAD 0x00000105 + +#define CKM_RC4_KEY_GEN 0x00000110 +#define CKM_RC4 0x00000111 +#define CKM_DES_KEY_GEN 0x00000120 +#define CKM_DES_ECB 0x00000121 +#define CKM_DES_CBC 0x00000122 +#define CKM_DES_MAC 0x00000123 + +/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ +#define CKM_DES_MAC_GENERAL 0x00000124 +#define CKM_DES_CBC_PAD 0x00000125 + +#define CKM_DES2_KEY_GEN 0x00000130 +#define CKM_DES3_KEY_GEN 0x00000131 +#define CKM_DES3_ECB 0x00000132 +#define CKM_DES3_CBC 0x00000133 +#define CKM_DES3_MAC 0x00000134 + +/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, + * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, + * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ +#define CKM_DES3_MAC_GENERAL 0x00000135 +#define CKM_DES3_CBC_PAD 0x00000136 +#define CKM_CDMF_KEY_GEN 0x00000140 +#define CKM_CDMF_ECB 0x00000141 +#define CKM_CDMF_CBC 0x00000142 +#define CKM_CDMF_MAC 0x00000143 +#define CKM_CDMF_MAC_GENERAL 0x00000144 +#define CKM_CDMF_CBC_PAD 0x00000145 + +#define CKM_MD2 0x00000200 + +/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD2_HMAC 0x00000201 +#define CKM_MD2_HMAC_GENERAL 0x00000202 + +#define CKM_MD5 0x00000210 + +/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD5_HMAC 0x00000211 +#define CKM_MD5_HMAC_GENERAL 0x00000212 + +#define CKM_SHA_1 0x00000220 + +/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ +#define CKM_SHA_1_HMAC 0x00000221 +#define CKM_SHA_1_HMAC_GENERAL 0x00000222 + +/* All of the following mechanisms are new for v2.0 */ +/* Note that CAST128 and CAST5 are the same algorithm */ +#define CKM_CAST_KEY_GEN 0x00000300 +#define CKM_CAST_ECB 0x00000301 +#define CKM_CAST_CBC 0x00000302 +#define CKM_CAST_MAC 0x00000303 +#define CKM_CAST_MAC_GENERAL 0x00000304 +#define CKM_CAST_CBC_PAD 0x00000305 +#define CKM_CAST3_KEY_GEN 0x00000310 +#define CKM_CAST3_ECB 0x00000311 +#define CKM_CAST3_CBC 0x00000312 +#define CKM_CAST3_MAC 0x00000313 +#define CKM_CAST3_MAC_GENERAL 0x00000314 +#define CKM_CAST3_CBC_PAD 0x00000315 +#define CKM_CAST5_KEY_GEN 0x00000320 +#define CKM_CAST128_KEY_GEN 0x00000320 +#define CKM_CAST5_ECB 0x00000321 +#define CKM_CAST128_ECB 0x00000321 +#define CKM_CAST5_CBC 0x00000322 +#define CKM_CAST128_CBC 0x00000322 +#define CKM_CAST5_MAC 0x00000323 +#define CKM_CAST128_MAC 0x00000323 +#define CKM_CAST5_MAC_GENERAL 0x00000324 +#define CKM_CAST128_MAC_GENERAL 0x00000324 +#define CKM_CAST5_CBC_PAD 0x00000325 +#define CKM_CAST128_CBC_PAD 0x00000325 +#define CKM_RC5_KEY_GEN 0x00000330 +#define CKM_RC5_ECB 0x00000331 +#define CKM_RC5_CBC 0x00000332 +#define CKM_RC5_MAC 0x00000333 +#define CKM_RC5_MAC_GENERAL 0x00000334 +#define CKM_RC5_CBC_PAD 0x00000335 +#define CKM_IDEA_KEY_GEN 0x00000340 +#define CKM_IDEA_ECB 0x00000341 +#define CKM_IDEA_CBC 0x00000342 +#define CKM_IDEA_MAC 0x00000343 +#define CKM_IDEA_MAC_GENERAL 0x00000344 +#define CKM_IDEA_CBC_PAD 0x00000345 +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 +#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 +#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 +#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 +#define CKM_XOR_BASE_AND_DATA 0x00000364 +#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 +#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 +#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 +#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 +#define CKM_SSL3_MD5_MAC 0x00000380 +#define CKM_SSL3_SHA1_MAC 0x00000381 +#define CKM_MD5_KEY_DERIVATION 0x00000390 +#define CKM_MD2_KEY_DERIVATION 0x00000391 +#define CKM_SHA1_KEY_DERIVATION 0x00000392 +#define CKM_PBE_MD2_DES_CBC 0x000003A0 +#define CKM_PBE_MD5_DES_CBC 0x000003A1 +#define CKM_PBE_MD5_CAST_CBC 0x000003A2 +#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 +#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 +#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 +#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 +#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 +#define CKM_PBE_SHA1_RC4_128 0x000003A6 +#define CKM_PBE_SHA1_RC4_40 0x000003A7 +#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 +#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 +#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA +#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB +#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 +#define CKM_KEY_WRAP_LYNKS 0x00000400 +#define CKM_KEY_WRAP_SET_OAEP 0x00000401 + +/* Fortezza mechanisms */ +#define CKM_SKIPJACK_KEY_GEN 0x00001000 +#define CKM_SKIPJACK_ECB64 0x00001001 +#define CKM_SKIPJACK_CBC64 0x00001002 +#define CKM_SKIPJACK_OFB64 0x00001003 +#define CKM_SKIPJACK_CFB64 0x00001004 +#define CKM_SKIPJACK_CFB32 0x00001005 +#define CKM_SKIPJACK_CFB16 0x00001006 +#define CKM_SKIPJACK_CFB8 0x00001007 +#define CKM_SKIPJACK_WRAP 0x00001008 +#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 +#define CKM_SKIPJACK_RELAYX 0x0000100a +#define CKM_KEA_KEY_PAIR_GEN 0x00001010 +#define CKM_KEA_KEY_DERIVE 0x00001011 +#define CKM_FORTEZZA_TIMESTAMP 0x00001020 +#define CKM_BATON_KEY_GEN 0x00001030 +#define CKM_BATON_ECB128 0x00001031 +#define CKM_BATON_ECB96 0x00001032 +#define CKM_BATON_CBC128 0x00001033 +#define CKM_BATON_COUNTER 0x00001034 +#define CKM_BATON_SHUFFLE 0x00001035 +#define CKM_BATON_WRAP 0x00001036 + +/* PKCS #11 V2.01 probably won't actually have ECDSA in it */ +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_ECDSA 0x00001041 +#define CKM_ECDSA_SHA1 0x00001042 + +#define CKM_JUNIPER_KEY_GEN 0x00001060 +#define CKM_JUNIPER_ECB128 0x00001061 +#define CKM_JUNIPER_CBC128 0x00001062 +#define CKM_JUNIPER_COUNTER 0x00001063 +#define CKM_JUNIPER_SHUFFLE 0x00001064 +#define CKM_JUNIPER_WRAP 0x00001065 +#define CKM_FASTHASH 0x00001070 + +#define CKM_AES_KEY_GEN 0x00001080 +#define CKM_AES_ECB 0x00001081 +#define CKM_AES_CBC 0x00001082 +#define CKM_AES_MAC 0x00001083 +#define CKM_AES_MAC_GENERAL 0x00001084 +#define CKM_AES_CBC_PAD 0x00001085 + +#define CKM_VENDOR_DEFINED 0x80000000 + +typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; + + +/* CK_MECHANISM is a structure that specifies a particular + * mechanism */ +typedef struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + + /* ulParameterLen was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulParameterLen; /* in bytes */ +} CK_MECHANISM; + +typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; + + +/* CK_MECHANISM_INFO provides information about a particular + * mechanism */ +typedef struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +} CK_MECHANISM_INFO; + +/* The flags are defined as follows: + * Bit Flag Mask Meaning */ +#define CKF_HW 0x00000001 /* performed by HW */ + +/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, + * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, + * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, + * and CKF_DERIVE are new for v2.0. They specify whether or not + * a mechanism can be used for a particular task */ +#define CKF_ENCRYPT 0x00000100 +#define CKF_DECRYPT 0x00000200 +#define CKF_DIGEST 0x00000400 +#define CKF_SIGN 0x00000800 +#define CKF_SIGN_RECOVER 0x00001000 +#define CKF_VERIFY 0x00002000 +#define CKF_VERIFY_RECOVER 0x00004000 +#define CKF_GENERATE 0x00008000 +#define CKF_GENERATE_KEY_PAIR 0x00010000 +#define CKF_WRAP 0x00020000 +#define CKF_UNWRAP 0x00040000 +#define CKF_DERIVE 0x00080000 + +#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */ + +typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; + + +/* CK_RV is a value that identifies the return value of a + * PKCS #11 function */ +/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_RV; + +#define CKR_OK 0x00000000 +#define CKR_CANCEL 0x00000001 +#define CKR_HOST_MEMORY 0x00000002 +#define CKR_SLOT_ID_INVALID 0x00000003 + +/* CKR_FLAGS_INVALID was removed for v2.0 */ + +/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ +#define CKR_GENERAL_ERROR 0x00000005 +#define CKR_FUNCTION_FAILED 0x00000006 + +/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, + * and CKR_CANT_LOCK are new for v2.01 */ +#define CKR_ARGUMENTS_BAD 0x00000007 +#define CKR_NO_EVENT 0x00000008 +#define CKR_NEED_TO_CREATE_THREADS 0x00000009 +#define CKR_CANT_LOCK 0x0000000A + +#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 +#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 +#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 +#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 +#define CKR_DATA_INVALID 0x00000020 +#define CKR_DATA_LEN_RANGE 0x00000021 +#define CKR_DEVICE_ERROR 0x00000030 +#define CKR_DEVICE_MEMORY 0x00000031 +#define CKR_DEVICE_REMOVED 0x00000032 +#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 +#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 +#define CKR_FUNCTION_CANCELED 0x00000050 +#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 + +/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ +#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 + +#define CKR_KEY_HANDLE_INVALID 0x00000060 + +/* CKR_KEY_SENSITIVE was removed for v2.0 */ + +#define CKR_KEY_SIZE_RANGE 0x00000062 +#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 + +/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, + * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, + * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for + * v2.0 */ +#define CKR_KEY_NOT_NEEDED 0x00000064 +#define CKR_KEY_CHANGED 0x00000065 +#define CKR_KEY_NEEDED 0x00000066 +#define CKR_KEY_INDIGESTIBLE 0x00000067 +#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 +#define CKR_KEY_NOT_WRAPPABLE 0x00000069 +#define CKR_KEY_UNEXTRACTABLE 0x0000006A + +#define CKR_MECHANISM_INVALID 0x00000070 +#define CKR_MECHANISM_PARAM_INVALID 0x00000071 + +/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID + * were removed for v2.0 */ +#define CKR_OBJECT_HANDLE_INVALID 0x00000082 +#define CKR_OPERATION_ACTIVE 0x00000090 +#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 +#define CKR_PIN_INCORRECT 0x000000A0 +#define CKR_PIN_INVALID 0x000000A1 +#define CKR_PIN_LEN_RANGE 0x000000A2 + +/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ +#define CKR_PIN_EXPIRED 0x000000A3 +#define CKR_PIN_LOCKED 0x000000A4 + +#define CKR_SESSION_CLOSED 0x000000B0 +#define CKR_SESSION_COUNT 0x000000B1 +#define CKR_SESSION_HANDLE_INVALID 0x000000B3 +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 +#define CKR_SESSION_READ_ONLY 0x000000B5 +#define CKR_SESSION_EXISTS 0x000000B6 + +/* CKR_SESSION_READ_ONLY_EXISTS and + * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ +#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 +#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 + +#define CKR_SIGNATURE_INVALID 0x000000C0 +#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 +#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 +#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 +#define CKR_TOKEN_NOT_PRESENT 0x000000E0 +#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 +#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 +#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 +#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 +#define CKR_USER_NOT_LOGGED_IN 0x00000101 +#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 +#define CKR_USER_TYPE_INVALID 0x00000103 + +/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES + * are new to v2.01 */ +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 +#define CKR_USER_TOO_MANY_TYPES 0x00000105 + +#define CKR_WRAPPED_KEY_INVALID 0x00000110 +#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 +#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 +#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 +#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 + +/* These are new to v2.0 */ +#define CKR_RANDOM_NO_RNG 0x00000121 +#define CKR_BUFFER_TOO_SMALL 0x00000150 +#define CKR_SAVED_STATE_INVALID 0x00000160 +#define CKR_INFORMATION_SENSITIVE 0x00000170 +#define CKR_STATE_UNSAVEABLE 0x00000180 + +/* These are new to v2.01 */ +#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 +#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 +#define CKR_MUTEX_BAD 0x000001A0 +#define CKR_MUTEX_NOT_LOCKED 0x000001A1 + +#define CKR_VENDOR_DEFINED 0x80000000 + + +/* CK_NOTIFY is an application callback that processes events */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_NOTIFICATION event, + CK_VOID_PTR pApplication /* passed to C_OpenSession */ +); + + +/* CK_FUNCTION_LIST is a structure holding a PKCS #11 spec + * version and pointers of appropriate types to all the + * PKCS #11 functions */ +/* CK_FUNCTION_LIST is new for v2.0 */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; + +typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; + +typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; + + +/* CK_CREATEMUTEX is an application callback for creating a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( + CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ +); + + +/* CK_DESTROYMUTEX is an application callback for destroying a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_LOCKMUTEX is an application callback for locking a mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_UNLOCKMUTEX is an application callback for unlocking a + * mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_C_INITIALIZE_ARGS provides the optional arguments to + * C_Initialize */ +typedef struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; +} CK_C_INITIALIZE_ARGS; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 +#define CKF_OS_LOCKING_OK 0x00000002 + +typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; + + +/* additional flags for parameters to functions */ + +/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ +#define CKF_DONT_BLOCK 1 + + +/* CK_KEA_DERIVE_PARAMS provides the parameters to the + * CKM_KEA_DERIVE mechanism */ +/* CK_KEA_DERIVE_PARAMS is new for v2.0 */ +typedef struct CK_KEA_DERIVE_PARAMS { + CK_BBOOL isSender; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pRandomB; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_KEA_DERIVE_PARAMS; + +typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; + + +/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and + * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just + * holds the effective keysize */ +typedef CK_ULONG CK_RC2_PARAMS; + +typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; + + +/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC + * mechanism */ +typedef struct CK_RC2_CBC_PARAMS { + /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + + CK_BYTE iv[8]; /* IV for CBC mode */ +} CK_RC2_CBC_PARAMS; + +typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; + + +/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC2_MAC_GENERAL mechanism */ +/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC2_MAC_GENERAL_PARAMS { + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC2_MAC_GENERAL_PARAMS; + +typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC2_MAC_GENERAL_PARAMS_PTR; + + +/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and + * CKM_RC5_MAC mechanisms */ +/* CK_RC5_PARAMS is new for v2.0 */ +typedef struct CK_RC5_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ +} CK_RC5_PARAMS; + +typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; + + +/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC + * mechanism */ +/* CK_RC5_CBC_PARAMS is new for v2.0 */ +typedef struct CK_RC5_CBC_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_BYTE_PTR pIv; /* pointer to IV */ + CK_ULONG ulIvLen; /* length of IV in bytes */ +} CK_RC5_CBC_PARAMS; + +typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; + + +/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC5_MAC_GENERAL mechanism */ +/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC5_MAC_GENERAL_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC5_MAC_GENERAL_PARAMS; + +typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC5_MAC_GENERAL_PARAMS_PTR; + + +/* CK_MAC_GENERAL_PARAMS provides the parameters to most block + * ciphers' MAC_GENERAL mechanisms. Its value is the length of + * the MAC */ +/* CK_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_MAC_GENERAL_PARAMS; + +typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; + + +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the + * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pPassword; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPAndGLen; + CK_ULONG ulQLen; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pPrimeP; + CK_BYTE_PTR pBaseG; + CK_BYTE_PTR pSubprimeQ; +} CK_SKIPJACK_PRIVATE_WRAP_PARAMS; + +typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ + CK_SKIPJACK_PRIVATE_WRAP_PTR; + + +/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the + * CKM_SKIPJACK_RELAYX mechanism */ +/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_RELAYX_PARAMS { + CK_ULONG ulOldWrappedXLen; + CK_BYTE_PTR pOldWrappedX; + CK_ULONG ulOldPasswordLen; + CK_BYTE_PTR pOldPassword; + CK_ULONG ulOldPublicDataLen; + CK_BYTE_PTR pOldPublicData; + CK_ULONG ulOldRandomLen; + CK_BYTE_PTR pOldRandomA; + CK_ULONG ulNewPasswordLen; + CK_BYTE_PTR pNewPassword; + CK_ULONG ulNewPublicDataLen; + CK_BYTE_PTR pNewPublicData; + CK_ULONG ulNewRandomLen; + CK_BYTE_PTR pNewRandomA; +} CK_SKIPJACK_RELAYX_PARAMS; + +typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ + CK_SKIPJACK_RELAYX_PARAMS_PTR; + + +typedef struct CK_PBE_PARAMS { + CK_CHAR_PTR pInitVector; + CK_CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; + CK_CHAR_PTR pSalt; + CK_ULONG ulSaltLen; + CK_ULONG ulIteration; +} CK_PBE_PARAMS; + +typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; + + +/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the + * CKM_KEY_WRAP_SET_OAEP mechanism */ +/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ +typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { + CK_BYTE bBC; /* block contents byte */ + CK_BYTE_PTR pX; /* extra data */ + CK_ULONG ulXLen; /* length of extra data in bytes */ +} CK_KEY_WRAP_SET_OAEP_PARAMS; + +typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ + CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; + + +typedef struct CK_SSL3_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_SSL3_RANDOM_DATA; + + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { + CK_SSL3_RANDOM_DATA RandomInfo; + CK_VERSION_PTR pVersion; +} CK_SSL3_MASTER_KEY_DERIVE_PARAMS; + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; + + +typedef struct CK_SSL3_KEY_MAT_OUT { + CK_OBJECT_HANDLE hClientMacSecret; + CK_OBJECT_HANDLE hServerMacSecret; + CK_OBJECT_HANDLE hClientKey; + CK_OBJECT_HANDLE hServerKey; + CK_BYTE_PTR pIVClient; + CK_BYTE_PTR pIVServer; +} CK_SSL3_KEY_MAT_OUT; + +typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; + + +typedef struct CK_SSL3_KEY_MAT_PARAMS { + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_BBOOL bIsExport; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_SSL3_KEY_MAT_PARAMS; + +typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; + + +typedef struct CK_KEY_DERIVATION_STRING_DATA { + CK_BYTE_PTR pData; + CK_ULONG ulLen; +} CK_KEY_DERIVATION_STRING_DATA; + +typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ + CK_KEY_DERIVATION_STRING_DATA_PTR; + + +/* The CK_EXTRACT_PARAMS is used for the + * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit + * of the base key should be used as the first bit of the + * derived key */ +/* CK_EXTRACT_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_EXTRACT_PARAMS; + +typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; + +/* Do not attempt to use these. They are only used by NETSCAPE's internal + * PKCS #11 interface. Most of these are place holders for other mechanism + * and will change in the future. + */ +#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001L +#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L +#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L +#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L +#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L +#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L +#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L +#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L +#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L +#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL +#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL +#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L +#define CKM_TLS_PRF_GENERAL 0x80000373L + +/* define used to pass in the database key for DSA private keys */ +#define CKA_NETSCAPE_DB 0xD5A0DB00L +#define CKA_NETSCAPE_TRUST 0x80000001L + +/* undo packing */ +//#include "pkcs11u.h" // TODO: msc specific? + +#endif diff --git a/ykcs11/version.c b/ykcs11/version.c new file mode 100644 index 0000000..ffdcdec --- /dev/null +++ b/ykcs11/version.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2015 Yubico AB + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Additional permission under GNU GPL version 3 section 7 + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, We grant you additional + * permission to convey the resulting work. Corresponding Source for a + * non-source form of such a combination shall include the source code + * for the parts of OpenSSL used as well as that of the covered work. + * + */ + +#include "ykcs11-version.h" + +#include + +#include + +/* From http://article.gmane.org/gmane.os.freebsd.devel.hackers/23606 */ +static int my_strverscmp (const char *s1, const char *s2) +{ + static const char *digits = "0123456789"; + size_t p1, p2; + + p1 = strcspn (s1, digits); + p2 = strcspn (s2, digits); + while (p1 == p2 && s1[p1] != '\0' && s2[p2] != '\0') { + int ret, lz1, lz2; + /* Different prefix */ + if ((ret = strncmp (s1, s2, p1)) != 0) + return ret; + + s1 += p1; + s2 += p2; + + lz1 = lz2 = 0; + if (*s1 == '0') + lz1 = 1; + if (*s2 == '0') + lz2 = 1; + + if (lz1 > lz2) + return -1; + else if (lz1 < lz2) + return 1; + else if (lz1 == 1) { + /* + * If the common prefix for s1 and s2 consists only of zeros, then the + * "longer" number has to compare less. Otherwise the comparison needs + * to be numerical (just fallthrough). See + * http://refspecs.freestandards.org/LSB_2.0.1/LSB-generic/ + * LSB-generic/baselib-strverscmp.html + */ + while (*s1 == '0' && *s2 == '0') { + ++s1; + ++s2; + } + + p1 = strspn (s1, digits); + p2 = strspn (s2, digits); + + /* Catch empty strings */ + if (p1 == 0 && p2 > 0) + return 1; + else if (p2 == 0 && p1 > 0) + return -1; + + /* Prefixes are not same */ + if (*s1 != *s2 && *s1 != '0' && *s2 != '0') { + if (p1 < p2) + return 1; + else if (p1 > p2) + return -1; + } else { + if (p1 < p2) + ret = strncmp (s1, s2, p1); + else if (p1 > p2) + ret = strncmp (s1, s2, p2); + if (ret != 0) + return ret; + } + } + + p1 = strspn (s1, digits); + p2 = strspn (s2, digits); + + if (p1 < p2) + return -1; + else if (p1 > p2) + return 1; + else if ((ret = strncmp (s1, s2, p1)) != 0) + return ret; + + /* Numbers are equal or not present, try with next ones. */ + s1 += p1; + s2 += p2; + p1 = strcspn (s1, digits); + p2 = strcspn (s2, digits); + } + + return strcmp (s1, s2); +} + +/** + * ykcs11_check_version: + * @req_version: Required version number, or NULL. + * + * Check that the version of the library is at minimum the requested + * one and return the version string; return NULL if the condition is + * not satisfied. If a NULL is passed to this function, no check is + * done, but the version string is simply returned. + * + * See %YKCS11_VERSION_STRING for a suitable @req_version string. + * + * Return value: Version string of run-time library, or NULL if the + * run-time library does not meet the required version number. + */ +const char * ykcs11_check_version (const char *req_version) +{ + if (!req_version + || my_strverscmp (req_version, YKCS11_VERSION_STRING) <= 0) + return YKCS11_VERSION_STRING; + + return NULL; +} diff --git a/ykcs11/ykcs11-version.h b/ykcs11/ykcs11-version.h new file mode 100644 index 0000000..e23b891 --- /dev/null +++ b/ykcs11/ykcs11-version.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015 Yubico AB + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Additional permission under GNU GPL version 3 section 7 + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, We grant you additional + * permission to convey the resulting work. Corresponding Source for a + * non-source form of such a combination shall include the source code + * for the parts of OpenSSL used as well as that of the covered work. + * + */ + +#ifndef YKCS11_VERSION_H +#define YKCS11_VERSION_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * YKCS11_VERSION_STRING + * + * Pre-processor symbol with a string that describe the header file + * version number. Used together with ykneomgr_check_version() to verify + * header file and run-time library consistency. + */ +#define YKCS11_VERSION_STRING "1.0.1" + + /** + * YKCS11_VERSION_NUMBER + * + * Pre-processor symbol with a hexadecimal value describing the header + * file version number. For example, when the header version is 1.2.3 + * this symbol will have the value 0x01020300. The last two digits + * are only used between public releases, and will otherwise be 00. + */ +#define YKCS11_VERSION_NUMBER @YKCS11_VERSION_NUMBER@ + + /** + * YKCS11_VERSION_MAJOR + * + * Pre-processor symbol with a decimal value that describe the major + * level of the header file version number. For example, when the + * header version is 1.2.3 this symbol will be 1. + */ +#define YKCS11_VERSION_MAJOR @YKCS11_VERSION_MAJOR@ + + /** + * YKCS11_VERSION_MINOR + * + * Pre-processor symbol with a decimal value that describe the minor + * level of the header file version number. For example, when the + * header version is 1.2.3 this symbol will be 2. + */ +#define YKCS11_VERSION_MINOR @YKCS11_VERSION_MINOR@ + + /** + * YKCS11_VERSION_PATCH + * + * Pre-processor symbol with a decimal value that describe the patch + * level of the header file version number. For example, when the + * header version is 1.2.3 this symbol will be 3. + */ +#define YKCS11_VERSION_PATCH @YKCS11_VERSION_PATCH@ + + const char *ykcs11_check_version (const char *req_version); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ykcs11/ykcs11-version.h.in b/ykcs11/ykcs11-version.h.in new file mode 100644 index 0000000..f973c1e --- /dev/null +++ b/ykcs11/ykcs11-version.h.in @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015 Yubico AB + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Additional permission under GNU GPL version 3 section 7 + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, We grant you additional + * permission to convey the resulting work. Corresponding Source for a + * non-source form of such a combination shall include the source code + * for the parts of OpenSSL used as well as that of the covered work. + * + */ + +#ifndef YKCS11_VERSION_H +#define YKCS11_VERSION_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * YKCS11_VERSION_STRING + * + * Pre-processor symbol with a string that describe the header file + * version number. Used together with ykneomgr_check_version() to verify + * header file and run-time library consistency. + */ +#define YKCS11_VERSION_STRING "@VERSION@" + + /** + * YKCS11_VERSION_NUMBER + * + * Pre-processor symbol with a hexadecimal value describing the header + * file version number. For example, when the header version is 1.2.3 + * this symbol will have the value 0x01020300. The last two digits + * are only used between public releases, and will otherwise be 00. + */ +#define YKCS11_VERSION_NUMBER @YKCS11_VERSION_NUMBER@ + + /** + * YKCS11_VERSION_MAJOR + * + * Pre-processor symbol with a decimal value that describe the major + * level of the header file version number. For example, when the + * header version is 1.2.3 this symbol will be 1. + */ +#define YKCS11_VERSION_MAJOR @YKCS11_VERSION_MAJOR@ + + /** + * YKCS11_VERSION_MINOR + * + * Pre-processor symbol with a decimal value that describe the minor + * level of the header file version number. For example, when the + * header version is 1.2.3 this symbol will be 2. + */ +#define YKCS11_VERSION_MINOR @YKCS11_VERSION_MINOR@ + + /** + * YKCS11_VERSION_PATCH + * + * Pre-processor symbol with a decimal value that describe the patch + * level of the header file version number. For example, when the + * header version is 1.2.3 this symbol will be 3. + */ +#define YKCS11_VERSION_PATCH @YKCS11_VERSION_PATCH@ + + const char *ykcs11_check_version (const char *req_version); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c new file mode 100644 index 0000000..71844c8 --- /dev/null +++ b/ykcs11/ykcs11.c @@ -0,0 +1,875 @@ +#include "pkcs11.h" +#include + +#define D(x) do { \ + printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ + printf x; \ + printf ("\n"); \ + } while (0) + +#define DBG(x) if (debug) { D(x); } + +static const int debug = 1; + +extern CK_FUNCTION_LIST function_list; + +/* General Purpose */ + +CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( + CK_VOID_PTR pInitArgs +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( + CK_VOID_PTR pReserved +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)( + CK_VOID_PTR pInfo +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)( + CK_FUNCTION_LIST_PTR_PTR ppFunctionList +) +{ + DBG(("In")); + if(ppFunctionList == NULL_PTR) { + return CKR_ARGUMENTS_BAD; + } + *ppFunctionList = &function_list; + + return CKR_OK; +} + +/* Slot and token management */ + +CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( + CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( + CK_SLOT_ID slotID, + CK_SLOT_INFO_PTR pInfo +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( + CK_SLOT_ID slotID, + CK_TOKEN_INFO_PTR pInfo +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)( + CK_FLAGS flags, + CK_SLOT_ID_PTR pSlot, + CK_VOID_PTR pReserved +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( + CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( + CK_SLOT_ID slotID, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_InitToken)( + CK_SLOT_ID slotID, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, + CK_UTF8CHAR_PTR pLabel +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)( + CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)( + CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pOldPin, + CK_ULONG ulOldLen, + CK_UTF8CHAR_PTR pNewPin, + CK_ULONG ulNewLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( + CK_SLOT_ID slotID, + CK_FLAGS flags, + CK_VOID_PTR pApplication, + CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( + CK_SESSION_HANDLE hSession +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( + CK_SLOT_ID slotID +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( + CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG_PTR pulOperationStateLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, + CK_OBJECT_HANDLE hAuthenticationKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Login)( + CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Logout)( + CK_SESSION_HANDLE hSession +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( + CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)( + CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( + CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)( + CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG_PTR pulSize +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( + CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)( + CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( + CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( + CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( + CK_SESSION_HANDLE hSession +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastPart, + CK_ULONG_PTR pulLastPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Digest)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)( + CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Sign)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_Verify)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hWrappingKey, + CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)( + CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey +) +{ + DBG(("In")); + + return CKR_OK; +} + +/* Random number generation functions */ + +CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)( + CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pRandomData, + CK_ULONG ulRandomLen +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)( + CK_SESSION_HANDLE hSession +) +{ + DBG(("In")); + + return CKR_OK; +} + +CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)( + CK_SESSION_HANDLE hSession +) +{ + DBG(("In")); + + return CKR_OK; +} +CK_FUNCTION_LIST function_list = { + { 2, 24 }, + C_Initialize, + C_Finalize, + C_GetInfo, + C_GetFunctionList, + C_GetSlotList, + C_GetSlotInfo, + C_GetTokenInfo, + C_GetMechanismList, + C_GetMechanismInfo, + C_InitToken, + C_InitPIN, + C_SetPIN, + C_OpenSession, + C_CloseSession, + C_CloseAllSessions, + C_GetSessionInfo, + C_GetOperationState, + C_SetOperationState, + C_Login, + C_Logout, + C_CreateObject, + C_CopyObject, + C_DestroyObject, + C_GetObjectSize, + C_GetAttributeValue, + C_SetAttributeValue, + C_FindObjectsInit, + C_FindObjects, + C_FindObjectsFinal, + C_EncryptInit, + C_Encrypt, + C_EncryptUpdate, + C_EncryptFinal, + C_DecryptInit, + C_Decrypt, + C_DecryptUpdate, + C_DecryptFinal, + C_DigestInit, + C_Digest, + C_DigestUpdate, + C_DigestKey, + C_DigestFinal, + C_SignInit, + C_Sign, + C_SignUpdate, + C_SignFinal, + C_SignRecoverInit, + C_SignRecover, + C_VerifyInit, + C_Verify, + C_VerifyUpdate, + C_VerifyFinal, + C_VerifyRecoverInit, + C_VerifyRecover, + C_DigestEncryptUpdate, + C_DecryptDigestUpdate, + C_SignEncryptUpdate, + C_DecryptVerifyUpdate, + C_GenerateKey, + C_GenerateKeyPair, + C_WrapKey, + C_UnwrapKey, + C_DeriveKey, + C_SeedRandom, + C_GenerateRandom, + C_GetFunctionStatus, + C_CancelFunction, + C_WaitForSlotEvent, +}; diff --git a/ykcs11/ykcs11.map b/ykcs11/ykcs11.map new file mode 100644 index 0000000..b6b62ac --- /dev/null +++ b/ykcs11/ykcs11.map @@ -0,0 +1,34 @@ +# Copyright (c) 2014 Yubico AB +# All rights reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Additional permission under GNU GPL version 3 section 7 +# +# If you modify this program, or any covered work, by linking or +# combining it with the OpenSSL project's OpenSSL library (or a +# modified version of that library), containing parts covered by the +# terms of the OpenSSL or SSLeay licenses, We grant you additional +# permission to convey the resulting work. Corresponding Source for a +# non-source form of such a combination shall include the source code +# for the parts of OpenSSL used as well as that of the covered work. + +YKCS11_0.1.0 +{ +global: + C_Initialize; + C_GetFunctionList; +local: + *; +}; \ No newline at end of file diff --git a/ykcs11/ykcs11.pc b/ykcs11/ykcs11.pc new file mode 100644 index 0000000..7b27b6d --- /dev/null +++ b/ykcs11/ykcs11.pc @@ -0,0 +1,12 @@ +prefix=/usr/local +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: yubico-piv-tool +Description: Yubico PIV PKCS#11 Module +URL: https://www.yubico.com/ +Version: 1.0.1 +Libs: -L${libdir} -lykcs11 +Cflags: -I${includedir}/ykpiv + diff --git a/ykcs11/ykcs11.pc.in b/ykcs11/ykcs11.pc.in new file mode 100644 index 0000000..53703c0 --- /dev/null +++ b/ykcs11/ykcs11.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE@ +Description: Yubico PIV PKCS#11 Module +URL: https://www.yubico.com/ +Version: @VERSION@ +Libs: -L${libdir} -lykcs11 +Cflags: -I${includedir}/ykpiv + From 80e6fe525ab494e6773795f1bd50b9a3f0dc09d9 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 30 Jun 2015 07:33:39 +0200 Subject: [PATCH 014/134] change IS_XXKEY macros to be YKPIV_IS_XX --- lib/ykpiv.c | 6 +++--- lib/ykpiv.h | 4 ++-- tool/yubico-piv-tool.c | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 7dec9e5..5897c2c 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -562,7 +562,7 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, dataptr += set_length(dataptr, in_len + bytes + 3); *dataptr++ = 0x82; *dataptr++ = 0x00; - *dataptr++ = IS_ECKEY(algorithm) && decipher ? 0x85 : 0x81; + *dataptr++ = YKPIV_IS_EC(algorithm) && decipher ? 0x85 : 0x81; dataptr += set_length(dataptr, in_len); memcpy(dataptr, sign_in, (size_t)in_len); dataptr += in_len; @@ -615,13 +615,13 @@ ykpiv_rc ykpiv_sign_data(ykpiv_state *state, unsigned char sign_in[256]; size_t key_len = 0; - if(IS_RSAKEY(algorithm)) { + if(YKPIV_IS_RSA(algorithm)) { key_len = 128; if(algorithm == YKPIV_ALGO_RSA2048) { key_len = 256; } } - if(IS_RSAKEY(algorithm) && key_len != in_len) { + if(YKPIV_IS_RSA(algorithm) && key_len != in_len) { if(in_len + RSA_PKCS1_PADDING_SIZE > key_len) { return YKPIV_SIZE_ERROR; } diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 4585d4c..0570b9b 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -158,8 +158,8 @@ extern "C" #define YKPIV_TOUCHPOLICY_NEVER 1 #define YKPIV_TOUCHPOLICY_ALWAYS 2 -#define IS_ECKEY(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384)) -#define IS_RSAKEY(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048)) +#define YKPIV_IS_EC(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384)) +#define YKPIV_IS_RSA(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048)) #ifdef __cplusplus } diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 601dcf6..233dd51 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -353,7 +353,7 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, unsigned char *in_ptr = in_data; unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key}; int sw; - if(IS_RSAKEY(algorithm)) { + if(YKPIV_IS_RSA(algorithm)) { RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key); unsigned char e[4]; unsigned char *e_ptr = e; @@ -397,7 +397,7 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, fprintf(stderr, "Failed setting iqmp component.\n"); goto import_out; } - } else if(IS_ECKEY(algorithm)) { + } else if(YKPIV_IS_EC(algorithm)) { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(private_key); const BIGNUM *s = EC_KEY_get0_private_key(ec); int element_len = 32; @@ -682,7 +682,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for fprintf(stderr, "Unsupported algorithm %x or hash %x\n", algorithm, hash); goto request_out; } - if(IS_RSAKEY(algorithm)) { + if(YKPIV_IS_RSA(algorithm)) { signinput = digest; len = oid_len + digest_len; } else { @@ -827,7 +827,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo if(nid == 0) { goto selfsign_out; } - if(IS_RSAKEY(algorithm)) { + if(YKPIV_IS_RSA(algorithm)) { signinput = digest; len = oid_len + md_len; } else { @@ -1090,7 +1090,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, EVP_MD_CTX_destroy(mdctx); } - if(IS_RSAKEY(algo)) { + if(YKPIV_IS_RSA(algo)) { prepare_rsa_signature(hashed, hash_len, hashed, &hash_len, EVP_MD_type(md)); } @@ -1342,7 +1342,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, goto test_out; } sscanf(cmdline_parser_slot_values[slot], "%2x", &key); - if(IS_RSAKEY(algorithm)) { + if(YKPIV_IS_RSA(algorithm)) { prepare_rsa_signature(data, data_len, encoded, &enc_len, EVP_MD_type(md)); ptr = encoded; } else { @@ -1448,7 +1448,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot, goto decipher_out; } sscanf(cmdline_parser_slot_values[slot], "%2x", &key); - if(IS_RSAKEY(algorithm)) { + if(YKPIV_IS_RSA(algorithm)) { unsigned char secret[32]; unsigned char secret2[32]; unsigned char data[256]; @@ -1489,7 +1489,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot, } else { fprintf(stderr, "Failed unwrapping PKCS1 envelope.\n"); } - } else if(IS_ECKEY(algorithm)) { + } else if(YKPIV_IS_EC(algorithm)) { unsigned char secret[48]; unsigned char secret2[48]; unsigned char public_key[97]; From a775ac6e697f8294428cfd07d0119854742ea298 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 30 Jun 2015 07:46:21 +0200 Subject: [PATCH 015/134] move around texts for help --- tool/cmdline.ggo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 848db95..a530326 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -57,6 +57,6 @@ text " /CN=host.example.com/OU=test/O=example.com/\n" option "pin" P "Pin/puk code for verification" string optional option "new-pin" N "New pin/puk code for changing" string optional dependon="pin" -option "sign" - "Sign data" flag off hidden option "pin-policy" - "Set pin policy for action generate or import-key" values="never","once","always" enum optional -option "touch-policy" - "Set touch policy for action generatem, import-key or set-mgm-key" values="never","always" enum optional +option "touch-policy" - "Set touch policy for action generate, import-key or set-mgm-key" values="never","always" enum optional +option "sign" - "Sign data" flag off hidden From 2b2fe1f9fa0406523bb2196b3e62c8bf57136e14 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 30 Jun 2015 11:14:36 +0200 Subject: [PATCH 016/134] Added basic version of slot info functions. --- lib/internal.h | 8 +- lib/ykpiv.c | 95 +++++++++++++------- lib/ykpiv.h | 87 ++++++++++--------- lib/ykpiv.map | 2 + ykcs11/Makefile.am | 1 + ykcs11/ykcs11.c | 211 ++++++++++++++++++++++++++++++--------------- 6 files changed, 263 insertions(+), 141 deletions(-) diff --git a/lib/internal.h b/lib/internal.h index b506233..9152379 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -41,10 +41,16 @@ #endif #endif +#define READER_LEN 32 +#define MAX_READERS 16 + struct ykpiv_state { SCARDCONTEXT context; SCARDHANDLE card; - int verbose; + unsigned long n_readers; + char readers[MAX_READERS][READER_LEN]; + unsigned long tot_readers_len; + int verbose; }; union u_APDU { diff --git a/lib/ykpiv.c b/lib/ykpiv.c index a02edd8..2481d2a 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -20,7 +20,7 @@ * If you modify this program, or any covered work, by linking or * combining it with the OpenSSL project's OpenSSL library (or a * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, We grant you additional + * terms of the OpenSSL or SSLeay licenses, We grant you additional * permission to convey the resulting work. Corresponding Source for a * non-source form of such a combination shall include the source code * for the parts of OpenSSL used as well as that of the covered work. @@ -131,6 +131,7 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { unsigned long active_protocol; char reader_buf[1024]; long rc; + int i; char *reader_ptr; rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); @@ -164,19 +165,31 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { return YKPIV_PCSC_ERROR; } + // TODO: improve here + state->n_readers = 0; + state->tot_readers_len = num_readers; + reader_ptr = reader_buf; + for (i = 0; i < num_readers; i++) + if (reader_buf[i] == '\0' && i != num_readers - 1) { + strcpy(state->readers[state->n_readers], reader_ptr); // TODO: strdup? + state->n_readers = state->n_readers + 1; + reader_ptr += i + 1; + } + // ********* + reader_ptr = reader_buf; if(wanted) { while(*reader_ptr != '\0') { if(strstr(reader_ptr, wanted)) { - if(state->verbose) { - fprintf(stderr, "using reader '%s' matching '%s'.\n", reader_ptr, wanted); - } - break; + if(state->verbose) { + fprintf(stderr, "using reader '%s' matching '%s'.\n", reader_ptr, wanted); + } + break; } else { - if(state->verbose) { - fprintf(stderr, "skipping reader '%s' since it doesn't match.\n", reader_ptr); - } - reader_ptr += strlen(reader_ptr) + 1; + if(state->verbose) { + fprintf(stderr, "skipping reader '%s' since it doesn't match.\n", reader_ptr); + } + reader_ptr += strlen(reader_ptr) + 1; } } } @@ -266,7 +279,7 @@ ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, } if(*out_len + recv_len - 2 > max_out) { if(state->verbose) { - fprintf(stderr, "Output buffer to small, wanted to write %lu, max was %lu.\n", *out_len + recv_len - 2, max_out); + fprintf(stderr, "Output buffer to small, wanted to write %lu, max was %lu.\n", *out_len + recv_len - 2, max_out); } return YKPIV_SIZE_ERROR; } @@ -400,7 +413,7 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) { *dataptr++ = 8; if(RAND_pseudo_bytes(dataptr, 8) == -1) { if(state->verbose) { - fprintf(stderr, "Failed getting randomness for authentication.\n"); + fprintf(stderr, "Failed getting randomness for authentication.\n"); } return YKPIV_RANDOMNESS_ERROR; } @@ -440,11 +453,11 @@ ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key) { DES_set_odd_parity(&key_tmp); if(DES_is_weak_key(&key_tmp) != 0) { if(state->verbose) { - fprintf(stderr, "Won't set new key '"); - dump_hex(new_key + i * 8, 8); - fprintf(stderr, "' since it's weak (with parity the key is: "); - dump_hex(key_tmp, 8); - fprintf(stderr, ").\n"); + fprintf(stderr, "Won't set new key '"); + dump_hex(new_key + i * 8, 8); + fprintf(stderr, "' since it's weak (with parity the key is: "); + dump_hex(key_tmp, 8); + fprintf(stderr, ").\n"); } return YKPIV_GENERIC_ERROR; } @@ -519,26 +532,26 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, pad_len = 128; case YKPIV_ALGO_RSA2048: if(pad_len == 0) { - pad_len = 256; + pad_len = 256; } if(!decipher) { - if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) { - return YKPIV_SIZE_ERROR; - } - RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len); - in_len = pad_len; + if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) { + return YKPIV_SIZE_ERROR; + } + RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len); + in_len = pad_len; } else { - if(in_len != pad_len) { - return YKPIV_SIZE_ERROR; - } - memcpy(sign_in, raw_in, in_len); + if(in_len != pad_len) { + return YKPIV_SIZE_ERROR; + } + memcpy(sign_in, raw_in, in_len); } break; case YKPIV_ALGO_ECCP256: if(!decipher && in_len > 32) { - return YKPIV_SIZE_ERROR; + return YKPIV_SIZE_ERROR; } else if(decipher && in_len != 65) { - return YKPIV_SIZE_ERROR; + return YKPIV_SIZE_ERROR; } memcpy(sign_in, raw_in, in_len); break; @@ -734,7 +747,7 @@ ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id, dataptr += len; if((res = ykpiv_transfer_data(state, templ, data, dataptr - data, NULL, &outlen, - &sw)) != YKPIV_OK) { + &sw)) != YKPIV_OK) { return res; } @@ -744,3 +757,27 @@ ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id, return YKPIV_GENERIC_ERROR; } } + +ykpiv_rc ykpiv_get_reader_slot_number(ykpiv_state *state, unsigned long *slots, unsigned long *total) { + if (state == NULL) + return YKPIV_MEMORY_ERROR; + + *slots = state->n_readers; + *total = state->tot_readers_len; + + return YKPIV_OK; + +} + +ykpiv_rc ykpiv_get_reader_slot(ykpiv_state *state, unsigned long slot, char *reader) { + if (state == NULL) + return YKPIV_MEMORY_ERROR; + + if (slot >= state->n_readers) + return YKPIV_SIZE_ERROR; + + strcpy(reader, state->readers[slot]); + + return YKPIV_OK; + +} diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 26a4a93..319da54 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -20,7 +20,7 @@ * If you modify this program, or any covered work, by linking or * combining it with the OpenSSL project's OpenSSL library (or a * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, We grant you additional + * terms of the OpenSSL or SSLeay licenses, We grant you additional * permission to convey the resulting work. Corresponding Source for a * non-source form of such a combination shall include the source code * for the parts of OpenSSL used as well as that of the covered work. @@ -40,50 +40,53 @@ extern "C" { #endif - typedef struct ykpiv_state ykpiv_state; + typedef struct ykpiv_state ykpiv_state; - typedef enum { - YKPIV_OK = 0, - YKPIV_MEMORY_ERROR = -1, - YKPIV_PCSC_ERROR = -2, - YKPIV_SIZE_ERROR = -3, - YKPIV_APPLET_ERROR = -4, - YKPIV_AUTHENTICATION_ERROR = -5, - YKPIV_RANDOMNESS_ERROR = -6, - YKPIV_GENERIC_ERROR = -7, - YKPIV_KEY_ERROR = -8, - YKPIV_PARSE_ERROR = -9, - YKPIV_WRONG_PIN = -10, - YKPIV_INVALID_OBJECT = -11, - YKPIV_ALGORITHM_ERROR = -12, - } ykpiv_rc; + typedef enum { + YKPIV_OK = 0, + YKPIV_MEMORY_ERROR = -1, + YKPIV_PCSC_ERROR = -2, + YKPIV_SIZE_ERROR = -3, + YKPIV_APPLET_ERROR = -4, + YKPIV_AUTHENTICATION_ERROR = -5, + YKPIV_RANDOMNESS_ERROR = -6, + YKPIV_GENERIC_ERROR = -7, + YKPIV_KEY_ERROR = -8, + YKPIV_PARSE_ERROR = -9, + YKPIV_WRONG_PIN = -10, + YKPIV_INVALID_OBJECT = -11, + YKPIV_ALGORITHM_ERROR = -12, + } ykpiv_rc; - const char *ykpiv_strerror(ykpiv_rc err); - const char *ykpiv_strerror_name(ykpiv_rc err); + const char *ykpiv_strerror(ykpiv_rc err); + const char *ykpiv_strerror_name(ykpiv_rc err); - ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); - ykpiv_rc ykpiv_done(ykpiv_state *state); - ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); - ykpiv_rc ykpiv_disconnect(ykpiv_state *state); - ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, - const unsigned char *in_data, long in_len, - unsigned char *out_data, unsigned long *out_len, int *sw); - ykpiv_rc ykpiv_authenticate(ykpiv_state *state, const unsigned char *key); - ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key); - ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, - unsigned char *hex_out, size_t *out_len); - ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in, - size_t in_len,unsigned char *sign_out, size_t *out_len, - unsigned char algorithm, unsigned char key); - ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *enc_in, - size_t in_len, unsigned char *enc_out, size_t *out_len, - unsigned char algorithm, unsigned char key); - ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len); - ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries); - ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id, - unsigned char *data, unsigned long *len); + ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); + ykpiv_rc ykpiv_done(ykpiv_state *state); + ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); + ykpiv_rc ykpiv_disconnect(ykpiv_state *state); + ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, + const unsigned char *in_data, long in_len, + unsigned char *out_data, unsigned long *out_len, int *sw); + ykpiv_rc ykpiv_authenticate(ykpiv_state *state, const unsigned char *key); + ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key); + ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, + unsigned char *hex_out, size_t *out_len); + ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in, + size_t in_len,unsigned char *sign_out, size_t *out_len, + unsigned char algorithm, unsigned char key); + ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *enc_in, + size_t in_len, unsigned char *enc_out, size_t *out_len, + unsigned char algorithm, unsigned char key); + ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len); + ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries); + ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id, + unsigned char *data, unsigned long *len); ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id, - unsigned char *indata, size_t len); + unsigned char *indata, size_t len); + + ykpiv_rc ykpiv_get_reader_slot_number(ykpiv_state *state, unsigned long *slots, unsigned long *total); + ykpiv_rc ykpiv_get_reader_slot(ykpiv_state *state, unsigned long slot, char *reader); #define YKPIV_ALGO_3DES 0x03 #define YKPIV_ALGO_RSA1024 0x06 @@ -118,7 +121,7 @@ extern "C" #define YKPIV_INS_GET_DATA 0xcb #define YKPIV_INS_PUT_DATA 0xdb - /* Yubico vendor specific instructions */ + /* Yubico vendor specific instructions */ #define YKPIV_INS_SET_MGMKEY 0xff #define YKPIV_INS_IMPORT_KEY 0xfe #define YKPIV_INS_GET_VERSION 0xfd diff --git a/lib/ykpiv.map b/lib/ykpiv.map index 19969cc..d7fb74c 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -52,4 +52,6 @@ YKPIV_0.2.0 { global: ykpiv_decipher_data; + ykpiv_get_reader_slot_number; + ykpiv_get_reader_slot; } YKPIV_0.1.0; diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index f0b1879..a30eed8 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -29,6 +29,7 @@ SUBDIRS = . AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS) $(LIBNSPR_CFLAGS) +AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 71844c8..9011620 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1,5 +1,9 @@ #include "pkcs11.h" #include +#include +#include + +// TODO: do a bit of backend magic or should be handled by libykpiv? #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ @@ -7,9 +11,24 @@ printf ("\n"); \ } while (0) -#define DBG(x) if (debug) { D(x); } +#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 -static const int debug = 1; +#if YKCS11_DBG +#define DBG(x) D(x); +#else +#define DBG(x) +#endif + +#if YKCS11_DINOUT +#define DIN D(("In")); +#define DOUT D(("Out")); +#else +#define DIN +#define DOUT +#endif + +static ykpiv_state *piv_state = NULL; extern CK_FUNCTION_LIST function_list; @@ -19,8 +38,22 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( CK_VOID_PTR pInitArgs ) { - DBG(("In")); + DIN; + // TODO: check for locks and mutexes + if (piv_state != NULL) + return CKR_CRYPTOKI_ALREADY_INITIALIZED; + if (ykpiv_init(&piv_state, YKCS11_DBG) != YKPIV_OK) { + DBG(("Unable to initialize YubiKey")); + return CKR_FUNCTION_FAILED; // TODO: better error? + } + + if(ykpiv_connect(piv_state, NULL) != YKPIV_OK) { + DBG(("Unable to connect to reader")); + return CKR_FUNCTION_FAILED; + } + + DOUT; return CKR_OK; } @@ -28,8 +61,21 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( CK_VOID_PTR pReserved ) { - DBG(("In")); + DIN; + if (pReserved != NULL_PTR) { + DBG(("Finalized called with pReserved != NULL")); + return CKR_ARGUMENTS_BAD; + } + if (piv_state == NULL) { + DBG(("Ykpiv is not finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + ykpiv_done(piv_state); // TODO: this calls disconnect... + piv_state == NULL; + + DOUT; return CKR_OK; } @@ -46,7 +92,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)( CK_FUNCTION_LIST_PTR_PTR ppFunctionList ) { - DBG(("In")); + DIN; if(ppFunctionList == NULL_PTR) { return CKR_ARGUMENTS_BAD; } @@ -63,8 +109,23 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( CK_ULONG_PTR pulCount ) { - DBG(("In")); + DIN; + unsigned long tot_readers_len; + ykpiv_get_reader_slot_number(piv_state, pulCount, &tot_readers_len); + //DBG(("%u val %x ptr", *pulCount, pSlotList)); + if (pSlotList == NULL_PTR) { + // Just return the number of slots + return CKR_OK; + } + pSlotList[0] = 0; + return CKR_OK; + /*if ((*pulCount / sizeof(CK_SLOT_ID)) < tot_readers_len) { + DBG(("Buffer too small: needed %u, provided %u", tot_readers_len, *pulCount / sizeof(CK_SLOT_ID))) + return CKR_BUFFER_TOO_SMALL; + }*/ + DBG(("%d token", tokenPresent)); + DBG(("%u count", *pulCount)); return CKR_OK; } @@ -73,7 +134,19 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( CK_SLOT_INFO_PTR pInfo ) { - DBG(("In")); + DIN; + /* + * According to pcsc-lite, the format of a reader name is: + * name [interface] (serial) index slot + * http://ludovicrousseau.blogspot.se/2010/05/what-is-in-pcsc-reader-name.html + */ + ykpiv_get_reader_slot(piv_state, 0, pInfo->slotDescription); + strcpy(pInfo->manufacturerID, "ADD SLOT MANUFACTURER NAME HERE"); + pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT; + + DBG(("slotID %u, pInfo %s", slotID, pInfo->slotDescription)); + + return CKR_OK; } @@ -83,7 +156,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( CK_TOKEN_INFO_PTR pInfo ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -94,7 +167,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)( CK_VOID_PTR pReserved ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -105,7 +178,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( CK_ULONG_PTR pulCount ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -116,7 +189,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( CK_MECHANISM_INFO_PTR pInfo ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -128,7 +201,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_InitToken)( CK_UTF8CHAR_PTR pLabel ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -139,7 +212,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)( CK_ULONG ulPinLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -152,7 +225,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)( CK_ULONG ulNewLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -165,7 +238,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( CK_SESSION_HANDLE_PTR phSession ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -174,7 +247,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( CK_SESSION_HANDLE hSession ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -183,7 +256,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( CK_SLOT_ID slotID ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -193,7 +266,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( CK_SESSION_INFO_PTR pInfo ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -204,7 +277,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)( CK_ULONG_PTR pulOperationStateLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -217,7 +290,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)( CK_OBJECT_HANDLE hAuthenticationKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -229,7 +302,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( CK_ULONG ulPinLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -238,7 +311,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( CK_SESSION_HANDLE hSession ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -250,7 +323,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_OBJECT_HANDLE_PTR phObject ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -263,7 +336,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)( CK_OBJECT_HANDLE_PTR phNewObject ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -273,7 +346,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( CK_OBJECT_HANDLE hObject ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -284,7 +357,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)( CK_ULONG_PTR pulSize ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -296,7 +369,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( CK_ULONG ulCount ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -308,7 +381,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)( CK_ULONG ulCount ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -319,7 +392,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( CK_ULONG ulCount ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -331,7 +404,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( CK_ULONG_PTR pulObjectCount ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -340,7 +413,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( CK_SESSION_HANDLE hSession ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -351,7 +424,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)( CK_OBJECT_HANDLE hKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -364,7 +437,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)( CK_ULONG_PTR pulEncryptedDataLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -377,7 +450,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)( CK_ULONG_PTR pulEncryptedPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -388,7 +461,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)( CK_ULONG_PTR pulLastEncryptedPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -399,7 +472,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)( CK_OBJECT_HANDLE hKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -412,7 +485,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)( CK_ULONG_PTR pulDataLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -425,7 +498,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)( CK_ULONG_PTR pulPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -436,7 +509,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)( CK_ULONG_PTR pulLastPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -446,7 +519,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)( CK_MECHANISM_PTR pMechanism ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -459,7 +532,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Digest)( CK_ULONG_PTR pulDigestLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -470,7 +543,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)( CK_ULONG ulPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -480,7 +553,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)( CK_OBJECT_HANDLE hKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -491,7 +564,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)( CK_ULONG_PTR pulDigestLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -502,7 +575,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( CK_OBJECT_HANDLE hKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -515,7 +588,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( CK_ULONG_PTR pulSignatureLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -526,7 +599,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)( CK_ULONG ulPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -537,7 +610,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)( CK_ULONG_PTR pulSignatureLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -548,7 +621,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)( CK_OBJECT_HANDLE hKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -561,7 +634,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)( CK_ULONG_PTR pulSignatureLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -572,7 +645,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)( CK_OBJECT_HANDLE hKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -585,7 +658,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Verify)( CK_ULONG ulSignatureLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -596,7 +669,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)( CK_ULONG ulPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -607,7 +680,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)( CK_ULONG ulSignatureLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -618,7 +691,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)( CK_OBJECT_HANDLE hKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -631,7 +704,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)( CK_ULONG_PTR pulDataLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -644,7 +717,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)( CK_ULONG_PTR pulEncryptedPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -657,7 +730,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)( CK_ULONG_PTR pulPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -670,7 +743,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)( CK_ULONG_PTR pulEncryptedPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -683,7 +756,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)( CK_ULONG_PTR pulPartLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -696,7 +769,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)( CK_OBJECT_HANDLE_PTR phKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -712,7 +785,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( CK_OBJECT_HANDLE_PTR phPrivateKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -726,7 +799,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)( CK_ULONG_PTR pulWrappedKeyLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -742,7 +815,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)( CK_OBJECT_HANDLE_PTR phKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -756,7 +829,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)( CK_OBJECT_HANDLE_PTR phKey ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -769,7 +842,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)( CK_ULONG ulSeedLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -780,7 +853,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)( CK_ULONG ulRandomLen ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -789,7 +862,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)( CK_SESSION_HANDLE hSession ) { - DBG(("In")); + DIN; return CKR_OK; } @@ -798,7 +871,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)( CK_SESSION_HANDLE hSession ) { - DBG(("In")); + DIN; return CKR_OK; } From f9ef0d6bbd7e0618b0a3fb52716100b9fd9a2601 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 3 Jul 2015 09:41:42 +0200 Subject: [PATCH 017/134] NEWS for yk4beta --- NEWS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 17a4cb7..7d3c344 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ yubico-piv-tool NEWS -- History of user-visible changes. -*- outline -*- -* Version 1.0.1 (unreleased) +* Version 1.1.0 (unreleased) + +** Support for YubiKey 4 stuff +ECCP384, touch, retired keys etc * Version 1.0.0 (released 2015-06-23) From f95c6f2f2db009c345e8dfb0da7d7e003de2ada7 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 3 Jul 2015 17:23:16 +0200 Subject: [PATCH 018/134] Added basic multivendor support for token information. --- lib/ykpiv.c | 2 +- ykcs11/Makefile.am | 2 ++ ykcs11/vendors.c | 28 +++++++++++++++++ ykcs11/vendors.h | 20 ++++++++++++ ykcs11/ykcs11.c | 78 +++++++++++++++++++++++++++++++++++++++------- ykcs11/yubico.c | 29 +++++++++++++++++ ykcs11/yubico.h | 8 +++++ 7 files changed, 154 insertions(+), 13 deletions(-) create mode 100644 ykcs11/vendors.c create mode 100644 ykcs11/vendors.h create mode 100644 ykcs11/yubico.c create mode 100644 ykcs11/yubico.h diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 2481d2a..b3a5114 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -177,7 +177,7 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { } // ********* - reader_ptr = reader_buf; + reader_ptr = reader_buf; // TODO: reader_buf is never free'd if(wanted) { while(*reader_ptr != '\0') { if(strstr(reader_ptr, wanted)) { diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index a30eed8..050c4dc 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -34,6 +34,8 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map +libykcs11_la_SOURCES += vendors.c vendor.h yubico.c yubico. h + #internal.h #libykcs11_la_SOURCES += error.c #libykcs11_la_LDADD = ../lib/libykpiv.la diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c new file mode 100644 index 0000000..fcbb803 --- /dev/null +++ b/ykcs11/vendors.c @@ -0,0 +1,28 @@ +#include "vendors.h" +#include "yubico.h" + +vendor_id_t get_vendor_id(char *vendor_name) { + vendor_id_t vid; + + if (strncmp(vendor_name, "Yubico", 6) == 0) + return YUBICO; + + return UNKNOWN; +} + +vendor_t get_vendor(vendor_id_t vid) { + vendor_t v; + + switch (vid) { + case YUBICO: + v.get_version = YUBICO_get_version; + break; + + case UNKNOWN: + v.get_version = NULL; + + } + + return v; + +} diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h new file mode 100644 index 0000000..c456d0e --- /dev/null +++ b/ykcs11/vendors.h @@ -0,0 +1,20 @@ +#ifndef VENDORS_H +#define VENDORS_H + +#include "pkcs11.h" + +typedef enum { + UNKNOWN = 0x00, + YUBICO = 0x01 +} vendor_id_t; + +typedef CK_VERSION (*get_version_f)(char *, int); + +typedef struct { + get_version_f get_version; +} vendor_t; + +vendor_id_t get_vendor_id(char *vendor_name); +vendor_t get_vendor(vendor_id_t vid); + +#endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 9011620..242e767 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -2,6 +2,7 @@ #include #include #include +#include "vendors.h" // TODO: do a bit of backend magic or should be handled by libykpiv? @@ -111,21 +112,29 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( { DIN; unsigned long tot_readers_len; - ykpiv_get_reader_slot_number(piv_state, pulCount, &tot_readers_len); - //DBG(("%u val %x ptr", *pulCount, pSlotList)); + unsigned long n_readers; + int i; + ykpiv_get_reader_slot_number(piv_state, &n_readers, &tot_readers_len); // TODO: maybe refactor this with a reader struct? if (pSlotList == NULL_PTR) { // Just return the number of slots + *pulCount = n_readers; + DOUT; return CKR_OK; } - pSlotList[0] = 0; - return CKR_OK; - /*if ((*pulCount / sizeof(CK_SLOT_ID)) < tot_readers_len) { - DBG(("Buffer too small: needed %u, provided %u", tot_readers_len, *pulCount / sizeof(CK_SLOT_ID))) - return CKR_BUFFER_TOO_SMALL; - }*/ + if (*pulCount < n_readers) { + DBG(("Buffer too small: needed %u, provided %u", n_readers, *pulCount)); + return CKR_BUFFER_TOO_SMALL; + } + + for (i = 0; i < n_readers; i++) { + pSlotList[i] = i; + } + DBG(("%d token", tokenPresent)); DBG(("%u count", *pulCount)); + + DOUT; return CKR_OK; } @@ -140,14 +149,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( * name [interface] (serial) index slot * http://ludovicrousseau.blogspot.se/2010/05/what-is-in-pcsc-reader-name.html */ - ykpiv_get_reader_slot(piv_state, 0, pInfo->slotDescription); + ykpiv_get_reader_slot(piv_state, slotID, pInfo->slotDescription); // TODO: should be ' ' padded strcpy(pInfo->manufacturerID, "ADD SLOT MANUFACTURER NAME HERE"); - pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT; + pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT; // TODO: What for other brands? Query for token status? DBG(("slotID %u, pInfo %s", slotID, pInfo->slotDescription)); - - return CKR_OK; } @@ -157,6 +164,53 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( ) { DIN; + CK_VERSION ver = {0, 0}; + vendor_t yubico; + char buf[64]; + + ykpiv_get_version(piv_state, buf, 64); + yubico = get_vendor(get_vendor_id("Yubico")); + ver = yubico.get_version(buf, strlen(buf)); + + memset(pInfo->label, ' ', sizeof(pInfo->label)); + strncpy(pInfo->label, "LABEL", 5); + + memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); + strncpy(pInfo->manufacturerID, "MANUFACTURER_ID", 15); + + memset(pInfo->model, ' ', sizeof(pInfo->model)); + strncpy(pInfo->model, "MODEL", 5); + + memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber)); + strncpy(pInfo->serialNumber, "12345", 5); + + pInfo->flags = 0x00000400; // bit flags indicating capabilities and status of the device as defined below + + pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? + + pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token + + pInfo->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION; // maximum number of read/write sessions that can be opened with the token at one time by a single TODO: should this be 1? + + pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token + + pInfo->ulMaxPinLen = 127; // maximum length in bytes of the PIN + + pInfo->ulMinPinLen = 3; // minimum length in bytes of the PIN + + pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; + + pInfo->hardwareVersion = ver; // version number of hardware + + pInfo->firmwareVersion = ver; // version number of firmware + + memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime)); return CKR_OK; } diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c new file mode 100644 index 0000000..80f40be --- /dev/null +++ b/ykcs11/yubico.c @@ -0,0 +1,29 @@ +#include "yubico.h" +#include "pkcs11.h" + +CK_VERSION YUBICO_get_version(char *version, int len) { + + CK_VERSION v = {0, 0}; + int i = 0; + + while (i < len && version[i] != '.') { + v.major *= 10; + v.major += version[i++] - '0'; + } + + i++; + + while (i < len && version[i] != '.') { + v.minor *= 10; + v.minor += version[i++] - '0'; + } + + i++; + + while (i < len && version[i] != '.') { + v.minor *= 10; + v.minor += version[i++] - '0'; + } + + return v; +} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h new file mode 100644 index 0000000..e2487f6 --- /dev/null +++ b/ykcs11/yubico.h @@ -0,0 +1,8 @@ +#ifndef YUBICO_H +#define YUBICO_H + +#include "pkcs11.h" + +CK_VERSION YUBICO_get_version(char *version, int len); + +#endif From 9f6dfed7cde65e4ba1b53987037db09a7f11d297 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 6 Jul 2015 16:42:36 +0200 Subject: [PATCH 019/134] More GetTokenInfo. --- ykcs11/pkcs11t.h | 2 ++ ykcs11/vendors.c | 15 ++++++++++++--- ykcs11/vendors.h | 12 ++++++++++-- ykcs11/ykcs11.c | 48 ++++++++++++++++++++++++++++++++++-------------- ykcs11/yubico.c | 26 +++++++++++++++++++++++++- ykcs11/yubico.h | 6 +++++- 6 files changed, 88 insertions(+), 21 deletions(-) diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index 497dfe0..b9bf233 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -228,6 +228,8 @@ typedef struct CK_TOKEN_INFO { * and sign) */ #define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 +#define CKF_TOKEN_INITIALIZED 0x00000400 + typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index fcbb803..179cc99 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -1,10 +1,11 @@ #include "vendors.h" #include "yubico.h" +#include vendor_id_t get_vendor_id(char *vendor_name) { vendor_id_t vid; - if (strncmp(vendor_name, "Yubico", 6) == 0) + if (strstr(vendor_name, "Yubico") != NULL) return YUBICO; return UNKNOWN; @@ -15,11 +16,19 @@ vendor_t get_vendor(vendor_id_t vid) { switch (vid) { case YUBICO: - v.get_version = YUBICO_get_version; + v.get_version = YUBICO_get_version; + v.get_label = YUBICO_get_label; + v.get_manufacturer = YUBICO_get_manufacturer; + v.get_model = YUBICO_get_model; + v.get_flags = YUBICO_get_flags; break; case UNKNOWN: - v.get_version = NULL; + v.get_version = NULL; // TODO: make up dummy functions? + v.get_label = NULL; + v.get_manufacturer = NULL; + v.get_model = NULL; + v.get_flags = NULL; } diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index c456d0e..5f1e867 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -8,10 +8,18 @@ typedef enum { YUBICO = 0x01 } vendor_id_t; -typedef CK_VERSION (*get_version_f)(char *, int); +typedef CK_VERSION (*get_version_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_UTF8CHAR_PTR (*get_label_f)(void); +typedef CK_UTF8CHAR_PTR (*get_manufacturer_f)(void); +typedef CK_UTF8CHAR_PTR (*get_model_f)(void); +typedef CK_FLAGS (*get_flags_f)(void); typedef struct { - get_version_f get_version; + get_version_f get_version; + get_label_f get_label; + get_manufacturer_f get_manufacturer; + get_model_f get_model; + get_flags_f get_flags; } vendor_t; vendor_id_t get_vendor_id(char *vendor_name); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 242e767..2457197 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -4,8 +4,6 @@ #include #include "vendors.h" -// TODO: do a bit of backend magic or should be handled by libykpiv? - #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ printf x; \ @@ -15,6 +13,9 @@ #define YKCS11_DBG 1 // General debug, must be either 1 or 0 #define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 +#define PIV_MIN_PIN_LEN 6 +#define PIV_MAX_PIN_LEN 8 + #if YKCS11_DBG #define DBG(x) D(x); #else @@ -164,27 +165,43 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( ) { DIN; - CK_VERSION ver = {0, 0}; - vendor_t yubico; - char buf[64]; + CK_VERSION ver = {0, 0}; + vendor_id_t vid; + vendor_t vendor; + CK_BYTE buf[64]; + CK_UTF8CHAR_PTR p; + CK_BYTE len; - ykpiv_get_version(piv_state, buf, 64); - yubico = get_vendor(get_vendor_id("Yubico")); - ver = yubico.get_version(buf, strlen(buf)); + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + ykpiv_get_reader_slot(piv_state, slotID, buf); + vid = get_vendor_id(buf); + + if (vid == UNKNOWN) + return CKR_TOKEN_NOT_RECOGNIZED; + + vendor = get_vendor(vid); memset(pInfo->label, ' ', sizeof(pInfo->label)); - strncpy(pInfo->label, "LABEL", 5); + p = vendor.get_label(); + len = strlen(p); + strncpy(pInfo->label, p, len); memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); - strncpy(pInfo->manufacturerID, "MANUFACTURER_ID", 15); + p = vendor.get_manufacturer(); + len = strlen(p); + strncpy(pInfo->manufacturerID, p, len); memset(pInfo->model, ' ', sizeof(pInfo->model)); - strncpy(pInfo->model, "MODEL", 5); + p = vendor.get_model(); + len = strlen(p); + strncpy(pInfo->model, p, len); memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber)); strncpy(pInfo->serialNumber, "12345", 5); - pInfo->flags = 0x00000400; // bit flags indicating capabilities and status of the device as defined below + pInfo->flags = vendor.get_flags(); // bit flags indicating capabilities and status of the device as defined below pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? @@ -194,9 +211,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token - pInfo->ulMaxPinLen = 127; // maximum length in bytes of the PIN + pInfo->ulMaxPinLen = PIV_MIN_PIN_LEN; // maximum length in bytes of the PIN - pInfo->ulMinPinLen = 3; // minimum length in bytes of the PIN + pInfo->ulMinPinLen = PIV_MAX_PIN_LEN; // minimum length in bytes of the PIN pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; @@ -206,6 +223,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; + ykpiv_get_version(piv_state, buf, sizeof(buf)); + ver = vendor.get_version(buf, strlen(buf)); + pInfo->hardwareVersion = ver; // version number of hardware pInfo->firmwareVersion = ver; // version number of firmware diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index 80f40be..5f14296 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -1,7 +1,7 @@ #include "yubico.h" #include "pkcs11.h" -CK_VERSION YUBICO_get_version(char *version, int len) { +CK_VERSION YUBICO_get_version(CK_UTF8CHAR_PTR version, CK_ULONG len) { CK_VERSION v = {0, 0}; int i = 0; @@ -27,3 +27,27 @@ CK_VERSION YUBICO_get_version(char *version, int len) { return v; } + +CK_UTF8CHAR_PTR YUBICO_get_label(void) { + + return "YubiKey"; + +} + +CK_UTF8CHAR_PTR YUBICO_get_manufacturer(void) { + + return "Yubico"; + +} + +CK_UTF8CHAR_PTR YUBICO_get_model(void) { + + return "PRO"; + +} + +CK_FLAGS YUBICO_get_flags(void) { + + return CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; + +} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index e2487f6..cf78790 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -3,6 +3,10 @@ #include "pkcs11.h" -CK_VERSION YUBICO_get_version(char *version, int len); +CK_VERSION YUBICO_get_version(CK_UTF8CHAR_PTR version, CK_ULONG len); +CK_UTF8CHAR_PTR YUBICO_get_label(void); +CK_UTF8CHAR_PTR YUBICO_get_manufacturer(void); +CK_UTF8CHAR_PTR YUBICO_get_model(void); +CK_FLAGS YUBICO_get_flags(void); #endif From 7777ac3dadd2c56e0a18d25c7bc7c3123cbdf028 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 6 Jul 2015 17:08:26 +0200 Subject: [PATCH 020/134] GetInfo. --- ykcs11/pkcs11f.h | 2 +- ykcs11/ykcs11.c | 31 ++++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/ykcs11/pkcs11f.h b/ykcs11/pkcs11f.h index 9f71d49..71ee267 100644 --- a/ykcs11/pkcs11f.h +++ b/ykcs11/pkcs11f.h @@ -71,7 +71,7 @@ CK_PKCS11_FUNCTION_INFO(C_Finalize) CK_PKCS11_FUNCTION_INFO(C_GetInfo) #ifdef CK_NEED_ARG_LIST ( - CK_VOID_PTR pInfo /* location that receives information */ + CK_INFO_PTR pInfo /* location that receives information */ ); #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 2457197..32b1908 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -13,6 +13,9 @@ #define YKCS11_DBG 1 // General debug, must be either 1 or 0 #define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 +#define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" +#define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" + #define PIV_MIN_PIN_LEN 6 #define PIV_MAX_PIN_LEN 8 @@ -82,11 +85,24 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( } CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)( - CK_VOID_PTR pInfo + CK_INFO_PTR pInfo ) { - DBG(("In")); + DIN; + CK_VERSION ver = {0.0}; + pInfo->cryptokiVersion = function_list.version; + memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); + strcpy(pInfo->manufacturerID, YKCS11_MANUFACTURER); + + pInfo->flags = 0; + + memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription)); + strcpy(pInfo->libraryDescription, YKCS11_LIBDESC); + + pInfo->libraryVersion = ver; + + DOUT; return CKR_OK; } @@ -131,7 +147,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( for (i = 0; i < n_readers; i++) { pSlotList[i] = i; } - + DBG(("%d token", tokenPresent)); DBG(("%u count", *pulCount)); @@ -180,9 +196,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( if (vid == UNKNOWN) return CKR_TOKEN_NOT_RECOGNIZED; - + vendor = get_vendor(vid); - + memset(pInfo->label, ' ', sizeof(pInfo->label)); p = vendor.get_label(); len = strlen(p); @@ -225,7 +241,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( ykpiv_get_version(piv_state, buf, sizeof(buf)); ver = vendor.get_version(buf, strlen(buf)); - + pInfo->hardwareVersion = ver; // version number of hardware pInfo->firmwareVersion = ver; // version number of firmware @@ -949,8 +965,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)( return CKR_OK; } + CK_FUNCTION_LIST function_list = { - { 2, 24 }, + { 2, 40 }, C_Initialize, C_Finalize, C_GetInfo, From 5295b2068f6632c01f32321d339897d562061128 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 7 Jul 2015 10:18:25 +0200 Subject: [PATCH 021/134] Add a bunch of TODOs. --- ykcs11/ykcs11.c | 183 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 60 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 32b1908..0744318 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -131,6 +131,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( unsigned long tot_readers_len; unsigned long n_readers; int i; + + // TODO: what about tokenPresent? + ykpiv_get_reader_slot_number(piv_state, &n_readers, &tot_readers_len); // TODO: maybe refactor this with a reader struct? if (pSlotList == NULL_PTR) { // Just return the number of slots @@ -258,7 +261,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -269,7 +273,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -280,7 +285,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -303,7 +309,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -316,7 +323,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -329,7 +337,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -338,7 +347,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -347,7 +357,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -357,7 +368,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -368,7 +380,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -381,7 +394,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -393,7 +407,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -402,7 +417,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -414,7 +430,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -427,7 +444,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -437,7 +455,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -448,7 +467,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -460,7 +480,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -472,7 +493,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -483,7 +505,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -495,7 +518,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -504,7 +528,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -515,7 +540,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -528,7 +554,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -541,7 +568,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -552,7 +580,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -563,7 +592,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -576,7 +606,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -589,7 +620,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -600,7 +632,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -610,7 +643,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -623,7 +657,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Digest)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -634,7 +669,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -644,7 +680,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -655,7 +692,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -666,7 +704,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -679,7 +718,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -690,7 +730,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -701,7 +742,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -712,7 +754,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -725,7 +768,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -736,7 +780,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -749,7 +794,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Verify)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -760,7 +806,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -771,7 +818,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -782,7 +830,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -795,7 +844,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -808,7 +858,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -821,7 +872,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -834,7 +886,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -847,7 +900,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -860,7 +914,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -876,7 +931,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -890,7 +946,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -906,7 +963,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -920,7 +978,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -933,7 +992,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -944,7 +1004,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -953,7 +1014,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } @@ -962,7 +1024,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)( ) { DIN; - + DBG(("TODO!!!")); + DOUT; return CKR_OK; } From 9489748380196701055ca461aa68f8f4d355c589 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 7 Jul 2015 10:22:49 +0200 Subject: [PATCH 022/134] Fix debug message. --- ykcs11/ykcs11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 0744318..3165af7 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -73,7 +73,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( } if (piv_state == NULL) { - DBG(("Ykpiv is not finalized")); + DBG(("Ykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; } From dae729705015826f34334c01d3d80d84f769d832 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 14 Jul 2015 14:13:02 +0200 Subject: [PATCH 023/134] Major refactor and vendor abstraction. --- lib/ykpiv.c | 28 ++++++---- lib/ykpiv.h | 4 +- lib/ykpiv.map | 3 +- ykcs11/Makefile.am | 3 +- ykcs11/vendors.c | 32 ++++++++---- ykcs11/vendors.h | 31 ++++++++---- ykcs11/ykcs11.c | 124 +++++++++++++++++++++++++++++++-------------- ykcs11/yubico.c | 75 +++++++++++++++++++-------- ykcs11/yubico.h | 15 ++++-- 9 files changed, 212 insertions(+), 103 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index b3a5114..e8182ad 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -127,6 +127,10 @@ ykpiv_rc ykpiv_disconnect(ykpiv_state *state) { } ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { + return ykpiv_connect2(state, wanted, NULL, 0); +} + +ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char **readers, unsigned long *len) { unsigned long num_readers = 0; unsigned long active_protocol; char reader_buf[1024]; @@ -165,19 +169,21 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { return YKPIV_PCSC_ERROR; } - // TODO: improve here - state->n_readers = 0; - state->tot_readers_len = num_readers; - reader_ptr = reader_buf; - for (i = 0; i < num_readers; i++) - if (reader_buf[i] == '\0' && i != num_readers - 1) { - strcpy(state->readers[state->n_readers], reader_ptr); // TODO: strdup? - state->n_readers = state->n_readers + 1; - reader_ptr += i + 1; + // Save available readers (aka PKCS11 slots) + if (readers != NULL) { + *readers = malloc(sizeof(char) * num_readers); + if (*readers == NULL) { + if(state->verbose) { + fprintf (stderr, "error: malloc failed"); + } + SCardReleaseContext(state->context); + return YKPIV_MEMORY_ERROR; } - // ********* + memcpy(*readers, reader_buf, num_readers); + *len = num_readers; + } - reader_ptr = reader_buf; // TODO: reader_buf is never free'd + reader_ptr = reader_buf; if(wanted) { while(*reader_ptr != '\0') { if(strstr(reader_ptr, wanted)) { diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 319da54..be1fb5b 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -64,6 +64,7 @@ extern "C" ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); ykpiv_rc ykpiv_done(ykpiv_state *state); ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); + ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char **readers, unsigned long *len); ykpiv_rc ykpiv_disconnect(ykpiv_state *state); ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, const unsigned char *in_data, long in_len, @@ -85,9 +86,6 @@ extern "C" ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id, unsigned char *indata, size_t len); - ykpiv_rc ykpiv_get_reader_slot_number(ykpiv_state *state, unsigned long *slots, unsigned long *total); - ykpiv_rc ykpiv_get_reader_slot(ykpiv_state *state, unsigned long slot, char *reader); - #define YKPIV_ALGO_3DES 0x03 #define YKPIV_ALGO_RSA1024 0x06 #define YKPIV_ALGO_RSA2048 0x07 diff --git a/lib/ykpiv.map b/lib/ykpiv.map index d7fb74c..09c7847 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -52,6 +52,5 @@ YKPIV_0.2.0 { global: ykpiv_decipher_data; - ykpiv_get_reader_slot_number; - ykpiv_get_reader_slot; + ykpiv_connect2; } YKPIV_0.1.0; diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index 050c4dc..22fbfea 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -34,7 +34,8 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map -libykcs11_la_SOURCES += vendors.c vendor.h yubico.c yubico. h +libykcs11_la_SOURCES += vendors.c vendor.h yubico.c yubico.h +libykcs11_la_SOURCES += utils.h utils.c #internal.h #libykcs11_la_SOURCES += error.c diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index 179cc99..0353368 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -16,20 +16,30 @@ vendor_t get_vendor(vendor_id_t vid) { switch (vid) { case YUBICO: - v.get_version = YUBICO_get_version; - v.get_label = YUBICO_get_label; - v.get_manufacturer = YUBICO_get_manufacturer; - v.get_model = YUBICO_get_model; - v.get_flags = YUBICO_get_flags; + v.get_slot_description = YUBICO_get_slot_description; + v.get_slot_manufacturer = YUBICO_get_slot_manufacturer; + v.get_slot_flags = YUBICO_get_slot_flags; + v.get_slot_version = YUBICO_get_slot_version; + v.get_token_label = YUBICO_get_token_label; + v.get_token_manufacturer = YUBICO_get_token_manufacturer; + v.get_token_model = YUBICO_get_token_model; + v.get_token_flags = YUBICO_get_token_flags; + v.get_token_version = YUBICO_get_token_version; + v.get_token_serial = YUBICO_get_token_serial; break; case UNKNOWN: - v.get_version = NULL; // TODO: make up dummy functions? - v.get_label = NULL; - v.get_manufacturer = NULL; - v.get_model = NULL; - v.get_flags = NULL; - + default: + v.get_slot_description = NULL; + v.get_slot_manufacturer = NULL; + v.get_slot_flags = NULL; + v.get_slot_version = NULL; + v.get_token_label = NULL; + v.get_token_manufacturer = NULL; + v.get_token_model = NULL; + v.get_token_flags = NULL; + v.get_token_version = NULL; + v.get_token_serial = NULL; } return v; diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index 5f1e867..d82f6c4 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -8,18 +8,29 @@ typedef enum { YUBICO = 0x01 } vendor_id_t; -typedef CK_VERSION (*get_version_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_UTF8CHAR_PTR (*get_label_f)(void); -typedef CK_UTF8CHAR_PTR (*get_manufacturer_f)(void); -typedef CK_UTF8CHAR_PTR (*get_model_f)(void); -typedef CK_FLAGS (*get_flags_f)(void); +typedef CK_UTF8CHAR_PTR (*get_s_description_f)(void); +typedef CK_UTF8CHAR_PTR (*get_s_manufacturer_f)(void); +typedef CK_FLAGS (*get_s_flags_f)(void); +typedef CK_VERSION (*get_s_version_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_UTF8CHAR_PTR (*get_t_label_f)(void); +typedef CK_UTF8CHAR_PTR (*get_t_manufacturer_f)(void); +typedef CK_UTF8CHAR_PTR (*get_t_model_f)(void); +typedef CK_FLAGS (*get_t_flags_f)(void); +typedef CK_VERSION (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_CHAR_PTR (*get_t_serial_f)(void); + typedef struct { - get_version_f get_version; - get_label_f get_label; - get_manufacturer_f get_manufacturer; - get_model_f get_model; - get_flags_f get_flags; + get_s_description_f get_slot_description; + get_s_manufacturer_f get_slot_manufacturer; + get_s_flags_f get_slot_flags; + get_s_version_f get_slot_version; + get_t_label_f get_token_label; + get_t_manufacturer_f get_token_manufacturer; + get_t_model_f get_token_model; + get_t_flags_f get_token_flags; + get_t_version_f get_token_version; + get_t_serial_f get_token_serial; } vendor_t; vendor_id_t get_vendor_id(char *vendor_name); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 3165af7..b0aed2c 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -3,6 +3,9 @@ #include #include #include "vendors.h" +#include "utils.h" + +#define HAS_TOKEN(x) ((slots[(x)].info.flags) & (CKF_TOKEN_PRESENT)) #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ @@ -10,8 +13,8 @@ printf ("\n"); \ } while (0) -#define YKCS11_DBG 1 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 +#define YKCS11_DBG 0 // General debug, must be either 1 or 0 +#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" @@ -19,6 +22,8 @@ #define PIV_MIN_PIN_LEN 6 #define PIV_MAX_PIN_LEN 8 +#define YKCS11_MAX_SLOTS 16 + #if YKCS11_DBG #define DBG(x) D(x); #else @@ -35,6 +40,9 @@ static ykpiv_state *piv_state = NULL; +static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; +static CK_ULONG n_slots = 0; + extern CK_FUNCTION_LIST function_list; /* General Purpose */ @@ -44,7 +52,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( ) { DIN; + CK_CHAR_PTR readers; + CK_ULONG len; + // TODO: check for locks and mutexes + if (piv_state != NULL) return CKR_CRYPTOKI_ALREADY_INITIALIZED; @@ -53,11 +65,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; // TODO: better error? } - if(ykpiv_connect(piv_state, NULL) != YKPIV_OK) { + if(ykpiv_connect2(piv_state, NULL, &readers, &len) != YKPIV_OK) { DBG(("Unable to connect to reader")); return CKR_FUNCTION_FAILED; } + parse_readers(readers, len, slots, &n_slots); + DBG(("FOUND: %lu slots %lu len", n_slots, len)); + DOUT; return CKR_OK; } @@ -73,7 +88,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( } if (piv_state == NULL) { - DBG(("Ykpiv is not initialized or already finalized")); + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; } @@ -89,7 +104,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)( ) { DIN; - CK_VERSION ver = {0.0}; + CK_VERSION ver = {0, 0}; // TODO: set version number pInfo->cryptokiVersion = function_list.version; memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); @@ -112,10 +127,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)( { DIN; if(ppFunctionList == NULL_PTR) { + DBG(("GetFunctionList called with ppFunctionList = NULL")); return CKR_ARGUMENTS_BAD; } *ppFunctionList = &function_list; + DOUT; return CKR_OK; } @@ -128,31 +145,29 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( ) { DIN; - unsigned long tot_readers_len; - unsigned long n_readers; int i; // TODO: what about tokenPresent? - ykpiv_get_reader_slot_number(piv_state, &n_readers, &tot_readers_len); // TODO: maybe refactor this with a reader struct? + //ykpiv_get_reader_slot_number(piv_state, &n_readers, &tot_reader_len); // TODO: maybe refactor this with a reader struct? if (pSlotList == NULL_PTR) { // Just return the number of slots - *pulCount = n_readers; + *pulCount = n_slots; DOUT; return CKR_OK; } - if (*pulCount < n_readers) { - DBG(("Buffer too small: needed %u, provided %u", n_readers, *pulCount)); + if (*pulCount < n_slots) { + DBG(("Buffer too small: needed %lu, provided %lu", n_slots, *pulCount)); return CKR_BUFFER_TOO_SMALL; } - for (i = 0; i < n_readers; i++) { + for (i = 0; i < n_slots; i++) { pSlotList[i] = i; } DBG(("%d token", tokenPresent)); - DBG(("%u count", *pulCount)); + DBG(("%lu count", *pulCount)); DOUT; return CKR_OK; @@ -164,17 +179,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( ) { DIN; - /* - * According to pcsc-lite, the format of a reader name is: - * name [interface] (serial) index slot - * http://ludovicrousseau.blogspot.se/2010/05/what-is-in-pcsc-reader-name.html - */ - ykpiv_get_reader_slot(piv_state, slotID, pInfo->slotDescription); // TODO: should be ' ' padded - strcpy(pInfo->manufacturerID, "ADD SLOT MANUFACTURER NAME HERE"); - pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT; // TODO: What for other brands? Query for token status? - DBG(("slotID %u, pInfo %s", slotID, pInfo->slotDescription)); + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + if (slotID >= n_slots) + return CKR_ARGUMENTS_BAD; + + memcpy(pInfo, &slots[slotID].info, sizeof(CK_SLOT_INFO)); + + DBG(("slotID %lu, pInfo %s", slotID, pInfo->slotDescription)); + + DOUT; return CKR_OK; } @@ -194,33 +210,44 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - ykpiv_get_reader_slot(piv_state, slotID, buf); - vid = get_vendor_id(buf); + if (slotID >= n_slots) + return CKR_ARGUMENTS_BAD; - if (vid == UNKNOWN) + vid = slots[slotID].vid; + + if (vid == UNKNOWN) { + DBG(("No support for token in slot %lu", slotID)); return CKR_TOKEN_NOT_RECOGNIZED; + } - vendor = get_vendor(vid); + if (!HAS_TOKEN(slotID)) { + DBG(("Slot %lu has no token inserted", slotID)); + return CKR_TOKEN_NOT_PRESENT; + } + + vendor = get_vendor(vid); // TODO: make a token field in slot_t ? memset(pInfo->label, ' ', sizeof(pInfo->label)); - p = vendor.get_label(); + p = vendor.get_token_label(); len = strlen(p); strncpy(pInfo->label, p, len); memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); - p = vendor.get_manufacturer(); + p = vendor.get_token_manufacturer(); len = strlen(p); strncpy(pInfo->manufacturerID, p, len); memset(pInfo->model, ' ', sizeof(pInfo->model)); - p = vendor.get_model(); + p = vendor.get_token_model(); len = strlen(p); strncpy(pInfo->model, p, len); memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber)); - strncpy(pInfo->serialNumber, "12345", 5); + p = vendor.get_token_serial(); + len = strlen(p); + strncpy(pInfo->serialNumber, p, len); - pInfo->flags = vendor.get_flags(); // bit flags indicating capabilities and status of the device as defined below + pInfo->flags = vendor.get_token_flags(); // bit flags indicating capabilities and status of the device as defined below pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? @@ -230,9 +257,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token - pInfo->ulMaxPinLen = PIV_MIN_PIN_LEN; // maximum length in bytes of the PIN + pInfo->ulMaxPinLen = PIV_MAX_PIN_LEN; // maximum length in bytes of the PIN - pInfo->ulMinPinLen = PIV_MAX_PIN_LEN; // minimum length in bytes of the PIN + pInfo->ulMinPinLen = PIV_MIN_PIN_LEN; // minimum length in bytes of the PIN pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; @@ -243,14 +270,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; ykpiv_get_version(piv_state, buf, sizeof(buf)); - ver = vendor.get_version(buf, strlen(buf)); + ver = vendor.get_token_version(buf, strlen(buf)); pInfo->hardwareVersion = ver; // version number of hardware pInfo->firmwareVersion = ver; // version number of firmware - memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime)); + memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime)); // No clock present, clear + DOUT; return CKR_OK; } @@ -273,7 +301,25 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( ) { DIN; - DBG(("TODO!!!")); + + int i; + + if (pMechanismList == NULL_PTR) { + // Just return the number of mechanisms + *pulCount = 3; + DOUT; + return CKR_OK; + } + + if (*pulCount < 3) { + DBG(("Buffer too small: needed %lu, provided %lu", 1l, *pulCount)); + return CKR_BUFFER_TOO_SMALL; + } + + for (i = 0; i < 3; i++) { + pMechanismList[i] = CKM_SHA_1; + } + DOUT; return CKR_OK; } @@ -284,9 +330,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( CK_MECHANISM_INFO_PTR pInfo ) { - DIN; - DBG(("TODO!!!")); - DOUT; + //DIN; + //DBG(("TODO!!!")); + //DOUT; return CKR_OK; } diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index 5f14296..7dfb61d 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -1,7 +1,58 @@ #include "yubico.h" #include "pkcs11.h" -CK_VERSION YUBICO_get_version(CK_UTF8CHAR_PTR version, CK_ULONG len) { + +CK_UTF8CHAR_PTR YUBICO_get_slot_description(void) { + + return "YubiKey Virtual Reader"; + +} + +CK_UTF8CHAR_PTR YUBICO_get_slot_manufacturer(void) { + + return "Yubico"; + +} + +CK_FLAGS YUBICO_get_slot_flags(void) { + + return CKF_TOKEN_PRESENT | CKF_HW_SLOT; + +} + +CK_VERSION YUBICO_get_slot_version(CK_UTF8CHAR_PTR version, CK_ULONG len) { + + CK_VERSION v = {1.0}; // Dummy value + + return v; + +} + +CK_UTF8CHAR_PTR YUBICO_get_token_label(void) { + + return "YubiKey PIV"; + +} + +CK_UTF8CHAR_PTR YUBICO_get_token_manufacturer(void) { + + return "Yubico"; + +} + +CK_UTF8CHAR_PTR YUBICO_get_token_model(void) { + + return "PRO"; + +} + +CK_FLAGS YUBICO_get_token_flags(void) { + + return CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; + +} + +CK_VERSION YUBICO_get_token_version(CK_UTF8CHAR_PTR version, CK_ULONG len) { CK_VERSION v = {0, 0}; int i = 0; @@ -28,26 +79,8 @@ CK_VERSION YUBICO_get_version(CK_UTF8CHAR_PTR version, CK_ULONG len) { return v; } -CK_UTF8CHAR_PTR YUBICO_get_label(void) { +CK_BYTE_PTR YUBICO_get_token_serial(void) { - return "YubiKey"; - -} - -CK_UTF8CHAR_PTR YUBICO_get_manufacturer(void) { - - return "Yubico"; - -} - -CK_UTF8CHAR_PTR YUBICO_get_model(void) { - - return "PRO"; - -} - -CK_FLAGS YUBICO_get_flags(void) { - - return CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; + return "1234"; } diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index cf78790..cdac771 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -3,10 +3,15 @@ #include "pkcs11.h" -CK_VERSION YUBICO_get_version(CK_UTF8CHAR_PTR version, CK_ULONG len); -CK_UTF8CHAR_PTR YUBICO_get_label(void); -CK_UTF8CHAR_PTR YUBICO_get_manufacturer(void); -CK_UTF8CHAR_PTR YUBICO_get_model(void); -CK_FLAGS YUBICO_get_flags(void); +CK_UTF8CHAR_PTR YUBICO_get_slot_description(void); +CK_UTF8CHAR_PTR YUBICO_get_slot_manufacturer(void); +CK_FLAGS YUBICO_get_slot_flags(void); +CK_VERSION YUBICO_get_slot_version(CK_UTF8CHAR_PTR version, CK_ULONG len); +CK_UTF8CHAR_PTR YUBICO_get_token_label(void); +CK_UTF8CHAR_PTR YUBICO_get_token_manufacturer(void); +CK_UTF8CHAR_PTR YUBICO_get_token_model(void); +CK_FLAGS YUBICO_get_token_flags(void); +CK_CHAR_PTR YUBICO_get_token_serial(void); +CK_VERSION YUBICO_get_token_version(CK_UTF8CHAR_PTR version, CK_ULONG len); #endif From 0e4569af2cecba09fdd903ad3f1019b55c8e8266 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 14 Jul 2015 15:45:03 +0200 Subject: [PATCH 024/134] Handle token presence in slots. --- ykcs11/ykcs11.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index b0aed2c..bdfc373 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -5,16 +5,14 @@ #include "vendors.h" #include "utils.h" -#define HAS_TOKEN(x) ((slots[(x)].info.flags) & (CKF_TOKEN_PRESENT)) - #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ printf x; \ printf ("\n"); \ } while (0) -#define YKCS11_DBG 0 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 +#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" @@ -42,6 +40,7 @@ static ykpiv_state *piv_state = NULL; static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; static CK_ULONG n_slots = 0; +static CK_ULONG n_tokenless_slots = 0; extern CK_FUNCTION_LIST function_list; @@ -70,8 +69,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; } - parse_readers(readers, len, slots, &n_slots); - DBG(("FOUND: %lu slots %lu len", n_slots, len)); + parse_readers(readers, len, slots, &n_slots, &n_tokenless_slots); + DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_tokenless_slots)); DOUT; return CKR_OK; @@ -92,6 +91,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( return CKR_CRYPTOKI_NOT_INITIALIZED; } + memset(slots, 0, sizeof(slots)); + ykpiv_done(piv_state); // TODO: this calls disconnect... piv_state == NULL; @@ -146,28 +147,38 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( { DIN; int i; - - // TODO: what about tokenPresent? + int j; //ykpiv_get_reader_slot_number(piv_state, &n_readers, &tot_reader_len); // TODO: maybe refactor this with a reader struct? if (pSlotList == NULL_PTR) { // Just return the number of slots *pulCount = n_slots; + + if (tokenPresent) + *pulCount = n_tokenless_slots; + else + *pulCount = n_slots; + DOUT; return CKR_OK; } - if (*pulCount < n_slots) { + if ((tokenPresent && *pulCount < n_tokenless_slots) || (!tokenPresent && *pulCount < n_slots)) { DBG(("Buffer too small: needed %lu, provided %lu", n_slots, *pulCount)); return CKR_BUFFER_TOO_SMALL; } - for (i = 0; i < n_slots; i++) { - pSlotList[i] = i; + for (j = 0, i = 0; i < n_slots; i++) { + if (tokenPresent) { + if (has_token(slots + i)) + pSlotList[j++] = i; + } + else + pSlotList[i] = i; } - DBG(("%d token", tokenPresent)); - DBG(("%lu count", *pulCount)); + DBG(("token present is %d", tokenPresent)); + DBG(("number of slot(s) is %lu", *pulCount)); DOUT; return CKR_OK; @@ -188,7 +199,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( memcpy(pInfo, &slots[slotID].info, sizeof(CK_SLOT_INFO)); - DBG(("slotID %lu, pInfo %s", slotID, pInfo->slotDescription)); + //DBG(("slotID %lu, pInfo %s", slotID, pInfo->slotDescription)); DOUT; return CKR_OK; @@ -220,7 +231,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( return CKR_TOKEN_NOT_RECOGNIZED; } - if (!HAS_TOKEN(slotID)) { + if (!has_token(slots + slotID)) { DBG(("Slot %lu has no token inserted", slotID)); return CKR_TOKEN_NOT_PRESENT; } @@ -330,9 +341,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( CK_MECHANISM_INFO_PTR pInfo ) { - //DIN; - //DBG(("TODO!!!")); - //DOUT; + DIN; + DBG(("TODO!!!")); + DOUT; return CKR_OK; } From de7e1ed00056472a7f33d52142add54818cb2643 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 14 Jul 2015 16:51:08 +0200 Subject: [PATCH 025/134] Added basic version of login. --- lib/ykpiv.h | 2 +- ykcs11/pkcs11t.h | 6 ++++-- ykcs11/ykcs11.c | 32 ++++++++++++++++++++++++++++---- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/lib/ykpiv.h b/lib/ykpiv.h index be1fb5b..0ccbfbb 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -74,7 +74,7 @@ extern "C" ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, unsigned char *hex_out, size_t *out_len); ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in, - size_t in_len,unsigned char *sign_out, size_t *out_len, + size_t in_len, unsigned char *sign_out, size_t *out_len, unsigned char algorithm, unsigned char key); ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *enc_in, size_t in_len, unsigned char *enc_out, size_t *out_len, diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index b9bf233..adc0575 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -245,9 +245,11 @@ typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; * v2.0 */ typedef CK_ULONG CK_USER_TYPE; /* Security Officer */ -#define CKU_SO 0 +#define CKU_SO 0 /* Normal user */ -#define CKU_USER 1 +#define CKU_USER 1 +/* Context specific */ +#define CKU_CONTEXT_SPECIFIC 2 /* CK_STATE enumerates the session states */ diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index bdfc373..010c3e0 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -42,7 +42,7 @@ static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; static CK_ULONG n_slots = 0; static CK_ULONG n_tokenless_slots = 0; -extern CK_FUNCTION_LIST function_list; +extern CK_FUNCTION_LIST function_list; // TODO: check all return values /* General Purpose */ @@ -92,7 +92,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( } memset(slots, 0, sizeof(slots)); - + ykpiv_done(piv_state); // TODO: this calls disconnect... piv_state == NULL; @@ -235,7 +235,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( DBG(("Slot %lu has no token inserted", slotID)); return CKR_TOKEN_NOT_PRESENT; } - + vendor = get_vendor(vid); // TODO: make a token field in slot_t ? memset(pInfo->label, ' ', sizeof(pInfo->label)); @@ -464,7 +464,31 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( ) { DIN; - DBG(("TODO!!!")); + CK_ULONG tries; + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (userType != CKU_USER && + userType != CKU_SO && + userType != CKU_CONTEXT_SPECIFIC) + return CKR_ARGUMENTS_BAD; + + if (ulPinLen < PIV_MIN_PIN_LEN || + ulPinLen > PIV_MAX_PIN_LEN) + return CKR_ARGUMENTS_BAD; + + //TODO: check session (read only?) + DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); + + tries = 0; + if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { + DBG(("You loose! %lu", tries)); + return CKR_PIN_INCORRECT; + } + + DBG(("You win! %lu", tries)) + DOUT; return CKR_OK; } From 9bd5bc571862db4b9de904ceeed899bb360f3ece Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 15 Jul 2015 14:19:10 +0200 Subject: [PATCH 026/134] Changed tokenless to with_token. --- ykcs11/ykcs11.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 010c3e0..847c6f8 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -40,7 +40,7 @@ static ykpiv_state *piv_state = NULL; static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; static CK_ULONG n_slots = 0; -static CK_ULONG n_tokenless_slots = 0; +static CK_ULONG n_slots_with_token = 0; extern CK_FUNCTION_LIST function_list; // TODO: check all return values @@ -69,8 +69,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; } - parse_readers(readers, len, slots, &n_slots, &n_tokenless_slots); - DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_tokenless_slots)); + parse_readers(readers, len, slots, &n_slots, &n_slots_with_token); + DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token)); DOUT; return CKR_OK; @@ -155,7 +155,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( *pulCount = n_slots; if (tokenPresent) - *pulCount = n_tokenless_slots; + *pulCount = n_slots_with_token; else *pulCount = n_slots; @@ -163,7 +163,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( return CKR_OK; } - if ((tokenPresent && *pulCount < n_tokenless_slots) || (!tokenPresent && *pulCount < n_slots)) { + if ((tokenPresent && *pulCount < n_slots_with_token) || (!tokenPresent && *pulCount < n_slots)) { DBG(("Buffer too small: needed %lu, provided %lu", n_slots, *pulCount)); return CKR_BUFFER_TOO_SMALL; } @@ -258,7 +258,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( len = strlen(p); strncpy(pInfo->serialNumber, p, len); - pInfo->flags = vendor.get_token_flags(); // bit flags indicating capabilities and status of the device as defined below + pInfo->flags = vendor.get_token_flags(); // bit flags indicating capabilities and status of the device as defined below // TODO: what about other flags? Like last attempt pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? From 94b812d0813ead8a1a84c483d7303fa08d0312db Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 15 Jul 2015 14:19:40 +0200 Subject: [PATCH 027/134] Added utils files. --- ykcs11/utils.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ ykcs11/utils.h | 16 +++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 ykcs11/utils.c create mode 100644 ykcs11/utils.h diff --git a/ykcs11/utils.c b/ykcs11/utils.c new file mode 100644 index 0000000..fe94111 --- /dev/null +++ b/ykcs11/utils.c @@ -0,0 +1,62 @@ +#include "utils.h" +#include + +CK_BBOOL has_token(const ykcs11_slot_t *slot) { + + return (slot->info.flags & CKF_TOKEN_PRESENT); + +} + +CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, + ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token) { + + CK_BYTE i; + CK_BYTE_PTR p; + CK_BYTE_PTR s; + CK_ULONG l; + vendor_t vendor; + + *n_slots = 0; + *n_with_token = 0; + p = readers; + + /* + * According to pcsc-lite, the format of a reader name is: + * name [interface] (serial) index slot + * http://ludovicrousseau.blogspot.se/2010/05/what-is-in-pcsc-reader-name.html + */ + + for (i = 0; i < len; i++) + if (readers[i] == '\0' && i != len - 1) { + slots[*n_slots].vid = get_vendor_id(p); + + if (slots[*n_slots].vid == UNKNOWN) { + // Unknown slot, just save what info we have + memset(&slots[*n_slots].info, 0, sizeof(CK_SLOT_INFO)); + memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); + strncpy(slots[*n_slots].info.slotDescription, p, strlen(p)); + } + else { + vendor = get_vendor(slots[*n_slots].vid); + + // Values must NOT be null terminated and ' ' padded + + memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); + s = vendor.get_slot_description(); + l = strlen(s); + strncpy(slots[*n_slots].info.slotDescription, s, l); + + memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID)); + s = vendor.get_slot_manufacturer(); + l = strlen(s); + strncpy(slots[*n_slots].info.manufacturerID, s, l); + + slots[*n_slots].info.flags = vendor.get_slot_flags(); + + if (has_token(slots + *n_slots)) + (*n_with_token)++; + } + (*n_slots)++; + p += i + 1; + } +} diff --git a/ykcs11/utils.h b/ykcs11/utils.h new file mode 100644 index 0000000..2e40461 --- /dev/null +++ b/ykcs11/utils.h @@ -0,0 +1,16 @@ +#ifndef UTILS_H +#define UTILS_H + +#include "pkcs11.h" +#include "vendors.h" + +typedef struct { + vendor_id_t vid; + CK_SLOT_INFO info; +} ykcs11_slot_t; // TODO: move this + +CK_BBOOL has_token(const ykcs11_slot_t *slot); +CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, + ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token); + +#endif From 7cd835614e9c725d9c5dc5bb96208e13de57fe7a Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 15 Jul 2015 15:45:03 +0200 Subject: [PATCH 028/134] Added basic session handling. --- ykcs11/ykcs11.c | 92 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 847c6f8..c4c05fb 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -22,6 +22,8 @@ #define YKCS11_MAX_SLOTS 16 +#define YKCS11_SESSION_ID 5355104 + #if YKCS11_DBG #define DBG(x) D(x); #else @@ -42,6 +44,9 @@ static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; static CK_ULONG n_slots = 0; static CK_ULONG n_slots_with_token = 0; +static CK_SESSION_HANDLE session = CK_INVALID_HANDLE; // TODO: support multiple sessions? +static CK_SESSION_INFO session_info; + extern CK_FUNCTION_LIST function_list; // TODO: check all return values /* General Purpose */ @@ -314,7 +319,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( DIN; int i; - + // TODO: check more return values like not init ... if (pMechanismList == NULL_PTR) { // Just return the number of mechanisms *pulCount = 3; @@ -394,7 +399,46 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (slotID >= n_slots || phSession == NULL) + return CKR_ARGUMENTS_BAD; + + if (!has_token(slots + slotID)) { + DBG(("Slot %lu has no token inserted", slotID)); + return CKR_TOKEN_NOT_PRESENT; + } + + if (flags & CKF_SERIAL_SESSION == 0) { + DBG(("Open session called without CKF_SERIAL_SESSION set")); + return CKR_SESSION_PARALLEL_NOT_SUPPORTED; + } + + if (session != CK_INVALID_HANDLE) { + DBG(("A session with this or another token already exists")); + return CKR_SESSION_COUNT; + } + + session = YKCS11_SESSION_ID; + session_info.slotID = slotID; + // TODO: KEEP TRACK OF THE APPLICATION + + if (flags & CKF_RW_SESSION) { + // R/W Session + session_info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session + } + else { + // R/O Session + session_info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default session + } + + session_info.flags = flags; + session_info.ulDeviceError = 0; + + *phSession = session; + DOUT; return CKR_OK; } @@ -404,7 +448,21 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (session == CK_INVALID_HANDLE) { + DBG(("There is no existing session")); + return CKR_SESSION_CLOSED; + } + + if (hSession != YKCS11_SESSION_ID) + return CKR_SESSION_HANDLE_INVALID; + + session = CK_INVALID_HANDLE; + memset(&session_info, 0, sizeof(CK_SESSION_INFO)); + DOUT; return CKR_OK; } @@ -414,7 +472,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (session_info.slotID != slotID) + return CKR_SLOT_ID_INVALID; + + session = CK_INVALID_HANDLE; + memset(&session_info, 0, sizeof(CK_SESSION_INFO)); // TODO: Better to call close session? + DOUT; return CKR_OK; } @@ -425,7 +492,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (pInfo == NULL) + return CKR_ARGUMENTS_BAD; + + if (hSession != session) + return CKR_SESSION_HANDLE_INVALID; + + memcpy(pInfo, &session_info, sizeof(CK_SESSION_INFO)); + DOUT; return CKR_OK; } @@ -465,7 +543,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( { DIN; CK_ULONG tries; - + if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -488,7 +566,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( } DBG(("You win! %lu", tries)) - + DOUT; return CKR_OK; } From 9e6c5ca1fda81742e7e0d81c165dc330781f55e5 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 15 Jul 2015 16:05:23 +0200 Subject: [PATCH 029/134] More work on login. --- ykcs11/ykcs11.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c4c05fb..ce4de29 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -556,13 +556,40 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( ulPinLen > PIV_MAX_PIN_LEN) return CKR_ARGUMENTS_BAD; - //TODO: check session (read only?) DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); - tries = 0; - if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { - DBG(("You loose! %lu", tries)); - return CKR_PIN_INCORRECT; + if (session == CK_INVALID_HANDLE) + return CKR_SESSION_CLOSED; + + if (hSession != session) + return CKR_SESSION_HANDLE_INVALID; + + if (userType != CKU_SO && + userType != CKU_USER && + userType != CKU_CONTEXT_SPECIFIC) + return CKR_USER_TYPE_INVALID; + + if (session_info.flags & CKF_RW_SESSION == 0) { // TODO: make macros for these? + DBG(("Tried to log-in to a read-only session")); + return CKR_SESSION_READ_ONLY_EXISTS; + } + + switch (userType) { + case CKU_USER: + if (session_info.state == CKS_RW_USER_FUNCTIONS) + return CKR_USER_ALREADY_LOGGED_IN; + + tries = 0; + if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { + DBG(("You loose! %lu", tries)); + return CKR_PIN_INCORRECT; + } + break; + + case CKU_SO: + case CKU_CONTEXT_SPECIFIC: + default: + return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now } DBG(("You win! %lu", tries)) From 5a39b5f582a0ee962cb643aa4fce9ae04aea755e Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 16 Jul 2015 16:07:06 +0200 Subject: [PATCH 030/134] More refactoring. --- ykcs11/pkcs11t.h | 31 ++++++++++- ykcs11/utils.c | 29 +++++++--- ykcs11/vendors.c | 42 +++++++------- ykcs11/vendors.h | 43 +++++++------- ykcs11/ykcs11.c | 87 ++++++++++++++++++----------- ykcs11/yubico.c | 142 +++++++++++++++++++++++++++++++++++++---------- ykcs11/yubico.h | 21 +++---- 7 files changed, 273 insertions(+), 122 deletions(-) diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index adc0575..ddb608e 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -84,6 +84,8 @@ typedef long int CK_LONG; /* at least 32 bits; each bit is a Boolean flag */ typedef CK_ULONG CK_FLAGS; +/* Custom type defined for consistency */ +typedef CK_FLAGS CK_PTR CK_FLAGS_PTR; /* some special values for certain CK_ULONG variables */ #define CK_UNAVAILABLE_INFORMATION (~0UL) @@ -456,11 +458,26 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_MD5_RSA_PKCS 0x00000005 #define CKM_SHA1_RSA_PKCS 0x00000006 +/* Added for 2.4 */ +#define CKM_RSA_PKCS_PSS 0x0000000D +#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E +/* Added for 2.4 */ + #define CKM_DSA_KEY_PAIR_GEN 0x00000010 #define CKM_DSA 0x00000011 #define CKM_DSA_SHA1 0x00000012 #define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 #define CKM_DH_PKCS_DERIVE 0x00000021 + +/* Added for 2.4 */ +#define CKM_SHA256_RSA_PKCS 0x00000040 +#define CKM_SHA384_RSA_PKCS 0x00000041 +#define CKM_SHA512_RSA_PKCS 0x00000042 +#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 +#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 +#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 +/* Added for 2.4 */ + #define CKM_RC2_KEY_GEN 0x00000100 #define CKM_RC2_ECB 0x00000101 #define CKM_RC2_CBC 0x00000102 @@ -517,6 +534,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SHA_1_HMAC 0x00000221 #define CKM_SHA_1_HMAC_GENERAL 0x00000222 +/* Added for 2.4 */ +#define CKM_SHA256 0x00000250 +#define CKM_SHA384 0x00000260 +#define CKM_SHA512 0x00000270 +/* Added for 2.4 */ + /* All of the following mechanisms are new for v2.0 */ /* Note that CAST128 and CAST5 are the same algorithm */ #define CKM_CAST_KEY_GEN 0x00000300 @@ -611,10 +634,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_BATON_WRAP 0x00001036 /* PKCS #11 V2.01 probably won't actually have ECDSA in it */ -#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_EC_KEY_PAIR_GEN 0x00001040 +//#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 // Deprecated in 2.11 #define CKM_ECDSA 0x00001041 #define CKM_ECDSA_SHA1 0x00001042 +/* Added for 2.4 */ +#define CKM_ECDH1_DERIVE 0x00001050 +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 +/* Added for 2.4 */ + #define CKM_JUNIPER_KEY_GEN 0x00001060 #define CKM_JUNIPER_ECB128 0x00001061 #define CKM_JUNIPER_CBC128 0x00001062 diff --git a/ykcs11/utils.c b/ykcs11/utils.c index fe94111..45acf8c 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -30,7 +30,7 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, if (readers[i] == '\0' && i != len - 1) { slots[*n_slots].vid = get_vendor_id(p); - if (slots[*n_slots].vid == UNKNOWN) { + if (slots[*n_slots].vid == UNKNOWN) { // TODO: distinguish between tokenless and unsupported? // Unknown slot, just save what info we have memset(&slots[*n_slots].info, 0, sizeof(CK_SLOT_INFO)); memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); @@ -42,16 +42,26 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, // Values must NOT be null terminated and ' ' padded memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); - s = vendor.get_slot_description(); - l = strlen(s); - strncpy(slots[*n_slots].info.slotDescription, s, l); + s = slots[*n_slots].info.slotDescription; + l = sizeof(slots[*n_slots].info.slotDescription); + if (vendor.get_slot_description(s, l) != CKR_OK) + return CK_FALSE; memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID)); - s = vendor.get_slot_manufacturer(); - l = strlen(s); - strncpy(slots[*n_slots].info.manufacturerID, s, l); + s = slots[*n_slots].info.manufacturerID; + l = sizeof(slots[*n_slots].info.manufacturerID); + if(vendor.get_slot_manufacturer(s, l) != CKR_OK) + return CK_FALSE; - slots[*n_slots].info.flags = vendor.get_slot_flags(); + if (vendor.get_slot_flags(&slots[*n_slots].info.flags) != CKR_OK) + return CK_FALSE; + + // Treating hw and fw version the same + if (vendor.get_slot_version(&slots[*n_slots].info.hardwareVersion) != CKR_OK) + return CK_FALSE; + + if (vendor.get_slot_version(&slots[*n_slots].info.firmwareVersion) != CKR_OK) + return CK_FALSE; if (has_token(slots + *n_slots)) (*n_with_token)++; @@ -59,4 +69,7 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, (*n_slots)++; p += i + 1; } + + return CK_TRUE; + } diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index 0353368..36bc6dc 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -16,30 +16,32 @@ vendor_t get_vendor(vendor_id_t vid) { switch (vid) { case YUBICO: - v.get_slot_description = YUBICO_get_slot_description; - v.get_slot_manufacturer = YUBICO_get_slot_manufacturer; - v.get_slot_flags = YUBICO_get_slot_flags; - v.get_slot_version = YUBICO_get_slot_version; - v.get_token_label = YUBICO_get_token_label; - v.get_token_manufacturer = YUBICO_get_token_manufacturer; - v.get_token_model = YUBICO_get_token_model; - v.get_token_flags = YUBICO_get_token_flags; - v.get_token_version = YUBICO_get_token_version; - v.get_token_serial = YUBICO_get_token_serial; + v.get_slot_description = YUBICO_get_slot_description; + v.get_slot_manufacturer = YUBICO_get_slot_manufacturer; + v.get_slot_flags = YUBICO_get_slot_flags; + v.get_slot_version = YUBICO_get_slot_version; + v.get_token_label = YUBICO_get_token_label; + v.get_token_manufacturer = YUBICO_get_token_manufacturer; + v.get_token_model = YUBICO_get_token_model; + v.get_token_flags = YUBICO_get_token_flags; + v.get_token_version = YUBICO_get_token_version; + v.get_token_serial = YUBICO_get_token_serial; + v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; break; case UNKNOWN: default: - v.get_slot_description = NULL; - v.get_slot_manufacturer = NULL; - v.get_slot_flags = NULL; - v.get_slot_version = NULL; - v.get_token_label = NULL; - v.get_token_manufacturer = NULL; - v.get_token_model = NULL; - v.get_token_flags = NULL; - v.get_token_version = NULL; - v.get_token_serial = NULL; + v.get_slot_description = NULL; + v.get_slot_manufacturer = NULL; + v.get_slot_flags = NULL; + v.get_slot_version = NULL; + v.get_token_label = NULL; + v.get_token_manufacturer = NULL; + v.get_token_model = NULL; + v.get_token_flags = NULL; + v.get_token_version = NULL; + v.get_token_serial = NULL; + v.get_token_mechanisms_num = NULL; } return v; diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index d82f6c4..ab2a75a 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -8,29 +8,32 @@ typedef enum { YUBICO = 0x01 } vendor_id_t; -typedef CK_UTF8CHAR_PTR (*get_s_description_f)(void); -typedef CK_UTF8CHAR_PTR (*get_s_manufacturer_f)(void); -typedef CK_FLAGS (*get_s_flags_f)(void); -typedef CK_VERSION (*get_s_version_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_UTF8CHAR_PTR (*get_t_label_f)(void); -typedef CK_UTF8CHAR_PTR (*get_t_manufacturer_f)(void); -typedef CK_UTF8CHAR_PTR (*get_t_model_f)(void); -typedef CK_FLAGS (*get_t_flags_f)(void); -typedef CK_VERSION (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_CHAR_PTR (*get_t_serial_f)(void); +typedef CK_RV (*get_s_description_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_s_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_s_flags_f)(CK_FLAGS_PTR); +typedef CK_RV (*get_s_version_f)(CK_VERSION_PTR); +typedef CK_RV (*get_t_label_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_model_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_flags_f)(CK_FLAGS_PTR); +typedef CK_RV (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG, CK_VERSION_PTR); +typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); +//typedef CK_RV (*get_t_mechanisms)(CK_); typedef struct { - get_s_description_f get_slot_description; - get_s_manufacturer_f get_slot_manufacturer; - get_s_flags_f get_slot_flags; - get_s_version_f get_slot_version; - get_t_label_f get_token_label; - get_t_manufacturer_f get_token_manufacturer; - get_t_model_f get_token_model; - get_t_flags_f get_token_flags; - get_t_version_f get_token_version; - get_t_serial_f get_token_serial; + get_s_description_f get_slot_description; + get_s_manufacturer_f get_slot_manufacturer; + get_s_flags_f get_slot_flags; + get_s_version_f get_slot_version; + get_t_label_f get_token_label; + get_t_manufacturer_f get_token_manufacturer; + get_t_model_f get_token_model; + get_t_flags_f get_token_flags; + get_t_version_f get_token_version; + get_t_serial_f get_token_serial; + get_t_mechanisms_num_f get_token_mechanisms_num; } vendor_t; vendor_id_t get_vendor_id(char *vendor_name); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index ce4de29..163bc6a 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -99,7 +99,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( memset(slots, 0, sizeof(slots)); ykpiv_done(piv_state); // TODO: this calls disconnect... - piv_state == NULL; + piv_state = NULL; DOUT; return CKR_OK; @@ -154,7 +154,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( int i; int j; - //ykpiv_get_reader_slot_number(piv_state, &n_readers, &tot_reader_len); // TODO: maybe refactor this with a reader struct? + // TODO: check more preconditions if (pSlotList == NULL_PTR) { // Just return the number of slots *pulCount = n_slots; @@ -220,8 +220,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( vendor_id_t vid; vendor_t vendor; CK_BYTE buf[64]; - CK_UTF8CHAR_PTR p; - CK_BYTE len; if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -244,26 +242,24 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( vendor = get_vendor(vid); // TODO: make a token field in slot_t ? memset(pInfo->label, ' ', sizeof(pInfo->label)); - p = vendor.get_token_label(); - len = strlen(p); - strncpy(pInfo->label, p, len); + if (vendor.get_token_label(pInfo->label, sizeof(pInfo->label)) != CKR_OK) + return CKR_FUNCTION_FAILED; memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); - p = vendor.get_token_manufacturer(); - len = strlen(p); - strncpy(pInfo->manufacturerID, p, len); + if(vendor.get_token_manufacturer(pInfo->manufacturerID, sizeof(pInfo->manufacturerID)) != CKR_OK) + return CKR_FUNCTION_FAILED; memset(pInfo->model, ' ', sizeof(pInfo->model)); - p = vendor.get_token_model(); - len = strlen(p); - strncpy(pInfo->model, p, len); + if(vendor.get_token_model(pInfo->model, sizeof(pInfo->model)) != CKR_OK) + return CKR_FUNCTION_FAILED; memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber)); - p = vendor.get_token_serial(); - len = strlen(p); - strncpy(pInfo->serialNumber, p, len); + if(vendor.get_token_serial(pInfo->serialNumber, sizeof(pInfo->serialNumber)) != CKR_OK) + return CKR_FUNCTION_FAILED; - pInfo->flags = vendor.get_token_flags(); // bit flags indicating capabilities and status of the device as defined below // TODO: what about other flags? Like last attempt + // bit flags indicating capabilities and status of the device as defined below // TODO: what about other flags? Like last attempt + if (vendor.get_token_flags(&pInfo->flags) != CKR_OK) + return CKR_FUNCTION_FAILED; pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? @@ -286,7 +282,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; ykpiv_get_version(piv_state, buf, sizeof(buf)); - ver = vendor.get_token_version(buf, strlen(buf)); + if (vendor.get_token_version(buf, strlen(buf), &ver) != CKR_OK) + return CKR_FUNCTION_FAILED; pInfo->hardwareVersion = ver; // version number of hardware @@ -317,18 +314,40 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( ) { DIN; + vendor_t vendor; + int i; + CK_ULONG count; + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (slotID > n_slots || pulCount == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + if (slots[slotID].vid == UNKNOWN) { + DBG(("Slot %lu is tokenless/unsupported", slotID)); + return CKR_SLOT_ID_INVALID; + } + + // TODO: check more return values + // TODO: user NULL_PTR more for coherence + + vendor = get_vendor(slots[slotID].vid); // TODO: make a token field in slot_t ?; + + if (vendor.get_token_mechanisms_num(&count) != CKR_OK) + return CKR_FUNCTION_FAILED; - int i; - // TODO: check more return values like not init ... if (pMechanismList == NULL_PTR) { - // Just return the number of mechanisms - *pulCount = 3; + *pulCount = count; + DBG(("Found %lu mechanisms", *pulCount)); DOUT; return CKR_OK; } - if (*pulCount < 3) { - DBG(("Buffer too small: needed %lu, provided %lu", 1l, *pulCount)); + if (*pulCount < count) { + DBG(("Buffer too small: needed %lu, provided %lu", count, *pulCount)); return CKR_BUFFER_TOO_SMALL; } @@ -411,7 +430,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_TOKEN_NOT_PRESENT; } - if (flags & CKF_SERIAL_SESSION == 0) { + if ((flags & CKF_SERIAL_SESSION) == 0) { DBG(("Open session called without CKF_SERIAL_SESSION set")); return CKR_SESSION_PARALLEL_NOT_SUPPORTED; } @@ -421,11 +440,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_SESSION_COUNT; } + // TODO: make sue we don't open a session with an UNKNOWN slot/token + session = YKCS11_SESSION_ID; session_info.slotID = slotID; // TODO: KEEP TRACK OF THE APPLICATION - if (flags & CKF_RW_SESSION) { + if ((flags & CKF_RW_SESSION)) { // R/W Session session_info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session } @@ -472,7 +493,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( ) { DIN; - + if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -481,7 +502,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( session = CK_INVALID_HANDLE; memset(&session_info, 0, sizeof(CK_SESSION_INFO)); // TODO: Better to call close session? - + DOUT; return CKR_OK; } @@ -498,12 +519,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( if (pInfo == NULL) return CKR_ARGUMENTS_BAD; - + if (hSession != session) return CKR_SESSION_HANDLE_INVALID; memcpy(pInfo, &session_info, sizeof(CK_SESSION_INFO)); - + DOUT; return CKR_OK; } @@ -560,7 +581,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( if (session == CK_INVALID_HANDLE) return CKR_SESSION_CLOSED; - + if (hSession != session) return CKR_SESSION_HANDLE_INVALID; @@ -569,7 +590,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( userType != CKU_CONTEXT_SPECIFIC) return CKR_USER_TYPE_INVALID; - if (session_info.flags & CKF_RW_SESSION == 0) { // TODO: make macros for these? + if ((session_info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? DBG(("Tried to log-in to a read-only session")); return CKR_SESSION_READ_ONLY_EXISTS; } @@ -578,7 +599,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( case CKU_USER: if (session_info.state == CKS_RW_USER_FUNCTIONS) return CKR_USER_ALREADY_LOGGED_IN; - + tries = 0; if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { DBG(("You loose! %lu", tries)); diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index 7dfb61d..8b7d3c6 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -1,86 +1,168 @@ #include "yubico.h" #include "pkcs11.h" +#include + +#define YUBICO_MECHANISMS_NUM 5 + +// TODO add a type in vendor_t for SLOT | READER +static const CK_UTF8CHAR_PTR slot_description = "YubiKey Virtual Reader"; +static const CK_UTF8CHAR_PTR slot_manufacturer = "Yubico"; +static const CK_FLAGS slot_flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; +static const CK_VERSION slot_version = {1, 0}; +static const CK_UTF8CHAR_PTR token_label = "YubiKey PIV X"; +static const CK_UTF8CHAR_PTR token_manufacturer = "Yubico"; +static const CK_UTF8CHAR_PTR token_model = "YubiKey MODEL"; +static const CK_FLAGS token_flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; +static const CK_BYTE_PTR token_serial = "1234"; +static const CK_MECHANISM_TYPE token_mechanisms[] = { + CKM_RSA_PKCS_KEY_PAIR_GEN, + CKM_RSA_PKCS, + // CKM_RSA_PKCS_PSS, + CKM_RSA_X_509, + CKM_SHA1_RSA_PKCS, + CKM_SHA256_RSA_PKCS, + // CKM_SHA384_RSA_PKCS, + CKM_SHA512_RSA_PKCS, + CKM_SHA1_RSA_PKCS_PSS, + CKM_SHA256_RSA_PKCS_PSS, + // CKM_SHA384_RSA_PKCS_PSS, + CKM_SHA256_RSA_PKCS_PSS, + CKM_EC_KEY_PAIR_GEN, + //CKM_ECDSA_KEY_PAIR_GEN, Same as CKM_EC_KEY_PAIR_GEN, deprecated in 2.11 + CKM_ECDSA, + CKM_ECDSA_SHA1, + CKM_ECDH1_DERIVE, + // CKM_ECDH1_COFACTOR_DERIVE, + CKM_SHA_1, + CKM_SHA256, + CKM_SHA384, + CKM_SHA512 + // SUPPORT FOR OATH? +}; +static const CK_ULONG token_mechanisms_num = sizeof(token_mechanisms) / sizeof(CK_MECHANISM_TYPE); -CK_UTF8CHAR_PTR YUBICO_get_slot_description(void) { - - return "YubiKey Virtual Reader"; - -} +CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len) { -CK_UTF8CHAR_PTR YUBICO_get_slot_manufacturer(void) { + if (strlen(slot_description) > len) + return CKR_BUFFER_TOO_SMALL; - return "Yubico"; + memcpy(str, slot_description, strlen(slot_description)); + return CKR_OK; } -CK_FLAGS YUBICO_get_slot_flags(void) { +CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len) { - return CKF_TOKEN_PRESENT | CKF_HW_SLOT; + if (strlen(slot_manufacturer) > len) + return CKR_BUFFER_TOO_SMALL; + + memcpy(str, slot_manufacturer, strlen(slot_manufacturer)); + return CKR_OK; } -CK_VERSION YUBICO_get_slot_version(CK_UTF8CHAR_PTR version, CK_ULONG len) { +CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags) { - CK_VERSION v = {1.0}; // Dummy value + *flags = slot_flags; + return CKR_OK; - return v; } -CK_UTF8CHAR_PTR YUBICO_get_token_label(void) { +CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version) { - return "YubiKey PIV"; + version->major = slot_version.major; + version->minor = slot_version.minor; + + return CKR_OK; } -CK_UTF8CHAR_PTR YUBICO_get_token_manufacturer(void) { +CK_RV YUBICO_get_token_label(CK_UTF8CHAR_PTR str, CK_ULONG len) { - return "Yubico"; + if (strlen(token_label) > len) + return CKR_BUFFER_TOO_SMALL; + + memcpy(str, token_label, strlen(token_label)); + return CKR_OK; } -CK_UTF8CHAR_PTR YUBICO_get_token_model(void) { +CK_RV YUBICO_get_token_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len) { - return "PRO"; + if (strlen(token_manufacturer) > len) + return CKR_BUFFER_TOO_SMALL; + + memcpy(str, token_manufacturer, strlen(token_manufacturer)); + return CKR_OK; } -CK_FLAGS YUBICO_get_token_flags(void) { +CK_RV YUBICO_get_token_model(CK_UTF8CHAR_PTR str, CK_ULONG len) { - return CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; + if (strlen(token_model) > len) + return CKR_BUFFER_TOO_SMALL; + + memcpy(str, token_model, strlen(token_model)); + return CKR_OK; } -CK_VERSION YUBICO_get_token_version(CK_UTF8CHAR_PTR version, CK_ULONG len) { +CK_RV YUBICO_get_token_flags(CK_FLAGS_PTR flags) { + + *flags = token_flags; + return CKR_OK; + +} + +CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG len, CK_VERSION_PTR version) { CK_VERSION v = {0, 0}; int i = 0; - while (i < len && version[i] != '.') { + while (i < len && v_str[i] != '.') { v.major *= 10; - v.major += version[i++] - '0'; + v.major += v_str[i++] - '0'; } i++; - while (i < len && version[i] != '.') { + while (i < len && v_str[i] != '.') { v.minor *= 10; - v.minor += version[i++] - '0'; + v.minor += v_str[i++] - '0'; } i++; - while (i < len && version[i] != '.') { + while (i < len && v_str[i] != '.') { v.minor *= 10; - v.minor += version[i++] - '0'; + v.minor += v_str[i++] - '0'; } - return v; + version->major = v.major; + version->minor = v.minor; + + return CKR_OK; } -CK_BYTE_PTR YUBICO_get_token_serial(void) { +CK_RV YUBICO_get_token_serial(CK_CHAR_PTR str, CK_ULONG len) { - return "1234"; + if (strlen(token_serial) > len) + return CKR_BUFFER_TOO_SMALL; + + memcpy(str, token_serial, strlen(token_serial)); + return CKR_OK; } + +CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num) { + + *num = token_mechanisms_num; + return CKR_OK; + +} + +/*CK_RV YUBICO_get_token_mechanisms(void) { + +}*/ diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index cdac771..aefeb4e 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -3,15 +3,16 @@ #include "pkcs11.h" -CK_UTF8CHAR_PTR YUBICO_get_slot_description(void); -CK_UTF8CHAR_PTR YUBICO_get_slot_manufacturer(void); -CK_FLAGS YUBICO_get_slot_flags(void); -CK_VERSION YUBICO_get_slot_version(CK_UTF8CHAR_PTR version, CK_ULONG len); -CK_UTF8CHAR_PTR YUBICO_get_token_label(void); -CK_UTF8CHAR_PTR YUBICO_get_token_manufacturer(void); -CK_UTF8CHAR_PTR YUBICO_get_token_model(void); -CK_FLAGS YUBICO_get_token_flags(void); -CK_CHAR_PTR YUBICO_get_token_serial(void); -CK_VERSION YUBICO_get_token_version(CK_UTF8CHAR_PTR version, CK_ULONG len); +CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags); +CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version); +CK_RV YUBICO_get_token_label(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_token_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_token_model(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_token_flags(CK_FLAGS_PTR flags); +CK_RV YUBICO_get_token_serial(CK_CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VERSION_PTR version); +CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num); #endif From b71cb628ea545fb2a93472f675ce69966ea904af Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 16 Jul 2015 17:52:54 +0200 Subject: [PATCH 031/134] Added mechanisms handling. --- ykcs11/utils.c | 5 ++++- ykcs11/vendors.c | 4 ++++ ykcs11/vendors.h | 5 ++++- ykcs11/ykcs11.c | 37 +++++++++++++++++++++++++----- ykcs11/yubico.c | 58 +++++++++++++++++++++++++++++++++++++++++++----- ykcs11/yubico.h | 2 ++ 6 files changed, 97 insertions(+), 14 deletions(-) diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 45acf8c..81dac8d 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -34,7 +34,10 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, // Unknown slot, just save what info we have memset(&slots[*n_slots].info, 0, sizeof(CK_SLOT_INFO)); memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); - strncpy(slots[*n_slots].info.slotDescription, p, strlen(p)); + if (strlen(p) <= sizeof(slots[*n_slots].info.slotDescription)) + strncpy(slots[*n_slots].info.slotDescription, p, strlen(p)); + else + strncpy(slots[*n_slots].info.slotDescription, p, sizeof(slots[*n_slots].info.slotDescription)); } else { vendor = get_vendor(slots[*n_slots].vid); diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index 36bc6dc..609453d 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -27,6 +27,8 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_version = YUBICO_get_token_version; v.get_token_serial = YUBICO_get_token_serial; v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; + v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; + v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; break; case UNKNOWN: @@ -42,6 +44,8 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_version = NULL; v.get_token_serial = NULL; v.get_token_mechanisms_num = NULL; + v.get_token_mechanism_list = NULL; + v.get_token_mechanism_info = NULL; } return v; diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index ab2a75a..ace8dee 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -19,7 +19,8 @@ typedef CK_RV (*get_t_flags_f)(CK_FLAGS_PTR); typedef CK_RV (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG, CK_VERSION_PTR); typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); -//typedef CK_RV (*get_t_mechanisms)(CK_); +typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); +typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); typedef struct { @@ -34,6 +35,8 @@ typedef struct { get_t_version_f get_token_version; get_t_serial_f get_token_serial; get_t_mechanisms_num_f get_token_mechanisms_num; + get_t_mechanism_list_f get_token_mechanism_list; + get_t_mechanism_info_f get_token_mechanism_info; } vendor_t; vendor_id_t get_vendor_id(char *vendor_name); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 163bc6a..271b4dd 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -74,9 +74,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; } - parse_readers(readers, len, slots, &n_slots, &n_slots_with_token); + if (parse_readers(readers, len, slots, &n_slots, &n_slots_with_token) != CK_TRUE) + CKR_FUNCTION_FAILED; + DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token)); + // TODO: FILL OUT INIT ARGS; + DOUT; return CKR_OK; } @@ -315,7 +319,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( { DIN; vendor_t vendor; - int i; CK_ULONG count; if (piv_state == NULL) { @@ -351,9 +354,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( return CKR_BUFFER_TOO_SMALL; } - for (i = 0; i < 3; i++) { - pMechanismList[i] = CKM_SHA_1; - } + if (vendor.get_token_mechanism_list(pMechanismList, *pulCount) != CKR_OK) + return CKR_FUNCTION_FAILED; DOUT; return CKR_OK; @@ -366,7 +368,30 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( ) { DIN; - DBG(("TODO!!!")); + vendor_t vendor; + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (slotID > n_slots || pInfo == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + if (slots[slotID].vid == UNKNOWN) { + DBG(("Slot %lu is tokenless/unsupported", slotID)); + return CKR_SLOT_ID_INVALID; + } + + // TODO: check more return values + // TODO: user NULL_PTR more for coherence + + vendor = get_vendor(slots[slotID].vid); // TODO: make a token field in slot_t ?; + + if (vendor.get_token_mechanism_info(type, pInfo) != CKR_OK) + return CKR_MECHANISM_INVALID; + + DOUT; return CKR_OK; } diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index 8b7d3c6..1004ace 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -4,6 +4,11 @@ #define YUBICO_MECHANISMS_NUM 5 +#define MIN_RSA_KEY_SIZE 1024 +#define MAX_RSA_KEY_SIZE 2048 +#define MIN_ECC_KEY_SIZE 256 +#define MAX_ECC_KEY_SIZE 384 + // TODO add a type in vendor_t for SLOT | READER static const CK_UTF8CHAR_PTR slot_description = "YubiKey Virtual Reader"; static const CK_UTF8CHAR_PTR slot_manufacturer = "Yubico"; @@ -14,7 +19,7 @@ static const CK_UTF8CHAR_PTR token_manufacturer = "Yubico"; static const CK_UTF8CHAR_PTR token_model = "YubiKey MODEL"; static const CK_FLAGS token_flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; static const CK_BYTE_PTR token_serial = "1234"; -static const CK_MECHANISM_TYPE token_mechanisms[] = { +static const CK_MECHANISM_TYPE token_mechanisms[] = { // KEEP ALIGNED WITH token_mechanism_infos CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, // CKM_RSA_PKCS_PSS, @@ -26,13 +31,11 @@ static const CK_MECHANISM_TYPE token_mechanisms[] = { CKM_SHA1_RSA_PKCS_PSS, CKM_SHA256_RSA_PKCS_PSS, // CKM_SHA384_RSA_PKCS_PSS, - CKM_SHA256_RSA_PKCS_PSS, + CKM_SHA512_RSA_PKCS_PSS, CKM_EC_KEY_PAIR_GEN, //CKM_ECDSA_KEY_PAIR_GEN, Same as CKM_EC_KEY_PAIR_GEN, deprecated in 2.11 CKM_ECDSA, CKM_ECDSA_SHA1, - CKM_ECDH1_DERIVE, - // CKM_ECDH1_COFACTOR_DERIVE, CKM_SHA_1, CKM_SHA256, CKM_SHA384, @@ -41,6 +44,29 @@ static const CK_MECHANISM_TYPE token_mechanisms[] = { }; static const CK_ULONG token_mechanisms_num = sizeof(token_mechanisms) / sizeof(CK_MECHANISM_TYPE); +static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH token_mechanisms + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_GENERATE_KEY_PAIR}, // CKM_RSA_PKCS_KEY_PAIR_GEN + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_DECRYPT | CKF_SIGN}, // CKM_RSA_PKCS + //{MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_RSA_PKCS_PSS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_DECRYPT | CKF_SIGN}, // CKM_RSA_X_509 + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA1_RSA_PKCS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA256_RSA_PKCS + //{MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA384_RSA_PKCS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA512_RSA_PKCS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA1_RSA_PKCS_PSS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA256_RSA_PKCS_PSS + //{, , }, // CKM_SHA384_RSA_PKCS_PSS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA512_RSA_PKCS_PSS + {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_GENERATE_KEY_PAIR}, // CKM_EC_KEY_PAIR_GEN + //{, , }, // CKM_ECDSA_KEY_PAIR_GEN Same as CKM_EC_KEY_PAIR_GEN deprecated in 2.11 + {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_ECDSA + {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_ECDSA_SHA1 + {0, 0, CKF_DIGEST}, // CKM_SHA_1 + {0, 0, CKF_DIGEST}, // CKM_SHA256 + {0, 0, CKF_DIGEST}, // CKM_SHA384 + {0, 0, CKF_DIGEST} // CKM_SHA512 +}; + CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len) { @@ -163,6 +189,26 @@ CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num) { } -/*CK_RV YUBICO_get_token_mechanisms(void) { +CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num) { -}*/ + if (token_mechanisms_num > num) + return CKR_BUFFER_TOO_SMALL; + + memcpy(mec, token_mechanisms, token_mechanisms_num * sizeof(CK_MECHANISM_TYPE)); + return CKR_OK; + +} + +CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info) { + + CK_ULONG i; + + for (i = 0; i < token_mechanisms_num; i++) + if (token_mechanisms[i] == mec) { + memcpy((CK_BYTE_PTR) info, (CK_BYTE_PTR) (token_mechanism_infos + i), sizeof(CK_MECHANISM_INFO)); + return CKR_OK; + } + + return CKR_MECHANISM_INVALID; + +} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index aefeb4e..c10500d 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -14,5 +14,7 @@ CK_RV YUBICO_get_token_flags(CK_FLAGS_PTR flags); CK_RV YUBICO_get_token_serial(CK_CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VERSION_PTR version); CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num); +CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num); +CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info); #endif From fa909fca30eaae706a31436f66dba00e267ec293 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 20 Jul 2015 17:04:39 +0200 Subject: [PATCH 032/134] Initial work to add object handling. --- ykcs11/Makefile.am | 1 + ykcs11/obj_types.h | 88 ++++++++++++++ ykcs11/objects.c | 281 +++++++++++++++++++++++++++++++++++++++++++++ ykcs11/objects.h | 12 ++ ykcs11/pkcs11t.h | 1 + ykcs11/utils.h | 2 +- ykcs11/vendors.c | 4 + ykcs11/vendors.h | 5 + ykcs11/ykcs11.c | 142 +++++++++++++++++++++-- ykcs11/yubico.c | 14 +++ ykcs11/yubico.h | 3 + 11 files changed, 543 insertions(+), 10 deletions(-) create mode 100644 ykcs11/obj_types.h create mode 100644 ykcs11/objects.c create mode 100644 ykcs11/objects.h diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index 22fbfea..f891949 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -36,6 +36,7 @@ lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map libykcs11_la_SOURCES += vendors.c vendor.h yubico.c yubico.h libykcs11_la_SOURCES += utils.h utils.c +libykcs11_la_SOURCES += obj_types.h objects.h objects.c #internal.h #libykcs11_la_SOURCES += error.c diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h new file mode 100644 index 0000000..0c58c4a --- /dev/null +++ b/ykcs11/obj_types.h @@ -0,0 +1,88 @@ +#ifndef OBJ_TYPES_H +#define OBJ_TYPES_H + +#include "pkcs11t.h" + +// TODO: this is mostly from OpenSC, how to give credit? +typedef enum { + PIV_OBJ_CCC = 0, // Card capability container + PIV_OBJ_CHUI, // Cardholder unique id + /* PIV_OBJ_UCHUI is not in new with 800-73-2 */ + PIV_OBJ_X509_PIV_AUTH, // PIV authentication + PIV_OBJ_CHF, // Cardholder fingerprints + PIV_OBJ_SEC_OBJ, // Security object + PIV_OBJ_CHFI, // Cardholder facial images + PIV_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_OBJ_X509_DS, // Certificate for digital signature + PIV_OBJ_X509_KM, // Certificate for key management + PIV_OBJ_PI, // Cardholder printed information + PIV_OBJ_DISCOVERY, // Discovery object + PIV_OBJ_HISTORY, // History object + PIV_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 + PIV_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 + PIV_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 + PIV_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 + PIV_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 + PIV_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 + PIV_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 + PIV_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 + PIV_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 + PIV_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 + PIV_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 + PIV_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 + PIV_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 + PIV_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 + PIV_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 + PIV_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 + PIV_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 + PIV_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 + PIV_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 + PIV_OBJ_RETIRED_X509_20, // Retired certificate for KM 20 + PIV_OBJ_IRIS_IMAGE, // Cardholder iris images + PIV_OBJ_BITGT, // Biometric information templates group template + PIV_OBJ_SM_SIGNER, // Secure messaging signer + PIV_OBJ_PC_REF_DATA, // Pairing code reference data + PIV_OBJ_9B03, // NON-STANDARD TODO: remove? + PIV_OBJ_9A06, // NON-STANDARD + PIV_OBJ_9C06, // NON-STANDARD + PIV_OBJ_9D06, // NON-STANDARD + PIV_OBJ_9E06, // NON-STANDARD + PIV_OBJ_8206, // NON-STANDARD + PIV_OBJ_8306, // NON-STANDARD + PIV_OBJ_8406, // NON-STANDARD + PIV_OBJ_8506, // NON-STANDARD + PIV_OBJ_8606, // NON-STANDARD + PIV_OBJ_8706, // NON-STANDARD + PIV_OBJ_8806, // NON-STANDARD + PIV_OBJ_8906, // NON-STANDARD + PIV_OBJ_8A06, // NON-STANDARD + PIV_OBJ_8B06, // NON-STANDARD + PIV_OBJ_8C06, // NON-STANDARD + PIV_OBJ_8D06, // NON-STANDARD + PIV_OBJ_8E06, // NON-STANDARD + PIV_OBJ_8F06, // NON-STANDARD + PIV_OBJ_9006, // NON-STANDARD + PIV_OBJ_9106, // NON-STANDARD + PIV_OBJ_9206, // NON-STANDARD + PIV_OBJ_9306, // NON-STANDARD + PIV_OBJ_9406, // NON-STANDARD + PIV_OBJ_9506, // NON-STANDARD + PIV_OBJ_LAST_ENUM +} piv_obj_id_t; + +#define PIV_OBJECT_TYPE_CERT 1 +#define PIV_OBJECT_TYPE_PUBKEY 2 +#define PIV_OBJECT_NOT_PRESENT 4 + +typedef struct { + //const CK_OBJECT_CLASS class; + piv_obj_id_t type; + const CK_CHAR_PTR name; // TODO: or utf8 + const CK_CHAR_PTR oid; + CK_BYTE tag_len; // TODO: or ulong? + CK_BYTE tag_value[3]; + CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed? + CK_ULONG flags; /* object has some internal object like a cert */ +} piv_obj_t; + +#endif diff --git a/ykcs11/objects.c b/ykcs11/objects.c new file mode 100644 index 0000000..e2e9678 --- /dev/null +++ b/ykcs11/objects.c @@ -0,0 +1,281 @@ +#include "objects.h" +#include +#include + +//TODO: this is mostly a snippet from OpenSC how to give credit? +/* Must be in order, and one per enumerated PIV_OBJ */ +static const piv_obj_t objects[] = { + { PIV_OBJ_CCC, "Card Capability Container", + "2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 0}, + { PIV_OBJ_CHUI, "Card Holder Unique Identifier", + "2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 0}, + { PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication", + "2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_CHF, "Card Holder Fingerprints", + "2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 0}, + { PIV_OBJ_SEC_OBJ, "Security Object", + "2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00", 0}, + { PIV_OBJ_CHFI, "Cardholder Facial Images", + "2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30", 0}, + { PIV_OBJ_X509_CARD_AUTH, "X.509 Certificate for Card Authentication", + "2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00", PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_X509_DS, "X.509 Certificate for Digital Signature", + "2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00", PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_X509_KM, "X.509 Certificate for Key Management", + "2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02", PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_PI, "Printed Information", + "2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 0}, + { PIV_OBJ_DISCOVERY, "Discovery Object", + "2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50", 0}, + { PIV_OBJ_HISTORY, "Key History Object", + "2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60", 0}, + +/* 800-73-3, 21 new objects, 20 history certificates */ + { PIV_OBJ_RETIRED_X509_1, "Retired X.509 Certificate for Key Management 1", + "2.16.840.1.101.3.7.2.16.1", 3, "\x5F\xC1\x0D", "\x10\x01", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_2, "Retired X.509 Certificate for Key Management 2", + "2.16.840.1.101.3.7.2.16.2", 3, "\x5F\xC1\x0E", "\x10\x02", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_3, "Retired X.509 Certificate for Key Management 3", + "2.16.840.1.101.3.7.2.16.3", 3, "\x5F\xC1\x0F", "\x10\x03", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_4, "Retired X.509 Certificate for Key Management 4", + "2.16.840.1.101.3.7.2.16.4", 3, "\x5F\xC1\x10", "\x10\x04", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_5, "Retired X.509 Certificate for Key Management 5", + "2.16.840.1.101.3.7.2.16.5", 3, "\x5F\xC1\x11", "\x10\x05", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_6, "Retired X.509 Certificate for Key Management 6", + "2.16.840.1.101.3.7.2.16.6", 3, "\x5F\xC1\x12", "\x10\x06", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_7, "Retired X.509 Certificate for Key Management 7", + "2.16.840.1.101.3.7.2.16.7", 3, "\x5F\xC1\x13", "\x10\x07", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_8, "Retired X.509 Certificate for Key Management 8", + "2.16.840.1.101.3.7.2.16.8", 3, "\x5F\xC1\x14", "\x10\x08", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_9, "Retired X.509 Certificate for Key Management 9", + "2.16.840.1.101.3.7.2.16.9", 3, "\x5F\xC1\x15", "\x10\x09", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_10, "Retired X.509 Certificate for Key Management 10", + "2.16.840.1.101.3.7.2.16.10", 3, "\x5F\xC1\x16", "\x10\x0A", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_11, "Retired X.509 Certificate for Key Management 11", + "2.16.840.1.101.3.7.2.16.11", 3, "\x5F\xC1\x17", "\x10\x0B", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_12, "Retired X.509 Certificate for Key Management 12", + "2.16.840.1.101.3.7.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_13, "Retired X.509 Certificate for Key Management 13", + "2.16.840.1.101.3.7.2.16.13", 3, "\x5F\xC1\x19", "\x10\x0D", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_14, "Retired X.509 Certificate for Key Management 14", + "2.16.840.1.101.3.7.2.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_15, "Retired X.509 Certificate for Key Management 15", + "2.16.840.1.101.3.7.2.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_16, "Retired X.509 Certificate for Key Management 16", + "2.16.840.1.101.3.7.2.16.16", 3, "\x5F\xC1\x1C", "\x10\x10", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_17, "Retired X.509 Certificate for Key Management 17", + "2.16.840.1.101.3.7.2.16.17", 3, "\x5F\xC1\x1D", "\x10\x11", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_18, "Retired X.509 Certificate for Key Management 18", + "2.16.840.1.101.3.7.2.16.18", 3, "\x5F\xC1\x1E", "\x10\x12", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_19, "Retired X.509 Certificate for Key Management 19", + "2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + { PIV_OBJ_RETIRED_X509_20, "Retired X.509 Certificate for Key Management 20", + "2.16.840.1.101.3.7.2.16.20", 3, "\x5F\xC1\x20", "\x10\x14", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + + { PIV_OBJ_IRIS_IMAGE, "Cardholder Iris Images", + "2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15", 0}, + { PIV_OBJ_BITGT, "Biometric Information Templates Group Template", + "2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16" }, + { PIV_OBJ_SM_SIGNER, "Secure Messaging Certificate Signer", + "2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17"}, + { PIV_OBJ_PC_REF_DATA, "Pairing Code Reference Data Container", + "2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"}, + +/* following not standard , to be used by piv-tool only for testing */ + { PIV_OBJ_9B03, "3DES-ECB ADM", + "2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 0}, + /* Only used when signing a cert req, usually from engine + * after piv-tool generated the key and saved the pub key + * to a file. Note RSA key can be 1024, 2048 or 3072 + * but still use the "9x06" name. + */ + { PIV_OBJ_9A06, "RSA 9A Pub key from last genkey", + "2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9C06, "Pub 9C key from last genkey", + "2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9D06, "Pub 9D key from last genkey", + "2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9E06, "Pub 9E key from last genkey", + "2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", PIV_OBJECT_TYPE_PUBKEY}, + + { PIV_OBJ_8206, "Pub 82 key ", + "2.16.840.1.101.3.7.2.9999.101", 2, "\x82\x06", "\x82\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8306, "Pub 83 key ", + "2.16.840.1.101.3.7.2.9999.102", 2, "\x83\x06", "\x83\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8406, "Pub 84 key ", + "2.16.840.1.101.3.7.2.9999.103", 2, "\x84\x06", "\x84\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8506, "Pub 85 key ", + "2.16.840.1.101.3.7.2.9999.104", 2, "\x85\x06", "\x85\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8606, "Pub 86 key ", + "2.16.840.1.101.3.7.2.9999.105", 2, "\x86\x06", "\x86\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8706, "Pub 87 key ", + "2.16.840.1.101.3.7.2.9999.106", 2, "\x87\x06", "\x87\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8806, "Pub 88 key ", + "2.16.840.1.101.3.7.2.9999.107", 2, "\x88\x06", "\x88\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8906, "Pub 89 key ", + "2.16.840.1.101.3.7.2.9999.108", 2, "\x89\x06", "\x89\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8A06, "Pub 8A key ", + "2.16.840.1.101.3.7.2.9999.109", 2, "\x8A\x06", "\x8A\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8B06, "Pub 8B key ", + "2.16.840.1.101.3.7.2.9999.110", 2, "\x8B\x06", "\x8B\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8C06, "Pub 8C key ", + "2.16.840.1.101.3.7.2.9999.111", 2, "\x8C\x06", "\x8C\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8D06, "Pub 8D key ", + "2.16.840.1.101.3.7.2.9999.112", 2, "\x8D\x06", "\x8D\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8E06, "Pub 8E key ", + "2.16.840.1.101.3.7.2.9999.113", 2, "\x8E\x06", "\x8E\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_8F06, "Pub 8F key ", + "2.16.840.1.101.3.7.2.9999.114", 2, "\x8F\x06", "\x8F\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9006, "Pub 90 key ", + "2.16.840.1.101.3.7.2.9999.115", 2, "\x90\x06", "\x90\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9106, "Pub 91 key ", + "2.16.840.1.101.3.7.2.9999.116", 2, "\x91\x06", "\x91\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9206, "Pub 92 key ", + "2.16.840.1.101.3.7.2.9999.117", 2, "\x92\x06", "\x92\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9306, "Pub 93 key ", + "2.16.840.1.101.3.7.2.9999.118", 2, "\x93\x06", "\x93\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9406, "Pub 94 key ", + "2.16.840.1.101.3.7.2.9999.119", 2, "\x94\x06", "\x94\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_9506, "Pub 95 key ", + "2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY}, + { PIV_OBJ_LAST_ENUM, "", "", 0, "", "", 0} +}; + +static const CK_ULONG n_objects = sizeof(objects) / sizeof(piv_obj_t); + +static CK_RV get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { + if ((objects[obj].flags & PIV_OBJECT_TYPE_PUBKEY)) + *class = CKO_PUBLIC_KEY; + else if ((objects[obj].flags & PIV_OBJECT_TYPE_CERT)) + *class = CKO_CERTIFICATE; + else + *class - CKO_DATA; // TODO: other possibilities? + return CKR_OK; +} + +static CK_RV get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { + strcpy(label, objects[obj].name); +} + +static CK_RV get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) { +// strcpy(oid, objects[obj].oid); + oid[0] = 0x2b; + oid[1] = 0x06; + oid[2] = 0x01; + oid[3] = 0x04; + oid[4] = 0x01; + oid[5] = 0x82; + oid[6] = 0x37; + oid[7] = 0x15; + oid[8] = 0x14; +} + + +CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { + fprintf(stderr, "FOR OBJECT %lu, I WANT ", obj); + CK_ULONG i; + + switch (template->type) { + case CKA_CLASS: + fprintf(stderr, "CLASS\n"); + get_object_class(obj, template->pValue); + return CKR_OK; + + case CKA_TOKEN: + //get_object + case CKA_PRIVATE: + template->ulValueLen = CK_UNAVAILABLE_INFORMATION; + return CKR_OK; + + case CKA_LABEL: + fprintf(stderr, "LABEL\n"); + get_object_label(obj, template->pValue); + return CKR_OK; + + case CKA_APPLICATION: + fprintf(stderr, "APPLICATION\n"); + get_object_label(obj, template->pValue); + return CKR_OK; + + case CKA_VALUE: + case CKA_OBJECT_ID: + fprintf(stderr, "OID\n!!!"); // TODO: this is a DER encoded byte array + + get_object_oid(obj, template->pValue); + template->ulValueLen = 9; + return CKR_OK; + + case CKA_CERTIFICATE_TYPE: + case CKA_ISSUER: + case CKA_SERIAL_NUMBER: + case CKA_KEY_TYPE: + fprintf(stderr, "Return the key type\n"); + return CKR_OK; + + case CKA_SUBJECT: + case CKA_ID: + case CKA_SENSITIVE: + case CKA_ENCRYPT: + case CKA_DECRYPT: + case CKA_WRAP: + case CKA_UNWRAP: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_DERIVE: + case CKA_START_DATE: + case CKA_END_DATE: + case CKA_MODULUS: + case CKA_MODULUS_BITS: + case CKA_PUBLIC_EXPONENT: + case CKA_PRIVATE_EXPONENT: + case CKA_PRIME_1: + case CKA_PRIME_2: + case CKA_EXPONENT_1: + case CKA_EXPONENT_2: + case CKA_COEFFICIENT: + case CKA_PRIME: + case CKA_SUBPRIME: + case CKA_BASE: + case CKA_VALUE_BITS: + case CKA_VALUE_LEN: + case CKA_EXTRACTABLE: + case CKA_LOCAL: + case CKA_NEVER_EXTRACTABLE: + case CKA_ALWAYS_SENSITIVE: + case CKA_MODIFIABLE: + fprintf(stderr, "MODIFIABLE\n"); + *((CK_ULONG_PTR)template->pValue) = CK_FALSE; + return CKR_OK; + case CKA_VENDOR_DEFINED: + default: + fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lu\n", template[0].type); + + return CKR_FUNCTION_FAILED; + } + + // Never reached + return CKR_FUNCTION_FAILED; + +} diff --git a/ykcs11/objects.h b/ykcs11/objects.h new file mode 100644 index 0000000..e7539ea --- /dev/null +++ b/ykcs11/objects.h @@ -0,0 +1,12 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + +#include "pkcs11t.h" +#include "obj_types.h" + +#include // TODO: delete + +CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); +//CK_RV get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class); + +#endif diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index ddb608e..3d10176 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -375,6 +375,7 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_LABEL 0x00000003 #define CKA_APPLICATION 0x00000010 #define CKA_VALUE 0x00000011 +#define CKA_OBJECT_ID 0x00000012 #define CKA_CERTIFICATE_TYPE 0x00000080 #define CKA_ISSUER 0x00000081 #define CKA_SERIAL_NUMBER 0x00000082 diff --git a/ykcs11/utils.h b/ykcs11/utils.h index 2e40461..804cef0 100644 --- a/ykcs11/utils.h +++ b/ykcs11/utils.h @@ -1,7 +1,7 @@ #ifndef UTILS_H #define UTILS_H -#include "pkcs11.h" +#include "pkcs11t.h" #include "vendors.h" typedef struct { diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index 609453d..b4fd55d 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -29,6 +29,8 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; + v.get_token_objects_num = YUBICO_get_token_objects_num; + v.get_token_object_list = YUBICO_get_token_object_list; break; case UNKNOWN: @@ -46,6 +48,8 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_mechanisms_num = NULL; v.get_token_mechanism_list = NULL; v.get_token_mechanism_info = NULL; + v.get_token_objects_num = NULL; + v.get_token_object_list = NULL; } return v; diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index ace8dee..73e00ac 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -2,6 +2,7 @@ #define VENDORS_H #include "pkcs11.h" +#include "objects.h" typedef enum { UNKNOWN = 0x00, @@ -21,6 +22,8 @@ typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); +typedef CK_RV (*get_t_objects_num_f)(CK_ULONG_PTR); +typedef CK_RV (*get_t_object_list_f)(piv_obj_id_t *, CK_ULONG); typedef struct { @@ -37,6 +40,8 @@ typedef struct { get_t_mechanisms_num_f get_token_mechanisms_num; get_t_mechanism_list_f get_token_mechanism_list; get_t_mechanism_info_f get_token_mechanism_info; + get_t_objects_num_f get_token_objects_num; + get_t_object_list_f get_token_object_list; } vendor_t; vendor_id_t get_vendor_id(char *vendor_name); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 271b4dd..9a977d4 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -12,7 +12,7 @@ } while (0) #define YKCS11_DBG 1 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 +#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" @@ -47,6 +47,25 @@ static CK_ULONG n_slots_with_token = 0; static CK_SESSION_HANDLE session = CK_INVALID_HANDLE; // TODO: support multiple sessions? static CK_SESSION_INFO session_info; +static struct { + CK_BBOOL active; + CK_ULONG idx; + CK_BBOOL all; + CK_OBJECT_CLASS class; +} find_obj; + +static piv_obj_id_t piv_objects[] = { // Mandatory PIV objects + PIV_OBJ_CCC, // Card capability container + PIV_OBJ_CHUI, // Cardholder unique id + PIV_OBJ_X509_PIV_AUTH, // PIV authentication + PIV_OBJ_CHF, // Cardholder fingerprints + PIV_OBJ_CHFI, // Cardholder facial images + PIV_OBJ_X509_DS, // Certificate for digital signature + PIV_OBJ_X509_KM, // Certificate for key management + PIV_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_OBJ_SEC_OBJ // Security object +}; + extern CK_FUNCTION_LIST function_list; // TODO: check all return values /* General Purpose */ @@ -79,8 +98,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token)); + find_obj.active = CK_FALSE; // TODO: FILL OUT INIT ARGS; - + DOUT; return CKR_OK; } @@ -369,7 +389,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( { DIN; vendor_t vendor; - + if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -391,7 +411,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( if (vendor.get_token_mechanism_info(type, pInfo) != CKR_OK) return CKR_MECHANISM_INVALID; - + DOUT; return CKR_OK; } @@ -712,7 +732,33 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (session != YKCS11_SESSION_ID) + return CKR_SESSION_CLOSED; + + if (hSession != session) + return CKR_SESSION_HANDLE_INVALID; + + if (pTemplate == NULL_PTR || ulCount == 0) + return CKR_ARGUMENTS_BAD; + + if (find_obj.active != CK_TRUE) + return CKR_OPERATION_NOT_INITIALIZED; + + if (pTemplate[0].pValue == NULL_PTR) { + DBG(("Just get size")); + pTemplate[0].ulValueLen = 1024; // TODO: get attribute size + DOUT; + return CKR_OK; + } + DBG(("Trying to get object %lx", hObject)); + DBG(("Type: 0x%lx Value: %lu Len: %lu", pTemplate[0].type, *((CK_ULONG_PTR)pTemplate[0].pValue), pTemplate[0].ulValueLen)); + // TODO: here for i in ulCount + return get_attribute(hObject, pTemplate); + DOUT; return CKR_OK; } @@ -737,11 +783,48 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( ) { DIN; - DBG(("TODO!!!")); + CK_ULONG i; + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (session != YKCS11_SESSION_ID) + return CKR_SESSION_CLOSED; + + if (hSession != session) + return CKR_SESSION_HANDLE_INVALID; + + if (find_obj.active == CK_TRUE) + return CKR_OPERATION_ACTIVE; + + if (ulCount == 0) { + DBG(("Find ALL the objects!")); + find_obj.active = CK_TRUE; + find_obj.all = CK_TRUE; + find_obj.idx = 0; + DOUT; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + DBG(("Initialized search for %lu objects", ulCount)); + + if (pTemplate == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + find_obj.active = CK_TRUE; + + for (i = 0; i < ulCount; i++) { + DBG(("Object %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); + + // if () + + } + + DOUT; return CKR_OK; } - +CK_ULONG bla = 1; // TODO: delete CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, @@ -750,7 +833,34 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (session != YKCS11_SESSION_ID) + return CKR_SESSION_CLOSED; + + if (hSession != session) + return CKR_SESSION_HANDLE_INVALID; + + if (phObject == NULL_PTR || + ulMaxObjectCount == 0 || + pulObjectCount == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + if (find_obj.active != CK_TRUE) + return CKR_OPERATION_NOT_INITIALIZED; + + DBG(("Can return %lu object(s)", ulMaxObjectCount)); + if (find_obj.all == CK_TRUE) { + // Trying to get all the objects, just return the next + //*phObject = piv_objects[find_obj.idx++]; + //*pulObjectCount = 1; + *phObject = piv_objects[bla]; + *pulObjectCount = bla--; + } + + DOUT; return CKR_OK; } @@ -760,7 +870,21 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (session != YKCS11_SESSION_ID) + return CKR_SESSION_CLOSED; + + if (hSession != session) + return CKR_SESSION_HANDLE_INVALID; + + if (find_obj.active != CK_TRUE) + return CKR_OPERATION_NOT_INITIALIZED; + + find_obj.active = CK_FALSE; + DOUT; return CKR_OK; } diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index 1004ace..dd968a4 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -67,6 +67,10 @@ static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH {0, 0, CKF_DIGEST} // CKM_SHA512 }; +static const piv_obj_id_t token_objects[] = { + +}; +static const CK_ULONG token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t); CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len) { @@ -212,3 +216,13 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P return CKR_MECHANISM_INVALID; } + +CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num) { + + *num = token_objects_num; + return CKR_OK; +} + +CK_RV YUBICO_get_token_object_list(piv_obj_id_t *obj, CK_ULONG len) { + +} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index c10500d..979c71e 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -2,6 +2,7 @@ #define YUBICO_H #include "pkcs11.h" +#include "obj_types.h" CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); @@ -16,5 +17,7 @@ CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VER CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num); CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num); CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info); +CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num); +CK_RV YUBICO_get_token_object_list(piv_obj_id_t * obj, CK_ULONG num); #endif From 7da7e8ab97664a03f77cabc760f1438fc84f80bb Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 21 Jul 2015 17:47:49 +0200 Subject: [PATCH 033/134] More object handling. --- ykcs11/obj_types.h | 14 +- ykcs11/objects.c | 515 +++++++++++++++++++++++++++------------------ ykcs11/pkcs11t.h | 1 + ykcs11/ykcs11.c | 33 ++- ykcs11/yubico.c | 40 +++- 5 files changed, 376 insertions(+), 227 deletions(-) diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 0c58c4a..7e9d83d 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -76,13 +76,13 @@ typedef enum { typedef struct { //const CK_OBJECT_CLASS class; - piv_obj_id_t type; - const CK_CHAR_PTR name; // TODO: or utf8 - const CK_CHAR_PTR oid; - CK_BYTE tag_len; // TODO: or ulong? - CK_BYTE tag_value[3]; - CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed? - CK_ULONG flags; /* object has some internal object like a cert */ + piv_obj_id_t type; + const char *name; // TODO: or utf8 + const char *oid; + CK_BYTE tag_len; // TODO: or ulong? + CK_BYTE tag_value[3]; + CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed? + CK_ULONG flags; /* object has some internal object like a cert */ } piv_obj_t; #endif diff --git a/ykcs11/objects.c b/ykcs11/objects.c index e2e9678..6b1e12d 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1,277 +1,376 @@ #include "objects.h" #include #include +#include //TODO: this is mostly a snippet from OpenSC how to give credit? /* Must be in order, and one per enumerated PIV_OBJ */ -static const piv_obj_t objects[] = { - { PIV_OBJ_CCC, "Card Capability Container", - "2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 0}, - { PIV_OBJ_CHUI, "Card Holder Unique Identifier", - "2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 0}, - { PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication", - "2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_CHF, "Card Holder Fingerprints", - "2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 0}, - { PIV_OBJ_SEC_OBJ, "Security Object", - "2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00", 0}, - { PIV_OBJ_CHFI, "Cardholder Facial Images", - "2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30", 0}, - { PIV_OBJ_X509_CARD_AUTH, "X.509 Certificate for Card Authentication", - "2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00", PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_X509_DS, "X.509 Certificate for Digital Signature", - "2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00", PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_X509_KM, "X.509 Certificate for Key Management", - "2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02", PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_PI, "Printed Information", - "2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 0}, - { PIV_OBJ_DISCOVERY, "Discovery Object", - "2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50", 0}, - { PIV_OBJ_HISTORY, "Key History Object", - "2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60", 0}, +static piv_obj_t objects[] = { + {PIV_OBJ_CCC, "Card Capability Container", + "2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 0}, + {PIV_OBJ_CHUI, "Card Holder Unique Identifier", + "2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 0}, + {PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication", + "2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_CHF, "Card Holder Fingerprints", + "2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 0}, + {PIV_OBJ_SEC_OBJ, "Security Object", + "2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00", 0}, + {PIV_OBJ_CHFI, "Cardholder Facial Images", + "2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30", 0}, + {PIV_OBJ_X509_CARD_AUTH, "X.509 Certificate for Card Authentication", + "2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00", PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_X509_DS, "X.509 Certificate for Digital Signature", + "2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00", PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_X509_KM, "X.509 Certificate for Key Management", + "2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02", PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_PI, "Printed Information", + "2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 0}, + {PIV_OBJ_DISCOVERY, "Discovery Object", + "2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50", 0}, + {PIV_OBJ_HISTORY, "Key History Object", + "2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60", 0}, /* 800-73-3, 21 new objects, 20 history certificates */ - { PIV_OBJ_RETIRED_X509_1, "Retired X.509 Certificate for Key Management 1", - "2.16.840.1.101.3.7.2.16.1", 3, "\x5F\xC1\x0D", "\x10\x01", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_2, "Retired X.509 Certificate for Key Management 2", - "2.16.840.1.101.3.7.2.16.2", 3, "\x5F\xC1\x0E", "\x10\x02", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_3, "Retired X.509 Certificate for Key Management 3", - "2.16.840.1.101.3.7.2.16.3", 3, "\x5F\xC1\x0F", "\x10\x03", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_4, "Retired X.509 Certificate for Key Management 4", - "2.16.840.1.101.3.7.2.16.4", 3, "\x5F\xC1\x10", "\x10\x04", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_5, "Retired X.509 Certificate for Key Management 5", - "2.16.840.1.101.3.7.2.16.5", 3, "\x5F\xC1\x11", "\x10\x05", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_6, "Retired X.509 Certificate for Key Management 6", - "2.16.840.1.101.3.7.2.16.6", 3, "\x5F\xC1\x12", "\x10\x06", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_7, "Retired X.509 Certificate for Key Management 7", - "2.16.840.1.101.3.7.2.16.7", 3, "\x5F\xC1\x13", "\x10\x07", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_8, "Retired X.509 Certificate for Key Management 8", - "2.16.840.1.101.3.7.2.16.8", 3, "\x5F\xC1\x14", "\x10\x08", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_9, "Retired X.509 Certificate for Key Management 9", - "2.16.840.1.101.3.7.2.16.9", 3, "\x5F\xC1\x15", "\x10\x09", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_10, "Retired X.509 Certificate for Key Management 10", - "2.16.840.1.101.3.7.2.16.10", 3, "\x5F\xC1\x16", "\x10\x0A", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_11, "Retired X.509 Certificate for Key Management 11", - "2.16.840.1.101.3.7.2.16.11", 3, "\x5F\xC1\x17", "\x10\x0B", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_12, "Retired X.509 Certificate for Key Management 12", - "2.16.840.1.101.3.7.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_13, "Retired X.509 Certificate for Key Management 13", - "2.16.840.1.101.3.7.2.16.13", 3, "\x5F\xC1\x19", "\x10\x0D", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_14, "Retired X.509 Certificate for Key Management 14", - "2.16.840.1.101.3.7.2.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_15, "Retired X.509 Certificate for Key Management 15", - "2.16.840.1.101.3.7.2.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_16, "Retired X.509 Certificate for Key Management 16", - "2.16.840.1.101.3.7.2.16.16", 3, "\x5F\xC1\x1C", "\x10\x10", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_17, "Retired X.509 Certificate for Key Management 17", - "2.16.840.1.101.3.7.2.16.17", 3, "\x5F\xC1\x1D", "\x10\x11", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_18, "Retired X.509 Certificate for Key Management 18", - "2.16.840.1.101.3.7.2.16.18", 3, "\x5F\xC1\x1E", "\x10\x12", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_19, "Retired X.509 Certificate for Key Management 19", - "2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_RETIRED_X509_20, "Retired X.509 Certificate for Key Management 20", - "2.16.840.1.101.3.7.2.16.20", 3, "\x5F\xC1\x20", "\x10\x14", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_1, "Retired X.509 Certificate for Key Management 1", + "2.16.840.1.101.3.7.2.16.1", 3, "\x5F\xC1\x0D", "\x10\x01", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_2, "Retired X.509 Certificate for Key Management 2", + "2.16.840.1.101.3.7.2.16.2", 3, "\x5F\xC1\x0E", "\x10\x02", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_3, "Retired X.509 Certificate for Key Management 3", + "2.16.840.1.101.3.7.2.16.3", 3, "\x5F\xC1\x0F", "\x10\x03", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_4, "Retired X.509 Certificate for Key Management 4", + "2.16.840.1.101.3.7.2.16.4", 3, "\x5F\xC1\x10", "\x10\x04", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_5, "Retired X.509 Certificate for Key Management 5", + "2.16.840.1.101.3.7.2.16.5", 3, "\x5F\xC1\x11", "\x10\x05", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_6, "Retired X.509 Certificate for Key Management 6", + "2.16.840.1.101.3.7.2.16.6", 3, "\x5F\xC1\x12", "\x10\x06", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_7, "Retired X.509 Certificate for Key Management 7", + "2.16.840.1.101.3.7.2.16.7", 3, "\x5F\xC1\x13", "\x10\x07", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_8, "Retired X.509 Certificate for Key Management 8", + "2.16.840.1.101.3.7.2.16.8", 3, "\x5F\xC1\x14", "\x10\x08", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_9, "Retired X.509 Certificate for Key Management 9", + "2.16.840.1.101.3.7.2.16.9", 3, "\x5F\xC1\x15", "\x10\x09", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_10, "Retired X.509 Certificate for Key Management 10", + "2.16.840.1.101.3.7.2.16.10", 3, "\x5F\xC1\x16", "\x10\x0A", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_11, "Retired X.509 Certificate for Key Management 11", + "2.16.840.1.101.3.7.2.16.11", 3, "\x5F\xC1\x17", "\x10\x0B", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_12, "Retired X.509 Certificate for Key Management 12", + "2.16.840.1.101.3.7.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_13, "Retired X.509 Certificate for Key Management 13", + "2.16.840.1.101.3.7.2.16.13", 3, "\x5F\xC1\x19", "\x10\x0D", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_14, "Retired X.509 Certificate for Key Management 14", + "2.16.840.1.101.3.7.2.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_15, "Retired X.509 Certificate for Key Management 15", + "2.16.840.1.101.3.7.2.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_16, "Retired X.509 Certificate for Key Management 16", + "2.16.840.1.101.3.7.2.16.16", 3, "\x5F\xC1\x1C", "\x10\x10", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_17, "Retired X.509 Certificate for Key Management 17", + "2.16.840.1.101.3.7.2.16.17", 3, "\x5F\xC1\x1D", "\x10\x11", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_18, "Retired X.509 Certificate for Key Management 18", + "2.16.840.1.101.3.7.2.16.18", 3, "\x5F\xC1\x1E", "\x10\x12", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_19, "Retired X.509 Certificate for Key Management 19", + "2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, + {PIV_OBJ_RETIRED_X509_20, "Retired X.509 Certificate for Key Management 20", + "2.16.840.1.101.3.7.2.16.20", 3, "\x5F\xC1\x20", "\x10\x14", + PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - { PIV_OBJ_IRIS_IMAGE, "Cardholder Iris Images", - "2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15", 0}, - { PIV_OBJ_BITGT, "Biometric Information Templates Group Template", - "2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16" }, - { PIV_OBJ_SM_SIGNER, "Secure Messaging Certificate Signer", - "2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17"}, - { PIV_OBJ_PC_REF_DATA, "Pairing Code Reference Data Container", - "2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"}, + {PIV_OBJ_IRIS_IMAGE, "Cardholder Iris Images", + "2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15", 0}, + {PIV_OBJ_BITGT, "Biometric Information Templates Group Template", + "2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16", 0}, + {PIV_OBJ_SM_SIGNER, "Secure Messaging Certificate Signer", + "2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17", 0}, + {PIV_OBJ_PC_REF_DATA, "Pairing Code Reference Data Container", + "2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18", 0}, /* following not standard , to be used by piv-tool only for testing */ - { PIV_OBJ_9B03, "3DES-ECB ADM", - "2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 0}, + {PIV_OBJ_9B03, "3DES-ECB ADM", + "2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 0}, /* Only used when signing a cert req, usually from engine * after piv-tool generated the key and saved the pub key * to a file. Note RSA key can be 1024, 2048 or 3072 * but still use the "9x06" name. */ - { PIV_OBJ_9A06, "RSA 9A Pub key from last genkey", - "2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9C06, "Pub 9C key from last genkey", - "2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9D06, "Pub 9D key from last genkey", - "2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9E06, "Pub 9E key from last genkey", - "2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9A06, "RSA 9A Pub key from last genkey", + "2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9C06, "Pub 9C key from last genkey", + "2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9D06, "Pub 9D key from last genkey", + "2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9E06, "Pub 9E key from last genkey", + "2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8206, "Pub 82 key ", - "2.16.840.1.101.3.7.2.9999.101", 2, "\x82\x06", "\x82\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8306, "Pub 83 key ", - "2.16.840.1.101.3.7.2.9999.102", 2, "\x83\x06", "\x83\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8406, "Pub 84 key ", - "2.16.840.1.101.3.7.2.9999.103", 2, "\x84\x06", "\x84\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8506, "Pub 85 key ", - "2.16.840.1.101.3.7.2.9999.104", 2, "\x85\x06", "\x85\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8606, "Pub 86 key ", - "2.16.840.1.101.3.7.2.9999.105", 2, "\x86\x06", "\x86\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8706, "Pub 87 key ", - "2.16.840.1.101.3.7.2.9999.106", 2, "\x87\x06", "\x87\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8806, "Pub 88 key ", - "2.16.840.1.101.3.7.2.9999.107", 2, "\x88\x06", "\x88\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8906, "Pub 89 key ", - "2.16.840.1.101.3.7.2.9999.108", 2, "\x89\x06", "\x89\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8A06, "Pub 8A key ", - "2.16.840.1.101.3.7.2.9999.109", 2, "\x8A\x06", "\x8A\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8B06, "Pub 8B key ", - "2.16.840.1.101.3.7.2.9999.110", 2, "\x8B\x06", "\x8B\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8C06, "Pub 8C key ", - "2.16.840.1.101.3.7.2.9999.111", 2, "\x8C\x06", "\x8C\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8D06, "Pub 8D key ", - "2.16.840.1.101.3.7.2.9999.112", 2, "\x8D\x06", "\x8D\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8E06, "Pub 8E key ", - "2.16.840.1.101.3.7.2.9999.113", 2, "\x8E\x06", "\x8E\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_8F06, "Pub 8F key ", - "2.16.840.1.101.3.7.2.9999.114", 2, "\x8F\x06", "\x8F\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9006, "Pub 90 key ", - "2.16.840.1.101.3.7.2.9999.115", 2, "\x90\x06", "\x90\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9106, "Pub 91 key ", - "2.16.840.1.101.3.7.2.9999.116", 2, "\x91\x06", "\x91\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9206, "Pub 92 key ", - "2.16.840.1.101.3.7.2.9999.117", 2, "\x92\x06", "\x92\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9306, "Pub 93 key ", - "2.16.840.1.101.3.7.2.9999.118", 2, "\x93\x06", "\x93\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9406, "Pub 94 key ", - "2.16.840.1.101.3.7.2.9999.119", 2, "\x94\x06", "\x94\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_9506, "Pub 95 key ", - "2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY}, - { PIV_OBJ_LAST_ENUM, "", "", 0, "", "", 0} + {PIV_OBJ_8206, "Pub 82 key ", + "2.16.840.1.101.3.7.2.9999.101", 2, "\x82\x06", "\x82\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8306, "Pub 83 key ", + "2.16.840.1.101.3.7.2.9999.102", 2, "\x83\x06", "\x83\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8406, "Pub 84 key ", + "2.16.840.1.101.3.7.2.9999.103", 2, "\x84\x06", "\x84\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8506, "Pub 85 key ", + "2.16.840.1.101.3.7.2.9999.104", 2, "\x85\x06", "\x85\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8606, "Pub 86 key ", + "2.16.840.1.101.3.7.2.9999.105", 2, "\x86\x06", "\x86\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8706, "Pub 87 key ", + "2.16.840.1.101.3.7.2.9999.106", 2, "\x87\x06", "\x87\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8806, "Pub 88 key ", + "2.16.840.1.101.3.7.2.9999.107", 2, "\x88\x06", "\x88\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8906, "Pub 89 key ", + "2.16.840.1.101.3.7.2.9999.108", 2, "\x89\x06", "\x89\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8A06, "Pub 8A key ", + "2.16.840.1.101.3.7.2.9999.109", 2, "\x8A\x06", "\x8A\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8B06, "Pub 8B key ", + "2.16.840.1.101.3.7.2.9999.110", 2, "\x8B\x06", "\x8B\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8C06, "Pub 8C key ", + "2.16.840.1.101.3.7.2.9999.111", 2, "\x8C\x06", "\x8C\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8D06, "Pub 8D key ", + "2.16.840.1.101.3.7.2.9999.112", 2, "\x8D\x06", "\x8D\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8E06, "Pub 8E key ", + "2.16.840.1.101.3.7.2.9999.113", 2, "\x8E\x06", "\x8E\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_8F06, "Pub 8F key ", + "2.16.840.1.101.3.7.2.9999.114", 2, "\x8F\x06", "\x8F\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9006, "Pub 90 key ", + "2.16.840.1.101.3.7.2.9999.115", 2, "\x90\x06", "\x90\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9106, "Pub 91 key ", + "2.16.840.1.101.3.7.2.9999.116", 2, "\x91\x06", "\x91\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9206, "Pub 92 key ", + "2.16.840.1.101.3.7.2.9999.117", 2, "\x92\x06", "\x92\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9306, "Pub 93 key ", + "2.16.840.1.101.3.7.2.9999.118", 2, "\x93\x06", "\x93\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9406, "Pub 94 key ", + "2.16.840.1.101.3.7.2.9999.119", 2, "\x94\x06", "\x94\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_9506, "Pub 95 key ", + "2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY}, + {PIV_OBJ_LAST_ENUM, "", "", 0, "", "", 0} }; static const CK_ULONG n_objects = sizeof(objects) / sizeof(piv_obj_t); -static CK_RV get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { +static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { if ((objects[obj].flags & PIV_OBJECT_TYPE_PUBKEY)) *class = CKO_PUBLIC_KEY; else if ((objects[obj].flags & PIV_OBJECT_TYPE_CERT)) *class = CKO_CERTIFICATE; else - *class - CKO_DATA; // TODO: other possibilities? - return CKR_OK; + *class = CKO_DATA; // TODO: other possibilities? } -static CK_RV get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { - strcpy(label, objects[obj].name); +static void get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { + strcpy((char *)label, objects[obj].name); } -static CK_RV get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) { -// strcpy(oid, objects[obj].oid); - oid[0] = 0x2b; - oid[1] = 0x06; - oid[2] = 0x01; - oid[3] = 0x04; - oid[4] = 0x01; - oid[5] = 0x82; - oid[6] = 0x37; - oid[7] = 0x15; - oid[8] = 0x14; +// Next two functions based off the code at +// https://github.com/m9aertner/oidConverter/blob/master/oid.c +// TODO: how to give credit? +static void make_base128(unsigned long l, int first, CK_BYTE_PTR buf, CK_ULONG_PTR n) { + if (l > 127) + make_base128(l / 128, 0, buf, n); + + l %= 128; + + if (first) + buf[(*n)++] = (CK_BYTE)l; + else + buf[(*n)++] = 0x80 | (CK_BYTE)l; } +static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR len) { + CK_CHAR_PTR tmp = strdup((char *)oid); + CK_CHAR_PTR p = tmp; + CK_BYTE_PTR q = NULL; + CK_ULONG n = 0; + CK_BYTE b = 0; + CK_ULONG l = 0; + CK_ULONG nodes; + + q = p; + *len = 0; + nodes = 1; + while (*p != 0) { + if (*p == '.') + nodes++; + p++; + } + + n = 0; + b = 0; + p = q; + while (n < nodes) { + q = p; + while (*p != 0) { + if (*p == '.') + break; + p++; + } + + l = 0; + if (*p == '.') { + *p = 0; + l = (CK_ULONG) atoi((char *)q); + q = p + 1; + p = q; + } + else { + l = (CK_ULONG) atoi((char *)q); + q = p; + } + + /* Digit is in l. */ + if (n == 0) + b = 40 * ((CK_BYTE)l); + else if (n == 1) { + b += (CK_BYTE) l; + asn1_oid[(*len)++] = b; + } + else { + make_base128(l, 1, asn1_oid, len); + } + n++; + } + + free(tmp); +} + +static void get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) { + strcpy((char *)oid, objects[obj].oid); +} + +static void get_object_certificate_type(CK_OBJECT_HANDLE obj, CK_CERTIFICATE_TYPE_PTR type) { + if ((objects[obj].flags & PIV_OBJECT_TYPE_CERT)) + *type = CKC_X_509; +} + +static void get_object_key_id(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR key_id) { + memcpy((char *)key_id, objects[obj].containerid, 2); +} CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { fprintf(stderr, "FOR OBJECT %lu, I WANT ", obj); - CK_ULONG i; switch (template->type) { case CKA_CLASS: fprintf(stderr, "CLASS\n"); - get_object_class(obj, template->pValue); + if (template->pValue == NULL_PTR) // TODO: just don't use functions, break and check return later? + template->ulValueLen = 1; + else + get_object_class(obj, template->pValue); + return CKR_OK; - case CKA_TOKEN: - //get_object +// case CKA_TOKEN: case CKA_PRIVATE: + fprintf(stderr, "PRIVATE\n"); // TODO: check more template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_OK; case CKA_LABEL: fprintf(stderr, "LABEL\n"); - get_object_label(obj, template->pValue); + if (template->pValue == NULL_PTR) + template->ulValueLen = strlen(objects[obj].name); + else + strcpy((char *)template->pValue, objects[obj].name); return CKR_OK; case CKA_APPLICATION: fprintf(stderr, "APPLICATION\n"); - get_object_label(obj, template->pValue); + if (template->pValue == NULL_PTR) + template->ulValueLen = strlen(objects[obj].name); + else + strcpy((char *)template->pValue, objects[obj].name); return CKR_OK; - case CKA_VALUE: - case CKA_OBJECT_ID: - fprintf(stderr, "OID\n!!!"); // TODO: this is a DER encoded byte array - - get_object_oid(obj, template->pValue); - template->ulValueLen = 9; +// case CKA_VALUE: + case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? + fprintf(stderr, "OID\n"); + if (template->pValue == NULL_PTR) + template->ulValueLen = strlen(objects[obj].oid) * 2; // Slightly oversized + else { + strcpy((char *)template->pValue, objects[obj].oid); + asn1_encode_oid(template->pValue, template->pValue, &template->ulValueLen); + } return CKR_OK; case CKA_CERTIFICATE_TYPE: - case CKA_ISSUER: - case CKA_SERIAL_NUMBER: + fprintf(stderr, "CERTIFICATE TYPE\n"); + if (template->pValue == NULL_PTR) + template->ulValueLen = 1; + else + *((CK_ULONG_PTR)template->pValue) = CKC_X_509; // Support only X.509 certs + return CKR_OK; +// case CKA_ISSUER: +// case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: - fprintf(stderr, "Return the key type\n"); + fprintf(stderr, "Return the key type TODO!!!\n"); return CKR_OK; - case CKA_SUBJECT: + /* case CKA_SUBJECT: */ case CKA_ID: - case CKA_SENSITIVE: - case CKA_ENCRYPT: - case CKA_DECRYPT: - case CKA_WRAP: - case CKA_UNWRAP: - case CKA_SIGN: - case CKA_SIGN_RECOVER: - case CKA_VERIFY: - case CKA_VERIFY_RECOVER: - case CKA_DERIVE: - case CKA_START_DATE: - case CKA_END_DATE: - case CKA_MODULUS: - case CKA_MODULUS_BITS: - case CKA_PUBLIC_EXPONENT: - case CKA_PRIVATE_EXPONENT: - case CKA_PRIME_1: - case CKA_PRIME_2: - case CKA_EXPONENT_1: - case CKA_EXPONENT_2: - case CKA_COEFFICIENT: - case CKA_PRIME: - case CKA_SUBPRIME: - case CKA_BASE: - case CKA_VALUE_BITS: - case CKA_VALUE_LEN: - case CKA_EXTRACTABLE: - case CKA_LOCAL: - case CKA_NEVER_EXTRACTABLE: - case CKA_ALWAYS_SENSITIVE: + fprintf(stderr, "KEY ID\n"); + if (template->pValue == NULL_PTR) + template->ulValueLen = 2; + else + memcpy((char *)template->pValue, objects[obj].containerid, 2); + return CKR_OK; + /* case CKA_SENSITIVE: */ + /* case CKA_ENCRYPT: */ + /* case CKA_DECRYPT: */ + /* case CKA_WRAP: */ + /* case CKA_UNWRAP: */ + /* case CKA_SIGN: */ + /* case CKA_SIGN_RECOVER: */ + /* case CKA_VERIFY: */ + /* case CKA_VERIFY_RECOVER: */ + /* case CKA_DERIVE: */ + /* case CKA_START_DATE: */ + /* case CKA_END_DATE: */ + /* case CKA_MODULUS: */ + /* case CKA_MODULUS_BITS: */ + /* case CKA_PUBLIC_EXPONENT: */ + /* case CKA_PRIVATE_EXPONENT: */ + /* case CKA_PRIME_1: */ + /* case CKA_PRIME_2: */ + /* case CKA_EXPONENT_1: */ + /* case CKA_EXPONENT_2: */ + /* case CKA_COEFFICIENT: */ + /* case CKA_PRIME: */ + /* case CKA_SUBPRIME: */ + /* case CKA_BASE: */ + /* case CKA_VALUE_BITS: */ + /* case CKA_VALUE_LEN: */ + /* case CKA_EXTRACTABLE: */ + /* case CKA_LOCAL: */ + /* case CKA_NEVER_EXTRACTABLE: */ + /* case CKA_ALWAYS_SENSITIVE: */ case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); + if (template->pValue == NULL_PTR) + template->ulValueLen = 1; + else *((CK_ULONG_PTR)template->pValue) = CK_FALSE; return CKR_OK; + case CKA_VENDOR_DEFINED: default: - fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lu\n", template[0].type); - + fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); + template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_FUNCTION_FAILED; } diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index 3d10176..6808b3f 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -356,6 +356,7 @@ typedef CK_ULONG CK_KEY_TYPE; /* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG * for v2.0 */ typedef CK_ULONG CK_CERTIFICATE_TYPE; +typedef CK_CERTIFICATE_TYPE CK_PTR CK_CERTIFICATE_TYPE_PTR; /* The following certificate types are defined: */ #define CKC_X_509 0x00000000 diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 9a977d4..4e83a0f 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -11,7 +11,7 @@ printf ("\n"); \ } while (0) -#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DBG 0 // General debug, must be either 1 or 0 #define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" @@ -49,6 +49,7 @@ static CK_SESSION_INFO session_info; static struct { CK_BBOOL active; + CK_ULONG num; CK_ULONG idx; CK_BBOOL all; CK_OBJECT_CLASS class; @@ -750,7 +751,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( if (pTemplate[0].pValue == NULL_PTR) { DBG(("Just get size")); - pTemplate[0].ulValueLen = 1024; // TODO: get attribute size + get_attribute(hObject, pTemplate); // TODO: get attribute size DOUT; return CKR_OK; } @@ -784,6 +785,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( { DIN; CK_ULONG i; + vendor_t vendor; if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -792,16 +794,23 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( return CKR_SESSION_CLOSED; if (hSession != session) - return CKR_SESSION_HANDLE_INVALID; + return CKR_SESSION_HANDLE_INVALID; // TODO: or session closed? if (find_obj.active == CK_TRUE) return CKR_OPERATION_ACTIVE; + if (slots[session_info.slotID].vid == UNKNOWN) { + DBG(("Slot %lu is tokenless/unsupported", slotID)); + return CKR_SLOT_ID_INVALID; + } + vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?; + if (ulCount == 0) { DBG(("Find ALL the objects!")); find_obj.active = CK_TRUE; - find_obj.all = CK_TRUE; + vendor.get_token_objects_num(&find_obj.num); find_obj.idx = 0; + find_obj.all = CK_TRUE; DOUT; return CKR_OK; } @@ -824,7 +833,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( DOUT; return CKR_OK; } -CK_ULONG bla = 1; // TODO: delete + CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, @@ -853,11 +862,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( DBG(("Can return %lu object(s)", ulMaxObjectCount)); if (find_obj.all == CK_TRUE) { - // Trying to get all the objects, just return the next - //*phObject = piv_objects[find_obj.idx++]; - //*pulObjectCount = 1; - *phObject = piv_objects[bla]; - *pulObjectCount = bla--; + // Trying to get all the objects, just return the next one + if (find_obj.idx == find_obj.num) { + *pulObjectCount = 0; + DOUT; + return CKR_OK; + } + + *phObject = piv_objects[find_obj.idx++]; + *pulObjectCount = 1; } diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index dd968a4..f3c25f5 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -67,8 +67,43 @@ static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH {0, 0, CKF_DIGEST} // CKM_SHA512 }; -static const piv_obj_id_t token_objects[] = { - +static const piv_obj_id_t token_objects[] = { // TODO: is there a way to get this from the token? + PIV_OBJ_CCC, // Card capability container + PIV_OBJ_CHUI, // Cardholder unique id + PIV_OBJ_X509_PIV_AUTH, // PIV authentication + PIV_OBJ_CHF, // Cardholder fingerprints + PIV_OBJ_SEC_OBJ, // Security object + PIV_OBJ_CHFI, // Cardholder facial images + PIV_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_OBJ_X509_DS, // Certificate for digital signature + PIV_OBJ_X509_KM, // Certificate for key management + //PIV_OBJ_PI, // Cardholder printed information + //PIV_OBJ_DISCOVERY, // Discovery object + //PIV_OBJ_HISTORY, // History object +/* PIV_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 + PIV_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 + PIV_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 + PIV_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 + PIV_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 + PIV_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 + PIV_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 + PIV_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 + PIV_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 + PIV_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 + PIV_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 + PIV_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 + PIV_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 + PIV_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 + PIV_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 + PIV_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 + PIV_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 + PIV_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 + PIV_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 + PIV_OBJ_RETIRED_X509_20, // Retired certificate for KM 20*/ + //PIV_OBJ_IRIS_IMAGE, // Cardholder iris images + //PIV_OBJ_BITGT, // Biometric information templates group template + //PIV_OBJ_SM_SIGNER, // Secure messaging signer + //PIV_OBJ_PC_REF_DATA, // Pairing code reference data }; static const CK_ULONG token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t); @@ -220,6 +255,7 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num) { *num = token_objects_num; + //fprintf("TIENI %lu\n", token_objects_num); return CKR_OK; } From 91d7e52b2120ab065f2e7a5e8c5c372bc4746244 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 22 Jul 2015 14:39:19 +0200 Subject: [PATCH 034/134] Refined get attribute value. --- ykcs11/objects.c | 90 +++++++++++++++++++++++++----------------------- ykcs11/ykcs11.c | 4 +-- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 6b1e12d..7b32763 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -173,9 +173,10 @@ static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { *class = CKO_DATA; // TODO: other possibilities? } -static void get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { +/*static void get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { strcpy((char *)label, objects[obj].name); } +*/ // Next two functions based off the code at // https://github.com/m9aertner/oidConverter/blob/master/oid.c @@ -249,7 +250,7 @@ static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR free(tmp); } -static void get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) { +/*static void get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) { strcpy((char *)oid, objects[obj].oid); } @@ -261,19 +262,21 @@ static void get_object_certificate_type(CK_OBJECT_HANDLE obj, CK_CERTIFICATE_TYP static void get_object_key_id(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR key_id) { memcpy((char *)key_id, objects[obj].containerid, 2); } +*/ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { + CK_BYTE_PTR data; + CK_BYTE tmp[64]; + CK_ULONG len = 0; fprintf(stderr, "FOR OBJECT %lu, I WANT ", obj); switch (template->type) { case CKA_CLASS: fprintf(stderr, "CLASS\n"); - if (template->pValue == NULL_PTR) // TODO: just don't use functions, break and check return later? - template->ulValueLen = 1; - else - get_object_class(obj, template->pValue); - - return CKR_OK; + len = 1; + get_object_class(obj, (CK_OBJECT_CLASS_PTR)tmp); + data = tmp; + break; // case CKA_TOKEN: case CKA_PRIVATE: @@ -283,38 +286,31 @@ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: fprintf(stderr, "LABEL\n"); - if (template->pValue == NULL_PTR) - template->ulValueLen = strlen(objects[obj].name); - else - strcpy((char *)template->pValue, objects[obj].name); - return CKR_OK; + len = strlen(objects[obj].name) + 1; + data = objects[obj].name; + break; case CKA_APPLICATION: fprintf(stderr, "APPLICATION\n"); - if (template->pValue == NULL_PTR) - template->ulValueLen = strlen(objects[obj].name); - else - strcpy((char *)template->pValue, objects[obj].name); - return CKR_OK; + len = strlen(objects[obj].name) + 1; + data = objects[obj].name; + break; // case CKA_VALUE: case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? fprintf(stderr, "OID\n"); - if (template->pValue == NULL_PTR) - template->ulValueLen = strlen(objects[obj].oid) * 2; // Slightly oversized - else { - strcpy((char *)template->pValue, objects[obj].oid); - asn1_encode_oid(template->pValue, template->pValue, &template->ulValueLen); - } - return CKR_OK; + strcpy((char *)tmp, objects[obj].oid); + asn1_encode_oid(tmp, tmp, &len); + data = tmp; + break; case CKA_CERTIFICATE_TYPE: fprintf(stderr, "CERTIFICATE TYPE\n"); - if (template->pValue == NULL_PTR) - template->ulValueLen = 1; - else - *((CK_ULONG_PTR)template->pValue) = CKC_X_509; // Support only X.509 certs - return CKR_OK; + len = 1; + tmp[0] = CKC_X_509; // Support only X.509 certs + data = tmp; + break; + // case CKA_ISSUER: // case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: @@ -324,11 +320,10 @@ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* case CKA_SUBJECT: */ case CKA_ID: fprintf(stderr, "KEY ID\n"); - if (template->pValue == NULL_PTR) - template->ulValueLen = 2; - else - memcpy((char *)template->pValue, objects[obj].containerid, 2); - return CKR_OK; + len = 2; + data = objects[obj].containerid; + break; + /* case CKA_SENSITIVE: */ /* case CKA_ENCRYPT: */ /* case CKA_DECRYPT: */ @@ -361,20 +356,29 @@ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* case CKA_ALWAYS_SENSITIVE: */ case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); - if (template->pValue == NULL_PTR) - template->ulValueLen = 1; - else - *((CK_ULONG_PTR)template->pValue) = CK_FALSE; - return CKR_OK; + len = 1; + tmp[0] = CK_FALSE; + data = tmp; + break; case CKA_VENDOR_DEFINED: default: fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; - return CKR_FUNCTION_FAILED; + return CKR_ATTRIBUTE_TYPE_INVALID; } - // Never reached - return CKR_FUNCTION_FAILED; + if (template->pValue == NULL_PTR) { + template->ulValueLen = len; // TODO: define? + return CKR_OK; + } + + if (template->ulValueLen < len) + return CKR_BUFFER_TOO_SMALL; + + template->ulValueLen = len; + memcpy(template->pValue, data, len); + + return CKR_OK; } diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 4e83a0f..6541352 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -11,7 +11,7 @@ printf ("\n"); \ } while (0) -#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 YKCS11_MANUFACTURER "Yubico (www.yubico.com)" @@ -800,7 +800,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( return CKR_OPERATION_ACTIVE; if (slots[session_info.slotID].vid == UNKNOWN) { - DBG(("Slot %lu is tokenless/unsupported", slotID)); + DBG(("Slot %lu is tokenless/unsupported", session_info.slotID)); return CKR_SLOT_ID_INVALID; } vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?; From b9268982a5a75b8e50b6084b7133a9ffb522a79a Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 24 Jul 2015 15:39:37 +0200 Subject: [PATCH 035/134] Refactor more. --- ykcs11/obj_types.h | 163 +++++++++++++----------- ykcs11/objects.c | 300 ++++++++++++++++++++++++--------------------- ykcs11/vendors.c | 4 +- ykcs11/vendors.h | 7 +- ykcs11/ykcs11.c | 122 ++++++++++++------ ykcs11/yubico.c | 132 +++++++++++++------- ykcs11/yubico.h | 5 +- 7 files changed, 434 insertions(+), 299 deletions(-) diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 7e9d83d..5e8aa4b 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -5,84 +5,103 @@ // TODO: this is mostly from OpenSC, how to give credit? typedef enum { - PIV_OBJ_CCC = 0, // Card capability container - PIV_OBJ_CHUI, // Cardholder unique id - /* PIV_OBJ_UCHUI is not in new with 800-73-2 */ - PIV_OBJ_X509_PIV_AUTH, // PIV authentication - PIV_OBJ_CHF, // Cardholder fingerprints - PIV_OBJ_SEC_OBJ, // Security object - PIV_OBJ_CHFI, // Cardholder facial images - PIV_OBJ_X509_CARD_AUTH, // Certificate for card authentication - PIV_OBJ_X509_DS, // Certificate for digital signature - PIV_OBJ_X509_KM, // Certificate for key management - PIV_OBJ_PI, // Cardholder printed information - PIV_OBJ_DISCOVERY, // Discovery object - PIV_OBJ_HISTORY, // History object - PIV_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 - PIV_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 - PIV_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 - PIV_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 - PIV_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 - PIV_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 - PIV_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 - PIV_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 - PIV_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 - PIV_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 - PIV_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 - PIV_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 - PIV_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 - PIV_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 - PIV_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 - PIV_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 - PIV_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 - PIV_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 - PIV_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 - PIV_OBJ_RETIRED_X509_20, // Retired certificate for KM 20 - PIV_OBJ_IRIS_IMAGE, // Cardholder iris images - PIV_OBJ_BITGT, // Biometric information templates group template - PIV_OBJ_SM_SIGNER, // Secure messaging signer - PIV_OBJ_PC_REF_DATA, // Pairing code reference data - PIV_OBJ_9B03, // NON-STANDARD TODO: remove? - PIV_OBJ_9A06, // NON-STANDARD - PIV_OBJ_9C06, // NON-STANDARD - PIV_OBJ_9D06, // NON-STANDARD - PIV_OBJ_9E06, // NON-STANDARD - PIV_OBJ_8206, // NON-STANDARD - PIV_OBJ_8306, // NON-STANDARD - PIV_OBJ_8406, // NON-STANDARD - PIV_OBJ_8506, // NON-STANDARD - PIV_OBJ_8606, // NON-STANDARD - PIV_OBJ_8706, // NON-STANDARD - PIV_OBJ_8806, // NON-STANDARD - PIV_OBJ_8906, // NON-STANDARD - PIV_OBJ_8A06, // NON-STANDARD - PIV_OBJ_8B06, // NON-STANDARD - PIV_OBJ_8C06, // NON-STANDARD - PIV_OBJ_8D06, // NON-STANDARD - PIV_OBJ_8E06, // NON-STANDARD - PIV_OBJ_8F06, // NON-STANDARD - PIV_OBJ_9006, // NON-STANDARD - PIV_OBJ_9106, // NON-STANDARD - PIV_OBJ_9206, // NON-STANDARD - PIV_OBJ_9306, // NON-STANDARD - PIV_OBJ_9406, // NON-STANDARD - PIV_OBJ_9506, // NON-STANDARD - PIV_OBJ_LAST_ENUM + PIV_DATA_OBJ_CCC = 0, // Card capability container + PIV_DATA_OBJ_CHUI, // Cardholder unique id + /* PIV_DATA_OBJ_UCHUI is not in new with 800-73-2 */ + PIV_DATA_OBJ_X509_PIV_AUTH, // PIV authentication + PIV_DATA_OBJ_CHF, // Cardholder fingerprints + PIV_DATA_OBJ_SEC_OBJ, // Security object + PIV_DATA_OBJ_CHFI, // Cardholder facial images + PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_DATA_OBJ_X509_DS, // Certificate for digital signature + PIV_DATA_OBJ_X509_KM, // Certificate for key management + PIV_DATA_OBJ_PI, // Cardholder printed information + PIV_DATA_OBJ_DISCOVERY, // Discovery object + PIV_DATA_OBJ_HISTORY, // History object + PIV_DATA_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 + PIV_DATA_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 + PIV_DATA_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 + PIV_DATA_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 + PIV_DATA_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 + PIV_DATA_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 + PIV_DATA_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 + PIV_DATA_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 + PIV_DATA_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 + PIV_DATA_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 + PIV_DATA_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 + PIV_DATA_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 + PIV_DATA_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 + PIV_DATA_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 + PIV_DATA_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 + PIV_DATA_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 + PIV_DATA_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 + PIV_DATA_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 + PIV_DATA_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 + PIV_DATA_OBJ_RETIRED_X509_20, // Retired certificate for KM 20 + PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images + PIV_DATA_OBJ_BITGT, // Biometric information templates group template + PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer + PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data +/* PIV_DATA_OBJ_9B03, // NON-STANDARD TODO: remove? + PIV_DATA_OBJ_9A06, // NON-STANDARD + PIV_DATA_OBJ_9C06, // NON-STANDARD + PIV_DATA_OBJ_9D06, // NON-STANDARD + PIV_DATA_OBJ_9E06, // NON-STANDARD + PIV_DATA_OBJ_8206, // NON-STANDARD + PIV_DATA_OBJ_8306, // NON-STANDARD + PIV_DATA_OBJ_8406, // NON-STANDARD + PIV_DATA_OBJ_8506, // NON-STANDARD + PIV_DATA_OBJ_8606, // NON-STANDARD + PIV_DATA_OBJ_8706, // NON-STANDARD + PIV_DATA_OBJ_8806, // NON-STANDARD + PIV_DATA_OBJ_8906, // NON-STANDARD + PIV_DATA_OBJ_8A06, // NON-STANDARD + PIV_DATA_OBJ_8B06, // NON-STANDARD + PIV_DATA_OBJ_8C06, // NON-STANDARD + PIV_DATA_OBJ_8D06, // NON-STANDARD + PIV_DATA_OBJ_8E06, // NON-STANDARD + PIV_DATA_OBJ_8F06, // NON-STANDARD + PIV_DATA_OBJ_9006, // NON-STANDARD + PIV_DATA_OBJ_9106, // NON-STANDARD + PIV_DATA_OBJ_9206, // NON-STANDARD + PIV_DATA_OBJ_9306, // NON-STANDARD + PIV_DATA_OBJ_9406, // NON-STANDARD + PIV_DATA_OBJ_9506, // NON-STANDARD*/ + PIV_DATA_OBJ_LAST, + + PIV_CERT_OBJ_X509_PIV_AUTH, // PIV authentication + PIV_CERT_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_CERT_OBJ_X509_DS, // Certificate for digital signature + PIV_CERT_OBJ_X509_KM, // Certificate for key management + PIV_CERT_OBJ_LAST + // TODO: private keys? } piv_obj_id_t; -#define PIV_OBJECT_TYPE_CERT 1 + +/*#define PIV_OBJECT_TYPE_CERT 1 // TODO: redundant now? #define PIV_OBJECT_TYPE_PUBKEY 2 -#define PIV_OBJECT_NOT_PRESENT 4 +#define PIV_OBJECT_NOT_PRESENT 4*/ typedef struct { - //const CK_OBJECT_CLASS class; - piv_obj_id_t type; - const char *name; // TODO: or utf8 - const char *oid; + const char *oid; CK_BYTE tag_len; // TODO: or ulong? - CK_BYTE tag_value[3]; - CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed? - CK_ULONG flags; /* object has some internal object like a cert */ + CK_BYTE tag_value[3]; // TODO: needed? + CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed? +} piv_data_obj_t; + +typedef struct { + CK_BBOOL todo; +} piv_cert_obj_t; + +typedef struct { + piv_obj_id_t type; // TODO: technically redundant + CK_BBOOL token; // TODO: not used yet + CK_BBOOL private; + CK_BBOOL modifiable; + const char *label; + CK_BBOOL copyable; + CK_BBOOL destroyable; +CK_ULONG sub_id; } piv_obj_t; #endif diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 7b32763..5845d53 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -3,174 +3,196 @@ #include #include -//TODO: this is mostly a snippet from OpenSC how to give credit? +//TODO: this is mostly a snippet from OpenSC how to give credit? Less and less so now /* Must be in order, and one per enumerated PIV_OBJ */ static piv_obj_t objects[] = { - {PIV_OBJ_CCC, "Card Capability Container", - "2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 0}, - {PIV_OBJ_CHUI, "Card Holder Unique Identifier", - "2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 0}, - {PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication", - "2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_CHF, "Card Holder Fingerprints", - "2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 0}, - {PIV_OBJ_SEC_OBJ, "Security Object", - "2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00", 0}, - {PIV_OBJ_CHFI, "Cardholder Facial Images", - "2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30", 0}, - {PIV_OBJ_X509_CARD_AUTH, "X.509 Certificate for Card Authentication", - "2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00", PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_X509_DS, "X.509 Certificate for Digital Signature", - "2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00", PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_X509_KM, "X.509 Certificate for Key Management", - "2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02", PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_PI, "Printed Information", - "2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 0}, - {PIV_OBJ_DISCOVERY, "Discovery Object", - "2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50", 0}, - {PIV_OBJ_HISTORY, "Key History Object", - "2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60", 0}, + {PIV_DATA_OBJ_CCC, 0, 0, 0, "Card Capability Container", 0, 0, 0}, + {PIV_DATA_OBJ_CHUI, 0, 0, 0, "Card Holder Unique Identifier", 0, 0, 1}, + // PIV_DATA_OBJ_UCHUI + {PIV_DATA_OBJ_X509_PIV_AUTH, 0, 0, 0, "X.509 Certificate for PIV Authentication", 0, 0, 2}, + {PIV_DATA_OBJ_CHF, 0, 0, 0, "Card Holder Fingerprints", 0, 0, 3}, + {PIV_DATA_OBJ_SEC_OBJ, 0, 0, 0, "Security Object", 0, 0, 4}, + {PIV_DATA_OBJ_CHFI, 0, 0, 0, "Cardholder Facial Images", 0, 0, 5}, + {PIV_DATA_OBJ_X509_CARD_AUTH, 0, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, 6}, + {PIV_DATA_OBJ_X509_DS, 0, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, 7}, + {PIV_DATA_OBJ_X509_KM, 0, 0, 0, "X.509 Certificate for Key Management", 0, 0, 8}, + {PIV_DATA_OBJ_PI, 0, 0, 0, "Printed Information", 0, 0, 9}, + {PIV_DATA_OBJ_DISCOVERY, 0, 0, 0, "Discovery Object", 0, 0, 10}, + {PIV_DATA_OBJ_HISTORY, 0, 0, 0, "Key History Object", 0, 0, 11}, + {PIV_DATA_OBJ_RETIRED_X509_1, 0, 0, 0, "Retired X.509 Certificate for Key Management 1", 0, 0, 12}, + {PIV_DATA_OBJ_RETIRED_X509_2, 0, 0, 0, "Retired X.509 Certificate for Key Management 2", 0, 0, 13}, + {PIV_DATA_OBJ_RETIRED_X509_3, 0, 0, 0, "Retired X.509 Certificate for Key Management 3", 0, 0, 14}, + {PIV_DATA_OBJ_RETIRED_X509_4, 0, 0, 0, "Retired X.509 Certificate for Key Management 4", 0, 0, 15}, + {PIV_DATA_OBJ_RETIRED_X509_5, 0, 0, 0, "Retired X.509 Certificate for Key Management 5", 0, 0, 16}, + {PIV_DATA_OBJ_RETIRED_X509_6, 0, 0, 0, "Retired X.509 Certificate for Key Management 6", 0, 0, 17}, + {PIV_DATA_OBJ_RETIRED_X509_7, 0, 0, 0, "Retired X.509 Certificate for Key Management 7", 0, 0, 18}, + {PIV_DATA_OBJ_RETIRED_X509_8, 0, 0, 0, "Retired X.509 Certificate for Key Management 8", 0, 0, 19}, + {PIV_DATA_OBJ_RETIRED_X509_9, 0, 0, 0, "Retired X.509 Certificate for Key Management 9", 0, 0, 20}, + {PIV_DATA_OBJ_RETIRED_X509_10, 0, 0, 0, "Retired X.509 Certificate for Key Management 10", 0, 0, 21}, + {PIV_DATA_OBJ_RETIRED_X509_11, 0, 0, 0, "Retired X.509 Certificate for Key Management 11", 0, 0, 22}, + {PIV_DATA_OBJ_RETIRED_X509_12, 0, 0, 0, "Retired X.509 Certificate for Key Management 12", 0, 0, 23}, + {PIV_DATA_OBJ_RETIRED_X509_13, 0, 0, 0, "Retired X.509 Certificate for Key Management 13", 0, 0, 24}, + {PIV_DATA_OBJ_RETIRED_X509_14, 0, 0, 0, "Retired X.509 Certificate for Key Management 14", 0, 0, 25}, + {PIV_DATA_OBJ_RETIRED_X509_15, 0, 0, 0, "Retired X.509 Certificate for Key Management 15", 0, 0, 26}, + {PIV_DATA_OBJ_RETIRED_X509_16, 0, 0, 0, "Retired X.509 Certificate for Key Management 16", 0, 0, 27}, + {PIV_DATA_OBJ_RETIRED_X509_17, 0, 0, 0, "Retired X.509 Certificate for Key Management 17", 0, 0, 28}, + {PIV_DATA_OBJ_RETIRED_X509_18, 0, 0, 0, "Retired X.509 Certificate for Key Management 18", 0, 0, 29}, + {PIV_DATA_OBJ_RETIRED_X509_19, 0, 0, 0, "Retired X.509 Certificate for Key Management 19", 0, 0, 30}, + {PIV_DATA_OBJ_RETIRED_X509_20, 0, 0, 0, "Retired X.509 Certificate for Key Management 20", 0, 0, 31}, + {PIV_DATA_OBJ_IRIS_IMAGE, 0, 0, 0, "Cardholder Iris Images", 0, 0, 32}, + {PIV_DATA_OBJ_BITGT, 0, 0, 0, "Biometric Information Templates Group Template", 0, 0, 33}, + {PIV_DATA_OBJ_SM_SIGNER, 0, 0, 0, "Secure Messaging Certificate Signer", 0, 0, 34}, + {PIV_DATA_OBJ_PC_REF_DATA, 0, 0, 0, "Pairing Code Reference Data Container", 0, 0, 35}, +/* {PIV_DATA_OBJ_9B03, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9A06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9C06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9D06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9E06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8206, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8306, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8406, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8506, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8606, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8706, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8806, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8906, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8A06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8B06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8C06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8D06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8E06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_8F06, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9006, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9106, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9206, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9306, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9406, 0, 0, 0, "", 0, 0, }, + {PIV_DATA_OBJ_9506, 0, 0, 0, "", 0, 0, },*/ + {PIV_DATA_OBJ_LAST, 0, 0, 0, "", 0, 0, 36}, + {PIV_CERT_OBJ_X509_PIV_AUTH, 0, 0, 0, "X.509 Certificate for PIV Authentication", 0, 0, 0}, + {PIV_CERT_OBJ_X509_CARD_AUTH, 0, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, 1}, + {PIV_CERT_OBJ_X509_DS, 0, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, 2}, + {PIV_CERT_OBJ_X509_KM, 0, 0, 0, "X.509 Certificate for Key Management", 0, 0, 3}, + {PIV_CERT_OBJ_LAST, 0, 0, 0, "", 0, 41} +}; + +static piv_data_obj_t data_objects[] = { + {"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00"}, + {"2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00"}, + {"2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01"}, + {"2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10"}, + {"2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00"}, + {"2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30"}, + {"2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00"}, + {"2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00"}, + {"2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02"}, + {"2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01"}, + {"2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50"}, + {"2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60"}, /* 800-73-3, 21 new objects, 20 history certificates */ - {PIV_OBJ_RETIRED_X509_1, "Retired X.509 Certificate for Key Management 1", - "2.16.840.1.101.3.7.2.16.1", 3, "\x5F\xC1\x0D", "\x10\x01", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_2, "Retired X.509 Certificate for Key Management 2", - "2.16.840.1.101.3.7.2.16.2", 3, "\x5F\xC1\x0E", "\x10\x02", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_3, "Retired X.509 Certificate for Key Management 3", - "2.16.840.1.101.3.7.2.16.3", 3, "\x5F\xC1\x0F", "\x10\x03", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_4, "Retired X.509 Certificate for Key Management 4", - "2.16.840.1.101.3.7.2.16.4", 3, "\x5F\xC1\x10", "\x10\x04", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_5, "Retired X.509 Certificate for Key Management 5", - "2.16.840.1.101.3.7.2.16.5", 3, "\x5F\xC1\x11", "\x10\x05", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_6, "Retired X.509 Certificate for Key Management 6", - "2.16.840.1.101.3.7.2.16.6", 3, "\x5F\xC1\x12", "\x10\x06", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_7, "Retired X.509 Certificate for Key Management 7", - "2.16.840.1.101.3.7.2.16.7", 3, "\x5F\xC1\x13", "\x10\x07", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_8, "Retired X.509 Certificate for Key Management 8", - "2.16.840.1.101.3.7.2.16.8", 3, "\x5F\xC1\x14", "\x10\x08", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_9, "Retired X.509 Certificate for Key Management 9", - "2.16.840.1.101.3.7.2.16.9", 3, "\x5F\xC1\x15", "\x10\x09", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_10, "Retired X.509 Certificate for Key Management 10", - "2.16.840.1.101.3.7.2.16.10", 3, "\x5F\xC1\x16", "\x10\x0A", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_11, "Retired X.509 Certificate for Key Management 11", - "2.16.840.1.101.3.7.2.16.11", 3, "\x5F\xC1\x17", "\x10\x0B", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_12, "Retired X.509 Certificate for Key Management 12", - "2.16.840.1.101.3.7.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_13, "Retired X.509 Certificate for Key Management 13", - "2.16.840.1.101.3.7.2.16.13", 3, "\x5F\xC1\x19", "\x10\x0D", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_14, "Retired X.509 Certificate for Key Management 14", - "2.16.840.1.101.3.7.2.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_15, "Retired X.509 Certificate for Key Management 15", - "2.16.840.1.101.3.7.2.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_16, "Retired X.509 Certificate for Key Management 16", - "2.16.840.1.101.3.7.2.16.16", 3, "\x5F\xC1\x1C", "\x10\x10", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_17, "Retired X.509 Certificate for Key Management 17", - "2.16.840.1.101.3.7.2.16.17", 3, "\x5F\xC1\x1D", "\x10\x11", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_18, "Retired X.509 Certificate for Key Management 18", - "2.16.840.1.101.3.7.2.16.18", 3, "\x5F\xC1\x1E", "\x10\x12", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_19, "Retired X.509 Certificate for Key Management 19", - "2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - {PIV_OBJ_RETIRED_X509_20, "Retired X.509 Certificate for Key Management 20", - "2.16.840.1.101.3.7.2.16.20", 3, "\x5F\xC1\x20", "\x10\x14", - PIV_OBJECT_NOT_PRESENT|PIV_OBJECT_TYPE_CERT}, - - {PIV_OBJ_IRIS_IMAGE, "Cardholder Iris Images", - "2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15", 0}, - {PIV_OBJ_BITGT, "Biometric Information Templates Group Template", - "2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16", 0}, - {PIV_OBJ_SM_SIGNER, "Secure Messaging Certificate Signer", - "2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17", 0}, - {PIV_OBJ_PC_REF_DATA, "Pairing Code Reference Data Container", - "2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18", 0}, + {"2.16.840.1.101.3.7.2.16.1", 3, "\x5F\xC1\x0D", "\x10\x01"}, + {"2.16.840.1.101.3.7.2.16.2", 3, "\x5F\xC1\x0E", "\x10\x02"}, + {"2.16.840.1.101.3.7.2.16.3", 3, "\x5F\xC1\x0F", "\x10\x03"}, + {"2.16.840.1.101.3.7.2.16.4", 3, "\x5F\xC1\x10", "\x10\x04"}, + {"2.16.840.1.101.3.7.2.16.5", 3, "\x5F\xC1\x11", "\x10\x05"}, + {"2.16.840.1.101.3.7.2.16.7", 3, "\x5F\xC1\x13", "\x10\x07"}, + {"2.16.840.1.101.3.7.2.16.8", 3, "\x5F\xC1\x14", "\x10\x08"}, + {"2.16.840.1.101.3.7.2.16.9", 3, "\x5F\xC1\x15", "\x10\x09"}, + {"2.16.840.1.101.3.7.2.16.10", 3, "\x5F\xC1\x16", "\x10\x0A"}, + {"2.16.840.1.101.3.7.2.16.11", 3, "\x5F\xC1\x17", "\x10\x0B"}, + {"2.16.840.1.101.3.7.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C"}, + {"2.16.840.1.101.3.7.2.16.13", 3, "\x5F\xC1\x19", "\x10\x0D"}, + {"2.16.840.1.101.3.7.2.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E"}, + {"2.16.840.1.101.3.7.2.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F"}, + {"2.16.840.1.101.3.7.2.16.16", 3, "\x5F\xC1\x1C", "\x10\x10"}, + {"2.16.840.1.101.3.7.2.16.17", 3, "\x5F\xC1\x1D", "\x10\x11"}, + {"2.16.840.1.101.3.7.2.16.18", 3, "\x5F\xC1\x1E", "\x10\x12"}, + {"2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13"}, + {"2.16.840.1.101.3.7.2.16.20", 3, "\x5F\xC1\x20", "\x10\x14"}, + {"2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15"}, + {"2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16"}, + {"2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17"}, + {"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"}, /* following not standard , to be used by piv-tool only for testing */ - {PIV_OBJ_9B03, "3DES-ECB ADM", - "2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 0}, +/* {PIV_DATA_OBJ_9B03, "3DES-ECB ADM", + "2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 0},*/ /* Only used when signing a cert req, usually from engine * after piv-tool generated the key and saved the pub key * to a file. Note RSA key can be 1024, 2048 or 3072 * but still use the "9x06" name. */ - {PIV_OBJ_9A06, "RSA 9A Pub key from last genkey", +/* {PIV_DATA_OBJ_9A06, "RSA 9A Pub key from last genkey", "2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9C06, "Pub 9C key from last genkey", + {PIV_DATA_OBJ_9C06, "Pub 9C key from last genkey", "2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9D06, "Pub 9D key from last genkey", + {PIV_DATA_OBJ_9D06, "Pub 9D key from last genkey", "2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9E06, "Pub 9E key from last genkey", + {PIV_DATA_OBJ_9E06, "Pub 9E key from last genkey", "2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8206, "Pub 82 key ", + {PIV_DATA_OBJ_8206, "Pub 82 key ", "2.16.840.1.101.3.7.2.9999.101", 2, "\x82\x06", "\x82\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8306, "Pub 83 key ", + {PIV_DATA_OBJ_8306, "Pub 83 key ", "2.16.840.1.101.3.7.2.9999.102", 2, "\x83\x06", "\x83\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8406, "Pub 84 key ", + {PIV_DATA_OBJ_8406, "Pub 84 key ", "2.16.840.1.101.3.7.2.9999.103", 2, "\x84\x06", "\x84\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8506, "Pub 85 key ", + {PIV_DATA_OBJ_8506, "Pub 85 key ", "2.16.840.1.101.3.7.2.9999.104", 2, "\x85\x06", "\x85\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8606, "Pub 86 key ", + {PIV_DATA_OBJ_8606, "Pub 86 key ", "2.16.840.1.101.3.7.2.9999.105", 2, "\x86\x06", "\x86\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8706, "Pub 87 key ", + {PIV_DATA_OBJ_8706, "Pub 87 key ", "2.16.840.1.101.3.7.2.9999.106", 2, "\x87\x06", "\x87\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8806, "Pub 88 key ", + {PIV_DATA_OBJ_8806, "Pub 88 key ", "2.16.840.1.101.3.7.2.9999.107", 2, "\x88\x06", "\x88\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8906, "Pub 89 key ", + {PIV_DATA_OBJ_8906, "Pub 89 key ", "2.16.840.1.101.3.7.2.9999.108", 2, "\x89\x06", "\x89\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8A06, "Pub 8A key ", + {PIV_DATA_OBJ_8A06, "Pub 8A key ", "2.16.840.1.101.3.7.2.9999.109", 2, "\x8A\x06", "\x8A\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8B06, "Pub 8B key ", + {PIV_DATA_OBJ_8B06, "Pub 8B key ", "2.16.840.1.101.3.7.2.9999.110", 2, "\x8B\x06", "\x8B\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8C06, "Pub 8C key ", + {PIV_DATA_OBJ_8C06, "Pub 8C key ", "2.16.840.1.101.3.7.2.9999.111", 2, "\x8C\x06", "\x8C\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8D06, "Pub 8D key ", + {PIV_DATA_OBJ_8D06, "Pub 8D key ", "2.16.840.1.101.3.7.2.9999.112", 2, "\x8D\x06", "\x8D\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8E06, "Pub 8E key ", + {PIV_DATA_OBJ_8E06, "Pub 8E key ", "2.16.840.1.101.3.7.2.9999.113", 2, "\x8E\x06", "\x8E\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_8F06, "Pub 8F key ", + {PIV_DATA_OBJ_8F06, "Pub 8F key ", "2.16.840.1.101.3.7.2.9999.114", 2, "\x8F\x06", "\x8F\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9006, "Pub 90 key ", + {PIV_DATA_OBJ_9006, "Pub 90 key ", "2.16.840.1.101.3.7.2.9999.115", 2, "\x90\x06", "\x90\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9106, "Pub 91 key ", + {PIV_DATA_OBJ_9106, "Pub 91 key ", "2.16.840.1.101.3.7.2.9999.116", 2, "\x91\x06", "\x91\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9206, "Pub 92 key ", + {PIV_DATA_OBJ_9206, "Pub 92 key ", "2.16.840.1.101.3.7.2.9999.117", 2, "\x92\x06", "\x92\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9306, "Pub 93 key ", + {PIV_DATA_OBJ_9306, "Pub 93 key ", "2.16.840.1.101.3.7.2.9999.118", 2, "\x93\x06", "\x93\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9406, "Pub 94 key ", + {PIV_DATA_OBJ_9406, "Pub 94 key ", "2.16.840.1.101.3.7.2.9999.119", 2, "\x94\x06", "\x94\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_9506, "Pub 95 key ", - "2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_OBJ_LAST_ENUM, "", "", 0, "", "", 0} + {PIV_DATA_OBJ_9506, "Pub 95 key ", + "2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY},*/ + {"", 0, "", ""} }; -static const CK_ULONG n_objects = sizeof(objects) / sizeof(piv_obj_t); +static piv_cert_obj_t cert_objects[] = { + {0}, + {0}, + {0}, + {0}, + {0} +}; + + +//static const CK_ULONG n_objects = sizeof(objects) / sizeof(piv_obj_t); static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { - if ((objects[obj].flags & PIV_OBJECT_TYPE_PUBKEY)) - *class = CKO_PUBLIC_KEY; - else if ((objects[obj].flags & PIV_OBJECT_TYPE_CERT)) + if (obj >= 0 && obj < PIV_DATA_OBJ_LAST) + *class = CKO_DATA; + else if (obj > PIV_DATA_OBJ_LAST && obj < PIV_CERT_OBJ_LAST) *class = CKO_CERTIFICATE; else - *class = CKO_DATA; // TODO: other possibilities? + *class = CKO_VENDOR_DEFINED | CKO_DATA; // Invalid value } /*static void get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { @@ -180,7 +202,7 @@ static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { // Next two functions based off the code at // https://github.com/m9aertner/oidConverter/blob/master/oid.c -// TODO: how to give credit? +// TODO: how to give credit? OR JUST STORE THE OID ALREADY ENCODED? static void make_base128(unsigned long l, int first, CK_BYTE_PTR buf, CK_ULONG_PTR n) { if (l > 127) make_base128(l / 128, 0, buf, n); @@ -286,20 +308,21 @@ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: fprintf(stderr, "LABEL\n"); - len = strlen(objects[obj].name) + 1; - data = objects[obj].name; + len = strlen(objects[obj].label) + 1; + data = objects[obj].label; break; case CKA_APPLICATION: fprintf(stderr, "APPLICATION\n"); - len = strlen(objects[obj].name) + 1; - data = objects[obj].name; + len = strlen(objects[obj].label) + 1; + data = objects[obj].label; break; -// case CKA_VALUE: +// case CKA_VALUE: // TODO: this can be done with -r and -d|-a case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? + // This only makes sense for data objects fprintf(stderr, "OID\n"); - strcpy((char *)tmp, objects[obj].oid); + strcpy((char *)tmp, data_objects[objects[obj].sub_id].oid); asn1_encode_oid(tmp, tmp, &len); data = tmp; break; @@ -319,9 +342,10 @@ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* case CKA_SUBJECT: */ case CKA_ID: - fprintf(stderr, "KEY ID\n"); - len = 2; - data = objects[obj].containerid; + // This only makes sense for data objects + fprintf(stderr, "ID\n"); + len = data_objects[objects[obj].sub_id].tag_len; + data = data_objects[objects[obj].sub_id].tag_value; break; /* case CKA_SENSITIVE: */ @@ -372,7 +396,7 @@ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { template->ulValueLen = len; // TODO: define? return CKR_OK; } - + if (template->ulValueLen < len) return CKR_BUFFER_TOO_SMALL; diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index b4fd55d..2b75387 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -29,7 +29,7 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; - v.get_token_objects_num = YUBICO_get_token_objects_num; +// v.get_token_objects_num = YUBICO_get_token_objects_num; v.get_token_object_list = YUBICO_get_token_object_list; break; @@ -48,7 +48,7 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_mechanisms_num = NULL; v.get_token_mechanism_list = NULL; v.get_token_mechanism_info = NULL; - v.get_token_objects_num = NULL; +// v.get_token_objects_num = NULL; v.get_token_object_list = NULL; } diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index 73e00ac..6b0d2f0 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -3,6 +3,7 @@ #include "pkcs11.h" #include "objects.h" +#include typedef enum { UNKNOWN = 0x00, @@ -22,8 +23,8 @@ typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); -typedef CK_RV (*get_t_objects_num_f)(CK_ULONG_PTR); -typedef CK_RV (*get_t_object_list_f)(piv_obj_id_t *, CK_ULONG); +//typedef CK_RV (*get_t_objects_num_f)(CK_ULONG_PTR); +typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG_PTR); typedef struct { @@ -40,7 +41,7 @@ typedef struct { get_t_mechanisms_num_f get_token_mechanisms_num; get_t_mechanism_list_f get_token_mechanism_list; get_t_mechanism_info_f get_token_mechanism_info; - get_t_objects_num_f get_token_objects_num; +// get_t_objects_num_f get_token_objects_num; get_t_object_list_f get_token_object_list; } vendor_t; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 6541352..61d3e93 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -7,7 +7,7 @@ #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ - printf x; \ + printf x;; \ printf ("\n"); \ } while (0) @@ -40,7 +40,7 @@ static ykpiv_state *piv_state = NULL; -static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; +static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; // TODO: build at runtime? static CK_ULONG n_slots = 0; static CK_ULONG n_slots_with_token = 0; @@ -51,21 +51,11 @@ static struct { CK_BBOOL active; CK_ULONG num; CK_ULONG idx; - CK_BBOOL all; - CK_OBJECT_CLASS class; + piv_obj_id_t *objects; } find_obj; -static piv_obj_id_t piv_objects[] = { // Mandatory PIV objects - PIV_OBJ_CCC, // Card capability container - PIV_OBJ_CHUI, // Cardholder unique id - PIV_OBJ_X509_PIV_AUTH, // PIV authentication - PIV_OBJ_CHF, // Cardholder fingerprints - PIV_OBJ_CHFI, // Cardholder facial images - PIV_OBJ_X509_DS, // Certificate for digital signature - PIV_OBJ_X509_KM, // Certificate for key management - PIV_OBJ_X509_CARD_AUTH, // Certificate for card authentication - PIV_OBJ_SEC_OBJ // Security object -}; +static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)? +static CK_ULONG n_token_objects = 0; extern CK_FUNCTION_LIST function_list; // TODO: check all return values @@ -200,7 +190,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( for (j = 0, i = 0; i < n_slots; i++) { if (tokenPresent) { - if (has_token(slots + i)) + if (has_token(slots + i)) // TODO: use more to check if TOKEN_REMOVED pSlotList[j++] = i; } else @@ -229,8 +219,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( memcpy(pInfo, &slots[slotID].info, sizeof(CK_SLOT_INFO)); - //DBG(("slotID %lu, pInfo %s", slotID, pInfo->slotDescription)); - DOUT; return CKR_OK; } @@ -465,18 +453,34 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( { DIN; + vendor_t vendor; + if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; if (slotID >= n_slots || phSession == NULL) return CKR_ARGUMENTS_BAD; + if (slots[slotID].vid == UNKNOWN) { + DBG(("No support for token in slot %lu", slotID)); + return CKR_TOKEN_NOT_RECOGNIZED; + } + if (!has_token(slots + slotID)) { DBG(("Slot %lu has no token inserted", slotID)); return CKR_TOKEN_NOT_PRESENT; } - if ((flags & CKF_SERIAL_SESSION) == 0) { + vendor = get_vendor(slots[slotID].vid); // TODO: make a token field in slot_t ? + + // Store all the objects available in the token + n_token_objects = sizeof(token_objects) / sizeof(piv_obj_id_t); + if (vendor.get_token_object_list(piv_state, token_objects, &n_token_objects) != CKR_OK) { + DBG(("Unable to retrieve token objects")); + return CKR_FUNCTION_FAILED; + } + + if ((flags & CKF_SERIAL_SESSION) == 0) { // TODO: check more error conditions DBG(("Open session called without CKF_SERIAL_SESSION set")); return CKR_SESSION_PARALLEL_NOT_SUPPORTED; } @@ -755,7 +759,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( DOUT; return CKR_OK; } - DBG(("Trying to get object %lx", hObject)); + DBG(("Trying to get %lu attributes for object %lx", ulCount, hObject)); DBG(("Type: 0x%lx Value: %lu Len: %lu", pTemplate[0].type, *((CK_ULONG_PTR)pTemplate[0].pValue), pTemplate[0].ulValueLen)); // TODO: here for i in ulCount return get_attribute(hObject, pTemplate); @@ -808,14 +812,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( if (ulCount == 0) { DBG(("Find ALL the objects!")); find_obj.active = CK_TRUE; - vendor.get_token_objects_num(&find_obj.num); + find_obj.num = n_token_objects; find_obj.idx = 0; - find_obj.all = CK_TRUE; + find_obj.objects = token_objects; DOUT; return CKR_OK; } - return CKR_FUNCTION_FAILED; - DBG(("Initialized search for %lu objects", ulCount)); +// return CKR_FUNCTION_FAILED; + DBG(("Initialized search with %lu parameters", ulCount)); if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD; @@ -823,10 +827,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( find_obj.active = CK_TRUE; for (i = 0; i < ulCount; i++) { - DBG(("Object %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); - - // if () - + DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); } @@ -861,19 +862,22 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( return CKR_OPERATION_NOT_INITIALIZED; DBG(("Can return %lu object(s)", ulMaxObjectCount)); - if (find_obj.all == CK_TRUE) { - // Trying to get all the objects, just return the next one - if (find_obj.idx == find_obj.num) { - *pulObjectCount = 0; - DOUT; - return CKR_OK; - } - *phObject = piv_objects[find_obj.idx++]; - *pulObjectCount = 1; + // Return the next object + if (find_obj.idx == find_obj.num) { + *pulObjectCount = 0; + DOUT; + return CKR_OK; } + *phObject = find_obj.objects[find_obj.idx++]; + *pulObjectCount = 1; + return CKR_OK; + // NEVER REACHED + DBG(("GETTING SOMETHING ELSE")); + *phObject = PIV_DATA_OBJ_X509_DS; + *pulObjectCount = 2; DOUT; return CKR_OK; } @@ -1073,11 +1077,35 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + if (session != YKCS11_SESSION_ID) + return CKR_SESSION_CLOSED; + + if (hSession != session) + return CKR_SESSION_HANDLE_INVALID; + + if (pMechanism == NULL_PTR || + hKey == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey)); DOUT; return CKR_OK; } - +/* TOTOD: DELETE */ +CK_BYTE sig_buf[1024]; +CK_ULONG sig_len = 1024; +void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, CK_BBOOL space) { + unsigned int i; + for (i = 0; i < len; i++) { + fprintf(output, "%02x%s", buf[i], space == CK_TRUE ? " " : ""); + } + fprintf(output, "\n"); +} +/* TODO: DELETE END*/ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, @@ -1087,7 +1115,21 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( ) { DIN; - DBG(("TODO!!!")); + // TODO: check conditions + char test_buf[] = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20\xa7\x47\x16\x1b\x15\x5f\xd0\x05\xbc\xbe\x84\x4a\x28\xa9\x6c\x74\xfe\xf6\x6a\x42\x84\xa0\x4e\x05\x7a\x0c\x88\xe2\xc8\x83\xc0\x00"; + CK_ULONG sig_len_in = sizeof(test_buf) - 1; + CK_ULONG sig_len_out = 1024; + ykpiv_rc r; + DBG(("Sending %lu bytes to sign", /*ulDataLen*/sig_len_in)); + dump_hex(test_buf, sig_len_in, stderr, CK_TRUE); + if ((r = ykpiv_sign_data(piv_state, /*pData*/test_buf, /*ulDataLen*/sig_len_in, sig_buf, &sig_len_out, YKPIV_ALGO_RSA2048, YKPIV_KEY_AUTHENTICATION)) != YKPIV_OK) { + DBG(("Sign error %s", ykpiv_strerror(r))); + return CKR_FUNCTION_FAILED; + } + DBG(("Got %lu bytes back", sig_len_out)); + dump_hex(sig_buf, sig_len_out, stderr, CK_TRUE); + memcpy(pSignature, sig_buf, sig_len_out); + *pulSignatureLen = sig_len_out; DOUT; return CKR_OK; } diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index f3c25f5..be80b60 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -68,42 +68,42 @@ static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH }; static const piv_obj_id_t token_objects[] = { // TODO: is there a way to get this from the token? - PIV_OBJ_CCC, // Card capability container - PIV_OBJ_CHUI, // Cardholder unique id - PIV_OBJ_X509_PIV_AUTH, // PIV authentication - PIV_OBJ_CHF, // Cardholder fingerprints - PIV_OBJ_SEC_OBJ, // Security object - PIV_OBJ_CHFI, // Cardholder facial images - PIV_OBJ_X509_CARD_AUTH, // Certificate for card authentication - PIV_OBJ_X509_DS, // Certificate for digital signature - PIV_OBJ_X509_KM, // Certificate for key management - //PIV_OBJ_PI, // Cardholder printed information - //PIV_OBJ_DISCOVERY, // Discovery object - //PIV_OBJ_HISTORY, // History object -/* PIV_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 - PIV_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 - PIV_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 - PIV_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 - PIV_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 - PIV_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 - PIV_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 - PIV_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 - PIV_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 - PIV_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 - PIV_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 - PIV_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 - PIV_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 - PIV_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 - PIV_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 - PIV_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 - PIV_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 - PIV_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 - PIV_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 - PIV_OBJ_RETIRED_X509_20, // Retired certificate for KM 20*/ - //PIV_OBJ_IRIS_IMAGE, // Cardholder iris images - //PIV_OBJ_BITGT, // Biometric information templates group template - //PIV_OBJ_SM_SIGNER, // Secure messaging signer - //PIV_OBJ_PC_REF_DATA, // Pairing code reference data + PIV_DATA_OBJ_CCC, // Card capability container + PIV_DATA_OBJ_CHUI, // Cardholder unique id + PIV_DATA_OBJ_X509_PIV_AUTH, // PIV authentication + PIV_DATA_OBJ_CHF, // Cardholder fingerprints + PIV_DATA_OBJ_SEC_OBJ, // Security object + PIV_DATA_OBJ_CHFI, // Cardholder facial images + PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_DATA_OBJ_X509_DS, // Certificate for digital signature + PIV_DATA_OBJ_X509_KM, // Certificate for key management + //PIV_DATA_OBJ_PI, // Cardholder printed information + //PIV_DATA_OBJ_DISCOVERY, // Discovery object + //PIV_DATA_OBJ_HISTORY, // History object +/* PIV_DATA_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 + PIV_DATA_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 + PIV_DATA_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 + PIV_DATA_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 + PIV_DATA_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 + PIV_DATA_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 + PIV_DATA_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 + PIV_DATA_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 + PIV_DATA_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 + PIV_DATA_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 + PIV_DATA_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 + PIV_DATA_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 + PIV_DATA_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 + PIV_DATA_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 + PIV_DATA_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 + PIV_DATA_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 + PIV_DATA_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 + PIV_DATA_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 + PIV_DATA_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 + PIV_DATA_OBJ_RETIRED_X509_20, // Retired certificate for KM 20*/ + //PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images + //PIV_DATA_OBJ_BITGT, // Biometric information templates group template + //PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer + //PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data }; static const CK_ULONG token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t); @@ -252,13 +252,61 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P } -CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num) { +/*CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num) { *num = token_objects_num; - //fprintf("TIENI %lu\n", token_objects_num); + return CKR_OK; + }*/ +#include +CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG_PTR len) { + CK_BYTE buf[2048]; + CK_ULONG buf_len; + + piv_obj_id_t certs[4]; + CK_ULONG n_cert = 0; + + if (state == NULL || obj == NULL || len == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + buf_len = sizeof(buf); + if (ykpiv_fetch_object(state, YKPIV_OBJ_AUTHENTICATION, buf, &buf_len) == YKPIV_OK) { + n_cert++; + certs[0] = PIV_CERT_OBJ_X509_PIV_AUTH; + fprintf(stderr, "Found AUTH cert (9a)\n"); + } + + buf_len = sizeof(buf); + if (ykpiv_fetch_object(state, YKPIV_OBJ_SIGNATURE, buf, &buf_len) == YKPIV_OK) { + n_cert++; + certs[1] = PIV_CERT_OBJ_X509_DS; + fprintf(stderr, "Found SIGNATURE cert (9c)\n"); + } + + buf_len = sizeof(buf); + if (ykpiv_fetch_object(state, YKPIV_OBJ_KEY_MANAGEMENT, buf, &buf_len) == YKPIV_OK) { + n_cert++; + certs[2] = PIV_CERT_OBJ_X509_KM; + fprintf(stderr, "Found KMK cert (9d)\n"); + } + + buf_len = sizeof(buf); + if (ykpiv_fetch_object(state, YKPIV_OBJ_CARD_AUTH, buf, &buf_len) == YKPIV_OK) { + n_cert++; + certs[3] = PIV_CERT_OBJ_X509_CARD_AUTH; + fprintf(stderr, "Found CARD AUTH cert\n"); + } + + if (n_cert + token_objects_num > *len) + return CKR_BUFFER_TOO_SMALL; + + // Copy mandatory data objects + memcpy(obj, token_objects, token_objects_num * sizeof(piv_obj_id_t)); + + // Copy certificates + memcpy(obj + token_objects_num, certs, n_cert * sizeof(piv_obj_id_t)); + + *len = token_objects_num + n_cert; + fprintf(stderr, "The total number of objects for this token is %lu\n", *len); + return CKR_OK; } - -CK_RV YUBICO_get_token_object_list(piv_obj_id_t *obj, CK_ULONG len) { - -} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index 979c71e..4e884b8 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -3,6 +3,7 @@ #include "pkcs11.h" #include "obj_types.h" +#include CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); @@ -17,7 +18,7 @@ CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VER CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num); CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num); CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info); -CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num); -CK_RV YUBICO_get_token_object_list(piv_obj_id_t * obj, CK_ULONG num); +//CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num); +CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t * obj, CK_ULONG_PTR num); #endif From 437094b2d7a181292a4775ecc406fe475e8d0a46 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 24 Jul 2015 16:58:40 +0200 Subject: [PATCH 036/134] Some improvements on sign. --- ykcs11/ykcs11.c | 68 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 61d3e93..a7dacb8 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -7,12 +7,12 @@ #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ - printf x;; \ + printf x; \ printf ("\n"); \ } while (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 YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" @@ -57,6 +57,12 @@ static struct { static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)? static CK_ULONG n_token_objects = 0; +static struct { + CK_BBOOL active; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE key; +} sign_info; + extern CK_FUNCTION_LIST function_list; // TODO: check all return values /* General Purpose */ @@ -809,27 +815,32 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( } vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?; + find_obj.active = CK_TRUE; + find_obj.idx = 0; + find_obj.num = n_token_objects; // TOTO: actually malloc here so that the array can be changed + find_obj.objects = token_objects; + if (ulCount == 0) { DBG(("Find ALL the objects!")); - find_obj.active = CK_TRUE; - find_obj.num = n_token_objects; - find_obj.idx = 0; - find_obj.objects = token_objects; DOUT; return CKR_OK; } -// return CKR_FUNCTION_FAILED; + DBG(("Initialized search with %lu parameters", ulCount)); - if (pTemplate == NULL_PTR) + if (pTemplate == NULL_PTR) { + find_obj.active = CK_FALSE; return CKR_ARGUMENTS_BAD; - - find_obj.active = CK_TRUE; - + } + for (i = 0; i < ulCount; i++) { DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); + // TODO: remove objects that don't match } + // TOTO: do it properly here, jsut a test now + find_obj.num = 1; + find_obj.objects = token_objects + 3; DOUT; return CKR_OK; @@ -872,13 +883,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( *phObject = find_obj.objects[find_obj.idx++]; *pulObjectCount = 1; - return CKR_OK; - // NEVER REACHED - DBG(("GETTING SOMETHING ELSE")); - *phObject = PIV_DATA_OBJ_X509_DS; - *pulObjectCount = 2; - DOUT; + DBG(("Returning object %lu", *phObject)); + return CKR_OK; } @@ -1092,6 +1099,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_ARGUMENTS_BAD; DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey)); + + sign_info.active = CK_TRUE; + memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); + sign_info.key = hKey; + // TODO: also allocate some space for the signature + + DOUT; return CKR_OK; } @@ -1115,14 +1129,32 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( ) { DIN; + + if (sign_info.active == CK_FALSE) + return CKR_OPERATION_NOT_INITIALIZED; + // TODO: check conditions char test_buf[] = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20\xa7\x47\x16\x1b\x15\x5f\xd0\x05\xbc\xbe\x84\x4a\x28\xa9\x6c\x74\xfe\xf6\x6a\x42\x84\xa0\x4e\x05\x7a\x0c\x88\xe2\xc8\x83\xc0\x00"; CK_ULONG sig_len_in = sizeof(test_buf) - 1; CK_ULONG sig_len_out = 1024; ykpiv_rc r; + CK_CHAR key; + DBG(("Sending %lu bytes to sign", /*ulDataLen*/sig_len_in)); dump_hex(test_buf, sig_len_in, stderr, CK_TRUE); - if ((r = ykpiv_sign_data(piv_state, /*pData*/test_buf, /*ulDataLen*/sig_len_in, sig_buf, &sig_len_out, YKPIV_ALGO_RSA2048, YKPIV_KEY_AUTHENTICATION)) != YKPIV_OK) { + + if (sign_info.key == PIV_DATA_OBJ_X509_PIV_AUTH) { + key = YKPIV_KEY_AUTHENTICATION; + DBG(("Using key 9a")); + } + else { + key = YKPIV_KEY_SIGNATURE; + DBG(("Using key 9c")); + } + + // TODO: check that mechanism makes sense for the key that we have. + + if ((r = ykpiv_sign_data(piv_state, /*pData*/test_buf, /*ulDataLen*/sig_len_in, sig_buf, &sig_len_out, YKPIV_ALGO_RSA2048, key)) != YKPIV_OK) { DBG(("Sign error %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } From b9596b33f51d31b50f78a9a6df105c0e4293d5ca Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 27 Jul 2015 17:03:29 +0200 Subject: [PATCH 037/134] Started major overhaul of slot vendors and token vendors. --- ykcs11/mechanisms.c | 40 ++++++++ ykcs11/mechanisms.h | 10 ++ ykcs11/utils.c | 103 +++++++++++++++++-- ykcs11/utils.h | 13 +-- ykcs11/vendors.c | 4 +- ykcs11/vendors.h | 6 +- ykcs11/ykcs11.c | 243 ++++++++++++++++++++++---------------------- ykcs11/ykcs11.h | 26 +++++ ykcs11/ykcs11.map | 1 + ykcs11/yubico.c | 39 ++++--- ykcs11/yubico.h | 4 +- 11 files changed, 330 insertions(+), 159 deletions(-) create mode 100644 ykcs11/mechanisms.c create mode 100644 ykcs11/mechanisms.h create mode 100644 ykcs11/ykcs11.h diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c new file mode 100644 index 0000000..b232d9d --- /dev/null +++ b/ykcs11/mechanisms.c @@ -0,0 +1,40 @@ +#include "mechanisms.h" + +// Supported mechanisms for signature +static const CK_MECHANISM_TYPE sign[] = { + CKM_RSA_PKCS, + CKM_RSA_PKCS_PSS, + CKM_RSA_X_509, + CKM_SHA1_RSA_PKCS, + CKM_SHA256_RSA_PKCS, + CKM_SHA384_RSA_PKCS, + CKM_SHA512_RSA_PKCS, + CKM_SHA1_RSA_PKCS_PSS, + CKM_SHA256_RSA_PKCS_PSS, + CKM_SHA384_RSA_PKCS_PSS, + CKM_SHA512_RSA_PKCS_PSS, + CKM_ECDSA, + CKM_ECDSA_SHA1 +}; + +CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m, const CK_OBJECT_HANDLE k) { + + CK_ULONG i; + CK_BBOOL supported = CK_FALSE; + + /* Check if mechanism is supported by the module */ + for (i = 0; i < sizeof(sign) / sizeof(CK_MECHANISM_TYPE); i++) { + if (m->mechanism == sign[i]) { + supported = CK_TRUE; + break; + } + } + if (supported == CK_FALSE) + return CKR_MECHANISM_INVALID; + + /* Check if mechanism is supported by the token */ + + + CK_OK; + +} diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h new file mode 100644 index 0000000..5c5e02f --- /dev/null +++ b/ykcs11/mechanisms.h @@ -0,0 +1,10 @@ +#ifndef MECHANISMS_H +#define MECHANISMS_H + +#include "pkcs11t.h" + + +CK_RV check_sign_mechanism(const CK_MECHANISM_PTR m, const CK_OBJECT_HANDLE k); + + +#endif diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 81dac8d..236153d 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -1,4 +1,5 @@ #include "utils.h" +#include #include CK_BBOOL has_token(const ykcs11_slot_t *slot) { @@ -7,7 +8,7 @@ CK_BBOOL has_token(const ykcs11_slot_t *slot) { } -CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, +CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token) { CK_BYTE i; @@ -40,6 +41,7 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, strncpy(slots[*n_slots].info.slotDescription, p, sizeof(slots[*n_slots].info.slotDescription)); } else { + // Supported slot vendor = get_vendor(slots[*n_slots].vid); // Values must NOT be null terminated and ' ' padded @@ -48,31 +50,116 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, s = slots[*n_slots].info.slotDescription; l = sizeof(slots[*n_slots].info.slotDescription); if (vendor.get_slot_description(s, l) != CKR_OK) - return CK_FALSE; + goto failure; memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID)); s = slots[*n_slots].info.manufacturerID; l = sizeof(slots[*n_slots].info.manufacturerID); if(vendor.get_slot_manufacturer(s, l) != CKR_OK) - return CK_FALSE; + goto failure; if (vendor.get_slot_flags(&slots[*n_slots].info.flags) != CKR_OK) - return CK_FALSE; + goto failure; // Treating hw and fw version the same if (vendor.get_slot_version(&slots[*n_slots].info.hardwareVersion) != CKR_OK) - return CK_FALSE; + goto failure; if (vendor.get_slot_version(&slots[*n_slots].info.firmwareVersion) != CKR_OK) - return CK_FALSE; + goto failure; - if (has_token(slots + *n_slots)) + if (has_token(slots + *n_slots)) { + // Save token information (*n_with_token)++; + + if (create_token(p, slots + *n_slots) != CKR_OK) + goto failure; + } } (*n_slots)++; p += i + 1; } - return CK_TRUE; + return CKR_OK; + +failure: + // TODO: destroy all token objects + for (i = 0; i < *n_slots; i++) + if (has_token(slots + i)) + destroy_token(slots + i); + return CKR_FUNCTION_FAILED; +} + +CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { + vendor_t token_vendor; + CK_TOKEN_INFO_PTR t_info; + fprintf(stderr, "Now trying to get token info from %s\n", p); // TODO: is p needed? + + slot->token = malloc(sizeof(ykcs11_token_t)); // TODO: free + if (slot->token == NULL) + return CKR_HOST_MEMORY; + + slot->token->vid = YUBICO; // TODO: this must become "slot_vendor.get_token_vid()" + token_vendor = get_vendor(slot->token->vid); + + t_info = &slot->token->info; + + memset(t_info->label, ' ', sizeof(t_info->label)); + if (token_vendor.get_token_label(t_info->label, sizeof(t_info->label)) != CKR_OK) + return CKR_FUNCTION_FAILED; + + memset(t_info->manufacturerID, ' ', sizeof(t_info->manufacturerID)); + if(token_vendor.get_token_manufacturer(t_info->manufacturerID, sizeof(t_info->manufacturerID)) != CKR_OK) + return CKR_FUNCTION_FAILED; + + memset(t_info->model, ' ', sizeof(t_info->model)); + if(token_vendor.get_token_model(t_info->model, sizeof(t_info->model)) != CKR_OK) + return CKR_FUNCTION_FAILED; + + memset(t_info->serialNumber, ' ', sizeof(t_info->serialNumber)); + if(token_vendor.get_token_serial(t_info->serialNumber, sizeof(t_info->serialNumber)) != CKR_OK) + return CKR_FUNCTION_FAILED; + + if (token_vendor.get_token_flags(&t_info->flags) != CKR_OK) + return CKR_FUNCTION_FAILED; + + t_info->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; + + t_info->ulSessionCount = CK_UNAVAILABLE_INFORMATION; + + t_info->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION; + + t_info->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; + + t_info->ulMaxPinLen = 8; + + t_info->ulMinPinLen = 6; + + t_info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; + + t_info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; + + t_info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; + + t_info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; + + //ykpiv_get_version(piv_state, buf, sizeof(buf)); + //if (token_vendor.get_token_version(buf, strlen(buf), &ver) != CKR_OK) // TODO: fix this + // return CKR_FUNCTION_FAILED; + + //t_info->hardwareVersion = ver; // version number of hardware // TODO: fix + + //t_info->firmwareVersion = ver; // version number of firmware // TODO: fix + + memset(t_info->utcTime, ' ', sizeof(t_info->utcTime)); // No clock present, clear + + // TODO: also get token objects here? (and destroy on failure) + + return CKR_OK; +} + +void destroy_token(ykcs11_slot_t *slot) { + free(slot->token); + slot->token = NULL; } diff --git a/ykcs11/utils.h b/ykcs11/utils.h index 804cef0..6190913 100644 --- a/ykcs11/utils.h +++ b/ykcs11/utils.h @@ -1,16 +1,11 @@ #ifndef UTILS_H #define UTILS_H -#include "pkcs11t.h" -#include "vendors.h" - -typedef struct { - vendor_id_t vid; - CK_SLOT_INFO info; -} ykcs11_slot_t; // TODO: move this +#include "ykcs11.h" CK_BBOOL has_token(const ykcs11_slot_t *slot); -CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, +CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token); - +CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot); +void destroy_token(ykcs11_slot_t *slot); #endif diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index 2b75387..b4fd55d 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -29,7 +29,7 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; -// v.get_token_objects_num = YUBICO_get_token_objects_num; + v.get_token_objects_num = YUBICO_get_token_objects_num; v.get_token_object_list = YUBICO_get_token_object_list; break; @@ -48,7 +48,7 @@ vendor_t get_vendor(vendor_id_t vid) { v.get_token_mechanisms_num = NULL; v.get_token_mechanism_list = NULL; v.get_token_mechanism_info = NULL; -// v.get_token_objects_num = NULL; + v.get_token_objects_num = NULL; v.get_token_object_list = NULL; } diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index 6b0d2f0..cba0763 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -23,8 +23,8 @@ typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); -//typedef CK_RV (*get_t_objects_num_f)(CK_ULONG_PTR); -typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG_PTR); +typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR); +typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); typedef struct { @@ -41,7 +41,7 @@ typedef struct { get_t_mechanisms_num_f get_token_mechanisms_num; get_t_mechanism_list_f get_token_mechanism_list; get_t_mechanism_info_f get_token_mechanism_info; -// get_t_objects_num_f get_token_objects_num; + get_t_objects_num_f get_token_objects_num; get_t_object_list_f get_token_object_list; } vendor_t; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index a7dacb8..934076b 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1,8 +1,10 @@ +#include "ykcs11.h" #include "pkcs11.h" #include +#include #include #include -#include "vendors.h" +//#include "vendors.h" #include "utils.h" #define D(x) do { \ @@ -44,8 +46,7 @@ static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; // TODO: build at runtime? static CK_ULONG n_slots = 0; static CK_ULONG n_slots_with_token = 0; -static CK_SESSION_HANDLE session = CK_INVALID_HANDLE; // TODO: support multiple sessions? -static CK_SESSION_INFO session_info; +static ykcs11_session_t session; // TODO: support multiple sessions? static struct { CK_BBOOL active; @@ -54,8 +55,8 @@ static struct { piv_obj_id_t *objects; } find_obj; -static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)? -static CK_ULONG n_token_objects = 0; +/*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)? And include inside a session struct? + static CK_ULONG n_token_objects = 0;*/ static struct { CK_BBOOL active; @@ -236,8 +237,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( { DIN; CK_VERSION ver = {0, 0}; - vendor_id_t vid; - vendor_t vendor; + vendor_t token_vendor; CK_BYTE buf[64]; if (piv_state == NULL) @@ -246,10 +246,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( if (slotID >= n_slots) return CKR_ARGUMENTS_BAD; - vid = slots[slotID].vid; - - if (vid == UNKNOWN) { - DBG(("No support for token in slot %lu", slotID)); + if (slots[slotID].vid == UNKNOWN) { + DBG(("No support for slot %lu", slotID)); return CKR_TOKEN_NOT_RECOGNIZED; } @@ -258,58 +256,30 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( return CKR_TOKEN_NOT_PRESENT; } - vendor = get_vendor(vid); // TODO: make a token field in slot_t ? + if (slots[slotID].token->vid == UNKNOWN) { + DBG(("No support for token in slot %lu", slotID)); + return CKR_TOKEN_NOT_RECOGNIZED; + } - memset(pInfo->label, ' ', sizeof(pInfo->label)); - if (vendor.get_token_label(pInfo->label, sizeof(pInfo->label)) != CKR_OK) - return CKR_FUNCTION_FAILED; - - memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); - if(vendor.get_token_manufacturer(pInfo->manufacturerID, sizeof(pInfo->manufacturerID)) != CKR_OK) - return CKR_FUNCTION_FAILED; - - memset(pInfo->model, ' ', sizeof(pInfo->model)); - if(vendor.get_token_model(pInfo->model, sizeof(pInfo->model)) != CKR_OK) - return CKR_FUNCTION_FAILED; - - memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber)); - if(vendor.get_token_serial(pInfo->serialNumber, sizeof(pInfo->serialNumber)) != CKR_OK) - return CKR_FUNCTION_FAILED; - - // bit flags indicating capabilities and status of the device as defined below // TODO: what about other flags? Like last attempt - if (vendor.get_token_flags(&pInfo->flags) != CKR_OK) - return CKR_FUNCTION_FAILED; + token_vendor = get_vendor(slots[slotID].token->vid); + memcpy(pInfo, &slots[slotID].token->info, sizeof(CK_TOKEN_INFO)); + + // Overwrite value that are application specific pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? - pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token pInfo->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION; // maximum number of read/write sessions that can be opened with the token at one time by a single TODO: should this be 1? pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token - pInfo->ulMaxPinLen = PIV_MAX_PIN_LEN; // maximum length in bytes of the PIN - pInfo->ulMinPinLen = PIV_MIN_PIN_LEN; // minimum length in bytes of the PIN - pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; - pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; - pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; - pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; - ykpiv_get_version(piv_state, buf, sizeof(buf)); - if (vendor.get_token_version(buf, strlen(buf), &ver) != CKR_OK) - return CKR_FUNCTION_FAILED; - - pInfo->hardwareVersion = ver; // version number of hardware - - pInfo->firmwareVersion = ver; // version number of firmware - - memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime)); // No clock present, clear - + DOUT; return CKR_OK; } @@ -406,7 +376,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( if (vendor.get_token_mechanism_info(type, pInfo) != CKR_OK) return CKR_MECHANISM_INVALID; - DOUT; return CKR_OK; } @@ -459,7 +428,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( { DIN; - vendor_t vendor; + vendor_t token_vendor; if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -468,6 +437,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_ARGUMENTS_BAD; if (slots[slotID].vid == UNKNOWN) { + DBG(("No support for slot %lu", slotID)); + return CKR_TOKEN_NOT_RECOGNIZED; + } + + if (slots[slotID].token->vid == UNKNOWN) { DBG(("No support for token in slot %lu", slotID)); return CKR_TOKEN_NOT_RECOGNIZED; } @@ -477,44 +451,59 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_TOKEN_NOT_PRESENT; } - vendor = get_vendor(slots[slotID].vid); // TODO: make a token field in slot_t ? - - // Store all the objects available in the token - n_token_objects = sizeof(token_objects) / sizeof(piv_obj_id_t); - if (vendor.get_token_object_list(piv_state, token_objects, &n_token_objects) != CKR_OK) { - DBG(("Unable to retrieve token objects")); - return CKR_FUNCTION_FAILED; - } - - if ((flags & CKF_SERIAL_SESSION) == 0) { // TODO: check more error conditions - DBG(("Open session called without CKF_SERIAL_SESSION set")); - return CKR_SESSION_PARALLEL_NOT_SUPPORTED; - } - - if (session != CK_INVALID_HANDLE) { + if (session.handle != CK_INVALID_HANDLE) { DBG(("A session with this or another token already exists")); return CKR_SESSION_COUNT; } - // TODO: make sue we don't open a session with an UNKNOWN slot/token + if ((flags & CKF_SERIAL_SESSION) == 0) { // TODO: check more error conditions + DBG(("Open session called without CKF_SERIAL_SESSION set")); // Reuired by specs + return CKR_SESSION_PARALLEL_NOT_SUPPORTED; + } - session = YKCS11_SESSION_ID; - session_info.slotID = slotID; - // TODO: KEEP TRACK OF THE APPLICATION + token_vendor = get_vendor(slots[slotID].token->vid); + + // Store the slot + session.slot = slots + slotID; + //session.slot->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO + + // Get the number of token objects + if (token_vendor.get_token_objects_num(piv_state, &session.slot->token->n_objects) != CKR_OK) { + DBG(("Unable to retrieve number of token objects")); + return CKR_FUNCTION_FAILED; + } + + // Get memory for the objects + session.slot->token->objects = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_objects); + if (session.slot->token->objects == NULL) { + DBG(("Unable to allocate memory for token objects")); + return CKR_HOST_MEMORY; + } + + // Store all the objects available in the token + if (token_vendor.get_token_object_list(piv_state, + session.slot->token->objects, + session.slot->token->n_objects) != CKR_OK) { + DBG(("Unable to retrieve token objects")); + return CKR_FUNCTION_FAILED; + } if ((flags & CKF_RW_SESSION)) { // R/W Session - session_info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session + session.info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session } else { // R/O Session - session_info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default session + session.info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default session } - session_info.flags = flags; - session_info.ulDeviceError = 0; + session.info.flags = flags; + session.info.ulDeviceError = 0; - *phSession = session; + session.handle = YKCS11_SESSION_ID; + // TODO: KEEP TRACK OF THE APPLICATION + + *phSession = session.handle; DOUT; return CKR_OK; @@ -529,16 +518,21 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (session == CK_INVALID_HANDLE) { + if (session.handle == CK_INVALID_HANDLE) { DBG(("There is no existing session")); return CKR_SESSION_CLOSED; } - if (hSession != YKCS11_SESSION_ID) + if (hSession != YKCS11_SESSION_ID) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } - session = CK_INVALID_HANDLE; - memset(&session_info, 0, sizeof(CK_SESSION_INFO)); + free(session.slot->token->objects); // TODO: make objects survive a session so there is no need to get them again? + session.slot->token->objects = NULL; + + memset(&session, 0, sizeof(ykcs11_session_t)); + session.handle = CK_INVALID_HANDLE; DOUT; return CKR_OK; @@ -549,18 +543,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( ) { DIN; + CK_RV rv; if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (session_info.slotID != slotID) + if (session.slot != slots + slotID) return CKR_SLOT_ID_INVALID; - session = CK_INVALID_HANDLE; - memset(&session_info, 0, sizeof(CK_SESSION_INFO)); // TODO: Better to call close session? + rv = C_CloseSession(session.handle); DOUT; - return CKR_OK; + return rv; } CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( @@ -576,10 +570,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( if (pInfo == NULL) return CKR_ARGUMENTS_BAD; - if (hSession != session) + if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; - memcpy(pInfo, &session_info, sizeof(CK_SESSION_INFO)); + memcpy(pInfo, &session.info, sizeof(CK_SESSION_INFO)); DOUT; return CKR_OK; @@ -635,25 +629,25 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); - if (session == CK_INVALID_HANDLE) + if (session.handle == CK_INVALID_HANDLE) return CKR_SESSION_CLOSED; - if (hSession != session) + if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; - if (userType != CKU_SO && + if (userType != CKU_SO && // TODO: what can SO do? userType != CKU_USER && userType != CKU_CONTEXT_SPECIFIC) return CKR_USER_TYPE_INVALID; - if ((session_info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? + if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? DBG(("Tried to log-in to a read-only session")); return CKR_SESSION_READ_ONLY_EXISTS; } switch (userType) { case CKU_USER: - if (session_info.state == CKS_RW_USER_FUNCTIONS) + if (session.info.state == CKS_RW_USER_FUNCTIONS) return CKR_USER_ALREADY_LOGGED_IN; tries = 0; @@ -747,10 +741,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (session != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; - if (hSession != session) + if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; if (pTemplate == NULL_PTR || ulCount == 0) @@ -800,25 +794,28 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (session != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; - if (hSession != session) - return CKR_SESSION_HANDLE_INVALID; // TODO: or session closed? + if (hSession != session.handle) + return CKR_SESSION_HANDLE_INVALID; if (find_obj.active == CK_TRUE) return CKR_OPERATION_ACTIVE; - if (slots[session_info.slotID].vid == UNKNOWN) { - DBG(("Slot %lu is tokenless/unsupported", session_info.slotID)); - return CKR_SLOT_ID_INVALID; + //vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?; + + find_obj.idx = 0; + find_obj.num = session.slot->token->n_objects; + + find_obj.objects = malloc(sizeof(piv_obj_id_t) * find_obj.num); + if (find_obj.objects == NULL) { + DBG(("Unable to allocate memory for finding objects")); + return CKR_HOST_MEMORY; } - vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?; + memcpy(find_obj.objects, session.slot->token->objects, sizeof(piv_obj_id_t) * find_obj.num); // TODO: add another 'num' field for then objects have to be excluded because of attribute matching; find_obj.active = CK_TRUE; - find_obj.idx = 0; - find_obj.num = n_token_objects; // TOTO: actually malloc here so that the array can be changed - find_obj.objects = token_objects; if (ulCount == 0) { DBG(("Find ALL the objects!")); @@ -832,15 +829,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( find_obj.active = CK_FALSE; return CKR_ARGUMENTS_BAD; } - + for (i = 0; i < ulCount; i++) { DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); // TODO: remove objects that don't match } - // TOTO: do it properly here, jsut a test now + // TODO: do it properly here, jsut a test now find_obj.num = 1; - find_obj.objects = token_objects + 3; + find_obj.objects = session.slot->token->objects + 3; DOUT; return CKR_OK; @@ -858,10 +855,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (session != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; - if (hSession != session) + if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; if (phObject == NULL_PTR || @@ -885,7 +882,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( *pulObjectCount = 1; DBG(("Returning object %lu", *phObject)); - + return CKR_OK; } @@ -898,15 +895,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (session != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; - if (hSession != session) + if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; if (find_obj.active != CK_TRUE) return CKR_OPERATION_NOT_INITIALIZED; + free(find_obj.objects); + find_obj.objects = NULL; + find_obj.active = CK_FALSE; DOUT; @@ -1088,24 +1088,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (session != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; - if (hSession != session) + if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; if (pMechanism == NULL_PTR || hKey == NULL_PTR) return CKR_ARGUMENTS_BAD; - DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey)); + DBG(("Trying to sign some data with mechanism %lu and key %lu more", pMechanism->mechanism, hKey)); + + if (check_sign_mechanism(pMechanism, hKey) == CK_FALSE) // TODO: do we need session here? + return CKR_MECHANISM_INVALID; sign_info.active = CK_TRUE; memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); sign_info.key = hKey; // TODO: also allocate some space for the signature - - + + DOUT; return CKR_OK; } @@ -1132,27 +1135,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (sign_info.active == CK_FALSE) return CKR_OPERATION_NOT_INITIALIZED; - + // TODO: check conditions char test_buf[] = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20\xa7\x47\x16\x1b\x15\x5f\xd0\x05\xbc\xbe\x84\x4a\x28\xa9\x6c\x74\xfe\xf6\x6a\x42\x84\xa0\x4e\x05\x7a\x0c\x88\xe2\xc8\x83\xc0\x00"; CK_ULONG sig_len_in = sizeof(test_buf) - 1; CK_ULONG sig_len_out = 1024; ykpiv_rc r; CK_CHAR key; - - DBG(("Sending %lu bytes to sign", /*ulDataLen*/sig_len_in)); - dump_hex(test_buf, sig_len_in, stderr, CK_TRUE); + + DBG(("Sending %lu bytes to sign", ulDataLen/*sig_len_in*/)); + dump_hex(pData, ulDataLen, stderr, CK_TRUE); if (sign_info.key == PIV_DATA_OBJ_X509_PIV_AUTH) { key = YKPIV_KEY_AUTHENTICATION; DBG(("Using key 9a")); } - else { + else { // TODO: test what happens if there is no key on the card key = YKPIV_KEY_SIGNATURE; DBG(("Using key 9c")); } - // TODO: check that mechanism makes sense for the key that we have. + // TODO: check that mechanism makes sense for the key that we have (check in signinit). if ((r = ykpiv_sign_data(piv_state, /*pData*/test_buf, /*ulDataLen*/sig_len_in, sig_buf, &sig_len_out, YKPIV_ALGO_RSA2048, key)) != YKPIV_OK) { DBG(("Sign error %s", ykpiv_strerror(r))); diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h new file mode 100644 index 0000000..0814875 --- /dev/null +++ b/ykcs11/ykcs11.h @@ -0,0 +1,26 @@ +#ifndef YKCS11_H +#define YKCS11_H + +#include "pkcs11t.h" +#include "vendors.h" + +typedef struct { + vendor_id_t vid; + CK_TOKEN_INFO info; + piv_obj_id_t *objects; + CK_ULONG n_objects; +} ykcs11_token_t; + +typedef struct { + vendor_id_t vid; + CK_SLOT_INFO info; + ykcs11_token_t *token; +} ykcs11_slot_t; + +typedef struct { + CK_SESSION_HANDLE handle; + CK_SESSION_INFO info; /* slotid, state, flags, deviceerror */ + ykcs11_slot_t *slot; +} ykcs11_session_t; + +#endif diff --git a/ykcs11/ykcs11.map b/ykcs11/ykcs11.map index b6b62ac..3b83e98 100644 --- a/ykcs11/ykcs11.map +++ b/ykcs11/ykcs11.map @@ -29,6 +29,7 @@ YKCS11_0.1.0 global: C_Initialize; C_GetFunctionList; +# TODO: add more here local: *; }; \ No newline at end of file diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index be80b60..c3f8f17 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -132,7 +132,6 @@ CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags) { *flags = slot_flags; return CKR_OK; - } CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version) { @@ -251,23 +250,20 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P return CKR_MECHANISM_INVALID; } - -/*CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num) { - - *num = token_objects_num; - return CKR_OK; - }*/ -#include -CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG_PTR len) { +#include // TODO: delete +static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *obj, CK_ULONG_PTR len) { CK_BYTE buf[2048]; CK_ULONG buf_len; piv_obj_id_t certs[4]; CK_ULONG n_cert = 0; - if (state == NULL || obj == NULL || len == NULL_PTR) + if (state == NULL || len == NULL_PTR) return CKR_ARGUMENTS_BAD; + if (num_only == CK_FALSE && obj == NULL) + return CKR_ARGUMENTS_BAD; + buf_len = sizeof(buf); if (ykpiv_fetch_object(state, YKPIV_OBJ_AUTHENTICATION, buf, &buf_len) == YKPIV_OK) { n_cert++; @@ -293,10 +289,18 @@ CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULO if (ykpiv_fetch_object(state, YKPIV_OBJ_CARD_AUTH, buf, &buf_len) == YKPIV_OK) { n_cert++; certs[3] = PIV_CERT_OBJ_X509_CARD_AUTH; - fprintf(stderr, "Found CARD AUTH cert\n"); + fprintf(stderr, "Found CARD AUTH cert (9e)\n"); } - if (n_cert + token_objects_num > *len) + fprintf(stderr, "The total number of objects for this token is %lu\n", n_cert + token_objects_num); + + if (num_only == CK_TRUE) { + // We just want the number of objects + *len = n_cert + token_objects_num; + return CKR_OK; + } + + if (*len < n_cert + token_objects_num) return CKR_BUFFER_TOO_SMALL; // Copy mandatory data objects @@ -305,8 +309,13 @@ CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULO // Copy certificates memcpy(obj + token_objects_num, certs, n_cert * sizeof(piv_obj_id_t)); - *len = token_objects_num + n_cert; - fprintf(stderr, "The total number of objects for this token is %lu\n", *len); - return CKR_OK; } + +CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num) { + return get_objects(state, CK_TRUE, NULL, num); +} + +CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num) { + return get_objects(state, CK_FALSE, obj, &num); +} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index 4e884b8..73edc71 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -18,7 +18,7 @@ CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VER CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num); CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num); CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info); -//CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num); -CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t * obj, CK_ULONG_PTR num); +CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num); +CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t * obj, CK_ULONG num); #endif From 07379a5c6067cce8c6a80e3b588cf13ea0808ce6 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 28 Jul 2015 10:33:47 +0200 Subject: [PATCH 038/134] Separated slot vendors and token vendors. --- ykcs11/Makefile.am | 5 ++- ykcs11/slot_vendors.c | 25 +++++++++++++++ ykcs11/slot_vendors.h | 22 ++++++++++++++ ykcs11/token_vendors.c | 39 ++++++++++++++++++++++++ ykcs11/token_vendors.h | 37 +++++++++++++++++++++++ ykcs11/utils.c | 37 ++++++++++++----------- ykcs11/vendor_ids.h | 10 ++++++ ykcs11/vendors.c | 46 ---------------------------- ykcs11/vendors.h | 47 ++--------------------------- ykcs11/ykcs11.c | 31 +++++++++---------- ykcs11/yubico_slot.c | 44 +++++++++++++++++++++++++++ ykcs11/yubico_slot.h | 11 +++++++ ykcs11/{yubico.c => yubico_token.c} | 43 +------------------------- ykcs11/{yubico.h => yubico_token.h} | 8 ++--- 14 files changed, 231 insertions(+), 174 deletions(-) create mode 100644 ykcs11/slot_vendors.c create mode 100644 ykcs11/slot_vendors.h create mode 100644 ykcs11/token_vendors.c create mode 100644 ykcs11/token_vendors.h create mode 100644 ykcs11/vendor_ids.h create mode 100644 ykcs11/yubico_slot.c create mode 100644 ykcs11/yubico_slot.h rename ykcs11/{yubico.c => yubico_token.c} (90%) rename ykcs11/{yubico.h => yubico_token.h} (75%) diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index f891949..339bcaa 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -34,7 +34,10 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map -libykcs11_la_SOURCES += vendors.c vendor.h yubico.c yubico.h +libykcs11_la_SOURCES += vendors.c vendor.h vendor_ids.h +libykcs11_la_SOURCES += slot_vendors.c slot_vendor.h +libykcs11_la_SOURCES += token_vendors.c token_vendor.h +libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h libykcs11_la_SOURCES += utils.h utils.c libykcs11_la_SOURCES += obj_types.h objects.h objects.c diff --git a/ykcs11/slot_vendors.c b/ykcs11/slot_vendors.c new file mode 100644 index 0000000..2158512 --- /dev/null +++ b/ykcs11/slot_vendors.c @@ -0,0 +1,25 @@ +#include "slot_vendors.h" +#include "yubico_slot.h" + +slot_vendor_t get_slot_vendor(vendor_id_t vid) { + slot_vendor_t v; + + switch (vid) { + case YUBICO: + v.get_slot_description = YUBICO_get_slot_description; + v.get_slot_manufacturer = YUBICO_get_slot_manufacturer; + v.get_slot_flags = YUBICO_get_slot_flags; + v.get_slot_version = YUBICO_get_slot_version; + break; + + case UNKNOWN: + default: + v.get_slot_description = NULL; + v.get_slot_manufacturer = NULL; + v.get_slot_flags = NULL; + v.get_slot_version = NULL; + } + + return v; + +} diff --git a/ykcs11/slot_vendors.h b/ykcs11/slot_vendors.h new file mode 100644 index 0000000..2426e23 --- /dev/null +++ b/ykcs11/slot_vendors.h @@ -0,0 +1,22 @@ +#ifndef SLOT_VENDORS_H +#define SLOT_VENDORS_H + +#include "pkcs11.h" +#include "vendor_ids.h" + +typedef CK_RV (*get_s_description_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_s_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_s_flags_f)(CK_FLAGS_PTR); +typedef CK_RV (*get_s_version_f)(CK_VERSION_PTR); + + +typedef struct { + get_s_description_f get_slot_description; + get_s_manufacturer_f get_slot_manufacturer; + get_s_flags_f get_slot_flags; + get_s_version_f get_slot_version; +} slot_vendor_t; + +slot_vendor_t get_slot_vendor(vendor_id_t vid); + +#endif diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c new file mode 100644 index 0000000..a19c18e --- /dev/null +++ b/ykcs11/token_vendors.c @@ -0,0 +1,39 @@ +#include "token_vendors.h" +#include "yubico_token.h" + +token_vendor_t get_token_vendor(vendor_id_t vid) { + token_vendor_t v; + + switch (vid) { + case YUBICO: + v.get_token_label = YUBICO_get_token_label; + v.get_token_manufacturer = YUBICO_get_token_manufacturer; + v.get_token_model = YUBICO_get_token_model; + v.get_token_flags = YUBICO_get_token_flags; + v.get_token_version = YUBICO_get_token_version; + v.get_token_serial = YUBICO_get_token_serial; + v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; + v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; + v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; + v.get_token_objects_num = YUBICO_get_token_objects_num; + v.get_token_object_list = YUBICO_get_token_object_list; + break; + + case UNKNOWN: + default: + v.get_token_label = NULL; + v.get_token_manufacturer = NULL; + v.get_token_model = NULL; + v.get_token_flags = NULL; + v.get_token_version = NULL; + v.get_token_serial = NULL; + v.get_token_mechanisms_num = NULL; + v.get_token_mechanism_list = NULL; + v.get_token_mechanism_info = NULL; + v.get_token_objects_num = NULL; + v.get_token_object_list = NULL; + } + + return v; + +} diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h new file mode 100644 index 0000000..16b070e --- /dev/null +++ b/ykcs11/token_vendors.h @@ -0,0 +1,37 @@ +#ifndef TOKEN_VENDORS_H +#define TOKEN_VENDORS_H + +#include "pkcs11.h" +#include "vendor_ids.h" +#include "objects.h" +#include + +typedef CK_RV (*get_t_label_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_model_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_flags_f)(CK_FLAGS_PTR); +typedef CK_RV (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG, CK_VERSION_PTR); +typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); +typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); +typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); +typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR); +typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); + +typedef struct { + get_t_label_f get_token_label; + get_t_manufacturer_f get_token_manufacturer; + get_t_model_f get_token_model; + get_t_flags_f get_token_flags; + get_t_version_f get_token_version; + get_t_serial_f get_token_serial; + get_t_mechanisms_num_f get_token_mechanisms_num; + get_t_mechanism_list_f get_token_mechanism_list; + get_t_mechanism_info_f get_token_mechanism_info; + get_t_objects_num_f get_token_objects_num; + get_t_object_list_f get_token_object_list; +} token_vendor_t; + +token_vendor_t get_token_vendor(vendor_id_t vid); + +#endif diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 236153d..13ee44e 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -11,11 +11,11 @@ CK_BBOOL has_token(const ykcs11_slot_t *slot) { CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token) { - CK_BYTE i; - CK_BYTE_PTR p; - CK_BYTE_PTR s; - CK_ULONG l; - vendor_t vendor; + CK_BYTE i; + CK_BYTE_PTR p; + CK_BYTE_PTR s; + CK_ULONG l; + slot_vendor_t slot; *n_slots = 0; *n_with_token = 0; @@ -42,30 +42,30 @@ CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, } else { // Supported slot - vendor = get_vendor(slots[*n_slots].vid); + slot = get_slot_vendor(slots[*n_slots].vid); // Values must NOT be null terminated and ' ' padded memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); s = slots[*n_slots].info.slotDescription; l = sizeof(slots[*n_slots].info.slotDescription); - if (vendor.get_slot_description(s, l) != CKR_OK) + if (slot.get_slot_description(s, l) != CKR_OK) goto failure; memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID)); s = slots[*n_slots].info.manufacturerID; l = sizeof(slots[*n_slots].info.manufacturerID); - if(vendor.get_slot_manufacturer(s, l) != CKR_OK) + if(slot.get_slot_manufacturer(s, l) != CKR_OK) goto failure; - if (vendor.get_slot_flags(&slots[*n_slots].info.flags) != CKR_OK) + if (slot.get_slot_flags(&slots[*n_slots].info.flags) != CKR_OK) goto failure; // Treating hw and fw version the same - if (vendor.get_slot_version(&slots[*n_slots].info.hardwareVersion) != CKR_OK) + if (slot.get_slot_version(&slots[*n_slots].info.hardwareVersion) != CKR_OK) goto failure; - if (vendor.get_slot_version(&slots[*n_slots].info.firmwareVersion) != CKR_OK) + if (slot.get_slot_version(&slots[*n_slots].info.firmwareVersion) != CKR_OK) goto failure; if (has_token(slots + *n_slots)) { @@ -92,7 +92,8 @@ failure: } CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { - vendor_t token_vendor; + + token_vendor_t token; CK_TOKEN_INFO_PTR t_info; fprintf(stderr, "Now trying to get token info from %s\n", p); // TODO: is p needed? @@ -101,27 +102,27 @@ CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { return CKR_HOST_MEMORY; slot->token->vid = YUBICO; // TODO: this must become "slot_vendor.get_token_vid()" - token_vendor = get_vendor(slot->token->vid); + token = get_token_vendor(slot->token->vid); t_info = &slot->token->info; memset(t_info->label, ' ', sizeof(t_info->label)); - if (token_vendor.get_token_label(t_info->label, sizeof(t_info->label)) != CKR_OK) + if (token.get_token_label(t_info->label, sizeof(t_info->label)) != CKR_OK) return CKR_FUNCTION_FAILED; memset(t_info->manufacturerID, ' ', sizeof(t_info->manufacturerID)); - if(token_vendor.get_token_manufacturer(t_info->manufacturerID, sizeof(t_info->manufacturerID)) != CKR_OK) + if(token.get_token_manufacturer(t_info->manufacturerID, sizeof(t_info->manufacturerID)) != CKR_OK) return CKR_FUNCTION_FAILED; memset(t_info->model, ' ', sizeof(t_info->model)); - if(token_vendor.get_token_model(t_info->model, sizeof(t_info->model)) != CKR_OK) + if(token.get_token_model(t_info->model, sizeof(t_info->model)) != CKR_OK) return CKR_FUNCTION_FAILED; memset(t_info->serialNumber, ' ', sizeof(t_info->serialNumber)); - if(token_vendor.get_token_serial(t_info->serialNumber, sizeof(t_info->serialNumber)) != CKR_OK) + if(token.get_token_serial(t_info->serialNumber, sizeof(t_info->serialNumber)) != CKR_OK) return CKR_FUNCTION_FAILED; - if (token_vendor.get_token_flags(&t_info->flags) != CKR_OK) + if (token.get_token_flags(&t_info->flags) != CKR_OK) return CKR_FUNCTION_FAILED; t_info->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; diff --git a/ykcs11/vendor_ids.h b/ykcs11/vendor_ids.h new file mode 100644 index 0000000..8505750 --- /dev/null +++ b/ykcs11/vendor_ids.h @@ -0,0 +1,10 @@ +#ifndef VENDOR_IDS_H +#define VENDOR_IDS_H + +typedef enum { + UNKNOWN = 0x00, + YUBICO = 0x01 +} vendor_id_t; + + +#endif diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index b4fd55d..25683f5 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -1,5 +1,4 @@ #include "vendors.h" -#include "yubico.h" #include vendor_id_t get_vendor_id(char *vendor_name) { @@ -10,48 +9,3 @@ vendor_id_t get_vendor_id(char *vendor_name) { return UNKNOWN; } - -vendor_t get_vendor(vendor_id_t vid) { - vendor_t v; - - switch (vid) { - case YUBICO: - v.get_slot_description = YUBICO_get_slot_description; - v.get_slot_manufacturer = YUBICO_get_slot_manufacturer; - v.get_slot_flags = YUBICO_get_slot_flags; - v.get_slot_version = YUBICO_get_slot_version; - v.get_token_label = YUBICO_get_token_label; - v.get_token_manufacturer = YUBICO_get_token_manufacturer; - v.get_token_model = YUBICO_get_token_model; - v.get_token_flags = YUBICO_get_token_flags; - v.get_token_version = YUBICO_get_token_version; - v.get_token_serial = YUBICO_get_token_serial; - v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; - v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; - v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; - v.get_token_objects_num = YUBICO_get_token_objects_num; - v.get_token_object_list = YUBICO_get_token_object_list; - break; - - case UNKNOWN: - default: - v.get_slot_description = NULL; - v.get_slot_manufacturer = NULL; - v.get_slot_flags = NULL; - v.get_slot_version = NULL; - v.get_token_label = NULL; - v.get_token_manufacturer = NULL; - v.get_token_model = NULL; - v.get_token_flags = NULL; - v.get_token_version = NULL; - v.get_token_serial = NULL; - v.get_token_mechanisms_num = NULL; - v.get_token_mechanism_list = NULL; - v.get_token_mechanism_info = NULL; - v.get_token_objects_num = NULL; - v.get_token_object_list = NULL; - } - - return v; - -} diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index cba0763..4125d22 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -1,51 +1,10 @@ #ifndef VENDORS_H #define VENDORS_H -#include "pkcs11.h" -#include "objects.h" -#include - -typedef enum { - UNKNOWN = 0x00, - YUBICO = 0x01 -} vendor_id_t; - -typedef CK_RV (*get_s_description_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*get_s_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*get_s_flags_f)(CK_FLAGS_PTR); -typedef CK_RV (*get_s_version_f)(CK_VERSION_PTR); -typedef CK_RV (*get_t_label_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*get_t_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*get_t_model_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*get_t_flags_f)(CK_FLAGS_PTR); -typedef CK_RV (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG, CK_VERSION_PTR); -typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); -typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); -typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); -typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); -typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR); -typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); - - -typedef struct { - get_s_description_f get_slot_description; - get_s_manufacturer_f get_slot_manufacturer; - get_s_flags_f get_slot_flags; - get_s_version_f get_slot_version; - get_t_label_f get_token_label; - get_t_manufacturer_f get_token_manufacturer; - get_t_model_f get_token_model; - get_t_flags_f get_token_flags; - get_t_version_f get_token_version; - get_t_serial_f get_token_serial; - get_t_mechanisms_num_f get_token_mechanisms_num; - get_t_mechanism_list_f get_token_mechanism_list; - get_t_mechanism_info_f get_token_mechanism_info; - get_t_objects_num_f get_token_objects_num; - get_t_object_list_f get_token_object_list; -} vendor_t; +#include "vendor_ids.h" +#include "slot_vendors.h" +#include "token_vendors.h" vendor_id_t get_vendor_id(char *vendor_name); -vendor_t get_vendor(vendor_id_t vid); #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 934076b..40a237d 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -237,7 +237,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( { DIN; CK_VERSION ver = {0, 0}; - vendor_t token_vendor; + token_vendor_t token; CK_BYTE buf[64]; if (piv_state == NULL) @@ -261,7 +261,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( return CKR_TOKEN_NOT_RECOGNIZED; } - token_vendor = get_vendor(slots[slotID].token->vid); + token = get_token_vendor(slots[slotID].token->vid); memcpy(pInfo, &slots[slotID].token->info, sizeof(CK_TOKEN_INFO)); @@ -278,7 +278,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; - DOUT; return CKR_OK; @@ -303,7 +302,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( ) { DIN; - vendor_t vendor; + token_vendor_t token; CK_ULONG count; if (piv_state == NULL) { @@ -322,9 +321,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( // TODO: check more return values // TODO: user NULL_PTR more for coherence - vendor = get_vendor(slots[slotID].vid); // TODO: make a token field in slot_t ?; + token = get_token_vendor(slots[slotID].vid); - if (vendor.get_token_mechanisms_num(&count) != CKR_OK) + if (token.get_token_mechanisms_num(&count) != CKR_OK) return CKR_FUNCTION_FAILED; if (pMechanismList == NULL_PTR) { @@ -339,7 +338,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( return CKR_BUFFER_TOO_SMALL; } - if (vendor.get_token_mechanism_list(pMechanismList, *pulCount) != CKR_OK) + if (token.get_token_mechanism_list(pMechanismList, *pulCount) != CKR_OK) return CKR_FUNCTION_FAILED; DOUT; @@ -353,7 +352,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( ) { DIN; - vendor_t vendor; + token_vendor_t token; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -371,9 +370,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( // TODO: check more return values // TODO: user NULL_PTR more for coherence - vendor = get_vendor(slots[slotID].vid); // TODO: make a token field in slot_t ?; + token = get_token_vendor(slots[slotID].vid); - if (vendor.get_token_mechanism_info(type, pInfo) != CKR_OK) + if (token.get_token_mechanism_info(type, pInfo) != CKR_OK) return CKR_MECHANISM_INVALID; DOUT; @@ -428,7 +427,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( { DIN; - vendor_t token_vendor; + token_vendor_t token; if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -461,14 +460,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_SESSION_PARALLEL_NOT_SUPPORTED; } - token_vendor = get_vendor(slots[slotID].token->vid); + token = get_token_vendor(slots[slotID].token->vid); // Store the slot session.slot = slots + slotID; //session.slot->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO // Get the number of token objects - if (token_vendor.get_token_objects_num(piv_state, &session.slot->token->n_objects) != CKR_OK) { + if (token.get_token_objects_num(piv_state, &session.slot->token->n_objects) != CKR_OK) { DBG(("Unable to retrieve number of token objects")); return CKR_FUNCTION_FAILED; } @@ -481,7 +480,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( } // Store all the objects available in the token - if (token_vendor.get_token_object_list(piv_state, + if (token.get_token_object_list(piv_state, session.slot->token->objects, session.slot->token->n_objects) != CKR_OK) { DBG(("Unable to retrieve token objects")); @@ -789,7 +788,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( { DIN; CK_ULONG i; - vendor_t vendor; + //token_vendor_t token; if (piv_state == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -803,8 +802,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( if (find_obj.active == CK_TRUE) return CKR_OPERATION_ACTIVE; - //vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?; - find_obj.idx = 0; find_obj.num = session.slot->token->n_objects; diff --git a/ykcs11/yubico_slot.c b/ykcs11/yubico_slot.c new file mode 100644 index 0000000..abfc8aa --- /dev/null +++ b/ykcs11/yubico_slot.c @@ -0,0 +1,44 @@ +#include "yubico_slot.h" +#include "pkcs11.h" +#include + +static const CK_UTF8CHAR_PTR slot_description = "YubiKey Virtual Reader"; +static const CK_UTF8CHAR_PTR slot_manufacturer = "Yubico"; +static const CK_FLAGS slot_flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; +static const CK_VERSION slot_version = {1, 0}; + +CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len) { + + if (strlen(slot_description) > len) + return CKR_BUFFER_TOO_SMALL; + + memcpy(str, slot_description, strlen(slot_description)); + return CKR_OK; + +} + +CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len) { + + if (strlen(slot_manufacturer) > len) + return CKR_BUFFER_TOO_SMALL; + + memcpy(str, slot_manufacturer, strlen(slot_manufacturer)); + return CKR_OK; + +} + +CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags) { + + *flags = slot_flags; + return CKR_OK; + +} + +CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version) { + + version->major = slot_version.major; + version->minor = slot_version.minor; + + return CKR_OK; + +} diff --git a/ykcs11/yubico_slot.h b/ykcs11/yubico_slot.h new file mode 100644 index 0000000..4bd617d --- /dev/null +++ b/ykcs11/yubico_slot.h @@ -0,0 +1,11 @@ +#ifndef YUBICO_SLOT_H +#define YUBICO_SLOT_H + +#include "pkcs11.h" + +CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags); +CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version); + +#endif diff --git a/ykcs11/yubico.c b/ykcs11/yubico_token.c similarity index 90% rename from ykcs11/yubico.c rename to ykcs11/yubico_token.c index c3f8f17..d86dc17 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico_token.c @@ -1,4 +1,4 @@ -#include "yubico.h" +#include "yubico_token.h" #include "pkcs11.h" #include @@ -9,11 +9,6 @@ #define MIN_ECC_KEY_SIZE 256 #define MAX_ECC_KEY_SIZE 384 -// TODO add a type in vendor_t for SLOT | READER -static const CK_UTF8CHAR_PTR slot_description = "YubiKey Virtual Reader"; -static const CK_UTF8CHAR_PTR slot_manufacturer = "Yubico"; -static const CK_FLAGS slot_flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; -static const CK_VERSION slot_version = {1, 0}; static const CK_UTF8CHAR_PTR token_label = "YubiKey PIV X"; static const CK_UTF8CHAR_PTR token_manufacturer = "Yubico"; static const CK_UTF8CHAR_PTR token_model = "YubiKey MODEL"; @@ -107,42 +102,6 @@ static const piv_obj_id_t token_objects[] = { // TODO: is there a way to get thi }; static const CK_ULONG token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t); -CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len) { - - if (strlen(slot_description) > len) - return CKR_BUFFER_TOO_SMALL; - - memcpy(str, slot_description, strlen(slot_description)); - return CKR_OK; - -} - -CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len) { - - if (strlen(slot_manufacturer) > len) - return CKR_BUFFER_TOO_SMALL; - - memcpy(str, slot_manufacturer, strlen(slot_manufacturer)); - return CKR_OK; - -} - -CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags) { - - *flags = slot_flags; - return CKR_OK; - -} - -CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version) { - - version->major = slot_version.major; - version->minor = slot_version.minor; - - return CKR_OK; - -} - CK_RV YUBICO_get_token_label(CK_UTF8CHAR_PTR str, CK_ULONG len) { if (strlen(token_label) > len) diff --git a/ykcs11/yubico.h b/ykcs11/yubico_token.h similarity index 75% rename from ykcs11/yubico.h rename to ykcs11/yubico_token.h index 73edc71..d0c9f7a 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico_token.h @@ -1,14 +1,10 @@ -#ifndef YUBICO_H -#define YUBICO_H +#ifndef YUBICO_TOKEN_H +#define YUBICO_TOKEN_H #include "pkcs11.h" #include "obj_types.h" #include -CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len); -CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); -CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags); -CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version); CK_RV YUBICO_get_token_label(CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_token_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_token_model(CK_UTF8CHAR_PTR str, CK_ULONG len); From bd144cc6211df63b72b7a4bb44df019d1ebe3ee5 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 28 Jul 2015 17:57:38 +0200 Subject: [PATCH 039/134] Yet another refactor of objects. --- ykcs11/Makefile.am | 1 + ykcs11/mechanisms.c | 70 +++- ykcs11/mechanisms.h | 6 +- ykcs11/obj_types.h | 181 +++++----- ykcs11/objects.c | 796 ++++++++++++++++++++++++++++++++--------- ykcs11/objects.h | 6 +- ykcs11/token_vendors.h | 2 +- ykcs11/utils.c | 2 +- ykcs11/utils.h | 1 + ykcs11/ykcs11.c | 81 +++-- ykcs11/ykcs11.h | 1 + ykcs11/yubico_token.c | 63 ++-- 12 files changed, 884 insertions(+), 326 deletions(-) diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index 339bcaa..d93c75c 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -37,6 +37,7 @@ libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map libykcs11_la_SOURCES += vendors.c vendor.h vendor_ids.h libykcs11_la_SOURCES += slot_vendors.c slot_vendor.h libykcs11_la_SOURCES += token_vendors.c token_vendor.h +libykcs11_la_SOURCES += mechanisms.c mechanisms.h libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h libykcs11_la_SOURCES += utils.h utils.c libykcs11_la_SOURCES += obj_types.h objects.h objects.c diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index b232d9d..b63ea59 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -1,7 +1,7 @@ #include "mechanisms.h" // Supported mechanisms for signature -static const CK_MECHANISM_TYPE sign[] = { +static const CK_MECHANISM_TYPE sign_mechanisms[] = { CKM_RSA_PKCS, CKM_RSA_PKCS_PSS, CKM_RSA_X_509, @@ -17,14 +17,16 @@ static const CK_MECHANISM_TYPE sign[] = { CKM_ECDSA_SHA1 }; -CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m, const CK_OBJECT_HANDLE k) { +CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) { - CK_ULONG i; - CK_BBOOL supported = CK_FALSE; + CK_ULONG i; + CK_BBOOL supported = CK_FALSE; + token_vendor_t token; + CK_MECHANISM_INFO info; - /* Check if mechanism is supported by the module */ - for (i = 0; i < sizeof(sign) / sizeof(CK_MECHANISM_TYPE); i++) { - if (m->mechanism == sign[i]) { + // Check if the mechanism is supported by the module + for (i = 0; i < sizeof(sign_mechanisms) / sizeof(CK_MECHANISM_TYPE); i++) { + if (m->mechanism == sign_mechanisms[i]) { supported = CK_TRUE; break; } @@ -32,9 +34,53 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m, if (supported == CK_FALSE) return CKR_MECHANISM_INVALID; - /* Check if mechanism is supported by the token */ - - - CK_OK; - + // Check if the mechanism is supported by the token + token = get_token_vendor(s->slot->token->vid); + + if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK) + return CKR_MECHANISM_INVALID; + + // TODO: also check that parametes make sens if any? + + CKR_OK; + +} + +CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) { + + switch (m) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + case CKM_RSA_PKCS: + case CKM_RSA_9796: + case CKM_RSA_X_509: + case CKM_MD2_RSA_PKCS: + case CKM_MD5_RSA_PKCS: + case CKM_SHA1_RSA_PKCS: +// case CKM_SHA224_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: +// case CKM_RIPEMD128_RSA_PKCS: +// case CKM_RIPEMD160_RSA_PKCS: +// case CKM_RSA_PKCS_OAEP: +// case CKM_RSA_X9_31_KEY_PAIR_GEN: +// case CKM_RSA_X9_31: +// case CKM_SHA1_RSA_X9_31: + case CKM_RSA_PKCS_PSS: + case CKM_SHA1_RSA_PKCS_PSS: +// case CKM_SHA224_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: +// case CKM_RSA_PKCS_TPM_1_1: +// case CKM_RSA_PKCS_OAEP_TPM_1_1: +// case CKM_RSA_AES_KEY_WRAP: + return CK_TRUE; + + default: + return CK_FALSE; + } + + // Not reached + return CK_FALSE; } diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index 5c5e02f..f95565e 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -1,10 +1,10 @@ #ifndef MECHANISMS_H #define MECHANISMS_H -#include "pkcs11t.h" +#include "ykcs11.h" -CK_RV check_sign_mechanism(const CK_MECHANISM_PTR m, const CK_OBJECT_HANDLE k); - +CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); +CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); #endif diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 5e8aa4b..5d02a62 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -5,88 +5,96 @@ // TODO: this is mostly from OpenSC, how to give credit? typedef enum { - PIV_DATA_OBJ_CCC = 0, // Card capability container - PIV_DATA_OBJ_CHUI, // Cardholder unique id - /* PIV_DATA_OBJ_UCHUI is not in new with 800-73-2 */ - PIV_DATA_OBJ_X509_PIV_AUTH, // PIV authentication - PIV_DATA_OBJ_CHF, // Cardholder fingerprints - PIV_DATA_OBJ_SEC_OBJ, // Security object - PIV_DATA_OBJ_CHFI, // Cardholder facial images - PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication - PIV_DATA_OBJ_X509_DS, // Certificate for digital signature - PIV_DATA_OBJ_X509_KM, // Certificate for key management - PIV_DATA_OBJ_PI, // Cardholder printed information - PIV_DATA_OBJ_DISCOVERY, // Discovery object - PIV_DATA_OBJ_HISTORY, // History object - PIV_DATA_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 - PIV_DATA_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 - PIV_DATA_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 - PIV_DATA_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 - PIV_DATA_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 - PIV_DATA_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 - PIV_DATA_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 - PIV_DATA_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 - PIV_DATA_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 - PIV_DATA_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 - PIV_DATA_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 - PIV_DATA_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 - PIV_DATA_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 - PIV_DATA_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 - PIV_DATA_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 - PIV_DATA_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 - PIV_DATA_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 - PIV_DATA_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 - PIV_DATA_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 - PIV_DATA_OBJ_RETIRED_X509_20, // Retired certificate for KM 20 - PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images - PIV_DATA_OBJ_BITGT, // Biometric information templates group template - PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer - PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data + PIV_DATA_OBJ_X509_PIV_AUTH = 0, // PIV authentication + PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_DATA_OBJ_X509_DS, // Certificate for digital signature + PIV_DATA_OBJ_X509_KM, // Certificate for key management + PIV_DATA_OBJ_CCC, // Card capability container + PIV_DATA_OBJ_CHUI, // Cardholder unique id + PIV_DATA_OBJ_CHF, // Cardholder fingerprints + PIV_DATA_OBJ_SEC_OBJ, // Security object + PIV_DATA_OBJ_CHFI, // Cardholder facial images + PIV_DATA_OBJ_PI, // Cardholder printed information + PIV_DATA_OBJ_DISCOVERY, // Discovery object + PIV_DATA_OBJ_HISTORY, // History object + PIV_DATA_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 + PIV_DATA_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 + PIV_DATA_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 + PIV_DATA_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 + PIV_DATA_OBJ_RETIRED_X509_5, // Retired certificate for KM 5 + PIV_DATA_OBJ_RETIRED_X509_6, // Retired certificate for KM 6 + PIV_DATA_OBJ_RETIRED_X509_7, // Retired certificate for KM 7 + PIV_DATA_OBJ_RETIRED_X509_8, // Retired certificate for KM 8 + PIV_DATA_OBJ_RETIRED_X509_9, // Retired certificate for KM 9 + PIV_DATA_OBJ_RETIRED_X509_10, // Retired certificate for KM 10 + PIV_DATA_OBJ_RETIRED_X509_11, // Retired certificate for KM 11 + PIV_DATA_OBJ_RETIRED_X509_12, // Retired certificate for KM 12 + PIV_DATA_OBJ_RETIRED_X509_13, // Retired certificate for KM 13 + PIV_DATA_OBJ_RETIRED_X509_14, // Retired certificate for KM 14 + PIV_DATA_OBJ_RETIRED_X509_15, // Retired certificate for KM 15 + PIV_DATA_OBJ_RETIRED_X509_16, // Retired certificate for KM 16 + PIV_DATA_OBJ_RETIRED_X509_17, // Retired certificate for KM 17 + PIV_DATA_OBJ_RETIRED_X509_18, // Retired certificate for KM 18 + PIV_DATA_OBJ_RETIRED_X509_19, // Retired certificate for KM 19 + PIV_DATA_OBJ_RETIRED_X509_20, // Retired certificate for KM 20 + PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images + PIV_DATA_OBJ_BITGT, // Biometric information templates group template + PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer + PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data /* PIV_DATA_OBJ_9B03, // NON-STANDARD TODO: remove? - PIV_DATA_OBJ_9A06, // NON-STANDARD - PIV_DATA_OBJ_9C06, // NON-STANDARD - PIV_DATA_OBJ_9D06, // NON-STANDARD - PIV_DATA_OBJ_9E06, // NON-STANDARD - PIV_DATA_OBJ_8206, // NON-STANDARD - PIV_DATA_OBJ_8306, // NON-STANDARD - PIV_DATA_OBJ_8406, // NON-STANDARD - PIV_DATA_OBJ_8506, // NON-STANDARD - PIV_DATA_OBJ_8606, // NON-STANDARD - PIV_DATA_OBJ_8706, // NON-STANDARD - PIV_DATA_OBJ_8806, // NON-STANDARD - PIV_DATA_OBJ_8906, // NON-STANDARD - PIV_DATA_OBJ_8A06, // NON-STANDARD - PIV_DATA_OBJ_8B06, // NON-STANDARD - PIV_DATA_OBJ_8C06, // NON-STANDARD - PIV_DATA_OBJ_8D06, // NON-STANDARD - PIV_DATA_OBJ_8E06, // NON-STANDARD - PIV_DATA_OBJ_8F06, // NON-STANDARD - PIV_DATA_OBJ_9006, // NON-STANDARD - PIV_DATA_OBJ_9106, // NON-STANDARD - PIV_DATA_OBJ_9206, // NON-STANDARD - PIV_DATA_OBJ_9306, // NON-STANDARD - PIV_DATA_OBJ_9406, // NON-STANDARD - PIV_DATA_OBJ_9506, // NON-STANDARD*/ + PIV_DATA_OBJ_9A06, // NON-STANDARD + PIV_DATA_OBJ_9C06, // NON-STANDARD + PIV_DATA_OBJ_9D06, // NON-STANDARD + PIV_DATA_OBJ_9E06, // NON-STANDARD + PIV_DATA_OBJ_8206, // NON-STANDARD + PIV_DATA_OBJ_8306, // NON-STANDARD + PIV_DATA_OBJ_8406, // NON-STANDARD + PIV_DATA_OBJ_8506, // NON-STANDARD + PIV_DATA_OBJ_8606, // NON-STANDARD + PIV_DATA_OBJ_8706, // NON-STANDARD + PIV_DATA_OBJ_8806, // NON-STANDARD + PIV_DATA_OBJ_8906, // NON-STANDARD + PIV_DATA_OBJ_8A06, // NON-STANDARD + PIV_DATA_OBJ_8B06, // NON-STANDARD + PIV_DATA_OBJ_8C06, // NON-STANDARD + PIV_DATA_OBJ_8D06, // NON-STANDARD + PIV_DATA_OBJ_8E06, // NON-STANDARD + PIV_DATA_OBJ_8F06, // NON-STANDARD + PIV_DATA_OBJ_9006, // NON-STANDARD + PIV_DATA_OBJ_9106, // NON-STANDARD + PIV_DATA_OBJ_9206, // NON-STANDARD + PIV_DATA_OBJ_9306, // NON-STANDARD + PIV_DATA_OBJ_9406, // NON-STANDARD + PIV_DATA_OBJ_9506, // NON-STANDARD*/ PIV_DATA_OBJ_LAST, - PIV_CERT_OBJ_X509_PIV_AUTH, // PIV authentication - PIV_CERT_OBJ_X509_CARD_AUTH, // Certificate for card authentication - PIV_CERT_OBJ_X509_DS, // Certificate for digital signature - PIV_CERT_OBJ_X509_KM, // Certificate for key management - PIV_CERT_OBJ_LAST - // TODO: private keys? + PIV_CERT_OBJ_X509_PIV_AUTH, // PIV authentication + PIV_CERT_OBJ_X509_CARD_AUTH, // Certificate for card authentication + PIV_CERT_OBJ_X509_DS, // Certificate for digital signature + PIV_CERT_OBJ_X509_KM, // Certificate for key management + PIV_CERT_OBJ_LAST, + + PIV_PVTK_OBJ_PIV_AUTH, // Private key for PIV authentication + PIV_PVTK_OBJ_CARD_AUTH, // Private Key for card authentication + PIV_PVTK_OBJ_DS, // Private Key for digital signature + PIV_PVTK_OBJ_KM, // Private Key for key management + PIV_PVTK_OBJ_LAST, + + PIV_PUBK_OBJ_PIV_AUTH, // Public key for PIV authentication + PIV_PUBK_OBJ_CARD_AUTH, // Public Key for card authentication + PIV_PUBK_OBJ_DS, // Public Key for digital signature + PIV_PUBK_OBJ_KM, // Public Key for key management + PIV_PUBK_OBJ_LAST + } piv_obj_id_t; - -/*#define PIV_OBJECT_TYPE_CERT 1 // TODO: redundant now? -#define PIV_OBJECT_TYPE_PUBKEY 2 -#define PIV_OBJECT_NOT_PRESENT 4*/ +typedef CK_RV (*get_attr_f)(CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR); typedef struct { const char *oid; - CK_BYTE tag_len; // TODO: or ulong? - CK_BYTE tag_value[3]; // TODO: needed? - CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed? + CK_BYTE tag_len; + CK_BYTE tag_value[3]; // TODO: needed? + CK_BYTE containerid[2]; /* will use as relative paths for simulation */ // TODO: needed? } piv_data_obj_t; typedef struct { @@ -94,14 +102,23 @@ typedef struct { } piv_cert_obj_t; typedef struct { - piv_obj_id_t type; // TODO: technically redundant - CK_BBOOL token; // TODO: not used yet - CK_BBOOL private; - CK_BBOOL modifiable; - const char *label; - CK_BBOOL copyable; - CK_BBOOL destroyable; -CK_ULONG sub_id; + CK_BBOOL todo; +} piv_pvtk_obj_t; + +typedef struct { + CK_BBOOL todo; +} piv_pubk_obj_t; + +typedef struct { + piv_obj_id_t piv_id; // TODO: technically redundant + CK_BBOOL token; // TODO: not used yet + CK_BBOOL private; + CK_BBOOL modifiable; + char *label; + CK_BBOOL copyable; // TODO: Optional, not used so far (default TRUE) + CK_BBOOL destroyable; // TODO: Optional, not used so far (default TRUE) + get_attr_f get_attribute; + CK_ULONG sub_id; // Sub-object id } piv_obj_t; #endif diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 5845d53..cbc008e 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1,91 +1,84 @@ +#include "obj_types.h" #include "objects.h" #include #include #include +CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); // TODO: static? +CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); +CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); +CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); + //TODO: this is mostly a snippet from OpenSC how to give credit? Less and less so now /* Must be in order, and one per enumerated PIV_OBJ */ -static piv_obj_t objects[] = { - {PIV_DATA_OBJ_CCC, 0, 0, 0, "Card Capability Container", 0, 0, 0}, - {PIV_DATA_OBJ_CHUI, 0, 0, 0, "Card Holder Unique Identifier", 0, 0, 1}, - // PIV_DATA_OBJ_UCHUI - {PIV_DATA_OBJ_X509_PIV_AUTH, 0, 0, 0, "X.509 Certificate for PIV Authentication", 0, 0, 2}, - {PIV_DATA_OBJ_CHF, 0, 0, 0, "Card Holder Fingerprints", 0, 0, 3}, - {PIV_DATA_OBJ_SEC_OBJ, 0, 0, 0, "Security Object", 0, 0, 4}, - {PIV_DATA_OBJ_CHFI, 0, 0, 0, "Cardholder Facial Images", 0, 0, 5}, - {PIV_DATA_OBJ_X509_CARD_AUTH, 0, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, 6}, - {PIV_DATA_OBJ_X509_DS, 0, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, 7}, - {PIV_DATA_OBJ_X509_KM, 0, 0, 0, "X.509 Certificate for Key Management", 0, 0, 8}, - {PIV_DATA_OBJ_PI, 0, 0, 0, "Printed Information", 0, 0, 9}, - {PIV_DATA_OBJ_DISCOVERY, 0, 0, 0, "Discovery Object", 0, 0, 10}, - {PIV_DATA_OBJ_HISTORY, 0, 0, 0, "Key History Object", 0, 0, 11}, - {PIV_DATA_OBJ_RETIRED_X509_1, 0, 0, 0, "Retired X.509 Certificate for Key Management 1", 0, 0, 12}, - {PIV_DATA_OBJ_RETIRED_X509_2, 0, 0, 0, "Retired X.509 Certificate for Key Management 2", 0, 0, 13}, - {PIV_DATA_OBJ_RETIRED_X509_3, 0, 0, 0, "Retired X.509 Certificate for Key Management 3", 0, 0, 14}, - {PIV_DATA_OBJ_RETIRED_X509_4, 0, 0, 0, "Retired X.509 Certificate for Key Management 4", 0, 0, 15}, - {PIV_DATA_OBJ_RETIRED_X509_5, 0, 0, 0, "Retired X.509 Certificate for Key Management 5", 0, 0, 16}, - {PIV_DATA_OBJ_RETIRED_X509_6, 0, 0, 0, "Retired X.509 Certificate for Key Management 6", 0, 0, 17}, - {PIV_DATA_OBJ_RETIRED_X509_7, 0, 0, 0, "Retired X.509 Certificate for Key Management 7", 0, 0, 18}, - {PIV_DATA_OBJ_RETIRED_X509_8, 0, 0, 0, "Retired X.509 Certificate for Key Management 8", 0, 0, 19}, - {PIV_DATA_OBJ_RETIRED_X509_9, 0, 0, 0, "Retired X.509 Certificate for Key Management 9", 0, 0, 20}, - {PIV_DATA_OBJ_RETIRED_X509_10, 0, 0, 0, "Retired X.509 Certificate for Key Management 10", 0, 0, 21}, - {PIV_DATA_OBJ_RETIRED_X509_11, 0, 0, 0, "Retired X.509 Certificate for Key Management 11", 0, 0, 22}, - {PIV_DATA_OBJ_RETIRED_X509_12, 0, 0, 0, "Retired X.509 Certificate for Key Management 12", 0, 0, 23}, - {PIV_DATA_OBJ_RETIRED_X509_13, 0, 0, 0, "Retired X.509 Certificate for Key Management 13", 0, 0, 24}, - {PIV_DATA_OBJ_RETIRED_X509_14, 0, 0, 0, "Retired X.509 Certificate for Key Management 14", 0, 0, 25}, - {PIV_DATA_OBJ_RETIRED_X509_15, 0, 0, 0, "Retired X.509 Certificate for Key Management 15", 0, 0, 26}, - {PIV_DATA_OBJ_RETIRED_X509_16, 0, 0, 0, "Retired X.509 Certificate for Key Management 16", 0, 0, 27}, - {PIV_DATA_OBJ_RETIRED_X509_17, 0, 0, 0, "Retired X.509 Certificate for Key Management 17", 0, 0, 28}, - {PIV_DATA_OBJ_RETIRED_X509_18, 0, 0, 0, "Retired X.509 Certificate for Key Management 18", 0, 0, 29}, - {PIV_DATA_OBJ_RETIRED_X509_19, 0, 0, 0, "Retired X.509 Certificate for Key Management 19", 0, 0, 30}, - {PIV_DATA_OBJ_RETIRED_X509_20, 0, 0, 0, "Retired X.509 Certificate for Key Management 20", 0, 0, 31}, - {PIV_DATA_OBJ_IRIS_IMAGE, 0, 0, 0, "Cardholder Iris Images", 0, 0, 32}, - {PIV_DATA_OBJ_BITGT, 0, 0, 0, "Biometric Information Templates Group Template", 0, 0, 33}, - {PIV_DATA_OBJ_SM_SIGNER, 0, 0, 0, "Secure Messaging Certificate Signer", 0, 0, 34}, - {PIV_DATA_OBJ_PC_REF_DATA, 0, 0, 0, "Pairing Code Reference Data Container", 0, 0, 35}, -/* {PIV_DATA_OBJ_9B03, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9A06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9C06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9D06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9E06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8206, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8306, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8406, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8506, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8606, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8706, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8806, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8906, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8A06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8B06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8C06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8D06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8E06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_8F06, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9006, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9106, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9206, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9306, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9406, 0, 0, 0, "", 0, 0, }, - {PIV_DATA_OBJ_9506, 0, 0, 0, "", 0, 0, },*/ - {PIV_DATA_OBJ_LAST, 0, 0, 0, "", 0, 0, 36}, - {PIV_CERT_OBJ_X509_PIV_AUTH, 0, 0, 0, "X.509 Certificate for PIV Authentication", 0, 0, 0}, - {PIV_CERT_OBJ_X509_CARD_AUTH, 0, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, 1}, - {PIV_CERT_OBJ_X509_DS, 0, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, 2}, - {PIV_CERT_OBJ_X509_KM, 0, 0, 0, "X.509 Certificate for Key Management", 0, 0, 3}, - {PIV_CERT_OBJ_LAST, 0, 0, 0, "", 0, 41} +static piv_obj_t piv_objects[] = { + {PIV_DATA_OBJ_X509_PIV_AUTH, 1, 0, 0, "X.509 Certificate for PIV Authentication", 0, 0, get_doa, 0}, + {PIV_DATA_OBJ_X509_CARD_AUTH, 1, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, get_doa, 1}, + {PIV_DATA_OBJ_X509_DS, 1, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, get_doa, 2}, + {PIV_DATA_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_doa, 3}, + {PIV_DATA_OBJ_CCC, 1, 0, 0, "Card Capability Container", 0, 0, get_doa, 4}, + {PIV_DATA_OBJ_CHUI, 1, 0, 0, "Card Holder Unique Identifier", 0, 0, get_doa, 5}, + {PIV_DATA_OBJ_CHF, 1, 1, 0, "Card Holder Fingerprints", 0, 0, get_doa, 6}, + {PIV_DATA_OBJ_SEC_OBJ, 1, 0, 0, "Security Object", 0, 0, get_doa, 7}, + {PIV_DATA_OBJ_CHFI, 1, 1, 0, "Cardholder Facial Images", 0, 0, get_doa, 8}, + {PIV_DATA_OBJ_PI, 1, 1, 0, "Printed Information", 0, 0, get_doa, 9}, + {PIV_DATA_OBJ_DISCOVERY, 1, 0, 0, "Discovery Object", 0, 0, get_doa, 10}, + {PIV_DATA_OBJ_HISTORY, 1, 0, 0, "Key History Object", 0, 0, get_doa, 11}, + {PIV_DATA_OBJ_RETIRED_X509_1, 1, 0, 0, "Retired X.509 Certificate for Key Management 1", 0, 0, get_doa, 12}, + {PIV_DATA_OBJ_RETIRED_X509_2, 1, 0, 0, "Retired X.509 Certificate for Key Management 2", 0, 0, get_doa, 13}, + {PIV_DATA_OBJ_RETIRED_X509_3, 1, 0, 0, "Retired X.509 Certificate for Key Management 3", 0, 0, get_doa, 14}, + {PIV_DATA_OBJ_RETIRED_X509_4, 1, 0, 0, "Retired X.509 Certificate for Key Management 4", 0, 0, get_doa, 15}, + {PIV_DATA_OBJ_RETIRED_X509_5, 1, 0, 0, "Retired X.509 Certificate for Key Management 5", 0, 0, get_doa, 16}, + {PIV_DATA_OBJ_RETIRED_X509_6, 1, 0, 0, "Retired X.509 Certificate for Key Management 6", 0, 0, get_doa, 17}, + {PIV_DATA_OBJ_RETIRED_X509_7, 1, 0, 0, "Retired X.509 Certificate for Key Management 7", 0, 0, get_doa, 18}, + {PIV_DATA_OBJ_RETIRED_X509_8, 1, 0, 0, "Retired X.509 Certificate for Key Management 8", 0, 0, get_doa, 19}, + {PIV_DATA_OBJ_RETIRED_X509_9, 1, 0, 0, "Retired X.509 Certificate for Key Management 9", 0, 0, get_doa, 20}, + {PIV_DATA_OBJ_RETIRED_X509_10, 1, 0, 0, "Retired X.509 Certificate for Key Management 10", 0, 0, get_doa, 21}, + {PIV_DATA_OBJ_RETIRED_X509_11, 1, 0, 0, "Retired X.509 Certificate for Key Management 11", 0, 0, get_doa, 22}, + {PIV_DATA_OBJ_RETIRED_X509_12, 1, 0, 0, "Retired X.509 Certificate for Key Management 12", 0, 0, get_doa, 23}, + {PIV_DATA_OBJ_RETIRED_X509_13, 1, 0, 0, "Retired X.509 Certificate for Key Management 13", 0, 0, get_doa, 24}, + {PIV_DATA_OBJ_RETIRED_X509_14, 1, 0, 0, "Retired X.509 Certificate for Key Management 14", 0, 0, get_doa, 25}, + {PIV_DATA_OBJ_RETIRED_X509_15, 1, 0, 0, "Retired X.509 Certificate for Key Management 15", 0, 0, get_doa, 26}, + {PIV_DATA_OBJ_RETIRED_X509_16, 1, 0, 0, "Retired X.509 Certificate for Key Management 16", 0, 0, get_doa, 27}, + {PIV_DATA_OBJ_RETIRED_X509_17, 1, 0, 0, "Retired X.509 Certificate for Key Management 17", 0, 0, get_doa, 28}, + {PIV_DATA_OBJ_RETIRED_X509_18, 1, 0, 0, "Retired X.509 Certificate for Key Management 18", 0, 0, get_doa, 29}, + {PIV_DATA_OBJ_RETIRED_X509_19, 1, 0, 0, "Retired X.509 Certificate for Key Management 19", 0, 0, get_doa, 30}, + {PIV_DATA_OBJ_RETIRED_X509_20, 1, 0, 0, "Retired X.509 Certificate for Key Management 20", 0, 0, get_doa, 31}, + {PIV_DATA_OBJ_IRIS_IMAGE, 1, 1, 0, "Cardholder Iris Images", 0, 0, get_doa, 32}, + {PIV_DATA_OBJ_BITGT, 1, 0, 0, "Biometric Information Templates Group Template", 0, 0, get_doa, 33}, + {PIV_DATA_OBJ_SM_SIGNER, 1, 0, 0, "Secure Messaging Certificate Signer", 0, 0, get_doa, 34}, + {PIV_DATA_OBJ_PC_REF_DATA, 1, 1, 0, "Pairing Code Reference Data Container", 0, 0, get_doa, 35}, + {PIV_DATA_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 36}, + + {PIV_CERT_OBJ_X509_PIV_AUTH, 1, 0, 0, "X.509 Certificate for PIV Authentication", 0, 0, get_coa, 0}, + {PIV_CERT_OBJ_X509_CARD_AUTH, 1, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, get_coa, 1}, + {PIV_CERT_OBJ_X509_DS, 1, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, get_coa, 2}, + {PIV_CERT_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_coa, 3}, + {PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, get_coa, 4}, + + {PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 0, "Pivate key for PIV Authentication", 0, 0, get_proa, 0}, + {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Pivate key for Card Authentication", 0, 0, get_proa, 1}, + {PIV_PVTK_OBJ_DS, 1, 0, 0, "Pivate key for Digital Signature", 0, 0, get_proa, 2}, + {PIV_PVTK_OBJ_KM, 1, 0, 0, "Private key for Key Management", 0, 0, get_proa, 3}, + {PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4}, + + {PIV_PUBK_OBJ_PIV_AUTH, 1, 0, 0, "Public key for PIV Authentication", 0, 0, get_proa, 0}, + {PIV_PUBK_OBJ_CARD_AUTH, 1, 0, 0, "Public key for Card Authentication", 0, 0, get_proa, 1}, + {PIV_PUBK_OBJ_DS, 1, 0, 0, "Public key for Digital Signature", 0, 0, get_proa, 2}, + {PIV_PUBK_OBJ_KM, 1, 0, 0, "Public key for Key Management", 0, 0, get_proa, 3}, + {PIV_PUBK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4} }; static piv_data_obj_t data_objects[] = { - {"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00"}, - {"2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00"}, {"2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01"}, - {"2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10"}, - {"2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00"}, - {"2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30"}, {"2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00"}, {"2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00"}, {"2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02"}, + {"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00"}, + {"2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00"}, + {"2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10"}, + {"2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00"}, + {"2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30"}, {"2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01"}, {"2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50"}, {"2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60"}, @@ -114,64 +107,6 @@ static piv_data_obj_t data_objects[] = { {"2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16"}, {"2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17"}, {"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"}, - -/* following not standard , to be used by piv-tool only for testing */ -/* {PIV_DATA_OBJ_9B03, "3DES-ECB ADM", - "2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 0},*/ - /* Only used when signing a cert req, usually from engine - * after piv-tool generated the key and saved the pub key - * to a file. Note RSA key can be 1024, 2048 or 3072 - * but still use the "9x06" name. - */ -/* {PIV_DATA_OBJ_9A06, "RSA 9A Pub key from last genkey", - "2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9C06, "Pub 9C key from last genkey", - "2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9D06, "Pub 9D key from last genkey", - "2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9E06, "Pub 9E key from last genkey", - "2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", PIV_OBJECT_TYPE_PUBKEY}, - - {PIV_DATA_OBJ_8206, "Pub 82 key ", - "2.16.840.1.101.3.7.2.9999.101", 2, "\x82\x06", "\x82\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8306, "Pub 83 key ", - "2.16.840.1.101.3.7.2.9999.102", 2, "\x83\x06", "\x83\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8406, "Pub 84 key ", - "2.16.840.1.101.3.7.2.9999.103", 2, "\x84\x06", "\x84\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8506, "Pub 85 key ", - "2.16.840.1.101.3.7.2.9999.104", 2, "\x85\x06", "\x85\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8606, "Pub 86 key ", - "2.16.840.1.101.3.7.2.9999.105", 2, "\x86\x06", "\x86\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8706, "Pub 87 key ", - "2.16.840.1.101.3.7.2.9999.106", 2, "\x87\x06", "\x87\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8806, "Pub 88 key ", - "2.16.840.1.101.3.7.2.9999.107", 2, "\x88\x06", "\x88\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8906, "Pub 89 key ", - "2.16.840.1.101.3.7.2.9999.108", 2, "\x89\x06", "\x89\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8A06, "Pub 8A key ", - "2.16.840.1.101.3.7.2.9999.109", 2, "\x8A\x06", "\x8A\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8B06, "Pub 8B key ", - "2.16.840.1.101.3.7.2.9999.110", 2, "\x8B\x06", "\x8B\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8C06, "Pub 8C key ", - "2.16.840.1.101.3.7.2.9999.111", 2, "\x8C\x06", "\x8C\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8D06, "Pub 8D key ", - "2.16.840.1.101.3.7.2.9999.112", 2, "\x8D\x06", "\x8D\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8E06, "Pub 8E key ", - "2.16.840.1.101.3.7.2.9999.113", 2, "\x8E\x06", "\x8E\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_8F06, "Pub 8F key ", - "2.16.840.1.101.3.7.2.9999.114", 2, "\x8F\x06", "\x8F\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9006, "Pub 90 key ", - "2.16.840.1.101.3.7.2.9999.115", 2, "\x90\x06", "\x90\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9106, "Pub 91 key ", - "2.16.840.1.101.3.7.2.9999.116", 2, "\x91\x06", "\x91\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9206, "Pub 92 key ", - "2.16.840.1.101.3.7.2.9999.117", 2, "\x92\x06", "\x92\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9306, "Pub 93 key ", - "2.16.840.1.101.3.7.2.9999.118", 2, "\x93\x06", "\x93\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9406, "Pub 94 key ", - "2.16.840.1.101.3.7.2.9999.119", 2, "\x94\x06", "\x94\x06", PIV_OBJECT_TYPE_PUBKEY}, - {PIV_DATA_OBJ_9506, "Pub 95 key ", - "2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY},*/ {"", 0, "", ""} }; @@ -183,17 +118,31 @@ static piv_cert_obj_t cert_objects[] = { {0} }; +static piv_pvtk_obj_t pvtkey_objects[] = { + {0}, + {0}, + {0}, + {0}, + {0} +}; -//static const CK_ULONG n_objects = sizeof(objects) / sizeof(piv_obj_t); +static piv_pubk_obj_t pubkey_objects[] = { + {0}, + {0}, + {0}, + {0}, + {0} +}; -static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { + +/*static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { if (obj >= 0 && obj < PIV_DATA_OBJ_LAST) *class = CKO_DATA; else if (obj > PIV_DATA_OBJ_LAST && obj < PIV_CERT_OBJ_LAST) *class = CKO_CERTIFICATE; else *class = CKO_VENDOR_DEFINED | CKO_DATA; // Invalid value -} + }*/ /*static void get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { strcpy((char *)label, objects[obj].name); @@ -286,67 +235,79 @@ static void get_object_key_id(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR key_id) { } */ -CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { +/* Get data object attribute */ +CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; CK_BYTE tmp[64]; CK_ULONG len = 0; - fprintf(stderr, "FOR OBJECT %lu, I WANT ", obj); + fprintf(stderr, "FOR DATA OBJECT %lu, I WANT ", obj); switch (template->type) { case CKA_CLASS: fprintf(stderr, "CLASS\n"); len = 1; - get_object_class(obj, (CK_OBJECT_CLASS_PTR)tmp); + tmp[0] = CKO_DATA; + data = tmp; + break; + + case CKA_TOKEN: + // Technically all these objects are token objects + fprintf(stderr, "TOKEN\n"); + len = 1; + tmp[0] = piv_objects[obj].token; data = tmp; break; -// case CKA_TOKEN: case CKA_PRIVATE: - fprintf(stderr, "PRIVATE\n"); // TODO: check more - template->ulValueLen = CK_UNAVAILABLE_INFORMATION; - return CKR_OK; + fprintf(stderr, "PRIVATE\n"); + len = 1; + tmp[0] = piv_objects[obj].private; + data = tmp; + break; case CKA_LABEL: fprintf(stderr, "LABEL\n"); - len = strlen(objects[obj].label) + 1; - data = objects[obj].label; + len = strlen(piv_objects[obj].label) + 1; + data = piv_objects[obj].label; break; case CKA_APPLICATION: fprintf(stderr, "APPLICATION\n"); - len = strlen(objects[obj].label) + 1; - data = objects[obj].label; + len = strlen(piv_objects[obj].label) + 1; + data = piv_objects[obj].label; break; -// case CKA_VALUE: // TODO: this can be done with -r and -d|-a + case CKA_VALUE: // TODO: this can be done with -r and -d|-a + fprintf(stderr, "VALUE TODO!!!\n"); + return CKR_FUNCTION_FAILED; + case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? // This only makes sense for data objects fprintf(stderr, "OID\n"); - strcpy((char *)tmp, data_objects[objects[obj].sub_id].oid); + strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid); asn1_encode_oid(tmp, tmp, &len); data = tmp; break; - case CKA_CERTIFICATE_TYPE: - fprintf(stderr, "CERTIFICATE TYPE\n"); - len = 1; - tmp[0] = CKC_X_509; // Support only X.509 certs - data = tmp; - break; + /* case CKA_CERTIFICATE_TYPE: */ + /* fprintf(stderr, "CERTIFICATE TYPE\n"); */ + /* len = 1; */ + /* tmp[0] = CKC_X_509; // Support only X.509 certs */ + /* data = tmp; */ + /* break; */ // case CKA_ISSUER: // case CKA_SERIAL_NUMBER: - case CKA_KEY_TYPE: - fprintf(stderr, "Return the key type TODO!!!\n"); - return CKR_OK; + /* case CKA_KEY_TYPE: */ + /* fprintf(stderr, "Return the key type TODO!!!\n"); */ + /* return CKR_OK; */ /* case CKA_SUBJECT: */ - case CKA_ID: - // This only makes sense for data objects - fprintf(stderr, "ID\n"); - len = data_objects[objects[obj].sub_id].tag_len; - data = data_objects[objects[obj].sub_id].tag_value; - break; + /* case CKA_ID: */ + /* fprintf(stderr, "ID\n"); */ + /* len = data_objects[objects[obj].sub_id].tag_len; */ + /* data = data_objects[objects[obj].sub_id].tag_value; */ + /* break; */ /* case CKA_SENSITIVE: */ /* case CKA_ENCRYPT: */ @@ -381,28 +342,511 @@ CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); len = 1; - tmp[0] = CK_FALSE; + tmp[0] = piv_objects[obj].modifiable; data = tmp; break; - case CKA_VENDOR_DEFINED: + /* case CKA_VENDOR_DEFINED: */ default: fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } - if (template->pValue == NULL_PTR) { - template->ulValueLen = len; // TODO: define? - return CKR_OK; - } - - if (template->ulValueLen < len) - return CKR_BUFFER_TOO_SMALL; - - template->ulValueLen = len; - memcpy(template->pValue, data, len); - + /* Just get the length */ + if (template->pValue == NULL_PTR) { + template->ulValueLen = len; // TODO: define? return CKR_OK; + } + + /* Actually get the attribute */ + if (template->ulValueLen < len) + return CKR_BUFFER_TOO_SMALL; + + template->ulValueLen = len; + memcpy(template->pValue, data, len); + + return CKR_OK; } + +/* Get certificate object attribute */ +CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { + CK_BYTE_PTR data; + CK_BYTE tmp[64]; + CK_ULONG len = 0; + fprintf(stderr, "FOR CERTIFICATE OBJECT %lu, I WANT ", obj); + + switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above? + case CKA_CLASS: + fprintf(stderr, "CLASS\n"); + len = 1; + tmp[0] = CKO_CERTIFICATE; + data = tmp; + break; + + case CKA_TOKEN: + // Technically all these objects are token objects + fprintf(stderr, "TOKEN\n"); + len = 1; + tmp[0] = piv_objects[obj].token; + data = tmp; + break; + + case CKA_PRIVATE: + fprintf(stderr, "PRIVATE\n"); + len = 1; + tmp[0] = piv_objects[obj].private; + data = tmp; + break; + + case CKA_LABEL: + fprintf(stderr, "LABEL\n"); + len = strlen(piv_objects[obj].label) + 1; + data = piv_objects[obj].label; + break; + + /* case CKA_APPLICATION: */ + /* fprintf(stderr, "APPLICATION\n"); */ + /* len = strlen(objects[obj].label) + 1; */ + /* data = objects[obj].label; */ + /* break; */ + + case CKA_VALUE: + fprintf(stderr, "VALUE TODO\n"); + return CKR_FUNCTION_FAILED; + + /* case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? */ + /* // This only makes sense for data objects */ + /* fprintf(stderr, "OID\n"); */ + /* strcpy((char *)tmp, certificate_objects[objects[obj].sub_id].oid); */ + /* asn1_encode_oid(tmp, tmp, &len); */ + /* data = tmp; */ + /* break; */ + + case CKA_CERTIFICATE_TYPE: + fprintf(stderr, "CERTIFICATE TYPE\n"); + len = 1; + tmp[0] = CKC_X_509; // Support only X.509 certs + data = tmp; + break; + + case CKA_ISSUER: + fprintf(stderr, "ISSUER TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_SERIAL_NUMBER: + fprintf(stderr, "SERIAL NUMBER TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + /* case CKA_KEY_TYPE: */ + /* fprintf(stderr, "Return the key type TODO!!!\n"); */ + /* return CKR_OK; */ + + case CKA_SUBJECT: + fprintf(stderr, "SUBJECT TODO\n"); // Required + return CKR_FUNCTION_FAILED; + + case CKA_ID: + fprintf(stderr, "ID\n"); + len = 1; + tmp[0] = piv_objects[obj].sub_id; + data = tmp; + break; + + /* case CKA_SENSITIVE: */ + /* case CKA_ENCRYPT: */ + /* case CKA_DECRYPT: */ + /* case CKA_WRAP: */ + /* case CKA_UNWRAP: */ + /* case CKA_SIGN: */ + /* case CKA_SIGN_RECOVER: */ + /* case CKA_VERIFY: */ + /* case CKA_VERIFY_RECOVER: */ + /* case CKA_DERIVE: */ + case CKA_START_DATE: + fprintf(stderr, "START DATE TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_END_DATE: + fprintf(stderr, "END DATE TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + /* case CKA_MODULUS: */ + /* case CKA_MODULUS_BITS: */ + /* case CKA_PUBLIC_EXPONENT: */ + /* case CKA_PRIVATE_EXPONENT: */ + /* case CKA_PRIME_1: */ + /* case CKA_PRIME_2: */ + /* case CKA_EXPONENT_1: */ + /* case CKA_EXPONENT_2: */ + /* case CKA_COEFFICIENT: */ + /* case CKA_PRIME: */ + /* case CKA_SUBPRIME: */ + /* case CKA_BASE: */ + /* case CKA_VALUE_BITS: */ + /* case CKA_VALUE_LEN: */ + /* case CKA_EXTRACTABLE: */ + /* case CKA_LOCAL: */ + /* case CKA_NEVER_EXTRACTABLE: */ + /* case CKA_ALWAYS_SENSITIVE: */ + case CKA_MODIFIABLE: + fprintf(stderr, "MODIFIABLE\n"); + len = 1; + tmp[0] = piv_objects[obj].modifiable; + data = tmp; + break; + + /* case CKA_VENDOR_DEFINED: */ + default: // TODO: there are other attributes for a (x509) certificate + fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); + template->ulValueLen = CK_UNAVAILABLE_INFORMATION; + return CKR_ATTRIBUTE_TYPE_INVALID; + } + + /* Just get the length */ + if (template->pValue == NULL_PTR) { + template->ulValueLen = len; // TODO: define? + return CKR_OK; + } + + /* Actually get the attribute */ + if (template->ulValueLen < len) + return CKR_BUFFER_TOO_SMALL; + + template->ulValueLen = len; + memcpy(template->pValue, data, len); + + return CKR_OK; + +} + +/* Get private key object attribute */ +CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { + CK_BYTE_PTR data; + CK_BYTE tmp[64]; + CK_ULONG len = 0; + fprintf(stderr, "FOR PRIVATE KEY OBJECT %lu, I WANT ", obj); + + switch (template->type) { + case CKA_CLASS: + fprintf(stderr, "CLASS\n"); + len = 1; + tmp[0] = CKO_PRIVATE_KEY; + data = tmp; + break; + + case CKA_TOKEN: + // Technically all these objects are token objects + fprintf(stderr, "TOKEN\n"); + len = 1; + tmp[0] = piv_objects[obj].token; + data = tmp; + break; + + case CKA_PRIVATE: + fprintf(stderr, "PRIVATE\n"); + len = 1; + tmp[0] = piv_objects[obj].private; + data = tmp; + break; + + case CKA_LABEL: + fprintf(stderr, "LABEL\n"); + len = strlen(piv_objects[obj].label) + 1; + data = piv_objects[obj].label; + break; + + /* case CKA_APPLICATION: */ + /* fprintf(stderr, "APPLICATION\n"); */ + /* len = strlen(objects[obj].label) + 1; */ + /* data = objects[obj].label; */ + /* break; */ + +// case CKA_VALUE: // TODO: this can be done with -r and -d|-a + /* case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? */ + /* // This only makes sense for data objects */ + /* fprintf(stderr, "OID\n"); */ + /* strcpy((char *)tmp, pvtkey_objects[objects[obj].sub_id].oid); */ + /* asn1_encode_oid(tmp, tmp, &len); */ + /* data = tmp; */ + /* break; */ + + /* case CKA_CERTIFICATE_TYPE: */ + /* fprintf(stderr, "CERTIFICATE TYPE\n"); */ + /* len = 1; */ + /* tmp[0] = CKC_X_509; // Support only X.509 certs */ + /* data = tmp; */ + /* break; */ + +// case CKA_ISSUER: +// case CKA_SERIAL_NUMBER: + case CKA_KEY_TYPE: + fprintf(stderr, "KEY TYPE TODO\n"); + return CKR_FUNCTION_FAILED; + + case CKA_SUBJECT: + fprintf(stderr, "SUBJECT TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_ID: + fprintf(stderr, "ID\n"); + len = 1; + tmp[0] = piv_objects[obj].sub_id; + data = tmp; + break; + + case CKA_SENSITIVE: + fprintf(stderr, "SENSITIVE TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + /* case CKA_ENCRYPT: */ + case CKA_DECRYPT: + fprintf(stderr, "DECRYPT TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + /* case CKA_WRAP: */ + case CKA_UNWRAP: + fprintf(stderr, "UNWRAP TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_SIGN: + fprintf(stderr, "SIGN TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_SIGN_RECOVER: + fprintf(stderr, "SIGN RECOVER TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + /* case CKA_VERIFY: */ + /* case CKA_VERIFY_RECOVER: */ + case CKA_DERIVE: + fprintf(stderr, "DERIVE TODO\n"); // Default false + return CKR_FUNCTION_FAILED; + + case CKA_START_DATE: + fprintf(stderr, "START DATE TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_END_DATE: + fprintf(stderr, "END DATE TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + /* case CKA_MODULUS: */ + /* case CKA_MODULUS_BITS: */ + /* case CKA_PUBLIC_EXPONENT: */ + /* case CKA_PRIVATE_EXPONENT: */ + /* case CKA_PRIME_1: */ + /* case CKA_PRIME_2: */ + /* case CKA_EXPONENT_1: */ + /* case CKA_EXPONENT_2: */ + /* case CKA_COEFFICIENT: */ + /* case CKA_PRIME: */ + /* case CKA_SUBPRIME: */ + /* case CKA_BASE: */ + /* case CKA_VALUE_BITS: */ + /* case CKA_VALUE_LEN: */ + /* case CKA_EXTRACTABLE: */ + case CKA_LOCAL: + fprintf(stderr, "LOCAL TODO\n"); // Required + return CKR_FUNCTION_FAILED; + + /* case CKA_NEVER_EXTRACTABLE: */ + /* case CKA_ALWAYS_SENSITIVE: */ + case CKA_MODIFIABLE: + fprintf(stderr, "MODIFIABLE\n"); + len = 1; + tmp[0] = piv_objects[obj].modifiable; + data = tmp; + break; + + /*case CKA_VENDOR_DEFINED:*/ + default: + fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); // TODO: there are other parameters for public keys, plus there is more if the key is RSA + template->ulValueLen = CK_UNAVAILABLE_INFORMATION; + return CKR_ATTRIBUTE_TYPE_INVALID; + } + + /* Just get the length */ + if (template->pValue == NULL_PTR) { + template->ulValueLen = len; // TODO: define? + return CKR_OK; + } + + /* Actually get the attribute */ + if (template->ulValueLen < len) + return CKR_BUFFER_TOO_SMALL; + + template->ulValueLen = len; + memcpy(template->pValue, data, len); + + return CKR_OK; + +} + +/* Get public key object attribute */ +CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { + CK_BYTE_PTR data; + CK_BYTE tmp[64]; + CK_ULONG len = 0; + fprintf(stderr, "FOR PUBLIC KEY OBJECT %lu, I WANT ", obj); + + switch (template->type) { + case CKA_CLASS: + fprintf(stderr, "CLASS\n"); + len = 1; + tmp[0] = CKO_PUBLIC_KEY; + data = tmp; + break; + + case CKA_TOKEN: + // Technically all these objects are token objects + fprintf(stderr, "TOKEN\n"); + len = 1; + tmp[0] = piv_objects[obj].token; + data = tmp; + break; + + case CKA_PRIVATE: + fprintf(stderr, "PRIVATE\n"); + len = 1; + tmp[0] = piv_objects[obj].private; + data = tmp; + break; + + case CKA_LABEL: + fprintf(stderr, "LABEL\n"); + len = strlen(piv_objects[obj].label) + 1; + data = piv_objects[obj].label; + break; + + /* case CKA_APPLICATION: */ + /* fprintf(stderr, "APPLICATION\n"); */ + /* len = strlen(objects[obj].label) + 1; */ + /* data = objects[obj].label; */ + /* break; */ + +// case CKA_VALUE: // TODO: this can be done with -r and -d|-a + /* case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? */ + /* // This only makes sense for data objects */ + /* fprintf(stderr, "OID\n"); */ + /* strcpy((char *)tmp, pubkey_objects[objects[obj].sub_id].oid); */ + /* asn1_encode_oid(tmp, tmp, &len); */ + /* data = tmp; */ + /* break; */ + + /* case CKA_CERTIFICATE_TYPE: */ + /* fprintf(stderr, "CERTIFICATE TYPE\n"); */ + /* len = 1; */ + /* tmp[0] = CKC_X_509; // Support only X.509 certs */ + /* data = tmp; */ + /* break; */ + +// case CKA_ISSUER: +// case CKA_SERIAL_NUMBER: + case CKA_KEY_TYPE: + fprintf(stderr, "KEY TYPE TODO\n"); + return CKR_FUNCTION_FAILED; + + case CKA_SUBJECT: + fprintf(stderr, "SUBJECT TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_ID: + fprintf(stderr, "ID\n"); + len = 1; + tmp[0] = piv_objects[obj].sub_id; + data = tmp; + break; + + /* case CKA_SENSITIVE: */ + case CKA_ENCRYPT: + fprintf(stderr, "ENCRYPT TODO\n"); // Required + return CKR_FUNCTION_FAILED; + + case CKA_DECRYPT: + fprintf(stderr, "DECRYPT TODO\n"); // Required + return CKR_FUNCTION_FAILED; + + case CKA_WRAP: + fprintf(stderr, "WRAP TODO\n"); // Required + return CKR_FUNCTION_FAILED; + + /* case CKA_UNWRAP: */ + /* case CKA_SIGN: */ + /* case CKA_SIGN_RECOVER: */ + /* case CKA_VERIFY: */ + /* case CKA_VERIFY_RECOVER: */ + case CKA_DERIVE: + fprintf(stderr, "DERIVE TODO\n"); // Defaul false + return CKR_FUNCTION_FAILED; + + case CKA_START_DATE: + fprintf(stderr, "START DATE TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + + case CKA_END_DATE: + fprintf(stderr, "END DATE TODO\n"); // Default empty + return CKR_FUNCTION_FAILED; + /* case CKA_MODULUS: */ + /* case CKA_MODULUS_BITS: */ + /* case CKA_PUBLIC_EXPONENT: */ + /* case CKA_PRIVATE_EXPONENT: */ + /* case CKA_PRIME_1: */ + /* case CKA_PRIME_2: */ + /* case CKA_EXPONENT_1: */ + /* case CKA_EXPONENT_2: */ + /* case CKA_COEFFICIENT: */ + /* case CKA_PRIME: */ + /* case CKA_SUBPRIME: */ + /* case CKA_BASE: */ + /* case CKA_VALUE_BITS: */ + /* case CKA_VALUE_LEN: */ + /* case CKA_EXTRACTABLE: */ + case CKA_LOCAL: + fprintf(stderr, "LOCAL TODO\n"); // Required + return CKR_FUNCTION_FAILED; + + /* case CKA_NEVER_EXTRACTABLE: */ + /* case CKA_ALWAYS_SENSITIVE: */ + case CKA_MODIFIABLE: + fprintf(stderr, "MODIFIABLE\n"); + len = 1; + tmp[0] = piv_objects[obj].modifiable; + data = tmp; + break; + + /* case CKA_VENDOR_DEFINED: */ + default: + fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); // TODO: there are other parameters for public keys + template->ulValueLen = CK_UNAVAILABLE_INFORMATION; + return CKR_ATTRIBUTE_TYPE_INVALID; + } + + /* Just get the length */ + if (template->pValue == NULL_PTR) { + template->ulValueLen = len; // TODO: define? + return CKR_OK; + } + + /* Actually get the attribute */ + if (template->ulValueLen < len) + return CKR_BUFFER_TOO_SMALL; + + template->ulValueLen = len; + memcpy(template->pValue, data, len); + + return CKR_OK; + +} + +CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { + CK_ULONG i; + + for (i = 0; i < s->slot->token->n_objects; i++) + if (s->slot->token->objects[i] == obj) { + return piv_objects[obj].get_attribute(obj, template); + } + + + return CKR_OBJECT_HANDLE_INVALID; +} diff --git a/ykcs11/objects.h b/ykcs11/objects.h index e7539ea..439361e 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -1,12 +1,10 @@ #ifndef OBJECTS_H #define OBJECTS_H -#include "pkcs11t.h" -#include "obj_types.h" +#include "ykcs11.h" #include // TODO: delete -CK_RV get_attribute(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); -//CK_RV get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class); +CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); #endif diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 16b070e..a57a6cd 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -3,7 +3,7 @@ #include "pkcs11.h" #include "vendor_ids.h" -#include "objects.h" +#include "obj_types.h" #include typedef CK_RV (*get_t_label_f)(CK_UTF8CHAR_PTR, CK_ULONG); diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 13ee44e..09fdc55 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -90,7 +90,7 @@ failure: return CKR_FUNCTION_FAILED; } - +#include // TODO: Delete CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { token_vendor_t token; diff --git a/ykcs11/utils.h b/ykcs11/utils.h index 6190913..5bcb8db 100644 --- a/ykcs11/utils.h +++ b/ykcs11/utils.h @@ -8,4 +8,5 @@ CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token); CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot); void destroy_token(ykcs11_slot_t *slot); + #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 40a237d..46faef9 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1,11 +1,12 @@ #include "ykcs11.h" -#include "pkcs11.h" +//#include "pkcs11.h" #include #include #include #include -//#include "vendors.h" +#include "obj_types.h" #include "utils.h" +#include "mechanisms.h" #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ @@ -14,7 +15,7 @@ } while (0) #define YKCS11_DBG 1 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 +#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" @@ -218,8 +219,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( { DIN; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (slotID >= n_slots) return CKR_ARGUMENTS_BAD; @@ -240,8 +243,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( token_vendor_t token; CK_BYTE buf[64]; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (slotID >= n_slots) return CKR_ARGUMENTS_BAD; @@ -429,8 +434,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( token_vendor_t token; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (slotID >= n_slots || phSession == NULL) return CKR_ARGUMENTS_BAD; @@ -514,8 +521,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( { DIN; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (session.handle == CK_INVALID_HANDLE) { DBG(("There is no existing session")); @@ -544,8 +553,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( DIN; CK_RV rv; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (session.slot != slots + slotID) return CKR_SLOT_ID_INVALID; @@ -563,8 +574,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( { DIN; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (pInfo == NULL) return CKR_ARGUMENTS_BAD; @@ -614,8 +627,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( DIN; CK_ULONG tries; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (userType != CKU_USER && userType != CKU_SO && @@ -736,9 +751,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( ) { DIN; + CK_RV rv; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; @@ -754,14 +772,19 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( if (pTemplate[0].pValue == NULL_PTR) { DBG(("Just get size")); - get_attribute(hObject, pTemplate); // TODO: get attribute size + rv = get_attribute(&session, hObject, pTemplate); + + if (rv != CKR_OK) { + DBG(("Unable to get size for attribute %lu of object %lu", pTemplate->type, hObject)); + } DOUT; return CKR_OK; } - DBG(("Trying to get %lu attributes for object %lx", ulCount, hObject)); + DBG(("Trying to get %lu attribute(s) for object %lu", ulCount, hObject)); DBG(("Type: 0x%lx Value: %lu Len: %lu", pTemplate[0].type, *((CK_ULONG_PTR)pTemplate[0].pValue), pTemplate[0].ulValueLen)); - // TODO: here for i in ulCount - return get_attribute(hObject, pTemplate); + // TODO: here for i in ulCount (get all the attributes) + + return get_attribute(&session, hObject, pTemplate); DOUT; return CKR_OK; @@ -788,10 +811,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( { DIN; CK_ULONG i; - //token_vendor_t token; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; @@ -833,8 +857,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( } // TODO: do it properly here, jsut a test now + //find_obj.objects = session.slot->token->objects + 3; + memmove(find_obj.objects, find_obj.objects + 3, sizeof(piv_obj_id_t) * (find_obj.num - 3)); find_obj.num = 1; - find_obj.objects = session.slot->token->objects + 3; DOUT; return CKR_OK; @@ -849,8 +874,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( { DIN; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; @@ -889,8 +916,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( { DIN; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; @@ -1082,8 +1111,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( { DIN; - if (piv_state == NULL) + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; + } if (session.handle != YKCS11_SESSION_ID) return CKR_SESSION_CLOSED; @@ -1095,11 +1126,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( hKey == NULL_PTR) return CKR_ARGUMENTS_BAD; - DBG(("Trying to sign some data with mechanism %lu and key %lu more", pMechanism->mechanism, hKey)); + DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey)); - if (check_sign_mechanism(pMechanism, hKey) == CK_FALSE) // TODO: do we need session here? + if (check_sign_mechanism(&session, pMechanism) != CKR_OK) { + DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); return CKR_MECHANISM_INVALID; + } + + sign_info.active = CK_TRUE; memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); sign_info.key = hKey; diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 0814875..2c9f644 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -2,6 +2,7 @@ #define YKCS11_H #include "pkcs11t.h" +#include "obj_types.h" #include "vendors.h" typedef struct { diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index d86dc17..3f0be65 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -63,15 +63,15 @@ static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH }; static const piv_obj_id_t token_objects[] = { // TODO: is there a way to get this from the token? - PIV_DATA_OBJ_CCC, // Card capability container - PIV_DATA_OBJ_CHUI, // Cardholder unique id PIV_DATA_OBJ_X509_PIV_AUTH, // PIV authentication - PIV_DATA_OBJ_CHF, // Cardholder fingerprints - PIV_DATA_OBJ_SEC_OBJ, // Security object - PIV_DATA_OBJ_CHFI, // Cardholder facial images PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication PIV_DATA_OBJ_X509_DS, // Certificate for digital signature PIV_DATA_OBJ_X509_KM, // Certificate for key management + PIV_DATA_OBJ_CCC, // Card capability container + PIV_DATA_OBJ_CHUI, // Cardholder unique id + PIV_DATA_OBJ_CHF, // Cardholder fingerprints + PIV_DATA_OBJ_SEC_OBJ, // Security object + PIV_DATA_OBJ_CHFI, // Cardholder facial images //PIV_DATA_OBJ_PI, // Cardholder printed information //PIV_DATA_OBJ_DISCOVERY, // Discovery object //PIV_DATA_OBJ_HISTORY, // History object @@ -193,7 +193,7 @@ CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num) { memcpy(mec, token_mechanisms, token_mechanisms_num * sizeof(CK_MECHANISM_TYPE)); return CKR_OK; - + } CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info) { @@ -205,9 +205,9 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P memcpy((CK_BYTE_PTR) info, (CK_BYTE_PTR) (token_mechanism_infos + i), sizeof(CK_MECHANISM_INFO)); return CKR_OK; } - + return CKR_MECHANISM_INVALID; - + } #include // TODO: delete static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *obj, CK_ULONG_PTR len) { @@ -215,6 +215,8 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *ob CK_ULONG buf_len; piv_obj_id_t certs[4]; + piv_obj_id_t pvtkeys[4]; + piv_obj_id_t pubkeys[4]; CK_ULONG n_cert = 0; if (state == NULL || len == NULL_PTR) @@ -222,51 +224,64 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *ob if (num_only == CK_FALSE && obj == NULL) return CKR_ARGUMENTS_BAD; - + buf_len = sizeof(buf); if (ykpiv_fetch_object(state, YKPIV_OBJ_AUTHENTICATION, buf, &buf_len) == YKPIV_OK) { + certs[n_cert] = PIV_CERT_OBJ_X509_PIV_AUTH; + pvtkeys[n_cert] = PIV_PVTK_OBJ_PIV_AUTH; + pubkeys[n_cert] = PIV_PUBK_OBJ_PIV_AUTH; n_cert++; - certs[0] = PIV_CERT_OBJ_X509_PIV_AUTH; fprintf(stderr, "Found AUTH cert (9a)\n"); } buf_len = sizeof(buf); - if (ykpiv_fetch_object(state, YKPIV_OBJ_SIGNATURE, buf, &buf_len) == YKPIV_OK) { + if (ykpiv_fetch_object(state, YKPIV_OBJ_CARD_AUTH, buf, &buf_len) == YKPIV_OK) { + certs[n_cert] = PIV_CERT_OBJ_X509_CARD_AUTH; + pvtkeys[n_cert] = PIV_PVTK_OBJ_CARD_AUTH; + pubkeys[n_cert] = PIV_PUBK_OBJ_CARD_AUTH; + n_cert++; + fprintf(stderr, "Found CARD AUTH cert (9e)\n"); + } + + buf_len = sizeof(buf); + if (ykpiv_fetch_object(state, YKPIV_OBJ_SIGNATURE, buf, &buf_len) == YKPIV_OK) { + certs[n_cert] = PIV_CERT_OBJ_X509_DS; + pvtkeys[n_cert] = PIV_PVTK_OBJ_DS; + pubkeys[n_cert] = PIV_PUBK_OBJ_DS; n_cert++; - certs[1] = PIV_CERT_OBJ_X509_DS; fprintf(stderr, "Found SIGNATURE cert (9c)\n"); } buf_len = sizeof(buf); if (ykpiv_fetch_object(state, YKPIV_OBJ_KEY_MANAGEMENT, buf, &buf_len) == YKPIV_OK) { + certs[n_cert] = PIV_CERT_OBJ_X509_KM; + pvtkeys[n_cert] = PIV_PVTK_OBJ_KM; + pubkeys[n_cert] = PIV_PUBK_OBJ_KM; n_cert++; - certs[2] = PIV_CERT_OBJ_X509_KM; fprintf(stderr, "Found KMK cert (9d)\n"); } - buf_len = sizeof(buf); - if (ykpiv_fetch_object(state, YKPIV_OBJ_CARD_AUTH, buf, &buf_len) == YKPIV_OK) { - n_cert++; - certs[3] = PIV_CERT_OBJ_X509_CARD_AUTH; - fprintf(stderr, "Found CARD AUTH cert (9e)\n"); - } + fprintf(stderr, "The total number of objects for this token is %lu\n", (n_cert * 3) + token_objects_num); - fprintf(stderr, "The total number of objects for this token is %lu\n", n_cert + token_objects_num); - if (num_only == CK_TRUE) { // We just want the number of objects - *len = n_cert + token_objects_num; + // Each cert object counts for 3: cert, pub key, pvt key + *len = (n_cert * 3) + token_objects_num; return CKR_OK; } - if (*len < n_cert + token_objects_num) + if (*len < (n_cert * 3) + token_objects_num) return CKR_BUFFER_TOO_SMALL; // Copy mandatory data objects memcpy(obj, token_objects, token_objects_num * sizeof(piv_obj_id_t)); // Copy certificates - memcpy(obj + token_objects_num, certs, n_cert * sizeof(piv_obj_id_t)); + if (n_cert > 0) { + memcpy(obj + token_objects_num, certs, n_cert * sizeof(piv_obj_id_t)); + memcpy(obj + token_objects_num + n_cert, pvtkeys, n_cert * sizeof(piv_obj_id_t)); + memcpy(obj + token_objects_num + (2 * n_cert), pubkeys, n_cert * sizeof(piv_obj_id_t)); + } return CKR_OK; } From 246cf626b29bb591f87703c705d1ba23c94c3f16 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 28 Jul 2015 18:56:47 +0200 Subject: [PATCH 040/134] Start to do some crypto. --- ykcs11/obj_types.h | 4 +++- ykcs11/objects.c | 22 +++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 5d02a62..a0f3c3c 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -3,6 +3,8 @@ #include "pkcs11t.h" +#include + // TODO: this is mostly from OpenSC, how to give credit? typedef enum { PIV_DATA_OBJ_X509_PIV_AUTH = 0, // PIV authentication @@ -98,7 +100,7 @@ typedef struct { } piv_data_obj_t; typedef struct { - CK_BBOOL todo; + X509 *data; } piv_cert_obj_t; typedef struct { diff --git a/ykcs11/objects.c b/ykcs11/objects.c index cbc008e..19a749e 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -56,10 +56,10 @@ static piv_obj_t piv_objects[] = { {PIV_CERT_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_coa, 3}, {PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, get_coa, 4}, - {PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 0, "Pivate key for PIV Authentication", 0, 0, get_proa, 0}, - {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Pivate key for Card Authentication", 0, 0, get_proa, 1}, - {PIV_PVTK_OBJ_DS, 1, 0, 0, "Pivate key for Digital Signature", 0, 0, get_proa, 2}, - {PIV_PVTK_OBJ_KM, 1, 0, 0, "Private key for Key Management", 0, 0, get_proa, 3}, + {PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, + {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Private key for Card Authentication", 0, 0, get_proa, 1}, + {PIV_PVTK_OBJ_DS, 1, 0, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, + {PIV_PVTK_OBJ_KM, 1, 0, 0, "Prrivate key for Key Management", 0, 0, get_proa, 3}, {PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4}, {PIV_PUBK_OBJ_PIV_AUTH, 1, 0, 0, "Public key for PIV Authentication", 0, 0, get_proa, 0}, @@ -111,11 +111,11 @@ static piv_data_obj_t data_objects[] = { }; static piv_cert_obj_t cert_objects[] = { - {0}, - {0}, - {0}, - {0}, - {0} + {NULL}, + {NULL}, + {NULL}, + {NULL}, + {NULL} }; static piv_pvtk_obj_t pvtkey_objects[] = { @@ -583,6 +583,10 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { // case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: fprintf(stderr, "KEY TYPE TODO\n"); + len = 1; + tmp[0] = CKK_RSA; // TODO: just an example + data = tmp; + break; return CKR_FUNCTION_FAILED; case CKA_SUBJECT: From 175f0ff42b851b113eac4f603e722b2d658addd5 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 30 Jul 2015 17:04:24 +0200 Subject: [PATCH 041/134] First crude signature implementation plus additional refactor. --- ykcs11/Makefile.am | 6 +- ykcs11/mechanisms.c | 19 +++- ykcs11/mechanisms.h | 3 + ykcs11/obj_types.h | 4 +- ykcs11/objects.c | 65 ++++++++++++- ykcs11/objects.h | 4 + ykcs11/openssl_utils.c | 78 ++++++++++++++++ ykcs11/openssl_utils.h | 17 ++++ ykcs11/token_vendors.c | 46 +++++----- ykcs11/token_vendors.h | 28 +++--- ykcs11/utils.c | 2 + ykcs11/ykcs11.c | 201 ++++++++++++++++++++++++++--------------- ykcs11/ykcs11.h | 5 +- ykcs11/yubico_token.c | 21 ++++- ykcs11/yubico_token.h | 5 +- 15 files changed, 383 insertions(+), 121 deletions(-) create mode 100644 ykcs11/openssl_utils.c create mode 100644 ykcs11/openssl_utils.h diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index d93c75c..f94ef82 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -39,8 +39,9 @@ libykcs11_la_SOURCES += slot_vendors.c slot_vendor.h libykcs11_la_SOURCES += token_vendors.c token_vendor.h libykcs11_la_SOURCES += mechanisms.c mechanisms.h libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h -libykcs11_la_SOURCES += utils.h utils.c -libykcs11_la_SOURCES += obj_types.h objects.h objects.c +libykcs11_la_SOURCES += utils.c utils.h +libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h +libykcs11_la_SOURCES += objects.c objects.h obj_types.h #internal.h #libykcs11_la_SOURCES += error.c @@ -54,6 +55,7 @@ EXTRA_libykcs11_la_DEPENDENCIES = ykcs11.map #libykcs11_la_LIBADD = $(OPENSSL_LIBS) $(PCSC_LIBS) #libykcs11_la_LIBADD += $(PCSC_WIN_LIBS) $(PCSC_MACOSX_LIBS) libykcs11_la_LIBADD = $(LIBNSPR) ../lib/libykpiv.la +libykcs11_la_LIBADD += ../tool/libpiv_util.la libykcs11_la_LDFLAGS = -no-undefined libykcs11_la_LDFLAGS += -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index b63ea59..7eb0c69 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -40,7 +40,7 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK) return CKR_MECHANISM_INVALID; - // TODO: also check that parametes make sens if any? + // TODO: also check that parametes make sense if any? CKR_OK; @@ -84,3 +84,20 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) { // Not reached return CK_FALSE; } + +CK_RV do_sign_padding(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, + CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { + switch (m->mechanism) { + case CKM_RSA_PKCS: + return do_pkcs_t1(in, in_len, out, out_len, key_len); + + case CKM_RSA_PKCS_PSS: + case CKM_RSA_X_509: + case CKM_SHA1_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: + return CKR_FUNCTION_FAILED; + } + +} diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index f95565e..8a38121 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -7,4 +7,7 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); +CK_RV do_sign_padding(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, + CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); + #endif diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index a0f3c3c..1f0913f 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -103,12 +103,12 @@ typedef struct { X509 *data; } piv_cert_obj_t; -typedef struct { +typedef struct { // TODO: enough to use the public key for the parameters? CK_BBOOL todo; } piv_pvtk_obj_t; typedef struct { - CK_BBOOL todo; + EVP_PKEY *data; } piv_pubk_obj_t; typedef struct { diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 19a749e..270e94d 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -3,6 +3,9 @@ #include #include #include +#include "openssl_utils.h" + +#define IS_CERT(x) (((x) >= PIV_CERT_OBJ_X509_PIV_AUTH && (x) < PIV_CERT_OBJ_LAST) ? CK_TRUE : CK_FALSE) CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); // TODO: static? CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); @@ -843,6 +846,38 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { } +CK_ULONG piv_2_ykpiv(piv_obj_id_t id) { + // TODO: add retired keys + switch(id) { + case PIV_CERT_OBJ_X509_PIV_AUTH: + return YKPIV_OBJ_AUTHENTICATION; + + case PIV_CERT_OBJ_X509_CARD_AUTH: + return YKPIV_OBJ_CARD_AUTH; + + case PIV_CERT_OBJ_X509_DS: + return YKPIV_OBJ_SIGNATURE; + + case PIV_CERT_OBJ_X509_KM: + return YKPIV_OBJ_KEY_MANAGEMENT; + + case PIV_PVTK_OBJ_PIV_AUTH: + return YKPIV_KEY_AUTHENTICATION; + + case PIV_PVTK_OBJ_CARD_AUTH: + return YKPIV_KEY_CARDAUTH; + + case PIV_PVTK_OBJ_DS: + return YKPIV_KEY_SIGNATURE; + + case PIV_PVTK_OBJ_KM: + return YKPIV_KEY_KEYMGM; + + default: + return 0ul; + } +} + CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_ULONG i; @@ -851,6 +886,34 @@ CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR return piv_objects[obj].get_attribute(obj, template); } - return CKR_OBJECT_HANDLE_INVALID; } + +CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs) { + CK_ULONG i, j; + + j = 0; + for (i = 0; i < s->slot->token->n_objects; i++) + if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE) + cert_ids[j++] = s->slot->token->objects[i]; + + fprintf(stderr, "Just to check: %lu %lu\n", j, n_certs); + + return CKR_OK; +} + +CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) { + + CK_RV rv; + + // Store the certificate as an object + rv = do_store_cert(data, len, &cert_objects[piv_objects[cert_id].sub_id].data); + if (rv != CKR_OK) + return rv; + + // Extract and store the public key as an object + rv = do_store_pubk(cert_objects[piv_objects[cert_id].sub_id].data, &pubkey_objects[piv_objects[cert_id].sub_id].data); + + return CKR_OK; +} + diff --git a/ykcs11/objects.h b/ykcs11/objects.h index 439361e..df0a60f 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -5,6 +5,10 @@ #include // TODO: delete +CK_ULONG piv_2_ykpiv(piv_obj_id_t id); + CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); +CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); +CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); #endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c new file mode 100644 index 0000000..d139a99 --- /dev/null +++ b/ykcs11/openssl_utils.c @@ -0,0 +1,78 @@ +#include "openssl_utils.h" +#include +#include "../tool/util.h" // TODO: share this better? + + +CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { + + const unsigned char *p = data; // Mandatory temp variable required by OpenSSL + int cert_len; + + /**cert = X509_new(); + if (*cert == NULL) + return CKR_HOST_MEMORY;*/ + //dump_hex(data, len, stderr, CK_TRUE); + + if (*p++ != 0x70) + return CKR_FUNCTION_FAILED; + + p += get_length(p, &cert_len); + + *cert = d2i_X509(NULL, &p, cert_len); + if (*cert == NULL) + return CKR_FUNCTION_FAILED; + + /* + BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE); + + X509_print_ex(STDout, *cert, 0, 0); + + BIO_free(STDout); + */ + + return CKR_OK; + +} + +CK_RV free_cert(X509 *cert) { + + X509_free((X509 *) cert); + + return CKR_OK; +} + + +CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key) { + + *key = X509_get_pubkey(cert); + + if (*key == NULL) + return CKR_FUNCTION_FAILED; + + return CKR_OK; + +} + +CK_RV free_key(EVP_PKEY *key) { + + EVP_PKEY_free(key); + + return CKR_OK; + +} +/* #include */ +/* #include */ +/* ERR_load_crypto_strings(); */ +/* //SSL_load_error_strings(); */ +CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { + fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len); + + + if (out_len < key_len) + CKR_BUFFER_TOO_SMALL; + + if (RSA_padding_add_PKCS1_type_1(out, key_len, in, in_len) == 0) + return CKR_FUNCTION_FAILED; + + return CKR_OK; +} diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h new file mode 100644 index 0000000..f9382d5 --- /dev/null +++ b/ykcs11/openssl_utils.h @@ -0,0 +1,17 @@ +#ifndef OPENSSL_UTIL_H +#define OPENSSL_UTIL_H + +#include +#include +#include +#include "pkcs11t.h" + +CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); +CK_RV free_cert(X509 *cert); + +CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); +CK_RV free_key(EVP_PKEY *key); + +CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); + +#endif diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index a19c18e..7fd1bfc 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -6,32 +6,34 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { switch (vid) { case YUBICO: - v.get_token_label = YUBICO_get_token_label; - v.get_token_manufacturer = YUBICO_get_token_manufacturer; - v.get_token_model = YUBICO_get_token_model; - v.get_token_flags = YUBICO_get_token_flags; - v.get_token_version = YUBICO_get_token_version; - v.get_token_serial = YUBICO_get_token_serial; - v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; - v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; - v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; - v.get_token_objects_num = YUBICO_get_token_objects_num; - v.get_token_object_list = YUBICO_get_token_object_list; + v.get_token_label = YUBICO_get_token_label; + v.get_token_manufacturer = YUBICO_get_token_manufacturer; + v.get_token_model = YUBICO_get_token_model; + v.get_token_flags = YUBICO_get_token_flags; + v.get_token_version = YUBICO_get_token_version; + v.get_token_serial = YUBICO_get_token_serial; + v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; + v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; + v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; + v.get_token_objects_num = YUBICO_get_token_objects_num; + v.get_token_object_list = YUBICO_get_token_object_list; + v.get_token_raw_certificate = YUBICO_get_token_raw_certificate; break; case UNKNOWN: default: - v.get_token_label = NULL; - v.get_token_manufacturer = NULL; - v.get_token_model = NULL; - v.get_token_flags = NULL; - v.get_token_version = NULL; - v.get_token_serial = NULL; - v.get_token_mechanisms_num = NULL; - v.get_token_mechanism_list = NULL; - v.get_token_mechanism_info = NULL; - v.get_token_objects_num = NULL; - v.get_token_object_list = NULL; + v.get_token_label = NULL; + v.get_token_manufacturer = NULL; + v.get_token_model = NULL; + v.get_token_flags = NULL; + v.get_token_version = NULL; + v.get_token_serial = NULL; + v.get_token_mechanisms_num = NULL; + v.get_token_mechanism_list = NULL; + v.get_token_mechanism_info = NULL; + v.get_token_objects_num = NULL; + v.get_token_object_list = NULL; + v.get_token_raw_certificate = NULL; } return v; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index a57a6cd..4df53e0 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -15,21 +15,23 @@ typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); -typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR); +typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR, CK_ULONG_PTR); typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); - +typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG); +// TODO: replace all the common call with functions defined in .c that use libykpiv typedef struct { - get_t_label_f get_token_label; - get_t_manufacturer_f get_token_manufacturer; - get_t_model_f get_token_model; - get_t_flags_f get_token_flags; - get_t_version_f get_token_version; - get_t_serial_f get_token_serial; - get_t_mechanisms_num_f get_token_mechanisms_num; - get_t_mechanism_list_f get_token_mechanism_list; - get_t_mechanism_info_f get_token_mechanism_info; - get_t_objects_num_f get_token_objects_num; - get_t_object_list_f get_token_object_list; + get_t_label_f get_token_label; + get_t_manufacturer_f get_token_manufacturer; + get_t_model_f get_token_model; + get_t_flags_f get_token_flags; + get_t_version_f get_token_version; + get_t_serial_f get_token_serial; + get_t_mechanisms_num_f get_token_mechanisms_num; + get_t_mechanism_list_f get_token_mechanism_list; + get_t_mechanism_info_f get_token_mechanism_info; + get_t_objects_num_f get_token_objects_num; + get_t_object_list_f get_token_object_list; + get_t_raw_certificate_f get_token_raw_certificate; } token_vendor_t; token_vendor_t get_token_vendor(vendor_id_t vid); diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 09fdc55..add1aef 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -156,6 +156,8 @@ CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { memset(t_info->utcTime, ' ', sizeof(t_info->utcTime)); // No clock present, clear // TODO: also get token objects here? (and destroy on failure) + slot->token->objects = NULL; + slot->token->n_objects = 0; return CKR_OK; } diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 46faef9..2ad268c 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -23,10 +23,12 @@ #define PIV_MIN_PIN_LEN 6 #define PIV_MAX_PIN_LEN 8 -#define YKCS11_MAX_SLOTS 16 +#define YKCS11_MAX_SLOTS 16 +#define YKCS11_MAX_SIG_BUF_LEN 1024 #define YKCS11_SESSION_ID 5355104 + #if YKCS11_DBG #define DBG(x) D(x); #else @@ -60,9 +62,10 @@ static struct { static CK_ULONG n_token_objects = 0;*/ static struct { - CK_BBOOL active; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE key; + CK_BBOOL active; + CK_MECHANISM mechanism; + CK_ULONG key; + CK_BYTE algo; } sign_info; extern CK_FUNCTION_LIST function_list; // TODO: check all return values @@ -269,7 +272,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( token = get_token_vendor(slots[slotID].token->vid); memcpy(pInfo, &slots[slotID].token->info, sizeof(CK_TOKEN_INFO)); - + // Overwrite value that are application specific pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token @@ -283,7 +286,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; - + DOUT; return CKR_OK; } @@ -430,9 +433,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( CK_SESSION_HANDLE_PTR phSession ) { - DIN; + DIN; // TODO: pApplication and Notify token_vendor_t token; + CK_RV rv; + piv_obj_id_t *cert_ids; + CK_ULONG i; + CK_BYTE cert_data[2100]; // Max cert value for ykpiv + CK_ULONG cert_len = sizeof(cert_data); if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -473,27 +481,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( session.slot = slots + slotID; //session.slot->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO - // Get the number of token objects - if (token.get_token_objects_num(piv_state, &session.slot->token->n_objects) != CKR_OK) { - DBG(("Unable to retrieve number of token objects")); - return CKR_FUNCTION_FAILED; - } - - // Get memory for the objects - session.slot->token->objects = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_objects); - if (session.slot->token->objects == NULL) { - DBG(("Unable to allocate memory for token objects")); - return CKR_HOST_MEMORY; - } - - // Store all the objects available in the token - if (token.get_token_object_list(piv_state, - session.slot->token->objects, - session.slot->token->n_objects) != CKR_OK) { - DBG(("Unable to retrieve token objects")); - return CKR_FUNCTION_FAILED; - } - + // Store session flags if ((flags & CKF_RW_SESSION)) { // R/W Session session.info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session @@ -506,13 +494,78 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( session.info.flags = flags; session.info.ulDeviceError = 0; + // Get the number of token objects + rv = token.get_token_objects_num(piv_state, &session.slot->token->n_objects, &session.slot->token->n_certs); + if (rv != CKR_OK) { + DBG(("Unable to retrieve number of token objects")); + return rv; + } + + // Get memory for the objects + session.slot->token->objects = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_objects); + if (session.slot->token->objects == NULL) { + DBG(("Unable to allocate memory for token object ids")); + return CKR_HOST_MEMORY; + } + + // Get memory for the certificates + cert_ids = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_certs); + if (cert_ids == NULL) { + DBG(("Unable to allocate memory for token certificate ids")); + return CKR_HOST_MEMORY; + } + + // Save a list of all the available objects in the token // TODO: change behavior based on login status + rv = token.get_token_object_list(piv_state, session.slot->token->objects, session.slot->token->n_objects); + if (rv != CKR_OK) { + DBG(("Unable to retrieve token objects")); + goto failure; + } + + // Get a list object ids for available certificates object from the session + rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); // TODO: better to get this from token? how? + if (rv != CKR_OK) { + DBG(("Unable to retrieve certificate ids from the session")); + goto failure; + } + + // Get the actual certificate data from the token and store it as an X509 object + for (i = 0; i < session.slot->token->n_certs; i++) { + rv = token.get_token_raw_certificate(piv_state, cert_ids[i], cert_data, cert_len); + if (rv != CKR_OK) { + DBG(("Unable to get certificate data from token")); + goto failure; + } + + rv = store_cert(cert_ids[i], cert_data, cert_len); + if (rv != CKR_OK) { + DBG(("Unable to store certificate data")); + goto failure; + } + } + session.handle = YKCS11_SESSION_ID; - // TODO: KEEP TRACK OF THE APPLICATION + // TODO: KEEP TRACK OF THE APPLICATION (possble to steal a session?) *phSession = session.handle; DOUT; return CKR_OK; + +failure: + if (session.slot->token->objects != NULL) { + free(session.slot->token->objects); + session.slot->token->objects = NULL; + } + + if (cert_ids != NULL) { + free(cert_ids); + cert_ids = NULL; + } + + free_certs(); // TODO + + return rv; } CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( @@ -677,7 +730,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now } - DBG(("You win! %lu", tries)) + DBG(("You win! %lu", tries)); + + // TODO: update session objects now that we're logged in ? DOUT; return CKR_OK; @@ -856,9 +911,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( // TODO: remove objects that don't match } - // TODO: do it properly here, jsut a test now + // TODO: do it properly here, just a test now //find_obj.objects = session.slot->token->objects + 3; - memmove(find_obj.objects, find_obj.objects + 3, sizeof(piv_obj_id_t) * (find_obj.num - 3)); + memmove(find_obj.objects, find_obj.objects + 14, sizeof(piv_obj_id_t) * (find_obj.num - 14)); find_obj.num = 1; DOUT; @@ -1128,33 +1183,41 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey)); + // Check if mechanism is supported if (check_sign_mechanism(&session, pMechanism) != CKR_OK) { DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); return CKR_MECHANISM_INVALID; } - - - - sign_info.active = CK_TRUE; memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); - sign_info.key = hKey; - // TODO: also allocate some space for the signature + // Get key algorithm + /*if (get_key_algo(hKey, &sign_info.algo) != CKR_OK) { + DBG(("Unable to retrieve type for key %lu", hKey)); + return CKR_FUNCTION_FAILED; + }*/ // TODO: use get attribute instead? + sign_info.algo = YKPIV_ALGO_RSA2048; // TODO: fix + + sign_info.key = piv_2_ykpiv(hKey); + if (sign_info.key == 0) { + DBG(("Incorrect key %lu", hKey)); + return CKR_KEY_HANDLE_INVALID; + } + + // Make sure that both mechanism and key have the same algorithm + if ((is_RSA_mechanism(pMechanism->mechanism) && sign_info.algo == YKPIV_ALGO_ECCP256) || + (!is_RSA_mechanism(pMechanism->mechanism) && (sign_info.algo != YKPIV_ALGO_ECCP256))) { + DBG(("Key and mechanism algorithm do not match")); + return CKR_ARGUMENTS_BAD; + } + + // TODO: also allocate some space for the signature in case of multipart + + sign_info.active = CK_TRUE; DOUT; return CKR_OK; } -/* TOTOD: DELETE */ -CK_BYTE sig_buf[1024]; -CK_ULONG sig_len = 1024; -void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, CK_BBOOL space) { - unsigned int i; - for (i = 0; i < len; i++) { - fprintf(output, "%02x%s", buf[i], space == CK_TRUE ? " " : ""); - } - fprintf(output, "\n"); -} -/* TODO: DELETE END*/ + CK_DEFINE_FUNCTION(CK_RV, C_Sign)( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, @@ -1164,39 +1227,35 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( ) { DIN; + CK_BYTE buf[YKCS11_MAX_SIG_BUF_LEN]; + CK_ULONG buf_len = sizeof(buf); if (sign_info.active == CK_FALSE) return CKR_OPERATION_NOT_INITIALIZED; // TODO: check conditions - char test_buf[] = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20\xa7\x47\x16\x1b\x15\x5f\xd0\x05\xbc\xbe\x84\x4a\x28\xa9\x6c\x74\xfe\xf6\x6a\x42\x84\xa0\x4e\x05\x7a\x0c\x88\xe2\xc8\x83\xc0\x00"; - CK_ULONG sig_len_in = sizeof(test_buf) - 1; - CK_ULONG sig_len_out = 1024; ykpiv_rc r; - CK_CHAR key; + CK_CHAR algo; - DBG(("Sending %lu bytes to sign", ulDataLen/*sig_len_in*/)); + DBG(("Sending %lu bytes to sign", ulDataLen)); dump_hex(pData, ulDataLen, stderr, CK_TRUE); - if (sign_info.key == PIV_DATA_OBJ_X509_PIV_AUTH) { - key = YKPIV_KEY_AUTHENTICATION; - DBG(("Using key 9a")); - } - else { // TODO: test what happens if there is no key on the card - key = YKPIV_KEY_SIGNATURE; - DBG(("Using key 9c")); - } - - // TODO: check that mechanism makes sense for the key that we have (check in signinit). - - if ((r = ykpiv_sign_data(piv_state, /*pData*/test_buf, /*ulDataLen*/sig_len_in, sig_buf, &sig_len_out, YKPIV_ALGO_RSA2048, key)) != YKPIV_OK) { - DBG(("Sign error %s", ykpiv_strerror(r))); +/* if (do_sign_padding(&sign_info.mechanism, pData, ulDataLen, buf, buf_len, 2048 / 8) != CKR_OK) { + DBG(("Unable to apply padding scheme")); + return CKR_FUNCTION_FAILED; + }*/ + memcpy(buf, pData, ulDataLen); // ykpiv does padding already + //dump_hex(buf, 256, stderr, CK_TRUE); + //*pulSignatureLen = 256; + DBG(("Using key %lx", sign_info.key)); // TODO: test what happens if there is no key on the card + if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, YKPIV_ALGO_RSA2048, sign_info.key)) != YKPIV_OK) { + DBG(("Sign error, %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } - DBG(("Got %lu bytes back", sig_len_out)); - dump_hex(sig_buf, sig_len_out, stderr, CK_TRUE); - memcpy(pSignature, sig_buf, sig_len_out); - *pulSignatureLen = sig_len_out; + DBG(("Got %lu bytes back", *pulSignatureLen)); + dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); +/* memcpy(pSignature, sig_buf, sig_len_out); + *pulSignatureLen = sig_len_out;*/ DOUT; return CKR_OK; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 2c9f644..cfa22da 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -8,8 +8,9 @@ typedef struct { vendor_id_t vid; CK_TOKEN_INFO info; - piv_obj_id_t *objects; - CK_ULONG n_objects; + piv_obj_id_t *objects; // List of objects in the token + CK_ULONG n_objects; // TOTAL number of objects in the token + CK_ULONG n_certs; // Number of certificate objects in the token (portion of n_objects) } ykcs11_token_t; typedef struct { diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index 3f0be65..a70dab8 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -210,11 +210,12 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P } #include // TODO: delete -static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *obj, CK_ULONG_PTR len) { +static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, + piv_obj_id_t *obj, CK_ULONG_PTR len, CK_ULONG_PTR num_certs) { CK_BYTE buf[2048]; CK_ULONG buf_len; - piv_obj_id_t certs[4]; + piv_obj_id_t certs[4]; // TODO: this can be > 4 if there are retired keys piv_obj_id_t pvtkeys[4]; piv_obj_id_t pubkeys[4]; CK_ULONG n_cert = 0; @@ -267,6 +268,8 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *ob // We just want the number of objects // Each cert object counts for 3: cert, pub key, pvt key *len = (n_cert * 3) + token_objects_num; + if (num_certs != NULL) + *num_certs = n_cert; return CKR_OK; } @@ -286,10 +289,18 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *ob return CKR_OK; } -CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num) { - return get_objects(state, CK_TRUE, NULL, num); +CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs) { + return get_objects(state, CK_TRUE, NULL, num, num_certs); } CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num) { - return get_objects(state, CK_FALSE, obj, &num); + return get_objects(state, CK_FALSE, obj, &num, NULL); +} + +CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG len) { + + if (ykpiv_fetch_object(state, piv_2_ykpiv(obj), data, &len) != YKPIV_OK) + return CKR_FUNCTION_FAILED; + + return CKR_OK; } diff --git a/ykcs11/yubico_token.h b/ykcs11/yubico_token.h index d0c9f7a..c39a7d3 100644 --- a/ykcs11/yubico_token.h +++ b/ykcs11/yubico_token.h @@ -14,7 +14,8 @@ CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VER CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num); CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num); CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info); -CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num); -CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t * obj, CK_ULONG num); +CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs); +CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num); +CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG len); #endif From b4152b8f037ba97f4c01562fe12dd794930ffb98 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 31 Jul 2015 17:14:16 +0200 Subject: [PATCH 042/134] Improvement on sign and object handling. --- ykcs11/objects.c | 95 +++-- ykcs11/openssl_utils.c | 81 ++++- ykcs11/openssl_utils.h | 8 +- ykcs11/pkcs11t.h | 779 +++++++++++++++++++++-------------------- ykcs11/ykcs11.c | 63 +++- 5 files changed, 590 insertions(+), 436 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 270e94d..c21e48b 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -59,16 +59,16 @@ static piv_obj_t piv_objects[] = { {PIV_CERT_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_coa, 3}, {PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, get_coa, 4}, - {PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, - {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Private key for Card Authentication", 0, 0, get_proa, 1}, - {PIV_PVTK_OBJ_DS, 1, 0, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, - {PIV_PVTK_OBJ_KM, 1, 0, 0, "Prrivate key for Key Management", 0, 0, get_proa, 3}, + {PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, // 9a + {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Private key for Card Authentication", 0, 0, get_proa, 1}, // 9e + {PIV_PVTK_OBJ_DS, 1, 0, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, // 9c + {PIV_PVTK_OBJ_KM, 1, 0, 0, "Prrivate key for Key Management", 0, 0, get_proa, 3}, // 9d {PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4}, - {PIV_PUBK_OBJ_PIV_AUTH, 1, 0, 0, "Public key for PIV Authentication", 0, 0, get_proa, 0}, - {PIV_PUBK_OBJ_CARD_AUTH, 1, 0, 0, "Public key for Card Authentication", 0, 0, get_proa, 1}, - {PIV_PUBK_OBJ_DS, 1, 0, 0, "Public key for Digital Signature", 0, 0, get_proa, 2}, - {PIV_PUBK_OBJ_KM, 1, 0, 0, "Public key for Key Management", 0, 0, get_proa, 3}, + {PIV_PUBK_OBJ_PIV_AUTH, 1, 0, 0, "Public key for PIV Authentication", 0, 0, get_puoa, 0}, + {PIV_PUBK_OBJ_CARD_AUTH, 1, 0, 0, "Public key for Card Authentication", 0, 0, get_puoa, 1}, + {PIV_PUBK_OBJ_DS, 1, 0, 0, "Public key for Digital Signature", 0, 0, get_puoa, 2}, + {PIV_PUBK_OBJ_KM, 1, 0, 0, "Public key for Key Management", 0, 0, get_puoa, 3}, {PIV_PUBK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4} }; @@ -238,6 +238,18 @@ static void get_object_key_id(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR key_id) { } */ +static CK_KEY_TYPE get_key_type(EVP_PKEY *key) { + return do_get_key_type(key); +} + +static CK_KEY_TYPE get_modulus_bits(EVP_PKEY *key) { + return do_get_rsa_modulus_length(key); +} + +static CK_RV get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { + return do_get_public_key(key, data, len); +} + /* Get data object attribute */ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; @@ -527,31 +539,32 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Get private key object attribute */ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; - CK_BYTE tmp[64]; + CK_BYTE b_tmp[1024]; + CK_ULONG ul_tmp; // TODO: fix elsewhere too CK_ULONG len = 0; fprintf(stderr, "FOR PRIVATE KEY OBJECT %lu, I WANT ", obj); switch (template->type) { case CKA_CLASS: fprintf(stderr, "CLASS\n"); - len = 1; - tmp[0] = CKO_PRIVATE_KEY; - data = tmp; + len = sizeof(CK_ULONG); + ul_tmp = CKO_PRIVATE_KEY; + data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_TOKEN: // Technically all these objects are token objects fprintf(stderr, "TOKEN\n"); - len = 1; - tmp[0] = piv_objects[obj].token; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].token; + data = b_tmp; break; case CKA_PRIVATE: fprintf(stderr, "PRIVATE\n"); - len = 1; - tmp[0] = piv_objects[obj].private; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].private; + data = b_tmp; break; case CKA_LABEL: @@ -585,12 +598,13 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { // case CKA_ISSUER: // case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: - fprintf(stderr, "KEY TYPE TODO\n"); - len = 1; - tmp[0] = CKK_RSA; // TODO: just an example - data = tmp; + fprintf(stderr, "KEY TYPE\n"); + len = sizeof(CK_ULONG); + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + data = (CK_BYTE_PTR) &ul_tmp; break; - return CKR_FUNCTION_FAILED; case CKA_SUBJECT: fprintf(stderr, "SUBJECT TODO\n"); // Default empty @@ -598,9 +612,9 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_ID: fprintf(stderr, "ID\n"); - len = 1; - tmp[0] = piv_objects[obj].sub_id; - data = tmp; + len = sizeof(CK_ULONG); + ul_tmp = piv_objects[obj].sub_id; + data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_SENSITIVE: @@ -638,8 +652,27 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_END_DATE: fprintf(stderr, "END DATE TODO\n"); // Default empty return CKR_FUNCTION_FAILED; - /* case CKA_MODULUS: */ - /* case CKA_MODULUS_BITS: */ + + /*case CKA_MODULUS:*/ + case CKA_EC_POINT: + // We're trying to get the key length, get the ec point of the PUBLIC key + // TODO: or just give an error and explicitly fetch the pubk len when needed + fprintf(stderr, "EC_POINT\n"); + len = sizeof(b_tmp); + if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + data = b_tmp; + break; + + case CKA_MODULUS_BITS: + fprintf(stderr, "MODULUS BITS\n"); + len = sizeof(CK_ULONG); + ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == 0) + return CKR_FUNCTION_FAILED; + data = (CK_BYTE_PTR) &ul_tmp; + break; + /* case CKA_PUBLIC_EXPONENT: */ /* case CKA_PRIVATE_EXPONENT: */ /* case CKA_PRIME_1: */ @@ -661,9 +694,9 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* case CKA_ALWAYS_SENSITIVE: */ case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); - len = 1; - tmp[0] = piv_objects[obj].modifiable; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].modifiable; + data = b_tmp; break; /*case CKA_VENDOR_DEFINED:*/ diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index d139a99..cb98f28 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -7,7 +7,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { const unsigned char *p = data; // Mandatory temp variable required by OpenSSL int cert_len; - + /**cert = X509_new(); if (*cert == NULL) return CKR_HOST_MEMORY;*/ @@ -50,24 +50,87 @@ CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key) { return CKR_FUNCTION_FAILED; return CKR_OK; - + +} + +CK_KEY_TYPE do_get_key_type(EVP_PKEY *key) { + + switch (key->type) { + case EVP_PKEY_RSA: + case EVP_PKEY_RSA2: + return CKK_RSA; + + case EVP_PKEY_EC: + return CKK_ECDSA; + + default: + return CKK_VENDOR_DEFINED; // Actually an error + } +} + +CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) { + + CK_ULONG key_len = 0; + RSA *rsa; + + rsa = EVP_PKEY_get1_RSA(key); + if (rsa == NULL) + return 0; + + return RSA_size(rsa) * 8; // There is also RSA_bits but only in >= 1.1.0 + +} + +/* #include */ +/* #include */ +/* ERR_load_crypto_strings(); */ +/* //SSL_load_error_strings(); */ +/* fprintf(stderr, "ERROR %s\n", ERR_error_string(ERR_get_error(), NULL)); */ +CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { + + RSA *rsa; + EC_KEY *eck; + const EC_GROUP *ecg; // Alternatice solution is to get i2d_PUBKEY and manually offset + const EC_POINT *ecp; + point_conversion_form_t pcf = POINT_CONVERSION_UNCOMPRESSED; + + switch(key->type) { + case EVP_PKEY_RSA: + case EVP_PKEY_RSA2: + + rsa = EVP_PKEY_get1_RSA(key); + return CKR_FUNCTION_FAILED; // TODO; + break; + + case EVP_PKEY_EC: + eck = EVP_PKEY_get1_EC_KEY(key); + ecg = EC_KEY_get0_group(eck); + ecp = EC_KEY_get0_public_key(eck); + + if ((*len = EC_POINT_point2oct(ecg, ecp, pcf, data, *len, NULL)) == 0) + return CKR_FUNCTION_FAILED; + break; + + default: + return CKR_FUNCTION_FAILED; + } + + return CKR_OK; + } CK_RV free_key(EVP_PKEY *key) { EVP_PKEY_free(key); - + return CKR_OK; - + } -/* #include */ -/* #include */ -/* ERR_load_crypto_strings(); */ -/* //SSL_load_error_strings(); */ + CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len); - + // TODO: rand must be seeded first if (out_len < key_len) CKR_BUFFER_TOO_SMALL; diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index f9382d5..00bff66 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -4,13 +4,17 @@ #include #include #include +#include #include "pkcs11t.h" CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); CK_RV free_cert(X509 *cert); -CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); -CK_RV free_key(EVP_PKEY *key); +CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); +CK_KEY_TYPE do_get_key_type(EVP_PKEY *key); +CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key); +CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); +CK_RV free_key(EVP_PKEY *key); CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index 6808b3f..7ced074 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -3,25 +3,25 @@ * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is the Netscape security libraries. - * + * * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are + * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. - * + * * Contributor(s): - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and @@ -158,9 +158,9 @@ typedef struct CK_SLOT_INFO { /* flags: bit flags that provide capabilities of the slot * Bit Flag Mask Meaning */ -#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ -#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ -#define CKF_HW_SLOT 0x00000004 /* hardware slot */ +#define CKF_TOKEN_PRESENT 0x00000001UL /* a token is there */ +#define CKF_REMOVABLE_DEVICE 0x00000002UL /* removable devices*/ +#define CKF_HW_SLOT 0x00000004UL /* hardware slot */ typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; @@ -195,42 +195,42 @@ typedef struct CK_TOKEN_INFO { } CK_TOKEN_INFO; /* The flags parameter is defined as follows: - * Bit Flag Mask Meaning + * Bit Flag Mask Meaning */ -#define CKF_RNG 0x00000001 /* has random # - * generator */ -#define CKF_WRITE_PROTECTED 0x00000002 /* token is - * write- - * protected */ -#define CKF_LOGIN_REQUIRED 0x00000004 /* user must - * login */ -#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's - * PIN is set */ +#define CKF_RNG 0x00000001UL /* has random # + * generator */ +#define CKF_WRITE_PROTECTED 0x00000002UL /* token is + * write- + * protected */ +#define CKF_LOGIN_REQUIRED 0x00000004UL /* user must + * login */ +#define CKF_USER_PIN_INITIALIZED 0x00000008UL /* normal user's + * PIN is set */ /* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, * that means that *every* time the state of cryptographic * operations of a session is successfully saved, all keys * needed to continue those operations are stored in the state */ -#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 +#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020UL /* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means * that the token has some sort of clock. The time on that * clock is returned in the token info structure */ -#define CKF_CLOCK_ON_TOKEN 0x00000040 +#define CKF_CLOCK_ON_TOKEN 0x00000040UL /* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is * set, that means that there is some way for the user to login * without sending a PIN through the PKCS #11 library itself */ -#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 +#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100UL /* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, * that means that a single session with the token can perform * dual simultaneous cryptographic operations (digest and * encrypt; decrypt and digest; sign and encrypt; and decrypt * and sign) */ -#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 +#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200UL -#define CKF_TOKEN_INITIALIZED 0x00000400 +#define CKF_TOKEN_INITIALIZED 0x00000400UL typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; @@ -239,7 +239,7 @@ typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; * identifies a session */ typedef CK_ULONG CK_SESSION_HANDLE; -typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; /* CK_USER_TYPE enumerates the types of PKCS #11 users */ @@ -279,8 +279,8 @@ typedef struct CK_SESSION_INFO { /* The flags are defined in the following table: * Bit Flag Mask Meaning */ -#define CKF_RW_SESSION 0x00000002 /* session is r/w */ -#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ +#define CKF_RW_SESSION 0x00000002UL /* session is r/w */ +#define CKF_SERIAL_SESSION 0x00000004UL /* no parallel */ typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; @@ -300,12 +300,12 @@ typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; typedef CK_ULONG CK_OBJECT_CLASS; /* The following classes of objects are defined: */ -#define CKO_DATA 0x00000000 -#define CKO_CERTIFICATE 0x00000001 -#define CKO_PUBLIC_KEY 0x00000002 -#define CKO_PRIVATE_KEY 0x00000003 -#define CKO_SECRET_KEY 0x00000004 -#define CKO_VENDOR_DEFINED 0x80000000 +#define CKO_DATA 0x00000000UL +#define CKO_CERTIFICATE 0x00000001UL +#define CKO_PUBLIC_KEY 0x00000002UL +#define CKO_PRIVATE_KEY 0x00000003UL +#define CKO_SECRET_KEY 0x00000004UL +#define CKO_VENDOR_DEFINED 0x80000000UL typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; @@ -315,40 +315,40 @@ typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; typedef CK_ULONG CK_KEY_TYPE; /* the following key types are defined: */ -#define CKK_RSA 0x00000000 -#define CKK_DSA 0x00000001 -#define CKK_DH 0x00000002 +#define CKK_RSA 0x00000000UL +#define CKK_DSA 0x00000001UL +#define CKK_DH 0x00000002UL /* CKK_ECDSA and CKK_KEA are new for v2.0 */ /* PKCS #11 V2.01 probably won't actually have ECDSA in it */ -#define CKK_ECDSA 0x00000003 +#define CKK_ECDSA 0x00000003UL -#define CKK_KEA 0x00000005 +#define CKK_KEA 0x00000005UL -#define CKK_GENERIC_SECRET 0x00000010 -#define CKK_RC2 0x00000011 -#define CKK_RC4 0x00000012 -#define CKK_DES 0x00000013 -#define CKK_DES2 0x00000014 -#define CKK_DES3 0x00000015 +#define CKK_GENERIC_SECRET 0x00000010UL +#define CKK_RC2 0x00000011UL +#define CKK_RC4 0x00000012UL +#define CKK_DES 0x00000013UL +#define CKK_DES2 0x00000014UL +#define CKK_DES3 0x00000015UL /* all these key types are new for v2.0 */ -#define CKK_CAST 0x00000016 -#define CKK_CAST3 0x00000017 -#define CKK_CAST5 0x00000018 +#define CKK_CAST 0x00000016UL +#define CKK_CAST3 0x00000017UL +#define CKK_CAST5 0x00000018UL #define CKK_CAST128 0x00000018 /* CAST128=CAST5 */ -#define CKK_RC5 0x00000019 -#define CKK_IDEA 0x0000001A -#define CKK_SKIPJACK 0x0000001B -#define CKK_BATON 0x0000001C -#define CKK_JUNIPER 0x0000001D -#define CKK_CDMF 0x0000001E +#define CKK_RC5 0x00000019UL +#define CKK_IDEA 0x0000001AUL +#define CKK_SKIPJACK 0x0000001BUL +#define CKK_BATON 0x0000001CUL +#define CKK_JUNIPER 0x0000001DUL +#define CKK_CDMF 0x0000001EUL /* all these key types are new for v2.11 */ -#define CKK_AES 0x0000001F +#define CKK_AES 0x0000001FUL -#define CKK_VENDOR_DEFINED 0x80000000 +#define CKK_VENDOR_DEFINED 0x80000000UL /* CK_CERTIFICATE_TYPE is a value that identifies a certificate @@ -359,8 +359,8 @@ typedef CK_ULONG CK_CERTIFICATE_TYPE; typedef CK_CERTIFICATE_TYPE CK_PTR CK_CERTIFICATE_TYPE_PTR; /* The following certificate types are defined: */ -#define CKC_X_509 0x00000000 -#define CKC_VENDOR_DEFINED 0x80000000 +#define CKC_X_509 0x00000000UL +#define CKC_VENDOR_DEFINED 0x80000000UL /* CK_ATTRIBUTE_TYPE is a value that identifies an attribute @@ -370,56 +370,63 @@ typedef CK_CERTIFICATE_TYPE CK_PTR CK_CERTIFICATE_TYPE_PTR; typedef CK_ULONG CK_ATTRIBUTE_TYPE; /* The following attribute types are defined: */ -#define CKA_CLASS 0x00000000 -#define CKA_TOKEN 0x00000001 -#define CKA_PRIVATE 0x00000002 -#define CKA_LABEL 0x00000003 -#define CKA_APPLICATION 0x00000010 -#define CKA_VALUE 0x00000011 -#define CKA_OBJECT_ID 0x00000012 -#define CKA_CERTIFICATE_TYPE 0x00000080 -#define CKA_ISSUER 0x00000081 -#define CKA_SERIAL_NUMBER 0x00000082 -#define CKA_KEY_TYPE 0x00000100 -#define CKA_SUBJECT 0x00000101 -#define CKA_ID 0x00000102 -#define CKA_SENSITIVE 0x00000103 -#define CKA_ENCRYPT 0x00000104 -#define CKA_DECRYPT 0x00000105 -#define CKA_WRAP 0x00000106 -#define CKA_UNWRAP 0x00000107 -#define CKA_SIGN 0x00000108 -#define CKA_SIGN_RECOVER 0x00000109 -#define CKA_VERIFY 0x0000010A -#define CKA_VERIFY_RECOVER 0x0000010B -#define CKA_DERIVE 0x0000010C -#define CKA_START_DATE 0x00000110 -#define CKA_END_DATE 0x00000111 -#define CKA_MODULUS 0x00000120 -#define CKA_MODULUS_BITS 0x00000121 -#define CKA_PUBLIC_EXPONENT 0x00000122 -#define CKA_PRIVATE_EXPONENT 0x00000123 -#define CKA_PRIME_1 0x00000124 -#define CKA_PRIME_2 0x00000125 -#define CKA_EXPONENT_1 0x00000126 -#define CKA_EXPONENT_2 0x00000127 -#define CKA_COEFFICIENT 0x00000128 -#define CKA_PRIME 0x00000130 -#define CKA_SUBPRIME 0x00000131 -#define CKA_BASE 0x00000132 -#define CKA_VALUE_BITS 0x00000160 -#define CKA_VALUE_LEN 0x00000161 +#define CKA_CLASS 0x00000000UL +#define CKA_TOKEN 0x00000001UL +#define CKA_PRIVATE 0x00000002UL +#define CKA_LABEL 0x00000003UL +#define CKA_APPLICATION 0x00000010UL +#define CKA_VALUE 0x00000011UL +#define CKA_OBJECT_ID 0x00000012UL +#define CKA_CERTIFICATE_TYPE 0x00000080UL +#define CKA_ISSUER 0x00000081UL +#define CKA_SERIAL_NUMBER 0x00000082UL +#define CKA_KEY_TYPE 0x00000100UL +#define CKA_SUBJECT 0x00000101UL +#define CKA_ID 0x00000102UL +#define CKA_SENSITIVE 0x00000103UL +#define CKA_ENCRYPT 0x00000104UL +#define CKA_DECRYPT 0x00000105UL +#define CKA_WRAP 0x00000106UL +#define CKA_UNWRAP 0x00000107UL +#define CKA_SIGN 0x00000108UL +#define CKA_SIGN_RECOVER 0x00000109UL +#define CKA_VERIFY 0x0000010AUL +#define CKA_VERIFY_RECOVER 0x0000010BUL +#define CKA_DERIVE 0x0000010CUL +#define CKA_START_DATE 0x00000110UL +#define CKA_END_DATE 0x00000111UL +#define CKA_MODULUS 0x00000120UL +#define CKA_MODULUS_BITS 0x00000121UL +#define CKA_PUBLIC_EXPONENT 0x00000122UL +#define CKA_PRIVATE_EXPONENT 0x00000123UL +#define CKA_PRIME_1 0x00000124UL +#define CKA_PRIME_2 0x00000125UL +#define CKA_EXPONENT_1 0x00000126UL +#define CKA_EXPONENT_2 0x00000127UL +#define CKA_COEFFICIENT 0x00000128UL +#define CKA_PRIME 0x00000130UL +#define CKA_SUBPRIME 0x00000131UL +#define CKA_BASE 0x00000132UL +#define CKA_VALUE_BITS 0x00000160UL +#define CKA_VALUE_LEN 0x00000161UL /* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, * CKA_ALWAYS_SENSITIVE, and CKA_MODIFIABLE are new for v2.0 */ -#define CKA_EXTRACTABLE 0x00000162 -#define CKA_LOCAL 0x00000163 -#define CKA_NEVER_EXTRACTABLE 0x00000164 -#define CKA_ALWAYS_SENSITIVE 0x00000165 -#define CKA_MODIFIABLE 0x00000170 +#define CKA_EXTRACTABLE 0x00000162UL +#define CKA_LOCAL 0x00000163UL +#define CKA_NEVER_EXTRACTABLE 0x00000164UL +#define CKA_ALWAYS_SENSITIVE 0x00000165UL +#define CKA_MODIFIABLE 0x00000170UL -#define CKA_VENDOR_DEFINED 0x80000000 +/* New in 2.2 */ +#define CKA_COPYABLE 0x00000171UL +#define CKA_DESTROYABLE 0x00000172UL +#define CKA_ECDSA_PARAMS 0x00000180UL +#define CKA_EC_PARAMS 0x00000180UL +#define CKA_EC_POINT 0x00000181UL +#define CKA_ALWAYS_AUTHENTICATE 0x00000202UL +#define CKA_VENDOR_DEFINED 0x80000000UL /* CK_ATTRIBUTE is a structure that includes the type, length * and value of an attribute */ @@ -449,219 +456,219 @@ typedef struct CK_DATE{ typedef CK_ULONG CK_MECHANISM_TYPE; /* the following mechanism types are defined: */ -#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 -#define CKM_RSA_PKCS 0x00000001 -#define CKM_RSA_9796 0x00000002 -#define CKM_RSA_X_509 0x00000003 +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000UL +#define CKM_RSA_PKCS 0x00000001UL +#define CKM_RSA_9796 0x00000002UL +#define CKM_RSA_X_509 0x00000003UL /* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS * are new for v2.0. They are mechanisms which hash and sign */ -#define CKM_MD2_RSA_PKCS 0x00000004 -#define CKM_MD5_RSA_PKCS 0x00000005 -#define CKM_SHA1_RSA_PKCS 0x00000006 +#define CKM_MD2_RSA_PKCS 0x00000004UL +#define CKM_MD5_RSA_PKCS 0x00000005UL +#define CKM_SHA1_RSA_PKCS 0x00000006UL /* Added for 2.4 */ -#define CKM_RSA_PKCS_PSS 0x0000000D -#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E +#define CKM_RSA_PKCS_PSS 0x0000000DUL +#define CKM_SHA1_RSA_PKCS_PSS 0x0000000EUL /* Added for 2.4 */ -#define CKM_DSA_KEY_PAIR_GEN 0x00000010 -#define CKM_DSA 0x00000011 -#define CKM_DSA_SHA1 0x00000012 -#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 -#define CKM_DH_PKCS_DERIVE 0x00000021 +#define CKM_DSA_KEY_PAIR_GEN 0x00000010UL +#define CKM_DSA 0x00000011UL +#define CKM_DSA_SHA1 0x00000012UL +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020UL +#define CKM_DH_PKCS_DERIVE 0x00000021UL /* Added for 2.4 */ -#define CKM_SHA256_RSA_PKCS 0x00000040 -#define CKM_SHA384_RSA_PKCS 0x00000041 -#define CKM_SHA512_RSA_PKCS 0x00000042 -#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 -#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 -#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 +#define CKM_SHA256_RSA_PKCS 0x00000040UL +#define CKM_SHA384_RSA_PKCS 0x00000041UL +#define CKM_SHA512_RSA_PKCS 0x00000042UL +#define CKM_SHA256_RSA_PKCS_PSS 0x00000043UL +#define CKM_SHA384_RSA_PKCS_PSS 0x00000044UL +#define CKM_SHA512_RSA_PKCS_PSS 0x00000045UL /* Added for 2.4 */ -#define CKM_RC2_KEY_GEN 0x00000100 -#define CKM_RC2_ECB 0x00000101 -#define CKM_RC2_CBC 0x00000102 -#define CKM_RC2_MAC 0x00000103 +#define CKM_RC2_KEY_GEN 0x00000100UL +#define CKM_RC2_ECB 0x00000101UL +#define CKM_RC2_CBC 0x00000102UL +#define CKM_RC2_MAC 0x00000103UL /* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ -#define CKM_RC2_MAC_GENERAL 0x00000104 -#define CKM_RC2_CBC_PAD 0x00000105 +#define CKM_RC2_MAC_GENERAL 0x00000104UL +#define CKM_RC2_CBC_PAD 0x00000105UL -#define CKM_RC4_KEY_GEN 0x00000110 -#define CKM_RC4 0x00000111 -#define CKM_DES_KEY_GEN 0x00000120 -#define CKM_DES_ECB 0x00000121 -#define CKM_DES_CBC 0x00000122 -#define CKM_DES_MAC 0x00000123 +#define CKM_RC4_KEY_GEN 0x00000110UL +#define CKM_RC4 0x00000111UL +#define CKM_DES_KEY_GEN 0x00000120UL +#define CKM_DES_ECB 0x00000121UL +#define CKM_DES_CBC 0x00000122UL +#define CKM_DES_MAC 0x00000123UL /* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ -#define CKM_DES_MAC_GENERAL 0x00000124 -#define CKM_DES_CBC_PAD 0x00000125 +#define CKM_DES_MAC_GENERAL 0x00000124UL +#define CKM_DES_CBC_PAD 0x00000125UL -#define CKM_DES2_KEY_GEN 0x00000130 -#define CKM_DES3_KEY_GEN 0x00000131 -#define CKM_DES3_ECB 0x00000132 -#define CKM_DES3_CBC 0x00000133 -#define CKM_DES3_MAC 0x00000134 +#define CKM_DES2_KEY_GEN 0x00000130UL +#define CKM_DES3_KEY_GEN 0x00000131UL +#define CKM_DES3_ECB 0x00000132UL +#define CKM_DES3_CBC 0x00000133UL +#define CKM_DES3_MAC 0x00000134UL /* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ -#define CKM_DES3_MAC_GENERAL 0x00000135 -#define CKM_DES3_CBC_PAD 0x00000136 -#define CKM_CDMF_KEY_GEN 0x00000140 -#define CKM_CDMF_ECB 0x00000141 -#define CKM_CDMF_CBC 0x00000142 -#define CKM_CDMF_MAC 0x00000143 -#define CKM_CDMF_MAC_GENERAL 0x00000144 -#define CKM_CDMF_CBC_PAD 0x00000145 +#define CKM_DES3_MAC_GENERAL 0x00000135UL +#define CKM_DES3_CBC_PAD 0x00000136UL +#define CKM_CDMF_KEY_GEN 0x00000140UL +#define CKM_CDMF_ECB 0x00000141UL +#define CKM_CDMF_CBC 0x00000142UL +#define CKM_CDMF_MAC 0x00000143UL +#define CKM_CDMF_MAC_GENERAL 0x00000144UL +#define CKM_CDMF_CBC_PAD 0x00000145UL -#define CKM_MD2 0x00000200 +#define CKM_MD2 0x00000200UL /* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ -#define CKM_MD2_HMAC 0x00000201 -#define CKM_MD2_HMAC_GENERAL 0x00000202 +#define CKM_MD2_HMAC 0x00000201UL +#define CKM_MD2_HMAC_GENERAL 0x00000202UL -#define CKM_MD5 0x00000210 +#define CKM_MD5 0x00000210UL /* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ -#define CKM_MD5_HMAC 0x00000211 -#define CKM_MD5_HMAC_GENERAL 0x00000212 +#define CKM_MD5_HMAC 0x00000211UL +#define CKM_MD5_HMAC_GENERAL 0x00000212UL -#define CKM_SHA_1 0x00000220 +#define CKM_SHA_1 0x00000220UL /* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ -#define CKM_SHA_1_HMAC 0x00000221 -#define CKM_SHA_1_HMAC_GENERAL 0x00000222 +#define CKM_SHA_1_HMAC 0x00000221UL +#define CKM_SHA_1_HMAC_GENERAL 0x00000222UL /* Added for 2.4 */ -#define CKM_SHA256 0x00000250 -#define CKM_SHA384 0x00000260 -#define CKM_SHA512 0x00000270 +#define CKM_SHA256 0x00000250UL +#define CKM_SHA384 0x00000260UL +#define CKM_SHA512 0x00000270UL /* Added for 2.4 */ /* All of the following mechanisms are new for v2.0 */ /* Note that CAST128 and CAST5 are the same algorithm */ -#define CKM_CAST_KEY_GEN 0x00000300 -#define CKM_CAST_ECB 0x00000301 -#define CKM_CAST_CBC 0x00000302 -#define CKM_CAST_MAC 0x00000303 -#define CKM_CAST_MAC_GENERAL 0x00000304 -#define CKM_CAST_CBC_PAD 0x00000305 -#define CKM_CAST3_KEY_GEN 0x00000310 -#define CKM_CAST3_ECB 0x00000311 -#define CKM_CAST3_CBC 0x00000312 -#define CKM_CAST3_MAC 0x00000313 -#define CKM_CAST3_MAC_GENERAL 0x00000314 -#define CKM_CAST3_CBC_PAD 0x00000315 -#define CKM_CAST5_KEY_GEN 0x00000320 -#define CKM_CAST128_KEY_GEN 0x00000320 -#define CKM_CAST5_ECB 0x00000321 -#define CKM_CAST128_ECB 0x00000321 -#define CKM_CAST5_CBC 0x00000322 -#define CKM_CAST128_CBC 0x00000322 -#define CKM_CAST5_MAC 0x00000323 -#define CKM_CAST128_MAC 0x00000323 -#define CKM_CAST5_MAC_GENERAL 0x00000324 -#define CKM_CAST128_MAC_GENERAL 0x00000324 -#define CKM_CAST5_CBC_PAD 0x00000325 -#define CKM_CAST128_CBC_PAD 0x00000325 -#define CKM_RC5_KEY_GEN 0x00000330 -#define CKM_RC5_ECB 0x00000331 -#define CKM_RC5_CBC 0x00000332 -#define CKM_RC5_MAC 0x00000333 -#define CKM_RC5_MAC_GENERAL 0x00000334 -#define CKM_RC5_CBC_PAD 0x00000335 -#define CKM_IDEA_KEY_GEN 0x00000340 -#define CKM_IDEA_ECB 0x00000341 -#define CKM_IDEA_CBC 0x00000342 -#define CKM_IDEA_MAC 0x00000343 -#define CKM_IDEA_MAC_GENERAL 0x00000344 -#define CKM_IDEA_CBC_PAD 0x00000345 -#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 -#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 -#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 -#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 -#define CKM_XOR_BASE_AND_DATA 0x00000364 -#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 -#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 -#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 -#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 -#define CKM_SSL3_MD5_MAC 0x00000380 -#define CKM_SSL3_SHA1_MAC 0x00000381 -#define CKM_MD5_KEY_DERIVATION 0x00000390 -#define CKM_MD2_KEY_DERIVATION 0x00000391 -#define CKM_SHA1_KEY_DERIVATION 0x00000392 -#define CKM_PBE_MD2_DES_CBC 0x000003A0 -#define CKM_PBE_MD5_DES_CBC 0x000003A1 -#define CKM_PBE_MD5_CAST_CBC 0x000003A2 -#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 -#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 -#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 -#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 -#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 -#define CKM_PBE_SHA1_RC4_128 0x000003A6 -#define CKM_PBE_SHA1_RC4_40 0x000003A7 -#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 -#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 -#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA -#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB -#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 -#define CKM_KEY_WRAP_LYNKS 0x00000400 -#define CKM_KEY_WRAP_SET_OAEP 0x00000401 +#define CKM_CAST_KEY_GEN 0x00000300UL +#define CKM_CAST_ECB 0x00000301UL +#define CKM_CAST_CBC 0x00000302UL +#define CKM_CAST_MAC 0x00000303UL +#define CKM_CAST_MAC_GENERAL 0x00000304UL +#define CKM_CAST_CBC_PAD 0x00000305UL +#define CKM_CAST3_KEY_GEN 0x00000310UL +#define CKM_CAST3_ECB 0x00000311UL +#define CKM_CAST3_CBC 0x00000312UL +#define CKM_CAST3_MAC 0x00000313UL +#define CKM_CAST3_MAC_GENERAL 0x00000314UL +#define CKM_CAST3_CBC_PAD 0x00000315UL +#define CKM_CAST5_KEY_GEN 0x00000320UL +#define CKM_CAST128_KEY_GEN 0x00000320UL +#define CKM_CAST5_ECB 0x00000321UL +#define CKM_CAST128_ECB 0x00000321UL +#define CKM_CAST5_CBC 0x00000322UL +#define CKM_CAST128_CBC 0x00000322UL +#define CKM_CAST5_MAC 0x00000323UL +#define CKM_CAST128_MAC 0x00000323UL +#define CKM_CAST5_MAC_GENERAL 0x00000324UL +#define CKM_CAST128_MAC_GENERAL 0x00000324UL +#define CKM_CAST5_CBC_PAD 0x00000325UL +#define CKM_CAST128_CBC_PAD 0x00000325UL +#define CKM_RC5_KEY_GEN 0x00000330UL +#define CKM_RC5_ECB 0x00000331UL +#define CKM_RC5_CBC 0x00000332UL +#define CKM_RC5_MAC 0x00000333UL +#define CKM_RC5_MAC_GENERAL 0x00000334UL +#define CKM_RC5_CBC_PAD 0x00000335UL +#define CKM_IDEA_KEY_GEN 0x00000340UL +#define CKM_IDEA_ECB 0x00000341UL +#define CKM_IDEA_CBC 0x00000342UL +#define CKM_IDEA_MAC 0x00000343UL +#define CKM_IDEA_MAC_GENERAL 0x00000344UL +#define CKM_IDEA_CBC_PAD 0x00000345UL +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350UL +#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360UL +#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362UL +#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363UL +#define CKM_XOR_BASE_AND_DATA 0x00000364UL +#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365UL +#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370UL +#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371UL +#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372UL +#define CKM_SSL3_MD5_MAC 0x00000380UL +#define CKM_SSL3_SHA1_MAC 0x00000381UL +#define CKM_MD5_KEY_DERIVATION 0x00000390UL +#define CKM_MD2_KEY_DERIVATION 0x00000391UL +#define CKM_SHA1_KEY_DERIVATION 0x00000392UL +#define CKM_PBE_MD2_DES_CBC 0x000003A0UL +#define CKM_PBE_MD5_DES_CBC 0x000003A1UL +#define CKM_PBE_MD5_CAST_CBC 0x000003A2UL +#define CKM_PBE_MD5_CAST3_CBC 0x000003A3UL +#define CKM_PBE_MD5_CAST5_CBC 0x000003A4UL +#define CKM_PBE_MD5_CAST128_CBC 0x000003A4UL +#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5UL +#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5UL +#define CKM_PBE_SHA1_RC4_128 0x000003A6UL +#define CKM_PBE_SHA1_RC4_40 0x000003A7UL +#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8UL +#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9UL +#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AAUL +#define CKM_PBE_SHA1_RC2_40_CBC 0x000003ABUL +#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0UL +#define CKM_KEY_WRAP_LYNKS 0x00000400UL +#define CKM_KEY_WRAP_SET_OAEP 0x00000401UL /* Fortezza mechanisms */ -#define CKM_SKIPJACK_KEY_GEN 0x00001000 -#define CKM_SKIPJACK_ECB64 0x00001001 -#define CKM_SKIPJACK_CBC64 0x00001002 -#define CKM_SKIPJACK_OFB64 0x00001003 -#define CKM_SKIPJACK_CFB64 0x00001004 -#define CKM_SKIPJACK_CFB32 0x00001005 -#define CKM_SKIPJACK_CFB16 0x00001006 -#define CKM_SKIPJACK_CFB8 0x00001007 -#define CKM_SKIPJACK_WRAP 0x00001008 -#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 -#define CKM_SKIPJACK_RELAYX 0x0000100a -#define CKM_KEA_KEY_PAIR_GEN 0x00001010 -#define CKM_KEA_KEY_DERIVE 0x00001011 -#define CKM_FORTEZZA_TIMESTAMP 0x00001020 -#define CKM_BATON_KEY_GEN 0x00001030 -#define CKM_BATON_ECB128 0x00001031 -#define CKM_BATON_ECB96 0x00001032 -#define CKM_BATON_CBC128 0x00001033 -#define CKM_BATON_COUNTER 0x00001034 -#define CKM_BATON_SHUFFLE 0x00001035 -#define CKM_BATON_WRAP 0x00001036 +#define CKM_SKIPJACK_KEY_GEN 0x00001000UL +#define CKM_SKIPJACK_ECB64 0x00001001UL +#define CKM_SKIPJACK_CBC64 0x00001002UL +#define CKM_SKIPJACK_OFB64 0x00001003UL +#define CKM_SKIPJACK_CFB64 0x00001004UL +#define CKM_SKIPJACK_CFB32 0x00001005UL +#define CKM_SKIPJACK_CFB16 0x00001006UL +#define CKM_SKIPJACK_CFB8 0x00001007UL +#define CKM_SKIPJACK_WRAP 0x00001008UL +#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009UL +#define CKM_SKIPJACK_RELAYX 0x0000100aUL +#define CKM_KEA_KEY_PAIR_GEN 0x00001010UL +#define CKM_KEA_KEY_DERIVE 0x00001011UL +#define CKM_FORTEZZA_TIMESTAMP 0x00001020UL +#define CKM_BATON_KEY_GEN 0x00001030UL +#define CKM_BATON_ECB128 0x00001031UL +#define CKM_BATON_ECB96 0x00001032UL +#define CKM_BATON_CBC128 0x00001033UL +#define CKM_BATON_COUNTER 0x00001034UL +#define CKM_BATON_SHUFFLE 0x00001035UL +#define CKM_BATON_WRAP 0x00001036UL /* PKCS #11 V2.01 probably won't actually have ECDSA in it */ -#define CKM_EC_KEY_PAIR_GEN 0x00001040 +#define CKM_EC_KEY_PAIR_GEN 0x00001040UL //#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 // Deprecated in 2.11 -#define CKM_ECDSA 0x00001041 -#define CKM_ECDSA_SHA1 0x00001042 +#define CKM_ECDSA 0x00001041UL +#define CKM_ECDSA_SHA1 0x00001042UL /* Added for 2.4 */ -#define CKM_ECDH1_DERIVE 0x00001050 -#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 +#define CKM_ECDH1_DERIVE 0x00001050UL +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051UL /* Added for 2.4 */ -#define CKM_JUNIPER_KEY_GEN 0x00001060 -#define CKM_JUNIPER_ECB128 0x00001061 -#define CKM_JUNIPER_CBC128 0x00001062 -#define CKM_JUNIPER_COUNTER 0x00001063 -#define CKM_JUNIPER_SHUFFLE 0x00001064 -#define CKM_JUNIPER_WRAP 0x00001065 -#define CKM_FASTHASH 0x00001070 +#define CKM_JUNIPER_KEY_GEN 0x00001060UL +#define CKM_JUNIPER_ECB128 0x00001061UL +#define CKM_JUNIPER_CBC128 0x00001062UL +#define CKM_JUNIPER_COUNTER 0x00001063UL +#define CKM_JUNIPER_SHUFFLE 0x00001064UL +#define CKM_JUNIPER_WRAP 0x00001065UL +#define CKM_FASTHASH 0x00001070UL -#define CKM_AES_KEY_GEN 0x00001080 -#define CKM_AES_ECB 0x00001081 -#define CKM_AES_CBC 0x00001082 -#define CKM_AES_MAC 0x00001083 -#define CKM_AES_MAC_GENERAL 0x00001084 -#define CKM_AES_CBC_PAD 0x00001085 +#define CKM_AES_KEY_GEN 0x00001080UL +#define CKM_AES_ECB 0x00001081UL +#define CKM_AES_CBC 0x00001082UL +#define CKM_AES_MAC 0x00001083UL +#define CKM_AES_MAC_GENERAL 0x00001084UL +#define CKM_AES_CBC_PAD 0x00001085UL -#define CKM_VENDOR_DEFINED 0x80000000 +#define CKM_VENDOR_DEFINED 0x80000000UL typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; @@ -690,27 +697,27 @@ typedef struct CK_MECHANISM_INFO { /* The flags are defined as follows: * Bit Flag Mask Meaning */ -#define CKF_HW 0x00000001 /* performed by HW */ +#define CKF_HW 0x00000001UL /* performed by HW */ /* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, * and CKF_DERIVE are new for v2.0. They specify whether or not * a mechanism can be used for a particular task */ -#define CKF_ENCRYPT 0x00000100 -#define CKF_DECRYPT 0x00000200 -#define CKF_DIGEST 0x00000400 -#define CKF_SIGN 0x00000800 -#define CKF_SIGN_RECOVER 0x00001000 -#define CKF_VERIFY 0x00002000 -#define CKF_VERIFY_RECOVER 0x00004000 -#define CKF_GENERATE 0x00008000 -#define CKF_GENERATE_KEY_PAIR 0x00010000 -#define CKF_WRAP 0x00020000 -#define CKF_UNWRAP 0x00040000 -#define CKF_DERIVE 0x00080000 +#define CKF_ENCRYPT 0x00000100UL +#define CKF_DECRYPT 0x00000200UL +#define CKF_DIGEST 0x00000400UL +#define CKF_SIGN 0x00000800UL +#define CKF_SIGN_RECOVER 0x00001000UL +#define CKF_VERIFY 0x00002000UL +#define CKF_VERIFY_RECOVER 0x00004000UL +#define CKF_GENERATE 0x00008000UL +#define CKF_GENERATE_KEY_PAIR 0x00010000UL +#define CKF_WRAP 0x00020000UL +#define CKF_UNWRAP 0x00040000UL +#define CKF_DERIVE 0x00080000UL -#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */ +#define CKF_EXTENSION 0x80000000UL /* FALSE for 2.01 */ typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; @@ -720,129 +727,129 @@ typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; /* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ typedef CK_ULONG CK_RV; -#define CKR_OK 0x00000000 -#define CKR_CANCEL 0x00000001 -#define CKR_HOST_MEMORY 0x00000002 -#define CKR_SLOT_ID_INVALID 0x00000003 +#define CKR_OK 0x00000000UL +#define CKR_CANCEL 0x00000001UL +#define CKR_HOST_MEMORY 0x00000002UL +#define CKR_SLOT_ID_INVALID 0x00000003UL /* CKR_FLAGS_INVALID was removed for v2.0 */ /* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ -#define CKR_GENERAL_ERROR 0x00000005 -#define CKR_FUNCTION_FAILED 0x00000006 +#define CKR_GENERAL_ERROR 0x00000005UL +#define CKR_FUNCTION_FAILED 0x00000006UL /* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, * and CKR_CANT_LOCK are new for v2.01 */ -#define CKR_ARGUMENTS_BAD 0x00000007 -#define CKR_NO_EVENT 0x00000008 -#define CKR_NEED_TO_CREATE_THREADS 0x00000009 -#define CKR_CANT_LOCK 0x0000000A +#define CKR_ARGUMENTS_BAD 0x00000007UL +#define CKR_NO_EVENT 0x00000008UL +#define CKR_NEED_TO_CREATE_THREADS 0x00000009UL +#define CKR_CANT_LOCK 0x0000000AUL -#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 -#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 -#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 -#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 -#define CKR_DATA_INVALID 0x00000020 -#define CKR_DATA_LEN_RANGE 0x00000021 -#define CKR_DEVICE_ERROR 0x00000030 -#define CKR_DEVICE_MEMORY 0x00000031 -#define CKR_DEVICE_REMOVED 0x00000032 -#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 -#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 -#define CKR_FUNCTION_CANCELED 0x00000050 -#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 +#define CKR_ATTRIBUTE_READ_ONLY 0x00000010UL +#define CKR_ATTRIBUTE_SENSITIVE 0x00000011UL +#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012UL +#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013UL +#define CKR_DATA_INVALID 0x00000020UL +#define CKR_DATA_LEN_RANGE 0x00000021UL +#define CKR_DEVICE_ERROR 0x00000030UL +#define CKR_DEVICE_MEMORY 0x00000031UL +#define CKR_DEVICE_REMOVED 0x00000032UL +#define CKR_ENCRYPTED_DATA_INVALID 0x00000040UL +#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041UL +#define CKR_FUNCTION_CANCELED 0x00000050UL +#define CKR_FUNCTION_NOT_PARALLEL 0x00000051UL /* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ -#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 +#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054UL -#define CKR_KEY_HANDLE_INVALID 0x00000060 +#define CKR_KEY_HANDLE_INVALID 0x00000060UL /* CKR_KEY_SENSITIVE was removed for v2.0 */ -#define CKR_KEY_SIZE_RANGE 0x00000062 -#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 +#define CKR_KEY_SIZE_RANGE 0x00000062UL +#define CKR_KEY_TYPE_INCONSISTENT 0x00000063UL /* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for * v2.0 */ -#define CKR_KEY_NOT_NEEDED 0x00000064 -#define CKR_KEY_CHANGED 0x00000065 -#define CKR_KEY_NEEDED 0x00000066 -#define CKR_KEY_INDIGESTIBLE 0x00000067 -#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 -#define CKR_KEY_NOT_WRAPPABLE 0x00000069 -#define CKR_KEY_UNEXTRACTABLE 0x0000006A +#define CKR_KEY_NOT_NEEDED 0x00000064UL +#define CKR_KEY_CHANGED 0x00000065UL +#define CKR_KEY_NEEDED 0x00000066UL +#define CKR_KEY_INDIGESTIBLE 0x00000067UL +#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068UL +#define CKR_KEY_NOT_WRAPPABLE 0x00000069UL +#define CKR_KEY_UNEXTRACTABLE 0x0000006AUL -#define CKR_MECHANISM_INVALID 0x00000070 -#define CKR_MECHANISM_PARAM_INVALID 0x00000071 +#define CKR_MECHANISM_INVALID 0x00000070UL +#define CKR_MECHANISM_PARAM_INVALID 0x00000071UL /* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID * were removed for v2.0 */ -#define CKR_OBJECT_HANDLE_INVALID 0x00000082 -#define CKR_OPERATION_ACTIVE 0x00000090 -#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 -#define CKR_PIN_INCORRECT 0x000000A0 -#define CKR_PIN_INVALID 0x000000A1 -#define CKR_PIN_LEN_RANGE 0x000000A2 +#define CKR_OBJECT_HANDLE_INVALID 0x00000082UL +#define CKR_OPERATION_ACTIVE 0x00000090UL +#define CKR_OPERATION_NOT_INITIALIZED 0x00000091UL +#define CKR_PIN_INCORRECT 0x000000A0UL +#define CKR_PIN_INVALID 0x000000A1UL +#define CKR_PIN_LEN_RANGE 0x000000A2UL /* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ -#define CKR_PIN_EXPIRED 0x000000A3 -#define CKR_PIN_LOCKED 0x000000A4 +#define CKR_PIN_EXPIRED 0x000000A3UL +#define CKR_PIN_LOCKED 0x000000A4UL -#define CKR_SESSION_CLOSED 0x000000B0 -#define CKR_SESSION_COUNT 0x000000B1 -#define CKR_SESSION_HANDLE_INVALID 0x000000B3 -#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 -#define CKR_SESSION_READ_ONLY 0x000000B5 -#define CKR_SESSION_EXISTS 0x000000B6 +#define CKR_SESSION_CLOSED 0x000000B0UL +#define CKR_SESSION_COUNT 0x000000B1UL +#define CKR_SESSION_HANDLE_INVALID 0x000000B3UL +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4UL +#define CKR_SESSION_READ_ONLY 0x000000B5UL +#define CKR_SESSION_EXISTS 0x000000B6UL /* CKR_SESSION_READ_ONLY_EXISTS and * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ -#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 -#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 +#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7UL +#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8UL -#define CKR_SIGNATURE_INVALID 0x000000C0 -#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 -#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 -#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 -#define CKR_TOKEN_NOT_PRESENT 0x000000E0 -#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 -#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 -#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 -#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 -#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 -#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 -#define CKR_USER_NOT_LOGGED_IN 0x00000101 -#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 -#define CKR_USER_TYPE_INVALID 0x00000103 +#define CKR_SIGNATURE_INVALID 0x000000C0UL +#define CKR_SIGNATURE_LEN_RANGE 0x000000C1UL +#define CKR_TEMPLATE_INCOMPLETE 0x000000D0UL +#define CKR_TEMPLATE_INCONSISTENT 0x000000D1UL +#define CKR_TOKEN_NOT_PRESENT 0x000000E0UL +#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1UL +#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2UL +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0UL +#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1UL +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2UL +#define CKR_USER_ALREADY_LOGGED_IN 0x00000100UL +#define CKR_USER_NOT_LOGGED_IN 0x00000101UL +#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102UL +#define CKR_USER_TYPE_INVALID 0x00000103UL /* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES * are new to v2.01 */ -#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 -#define CKR_USER_TOO_MANY_TYPES 0x00000105 +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104UL +#define CKR_USER_TOO_MANY_TYPES 0x00000105UL -#define CKR_WRAPPED_KEY_INVALID 0x00000110 -#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 -#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 -#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 -#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 -#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 +#define CKR_WRAPPED_KEY_INVALID 0x00000110UL +#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112UL +#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113UL +#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114UL +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115UL +#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120UL /* These are new to v2.0 */ -#define CKR_RANDOM_NO_RNG 0x00000121 -#define CKR_BUFFER_TOO_SMALL 0x00000150 -#define CKR_SAVED_STATE_INVALID 0x00000160 -#define CKR_INFORMATION_SENSITIVE 0x00000170 -#define CKR_STATE_UNSAVEABLE 0x00000180 +#define CKR_RANDOM_NO_RNG 0x00000121UL +#define CKR_BUFFER_TOO_SMALL 0x00000150UL +#define CKR_SAVED_STATE_INVALID 0x00000160UL +#define CKR_INFORMATION_SENSITIVE 0x00000170UL +#define CKR_STATE_UNSAVEABLE 0x00000180UL /* These are new to v2.01 */ -#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 -#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 -#define CKR_MUTEX_BAD 0x000001A0 -#define CKR_MUTEX_NOT_LOCKED 0x000001A1 +#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190UL +#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191UL +#define CKR_MUTEX_BAD 0x000001A0UL +#define CKR_MUTEX_NOT_LOCKED 0x000001A1UL -#define CKR_VENDOR_DEFINED 0x80000000 +#define CKR_VENDOR_DEFINED 0x80000000UL /* CK_NOTIFY is an application callback that processes events */ @@ -905,8 +912,8 @@ typedef struct CK_C_INITIALIZE_ARGS { /* flags: bit flags that provide capabilities of the slot * Bit Flag Mask Meaning */ -#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 -#define CKF_OS_LOCKING_OK 0x00000002 +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001UL +#define CKF_OS_LOCKING_OK 0x00000002UL typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; @@ -1144,24 +1151,24 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; * PKCS #11 interface. Most of these are place holders for other mechanism * and will change in the future. */ -#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001L -#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L -#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L -#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L -#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L -#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL -#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL -#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L -#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L -#define CKM_TLS_PRF_GENERAL 0x80000373L +#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001UL +#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002UL +#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003UL +#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004UL +#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005UL +#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006UL +#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007UL +#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008UL +#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009UL +#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aUL +#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bUL +#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371UL +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372UL +#define CKM_TLS_PRF_GENERAL 0x80000373UL /* define used to pass in the database key for DSA private keys */ -#define CKA_NETSCAPE_DB 0xD5A0DB00L -#define CKA_NETSCAPE_TRUST 0x80000001L +#define CKA_NETSCAPE_DB 0xD5A0DB00UL +#define CKA_NETSCAPE_TRUST 0x80000001UL /* undo packing */ //#include "pkcs11u.h" // TODO: msc specific? diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 2ad268c..45937cd 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -65,6 +65,7 @@ static struct { CK_BBOOL active; CK_MECHANISM mechanism; CK_ULONG key; + CK_ULONG key_len; CK_BYTE algo; } sign_info; @@ -913,7 +914,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( // TODO: do it properly here, just a test now //find_obj.objects = session.slot->token->objects + 3; - memmove(find_obj.objects, find_obj.objects + 14, sizeof(piv_obj_id_t) * (find_obj.num - 14)); + memmove(find_obj.objects, find_obj.objects + 13, sizeof(piv_obj_id_t) * (find_obj.num - 13)); find_obj.num = 1; DOUT; @@ -1165,6 +1166,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( ) { DIN; + CK_KEY_TYPE type = 0; // TODO: replace these with sign_info's fields? + CK_ULONG key_len = 0; + CK_BYTE buf[1024]; + CK_ATTRIBUTE template[] = { + {CKA_KEY_TYPE, &type, sizeof(type)}, + {CKA_MODULUS_BITS, &key_len, sizeof(key_len)}, + {CKA_EC_POINT, buf, sizeof(buf)} + }; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -1186,23 +1195,61 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( // Check if mechanism is supported if (check_sign_mechanism(&session, pMechanism) != CKR_OK) { DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); - return CKR_MECHANISM_INVALID; + return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that } memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); // Get key algorithm - /*if (get_key_algo(hKey, &sign_info.algo) != CKR_OK) { - DBG(("Unable to retrieve type for key %lu", hKey)); - return CKR_FUNCTION_FAILED; - }*/ // TODO: use get attribute instead? - sign_info.algo = YKPIV_ALGO_RSA2048; // TODO: fix + if (get_attribute(&session, hKey, template) != CKR_OK) { + DBG(("Unable to get key type")); + return CKR_KEY_HANDLE_INVALID; + } + DBG(("Key algorithm is %lu\n", type)); + + // Get key length and algorithm type + if (type == CKK_RSA) { + // RSA key + if (get_attribute(&session, hKey, template + 1) != CKR_OK) { + DBG(("Unable to get key length")); + return CKR_KEY_HANDLE_INVALID; + } + + sign_info.key_len = key_len; + + if (key_len == 1024) + sign_info.algo = YKPIV_ALGO_RSA1024; + else + sign_info.algo = YKPIV_ALGO_RSA2048; + + } + else { + // ECDSA key + if (get_attribute(&session, hKey, template + 2) != CKR_OK) { + DBG(("Unable to get key length")); + return CKR_KEY_HANDLE_INVALID; + } + + // The buffer contains an uncompressed point of the form 04, x, y + // TODO: is this a fine representation for an EC public key? + sign_info.key_len = ((template[2].ulValueLen - 1) / 2) * 8; + + if (sign_info.key_len == 256) + sign_info.algo = YKPIV_ALGO_ECCP256; + /*else + sign_info.algo = ;*/ + } + + DBG(("Key length is %lu bit", sign_info.key_len)); + //sign_info.key_len /= 8; + sign_info.key = piv_2_ykpiv(hKey); if (sign_info.key == 0) { DBG(("Incorrect key %lu", hKey)); return CKR_KEY_HANDLE_INVALID; } + DBG(("Algorithm is %d", sign_info.algo)); // Make sure that both mechanism and key have the same algorithm if ((is_RSA_mechanism(pMechanism->mechanism) && sign_info.algo == YKPIV_ALGO_ECCP256) || (!is_RSA_mechanism(pMechanism->mechanism) && (sign_info.algo != YKPIV_ALGO_ECCP256))) { @@ -1248,7 +1295,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( //dump_hex(buf, 256, stderr, CK_TRUE); //*pulSignatureLen = 256; DBG(("Using key %lx", sign_info.key)); // TODO: test what happens if there is no key on the card - if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, YKPIV_ALGO_RSA2048, sign_info.key)) != YKPIV_OK) { + if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, sign_info.algo, sign_info.key)) != YKPIV_OK) { DBG(("Sign error, %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } From 706ff894f254f5ef309451e75666fd118b26c950 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 3 Aug 2015 13:31:11 +0200 Subject: [PATCH 043/134] Added object matching. --- ykcs11/obj_types.h | 4 ++- ykcs11/objects.c | 44 +++++++++++++++++++++++++++- ykcs11/objects.h | 8 +++-- ykcs11/ykcs11.c | 73 ++++++++++++++++++++++++++++++++++------------ 4 files changed, 105 insertions(+), 24 deletions(-) diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 1f0913f..38bf018 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -90,6 +90,8 @@ typedef enum { } piv_obj_id_t; +#define OBJECT_INVALID (PIV_PUBK_OBJ_LAST + 1) + typedef CK_RV (*get_attr_f)(CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR); typedef struct { @@ -120,7 +122,7 @@ typedef struct { CK_BBOOL copyable; // TODO: Optional, not used so far (default TRUE) CK_BBOOL destroyable; // TODO: Optional, not used so far (default TRUE) get_attr_f get_attribute; - CK_ULONG sub_id; // Sub-object id + CK_BYTE sub_id; // Sub-object id } piv_obj_t; #endif diff --git a/ykcs11/objects.c b/ykcs11/objects.c index c21e48b..5f5630b 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -612,7 +612,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_ID: fprintf(stderr, "ID\n"); - len = sizeof(CK_ULONG); + len = sizeof(CK_BYTE); ul_tmp = piv_objects[obj].sub_id; data = (CK_BYTE_PTR) &ul_tmp; break; @@ -922,6 +922,48 @@ CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR return CKR_OBJECT_HANDLE_INVALID; } +CK_BBOOL attribute_match(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribute) { + + CK_ATTRIBUTE to_match; + CK_BYTE_PTR data; + + // Get the size first + to_match.type = attribute->type; + to_match.pValue = NULL; + to_match.ulValueLen = 0; + + if (get_attribute(s, obj, &to_match) != CKR_OK) + return CK_FALSE; + + if (to_match.ulValueLen != attribute->ulValueLen) + return CK_FALSE; + + // Allocate space for the attribute + data = malloc(to_match.ulValueLen); + if (data == NULL) + return CK_FALSE; + + // Retrieve the attribute + to_match.pValue = data; + if (get_attribute(s, obj, &to_match) != CKR_OK) { + free(data); + data = NULL; + return CK_FALSE; + } + + // Compare the attributes + if (memcmp(attribute->pValue, to_match.pValue, to_match.ulValueLen) != 0) { + free(data); + data = NULL; + return CK_FALSE; + } + + free(data); + data = NULL; + + return CK_TRUE; +} + CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs) { CK_ULONG i, j; diff --git a/ykcs11/objects.h b/ykcs11/objects.h index df0a60f..801923d 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -7,8 +7,10 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id); -CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); -CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); -CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); +CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); +CK_BBOOL attribute_match(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribute); + +CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); +CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 45937cd..d994b8b 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -581,7 +581,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( } if (session.handle == CK_INVALID_HANDLE) { - DBG(("There is no existing session")); + DBG(("Trying to close a session, but there is no existing one")); return CKR_SESSION_CLOSED; } @@ -697,8 +697,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); - if (session.handle == CK_INVALID_HANDLE) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -814,8 +816,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -867,14 +871,19 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( { DIN; CK_ULONG i; + CK_ULONG j; + CK_ULONG total; + if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -885,6 +894,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( find_obj.idx = 0; find_obj.num = session.slot->token->n_objects; + // TODO: remove private objects if needed + find_obj.objects = malloc(sizeof(piv_obj_id_t) * find_obj.num); if (find_obj.objects == NULL) { DBG(("Unable to allocate memory for finding objects")); @@ -892,31 +903,46 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( } memcpy(find_obj.objects, session.slot->token->objects, sizeof(piv_obj_id_t) * find_obj.num); // TODO: add another 'num' field for then objects have to be excluded because of attribute matching; - find_obj.active = CK_TRUE; - if (ulCount == 0) { - DBG(("Find ALL the objects!")); + DBG(("Find ALL the objects! Got %lu", find_obj.num)); + find_obj.active = CK_TRUE; DOUT; return CKR_OK; } DBG(("Initialized search with %lu parameters", ulCount)); - if (pTemplate == NULL_PTR) { - find_obj.active = CK_FALSE; + if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD; - } + // Match parameters + total = find_obj.num; for (i = 0; i < ulCount; i++) { DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); - // TODO: remove objects that don't match + + for (j = 0; j < find_obj.num; j++) { + if (find_obj.objects[j] == OBJECT_INVALID) + continue; // Object already discarded, keep going + + if (attribute_match(&session, find_obj.objects[j], pTemplate + i) == CK_FALSE) { + DBG(("Removing object %u from the list", find_obj.objects[j])); + find_obj.objects[j] = OBJECT_INVALID; // Object not matching, mark it + total--; + } + else + DBG(("Keeping object %u in the list", find_obj.objects[j])); + } } + DBG(("%lu object(s) left after attribute matching", total)); + // TODO: do it properly here, just a test now //find_obj.objects = session.slot->token->objects + 3; - memmove(find_obj.objects, find_obj.objects + 13, sizeof(piv_obj_id_t) * (find_obj.num - 13)); - find_obj.num = 1; + /*memmove(find_obj.objects, find_obj.objects + 12, sizeof(piv_obj_id_t) * (find_obj.num - 12)); + find_obj.num = 1;*/ + find_obj.active = CK_TRUE; + DOUT; return CKR_OK; } @@ -935,8 +961,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -951,7 +979,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( DBG(("Can return %lu object(s)", ulMaxObjectCount)); - // Return the next object + // Return the next object, if any + while(find_obj.idx < find_obj.num && + find_obj.objects[find_obj.idx] == OBJECT_INVALID) + find_obj.idx++; + if (find_obj.idx == find_obj.num) { *pulObjectCount = 0; DOUT; @@ -977,8 +1009,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -1180,8 +1214,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.handle != YKCS11_SESSION_ID) + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); return CKR_SESSION_CLOSED; + } if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; @@ -1241,8 +1277,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( } DBG(("Key length is %lu bit", sign_info.key_len)); - //sign_info.key_len /= 8; - + sign_info.key = piv_2_ykpiv(hKey); if (sign_info.key == 0) { DBG(("Incorrect key %lu", hKey)); From 67ed63bc28170da469b096a760899bf4efd0a726 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 3 Aug 2015 15:13:49 +0200 Subject: [PATCH 044/134] Hiding private objects if user is not logged in. --- ykcs11/objects.c | 21 +++++++++++++--- ykcs11/objects.h | 1 + ykcs11/ykcs11.c | 65 ++++++++++++++++++++++++++++++------------------ 3 files changed, 60 insertions(+), 27 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 5f5630b..b09ff70 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -59,10 +59,10 @@ static piv_obj_t piv_objects[] = { {PIV_CERT_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_coa, 3}, {PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, get_coa, 4}, - {PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, // 9a + {PIV_PVTK_OBJ_PIV_AUTH, 1, 1, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, // 9a {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Private key for Card Authentication", 0, 0, get_proa, 1}, // 9e - {PIV_PVTK_OBJ_DS, 1, 0, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, // 9c - {PIV_PVTK_OBJ_KM, 1, 0, 0, "Prrivate key for Key Management", 0, 0, get_proa, 3}, // 9d + {PIV_PVTK_OBJ_DS, 1, 1, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, // 9c + {PIV_PVTK_OBJ_KM, 1, 1, 0, "Private key for Key Management", 0, 0, get_proa, 3}, // 9d {PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4}, {PIV_PUBK_OBJ_PIV_AUTH, 1, 0, 0, "Public key for PIV Authentication", 0, 0, get_puoa, 0}, @@ -964,6 +964,21 @@ CK_BBOOL attribute_match(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE return CK_TRUE; } +CK_BBOOL is_private_object(ykcs11_session_t *s, CK_OBJECT_HANDLE obj) { + + CK_ATTRIBUTE attr; + CK_BYTE private; + + attr.type = CKA_PRIVATE; + attr.pValue = &private; + attr.ulValueLen = sizeof(private); + + if (get_attribute(s, obj, &attr) != CKR_OK) + return CK_FALSE; + + return private == CK_FALSE ? CK_FALSE : CK_TRUE; +} + CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs) { CK_ULONG i, j; diff --git a/ykcs11/objects.h b/ykcs11/objects.h index 801923d..e87f1df 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -9,6 +9,7 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id); CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); CK_BBOOL attribute_match(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribute); +CK_BBOOL is_private_object(ykcs11_session_t *s, CK_OBJECT_HANDLE obj); CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index d994b8b..df38bbf 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -482,7 +482,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( session.slot = slots + slotID; //session.slot->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO - // Store session flags + // Store session state + session.info.state = 0; + if ((flags & CKF_RW_SESSION)) { // R/W Session session.info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session @@ -721,7 +723,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_USER_ALREADY_LOGGED_IN; tries = 0; - if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { + if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { // TODO: call this from vendors.c DBG(("You loose! %lu", tries)); return CKR_PIN_INCORRECT; } @@ -735,7 +737,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( DBG(("You win! %lu", tries)); - // TODO: update session objects now that we're logged in ? + if ((session.info.flags & CKF_RW_SESSION) == 0) + session.info.state = CKS_RO_USER_FUNCTIONS; + else + session.info.state = CKS_RW_USER_FUNCTIONS; DOUT; return CKR_OK; @@ -873,6 +878,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( CK_ULONG i; CK_ULONG j; CK_ULONG total; + CK_BBOOL private; if (piv_state == NULL) { @@ -891,46 +897,57 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( if (find_obj.active == CK_TRUE) return CKR_OPERATION_ACTIVE; + if (ulCount != 0 && pTemplate == NULL_PTR) + return CKR_ARGUMENTS_BAD; + find_obj.idx = 0; find_obj.num = session.slot->token->n_objects; - // TODO: remove private objects if needed + // Check if we should remove private objects + if (session.info.state == CKS_RO_PUBLIC_SESSION || + session.info.state == CKS_RW_PUBLIC_SESSION) { + DBG(("Removing private objects because state is %lu", session.info.state)); + private = CK_FALSE; + } + else { + DBG(("Keeping private objects")); + private = CK_TRUE; + } find_obj.objects = malloc(sizeof(piv_obj_id_t) * find_obj.num); if (find_obj.objects == NULL) { DBG(("Unable to allocate memory for finding objects")); return CKR_HOST_MEMORY; } - memcpy(find_obj.objects, session.slot->token->objects, sizeof(piv_obj_id_t) * find_obj.num); // TODO: add another 'num' field for then objects have to be excluded because of attribute matching; - - if (ulCount == 0) { - DBG(("Find ALL the objects! Got %lu", find_obj.num)); - find_obj.active = CK_TRUE; - DOUT; - return CKR_OK; - } + memcpy(find_obj.objects, session.slot->token->objects, sizeof(piv_obj_id_t) * find_obj.num); DBG(("Initialized search with %lu parameters", ulCount)); - if (pTemplate == NULL_PTR) - return CKR_ARGUMENTS_BAD; - // Match parameters total = find_obj.num; - for (i = 0; i < ulCount; i++) { - DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); + for (i = 0; i < find_obj.num; i++) { - for (j = 0; j < find_obj.num; j++) { - if (find_obj.objects[j] == OBJECT_INVALID) - continue; // Object already discarded, keep going + if (find_obj.objects[i] == OBJECT_INVALID) + continue; // Object already discarded, keep going - if (attribute_match(&session, find_obj.objects[j], pTemplate + i) == CK_FALSE) { - DBG(("Removing object %u from the list", find_obj.objects[j])); - find_obj.objects[j] = OBJECT_INVALID; // Object not matching, mark it + // Strip away private objects if needed + if (private == CK_FALSE) + if (is_private_object(&session, find_obj.objects[i]) == CK_TRUE) { + DBG(("Stripping away private object %u", find_obj.objects[i])); + find_obj.objects[i] = OBJECT_INVALID; + continue; + } + + for (j = 0; j < ulCount; j++) { + DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", j, pTemplate[j].type, *((CK_ULONG_PTR)pTemplate[j].pValue), pTemplate[j].ulValueLen)); + + if (attribute_match(&session, find_obj.objects[i], pTemplate + j) == CK_FALSE) { + DBG(("Removing object %u from the list", find_obj.objects[i])); + find_obj.objects[i] = OBJECT_INVALID; // Object not matching, mark it total--; } else - DBG(("Keeping object %u in the list", find_obj.objects[j])); + DBG(("Keeping object %u in the list", find_obj.objects[i])); } } From 7ce5ea4dc2080a1a76f1a92884608c1ebcff0e84 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 3 Aug 2015 16:21:09 +0200 Subject: [PATCH 045/134] Added sign_data2 to libykpiv to disable padding. --- lib/ykpiv.c | 26 ++++++++++++++++++++------ lib/ykpiv.h | 6 +++++- lib/ykpiv.map | 1 + ykcs11/mechanisms.c | 8 ++++++-- ykcs11/mechanisms.h | 4 ++-- ykcs11/openssl_utils.c | 2 +- ykcs11/ykcs11.c | 30 +++++++++++++----------------- 7 files changed, 48 insertions(+), 29 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index e8182ad..8cd9a70 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -520,7 +520,7 @@ ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, static ykpiv_rc _general_authenticate(ykpiv_state *state, const unsigned char *raw_in, size_t in_len, unsigned char *out, size_t *out_len, - unsigned char algorithm, unsigned char key, bool decipher) { + unsigned char algorithm, unsigned char key, bool decipher, bool padding) { unsigned char indata[1024]; unsigned char *dataptr = indata; unsigned char data[1024]; @@ -538,14 +538,18 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, pad_len = 128; case YKPIV_ALGO_RSA2048: if(pad_len == 0) { - pad_len = 256; + pad_len = 256; } if(!decipher) { if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) { return YKPIV_SIZE_ERROR; } - RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len); - in_len = pad_len; + if (padding) { + RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len); + in_len = pad_len; + } + else if (in_len != pad_len) + return YKPIV_SIZE_ERROR; } else { if(in_len != pad_len) { return YKPIV_SIZE_ERROR; @@ -629,7 +633,17 @@ ykpiv_rc ykpiv_sign_data(ykpiv_state *state, unsigned char algorithm, unsigned char key) { return _general_authenticate(state, raw_in, in_len, sign_out, out_len, - algorithm, key, false); + algorithm, key, false, true); +} + +ykpiv_rc ykpiv_sign_data2(ykpiv_state *state, + const unsigned char *raw_in, size_t in_len, + unsigned char *sign_out, size_t *out_len, + unsigned char algorithm, unsigned char key, + int padding) { + + return _general_authenticate(state, raw_in, in_len, sign_out, out_len, + algorithm, key, false, padding); } @@ -637,7 +651,7 @@ ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *in, size_t in_len, unsigned char *out, size_t *out_len, unsigned char algorithm, unsigned char key) { return _general_authenticate(state, in, in_len, out, out_len, - algorithm, key, true); + algorithm, key, true, true); } ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len) { diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 0ccbfbb..baa7d98 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -64,7 +64,8 @@ extern "C" ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); ykpiv_rc ykpiv_done(ykpiv_state *state); ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); - ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char **readers, unsigned long *len); + ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, + unsigned char **readers, unsigned long *len); // Allow to return a reader string ykpiv_rc ykpiv_disconnect(ykpiv_state *state); ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, const unsigned char *in_data, long in_len, @@ -76,6 +77,9 @@ extern "C" ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in, size_t in_len, unsigned char *sign_out, size_t *out_len, unsigned char algorithm, unsigned char key); + ykpiv_rc ykpiv_sign_data2(ykpiv_state *state, const unsigned char *sign_in, + size_t in_len, unsigned char *sign_out, size_t *out_len, + unsigned char algorithm, unsigned char key, int padding); // Allow not to add padding ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *enc_in, size_t in_len, unsigned char *enc_out, size_t *out_len, unsigned char algorithm, unsigned char key); diff --git a/lib/ykpiv.map b/lib/ykpiv.map index 09c7847..a6ddb40 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -53,4 +53,5 @@ YKPIV_0.2.0 global: ykpiv_decipher_data; ykpiv_connect2; + ykpiv_sign_data2; } YKPIV_0.1.0; diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 7eb0c69..0d3e30e 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -85,14 +85,18 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) { return CK_FALSE; } -CK_RV do_sign_padding(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, - CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { +CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, + CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { switch (m->mechanism) { case CKM_RSA_PKCS: return do_pkcs_t1(in, in_len, out, out_len, key_len); case CKM_RSA_PKCS_PSS: + return CKR_FUNCTION_FAILED; + case CKM_RSA_X_509: + return CKR_OK; + case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index 8a38121..cb4130d 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -7,7 +7,7 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); -CK_RV do_sign_padding(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, - CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); +CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, + CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); #endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index cb98f28..afdfcf1 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -130,7 +130,7 @@ CK_RV free_key(EVP_PKEY *key) { CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len); - // TODO: rand must be seeded first + // TODO: rand must be seeded first (should be automatic) if (out_len < key_len) CKR_BUFFER_TOO_SMALL; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index df38bbf..781bdaf 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -814,7 +814,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( ) { DIN; - CK_RV rv; + CK_ULONG i; + CK_RV rv, rv_final; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -835,24 +836,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( if (find_obj.active != CK_TRUE) return CKR_OPERATION_NOT_INITIALIZED; - if (pTemplate[0].pValue == NULL_PTR) { - DBG(("Just get size")); - rv = get_attribute(&session, hObject, pTemplate); + rv_final = CKR_OK; + for (i = 0; i < ulCount; i++) { + rv = get_attribute(&session, hObject, pTemplate + i); + + // TODO: this function has some complex cases for return vlaue. Make sure to check them. if (rv != CKR_OK) { - DBG(("Unable to get size for attribute %lu of object %lu", pTemplate->type, hObject)); + DBG(("Unable to get attribute %lu of object %lu", (pTemplate + i)->type, hObject)); + rv_final = rv; } - DOUT; - return CKR_OK; } - DBG(("Trying to get %lu attribute(s) for object %lu", ulCount, hObject)); - DBG(("Type: 0x%lx Value: %lu Len: %lu", pTemplate[0].type, *((CK_ULONG_PTR)pTemplate[0].pValue), pTemplate[0].ulValueLen)); - // TODO: here for i in ulCount (get all the attributes) - - return get_attribute(&session, hObject, pTemplate); DOUT; - return CKR_OK; + return rv_final; } CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)( @@ -1339,10 +1336,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( DBG(("Sending %lu bytes to sign", ulDataLen)); dump_hex(pData, ulDataLen, stderr, CK_TRUE); -/* if (do_sign_padding(&sign_info.mechanism, pData, ulDataLen, buf, buf_len, 2048 / 8) != CKR_OK) { + if (apply_sign_mechanism(&sign_info.mechanism, pData, ulDataLen, buf, buf_len, 2048 / 8) != CKR_OK) { DBG(("Unable to apply padding scheme")); return CKR_FUNCTION_FAILED; - }*/ + } memcpy(buf, pData, ulDataLen); // ykpiv does padding already //dump_hex(buf, 256, stderr, CK_TRUE); //*pulSignatureLen = 256; @@ -1353,8 +1350,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( } DBG(("Got %lu bytes back", *pulSignatureLen)); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); -/* memcpy(pSignature, sig_buf, sig_len_out); - *pulSignatureLen = sig_len_out;*/ + DOUT; return CKR_OK; } From d312d7a1e10def2ddb3b7eec159c15ccdb42f0e9 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 4 Aug 2015 19:19:04 +0200 Subject: [PATCH 046/134] Added more signature infrestructure. --- ykcs11/Makefile.am | 2 +- ykcs11/mechanisms.c | 109 ++++++++++++++++++++++++++++++++++++++--- ykcs11/mechanisms.h | 8 +-- ykcs11/openssl_types.h | 22 +++++++++ ykcs11/openssl_utils.c | 74 ++++++++++++++++++++++++++++ ykcs11/openssl_utils.h | 14 ++++-- ykcs11/ykcs11.c | 78 +++++++++++++++-------------- ykcs11/ykcs11.h | 40 +++++++++++++++ 8 files changed, 293 insertions(+), 54 deletions(-) create mode 100644 ykcs11/openssl_types.h diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index f94ef82..c635276 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -40,7 +40,7 @@ libykcs11_la_SOURCES += token_vendors.c token_vendor.h libykcs11_la_SOURCES += mechanisms.c mechanisms.h libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h libykcs11_la_SOURCES += utils.c utils.h -libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h +libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h openssl_types.h libykcs11_la_SOURCES += objects.c objects.h obj_types.h #internal.h diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 0d3e30e..ec23cf9 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -53,8 +53,6 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) { case CKM_RSA_PKCS: case CKM_RSA_9796: case CKM_RSA_X_509: - case CKM_MD2_RSA_PKCS: - case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: // case CKM_SHA224_RSA_PKCS: case CKM_SHA256_RSA_PKCS: @@ -85,15 +83,60 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) { return CK_FALSE; } -CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, - CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { - switch (m->mechanism) { +CK_RV apply_sign_mechanism_init(op_info_t *op_info) { + + if (op_info->type != YKCS11_SIGN) + return CKR_FUNCTION_FAILED; + + switch (op_info->mechanism.mechanism) { + case CKM_RSA_PKCS: + // No hash required for this mechanism + return CKR_OK; + + case CKM_RSA_PKCS_PSS: // TODO + return CKR_FUNCTION_FAILED; + + case CKM_RSA_X_509: + // No hash required for this mechanism + return CKR_OK; + + case CKM_SHA1_RSA_PKCS: + case CKM_ECDSA_SHA1: + return do_md_init(YKCS11_SHA1, &op_info->op.sign.md_ctx); + + case CKM_SHA256_RSA_PKCS: + return do_md_init(YKCS11_SHA256, &op_info->op.sign.md_ctx); + + case CKM_SHA384_RSA_PKCS: + return do_md_init(YKCS11_SHA384, &op_info->op.sign.md_ctx); + + case CKM_SHA512_RSA_PKCS: + return do_md_init(YKCS11_SHA512, &op_info->op.sign.md_ctx); + + case CKM_ECDSA: + return CKR_FUNCTION_FAILED; // TODO: but no hash needed + + default: + CKR_FUNCTION_FAILED; + } + + // Never reached + return CKR_FUNCTION_FAILED; +} + +CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len) { + CK_RV rv; + + if (op_info->type != YKCS11_SIGN) + return CKR_FUNCTION_FAILED; + + switch (op_info->mechanism.mechanism) { case CKM_RSA_PKCS: - return do_pkcs_t1(in, in_len, out, out_len, key_len); + return CKR_OK; case CKM_RSA_PKCS_PSS: return CKR_FUNCTION_FAILED; - + case CKM_RSA_X_509: return CKR_OK; @@ -101,7 +144,57 @@ CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: + case CKM_ECDSA_SHA1: + rv = do_md_update(op_info->op.sign.md_ctx, in, in_len); + if (rv != CKR_OK) + return CKR_FUNCTION_FAILED; + + return CKR_OK; + + case CKM_ECDSA: + return CKR_FUNCTION_FAILED; + + default: + return CKR_FUNCTION_FAILED; + } + +} + + +CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { + + CK_RV rv; + + if (op_info->type != YKCS11_SIGN) + return CKR_FUNCTION_FAILED; + + switch (op_info->mechanism.mechanism) { + case CKM_RSA_PKCS_PSS: + return CKR_FUNCTION_FAILED; + + case CKM_RSA_X_509: + return CKR_OK; + + case CKM_SHA1_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: + case CKM_ECDSA_SHA1: + // Finalize the hash if needed and add digest info + rv = do_md_finalize(op_info->op.sign.md_ctx, CK_TRUE, op_info->buf, &op_info->buf_len); + if (rv != CKR_OK) + return CKR_FUNCTION_FAILED; + fprintf(stderr, "The hashed value is %lu long and looks like\n", op_info->buf_len); + dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); + + case CKM_RSA_PKCS: + // And compute padding for all pkcs1 variants + return do_pkcs_t1(op_info->buf, op_info->buf_len, op_info->buf, sizeof(op_info->buf), op_info->op.sign.key_len); + + case CKM_ECDSA: + return CKR_FUNCTION_FAILED; + + default: return CKR_FUNCTION_FAILED; } - } diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index cb4130d..846ff50 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -3,11 +3,11 @@ #include "ykcs11.h" - -CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); +CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); -CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, - CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); +CK_RV apply_sign_mechanism_init(op_info_t *op_info); +CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len); +CK_RV apply_sign_mechanism_finalize(op_info_t *op_info); #endif diff --git a/ykcs11/openssl_types.h b/ykcs11/openssl_types.h new file mode 100644 index 0000000..b56f934 --- /dev/null +++ b/ykcs11/openssl_types.h @@ -0,0 +1,22 @@ +#ifndef OPENSSL_TYPES_H +#define OPENSSL_TYPES_H + +#include +#include +#include +#include + +typedef enum { + YKCS11_NO_HASH, + YKCS11_SHA1, + //YKCS11_SHA224, + YKCS11_SHA256, + YKCS11_SHA384, + YKCS11_SHA512, + //YKCS11_RIPEMD128_RSA_PKCS, + //YKCS11_RIPEMD160 +} hash_t; + +typedef EVP_MD_CTX ykcs11_md_ctx_t; + +#endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index afdfcf1..cd503e7 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -139,3 +139,77 @@ CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_ return CKR_OK; } + +CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx) { + + const EVP_MD *md; + + switch (hash) { + case YKCS11_NO_HASH: + return CKR_FUNCTION_FAILED; + + case YKCS11_SHA1: + md = EVP_sha1(); + break; + + //case YKCS11_SHA224: + + case YKCS11_SHA256: + md = EVP_sha256(); + break; + + case YKCS11_SHA384: + md = EVP_sha384(); + break; + + case YKCS11_SHA512: + md = EVP_sha512(); + break; + + //case YKCS11_RIPEMD128_RSA_PKCS_HASH: + //case YKCS11_RIPEMD160_HASH: + + default: + return CKR_FUNCTION_FAILED; + } + + *ctx = EVP_MD_CTX_create(); + + // The OpenSSL function above never fail + if (EVP_DigestInit_ex(*ctx, md, NULL) == 0) { + EVP_MD_CTX_destroy(*ctx); + return CKR_FUNCTION_FAILED; + } + + return CKR_OK; +} + +CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len) { + + return EVP_DigestUpdate(ctx, in, in_len) == 1 ? CKR_OK : CKR_FUNCTION_FAILED; + +} + +CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BBOOL di, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { + + int rv; + bool rv2; + unsigned int len; + + // Finalize digest and store result + rv = EVP_DigestFinal_ex(ctx, out, (unsigned int *)out_len); + // Check wheter digest info is required + if (di == CK_TRUE) + rv2 = prepare_rsa_signature(out, *out_len, out, &len, EVP_MD_CTX_type(ctx)); + + // Destroy the md context + EVP_MD_CTX_destroy(ctx); + + // Error if either of the previous calls failed + if (rv != 1 || !rv2) + return CKR_FUNCTION_FAILED; + + *out_len = len; + + return CKR_OK; +} diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 00bff66..a82b340 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -1,10 +1,12 @@ #ifndef OPENSSL_UTIL_H #define OPENSSL_UTIL_H -#include -#include -#include -#include +/* #include */ +/* #include */ +/* #include */ +/* #include */ + +#include "openssl_types.h" #include "pkcs11t.h" CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); @@ -18,4 +20,8 @@ CK_RV free_key(EVP_PKEY *key); CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); +CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx); +CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len); +CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BBOOL di, CK_BYTE_PTR out, CK_ULONG_PTR out_len); + #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 781bdaf..51dbc12 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -7,6 +7,7 @@ #include "obj_types.h" #include "utils.h" #include "mechanisms.h" +#include "openssl_types.h" #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ @@ -58,16 +59,10 @@ static struct { piv_obj_id_t *objects; } find_obj; -/*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)? And include inside a session struct? - static CK_ULONG n_token_objects = 0;*/ +op_info_t op_info; -static struct { - CK_BBOOL active; - CK_MECHANISM mechanism; - CK_ULONG key; - CK_ULONG key_len; - CK_BYTE algo; -} sign_info; +/*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tidy this up, also build at runtime (during open session)? And include inside a session struct? + static CK_ULONG n_token_objects = 0;*/ extern CK_FUNCTION_LIST function_list; // TODO: check all return values @@ -87,7 +82,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_CRYPTOKI_ALREADY_INITIALIZED; if (ykpiv_init(&piv_state, YKCS11_DBG) != YKPIV_OK) { - DBG(("Unable to initialize YubiKey")); + DBG(("Unable to initialize libykpiv")); return CKR_FUNCTION_FAILED; // TODO: better error? } @@ -1247,7 +1242,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that } - memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); + memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); // Get key algorithm if (get_attribute(&session, hKey, template) != CKR_OK) { @@ -1265,12 +1260,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_KEY_HANDLE_INVALID; } - sign_info.key_len = key_len; + op_info.op.sign.key_len = key_len; if (key_len == 1024) - sign_info.algo = YKPIV_ALGO_RSA1024; + op_info.op.sign.algo = YKPIV_ALGO_RSA1024; else - sign_info.algo = YKPIV_ALGO_RSA2048; + op_info.op.sign.algo = YKPIV_ALGO_RSA2048; } else { @@ -1282,33 +1277,38 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( // The buffer contains an uncompressed point of the form 04, x, y // TODO: is this a fine representation for an EC public key? - sign_info.key_len = ((template[2].ulValueLen - 1) / 2) * 8; + op_info.op.sign.key_len = ((template[2].ulValueLen - 1) / 2) * 8; - if (sign_info.key_len == 256) - sign_info.algo = YKPIV_ALGO_ECCP256; + if (op_info.op.sign.key_len == 256) + op_info.op.sign.algo = YKPIV_ALGO_ECCP256; /*else - sign_info.algo = ;*/ + op_info.algo = ;*/ } - DBG(("Key length is %lu bit", sign_info.key_len)); + //op_info.hash = get_mechanism_hash(pMechanism->mechanism); - sign_info.key = piv_2_ykpiv(hKey); - if (sign_info.key == 0) { + DBG(("Key length is %lu bit", op_info.op.sign.key_len)); + + op_info.op.sign.key = piv_2_ykpiv(hKey); + if (op_info.op.sign.key == 0) { DBG(("Incorrect key %lu", hKey)); return CKR_KEY_HANDLE_INVALID; } - DBG(("Algorithm is %d", sign_info.algo)); + DBG(("Algorithm is %d", op_info.op.sign.algo)); // Make sure that both mechanism and key have the same algorithm - if ((is_RSA_mechanism(pMechanism->mechanism) && sign_info.algo == YKPIV_ALGO_ECCP256) || - (!is_RSA_mechanism(pMechanism->mechanism) && (sign_info.algo != YKPIV_ALGO_ECCP256))) { + if ((is_RSA_mechanism(pMechanism->mechanism) && op_info.op.sign.algo == YKPIV_ALGO_ECCP256) || + (!is_RSA_mechanism(pMechanism->mechanism) && (op_info.op.sign.algo != YKPIV_ALGO_ECCP256))) { DBG(("Key and mechanism algorithm do not match")); return CKR_ARGUMENTS_BAD; } - // TODO: also allocate some space for the signature in case of multipart + op_info.type = YKCS11_SIGN; - sign_info.active = CK_TRUE; + if (apply_sign_mechanism_init(&op_info) != CKR_OK) { + DBG(("Unable to initialize signing operation")); + return CKR_FUNCTION_FAILED; + } DOUT; return CKR_OK; @@ -1323,28 +1323,32 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( ) { DIN; - CK_BYTE buf[YKCS11_MAX_SIG_BUF_LEN]; - CK_ULONG buf_len = sizeof(buf); - if (sign_info.active == CK_FALSE) + if (op_info.type == YKCS11_NOOP) return CKR_OPERATION_NOT_INITIALIZED; - // TODO: check conditions - ykpiv_rc r; - CK_CHAR algo; + if (op_info.type != YKCS11_SIGN) + return CKR_OPERATION_ACTIVE; + + // TODO: check other conditions + ykpiv_rc r; // TODO: delete this DBG(("Sending %lu bytes to sign", ulDataLen)); dump_hex(pData, ulDataLen, stderr, CK_TRUE); - if (apply_sign_mechanism(&sign_info.mechanism, pData, ulDataLen, buf, buf_len, 2048 / 8) != CKR_OK) { - DBG(("Unable to apply padding scheme")); + if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { + DBG(("Unable to perform signing operation step")); + return CKR_FUNCTION_FAILED; + } + + if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) { + DBG(("Unable to finalize signing operation")); return CKR_FUNCTION_FAILED; } - memcpy(buf, pData, ulDataLen); // ykpiv does padding already //dump_hex(buf, 256, stderr, CK_TRUE); //*pulSignatureLen = 256; - DBG(("Using key %lx", sign_info.key)); // TODO: test what happens if there is no key on the card - if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, sign_info.algo, sign_info.key)) != YKPIV_OK) { + DBG(("Using key %lx", op_info.op.sign.key)); // TODO: test what happens if there is no key on the card + if ((r = ykpiv_sign_data(piv_state, op_info.buf, ulDataLen, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key)) != YKPIV_OK) { DBG(("Sign error, %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index cfa22da..fc20bb0 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -3,8 +3,11 @@ #include "pkcs11t.h" #include "obj_types.h" +#include "openssl_types.h" #include "vendors.h" +#define YKCS11_OP_BUFSIZE 4096 + typedef struct { vendor_id_t vid; CK_TOKEN_INFO info; @@ -25,4 +28,41 @@ typedef struct { ykcs11_slot_t *slot; } ykcs11_session_t; + +typedef enum { + YKCS11_NOOP, + YKCS11_SIGN, + YKCS11_HASH, + YKCS11_DECRYPT +} ykcs11_op_type_t; + +typedef struct { + ykcs11_md_ctx_t *md_ctx; + CK_BYTE algo; + CK_ULONG key; + CK_ULONG key_len; +} sign_info_t; + +typedef struct { + CK_BYTE todo; +} hash_info_t; + +typedef struct { + CK_BYTE todo; +} decrypt_info_t; + +typedef union { + sign_info_t sign; + hash_info_t hash; + decrypt_info_t decrypt; +} op_t; + +typedef struct { + ykcs11_op_type_t type; + CK_MECHANISM mechanism; + op_t op; + CK_BYTE buf[YKCS11_OP_BUFSIZE]; + CK_ULONG buf_len; +} op_info_t; + #endif From e89de35efc108d2d2d019bd280e905b1e837e740 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 5 Aug 2015 15:40:24 +0200 Subject: [PATCH 047/134] Added PSS (first stab). --- ykcs11/mechanisms.c | 87 +++++++++++++++++++++++++++++------ ykcs11/mechanisms.h | 1 + ykcs11/obj_types.h | 2 +- ykcs11/objects.c | 9 +++- ykcs11/openssl_types.h | 1 + ykcs11/openssl_utils.c | 101 +++++++++++++++++++++++++++++++++++------ ykcs11/openssl_utils.h | 9 +++- ykcs11/ykcs11.c | 36 ++++++++++++--- ykcs11/ykcs11.h | 9 ++-- ykcs11/yubico_token.c | 12 ++--- 10 files changed, 219 insertions(+), 48 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index ec23cf9..e41fa35 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -83,6 +83,25 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) { return CK_FALSE; } +CK_BBOOL is_PSS_mechanism(CK_MECHANISM_TYPE m) { + + switch (m) { + case CKM_RSA_PKCS_PSS: + case CKM_SHA1_RSA_PKCS_PSS: +// case CKM_SHA224_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + return CK_TRUE; + + default: + return CK_FALSE; + } + + // Not reached + return CK_FALSE; +} + CK_RV apply_sign_mechanism_init(op_info_t *op_info) { if (op_info->type != YKCS11_SIGN) @@ -93,31 +112,36 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) { // No hash required for this mechanism return CKR_OK; - case CKM_RSA_PKCS_PSS: // TODO - return CKR_FUNCTION_FAILED; + case CKM_RSA_PKCS_PSS: + // No hash required for this mechanism + return CKR_OK; case CKM_RSA_X_509: // No hash required for this mechanism return CKR_OK; case CKM_SHA1_RSA_PKCS: + case CKM_SHA1_RSA_PKCS_PSS: case CKM_ECDSA_SHA1: return do_md_init(YKCS11_SHA1, &op_info->op.sign.md_ctx); case CKM_SHA256_RSA_PKCS: + case CKM_SHA256_RSA_PKCS_PSS: return do_md_init(YKCS11_SHA256, &op_info->op.sign.md_ctx); case CKM_SHA384_RSA_PKCS: + case CKM_SHA384_RSA_PKCS_PSS: return do_md_init(YKCS11_SHA384, &op_info->op.sign.md_ctx); case CKM_SHA512_RSA_PKCS: + case CKM_SHA512_RSA_PKCS_PSS: return do_md_init(YKCS11_SHA512, &op_info->op.sign.md_ctx); case CKM_ECDSA: return CKR_FUNCTION_FAILED; // TODO: but no hash needed default: - CKR_FUNCTION_FAILED; + return CKR_FUNCTION_FAILED; } // Never reached @@ -132,9 +156,8 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i switch (op_info->mechanism.mechanism) { case CKM_RSA_PKCS: - return CKR_OK; - case CKM_RSA_PKCS_PSS: + // Mechanism not suitable for multipart signatures return CKR_FUNCTION_FAILED; case CKM_RSA_X_509: @@ -144,6 +167,10 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: case CKM_ECDSA_SHA1: rv = do_md_update(op_info->op.sign.md_ctx, in, in_len); if (rv != CKR_OK) @@ -160,17 +187,39 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i } - CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { - CK_RV rv; + CK_RV rv; + int nid = NID_undef; + RSA *rsa; + CK_ULONG len; if (op_info->type != YKCS11_SIGN) return CKR_FUNCTION_FAILED; switch (op_info->mechanism.mechanism) { + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + // Finalize the hash + rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + if (rv != CKR_OK) + return CKR_FUNCTION_FAILED; + case CKM_RSA_PKCS_PSS: - return CKR_FUNCTION_FAILED; + // Compute padding for all PSS variants + // TODO: digestinfo/paraminfo ? + + rv = do_encode_rsa_public_key(op_info->op.sign.key, op_info->op.sign.key_len, &rsa); + if (rv != CKR_OK) + return CKR_FUNCTION_FAILED; + + rv = do_pkcs_pss(rsa, op_info->buf, op_info->buf_len, nid, op_info->buf, &op_info->buf_len); + + // TODO: does rsa have to be free'd ? + + return rv; case CKM_RSA_X_509: return CKR_OK; @@ -179,18 +228,30 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: - case CKM_ECDSA_SHA1: - // Finalize the hash if needed and add digest info - rv = do_md_finalize(op_info->op.sign.md_ctx, CK_TRUE, op_info->buf, &op_info->buf_len); + // Finalize the hash add digest info + rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); if (rv != CKR_OK) return CKR_FUNCTION_FAILED; fprintf(stderr, "The hashed value is %lu long and looks like\n", op_info->buf_len); dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); case CKM_RSA_PKCS: - // And compute padding for all pkcs1 variants - return do_pkcs_t1(op_info->buf, op_info->buf_len, op_info->buf, sizeof(op_info->buf), op_info->op.sign.key_len); + // Add digest info if needed + if (nid != NID_undef) { + rv = do_pkcs_1_digest_info(op_info->buf, op_info->buf_len, nid, op_info->buf, &op_info->buf_len); + if (rv != CKR_OK) + return CKR_FUNCTION_FAILED; + fprintf(stderr, "After adding digestinfo is %lu long and looks like\n", op_info->buf_len); + dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); + } + + // Compute padding for all PKCS1 variants + len = op_info->buf_len; + op_info->buf_len = sizeof(op_info->buf); + return do_pkcs_1_t1(op_info->buf, len, op_info->buf, &op_info->buf_len, op_info->op.sign.key_len); + + case CKM_ECDSA_SHA1: // TODO: case CKM_ECDSA: return CKR_FUNCTION_FAILED; diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index 846ff50..b39a78e 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -5,6 +5,7 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); +CK_BBOOL is_PSS_mechanism(CK_MECHANISM_TYPE m); CK_RV apply_sign_mechanism_init(op_info_t *op_info); CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len); diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 38bf018..44876b0 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -110,7 +110,7 @@ typedef struct { // TODO: enough to use the public key for the parameters? } piv_pvtk_obj_t; typedef struct { - EVP_PKEY *data; + EVP_PKEY *data; // TODO: make custo type for this and X509 } piv_pubk_obj_t; typedef struct { diff --git a/ykcs11/objects.c b/ykcs11/objects.c index b09ff70..55d6045 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -653,7 +653,14 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { fprintf(stderr, "END DATE TODO\n"); // Default empty return CKR_FUNCTION_FAILED; - /*case CKA_MODULUS:*/ + case CKA_MODULUS: + fprintf(stderr, "MODULUS\n"); + len = sizeof(b_tmp); + if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + data = b_tmp; + break; + case CKA_EC_POINT: // We're trying to get the key length, get the ec point of the PUBLIC key // TODO: or just give an error and explicitly fetch the pubk len when needed diff --git a/ykcs11/openssl_types.h b/ykcs11/openssl_types.h index b56f934..eef3396 100644 --- a/ykcs11/openssl_types.h +++ b/ykcs11/openssl_types.h @@ -18,5 +18,6 @@ typedef enum { } hash_t; typedef EVP_MD_CTX ykcs11_md_ctx_t; +//typedef EVP_PKEY ykcs11_evp_pkey_t; #endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index cd503e7..2d69ce8 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -89,8 +89,10 @@ CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) { CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { RSA *rsa; + unsigned char *p; + EC_KEY *eck; - const EC_GROUP *ecg; // Alternatice solution is to get i2d_PUBKEY and manually offset + const EC_GROUP *ecg; // Alternative solution is to get i2d_PUBKEY and manually offset const EC_POINT *ecp; point_conversion_form_t pcf = POINT_CONVERSION_UNCOMPRESSED; @@ -99,7 +101,23 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { case EVP_PKEY_RSA2: rsa = EVP_PKEY_get1_RSA(key); - return CKR_FUNCTION_FAILED; // TODO; + + if (RSA_size(rsa) > *len) + return CKR_BUFFER_TOO_SMALL; + + p = data; + + if ((*len = i2d_RSAPublicKey(rsa, &p)) == 0) + return CKR_FUNCTION_FAILED; + + // TODO: this is the correct thing to do so that we strip out the exponent + // OTOH we also need a function to get the exponent out with CKA_PUBLIC_EXPONENT + /*BN_bn2bin(rsa->n, data); + *len = 256;*/ + + fprintf(stderr, "Public key is: \n"); + dump_hex(data, *len, stderr, CK_TRUE); + break; case EVP_PKEY_EC: @@ -119,6 +137,20 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { } +CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key) { + + const unsigned char *p = data; + + if (data == NULL) + return CKR_ARGUMENTS_BAD; + + if ((*key = d2i_RSAPublicKey(NULL, &p, len)) == NULL) + return CKR_FUNCTION_FAILED; + + return CKR_OK; + +} + CK_RV free_key(EVP_PKEY *key) { EVP_PKEY_free(key); @@ -127,16 +159,52 @@ CK_RV free_key(EVP_PKEY *key) { } -CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { +CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len) { + key_len /= 8; fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len); // TODO: rand must be seeded first (should be automatic) - if (out_len < key_len) + if (*out_len < key_len) CKR_BUFFER_TOO_SMALL; if (RSA_padding_add_PKCS1_type_1(out, key_len, in, in_len) == 0) return CKR_FUNCTION_FAILED; + *out_len = key_len; + + return CKR_OK; +} + +CK_RV do_pkcs_1_digest_info(CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { + + unsigned int len; + CK_RV rv; + + rv = prepare_rsa_signature(in, in_len, out, &len, nid); + if (!rv) + return CKR_FUNCTION_FAILED; + + *out_len = len; + + return CKR_OK; + +} + +CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, + CK_BYTE_PTR out, CK_ULONG_PTR out_len) { + unsigned char em[512]; // Max for this is ceil((|key_len_bits| - 1) / 8) + + // TODO: rand must be seeded first (should be automatic) + if (*out_len < RSA_size(key)) + CKR_BUFFER_TOO_SMALL; + + fprintf(stderr, "Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key)); + + if (RSA_padding_add_PKCS1_PSS(key, em, in, EVP_get_digestbynid(nid), -2) == 0) + return CKR_FUNCTION_FAILED; + + *out_len = RSA_size(key); + printf("hello!!!!!!!\n"); return CKR_OK; } @@ -177,7 +245,7 @@ CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx) { // The OpenSSL function above never fail if (EVP_DigestInit_ex(*ctx, md, NULL) == 0) { - EVP_MD_CTX_destroy(*ctx); + EVP_MD_CTX_destroy((EVP_MD_CTX *)*ctx); return CKR_FUNCTION_FAILED; } @@ -186,27 +254,32 @@ CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx) { CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len) { - return EVP_DigestUpdate(ctx, in, in_len) == 1 ? CKR_OK : CKR_FUNCTION_FAILED; + if (EVP_DigestUpdate(ctx, in, in_len) != 1) { + EVP_MD_CTX_destroy(ctx); + return CKR_FUNCTION_FAILED; + } + + return CKR_OK; } -CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BBOOL di, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { +CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int *nid) { int rv; - bool rv2; unsigned int len; + // Keep track of the md type if requested + if (nid != NULL) + *nid = EVP_MD_CTX_type(ctx); + // Finalize digest and store result - rv = EVP_DigestFinal_ex(ctx, out, (unsigned int *)out_len); - // Check wheter digest info is required - if (di == CK_TRUE) - rv2 = prepare_rsa_signature(out, *out_len, out, &len, EVP_MD_CTX_type(ctx)); + rv = EVP_DigestFinal_ex(ctx, out, &len); // Destroy the md context EVP_MD_CTX_destroy(ctx); - // Error if either of the previous calls failed - if (rv != 1 || !rv2) + // Error if the previous call failed + if (rv != 1) return CKR_FUNCTION_FAILED; *out_len = len; diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index a82b340..12febb8 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -16,12 +16,17 @@ CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); CK_KEY_TYPE do_get_key_type(EVP_PKEY *key); CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key); CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); +CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key); CK_RV free_key(EVP_PKEY *key); -CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); +CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len); +CK_RV do_pkcs_1_digest_info(CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_BYTE_PTR out, CK_ULONG_PTR out_len); + +CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, + CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx); CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len); -CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BBOOL di, CK_BYTE_PTR out, CK_ULONG_PTR out_len); +CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int *nid); #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 51dbc12..e83fc38 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1215,7 +1215,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( CK_ATTRIBUTE template[] = { {CKA_KEY_TYPE, &type, sizeof(type)}, {CKA_MODULUS_BITS, &key_len, sizeof(key_len)}, - {CKA_EC_POINT, buf, sizeof(buf)} + {CKA_MODULUS, NULL, 0}, + {CKA_EC_POINT, buf, sizeof(buf)}, }; if (piv_state == NULL) { @@ -1267,17 +1268,36 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( else op_info.op.sign.algo = YKPIV_ALGO_RSA2048; + // Also store the raw public key if the mechanism is PSS + if (is_PSS_mechanism(pMechanism->mechanism)) { + op_info.op.sign.key = malloc(key_len); + if (op_info.op.sign.key == NULL) + return CKR_HOST_MEMORY; + + template[2].pValue = op_info.op.sign.key; + template[2].ulValueLen = key_len; + + if (get_attribute(&session, hKey, template + 2) != CKR_OK) { + DBG(("Unable to get public key")); + return CKR_KEY_HANDLE_INVALID; + } + + } + else { + op_info.op.sign.key = NULL; + } + } else { // ECDSA key - if (get_attribute(&session, hKey, template + 2) != CKR_OK) { + if (get_attribute(&session, hKey, template + 3) != CKR_OK) { DBG(("Unable to get key length")); return CKR_KEY_HANDLE_INVALID; } // The buffer contains an uncompressed point of the form 04, x, y // TODO: is this a fine representation for an EC public key? - op_info.op.sign.key_len = ((template[2].ulValueLen - 1) / 2) * 8; + op_info.op.sign.key_len = ((template[3].ulValueLen - 1) / 2) * 8; if (op_info.op.sign.key_len == 256) op_info.op.sign.algo = YKPIV_ALGO_ECCP256; @@ -1289,8 +1309,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( DBG(("Key length is %lu bit", op_info.op.sign.key_len)); - op_info.op.sign.key = piv_2_ykpiv(hKey); - if (op_info.op.sign.key == 0) { + op_info.op.sign.key_id = piv_2_ykpiv(hKey); + if (op_info.op.sign.key_id == 0) { DBG(("Incorrect key %lu", hKey)); return CKR_KEY_HANDLE_INVALID; } @@ -1305,6 +1325,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( op_info.type = YKCS11_SIGN; + // TODO: check mechanism parameters and key length and key supported parameters + if (apply_sign_mechanism_init(&op_info) != CKR_OK) { DBG(("Unable to initialize signing operation")); return CKR_FUNCTION_FAILED; @@ -1347,8 +1369,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( } //dump_hex(buf, 256, stderr, CK_TRUE); //*pulSignatureLen = 256; - DBG(("Using key %lx", op_info.op.sign.key)); // TODO: test what happens if there is no key on the card - if ((r = ykpiv_sign_data(piv_state, op_info.buf, ulDataLen, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key)) != YKPIV_OK) { + DBG(("Using key %lx", op_info.op.sign.key_id)); // TODO: test what happens if there is no key on the card + if ((r = ykpiv_sign_data(piv_state, op_info.buf, ulDataLen, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id)) != YKPIV_OK) { DBG(("Sign error, %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index fc20bb0..5482b3c 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -37,10 +37,11 @@ typedef enum { } ykcs11_op_type_t; typedef struct { - ykcs11_md_ctx_t *md_ctx; - CK_BYTE algo; - CK_ULONG key; - CK_ULONG key_len; + ykcs11_md_ctx_t *md_ctx; // Digest context + CK_BYTE_PTR key; // Raw public key (needed for PSS) + CK_BYTE algo; // Algo for ykpiv + CK_ULONG key_id; // Key id for ykpiv + CK_ULONG key_len; // Length in bits } sign_info_t; typedef struct { diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index a70dab8..e7aad07 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -17,15 +17,15 @@ static const CK_BYTE_PTR token_serial = "1234"; static const CK_MECHANISM_TYPE token_mechanisms[] = { // KEEP ALIGNED WITH token_mechanism_infos CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, - // CKM_RSA_PKCS_PSS, + CKM_RSA_PKCS_PSS, CKM_RSA_X_509, CKM_SHA1_RSA_PKCS, CKM_SHA256_RSA_PKCS, - // CKM_SHA384_RSA_PKCS, + CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS, CKM_SHA1_RSA_PKCS_PSS, CKM_SHA256_RSA_PKCS_PSS, - // CKM_SHA384_RSA_PKCS_PSS, + CKM_SHA384_RSA_PKCS_PSS, CKM_SHA512_RSA_PKCS_PSS, CKM_EC_KEY_PAIR_GEN, //CKM_ECDSA_KEY_PAIR_GEN, Same as CKM_EC_KEY_PAIR_GEN, deprecated in 2.11 @@ -42,15 +42,15 @@ static const CK_ULONG token_mechanisms_num = sizeof(token_mechanisms) / sizeof(C static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH token_mechanisms {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_GENERATE_KEY_PAIR}, // CKM_RSA_PKCS_KEY_PAIR_GEN {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_DECRYPT | CKF_SIGN}, // CKM_RSA_PKCS - //{MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_RSA_PKCS_PSS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_RSA_PKCS_PSS {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_DECRYPT | CKF_SIGN}, // CKM_RSA_X_509 {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA1_RSA_PKCS {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA256_RSA_PKCS - //{MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA384_RSA_PKCS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA384_RSA_PKCS {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA512_RSA_PKCS {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA1_RSA_PKCS_PSS {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA256_RSA_PKCS_PSS - //{, , }, // CKM_SHA384_RSA_PKCS_PSS + {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA384_RSA_PKCS_PSS {MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_SHA512_RSA_PKCS_PSS {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_GENERATE_KEY_PAIR}, // CKM_EC_KEY_PAIR_GEN //{, , }, // CKM_ECDSA_KEY_PAIR_GEN Same as CKM_EC_KEY_PAIR_GEN deprecated in 2.11 From e3acd1f027767678a373101cd606aa2f40a449fd Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 6 Aug 2015 10:00:29 +0200 Subject: [PATCH 048/134] Fixed object attribute matching. Added ECDSA. --- ykcs11/mechanisms.c | 42 ++++++++++++++++++++++++++++++++++++------ ykcs11/mechanisms.h | 1 + ykcs11/ykcs11.c | 17 ++++++++--------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index e41fa35..4fd105c 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -102,6 +102,32 @@ CK_BBOOL is_PSS_mechanism(CK_MECHANISM_TYPE m) { return CK_FALSE; } +CK_BBOOL is_hashed_mechanism(CK_MECHANISM_TYPE m) { + + switch (m) { + case CKM_SHA1_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + case CKM_ECDSA_SHA1: + case CKM_SHA_1: + case CKM_SHA256: + case CKM_SHA384: + case CKM_SHA512: + return CK_TRUE; + + default: + return CK_FALSE; + } + + // Not reached + return CK_FALSE; +} + CK_RV apply_sign_mechanism_init(op_info_t *op_info) { if (op_info->type != YKCS11_SIGN) @@ -138,7 +164,8 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) { return do_md_init(YKCS11_SHA512, &op_info->op.sign.md_ctx); case CKM_ECDSA: - return CKR_FUNCTION_FAILED; // TODO: but no hash needed + // No hash required for this mechanism + return CKR_OK; default: return CKR_FUNCTION_FAILED; @@ -157,6 +184,7 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i switch (op_info->mechanism.mechanism) { case CKM_RSA_PKCS: case CKM_RSA_PKCS_PSS: + case CKM_ECDSA: // Mechanism not suitable for multipart signatures return CKR_FUNCTION_FAILED; @@ -178,9 +206,6 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i return CKR_OK; - case CKM_ECDSA: - return CKR_FUNCTION_FAILED; - default: return CKR_FUNCTION_FAILED; } @@ -251,9 +276,14 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { op_info->buf_len = sizeof(op_info->buf); return do_pkcs_1_t1(op_info->buf, len, op_info->buf, &op_info->buf_len, op_info->op.sign.key_len); - case CKM_ECDSA_SHA1: // TODO: + case CKM_ECDSA_SHA1: + // Finalize the hash + rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + if (rv != CKR_OK) + return CKR_FUNCTION_FAILED; + case CKM_ECDSA: - return CKR_FUNCTION_FAILED; + return CKR_OK; default: return CKR_FUNCTION_FAILED; diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index b39a78e..1869774 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -6,6 +6,7 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); CK_BBOOL is_PSS_mechanism(CK_MECHANISM_TYPE m); +CK_BBOOL is_hashed_mechanism(CK_MECHANISM_TYPE m); CK_RV apply_sign_mechanism_init(op_info_t *op_info); CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index e83fc38..f650769 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -927,6 +927,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( if (is_private_object(&session, find_obj.objects[i]) == CK_TRUE) { DBG(("Stripping away private object %u", find_obj.objects[i])); find_obj.objects[i] = OBJECT_INVALID; + total--; continue; } @@ -937,6 +938,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( DBG(("Removing object %u from the list", find_obj.objects[i])); find_obj.objects[i] = OBJECT_INVALID; // Object not matching, mark it total--; + break; } else DBG(("Keeping object %u in the list", find_obj.objects[i])); @@ -945,11 +947,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( DBG(("%lu object(s) left after attribute matching", total)); - // TODO: do it properly here, just a test now - //find_obj.objects = session.slot->token->objects + 3; - /*memmove(find_obj.objects, find_obj.objects + 12, sizeof(piv_obj_id_t) * (find_obj.num - 12)); - find_obj.num = 1;*/ - find_obj.active = CK_TRUE; DOUT; @@ -1358,10 +1355,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( DBG(("Sending %lu bytes to sign", ulDataLen)); dump_hex(pData, ulDataLen, stderr, CK_TRUE); - if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { - DBG(("Unable to perform signing operation step")); - return CKR_FUNCTION_FAILED; - } + if (is_hashed_mechanism(op_info.mechanism.mechanism) == CK_TRUE) { + if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { + DBG(("Unable to perform signing operation step")); + return CKR_FUNCTION_FAILED; + } + } if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) { DBG(("Unable to finalize signing operation")); From fa2cdaa2ed41b774a8f47efc26c38b9c74e137fe Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 6 Aug 2015 16:22:48 +0200 Subject: [PATCH 049/134] Added more attribute extraction for objects. --- ykcs11/obj_types.h | 12 +- ykcs11/objects.c | 339 ++++++++++++++--------------------------- ykcs11/openssl_utils.c | 21 ++- ykcs11/openssl_utils.h | 1 + ykcs11/ykcs11.c | 4 +- 5 files changed, 150 insertions(+), 227 deletions(-) diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 44876b0..7c94f29 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -106,11 +106,19 @@ typedef struct { } piv_cert_obj_t; typedef struct { // TODO: enough to use the public key for the parameters? - CK_BBOOL todo; + CK_BBOOL decrypt; + CK_BBOOL sign; + CK_BBOOL unwrap; + CK_BBOOL derive; + CK_BBOOL always_auth; } piv_pvtk_obj_t; typedef struct { - EVP_PKEY *data; // TODO: make custo type for this and X509 + EVP_PKEY *data; // TODO: make custom type for this and X509 + CK_BBOOL encrypt; + CK_BBOOL verify; + CK_BBOOL wrap; + CK_BBOOL derive; } piv_pubk_obj_t; typedef struct { diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 55d6045..b73979a 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -122,19 +122,19 @@ static piv_cert_obj_t cert_objects[] = { }; static piv_pvtk_obj_t pvtkey_objects[] = { - {0}, - {0}, - {0}, - {0}, - {0} + {1, 1, 0, 0, 0}, + {1, 1, 0, 0, 0}, + {1, 1, 0, 0, 0}, + {1, 1, 0, 0, 1}, + {1, 1, 0, 0, 0} }; static piv_pubk_obj_t pubkey_objects[] = { - {0}, - {0}, - {0}, - {0}, - {0} + {NULL, 1, 1, 0, 0}, + {NULL, 1, 1, 0, 0}, + {NULL, 1, 1, 0, 0}, + {NULL, 1, 1, 0, 0}, + {NULL, 1, 1, 0, 0} }; @@ -242,7 +242,7 @@ static CK_KEY_TYPE get_key_type(EVP_PKEY *key) { return do_get_key_type(key); } -static CK_KEY_TYPE get_modulus_bits(EVP_PKEY *key) { +static CK_ULONG get_modulus_bits(EVP_PKEY *key) { return do_get_rsa_modulus_length(key); } @@ -250,6 +250,10 @@ static CK_RV get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { return do_get_public_key(key, data, len); } +static CK_RV get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { + return do_get_curve_parameters(key, data, len); +} + /* Get data object attribute */ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; @@ -297,63 +301,12 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { return CKR_FUNCTION_FAILED; case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? - // This only makes sense for data objects fprintf(stderr, "OID\n"); strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid); asn1_encode_oid(tmp, tmp, &len); data = tmp; break; - /* case CKA_CERTIFICATE_TYPE: */ - /* fprintf(stderr, "CERTIFICATE TYPE\n"); */ - /* len = 1; */ - /* tmp[0] = CKC_X_509; // Support only X.509 certs */ - /* data = tmp; */ - /* break; */ - -// case CKA_ISSUER: -// case CKA_SERIAL_NUMBER: - /* case CKA_KEY_TYPE: */ - /* fprintf(stderr, "Return the key type TODO!!!\n"); */ - /* return CKR_OK; */ - - /* case CKA_SUBJECT: */ - /* case CKA_ID: */ - /* fprintf(stderr, "ID\n"); */ - /* len = data_objects[objects[obj].sub_id].tag_len; */ - /* data = data_objects[objects[obj].sub_id].tag_value; */ - /* break; */ - - /* case CKA_SENSITIVE: */ - /* case CKA_ENCRYPT: */ - /* case CKA_DECRYPT: */ - /* case CKA_WRAP: */ - /* case CKA_UNWRAP: */ - /* case CKA_SIGN: */ - /* case CKA_SIGN_RECOVER: */ - /* case CKA_VERIFY: */ - /* case CKA_VERIFY_RECOVER: */ - /* case CKA_DERIVE: */ - /* case CKA_START_DATE: */ - /* case CKA_END_DATE: */ - /* case CKA_MODULUS: */ - /* case CKA_MODULUS_BITS: */ - /* case CKA_PUBLIC_EXPONENT: */ - /* case CKA_PRIVATE_EXPONENT: */ - /* case CKA_PRIME_1: */ - /* case CKA_PRIME_2: */ - /* case CKA_EXPONENT_1: */ - /* case CKA_EXPONENT_2: */ - /* case CKA_COEFFICIENT: */ - /* case CKA_PRIME: */ - /* case CKA_SUBPRIME: */ - /* case CKA_BASE: */ - /* case CKA_VALUE_BITS: */ - /* case CKA_VALUE_LEN: */ - /* case CKA_EXTRACTABLE: */ - /* case CKA_LOCAL: */ - /* case CKA_NEVER_EXTRACTABLE: */ - /* case CKA_ALWAYS_SENSITIVE: */ case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); len = 1; @@ -361,7 +314,6 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { data = tmp; break; - /* case CKA_VENDOR_DEFINED: */ default: fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; @@ -421,24 +373,10 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { data = piv_objects[obj].label; break; - /* case CKA_APPLICATION: */ - /* fprintf(stderr, "APPLICATION\n"); */ - /* len = strlen(objects[obj].label) + 1; */ - /* data = objects[obj].label; */ - /* break; */ - case CKA_VALUE: fprintf(stderr, "VALUE TODO\n"); return CKR_FUNCTION_FAILED; - /* case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? */ - /* // This only makes sense for data objects */ - /* fprintf(stderr, "OID\n"); */ - /* strcpy((char *)tmp, certificate_objects[objects[obj].sub_id].oid); */ - /* asn1_encode_oid(tmp, tmp, &len); */ - /* data = tmp; */ - /* break; */ - case CKA_CERTIFICATE_TYPE: fprintf(stderr, "CERTIFICATE TYPE\n"); len = 1; @@ -454,10 +392,6 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { fprintf(stderr, "SERIAL NUMBER TODO\n"); // Default empty return CKR_FUNCTION_FAILED; - /* case CKA_KEY_TYPE: */ - /* fprintf(stderr, "Return the key type TODO!!!\n"); */ - /* return CKR_OK; */ - case CKA_SUBJECT: fprintf(stderr, "SUBJECT TODO\n"); // Required return CKR_FUNCTION_FAILED; @@ -469,16 +403,6 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { data = tmp; break; - /* case CKA_SENSITIVE: */ - /* case CKA_ENCRYPT: */ - /* case CKA_DECRYPT: */ - /* case CKA_WRAP: */ - /* case CKA_UNWRAP: */ - /* case CKA_SIGN: */ - /* case CKA_SIGN_RECOVER: */ - /* case CKA_VERIFY: */ - /* case CKA_VERIFY_RECOVER: */ - /* case CKA_DERIVE: */ case CKA_START_DATE: fprintf(stderr, "START DATE TODO\n"); // Default empty return CKR_FUNCTION_FAILED; @@ -487,24 +411,6 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { fprintf(stderr, "END DATE TODO\n"); // Default empty return CKR_FUNCTION_FAILED; - /* case CKA_MODULUS: */ - /* case CKA_MODULUS_BITS: */ - /* case CKA_PUBLIC_EXPONENT: */ - /* case CKA_PRIVATE_EXPONENT: */ - /* case CKA_PRIME_1: */ - /* case CKA_PRIME_2: */ - /* case CKA_EXPONENT_1: */ - /* case CKA_EXPONENT_2: */ - /* case CKA_COEFFICIENT: */ - /* case CKA_PRIME: */ - /* case CKA_SUBPRIME: */ - /* case CKA_BASE: */ - /* case CKA_VALUE_BITS: */ - /* case CKA_VALUE_LEN: */ - /* case CKA_EXTRACTABLE: */ - /* case CKA_LOCAL: */ - /* case CKA_NEVER_EXTRACTABLE: */ - /* case CKA_ALWAYS_SENSITIVE: */ case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); len = 1; @@ -512,7 +418,6 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { data = tmp; break; - /* case CKA_VENDOR_DEFINED: */ default: // TODO: there are other attributes for a (x509) certificate fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; @@ -573,30 +478,6 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { data = piv_objects[obj].label; break; - /* case CKA_APPLICATION: */ - /* fprintf(stderr, "APPLICATION\n"); */ - /* len = strlen(objects[obj].label) + 1; */ - /* data = objects[obj].label; */ - /* break; */ - -// case CKA_VALUE: // TODO: this can be done with -r and -d|-a - /* case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? */ - /* // This only makes sense for data objects */ - /* fprintf(stderr, "OID\n"); */ - /* strcpy((char *)tmp, pvtkey_objects[objects[obj].sub_id].oid); */ - /* asn1_encode_oid(tmp, tmp, &len); */ - /* data = tmp; */ - /* break; */ - - /* case CKA_CERTIFICATE_TYPE: */ - /* fprintf(stderr, "CERTIFICATE TYPE\n"); */ - /* len = 1; */ - /* tmp[0] = CKC_X_509; // Support only X.509 certs */ - /* data = tmp; */ - /* break; */ - -// case CKA_ISSUER: -// case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: fprintf(stderr, "KEY TYPE\n"); len = sizeof(CK_ULONG); @@ -621,29 +502,37 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { fprintf(stderr, "SENSITIVE TODO\n"); // Default empty return CKR_FUNCTION_FAILED; - /* case CKA_ENCRYPT: */ case CKA_DECRYPT: - fprintf(stderr, "DECRYPT TODO\n"); // Default empty - return CKR_FUNCTION_FAILED; + fprintf(stderr, "DECRYPT\n"); // Default empty + len = sizeof(CK_BBOOL); + b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].decrypt; + data = b_tmp; + break; - /* case CKA_WRAP: */ case CKA_UNWRAP: - fprintf(stderr, "UNWRAP TODO\n"); // Default empty - return CKR_FUNCTION_FAILED; + fprintf(stderr, "UNWRAP\n"); // Default empty + len = sizeof(CK_BBOOL); + b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].unwrap; + data = b_tmp; + break; case CKA_SIGN: - fprintf(stderr, "SIGN TODO\n"); // Default empty - return CKR_FUNCTION_FAILED; + fprintf(stderr, "SIGN\n"); // Default empty + len = sizeof(CK_BBOOL); + b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].sign; + data = b_tmp; + break; case CKA_SIGN_RECOVER: fprintf(stderr, "SIGN RECOVER TODO\n"); // Default empty return CKR_FUNCTION_FAILED; - /* case CKA_VERIFY: */ - /* case CKA_VERIFY_RECOVER: */ case CKA_DERIVE: - fprintf(stderr, "DERIVE TODO\n"); // Default false - return CKR_FUNCTION_FAILED; + fprintf(stderr, "DERIVE\n"); // Default false + len = sizeof(CK_BBOOL); + b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].derive; + data = b_tmp; + break; case CKA_START_DATE: fprintf(stderr, "START DATE TODO\n"); // Default empty @@ -698,7 +587,15 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { return CKR_FUNCTION_FAILED; /* case CKA_NEVER_EXTRACTABLE: */ - /* case CKA_ALWAYS_SENSITIVE: */ + /*case CKA_ALWAYS_SENSITIVE:*/ + + case CKA_ALWAYS_AUTHENTICATE: + fprintf(stderr, "ALWAYS AUTHENTICATE\n"); + len = sizeof(CK_BBOOL); + b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].always_auth; + data = b_tmp; + break; + case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); len = sizeof(CK_BBOOL); @@ -733,31 +630,32 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Get public key object attribute */ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; - CK_BYTE tmp[64]; + CK_BYTE b_tmp[1024]; + CK_ULONG ul_tmp; // TODO: fix elsewhere too CK_ULONG len = 0; fprintf(stderr, "FOR PUBLIC KEY OBJECT %lu, I WANT ", obj); switch (template->type) { case CKA_CLASS: fprintf(stderr, "CLASS\n"); - len = 1; - tmp[0] = CKO_PUBLIC_KEY; - data = tmp; + len = sizeof(CK_ULONG); + ul_tmp = CKO_PUBLIC_KEY; + data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_TOKEN: // Technically all these objects are token objects fprintf(stderr, "TOKEN\n"); - len = 1; - tmp[0] = piv_objects[obj].token; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].token; + data = b_tmp; break; case CKA_PRIVATE: fprintf(stderr, "PRIVATE\n"); - len = 1; - tmp[0] = piv_objects[obj].private; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].private; + data = b_tmp; break; case CKA_LABEL: @@ -766,33 +664,16 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { data = piv_objects[obj].label; break; - /* case CKA_APPLICATION: */ - /* fprintf(stderr, "APPLICATION\n"); */ - /* len = strlen(objects[obj].label) + 1; */ - /* data = objects[obj].label; */ - /* break; */ - // case CKA_VALUE: // TODO: this can be done with -r and -d|-a - /* case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? */ - /* // This only makes sense for data objects */ - /* fprintf(stderr, "OID\n"); */ - /* strcpy((char *)tmp, pubkey_objects[objects[obj].sub_id].oid); */ - /* asn1_encode_oid(tmp, tmp, &len); */ - /* data = tmp; */ - /* break; */ - /* case CKA_CERTIFICATE_TYPE: */ - /* fprintf(stderr, "CERTIFICATE TYPE\n"); */ - /* len = 1; */ - /* tmp[0] = CKC_X_509; // Support only X.509 certs */ - /* data = tmp; */ - /* break; */ - -// case CKA_ISSUER: -// case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: - fprintf(stderr, "KEY TYPE TODO\n"); - return CKR_FUNCTION_FAILED; + fprintf(stderr, "KEY TYPE\n"); + len = sizeof(CK_ULONG); + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); + if (ul_tmp == CKK_VENDOR_DEFINED) // This value is used as an error here + return CKR_FUNCTION_FAILED; + data = (CK_BYTE_PTR) &ul_tmp; + break; case CKA_SUBJECT: fprintf(stderr, "SUBJECT TODO\n"); // Default empty @@ -800,32 +681,38 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_ID: fprintf(stderr, "ID\n"); - len = 1; - tmp[0] = piv_objects[obj].sub_id; - data = tmp; + len = sizeof(CK_BYTE); + b_tmp[0] = piv_objects[obj].sub_id; + data = b_tmp; break; - /* case CKA_SENSITIVE: */ case CKA_ENCRYPT: - fprintf(stderr, "ENCRYPT TODO\n"); // Required - return CKR_FUNCTION_FAILED; + fprintf(stderr, "ENCRYPT\n"); + len = sizeof(CK_BBOOL); + b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].encrypt; + data = b_tmp; + break; - case CKA_DECRYPT: - fprintf(stderr, "DECRYPT TODO\n"); // Required - return CKR_FUNCTION_FAILED; + case CKA_VERIFY: // TODO: what about verify recover ? + fprintf(stderr, "VERIFY\n"); + len = sizeof(CK_BBOOL); + b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].verify; + data = b_tmp; + break; case CKA_WRAP: - fprintf(stderr, "WRAP TODO\n"); // Required - return CKR_FUNCTION_FAILED; + fprintf(stderr, "WRAP\n"); + len = sizeof(CK_BBOOL); + b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].wrap; + data = b_tmp; + break; - /* case CKA_UNWRAP: */ - /* case CKA_SIGN: */ - /* case CKA_SIGN_RECOVER: */ - /* case CKA_VERIFY: */ - /* case CKA_VERIFY_RECOVER: */ case CKA_DERIVE: - fprintf(stderr, "DERIVE TODO\n"); // Defaul false - return CKR_FUNCTION_FAILED; + fprintf(stderr, "DERIVE\n"); + len = sizeof(CK_BBOOL); + b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].derive; + data = b_tmp; + break; case CKA_START_DATE: fprintf(stderr, "START DATE TODO\n"); // Default empty @@ -834,37 +721,47 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_END_DATE: fprintf(stderr, "END DATE TODO\n"); // Default empty return CKR_FUNCTION_FAILED; - /* case CKA_MODULUS: */ - /* case CKA_MODULUS_BITS: */ - /* case CKA_PUBLIC_EXPONENT: */ - /* case CKA_PRIVATE_EXPONENT: */ - /* case CKA_PRIME_1: */ - /* case CKA_PRIME_2: */ - /* case CKA_EXPONENT_1: */ - /* case CKA_EXPONENT_2: */ - /* case CKA_COEFFICIENT: */ - /* case CKA_PRIME: */ - /* case CKA_SUBPRIME: */ - /* case CKA_BASE: */ - /* case CKA_VALUE_BITS: */ - /* case CKA_VALUE_LEN: */ - /* case CKA_EXTRACTABLE: */ + + case CKA_EC_POINT: + // We're trying to get the key length, get the ec point of the PUBLIC key + fprintf(stderr, "EC_POINT\n"); + len = sizeof(b_tmp); + if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + data = b_tmp; + break; + + case CKA_EC_PARAMS: + // Here we want the curve parameters (DER encoded OID) + fprintf(stderr, "EC_PARAMS\n"); + len = sizeof(b_tmp); + if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + data = b_tmp; + break; + + case CKA_MODULUS_BITS: + fprintf(stderr, "MODULUS BITS\n"); + len = sizeof(CK_ULONG); + ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == 0) + return CKR_FUNCTION_FAILED; + data = (CK_BYTE_PTR) &ul_tmp; + break; + case CKA_LOCAL: fprintf(stderr, "LOCAL TODO\n"); // Required return CKR_FUNCTION_FAILED; - /* case CKA_NEVER_EXTRACTABLE: */ - /* case CKA_ALWAYS_SENSITIVE: */ case CKA_MODIFIABLE: fprintf(stderr, "MODIFIABLE\n"); - len = 1; - tmp[0] = piv_objects[obj].modifiable; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].modifiable; + data = b_tmp; break; - /* case CKA_VENDOR_DEFINED: */ default: - fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); // TODO: there are other parameters for public keys + fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! 0x%lx\n", template[0].type); // TODO: there are other parameters for public keys template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 2d69ce8..1b30237 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -90,7 +90,7 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { RSA *rsa; unsigned char *p; - + EC_KEY *eck; const EC_GROUP *ecg; // Alternative solution is to get i2d_PUBKEY and manually offset const EC_POINT *ecp; @@ -143,7 +143,7 @@ CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key) { if (data == NULL) return CKR_ARGUMENTS_BAD; - + if ((*key = d2i_RSAPublicKey(NULL, &p, len)) == NULL) return CKR_FUNCTION_FAILED; @@ -151,6 +151,23 @@ CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key) { } +CK_RV do_get_curve_parameters( EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { + + EC_KEY *eck; + const EC_GROUP *ecg; + unsigned char *p; + + eck = EVP_PKEY_get1_EC_KEY(key); + ecg = EC_KEY_get0_group(eck); + + p = data; + + if ((*len = i2d_ECPKParameters(ecg, &p)) == 0) + return CKR_FUNCTION_FAILED; + + return CKR_OK; +} + CK_RV free_key(EVP_PKEY *key) { EVP_PKEY_free(key); diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 12febb8..e146001 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -17,6 +17,7 @@ CK_KEY_TYPE do_get_key_type(EVP_PKEY *key); CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key); CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key); +CK_RV do_get_curve_parameters( EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); CK_RV free_key(EVP_PKEY *key); CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index f650769..3540215 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -15,7 +15,7 @@ printf ("\n"); \ } while (0) -#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DBG 0 // General debug, must be either 1 or 0 #define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" @@ -838,7 +838,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( // TODO: this function has some complex cases for return vlaue. Make sure to check them. if (rv != CKR_OK) { - DBG(("Unable to get attribute %lu of object %lu", (pTemplate + i)->type, hObject)); + DBG(("Unable to get attribute 0x%lx of object %lu", (pTemplate + i)->type, hObject)); rv_final = rv; } } From 6f0a9e7a092dcb14ec9d3e9a5d3a57c236a2e91e Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 6 Aug 2015 17:14:47 +0200 Subject: [PATCH 050/134] Moved debug capabilities to its own file. Fixed EC point replresentation. --- ykcs11/Makefile.am | 1 + ykcs11/debug.h | 28 ++++++++ ykcs11/mechanisms.c | 4 +- ykcs11/objects.c | 160 ++++++++++++++++++++--------------------- ykcs11/objects.h | 2 - ykcs11/openssl_utils.c | 20 ++++-- ykcs11/utils.c | 3 +- ykcs11/ykcs11.c | 30 +------- ykcs11/yubico_token.c | 13 ++-- 9 files changed, 136 insertions(+), 125 deletions(-) create mode 100644 ykcs11/debug.h diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index c635276..4e91d9f 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -34,6 +34,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map +libykcs11_la_SOURCES += debug.h libykcs11_la_SOURCES += vendors.c vendor.h vendor_ids.h libykcs11_la_SOURCES += slot_vendors.c slot_vendor.h libykcs11_la_SOURCES += token_vendors.c token_vendor.h diff --git a/ykcs11/debug.h b/ykcs11/debug.h new file mode 100644 index 0000000..946fc25 --- /dev/null +++ b/ykcs11/debug.h @@ -0,0 +1,28 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#define D(x) do { \ + printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ + printf x; \ + printf ("\n"); \ + } while (0) + +#define YKCS11_DBG 0 // General debug, must be either 1 or 0 +#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 + +#if YKCS11_DBG +#include +#define DBG(x) D(x); +#else +#define DBG(x) +#endif + +#if YKCS11_DINOUT +#define DIN D(("In")); +#define DOUT D(("Out")); +#else +#define DIN +#define DOUT +#endif + +#endif diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 4fd105c..bec71a3 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -257,7 +257,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); if (rv != CKR_OK) return CKR_FUNCTION_FAILED; - fprintf(stderr, "The hashed value is %lu long and looks like\n", op_info->buf_len); + DBG(("The hashed value is %lu long and looks like\n", op_info->buf_len)); dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); case CKM_RSA_PKCS: @@ -267,7 +267,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { if (rv != CKR_OK) return CKR_FUNCTION_FAILED; - fprintf(stderr, "After adding digestinfo is %lu long and looks like\n", op_info->buf_len); + DBG(("After adding digestinfo is %lu long and looks like\n", op_info->buf_len)); dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); } diff --git a/ykcs11/objects.c b/ykcs11/objects.c index b73979a..8f0ff96 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -4,6 +4,7 @@ #include #include #include "openssl_utils.h" +#include "debug.h" #define IS_CERT(x) (((x) >= PIV_CERT_OBJ_X509_PIV_AUTH && (x) < PIV_CERT_OBJ_LAST) ? CK_TRUE : CK_FALSE) @@ -259,11 +260,11 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; CK_BYTE tmp[64]; CK_ULONG len = 0; - fprintf(stderr, "FOR DATA OBJECT %lu, I WANT ", obj); + DBG(("For data object %lu, get ", obj)); switch (template->type) { case CKA_CLASS: - fprintf(stderr, "CLASS\n"); + DBG(("CLASS\n")); len = 1; tmp[0] = CKO_DATA; data = tmp; @@ -271,51 +272,51 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - fprintf(stderr, "TOKEN\n"); + DBG(("TOKEN\n")); len = 1; tmp[0] = piv_objects[obj].token; data = tmp; break; case CKA_PRIVATE: - fprintf(stderr, "PRIVATE\n"); + DBG(("PRIVATE\n")); len = 1; tmp[0] = piv_objects[obj].private; data = tmp; break; case CKA_LABEL: - fprintf(stderr, "LABEL\n"); + DBG(("LABEL\n")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_APPLICATION: - fprintf(stderr, "APPLICATION\n"); + DBG(("APPLICATION\n")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_VALUE: // TODO: this can be done with -r and -d|-a - fprintf(stderr, "VALUE TODO!!!\n"); + DBG(("VALUE TODO!!!\n")); return CKR_FUNCTION_FAILED; case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? - fprintf(stderr, "OID\n"); + DBG(("OID\n")); strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid); asn1_encode_oid(tmp, tmp, &len); data = tmp; break; case CKA_MODIFIABLE: - fprintf(stderr, "MODIFIABLE\n"); + DBG(("MODIFIABLE\n")); len = 1; tmp[0] = piv_objects[obj].modifiable; data = tmp; break; default: - fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); + DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -342,11 +343,11 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; CK_BYTE tmp[64]; CK_ULONG len = 0; - fprintf(stderr, "FOR CERTIFICATE OBJECT %lu, I WANT ", obj); + DBG(("For certificate object %lu, get ", obj)); switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above? case CKA_CLASS: - fprintf(stderr, "CLASS\n"); + DBG(("CLASS\n")); len = 1; tmp[0] = CKO_CERTIFICATE; data = tmp; @@ -354,72 +355,72 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - fprintf(stderr, "TOKEN\n"); + DBG(("TOKEN\n")); len = 1; tmp[0] = piv_objects[obj].token; data = tmp; break; case CKA_PRIVATE: - fprintf(stderr, "PRIVATE\n"); + DBG(("PRIVATE\n")); len = 1; tmp[0] = piv_objects[obj].private; data = tmp; break; case CKA_LABEL: - fprintf(stderr, "LABEL\n"); + DBG(("LABEL\n")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_VALUE: - fprintf(stderr, "VALUE TODO\n"); + DBG(("VALUE TODO\n")); return CKR_FUNCTION_FAILED; case CKA_CERTIFICATE_TYPE: - fprintf(stderr, "CERTIFICATE TYPE\n"); + DBG(("CERTIFICATE TYPE\n")); len = 1; tmp[0] = CKC_X_509; // Support only X.509 certs data = tmp; break; case CKA_ISSUER: - fprintf(stderr, "ISSUER TODO\n"); // Default empty + DBG(("ISSUER TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_SERIAL_NUMBER: - fprintf(stderr, "SERIAL NUMBER TODO\n"); // Default empty + DBG(("SERIAL NUMBER TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_SUBJECT: - fprintf(stderr, "SUBJECT TODO\n"); // Required + DBG(("SUBJECT TODO\n")); // Required return CKR_FUNCTION_FAILED; case CKA_ID: - fprintf(stderr, "ID\n"); + DBG(("ID\n")); len = 1; tmp[0] = piv_objects[obj].sub_id; data = tmp; break; case CKA_START_DATE: - fprintf(stderr, "START DATE TODO\n"); // Default empty + DBG(("START DATE TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - fprintf(stderr, "END DATE TODO\n"); // Default empty + DBG(("END DATE TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_MODIFIABLE: - fprintf(stderr, "MODIFIABLE\n"); + DBG(("MODIFIABLE\n")); len = 1; tmp[0] = piv_objects[obj].modifiable; data = tmp; break; default: // TODO: there are other attributes for a (x509) certificate - fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); + DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -447,11 +448,11 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE b_tmp[1024]; CK_ULONG ul_tmp; // TODO: fix elsewhere too CK_ULONG len = 0; - fprintf(stderr, "FOR PRIVATE KEY OBJECT %lu, I WANT ", obj); + DBG(("For private key object %lu, get ", obj)); switch (template->type) { case CKA_CLASS: - fprintf(stderr, "CLASS\n"); + DBG(("CLASS\n")); len = sizeof(CK_ULONG); ul_tmp = CKO_PRIVATE_KEY; data = (CK_BYTE_PTR) &ul_tmp; @@ -459,27 +460,27 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - fprintf(stderr, "TOKEN\n"); + DBG(("TOKEN\n")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].token; data = b_tmp; break; case CKA_PRIVATE: - fprintf(stderr, "PRIVATE\n"); + DBG(("PRIVATE\n")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].private; data = b_tmp; break; case CKA_LABEL: - fprintf(stderr, "LABEL\n"); + DBG(("LABEL\n")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_KEY_TYPE: - fprintf(stderr, "KEY TYPE\n"); + DBG(("KEY TYPE\n")); len = sizeof(CK_ULONG); ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == CKK_VENDOR_DEFINED) @@ -488,87 +489,87 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_SUBJECT: - fprintf(stderr, "SUBJECT TODO\n"); // Default empty + DBG(("SUBJECT TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_ID: - fprintf(stderr, "ID\n"); + DBG(("ID\n")); len = sizeof(CK_BYTE); ul_tmp = piv_objects[obj].sub_id; data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_SENSITIVE: - fprintf(stderr, "SENSITIVE TODO\n"); // Default empty + DBG(("SENSITIVE TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_DECRYPT: - fprintf(stderr, "DECRYPT\n"); // Default empty + DBG(("DECRYPT\n")); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].decrypt; data = b_tmp; break; case CKA_UNWRAP: - fprintf(stderr, "UNWRAP\n"); // Default empty + DBG(("UNWRAP\n")); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].unwrap; data = b_tmp; break; case CKA_SIGN: - fprintf(stderr, "SIGN\n"); // Default empty + DBG(("SIGN\n")); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].sign; data = b_tmp; break; case CKA_SIGN_RECOVER: - fprintf(stderr, "SIGN RECOVER TODO\n"); // Default empty + DBG(("SIGN RECOVER TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_DERIVE: - fprintf(stderr, "DERIVE\n"); // Default false + DBG(("DERIVE\n")); // Default false len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].derive; data = b_tmp; break; case CKA_START_DATE: - fprintf(stderr, "START DATE TODO\n"); // Default empty + DBG(("START DATE TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - fprintf(stderr, "END DATE TODO\n"); // Default empty + DBG(("END DATE TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_MODULUS: - fprintf(stderr, "MODULUS\n"); + DBG(("MODULUS\n")); len = sizeof(b_tmp); if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; data = b_tmp; break; - + case CKA_EC_POINT: // We're trying to get the key length, get the ec point of the PUBLIC key // TODO: or just give an error and explicitly fetch the pubk len when needed - fprintf(stderr, "EC_POINT\n"); + DBG(("EC_POINT\n")); len = sizeof(b_tmp); if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; data = b_tmp; break; - + case CKA_MODULUS_BITS: - fprintf(stderr, "MODULUS BITS\n"); + DBG(("MODULUS BITS\n")); len = sizeof(CK_ULONG); ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == 0) return CKR_FUNCTION_FAILED; data = (CK_BYTE_PTR) &ul_tmp; break; - + /* case CKA_PUBLIC_EXPONENT: */ /* case CKA_PRIVATE_EXPONENT: */ /* case CKA_PRIME_1: */ @@ -583,21 +584,21 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* case CKA_VALUE_LEN: */ /* case CKA_EXTRACTABLE: */ case CKA_LOCAL: - fprintf(stderr, "LOCAL TODO\n"); // Required + DBG(("LOCAL TODO\n")); // Required return CKR_FUNCTION_FAILED; /* case CKA_NEVER_EXTRACTABLE: */ /*case CKA_ALWAYS_SENSITIVE:*/ case CKA_ALWAYS_AUTHENTICATE: - fprintf(stderr, "ALWAYS AUTHENTICATE\n"); + DBG(("ALWAYS AUTHENTICATE\n")); len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].always_auth; data = b_tmp; break; case CKA_MODIFIABLE: - fprintf(stderr, "MODIFIABLE\n"); + DBG(("MODIFIABLE\n")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].modifiable; data = b_tmp; @@ -605,7 +606,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /*case CKA_VENDOR_DEFINED:*/ default: - fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! %lx\n", template[0].type); // TODO: there are other parameters for public keys, plus there is more if the key is RSA + DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); // TODO: there are other parameters for public keys, plus there is more if the key is RSA template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -633,11 +634,11 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE b_tmp[1024]; CK_ULONG ul_tmp; // TODO: fix elsewhere too CK_ULONG len = 0; - fprintf(stderr, "FOR PUBLIC KEY OBJECT %lu, I WANT ", obj); + DBG(("For public key object %lu, get ", obj)); switch (template->type) { case CKA_CLASS: - fprintf(stderr, "CLASS\n"); + DBG(("CLASS\n")); len = sizeof(CK_ULONG); ul_tmp = CKO_PUBLIC_KEY; data = (CK_BYTE_PTR) &ul_tmp; @@ -645,21 +646,21 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - fprintf(stderr, "TOKEN\n"); + DBG(("TOKEN\n")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].token; data = b_tmp; break; case CKA_PRIVATE: - fprintf(stderr, "PRIVATE\n"); + DBG(("PRIVATE\n")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].private; data = b_tmp; break; case CKA_LABEL: - fprintf(stderr, "LABEL\n"); + DBG(("LABEL\n")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; @@ -667,7 +668,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { // case CKA_VALUE: // TODO: this can be done with -r and -d|-a case CKA_KEY_TYPE: - fprintf(stderr, "KEY TYPE\n"); + DBG(("KEY TYPE\n")); len = sizeof(CK_ULONG); ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); if (ul_tmp == CKK_VENDOR_DEFINED) // This value is used as an error here @@ -676,55 +677,55 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_SUBJECT: - fprintf(stderr, "SUBJECT TODO\n"); // Default empty + DBG(("SUBJECT TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_ID: - fprintf(stderr, "ID\n"); + DBG(("ID\n")); len = sizeof(CK_BYTE); b_tmp[0] = piv_objects[obj].sub_id; data = b_tmp; break; case CKA_ENCRYPT: - fprintf(stderr, "ENCRYPT\n"); + DBG(("ENCRYPT\n")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].encrypt; data = b_tmp; break; case CKA_VERIFY: // TODO: what about verify recover ? - fprintf(stderr, "VERIFY\n"); + DBG(("VERIFY\n")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].verify; data = b_tmp; break; case CKA_WRAP: - fprintf(stderr, "WRAP\n"); + DBG(("WRAP\n")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].wrap; data = b_tmp; break; case CKA_DERIVE: - fprintf(stderr, "DERIVE\n"); + DBG(("DERIVE\n")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].derive; data = b_tmp; break; case CKA_START_DATE: - fprintf(stderr, "START DATE TODO\n"); // Default empty + DBG(("START DATE TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - fprintf(stderr, "END DATE TODO\n"); // Default empty + DBG(("END DATE TODO\n")); // Default empty return CKR_FUNCTION_FAILED; case CKA_EC_POINT: // We're trying to get the key length, get the ec point of the PUBLIC key - fprintf(stderr, "EC_POINT\n"); + DBG(("EC_POINT\n")); len = sizeof(b_tmp); if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; @@ -733,7 +734,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_EC_PARAMS: // Here we want the curve parameters (DER encoded OID) - fprintf(stderr, "EC_PARAMS\n"); + DBG(("EC_PARAMS\n")); len = sizeof(b_tmp); if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; @@ -741,27 +742,27 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_MODULUS_BITS: - fprintf(stderr, "MODULUS BITS\n"); + DBG(("MODULUS BITS\n")); len = sizeof(CK_ULONG); ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == 0) return CKR_FUNCTION_FAILED; data = (CK_BYTE_PTR) &ul_tmp; break; - + case CKA_LOCAL: - fprintf(stderr, "LOCAL TODO\n"); // Required + DBG(("LOCAL TODO\n")); // Required return CKR_FUNCTION_FAILED; case CKA_MODIFIABLE: - fprintf(stderr, "MODIFIABLE\n"); + DBG(("MODIFIABLE\n")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].modifiable; data = b_tmp; break; default: - fprintf(stderr, "UNKNOWN ATTRIBUTE!!!!! 0x%lx\n", template[0].type); // TODO: there are other parameters for public keys + DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); // TODO: there are other parameters for public keys template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -788,25 +789,25 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id) { switch(id) { case PIV_CERT_OBJ_X509_PIV_AUTH: return YKPIV_OBJ_AUTHENTICATION; - + case PIV_CERT_OBJ_X509_CARD_AUTH: return YKPIV_OBJ_CARD_AUTH; - + case PIV_CERT_OBJ_X509_DS: return YKPIV_OBJ_SIGNATURE; - + case PIV_CERT_OBJ_X509_KM: return YKPIV_OBJ_KEY_MANAGEMENT; case PIV_PVTK_OBJ_PIV_AUTH: return YKPIV_KEY_AUTHENTICATION; - + case PIV_PVTK_OBJ_CARD_AUTH: return YKPIV_KEY_CARDAUTH; - + case PIV_PVTK_OBJ_DS: return YKPIV_KEY_SIGNATURE; - + case PIV_PVTK_OBJ_KM: return YKPIV_KEY_KEYMGM; @@ -891,7 +892,7 @@ CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE) cert_ids[j++] = s->slot->token->objects[i]; - fprintf(stderr, "Just to check: %lu %lu\n", j, n_certs); + DBG(("Just to check: %lu %lu\n", j, n_certs)); return CKR_OK; } @@ -910,4 +911,3 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) { return CKR_OK; } - diff --git a/ykcs11/objects.h b/ykcs11/objects.h index e87f1df..cbc3b0e 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -3,8 +3,6 @@ #include "ykcs11.h" -#include // TODO: delete - CK_ULONG piv_2_ykpiv(piv_obj_id_t id); CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 1b30237..2d8bb3f 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -115,8 +115,8 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { /*BN_bn2bin(rsa->n, data); *len = 256;*/ - fprintf(stderr, "Public key is: \n"); - dump_hex(data, *len, stderr, CK_TRUE); + /* fprintf(stderr, "Public key is: \n"); */ + /* dump_hex(data, *len, stderr, CK_TRUE); */ break; @@ -125,8 +125,16 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { ecg = EC_KEY_get0_group(eck); ecp = EC_KEY_get0_public_key(eck); - if ((*len = EC_POINT_point2oct(ecg, ecp, pcf, data, *len, NULL)) == 0) + // Adde the DER structure with length after extracting the point + data[0] = 0x04; + + if ((*len = EC_POINT_point2oct(ecg, ecp, pcf, data + 2, *len - 2, NULL)) == 0) return CKR_FUNCTION_FAILED; + + data[1] = *len; + + *len += 2; + break; default: @@ -178,7 +186,7 @@ CK_RV free_key(EVP_PKEY *key) { CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len) { key_len /= 8; - fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len); + DBG(("Apply padding to %lu bytes and get %lu\n", in_len, key_len)); // TODO: rand must be seeded first (should be automatic) if (*out_len < key_len) @@ -215,13 +223,13 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, if (*out_len < RSA_size(key)) CKR_BUFFER_TOO_SMALL; - fprintf(stderr, "Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key)); + DBG(("Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key))); if (RSA_padding_add_PKCS1_PSS(key, em, in, EVP_get_digestbynid(nid), -2) == 0) return CKR_FUNCTION_FAILED; *out_len = RSA_size(key); - printf("hello!!!!!!!\n"); + return CKR_OK; } diff --git a/ykcs11/utils.c b/ykcs11/utils.c index add1aef..00eb483 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -90,12 +90,11 @@ failure: return CKR_FUNCTION_FAILED; } -#include // TODO: Delete + CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { token_vendor_t token; CK_TOKEN_INFO_PTR t_info; - fprintf(stderr, "Now trying to get token info from %s\n", p); // TODO: is p needed? slot->token = malloc(sizeof(ykcs11_token_t)); // TODO: free if (slot->token == NULL) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 3540215..30235a6 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1,6 +1,5 @@ #include "ykcs11.h" //#include "pkcs11.h" -#include #include #include #include @@ -8,15 +7,7 @@ #include "utils.h" #include "mechanisms.h" #include "openssl_types.h" - -#define D(x) do { \ - printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ - printf x; \ - printf ("\n"); \ - } while (0) - -#define YKCS11_DBG 0 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 +#include "debug.h" #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" @@ -29,21 +20,6 @@ #define YKCS11_SESSION_ID 5355104 - -#if YKCS11_DBG -#define DBG(x) D(x); -#else -#define DBG(x) -#endif - -#if YKCS11_DINOUT -#define DIN D(("In")); -#define DOUT D(("Out")); -#else -#define DIN -#define DOUT -#endif - static ykpiv_state *piv_state = NULL; static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; // TODO: build at runtime? @@ -1292,8 +1268,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_KEY_HANDLE_INVALID; } - // The buffer contains an uncompressed point of the form 04, x, y - // TODO: is this a fine representation for an EC public key? + // The buffer contains an uncompressed point of the form 04, len, 04, x, y + op_info.op.sign.key_len = ((template[3].ulValueLen - 1) / 2) * 8; if (op_info.op.sign.key_len == 256) diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index e7aad07..fc09edc 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -1,6 +1,7 @@ #include "yubico_token.h" #include "pkcs11.h" #include +#include "debug.h" #define YUBICO_MECHANISMS_NUM 5 @@ -209,7 +210,7 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P return CKR_MECHANISM_INVALID; } -#include // TODO: delete + static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *obj, CK_ULONG_PTR len, CK_ULONG_PTR num_certs) { CK_BYTE buf[2048]; @@ -232,7 +233,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_PIV_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_PIV_AUTH; n_cert++; - fprintf(stderr, "Found AUTH cert (9a)\n"); + DBG(("Found AUTH cert (9a)\n")); } buf_len = sizeof(buf); @@ -241,7 +242,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_CARD_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_CARD_AUTH; n_cert++; - fprintf(stderr, "Found CARD AUTH cert (9e)\n"); + DBG(("Found CARD AUTH cert (9e)\n")); } buf_len = sizeof(buf); @@ -250,7 +251,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_DS; pubkeys[n_cert] = PIV_PUBK_OBJ_DS; n_cert++; - fprintf(stderr, "Found SIGNATURE cert (9c)\n"); + DBG(("Found SIGNATURE cert (9c)\n")); } buf_len = sizeof(buf); @@ -259,10 +260,10 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_KM; pubkeys[n_cert] = PIV_PUBK_OBJ_KM; n_cert++; - fprintf(stderr, "Found KMK cert (9d)\n"); + DBG(("Found KMK cert (9d)\n")); } - fprintf(stderr, "The total number of objects for this token is %lu\n", (n_cert * 3) + token_objects_num); + DBG(("The total number of objects for this token is %lu\n", (n_cert * 3) + token_objects_num)); if (num_only == CK_TRUE) { // We just want the number of objects From 5bef13acece5ef4462e1573cb4930183e18c257b Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 7 Aug 2015 17:09:09 +0200 Subject: [PATCH 051/134] First stab at key generation. --- ykcs11/debug.h | 6 +- ykcs11/mechanisms.c | 163 ++++++++++++++++++++++++++++++++++++++++- ykcs11/mechanisms.h | 4 + ykcs11/objects.c | 130 ++++++++++++++++---------------- ykcs11/openssl_utils.c | 1 + ykcs11/token_vendors.c | 45 ++++++++++++ ykcs11/token_vendors.h | 6 ++ ykcs11/ykcs11.c | 161 +++++++++++++++++++++++++++++++--------- ykcs11/ykcs11.h | 12 ++- ykcs11/yubico_token.c | 10 +-- 10 files changed, 428 insertions(+), 110 deletions(-) diff --git a/ykcs11/debug.h b/ykcs11/debug.h index 946fc25..a89f49c 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -1,15 +1,15 @@ #ifndef DEBUG_H #define DEBUG_H +#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 { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ printf x; \ printf ("\n"); \ } while (0) -#define YKCS11_DBG 0 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 - #if YKCS11_DBG #include #define DBG(x) D(x); diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index bec71a3..1e94f39 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -17,6 +17,13 @@ static const CK_MECHANISM_TYPE sign_mechanisms[] = { CKM_ECDSA_SHA1 }; +// Supported mechanisms for key pair generation +static const CK_MECHANISM_TYPE generation_mechanisms[] = { + CKM_RSA_PKCS_KEY_PAIR_GEN, + //CKM_ECDSA_KEY_PAIR_GEN, Deperecated + CKM_EC_KEY_PAIR_GEN +}; + CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) { CK_ULONG i; @@ -40,9 +47,9 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK) return CKR_MECHANISM_INVALID; - // TODO: also check that parametes make sense if any? + // TODO: also check that parametes make sense if any? And key size is in [min max] - CKR_OK; + return CKR_OK; } @@ -289,3 +296,155 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { return CKR_FUNCTION_FAILED; } } + +CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) { + + CK_ULONG i; + CK_BBOOL supported = CK_FALSE; + token_vendor_t token; + CK_MECHANISM_INFO info; + + // Check if the mechanism is supported by the module + for (i = 0; i < sizeof(generation_mechanisms) / sizeof(CK_MECHANISM_TYPE); i++) { + if (m->mechanism == generation_mechanisms[i]) { + supported = CK_TRUE; + break; + } + } + if (supported == CK_FALSE) + return CKR_MECHANISM_INVALID; + + // Check if the mechanism is supported by the token + token = get_token_vendor(s->slot->token->vid); + + if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK) + return CKR_MECHANISM_INVALID; + + // TODO: also check that parametes make sense if any? And key size is in [min max] + + return CKR_OK; + +} + +CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) { + + CK_ULONG i; + CK_BBOOL rsa_mechanism; + + op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism); + + for (i = 0; i < n; i++) { + switch (templ[i].type) { + case CKA_CLASS: + if (*((CK_ULONG_PTR) templ[i].pValue) != CKO_PUBLIC_KEY) + return CKR_TEMPLATE_INCONSISTENT; + + break; + + case CKA_KEY_TYPE: + if ((op_info->op.gen.rsa == CK_TRUE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_RSA) || + (op_info->op.gen.rsa == CK_FALSE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_ECDSA)) + return CKR_TEMPLATE_INCONSISTENT; + + break; + + case CKA_PUBLIC_EXPONENT: + if (op_info->op.gen.rsa == CK_FALSE) + return CKR_MECHANISM_PARAM_INVALID; + + // Only support F4 + if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, "\x01\x00\x01", 3) != 0) + return CKR_MECHANISM_PARAM_INVALID; + + break; + + case CKA_MODULUS_BITS: + if (op_info->op.gen.rsa == CK_FALSE) + return CKR_MECHANISM_PARAM_INVALID; + + if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 && + *((CK_ULONG_PTR) templ[i].pValue) != 2048) // TODO: make define? + return CKR_MECHANISM_PARAM_INVALID; + + op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); // TODO: check length? + break; + + case CKA_ID: + // TODO: get pvt key with attributed id and store it's id into op_info + + case CKA_TOKEN: + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_WRAP: + // Ignore these attributes for now + break; + + default: + return CKR_MECHANISM_PARAM_INVALID; + } + } + + return CKR_OK; + +} + +CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) { + + CK_ULONG i; + CK_BBOOL rsa_mechanism; + + op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism); + + for (i = 0; i < n; i++) { + switch (templ[i].type) { + case CKA_CLASS: + if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_PRIVATE_KEY) + return CKR_TEMPLATE_INCONSISTENT; + + break; + + case CKA_KEY_TYPE: + if ((op_info->op.gen.rsa == CK_TRUE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_RSA) || + (op_info->op.gen.rsa == CK_FALSE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_ECDSA)) + return CKR_TEMPLATE_INCONSISTENT; + + break; + + case CKA_PUBLIC_EXPONENT: + if (op_info->op.gen.rsa == CK_FALSE) + return CKR_MECHANISM_PARAM_INVALID; + + // Only support F4 + if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, "\x01\x00\x01", 3) != 0) + return CKR_MECHANISM_PARAM_INVALID; + + break; + + case CKA_MODULUS_BITS: + if (op_info->op.gen.rsa == CK_FALSE) + return CKR_MECHANISM_PARAM_INVALID; + + if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 && + *((CK_ULONG_PTR) templ[i].pValue) != 2048) // TODO: make define? + return CKR_MECHANISM_PARAM_INVALID; + + op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); // TODO: check length? + break; + + case CKA_SENSITIVE: + case CKA_DECRYPT: + case CKA_UNWRAP: + case CKA_SIGN: + case CKA_PRIVATE: + case CKA_TOKEN: + // Ignore these attributes for now + break; + + default: + return CKR_MECHANISM_PARAM_INVALID; + } + } + + return CKR_OK; + +} diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index 1869774..c49ca04 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -12,4 +12,8 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info); CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len); CK_RV apply_sign_mechanism_finalize(op_info_t *op_info); +CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); +CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); +CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); + #endif diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 8f0ff96..a72c2cb 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -264,7 +264,7 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { switch (template->type) { case CKA_CLASS: - DBG(("CLASS\n")); + DBG(("CLASS")); len = 1; tmp[0] = CKO_DATA; data = tmp; @@ -272,51 +272,51 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN\n")); + DBG(("TOKEN")); len = 1; tmp[0] = piv_objects[obj].token; data = tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE\n")); + DBG(("PRIVATE")); len = 1; tmp[0] = piv_objects[obj].private; data = tmp; break; case CKA_LABEL: - DBG(("LABEL\n")); + DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_APPLICATION: - DBG(("APPLICATION\n")); + DBG(("APPLICATION")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_VALUE: // TODO: this can be done with -r and -d|-a - DBG(("VALUE TODO!!!\n")); + DBG(("VALUE TODO!!!")); return CKR_FUNCTION_FAILED; case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? - DBG(("OID\n")); + DBG(("OID")); strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid); asn1_encode_oid(tmp, tmp, &len); data = tmp; break; case CKA_MODIFIABLE: - DBG(("MODIFIABLE\n")); + DBG(("MODIFIABLE")); len = 1; tmp[0] = piv_objects[obj].modifiable; data = tmp; break; default: - DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); + DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -347,7 +347,7 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above? case CKA_CLASS: - DBG(("CLASS\n")); + DBG(("CLASS")); len = 1; tmp[0] = CKO_CERTIFICATE; data = tmp; @@ -355,72 +355,72 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN\n")); + DBG(("TOKEN")); len = 1; tmp[0] = piv_objects[obj].token; data = tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE\n")); + DBG(("PRIVATE")); len = 1; tmp[0] = piv_objects[obj].private; data = tmp; break; case CKA_LABEL: - DBG(("LABEL\n")); + DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_VALUE: - DBG(("VALUE TODO\n")); + DBG(("VALUE TODO")); return CKR_FUNCTION_FAILED; case CKA_CERTIFICATE_TYPE: - DBG(("CERTIFICATE TYPE\n")); + DBG(("CERTIFICATE TYPE")); len = 1; tmp[0] = CKC_X_509; // Support only X.509 certs data = tmp; break; case CKA_ISSUER: - DBG(("ISSUER TODO\n")); // Default empty + DBG(("ISSUER TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_SERIAL_NUMBER: - DBG(("SERIAL NUMBER TODO\n")); // Default empty + DBG(("SERIAL NUMBER TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_SUBJECT: - DBG(("SUBJECT TODO\n")); // Required + DBG(("SUBJECT TODO")); // Required return CKR_FUNCTION_FAILED; case CKA_ID: - DBG(("ID\n")); + DBG(("ID")); len = 1; tmp[0] = piv_objects[obj].sub_id; data = tmp; break; case CKA_START_DATE: - DBG(("START DATE TODO\n")); // Default empty + DBG(("START DATE TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - DBG(("END DATE TODO\n")); // Default empty + DBG(("END DATE TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_MODIFIABLE: - DBG(("MODIFIABLE\n")); + DBG(("MODIFIABLE")); len = 1; tmp[0] = piv_objects[obj].modifiable; data = tmp; break; default: // TODO: there are other attributes for a (x509) certificate - DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); + DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -452,7 +452,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { switch (template->type) { case CKA_CLASS: - DBG(("CLASS\n")); + DBG(("CLASS")); len = sizeof(CK_ULONG); ul_tmp = CKO_PRIVATE_KEY; data = (CK_BYTE_PTR) &ul_tmp; @@ -460,27 +460,27 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN\n")); + DBG(("TOKEN")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].token; data = b_tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE\n")); + DBG(("PRIVATE")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].private; data = b_tmp; break; case CKA_LABEL: - DBG(("LABEL\n")); + DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; case CKA_KEY_TYPE: - DBG(("KEY TYPE\n")); + DBG(("KEY TYPE")); len = sizeof(CK_ULONG); ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == CKK_VENDOR_DEFINED) @@ -489,62 +489,62 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_SUBJECT: - DBG(("SUBJECT TODO\n")); // Default empty + DBG(("SUBJECT TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_ID: - DBG(("ID\n")); + DBG(("ID")); len = sizeof(CK_BYTE); ul_tmp = piv_objects[obj].sub_id; data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_SENSITIVE: - DBG(("SENSITIVE TODO\n")); // Default empty + DBG(("SENSITIVE TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_DECRYPT: - DBG(("DECRYPT\n")); // Default empty + DBG(("DECRYPT")); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].decrypt; data = b_tmp; break; case CKA_UNWRAP: - DBG(("UNWRAP\n")); // Default empty + DBG(("UNWRAP")); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].unwrap; data = b_tmp; break; case CKA_SIGN: - DBG(("SIGN\n")); // Default empty + DBG(("SIGN")); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].sign; data = b_tmp; break; case CKA_SIGN_RECOVER: - DBG(("SIGN RECOVER TODO\n")); // Default empty + DBG(("SIGN RECOVER TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_DERIVE: - DBG(("DERIVE\n")); // Default false + DBG(("DERIVE")); // Default false len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].derive; data = b_tmp; break; case CKA_START_DATE: - DBG(("START DATE TODO\n")); // Default empty + DBG(("START DATE TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - DBG(("END DATE TODO\n")); // Default empty + DBG(("END DATE TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_MODULUS: - DBG(("MODULUS\n")); + DBG(("MODULUS")); len = sizeof(b_tmp); if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; @@ -554,7 +554,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_EC_POINT: // We're trying to get the key length, get the ec point of the PUBLIC key // TODO: or just give an error and explicitly fetch the pubk len when needed - DBG(("EC_POINT\n")); + DBG(("EC_POINT")); len = sizeof(b_tmp); if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; @@ -562,7 +562,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_MODULUS_BITS: - DBG(("MODULUS BITS\n")); + DBG(("MODULUS BITS")); len = sizeof(CK_ULONG); ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == 0) @@ -584,21 +584,21 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* case CKA_VALUE_LEN: */ /* case CKA_EXTRACTABLE: */ case CKA_LOCAL: - DBG(("LOCAL TODO\n")); // Required + DBG(("LOCAL TODO")); // Required return CKR_FUNCTION_FAILED; /* case CKA_NEVER_EXTRACTABLE: */ /*case CKA_ALWAYS_SENSITIVE:*/ case CKA_ALWAYS_AUTHENTICATE: - DBG(("ALWAYS AUTHENTICATE\n")); + DBG(("ALWAYS AUTHENTICATE")); len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].always_auth; data = b_tmp; break; case CKA_MODIFIABLE: - DBG(("MODIFIABLE\n")); + DBG(("MODIFIABLE")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].modifiable; data = b_tmp; @@ -606,7 +606,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /*case CKA_VENDOR_DEFINED:*/ default: - DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); // TODO: there are other parameters for public keys, plus there is more if the key is RSA + DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); // TODO: there are other parameters for public keys, plus there is more if the key is RSA template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -638,7 +638,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { switch (template->type) { case CKA_CLASS: - DBG(("CLASS\n")); + DBG(("CLASS")); len = sizeof(CK_ULONG); ul_tmp = CKO_PUBLIC_KEY; data = (CK_BYTE_PTR) &ul_tmp; @@ -646,21 +646,21 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN\n")); + DBG(("TOKEN")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].token; data = b_tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE\n")); + DBG(("PRIVATE")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].private; data = b_tmp; break; case CKA_LABEL: - DBG(("LABEL\n")); + DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; data = piv_objects[obj].label; break; @@ -668,7 +668,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { // case CKA_VALUE: // TODO: this can be done with -r and -d|-a case CKA_KEY_TYPE: - DBG(("KEY TYPE\n")); + DBG(("KEY TYPE")); len = sizeof(CK_ULONG); ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); if (ul_tmp == CKK_VENDOR_DEFINED) // This value is used as an error here @@ -677,55 +677,55 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_SUBJECT: - DBG(("SUBJECT TODO\n")); // Default empty + DBG(("SUBJECT TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_ID: - DBG(("ID\n")); + DBG(("ID")); len = sizeof(CK_BYTE); b_tmp[0] = piv_objects[obj].sub_id; data = b_tmp; break; case CKA_ENCRYPT: - DBG(("ENCRYPT\n")); + DBG(("ENCRYPT")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].encrypt; data = b_tmp; break; case CKA_VERIFY: // TODO: what about verify recover ? - DBG(("VERIFY\n")); + DBG(("VERIFY")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].verify; data = b_tmp; break; case CKA_WRAP: - DBG(("WRAP\n")); + DBG(("WRAP")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].wrap; data = b_tmp; break; case CKA_DERIVE: - DBG(("DERIVE\n")); + DBG(("DERIVE")); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].derive; data = b_tmp; break; case CKA_START_DATE: - DBG(("START DATE TODO\n")); // Default empty + DBG(("START DATE TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - DBG(("END DATE TODO\n")); // Default empty + DBG(("END DATE TODO")); // Default empty return CKR_FUNCTION_FAILED; case CKA_EC_POINT: // We're trying to get the key length, get the ec point of the PUBLIC key - DBG(("EC_POINT\n")); + DBG(("EC_POINT")); len = sizeof(b_tmp); if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; @@ -734,7 +734,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_EC_PARAMS: // Here we want the curve parameters (DER encoded OID) - DBG(("EC_PARAMS\n")); + DBG(("EC_PARAMS")); len = sizeof(b_tmp); if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; @@ -742,7 +742,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_MODULUS_BITS: - DBG(("MODULUS BITS\n")); + DBG(("MODULUS BITS")); len = sizeof(CK_ULONG); ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == 0) @@ -751,18 +751,18 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_LOCAL: - DBG(("LOCAL TODO\n")); // Required + DBG(("LOCAL TODO")); // Required return CKR_FUNCTION_FAILED; case CKA_MODIFIABLE: - DBG(("MODIFIABLE\n")); + DBG(("MODIFIABLE")); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].modifiable; data = b_tmp; break; default: - DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); // TODO: there are other parameters for public keys + DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); // TODO: there are other parameters for public keys template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -892,7 +892,7 @@ CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE) cert_ids[j++] = s->slot->token->objects[i]; - DBG(("Just to check: %lu %lu\n", j, n_certs)); + DBG(("Just to check: %lu %lu", j, n_certs)); return CKR_OK; } diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 2d8bb3f..3eac7e2 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -1,6 +1,7 @@ #include "openssl_utils.h" #include #include "../tool/util.h" // TODO: share this better? +#include "debug.h" CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 7fd1bfc..96045b8 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -1,6 +1,49 @@ #include "token_vendors.h" #include "yubico_token.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 long recv_len = sizeof(data); + unsigned long received = 0; + int sw; + + templ[3] = key; + + in_data[0] = 0xac; + in_data[1] = 3; + in_data[2] = 0x80; + in_data[3] = 1; + + switch(key_len) { + case 2048: + in_data[4] = YKPIV_ALGO_RSA2048; + break; + + case 1024: + in_data[4] = YKPIV_ALGO_RSA1024; + break; + + case 256: + in_data[4] = YKPIV_ALGO_ECCP256; + break; + + default: + return CKR_FUNCTION_FAILED; + } + //DBG(("Generating key %x with algorithm %u and length %lu", templ[3], in_data[4], key_len)); + if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, &recv_len, &sw) != YKPIV_OK || + sw != 0x9000) + return CKR_DEVICE_ERROR; + + + /* to drop the 90 00 and the 7f 49 at the start */ + received += recv_len - 4; + return CKR_OK; +} + token_vendor_t get_token_vendor(vendor_id_t vid) { token_vendor_t v; @@ -18,6 +61,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_objects_num = YUBICO_get_token_objects_num; v.get_token_object_list = YUBICO_get_token_object_list; v.get_token_raw_certificate = YUBICO_get_token_raw_certificate; + v.token_generate_key = COMMON_token_generate_key; break; case UNKNOWN: @@ -34,6 +78,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_objects_num = NULL; v.get_token_object_list = NULL; v.get_token_raw_certificate = NULL; + v.token_generate_key = NULL; } return v; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 4df53e0..b143ca8 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -18,7 +18,12 @@ typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR, CK_ULONG_PTR); typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG); + +// Common token functions below +typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); + // TODO: replace all the common call with functions defined in .c that use libykpiv + typedef struct { get_t_label_f get_token_label; get_t_manufacturer_f get_token_manufacturer; @@ -32,6 +37,7 @@ typedef struct { get_t_objects_num_f get_token_objects_num; get_t_object_list_f get_token_object_list; get_t_raw_certificate_f get_token_raw_certificate; + t_generate_key_f token_generate_key; } token_vendor_t; token_vendor_t get_token_vendor(vendor_id_t vid); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 30235a6..78d881d 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -37,9 +37,6 @@ static struct { op_info_t op_info; -/*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tidy this up, also build at runtime (during open session)? And include inside a session struct? - static CK_ULONG n_token_objects = 0;*/ - extern CK_FUNCTION_LIST function_list; // TODO: check all return values /* General Purpose */ @@ -489,14 +486,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_HOST_MEMORY; } - // Save a list of all the available objects in the token // TODO: change behavior based on login status + // Save a list of all the available objects in the token rv = token.get_token_object_list(piv_state, session.slot->token->objects, session.slot->token->n_objects); if (rv != CKR_OK) { DBG(("Unable to retrieve token objects")); goto failure; } - // Get a list object ids for available certificates object from the session + // Get a list of object ids for available certificates object from the session rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); // TODO: better to get this from token? how? if (rv != CKR_OK) { DBG(("Unable to retrieve certificate ids from the session")); @@ -537,7 +534,7 @@ failure: cert_ids = NULL; } - free_certs(); // TODO + free_certs(); // TODO: remove the one allocated so far return rv; } @@ -659,14 +656,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (userType != CKU_USER && - userType != CKU_SO && + if (userType != CKU_SO && // TODO: what can SO do? + userType != CKU_USER && userType != CKU_CONTEXT_SPECIFIC) - return CKR_ARGUMENTS_BAD; - - if (ulPinLen < PIV_MIN_PIN_LEN || - ulPinLen > PIV_MAX_PIN_LEN) - return CKR_ARGUMENTS_BAD; + return CKR_USER_TYPE_INVALID; DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); @@ -678,11 +671,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; - if (userType != CKU_SO && // TODO: what can SO do? - userType != CKU_USER && - userType != CKU_CONTEXT_SPECIFIC) - return CKR_USER_TYPE_INVALID; - if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? DBG(("Tried to log-in to a read-only session")); return CKR_SESSION_READ_ONLY_EXISTS; @@ -690,17 +678,53 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( switch (userType) { case CKU_USER: - if (session.info.state == CKS_RW_USER_FUNCTIONS) + if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN) + return CKR_ARGUMENTS_BAD; + + if (session.info.state == CKS_RW_USER_FUNCTIONS) // TODO: make sure to set session default state as not logged return CKR_USER_ALREADY_LOGGED_IN; + if (session.info.state == CKS_RW_SO_FUNCTIONS) + return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; + tries = 0; if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { // TODO: call this from vendors.c DBG(("You loose! %lu", tries)); return CKR_PIN_INCORRECT; } + + if ((session.info.flags & CKF_RW_SESSION) == 0) // TODO: double check with the if line 678 for R/O + session.info.state = CKS_RO_USER_FUNCTIONS; + else + session.info.state = CKS_RW_USER_FUNCTIONS; break; case CKU_SO: + // TODO: check for mgmt key length? + if (session.info.state == CKS_RW_SO_FUNCTIONS) + return CKR_USER_ALREADY_LOGGED_IN; + + if (session.info.state == CKS_RO_USER_FUNCTIONS || + session.info.state == CKS_RW_USER_FUNCTIONS) + return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; + + /***** TODO: replace this with a token function *****/ + unsigned char key[24]; + size_t key_len = sizeof(key); + if(ykpiv_hex_decode(pPin, ulPinLen, key, &key_len) != YKPIV_OK) { + DBG(("Failed decoding key")); + return CKR_FUNCTION_FAILED; + } + + if(ykpiv_authenticate(piv_state, key) != YKPIV_OK) { + DBG(("Failed to authenticate")); + return CKR_PIN_INCORRECT; + } + /***************************************************/ + + session.info.state = CKS_RW_SO_FUNCTIONS; + break; + case CKU_CONTEXT_SPECIFIC: default: return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now @@ -708,11 +732,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( DBG(("You win! %lu", tries)); - if ((session.info.flags & CKF_RW_SESSION) == 0) - session.info.state = CKS_RO_USER_FUNCTIONS; - else - session.info.state = CKS_RW_USER_FUNCTIONS; - DOUT; return CKR_OK; } @@ -804,8 +823,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( if (pTemplate == NULL_PTR || ulCount == 0) return CKR_ARGUMENTS_BAD; - if (find_obj.active != CK_TRUE) - return CKR_OPERATION_NOT_INITIALIZED; + /*if (find_obj.active != CK_TRUE) + return CKR_OPERATION_NOT_INITIALIZED; actually this can be called from many other functions*/ rv_final = CKR_OK; for (i = 0; i < ulCount; i++) { @@ -1205,6 +1224,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( if (hSession != session.handle) return CKR_SESSION_HANDLE_INVALID; + if (op_info.type != YKCS11_NOOP) { + DBG(("Other operation in process")); + return CKR_OPERATION_ACTIVE; + } + if (pMechanism == NULL_PTR || hKey == NULL_PTR) return CKR_ARGUMENTS_BAD; @@ -1213,7 +1237,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( // Check if mechanism is supported if (check_sign_mechanism(&session, pMechanism) != CKR_OK) { - DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); + DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism)); return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that } memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); @@ -1282,7 +1306,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( DBG(("Key length is %lu bit", op_info.op.sign.key_len)); - op_info.op.sign.key_id = piv_2_ykpiv(hKey); + op_info.op.sign.key_id = piv_2_ykpiv(hKey); // TODO: have to set this!!! if (op_info.op.sign.key_id == 0) { DBG(("Incorrect key %lu", hKey)); return CKR_KEY_HANDLE_INVALID; @@ -1319,11 +1343,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( { DIN; - if (op_info.type == YKCS11_NOOP) + if (op_info.type != YKCS11_SIGN) { + DBG(("Signature operation not initialized")); return CKR_OPERATION_NOT_INITIALIZED; - - if (op_info.type != YKCS11_SIGN) - return CKR_OPERATION_ACTIVE; + } // TODO: check other conditions ykpiv_rc r; // TODO: delete this @@ -1564,7 +1587,79 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( ) { DIN; - DBG(("TODO!!!")); + CK_RV rv; + token_vendor_t token; + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); + return CKR_SESSION_CLOSED; + } + + if (hSession != session.handle) + return CKR_SESSION_HANDLE_INVALID; + + if (session.info.state != CKS_RW_SO_FUNCTIONS) { + DBG(("Authentication required to generate keys")); + return CKR_SESSION_READ_ONLY; + } + + if (op_info.type != YKCS11_NOOP) { + DBG(("Other operation in process")); + return CKR_OPERATION_ACTIVE; + } + + if (pMechanism == NULL_PTR || + pPublicKeyTemplate == NULL_PTR || + pPrivateKeyTemplate == NULL_PTR || + phPublicKey == NULL_PTR || + phPrivateKey == NULL_PTR) + return CKR_ARGUMENTS_BAD; + + DBG(("Trying to generate a key pair with mechanism %lu", pMechanism->mechanism)); + + DBG(("Found %lu attributes for the public key and %lu attributes for the private key", ulPublicKeyAttributeCount, ulPrivateKeyAttributeCount)); + + // Check if mechanism is supported + if ((rv = check_generation_mechanism(&session, pMechanism)) != CKR_OK) { + DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism)); + return rv; + } + memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); + + // Check the template for the public key + if ((rv = check_pubkey_template(&op_info, pPublicKeyTemplate, ulPublicKeyAttributeCount)) != CKR_OK) { + DBG(("Invalid public key template")); + return rv; + } + + // Check the template for the public key + if ((rv = check_pvtkey_template(&op_info, pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) != CKR_OK) { + DBG(("Invalid private key template")); + return rv; + } + + if (op_info.op.gen.key_len == 0) { + op_info.op.gen.key_len = 1024; // TODO: for testing purpose set it to rsa2048; + } + + if (op_info.op.gen.key_id == 0) { + op_info.op.gen.key_id = PIV_PVTK_OBJ_KM; // TODO: set default key or error? + } + + token = get_token_vendor(session.slot->token->vid); + + if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len)) != CKR_OK) { + DBG(("Unable to generate key pair")); + return rv; + } + + // TODO: save return object handlers + DOUT; return CKR_OK; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 5482b3c..96d3193 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -31,16 +31,23 @@ typedef struct { typedef enum { YKCS11_NOOP, + YKCS11_GEN, YKCS11_SIGN, YKCS11_HASH, YKCS11_DECRYPT } ykcs11_op_type_t; +typedef struct { + CK_BBOOL rsa; // RSA or EC key + CK_BYTE key_id; // Key id + CK_ULONG key_len; // Length in bits +} gen_info_t; + typedef struct { ykcs11_md_ctx_t *md_ctx; // Digest context CK_BYTE_PTR key; // Raw public key (needed for PSS) - CK_BYTE algo; // Algo for ykpiv - CK_ULONG key_id; // Key id for ykpiv + CK_BYTE algo; // Algo for ykpiv // TODO: infer this from the key length? + CK_ULONG key_id; // Key id for ykpiv // TODO: make this a ULONG and store the id {0, 1, 2, 3} CK_ULONG key_len; // Length in bits } sign_info_t; @@ -53,6 +60,7 @@ typedef struct { } decrypt_info_t; typedef union { + gen_info_t gen; sign_info_t sign; hash_info_t hash; decrypt_info_t decrypt; diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index fc09edc..93671e0 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -233,7 +233,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_PIV_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_PIV_AUTH; n_cert++; - DBG(("Found AUTH cert (9a)\n")); + DBG(("Found AUTH cert (9a)")); } buf_len = sizeof(buf); @@ -242,7 +242,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_CARD_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_CARD_AUTH; n_cert++; - DBG(("Found CARD AUTH cert (9e)\n")); + DBG(("Found CARD AUTH cert (9e)")); } buf_len = sizeof(buf); @@ -251,7 +251,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_DS; pubkeys[n_cert] = PIV_PUBK_OBJ_DS; n_cert++; - DBG(("Found SIGNATURE cert (9c)\n")); + DBG(("Found SIGNATURE cert (9c)")); } buf_len = sizeof(buf); @@ -260,10 +260,10 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_KM; pubkeys[n_cert] = PIV_PUBK_OBJ_KM; n_cert++; - DBG(("Found KMK cert (9d)\n")); + DBG(("Found KMK cert (9d)")); } - DBG(("The total number of objects for this token is %lu\n", (n_cert * 3) + token_objects_num)); + DBG(("The total number of objects for this token is %lu", (n_cert * 3) + token_objects_num)); if (num_only == CK_TRUE) { // We just want the number of objects From 097bfaf7a1c932baf781299b7e60c68cec1e1e18 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 11 Aug 2015 11:46:40 +0200 Subject: [PATCH 052/134] Added EC key generation. --- ykcs11/debug.h | 2 +- ykcs11/mechanisms.c | 64 +++++++++------ ykcs11/openssl_utils.c | 175 ++++++++++++++++++++++++++++++++++++++++- ykcs11/openssl_utils.h | 2 + ykcs11/pkcs11t.h | 4 + ykcs11/token_vendors.c | 8 ++ ykcs11/utils.c | 10 +++ ykcs11/utils.h | 2 + ykcs11/ykcs11.c | 42 ++++++---- ykcs11/ykcs11.h | 2 +- 10 files changed, 271 insertions(+), 40 deletions(-) diff --git a/ykcs11/debug.h b/ykcs11/debug.h index a89f49c..5debc5d 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -1,7 +1,7 @@ #ifndef DEBUG_H #define DEBUG_H -#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DBG 0 // 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/mechanisms.c b/ykcs11/mechanisms.c index 1e94f39..0012622 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -1,5 +1,8 @@ #include "mechanisms.h" +#define F4 "\x01\x00\x01" +#define PRIME256V1 "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" + // Supported mechanisms for signature static const CK_MECHANISM_TYPE sign_mechanisms[] = { CKM_RSA_PKCS, @@ -264,7 +267,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); if (rv != CKR_OK) return CKR_FUNCTION_FAILED; - DBG(("The hashed value is %lu long and looks like\n", op_info->buf_len)); +// DBG(("The hashed value is %lu long and looks like\n", op_info->buf_len)); dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); case CKM_RSA_PKCS: @@ -274,7 +277,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { if (rv != CKR_OK) return CKR_FUNCTION_FAILED; - DBG(("After adding digestinfo is %lu long and looks like\n", op_info->buf_len)); +// DBG(("After adding digestinfo is %lu long and looks like\n", op_info->buf_len)); dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); } @@ -350,27 +353,39 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG case CKA_PUBLIC_EXPONENT: if (op_info->op.gen.rsa == CK_FALSE) - return CKR_MECHANISM_PARAM_INVALID; + return CKR_ATTRIBUTE_VALUE_INVALID; // Only support F4 - if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, "\x01\x00\x01", 3) != 0) - return CKR_MECHANISM_PARAM_INVALID; + if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0) + return CKR_ATTRIBUTE_VALUE_INVALID; break; case CKA_MODULUS_BITS: if (op_info->op.gen.rsa == CK_FALSE) - return CKR_MECHANISM_PARAM_INVALID; + return CKR_ATTRIBUTE_VALUE_INVALID; if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 && *((CK_ULONG_PTR) templ[i].pValue) != 2048) // TODO: make define? - return CKR_MECHANISM_PARAM_INVALID; + return CKR_ATTRIBUTE_VALUE_INVALID; - op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); // TODO: check length? + op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); + break; + + case CKA_EC_PARAMS: + // Only support PRIME256V1 + if (templ[i].ulValueLen != 10 || memcmp((CK_BYTE_PTR)templ[i].pValue, PRIME256V1, 10) != 0) + return CKR_CURVE_NOT_SUPPORTED; + + op_info->op.gen.key_len = 256; break; case CKA_ID: - // TODO: get pvt key with attributed id and store it's id into op_info + if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE) + return CKR_ATTRIBUTE_VALUE_INVALID; + + op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue); + break; case CKA_TOKEN: case CKA_ENCRYPT: @@ -378,9 +393,9 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG case CKA_WRAP: // Ignore these attributes for now break; - + default: - return CKR_MECHANISM_PARAM_INVALID; + return CKR_ATTRIBUTE_VALUE_INVALID; } } @@ -410,17 +425,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG break; - case CKA_PUBLIC_EXPONENT: - if (op_info->op.gen.rsa == CK_FALSE) - return CKR_MECHANISM_PARAM_INVALID; - - // Only support F4 - if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, "\x01\x00\x01", 3) != 0) - return CKR_MECHANISM_PARAM_INVALID; - - break; - - case CKA_MODULUS_BITS: +/* case CKA_MODULUS_BITS: if (op_info->op.gen.rsa == CK_FALSE) return CKR_MECHANISM_PARAM_INVALID; @@ -429,6 +434,19 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG return CKR_MECHANISM_PARAM_INVALID; op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); // TODO: check length? + break;*/ + + case CKA_ID: + if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE) + return CKR_ATTRIBUTE_VALUE_INVALID; + + // Check if ID was already specified in the public key template + // In that case it has to match + if (op_info->op.gen.key_id != 0 && + op_info->op.gen.key_id != (*((CK_BYTE_PTR)templ[i].pValue) + PIV_PVTK_OBJ_PIV_AUTH)) + return CKR_TEMPLATE_INCONSISTENT; + + op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue); break; case CKA_SENSITIVE: @@ -441,7 +459,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG break; default: - return CKR_MECHANISM_PARAM_INVALID; + return CKR_ATTRIBUTE_VALUE_INVALID; } } diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 3eac7e2..f4e8964 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -3,7 +3,6 @@ #include "../tool/util.h" // TODO: share this better? #include "debug.h" - CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { const unsigned char *p = data; // Mandatory temp variable required by OpenSSL @@ -34,6 +33,177 @@ 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) { + + X509 *cert = NULL; + EVP_PKEY *key = NULL; + RSA *rsa = NULL; + BIGNUM *bignum_n = NULL; + BIGNUM *bignum_e = NULL; + EC_KEY *eck = NULL; + EC_GROUP *ecg = NULL; + EC_POINT *ecp = NULL; + ASN1_TIME *tm = NULL; + time_t t; + + unsigned char *data_ptr; + unsigned char *p; + int len; + + CK_RV rv = CKR_FUNCTION_FAILED; + + cert = X509_new(); + if (cert == NULL) + goto create_empty_cert_cleanup; + + key = EVP_PKEY_new(); + if (key == NULL) + goto create_empty_cert_cleanup; + + if (is_rsa) { + // RSA + rsa = RSA_new(); + if (rsa == NULL) + 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; + + data_ptr++; + data_ptr += get_length(data_ptr, &len); + bignum_n = BN_bin2bn(data_ptr, len, NULL); + if(bignum_n == NULL) + goto create_empty_cert_cleanup; + + data_ptr += len; + + if(*data_ptr != 0x82) + goto create_empty_cert_cleanup; + + data_ptr++; + data_ptr += get_length(data_ptr, &len); + bignum_e = BN_bin2bn(data_ptr, len, NULL); + if(bignum_e == NULL) + goto create_empty_cert_cleanup; + + rsa->n = bignum_n; + rsa->e = bignum_e; + + if (EVP_PKEY_set1_RSA(key, rsa) == 0) + goto create_empty_cert_cleanup; + } + else { + // ECCP256 + data_ptr = in + 3; + + eck = EC_KEY_new(); + if (eck == NULL) + goto create_empty_cert_cleanup; + + ecg = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + if (ecg == NULL) + goto create_empty_cert_cleanup; + + EC_GROUP_set_asn1_flag(ecg, NID_X9_62_prime256v1); + EC_KEY_set_group(eck, ecg); + ecp = EC_POINT_new(ecg); + + if(*data_ptr++ != 0x86) + goto create_empty_cert_cleanup; + + // The curve point should always be 65 bytes + if(*data_ptr++ != 65) + goto create_empty_cert_cleanup; + + if(EC_POINT_oct2point(ecg, ecp, data_ptr, 65, NULL) == 0) + goto create_empty_cert_cleanup; + + if(EC_KEY_set_public_key(eck, ecp) == 0) + goto create_empty_cert_cleanup; + + if (EVP_PKEY_set1_EC_KEY(key, eck) == 0) + goto create_empty_cert_cleanup; + } + + 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) + goto create_empty_cert_cleanup; + + ASN1_TIME_set_string(tm, "000001010000Z"); + X509_set_notBefore(cert, tm); + X509_set_notAfter(cert, tm); + + /* TODO REMOVE THIS */ + BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE); + + X509_print_ex(STDout, cert, 0, 0); + + BIO_free(STDout); + /********************/ + + rv = CKR_OK; + +create_empty_cert_cleanup: + + if (tm != NULL) { + ASN1_STRING_free(tm); + tm = NULL; + } + + if (bignum_n != NULL) { + BN_free(bignum_n); + bignum_n = NULL; + } + + if (bignum_e != NULL) { + BN_free(bignum_e); + bignum_e = NULL; + } + +/* if (rsa != NULL) { // TODO: adding this generates an error. Automatically free'd by EVP_PKEY_free ? + RSA_free(rsa); + rsa = NULL; + }*/ + + if (ecp != NULL) { + EC_POINT_free(ecp); + ecp = NULL; + } + + if (ecg != NULL) { + EC_GROUP_free(ecg); + ecg = NULL; + } + + if (eck != NULL) { + EC_KEY_free(eck); + eck = NULL; + } + + if (key != NULL) { + EVP_PKEY_free(key); + key = NULL; + } + + if (cert != NULL) { + X509_free(cert); + cert = NULL; + } + + return rv; +} CK_RV free_cert(X509 *cert) { @@ -142,6 +312,9 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { return CKR_FUNCTION_FAILED; } + EC_KEY_free(eck); + eck = NULL; + return CKR_OK; } diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index e146001..c29fd18 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -10,6 +10,8 @@ #include "pkcs11t.h" CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); +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); CK_RV free_cert(X509 *cert); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index 7ced074..5b64d63 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -838,6 +838,10 @@ typedef CK_ULONG CK_RV; /* These are new to v2.0 */ #define CKR_RANDOM_NO_RNG 0x00000121UL +/* Next two are new for v2.2 */ +#define CKR_DOMAIN_PARAMS_INVALID 0x00000130UL +#define CKR_CURVE_NOT_SUPPORTED 0x00000140UL +/* ************************* */ #define CKR_BUFFER_TOO_SMALL 0x00000150UL #define CKR_SAVED_STATE_INVALID 0x00000160UL #define CKR_INFORMATION_SENSITIVE 0x00000170UL diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 96045b8..f6b285e 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -10,6 +10,8 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE unsigned long received = 0; int sw; + CK_RV rv; + templ[3] = key; in_data[0] = 0xac; @@ -41,6 +43,12 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE /* 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) + return rv; + return CKR_OK; } diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 00eb483..170fd37 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -165,3 +165,13 @@ void destroy_token(ykcs11_slot_t *slot) { free(slot->token); slot->token = NULL; } + +CK_BBOOL is_valid_key_id(CK_BYTE id) { + + // Valid ids are 0, 1, 2, 3 + if (id > 3) + return CK_FALSE; + + return CK_TRUE; + +} diff --git a/ykcs11/utils.h b/ykcs11/utils.h index 5bcb8db..8ada4dc 100644 --- a/ykcs11/utils.h +++ b/ykcs11/utils.h @@ -9,4 +9,6 @@ CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot); void destroy_token(ykcs11_slot_t *slot); +CK_BBOOL is_valid_key_id(CK_BYTE id); + #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 78d881d..1200018 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -534,7 +534,7 @@ failure: cert_ids = NULL; } - free_certs(); // TODO: remove the one allocated so far + //free_certs(); // TODO: remove the one allocated so far return rv; } @@ -680,7 +680,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( case CKU_USER: if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN) return CKR_ARGUMENTS_BAD; - + if (session.info.state == CKS_RW_USER_FUNCTIONS) // TODO: make sure to set session default state as not logged return CKR_USER_ALREADY_LOGGED_IN; @@ -866,7 +866,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( CK_ULONG j; CK_ULONG total; CK_BBOOL private; - + if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -925,7 +925,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( total--; continue; } - + for (j = 0; j < ulCount; j++) { DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", j, pTemplate[j].type, *((CK_ULONG_PTR)pTemplate[j].pValue), pTemplate[j].ulValueLen)); @@ -941,9 +941,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( } DBG(("%lu object(s) left after attribute matching", total)); - + find_obj.active = CK_TRUE; - + DOUT; return CKR_OK; } @@ -984,7 +984,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( while(find_obj.idx < find_obj.num && find_obj.objects[find_obj.idx] == OBJECT_INVALID) find_obj.idx++; - + if (find_obj.idx == find_obj.num) { *pulObjectCount = 0; DOUT; @@ -1272,7 +1272,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_HOST_MEMORY; template[2].pValue = op_info.op.sign.key; - template[2].ulValueLen = key_len; + template[2].ulValueLen = key_len; if (get_attribute(&session, hKey, template + 2) != CKR_OK) { DBG(("Unable to get public key")); @@ -1620,7 +1620,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( phPrivateKey == NULL_PTR) return CKR_ARGUMENTS_BAD; - DBG(("Trying to generate a key pair with mechanism %lu", pMechanism->mechanism)); + DBG(("Trying to generate a key pair with mechanism %lx", pMechanism->mechanism)); DBG(("Found %lu attributes for the public key and %lu attributes for the private key", ulPublicKeyAttributeCount, ulPrivateKeyAttributeCount)); @@ -1631,24 +1631,37 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( } memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); + // Clear values + op_info.op.gen.key_len = 0; + op_info.op.gen.key_id = 0; + // Check the template for the public key if ((rv = check_pubkey_template(&op_info, pPublicKeyTemplate, ulPublicKeyAttributeCount)) != CKR_OK) { DBG(("Invalid public key template")); return rv; } - // Check the template for the public key + // Check the template for the private key if ((rv = check_pvtkey_template(&op_info, pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) != CKR_OK) { DBG(("Invalid private key template")); return rv; } if (op_info.op.gen.key_len == 0) { - op_info.op.gen.key_len = 1024; // TODO: for testing purpose set it to rsa2048; + DBG(("Key length not specified")); + return CKR_TEMPLATE_INCOMPLETE; } if (op_info.op.gen.key_id == 0) { - op_info.op.gen.key_id = PIV_PVTK_OBJ_KM; // TODO: set default key or error? + DBG(("Key id not specified, using default value")); + return CKR_TEMPLATE_INCOMPLETE; + } + + if (op_info.op.gen.rsa) { + DBG(("Generating %lu bit RSA key in object %u", op_info.op.gen.key_len, op_info.op.gen.key_id)); + } + else { + DBG(("Generating %lu bit EC key in object %u", op_info.op.gen.key_len, op_info.op.gen.key_id)); } token = get_token_vendor(session.slot->token->vid); @@ -1658,8 +1671,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( return rv; } - // TODO: save return object handlers - + *phPrivateKey = op_info.op.gen.key_id; + *phPublicKey = op_info.op.gen.key_id - PIV_PVTK_OBJ_KM + PIV_PUBK_OBJ_KM; // TODO: make function for these? + DOUT; return CKR_OK; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 96d3193..057c155 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -47,7 +47,7 @@ typedef struct { ykcs11_md_ctx_t *md_ctx; // Digest context CK_BYTE_PTR key; // Raw public key (needed for PSS) CK_BYTE algo; // Algo for ykpiv // TODO: infer this from the key length? - CK_ULONG key_id; // Key id for ykpiv // TODO: make this a ULONG and store the id {0, 1, 2, 3} + CK_ULONG key_id; // Key id for ykpiv // TODO: make this a BYTE and store the id {0, 1, 2, 3} CK_ULONG key_len; // Length in bits } sign_info_t; From bf56cd8f3097d57b7fd5ac2c4425427fc8deb3ee Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 11 Aug 2015 14:12:34 +0200 Subject: [PATCH 053/134] Added certificate import on key generation. --- tool/util.c | 22 +++++++++++++++ tool/util.h | 1 + ykcs11/debug.h | 2 +- ykcs11/openssl_utils.c | 22 ++++++++++----- ykcs11/token_vendors.c | 61 +++++++++++++++++++++++++++++++++--------- 5 files changed, 87 insertions(+), 21 deletions(-) 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; } From 2a6acc5259f30cb95bcac21e706b74be47799c09 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 11 Aug 2015 16:28:59 +0200 Subject: [PATCH 054/134] Update object in the session after key creation (if object already exists). --- ykcs11/debug.h | 2 +- ykcs11/objects.c | 2 +- ykcs11/openssl_utils.c | 6 ++-- ykcs11/token_vendors.c | 2 -- ykcs11/ykcs11.c | 68 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/ykcs11/debug.h b/ykcs11/debug.h index a89f49c..5debc5d 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -1,7 +1,7 @@ #ifndef DEBUG_H #define DEBUG_H -#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DBG 0 // 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/objects.c b/ykcs11/objects.c index a72c2cb..ba02f67 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -58,7 +58,7 @@ static piv_obj_t piv_objects[] = { {PIV_CERT_OBJ_X509_CARD_AUTH, 1, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, get_coa, 1}, {PIV_CERT_OBJ_X509_DS, 1, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, get_coa, 2}, {PIV_CERT_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_coa, 3}, - {PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, get_coa, 4}, + {PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4}, {PIV_PVTK_OBJ_PIV_AUTH, 1, 1, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, // 9a {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Private key for Card Authentication", 0, 0, get_proa, 1}, // 9e diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index cea47c8..3f2c9cf 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -115,13 +115,13 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ goto create_empty_cert_cleanup; // The curve point should always be 65 bytes - if(*data_ptr++ != 65) + if (*data_ptr++ != 65) goto create_empty_cert_cleanup; - if(EC_POINT_oct2point(ecg, ecp, data_ptr, 65, NULL) == 0) + if (EC_POINT_oct2point(ecg, ecp, data_ptr, 65, NULL) == 0) goto create_empty_cert_cleanup; - if(EC_KEY_set_public_key(eck, ecp) == 0) + if (EC_KEY_set_public_key(eck, ecp) == 0) goto create_empty_cert_cleanup; if (EVP_PKEY_set1_EC_KEY(key, eck) == 0) diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 1571182..083aea2 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -78,8 +78,6 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE *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; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 1200018..57835d4 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -502,7 +502,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( // Get the actual certificate data from the token and store it as an X509 object for (i = 0; i < session.slot->token->n_certs; i++) { - rv = token.get_token_raw_certificate(piv_state, cert_ids[i], cert_data, cert_len); + rv = token.get_token_raw_certificate(piv_state, cert_ids[i], cert_data, cert_len); // TODO: double check len here (check inside, never changed but used below) if (rv != CKR_OK) { DBG(("Unable to get certificate data from token")); goto failure; @@ -1589,6 +1589,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( DIN; CK_RV rv; token_vendor_t token; + CK_ULONG n_objs; + CK_ULONG n_certs; + CK_ULONG i; + CK_BBOOL is_new; + CK_ULONG dobj_id; + CK_ULONG cert_id; + CK_ULONG pvtk_id; + CK_ULONG pubk_id; + piv_obj_id_t *obj_ptr; + CK_BYTE cert_data[2100]; + CK_ULONG cert_len; + if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -1671,6 +1683,60 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( return rv; } + rv = token.get_token_objects_num(piv_state, &n_objs, &n_certs); + if (rv != CKR_OK) { + DBG(("Unable to retrieve token objects")); + return rv; + } + DBG(("There were %lu objs and %lu certs, there are %lu objs and %lu certs", session.slot->token->n_objects, session.slot->token->n_certs, n_objs, n_certs)); + + is_new = CK_TRUE; + for (i = 0; i < session.slot->token->n_objects; i++) { + if (session.slot->token->objects[i] == op_info.op.gen.key_id) + is_new = CK_FALSE; + } + + dobj_id = op_info.op.gen.key_id - PIV_PVTK_OBJ_PIV_AUTH; // TODO: make function for these + cert_id = PIV_DATA_OBJ_LAST + 1 + dobj_id; + pvtk_id = op_info.op.gen.key_id; + pubk_id = PIV_PVTK_OBJ_LAST + 1 + dobj_id; + + // Check whether we created a new object or updated an existing one + if (is_new == CK_TRUE) { + // New object created + DBG(("OBJECT NOT FOUND!")); + } + else { + // Updated old object + cert_len = sizeof(cert_data); + rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, cert_len); // TODO: double check len here (check inside, never changed but used below). One more time above + if (rv != CKR_OK) { + DBG(("Unable to get certificate data from token")); + return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point + } + + rv = store_cert(cert_id, cert_data, cert_len); + if (rv != CKR_OK) { + DBG(("Unable to store certificate data")); + return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point + } + + /*session.slot->token->n_objects += 4; + session.slot->token->n_certs++; + + obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); + if (obj_ptr == NULL) { + DBG(("Unable to store new item in the session")); + return CKR_HOST_MEMORY; + } + + obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 4; + *obj_ptr++ = dobj_id; + *obj_ptr++ = cert_id; + *obj_ptr++ = pvtk_id; + *obj_ptr++ = pubk_id;*/ + } + *phPrivateKey = op_info.op.gen.key_id; *phPublicKey = op_info.op.gen.key_id - PIV_PVTK_OBJ_KM + PIV_PUBK_OBJ_KM; // TODO: make function for these? From 4010ebbb9176cc7b99da2160612fde5fda93c11a Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 11 Aug 2015 16:54:25 +0200 Subject: [PATCH 055/134] Update object in the session (when the object wasn't there to begin with). --- ykcs11/ykcs11.c | 71 ++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 57835d4..bd9db35 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -559,10 +559,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; } - + DBG(("HI")); free(session.slot->token->objects); // TODO: make objects survive a session so there is no need to get them again? session.slot->token->objects = NULL; - + DBG(("HI2")); memset(&session, 0, sizeof(ykcs11_session_t)); session.handle = CK_INVALID_HANDLE; @@ -1683,12 +1683,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( return rv; } - rv = token.get_token_objects_num(piv_state, &n_objs, &n_certs); - if (rv != CKR_OK) { - DBG(("Unable to retrieve token objects")); - return rv; - } - DBG(("There were %lu objs and %lu certs, there are %lu objs and %lu certs", session.slot->token->n_objects, session.slot->token->n_certs, n_objs, n_certs)); + /* rv = token.get_token_objects_num(piv_state, &n_objs, &n_certs); */ + /* if (rv != CKR_OK) { */ + /* DBG(("Unable to retrieve token objects")); */ + /* return rv; */ + /* } */ + /* DBG(("There were %lu objs and %lu certs, there are %lu objs and %lu certs", session.slot->token->n_objects, session.slot->token->n_certs, n_objs, n_certs)); */ is_new = CK_TRUE; for (i = 0; i < session.slot->token->n_objects; i++) { @@ -1703,25 +1703,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( // Check whether we created a new object or updated an existing one if (is_new == CK_TRUE) { - // New object created - DBG(("OBJECT NOT FOUND!")); - } - else { - // Updated old object - cert_len = sizeof(cert_data); - rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, cert_len); // TODO: double check len here (check inside, never changed but used below). One more time above - if (rv != CKR_OK) { - DBG(("Unable to get certificate data from token")); - return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point - } + // New object created, add it to the object list - rv = store_cert(cert_id, cert_data, cert_len); - if (rv != CKR_OK) { - DBG(("Unable to store certificate data")); - return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point - } - - /*session.slot->token->n_objects += 4; + // Each object counts as four + session.slot->token->n_objects += 4; session.slot->token->n_certs++; obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); @@ -1729,14 +1714,44 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( DBG(("Unable to store new item in the session")); return CKR_HOST_MEMORY; } + session.slot->token->objects = obj_ptr; + + obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 4; + *obj_ptr++ = dobj_id; + *obj_ptr++ = cert_id; + *obj_ptr++ = pvtk_id; + *obj_ptr++ = pubk_id; + } + + // Write/Update the object + cert_len = sizeof(cert_data); + rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, cert_len); // TODO: double check len here (check inside, never changed but used below). One more time above + if (rv != CKR_OK) { + DBG(("Unable to get certificate data from token")); + return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point + } + + rv = store_cert(cert_id, cert_data, cert_len); + if (rv != CKR_OK) { + DBG(("Unable to store certificate data")); + return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point + } + + /*session.slot->token->n_objects += 4; + session.slot->token->n_certs++; + + obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); + if (obj_ptr == NULL) { + DBG(("Unable to store new item in the session")); + return CKR_HOST_MEMORY; + } obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 4; *obj_ptr++ = dobj_id; *obj_ptr++ = cert_id; *obj_ptr++ = pvtk_id; *obj_ptr++ = pubk_id;*/ - } - + *phPrivateKey = op_info.op.gen.key_id; *phPublicKey = op_info.op.gen.key_id - PIV_PVTK_OBJ_KM + PIV_PUBK_OBJ_KM; // TODO: make function for these? From df2ff3cd510f4279da0a91eafcb32fd1964476a4 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 12 Aug 2015 15:41:58 +0200 Subject: [PATCH 056/134] Fixed pkcs1.5 padding --- lib/ykpiv.c | 74 +++++++++++++++++++++++++----------------- ykcs11/debug.h | 4 +-- ykcs11/mechanisms.c | 18 +++++----- ykcs11/openssl_utils.c | 6 +++- ykcs11/ykcs11.c | 33 +++++++++++++------ 5 files changed, 85 insertions(+), 50 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 8cd9a70..b8c323b 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -534,39 +534,55 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, ykpiv_rc res; switch(algorithm) { - case YKPIV_ALGO_RSA1024: - pad_len = 128; - case YKPIV_ALGO_RSA2048: - if(pad_len == 0) { - pad_len = 256; + case YKPIV_ALGO_RSA1024: + pad_len = 128; + + case YKPIV_ALGO_RSA2048: + if(pad_len == 0) { + pad_len = 256; + } + if(!decipher) { + // Signature + if (padding) { + // Padding required + if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) { + return YKPIV_SIZE_ERROR; + } + + // Add padding and copy data + RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len); + in_len = pad_len; } - if(!decipher) { - if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) { - return YKPIV_SIZE_ERROR; - } - if (padding) { - RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len); - in_len = pad_len; - } - else if (in_len != pad_len) - return YKPIV_SIZE_ERROR; - } else { - if(in_len != pad_len) { - return YKPIV_SIZE_ERROR; - } - memcpy(sign_in, raw_in, in_len); + else { + // No padding required + if (in_len != pad_len) + return YKPIV_SIZE_ERROR; + + // Just copy data + memcpy(sign_in, raw_in, in_len); } - break; - case YKPIV_ALGO_ECCP256: - if(!decipher && in_len > 32) { - return YKPIV_SIZE_ERROR; - } else if(decipher && in_len != 65) { - return YKPIV_SIZE_ERROR; + } + else { + // Decryption + if(in_len != pad_len) { + return YKPIV_SIZE_ERROR; } + + // Just copy data memcpy(sign_in, raw_in, in_len); - break; - default: - return YKPIV_ALGORITHM_ERROR; + } + break; + + case YKPIV_ALGO_ECCP256: + if(!decipher && in_len > 32) { + return YKPIV_SIZE_ERROR; + } else if(decipher && in_len != 65) { + return YKPIV_SIZE_ERROR; + } + memcpy(sign_in, raw_in, in_len); + break; + default: + return YKPIV_ALGORITHM_ERROR; } if(in_len < 0x80) { diff --git a/ykcs11/debug.h b/ykcs11/debug.h index 5debc5d..1fbe740 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -1,8 +1,8 @@ #ifndef DEBUG_H #define DEBUG_H -#define YKCS11_DBG 0 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 +#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 0012622..5b84b09 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -1,4 +1,5 @@ #include "mechanisms.h" +#include "debug.h" #define F4 "\x01\x00\x01" #define PRIME256V1 "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" @@ -267,8 +268,6 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); if (rv != CKR_OK) return CKR_FUNCTION_FAILED; -// DBG(("The hashed value is %lu long and looks like\n", op_info->buf_len)); - dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); case CKM_RSA_PKCS: // Add digest info if needed @@ -276,11 +275,8 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { rv = do_pkcs_1_digest_info(op_info->buf, op_info->buf_len, nid, op_info->buf, &op_info->buf_len); if (rv != CKR_OK) return CKR_FUNCTION_FAILED; - -// DBG(("After adding digestinfo is %lu long and looks like\n", op_info->buf_len)); - dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE); } - + // Compute padding for all PKCS1 variants len = op_info->buf_len; op_info->buf_len = sizeof(op_info->buf); @@ -356,8 +352,10 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG return CKR_ATTRIBUTE_VALUE_INVALID; // Only support F4 - if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0) + if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0) { + DBG(("Unsupported public exponent")); return CKR_ATTRIBUTE_VALUE_INVALID; + } break; @@ -366,8 +364,10 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG return CKR_ATTRIBUTE_VALUE_INVALID; if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 && - *((CK_ULONG_PTR) templ[i].pValue) != 2048) // TODO: make define? + *((CK_ULONG_PTR) templ[i].pValue) != 2048) { // TODO: make define? + DBG(("Unsupported MODULUS_BITS (key length)")); return CKR_ATTRIBUTE_VALUE_INVALID; + } op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); break; @@ -395,6 +395,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG break; default: + DBG(("Invalid attribute %lx in public key template", templ[i].type)); return CKR_ATTRIBUTE_VALUE_INVALID; } } @@ -459,6 +460,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG break; default: + DBG(("Invalid attribute %lx in private key template", templ[i].type)); return CKR_ATTRIBUTE_VALUE_INVALID; } } diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 3f2c9cf..0a6172a 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -2,6 +2,7 @@ #include #include "../tool/util.h" // TODO: share this better? #include "debug.h" +#include CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { @@ -367,6 +368,8 @@ CK_RV free_key(EVP_PKEY *key) { } CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len) { + unsigned char buffer[512]; + key_len /= 8; DBG(("Apply padding to %lu bytes and get %lu\n", in_len, key_len)); @@ -374,9 +377,10 @@ CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PT if (*out_len < key_len) CKR_BUFFER_TOO_SMALL; - if (RSA_padding_add_PKCS1_type_1(out, key_len, in, in_len) == 0) + if (RSA_padding_add_PKCS1_type_1(buffer, key_len, in, in_len) == 0) return CKR_FUNCTION_FAILED; + memcpy(out, buffer, key_len); *out_len = key_len; return CKR_OK; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index bd9db35..117c88d 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -559,10 +559,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; } - DBG(("HI")); + free(session.slot->token->objects); // TODO: make objects survive a session so there is no need to get them again? session.slot->token->objects = NULL; - DBG(("HI2")); + memset(&session, 0, sizeof(ykcs11_session_t)); session.handle = CK_INVALID_HANDLE; @@ -1351,24 +1351,37 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( // TODO: check other conditions ykpiv_rc r; // TODO: delete this + if (pSignature == NULL_PTR) { + // Just return the size of the signature + *pulSignatureLen = op_info.op.sign.key_len / 8; + DBG(("The size of the signature will be %lu", *pulSignatureLen)); + + DOUT; + return CKR_OK; + } + + DBG(("Sending %lu bytes to sign", ulDataLen)); dump_hex(pData, ulDataLen, stderr, CK_TRUE); if (is_hashed_mechanism(op_info.mechanism.mechanism) == CK_TRUE) { - if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { - DBG(("Unable to perform signing operation step")); - return CKR_FUNCTION_FAILED; - } + if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { + DBG(("Unable to perform signing operation step")); + return CKR_FUNCTION_FAILED; // TODO: every error in here must stop and clear the signing operation } + } if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) { DBG(("Unable to finalize signing operation")); return CKR_FUNCTION_FAILED; } - //dump_hex(buf, 256, stderr, CK_TRUE); - //*pulSignatureLen = 256; + DBG(("Using key %lx", op_info.op.sign.key_id)); // TODO: test what happens if there is no key on the card - if ((r = ykpiv_sign_data(piv_state, op_info.buf, ulDataLen, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id)) != YKPIV_OK) { + DBG(("After padding and transformation there are %lu bytes", op_info.buf_len)); + dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE); + + *pulSignatureLen = sizeof(op_info.buf); + if ((r = ykpiv_sign_data2(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id, 0)) != YKPIV_OK) { DBG(("Sign error, %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } @@ -1665,7 +1678,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( } if (op_info.op.gen.key_id == 0) { - DBG(("Key id not specified, using default value")); + DBG(("Key id not specified")); return CKR_TEMPLATE_INCOMPLETE; } From 9c082be0823fee987f9e23e069648ea018ca167c Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 12 Aug 2015 16:05:03 +0200 Subject: [PATCH 057/134] Added simple logout function. --- ykcs11/ykcs11.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 117c88d..f0c073a 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -727,7 +727,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( case CKU_CONTEXT_SPECIFIC: default: - return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now + return CKR_USER_TYPE_INVALID; } DBG(("You win! %lu", tries)); @@ -741,7 +741,33 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); + return CKR_SESSION_CLOSED; + } + + if (hSession != session.handle) + return CKR_SESSION_HANDLE_INVALID; + + // TODO: check more conditions + + if (session.info.state == CKS_RO_PUBLIC_SESSION || + session.info.state == CKS_RW_PUBLIC_SESSION) + return CKR_USER_NOT_LOGGED_IN; + + if ((session.info.flags & CKF_RW_SESSION) == 0) + session.info.state = CKS_RO_PUBLIC_SESSION; + else + session.info.state = CKS_RW_PUBLIC_SESSION; + + // TODO: more things to clean? + DOUT; return CKR_OK; } From de083bb27a1e5ed51f84d76144217c7f161a11cb Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 12 Aug 2015 17:05:47 +0200 Subject: [PATCH 058/134] Fixed wrong free. --- ykcs11/openssl_utils.c | 7 ++++--- ykcs11/ykcs11.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 0a6172a..6014d88 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -305,7 +305,7 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { ecg = EC_KEY_get0_group(eck); ecp = EC_KEY_get0_public_key(eck); - // Adde the DER structure with length after extracting the point + // Add the DER structure with length after extracting the point data[0] = 0x04; if ((*len = EC_POINT_point2oct(ecg, ecp, pcf, data + 2, *len - 2, NULL)) == 0) @@ -315,14 +315,15 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { *len += 2; + // TODO: free ecg and ecp? break; default: return CKR_FUNCTION_FAILED; } - EC_KEY_free(eck); - eck = NULL; + EVP_PKEY_free(key); + key = NULL; return CKR_OK; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index f0c073a..a035474 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1274,7 +1274,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_KEY_HANDLE_INVALID; } - DBG(("Key algorithm is %lu\n", type)); + DBG(("Key type is %lu\n", type)); // Get key length and algorithm type if (type == CKK_RSA) { From 6a60c779da17d0a3814d9c019c25e28e5aca44d7 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 19 Aug 2015 13:23:01 +0200 Subject: [PATCH 059/134] More free. --- ykcs11/objects.c | 1 + ykcs11/openssl_utils.c | 48 ++++++++++++++++++++++++++++++------------ ykcs11/openssl_utils.h | 2 +- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index ba02f67..ecfe714 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -738,6 +738,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { len = sizeof(b_tmp); if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; + data = b_tmp; break; diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 6014d88..fc23b1a 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -161,7 +161,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: @@ -257,7 +257,12 @@ CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) { if (rsa == NULL) return 0; - return RSA_size(rsa) * 8; // There is also RSA_bits but only in >= 1.1.0 + key_len = RSA_size(rsa) * 8; // There is also RSA_bits but only in >= 1.1.0 + + RSA_free(rsa); + rsa = NULL; + + return key_len; } @@ -282,13 +287,19 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { rsa = EVP_PKEY_get1_RSA(key); - if (RSA_size(rsa) > *len) + if (RSA_size(rsa) > *len) { + RSA_free(rsa); + rsa = NULL; return CKR_BUFFER_TOO_SMALL; + } p = data; - if ((*len = i2d_RSAPublicKey(rsa, &p)) == 0) + if ((*len = i2d_RSAPublicKey(rsa, &p)) == 0) { + RSA_free(rsa); + rsa = NULL; return CKR_FUNCTION_FAILED; + } // TODO: this is the correct thing to do so that we strip out the exponent // OTOH we also need a function to get the exponent out with CKA_PUBLIC_EXPONENT @@ -308,24 +319,26 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { // Add the DER structure with length after extracting the point data[0] = 0x04; - if ((*len = EC_POINT_point2oct(ecg, ecp, pcf, data + 2, *len - 2, NULL)) == 0) + if ((*len = EC_POINT_point2oct(ecg, ecp, pcf, data + 2, *len - 2, NULL)) == 0) { + EC_KEY_free(eck); + eck = NULL; return CKR_FUNCTION_FAILED; + } data[1] = *len; *len += 2; - // TODO: free ecg and ecp? + EC_KEY_free(eck); + eck = NULL; + break; default: return CKR_FUNCTION_FAILED; } - EVP_PKEY_free(key); - key = NULL; - - return CKR_OK; + return CKR_OK; } @@ -342,8 +355,9 @@ CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key) { return CKR_OK; } + #include -CK_RV do_get_curve_parameters( EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { +CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { EC_KEY *eck; const EC_GROUP *ecg; @@ -354,8 +368,14 @@ CK_RV do_get_curve_parameters( EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len p = data; - if ((*len = i2d_ECPKParameters(ecg, &p)) == 0) - return CKR_FUNCTION_FAILED; + if ((*len = i2d_ECPKParameters(ecg, &p)) == 0) { + EC_KEY_free(eck); + eck = NULL; + return CKR_FUNCTION_FAILED; + } + + EC_KEY_free(eck); + eck = NULL; return CKR_OK; } @@ -370,7 +390,7 @@ CK_RV free_key(EVP_PKEY *key) { CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len) { unsigned char buffer[512]; - + key_len /= 8; DBG(("Apply padding to %lu bytes and get %lu\n", in_len, key_len)); diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index c29fd18..03f0c2a 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -19,7 +19,7 @@ CK_KEY_TYPE do_get_key_type(EVP_PKEY *key); CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key); CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key); -CK_RV do_get_curve_parameters( EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); +CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); CK_RV free_key(EVP_PKEY *key); CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len); From a792e16333303b30f346615216c2d21354ba7996 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 19 Aug 2015 15:20:27 +0200 Subject: [PATCH 060/134] Fixed unhashed sign mechanisms. --- ykcs11/mechanisms.c | 2 +- ykcs11/ykcs11.c | 27 ++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 5b84b09..785431a 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -199,7 +199,7 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i // Mechanism not suitable for multipart signatures return CKR_FUNCTION_FAILED; - case CKM_RSA_X_509: + case CKM_RSA_X_509: // TODO: shouldn't this be in the group above? return CKR_OK; case CKM_SHA1_RSA_PKCS: diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index a035474..a0e36f0 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1319,8 +1319,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( } // The buffer contains an uncompressed point of the form 04, len, 04, x, y + // Where len is the |x| + |y| + 1 bytes - op_info.op.sign.key_len = ((template[3].ulValueLen - 1) / 2) * 8; + op_info.op.sign.key_len = ((buf[1] - 1) / 2) * 8; if (op_info.op.sign.key_len == 256) op_info.op.sign.algo = YKPIV_ALGO_ECCP256; @@ -1385,7 +1386,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( DOUT; return CKR_OK; } - DBG(("Sending %lu bytes to sign", ulDataLen)); dump_hex(pData, ulDataLen, stderr, CK_TRUE); @@ -1396,13 +1396,34 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( return CKR_FUNCTION_FAILED; // TODO: every error in here must stop and clear the signing operation } } + else { + if (is_RSA_mechanism(op_info.mechanism.mechanism)) { + // RSA_X_509 + if (ulDataLen > (op_info.op.sign.key_len / 8)) { + DBG(("Data must be shorter than key length (%lu bits)", op_info.op.sign.key_len)); + return CKR_FUNCTION_FAILED; + } + } + else { + // ECDSA + if (ulDataLen > 128) { + // Specs say ECDSA only supports 1024 bit + DBG(("Meximum data length for ECDSA is 128 bytes")); + return CKR_FUNCTION_FAILED; + } + } + + op_info.buf_len = ulDataLen; + memcpy(op_info.buf, pData, ulDataLen); + } + if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) { DBG(("Unable to finalize signing operation")); return CKR_FUNCTION_FAILED; } - DBG(("Using key %lx", op_info.op.sign.key_id)); // TODO: test what happens if there is no key on the card + DBG(("Using key %lx", op_info.op.sign.key_id)); DBG(("After padding and transformation there are %lu bytes", op_info.buf_len)); dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE); From bb4ed223156dc0e5f42ca967663c01b91ad65215 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 19 Aug 2015 15:41:41 +0200 Subject: [PATCH 061/134] Fixed RSA_X_509 padding. --- ykcs11/mechanisms.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 785431a..f4a0d78 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -1,5 +1,6 @@ #include "mechanisms.h" #include "debug.h" +#include #define F4 "\x01\x00\x01" #define PRIME256V1 "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" @@ -146,14 +147,9 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) { switch (op_info->mechanism.mechanism) { case CKM_RSA_PKCS: - // No hash required for this mechanism - return CKR_OK; - case CKM_RSA_PKCS_PSS: - // No hash required for this mechanism - return CKR_OK; - case CKM_RSA_X_509: + case CKM_ECDSA: // No hash required for this mechanism return CKR_OK; @@ -174,10 +170,6 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) { case CKM_SHA512_RSA_PKCS_PSS: return do_md_init(YKCS11_SHA512, &op_info->op.sign.md_ctx); - case CKM_ECDSA: - // No hash required for this mechanism - return CKR_OK; - default: return CKR_FUNCTION_FAILED; } @@ -196,12 +188,10 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i case CKM_RSA_PKCS: case CKM_RSA_PKCS_PSS: case CKM_ECDSA: + case CKM_RSA_X_509: // Mechanism not suitable for multipart signatures return CKR_FUNCTION_FAILED; - case CKM_RSA_X_509: // TODO: shouldn't this be in the group above? - return CKR_OK; - case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: @@ -250,14 +240,19 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { rv = do_encode_rsa_public_key(op_info->op.sign.key, op_info->op.sign.key_len, &rsa); if (rv != CKR_OK) return CKR_FUNCTION_FAILED; - + rv = do_pkcs_pss(rsa, op_info->buf, op_info->buf_len, nid, op_info->buf, &op_info->buf_len); // TODO: does rsa have to be free'd ? - + return rv; case CKM_RSA_X_509: + // Padding in this case consists of prepending zeroes + len = (op_info->op.sign.key_len / 8) - op_info->buf_len; + memmove(op_info->buf + len, op_info->buf, op_info->buf_len); + memset(op_info->buf, 0, len); + op_info->buf_len = op_info->op.sign.key_len / 8; return CKR_OK; case CKM_SHA1_RSA_PKCS: @@ -393,7 +388,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG case CKA_WRAP: // Ignore these attributes for now break; - + default: DBG(("Invalid attribute %lx in public key template", templ[i].type)); return CKR_ATTRIBUTE_VALUE_INVALID; @@ -401,7 +396,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG } return CKR_OK; - + } CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) { @@ -466,5 +461,5 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG } return CKR_OK; - + } From cd1e67021de72f6c777e5c05a739394eab0664a6 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 19 Aug 2015 16:21:40 +0200 Subject: [PATCH 062/134] Removed unnecessary line. --- ykcs11/openssl_utils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index fc23b1a..b674698 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -355,7 +355,6 @@ CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key) { return CKR_OK; } - #include CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { From cef514eb28a2f6cf481cc4e95ef6ad198d446438 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 21 Aug 2015 10:05:14 +0200 Subject: [PATCH 063/134] drop generated files --- ykcs11/ykcs11-version.h | 91 ----------------------------------------- ykcs11/ykcs11.pc | 12 ------ 2 files changed, 103 deletions(-) delete mode 100644 ykcs11/ykcs11-version.h delete mode 100644 ykcs11/ykcs11.pc diff --git a/ykcs11/ykcs11-version.h b/ykcs11/ykcs11-version.h deleted file mode 100644 index e23b891..0000000 --- a/ykcs11/ykcs11-version.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2015 Yubico AB - * All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional permission under GNU GPL version 3 section 7 - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, We grant you additional - * permission to convey the resulting work. Corresponding Source for a - * non-source form of such a combination shall include the source code - * for the parts of OpenSSL used as well as that of the covered work. - * - */ - -#ifndef YKCS11_VERSION_H -#define YKCS11_VERSION_H - -#ifdef __cplusplus -extern "C" -{ -#endif - - /** - * YKCS11_VERSION_STRING - * - * Pre-processor symbol with a string that describe the header file - * version number. Used together with ykneomgr_check_version() to verify - * header file and run-time library consistency. - */ -#define YKCS11_VERSION_STRING "1.0.1" - - /** - * YKCS11_VERSION_NUMBER - * - * Pre-processor symbol with a hexadecimal value describing the header - * file version number. For example, when the header version is 1.2.3 - * this symbol will have the value 0x01020300. The last two digits - * are only used between public releases, and will otherwise be 00. - */ -#define YKCS11_VERSION_NUMBER @YKCS11_VERSION_NUMBER@ - - /** - * YKCS11_VERSION_MAJOR - * - * Pre-processor symbol with a decimal value that describe the major - * level of the header file version number. For example, when the - * header version is 1.2.3 this symbol will be 1. - */ -#define YKCS11_VERSION_MAJOR @YKCS11_VERSION_MAJOR@ - - /** - * YKCS11_VERSION_MINOR - * - * Pre-processor symbol with a decimal value that describe the minor - * level of the header file version number. For example, when the - * header version is 1.2.3 this symbol will be 2. - */ -#define YKCS11_VERSION_MINOR @YKCS11_VERSION_MINOR@ - - /** - * YKCS11_VERSION_PATCH - * - * Pre-processor symbol with a decimal value that describe the patch - * level of the header file version number. For example, when the - * header version is 1.2.3 this symbol will be 3. - */ -#define YKCS11_VERSION_PATCH @YKCS11_VERSION_PATCH@ - - const char *ykcs11_check_version (const char *req_version); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ykcs11/ykcs11.pc b/ykcs11/ykcs11.pc deleted file mode 100644 index 7b27b6d..0000000 --- a/ykcs11/ykcs11.pc +++ /dev/null @@ -1,12 +0,0 @@ -prefix=/usr/local -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: yubico-piv-tool -Description: Yubico PIV PKCS#11 Module -URL: https://www.yubico.com/ -Version: 1.0.1 -Libs: -L${libdir} -lykcs11 -Cflags: -I${includedir}/ykpiv - From 7573c05c8247c50528b44fe14d11ffb5452c3d6a Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 21 Aug 2015 10:06:20 +0200 Subject: [PATCH 064/134] fixup filenames and add missing headers --- ykcs11/Makefile.am | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index 4e91d9f..fdd13af 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -34,15 +34,16 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c version.c ykcs11.pc.in ykcs11.map -libykcs11_la_SOURCES += debug.h -libykcs11_la_SOURCES += vendors.c vendor.h vendor_ids.h -libykcs11_la_SOURCES += slot_vendors.c slot_vendor.h -libykcs11_la_SOURCES += token_vendors.c token_vendor.h +libykcs11_la_SOURCES += ykcs11.h debug.h +libykcs11_la_SOURCES += vendors.c vendors.h vendor_ids.h +libykcs11_la_SOURCES += slot_vendors.c slot_vendors.h +libykcs11_la_SOURCES += token_vendors.c token_vendors.h libykcs11_la_SOURCES += mechanisms.c mechanisms.h libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h libykcs11_la_SOURCES += utils.c utils.h libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h openssl_types.h libykcs11_la_SOURCES += objects.c objects.h obj_types.h +libykcs11_la_SOURCES += pkcs11.h pkcs11f.h pkcs11t.h #internal.h #libykcs11_la_SOURCES += error.c From 2764846bb611a3309a70c5dbef0970a6eda78f31 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 21 Aug 2015 10:32:40 +0200 Subject: [PATCH 065/134] add mac install_name_tool fixes for ykcs11 build --- mac.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mac.mk b/mac.mk index 1c4ffc4..627bd8d 100644 --- a/mac.mk +++ b/mac.mk @@ -65,8 +65,11 @@ doit: chmod u+w $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib && \ install_name_tool -id @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib && \ install_name_tool -id @executable_path/../lib/libykpiv.1.dylib $(PWD)/tmp/root/lib/libykpiv.1.dylib && \ + install_name_tool -id @executable_path/../lib/libykcs11.1.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \ install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libykpiv.1.dylib && \ + install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \ install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/bin/yubico-piv-tool && \ + install_name_tool -change $(PWD)/tmp/root/lib/libykpiv.1.dylib @executable_path/../lib/libykpiv.1.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \ install_name_tool -change $(PWD)/tmp/root/lib/libykpiv.1.dylib @executable_path/../lib/libykpiv.1.dylib $(PWD)/tmp/root/bin/yubico-piv-tool ; \ if otool -L $(PWD)/tmp/root/lib/*.dylib $(PWD)/tmp/root/bin/* | grep '$(PWD)/tmp/root' | grep -q compatibility; then \ echo "something is incorrectly linked!"; \ From 86184696198adc996e50182038d30d1ffe87ba83 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 14:58:14 +0200 Subject: [PATCH 066/134] Fixed PSS (still untested). --- ykcs11/openssl_utils.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index b674698..617d6b0 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -425,17 +425,24 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { unsigned char em[512]; // Max for this is ceil((|key_len_bits| - 1) / 8) + OpenSSL_add_all_digests(); + // TODO: rand must be seeded first (should be automatic) if (*out_len < RSA_size(key)) CKR_BUFFER_TOO_SMALL; DBG(("Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key))); - if (RSA_padding_add_PKCS1_PSS(key, em, in, EVP_get_digestbynid(nid), -2) == 0) + // In case of raw PSS (no hash) this function will fail because OpenSSL requires an MD + if (RSA_padding_add_PKCS1_PSS(key, em, in, EVP_get_digestbynid(nid), -2) == 0) { + EVP_cleanup(); return CKR_FUNCTION_FAILED; + } *out_len = RSA_size(key); + EVP_cleanup(); + return CKR_OK; } From f27ca3837cb80515f50e863581a7a80db8b3a705 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 16:25:22 +0200 Subject: [PATCH 067/134] Add more precondition checks and debug messages. --- ykcs11/debug.h | 4 ++-- ykcs11/ykcs11.c | 60 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/ykcs11/debug.h b/ykcs11/debug.h index 1fbe740..5debc5d 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -1,8 +1,8 @@ #ifndef DEBUG_H #define DEBUG_H -#define YKCS11_DBG 1 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 +#define YKCS11_DBG 0 // 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 { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index a0e36f0..aafcde2 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -149,7 +149,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( int i; int j; - // TODO: check more preconditions + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + if (pSlotList == NULL_PTR) { // Just return the number of slots *pulCount = n_slots; @@ -196,8 +200,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (slotID >= n_slots) - return CKR_ARGUMENTS_BAD; + if (slotID >= n_slots) { + DBG(("Invalid slot ID %lu, slotID")); + return CKR_SLOT_ID_INVALID; + } memcpy(pInfo, &slots[slotID].info, sizeof(CK_SLOT_INFO)); @@ -220,12 +226,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (slotID >= n_slots) - return CKR_ARGUMENTS_BAD; + if (slotID >= n_slots) { + DBG(("Invalid slot ID %lu, slotID")); + return CKR_SLOT_ID_INVALID; + } if (slots[slotID].vid == UNKNOWN) { DBG(("No support for slot %lu", slotID)); - return CKR_TOKEN_NOT_RECOGNIZED; + return CKR_SLOT_ID_INVALID; } if (!has_token(slots + slotID)) { @@ -242,7 +250,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( memcpy(pInfo, &slots[slotID].token->info, sizeof(CK_TOKEN_INFO)); - // Overwrite value that are application specific + // Overwrite values that are application specific pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token @@ -287,8 +295,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (slotID > n_slots || pulCount == NULL_PTR) + if (slotID >= n_slots) { + DBG(("Invalid slot ID %lu", slotID)); + return CKR_SLOT_ID_INVALID; + } + + if (pulCount == NULL_PTR) { + DBG(("Wrong/Missing parameter")); return CKR_ARGUMENTS_BAD; + } if (slots[slotID].vid == UNKNOWN) { DBG(("Slot %lu is tokenless/unsupported", slotID)); @@ -296,7 +311,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( } // TODO: check more return values - // TODO: user NULL_PTR more for coherence token = get_token_vendor(slots[slotID].vid); @@ -315,8 +329,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( return CKR_BUFFER_TOO_SMALL; } - if (token.get_token_mechanism_list(pMechanismList, *pulCount) != CKR_OK) + if (token.get_token_mechanism_list(pMechanismList, *pulCount) != CKR_OK) { + DBG(("Unable to retrieve mechanism list")); return CKR_FUNCTION_FAILED; + } DOUT; return CKR_OK; @@ -336,21 +352,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (slotID > n_slots || pInfo == NULL_PTR) + if (slotID >= n_slots) { + DBG(("Invalid slot ID %lu, slotID")); + return CKR_SLOT_ID_INVALID; + } + + if (pInfo == NULL_PTR) { + DBG(("Wrong/Missing parameter")); return CKR_ARGUMENTS_BAD; + } if (slots[slotID].vid == UNKNOWN) { DBG(("Slot %lu is tokenless/unsupported", slotID)); return CKR_SLOT_ID_INVALID; } - // TODO: check more return values - // TODO: user NULL_PTR more for coherence - token = get_token_vendor(slots[slotID].vid); - if (token.get_token_mechanism_info(type, pInfo) != CKR_OK) + if (token.get_token_mechanism_info(type, pInfo) != CKR_OK) { + DBG(("Unable to retrieve mechanism information")); return CKR_MECHANISM_INVALID; + } DOUT; return CKR_OK; @@ -767,7 +789,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( session.info.state = CKS_RW_PUBLIC_SESSION; // TODO: more things to clean? - + DOUT; return CKR_OK; } @@ -1660,7 +1682,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( piv_obj_id_t *obj_ptr; CK_BYTE cert_data[2100]; CK_ULONG cert_len; - + if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -1759,7 +1781,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( dobj_id = op_info.op.gen.key_id - PIV_PVTK_OBJ_PIV_AUTH; // TODO: make function for these cert_id = PIV_DATA_OBJ_LAST + 1 + dobj_id; pvtk_id = op_info.op.gen.key_id; - pubk_id = PIV_PVTK_OBJ_LAST + 1 + dobj_id; + pubk_id = PIV_PVTK_OBJ_LAST + 1 + dobj_id; // Check whether we created a new object or updated an existing one if (is_new == CK_TRUE) { @@ -1811,7 +1833,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( *obj_ptr++ = cert_id; *obj_ptr++ = pvtk_id; *obj_ptr++ = pubk_id;*/ - + *phPrivateKey = op_info.op.gen.key_id; *phPublicKey = op_info.op.gen.key_id - PIV_PVTK_OBJ_KM + PIV_PUBK_OBJ_KM; // TODO: make function for these? From 4542a4506bc4420e18049dac693522f9efa8e205 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 16:26:37 +0200 Subject: [PATCH 068/134] Skip token initialization. --- ykcs11/ykcs11.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index aafcde2..eaef813 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -386,8 +386,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_InitToken)( ) { DIN; - - return CKR_OK; + DBG(("Token initialization unsupported")); + DOUT; + return CKR_FUNCTION_FAILED; } CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)( From 255815d78f4d5417e3f8b0efba3c963dc6635f65 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 16:27:46 +0200 Subject: [PATCH 069/134] Skip PIN initialization. --- ykcs11/ykcs11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index eaef813..e97e270 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -398,9 +398,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)( ) { DIN; - DBG(("TODO!!!")); + DBG(("PIN initialization unsupported")); DOUT; - return CKR_OK; + return CKR_FUNCTION_FAILED; } CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)( From 6cbdbc3c14e069f6747748f2464036957d655ba2 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 16:39:44 +0200 Subject: [PATCH 070/134] More debug messages and precondition checks. --- ykcs11/ykcs11.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index e97e270..5d359d7 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -439,8 +439,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (slotID >= n_slots || phSession == NULL) + if (slotID >= n_slots) { + DBG(("Invalid slot ID %lu, slotID")); + return CKR_SLOT_ID_INVALID; + } + + if (phSession == NULL_PTR) { + DBG(("Wrong/Missing parameter")); return CKR_ARGUMENTS_BAD; + } if (slots[slotID].vid == UNKNOWN) { DBG(("No support for slot %lu", slotID)); @@ -462,7 +469,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_SESSION_COUNT; } - if ((flags & CKF_SERIAL_SESSION) == 0) { // TODO: check more error conditions + if ((flags & CKF_SERIAL_SESSION) == 0) { DBG(("Open session called without CKF_SERIAL_SESSION set")); // Reuired by specs return CKR_SESSION_PARALLEL_NOT_SUPPORTED; } @@ -478,11 +485,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( if ((flags & CKF_RW_SESSION)) { // R/W Session - session.info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session + session.info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default RO session } else { // R/O Session - session.info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default session + session.info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default RW session } session.info.flags = flags; @@ -517,7 +524,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( } // Get a list of object ids for available certificates object from the session - rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); // TODO: better to get this from token? how? + rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); if (rv != CKR_OK) { DBG(("Unable to retrieve certificate ids from the session")); goto failure; From 8fa6ff8edbcb227e385a7877d4fceced3e6e8213 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 16:47:23 +0200 Subject: [PATCH 071/134] Use buffer length while storing cert. --- ykcs11/debug.h | 4 ++-- ykcs11/token_vendors.h | 2 +- ykcs11/ykcs11.c | 13 +++++++------ ykcs11/yubico_token.c | 4 ++-- ykcs11/yubico_token.h | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/ykcs11/debug.h b/ykcs11/debug.h index 5debc5d..1fbe740 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -1,8 +1,8 @@ #ifndef DEBUG_H #define DEBUG_H -#define YKCS11_DBG 0 // General debug, must be either 1 or 0 -#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0 +#define YKCS11_DBG 1 // General debug, must be either 1 or 0 +#define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 #define D(x) do { \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index b143ca8..041e2a0 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -17,7 +17,7 @@ typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR, CK_ULONG_PTR); typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); -typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG); +typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG_PTR); // Common token functions below typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 5d359d7..e80f422 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -201,7 +201,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu, slotID")); + DBG(("Invalid slot ID %lu", slotID)); return CKR_SLOT_ID_INVALID; } @@ -227,7 +227,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu, slotID")); + DBG(("Invalid slot ID %lu", slotID)); return CKR_SLOT_ID_INVALID; } @@ -353,7 +353,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu, slotID")); + DBG(("Invalid slot ID %lu", slotID)); return CKR_SLOT_ID_INVALID; } @@ -440,7 +440,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu, slotID")); + DBG(("Invalid slot ID %lu", slotID)); return CKR_SLOT_ID_INVALID; } @@ -532,7 +532,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( // Get the actual certificate data from the token and store it as an X509 object for (i = 0; i < session.slot->token->n_certs; i++) { - rv = token.get_token_raw_certificate(piv_state, cert_ids[i], cert_data, cert_len); // TODO: double check len here (check inside, never changed but used below) + cert_len = sizeof(cert_data); + rv = token.get_token_raw_certificate(piv_state, cert_ids[i], cert_data, &cert_len); if (rv != CKR_OK) { DBG(("Unable to get certificate data from token")); goto failure; @@ -1815,7 +1816,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( // Write/Update the object cert_len = sizeof(cert_data); - rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, cert_len); // TODO: double check len here (check inside, never changed but used below). One more time above + rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, &cert_len); // TODO: double check len here (check inside, never changed but used below). One more time above if (rv != CKR_OK) { DBG(("Unable to get certificate data from token")); return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index 93671e0..5915780 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -298,9 +298,9 @@ CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULO return get_objects(state, CK_FALSE, obj, &num, NULL); } -CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG len) { +CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG_PTR len) { - if (ykpiv_fetch_object(state, piv_2_ykpiv(obj), data, &len) != YKPIV_OK) + if (ykpiv_fetch_object(state, piv_2_ykpiv(obj), data, len) != YKPIV_OK) return CKR_FUNCTION_FAILED; return CKR_OK; diff --git a/ykcs11/yubico_token.h b/ykcs11/yubico_token.h index c39a7d3..09e57ea 100644 --- a/ykcs11/yubico_token.h +++ b/ykcs11/yubico_token.h @@ -16,6 +16,6 @@ CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num); CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info); CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs); CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num); -CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG len); +CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG_PTR len); #endif From 242087412520f45ca4bbbe3c825f5c73259b7c67 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 16:59:05 +0200 Subject: [PATCH 072/134] More debug messages and precondition checks. --- ykcs11/ykcs11.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index e80f422..9b7df2f 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -591,7 +591,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( return CKR_SESSION_HANDLE_INVALID; } - free(session.slot->token->objects); // TODO: make objects survive a session so there is no need to get them again? + free(session.slot->token->objects); session.slot->token->objects = NULL; memset(&session, 0, sizeof(ykcs11_session_t)); @@ -613,8 +613,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (session.slot != slots + slotID) + if (session.slot != slots + slotID) { + DBG(("Invalid slot ID %lu", slotID)); return CKR_SLOT_ID_INVALID; + } rv = C_CloseSession(session.handle); @@ -634,11 +636,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (pInfo == NULL) + if (pInfo == NULL) { + DBG(("Wrong/Missing parameter")); return CKR_ARGUMENTS_BAD; + } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } memcpy(pInfo, &session.info, sizeof(CK_SESSION_INFO)); @@ -699,8 +705,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { return CKR_SESSION_HANDLE_INVALID; + } if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? DBG(("Tried to log-in to a read-only session")); From 0c3c9c5a00f3e4af177d22bbef673c416a9f7b11 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 20 Aug 2015 17:42:14 +0200 Subject: [PATCH 073/134] Close the operation after sign is done. --- ykcs11/ykcs11.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 9b7df2f..48b414e 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1414,7 +1414,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( } // TODO: check other conditions - ykpiv_rc r; // TODO: delete this + ykpiv_rc r; // TODO: delete this ? if (pSignature == NULL_PTR) { // Just return the size of the signature @@ -1473,6 +1473,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( DBG(("Got %lu bytes back", *pulSignatureLen)); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); + op_info.type = YKCS11_NOOP; // TODO: anything to clear here? + DOUT; return CKR_OK; } From 5d7f0b3d931be440be32dabb4c15804b64932e4e Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 21 Aug 2015 13:20:01 +0200 Subject: [PATCH 074/134] Removed nspr stuff. --- configure.ac | 2 +- ykcs11/Makefile.am | 4 ++-- ykcs11/pkcs11t.h | 8 ++++---- ykcs11/slot_vendors.c | 1 + 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 273efdc..ec89a0d 100644 --- a/configure.ac +++ b/configure.ac @@ -52,7 +52,7 @@ PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES(OPENSSL, libcrypto) -PKG_CHECK_MODULES([LIBNSPR], [nspr], [], []) +#PKG_CHECK_MODULES([LIBNSPR], [nspr], [], []) gl_LD_VERSION_SCRIPT gl_VALGRIND_TESTS diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index fdd13af..6d7845a 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -28,7 +28,7 @@ SUBDIRS = . #tests AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) -AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS) $(LIBNSPR_CFLAGS) +AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS) AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib lib_LTLIBRARIES = libykcs11.la @@ -56,7 +56,7 @@ EXTRA_libykcs11_la_DEPENDENCIES = ykcs11.map #libykcs11_la_LIBADD = $(OPENSSL_LIBS) $(PCSC_LIBS) #libykcs11_la_LIBADD += $(PCSC_WIN_LIBS) $(PCSC_MACOSX_LIBS) -libykcs11_la_LIBADD = $(LIBNSPR) ../lib/libykpiv.la +libykcs11_la_LIBADD = ../lib/libykpiv.la libykcs11_la_LIBADD += ../tool/libpiv_util.la libykcs11_la_LDFLAGS = -no-undefined diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index 5b64d63..9543f5c 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -52,14 +52,14 @@ #define CK_TRUE (!CK_FALSE) #endif -#include "prtypes.h" +//#include "prtypes.h" #define CK_PTR * #define CK_NULL_PTR 0 #define NULL_PTR 0 -#define CK_CALLBACK_FUNCTION(rv,func) rv (PR_CALLBACK * func) -#define CK_DECLARE_FUNCTION(rv,func) PR_EXTERN(rv) func -#define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (PR_CALLBACK * func) +#define CK_CALLBACK_FUNCTION(rv,func) rv (/*PR_CALLBACK*/ * func) +#define CK_DECLARE_FUNCTION(rv,func) /*PR_EXTERN(*/rv/*)*/ func +#define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (/*PR_CALLBACK*/ * func) #define CK_DEFINE_FUNCTION(rv, func) rv func /* an unsigned 8-bit value */ diff --git a/ykcs11/slot_vendors.c b/ykcs11/slot_vendors.c index 2158512..5ce9fed 100644 --- a/ykcs11/slot_vendors.c +++ b/ykcs11/slot_vendors.c @@ -1,5 +1,6 @@ #include "slot_vendors.h" #include "yubico_slot.h" +#include slot_vendor_t get_slot_vendor(vendor_id_t vid) { slot_vendor_t v; From 0184424f3f8ee7c46af5abfe5fadb22db92487c9 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 21 Aug 2015 14:10:38 +0200 Subject: [PATCH 075/134] Add debug messages for failed login. --- ykcs11/ykcs11.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 48b414e..1eb48c0 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -706,6 +706,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( } if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; } @@ -719,11 +720,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN) return CKR_ARGUMENTS_BAD; - if (session.info.state == CKS_RW_USER_FUNCTIONS) // TODO: make sure to set session default state as not logged + if (session.info.state == CKS_RW_USER_FUNCTIONS) { // TODO: make sure to set session default state as not logged + DBG(("This user type is already logged in")); return CKR_USER_ALREADY_LOGGED_IN; + } - if (session.info.state == CKS_RW_SO_FUNCTIONS) + if (session.info.state == CKS_RW_SO_FUNCTIONS) { + DBG(("A different uyser type is already logged in")); return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; + } tries = 0; if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { // TODO: call this from vendors.c From 5a069f10779bd1faf501d13424ce795f0177817a Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 21 Aug 2015 15:41:32 +0200 Subject: [PATCH 076/134] Temporary fix for multiple logins. --- ykcs11/ykcs11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 1eb48c0..7376d8e 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -720,10 +720,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN) return CKR_ARGUMENTS_BAD; - if (session.info.state == CKS_RW_USER_FUNCTIONS) { // TODO: make sure to set session default state as not logged + /*if (session.info.state == CKS_RW_USER_FUNCTIONS) { // TODO: make sure to set session default state as not logged DBG(("This user type is already logged in")); return CKR_USER_ALREADY_LOGGED_IN; - } + }*/ //TODO: TEMPORARY FIX TO ALLOW MULTIPLE LOGIN. THIS MUST GO BACK IN! if (session.info.state == CKS_RW_SO_FUNCTIONS) { DBG(("A different uyser type is already logged in")); From 3150a3698861ac33976462e2d033c5788cb2283a Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 21 Aug 2015 15:57:28 +0200 Subject: [PATCH 077/134] More debug messages. --- ykcs11/ykcs11.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 7376d8e..b7d3be1 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -795,8 +795,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } // TODO: check more conditions @@ -886,8 +888,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } if (pTemplate == NULL_PTR || ulCount == 0) return CKR_ARGUMENTS_BAD; @@ -947,8 +951,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } if (find_obj.active == CK_TRUE) return CKR_OPERATION_ACTIVE; @@ -1036,8 +1042,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } if (phObject == NULL_PTR || ulMaxObjectCount == 0 || @@ -1084,8 +1092,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } if (find_obj.active != CK_TRUE) return CKR_OPERATION_NOT_INITIALIZED; @@ -1290,8 +1300,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } if (op_info.type != YKCS11_NOOP) { DBG(("Other operation in process")); @@ -1717,8 +1729,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( return CKR_SESSION_CLOSED; } - if (hSession != session.handle) + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); return CKR_SESSION_HANDLE_INVALID; + } if (session.info.state != CKS_RW_SO_FUNCTIONS) { DBG(("Authentication required to generate keys")); @@ -1734,8 +1748,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( pPublicKeyTemplate == NULL_PTR || pPrivateKeyTemplate == NULL_PTR || phPublicKey == NULL_PTR || - phPrivateKey == NULL_PTR) + phPrivateKey == NULL_PTR) { + DBG(("Wrong/Missing parameter")); return CKR_ARGUMENTS_BAD; + } DBG(("Trying to generate a key pair with mechanism %lx", pMechanism->mechanism)); From 4fec8063354c392e6944e9185408ab2fdc42eab8 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 24 Aug 2015 11:17:07 +0200 Subject: [PATCH 078/134] Add support for ECDSA_SHA256. --- ykcs11/mechanisms.c | 11 +++++++++-- ykcs11/pkcs11t.h | 6 ++++++ ykcs11/yubico_token.c | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index f4a0d78..fd85abd 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -19,7 +19,8 @@ static const CK_MECHANISM_TYPE sign_mechanisms[] = { CKM_SHA384_RSA_PKCS_PSS, CKM_SHA512_RSA_PKCS_PSS, CKM_ECDSA, - CKM_ECDSA_SHA1 + CKM_ECDSA_SHA1, + CKM_ECDSA_SHA256 }; // Supported mechanisms for key pair generation @@ -126,6 +127,7 @@ CK_BBOOL is_hashed_mechanism(CK_MECHANISM_TYPE m) { case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: case CKM_ECDSA_SHA1: + case CKM_ECDSA_SHA256: case CKM_SHA_1: case CKM_SHA256: case CKM_SHA384: @@ -160,6 +162,7 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) { case CKM_SHA256_RSA_PKCS: case CKM_SHA256_RSA_PKCS_PSS: + case CKM_ECDSA_SHA256: return do_md_init(YKCS11_SHA256, &op_info->op.sign.md_ctx); case CKM_SHA384_RSA_PKCS: @@ -201,6 +204,7 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: case CKM_ECDSA_SHA1: + case CKM_ECDSA_SHA256: rv = do_md_update(op_info->op.sign.md_ctx, in, in_len); if (rv != CKR_OK) return CKR_FUNCTION_FAILED; @@ -278,6 +282,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { return do_pkcs_1_t1(op_info->buf, len, op_info->buf, &op_info->buf_len, op_info->op.sign.key_len); case CKM_ECDSA_SHA1: + case CKM_ECDSA_SHA256: // Finalize the hash rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); if (rv != CKR_OK) @@ -358,7 +363,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG if (op_info->op.gen.rsa == CK_FALSE) return CKR_ATTRIBUTE_VALUE_INVALID; - if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 && + if (*((CK_ULONG_PTR) templ[i].pValue) != 1024 && *((CK_ULONG_PTR) templ[i].pValue) != 2048) { // TODO: make define? DBG(("Unsupported MODULUS_BITS (key length)")); return CKR_ATTRIBUTE_VALUE_INVALID; @@ -386,6 +391,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG case CKA_ENCRYPT: case CKA_VERIFY: case CKA_WRAP: + case CKA_DERIVE: // Ignore these attributes for now break; @@ -451,6 +457,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG case CKA_SIGN: case CKA_PRIVATE: case CKA_TOKEN: + case CKA_DERIVE: // Ignore these attributes for now break; diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index 9543f5c..f793cfe 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -647,6 +647,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE; //#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 // Deprecated in 2.11 #define CKM_ECDSA 0x00001041UL #define CKM_ECDSA_SHA1 0x00001042UL +/* NOT STANDARD */ +#define CKM_ECDSA_SHA224 0x00001043UL +#define CKM_ECDSA_SHA256 0x00001044UL +#define CKM_ECDSA_SHA384 0x00001045UL +#define CKM_ECDSA_SHA512 0x00001046UL +/* NOT STANDARD */ /* Added for 2.4 */ #define CKM_ECDH1_DERIVE 0x00001050UL diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index 5915780..b005d3a 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -32,6 +32,7 @@ static const CK_MECHANISM_TYPE token_mechanisms[] = { // KEEP ALIGNED WITH token //CKM_ECDSA_KEY_PAIR_GEN, Same as CKM_EC_KEY_PAIR_GEN, deprecated in 2.11 CKM_ECDSA, CKM_ECDSA_SHA1, + CKM_ECDSA_SHA256, CKM_SHA_1, CKM_SHA256, CKM_SHA384, @@ -57,6 +58,7 @@ static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH //{, , }, // CKM_ECDSA_KEY_PAIR_GEN Same as CKM_EC_KEY_PAIR_GEN deprecated in 2.11 {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_ECDSA {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_ECDSA_SHA1 + {MIN_ECC_KEY_SIZE, MAX_ECC_KEY_SIZE, CKF_HW | CKF_SIGN}, // CKM_ECDSA_SHA256 {0, 0, CKF_DIGEST}, // CKM_SHA_1 {0, 0, CKF_DIGEST}, // CKM_SHA256 {0, 0, CKF_DIGEST}, // CKM_SHA384 From e2c4e9fc2ebc0c97c9bd8ef7e122c244390332fd Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 24 Aug 2015 14:20:01 +0200 Subject: [PATCH 079/134] Use longer buffer to store the signature. --- ykcs11/ykcs11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index b7d3be1..1fa0643 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1435,7 +1435,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (pSignature == NULL_PTR) { // Just return the size of the signature - *pulSignatureLen = op_info.op.sign.key_len / 8; + *pulSignatureLen = op_info.op.sign.key_len / 8 * 2 + 32; // Approximate the size of the signature. Specs agree with this. DBG(("The size of the signature will be %lu", *pulSignatureLen)); DOUT; From f776ac58a3af2d98e671c0cd59b9d6f23e88543c Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 24 Aug 2015 17:39:00 +0200 Subject: [PATCH 080/134] Strip DER encoding from EC signatures. --- ykcs11/utils.c | 26 +++++++++++++++++++++++--- ykcs11/utils.h | 2 ++ ykcs11/ykcs11.c | 9 +++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 170fd37..05fedfc 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -87,7 +87,7 @@ failure: for (i = 0; i < *n_slots; i++) if (has_token(slots + i)) destroy_token(slots + i); - + return CKR_FUNCTION_FAILED; } @@ -157,7 +157,7 @@ CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { // TODO: also get token objects here? (and destroy on failure) slot->token->objects = NULL; slot->token->n_objects = 0; - + return CKR_OK; } @@ -173,5 +173,25 @@ CK_BBOOL is_valid_key_id(CK_BYTE id) { return CK_FALSE; return CK_TRUE; - +} + +void strip_DER_encoding_from_ECSIG(CK_BYTE_PTR data, CK_ULONG_PTR len) { + + CK_BYTE_PTR ptr; + CK_ULONG n_len; + + // Maximum DER length for P256 is 2 + 2 + 33 + 2 + 33 = 72 + if (*len <= 72) + n_len = 32; + else + n_len = 48; + + ptr = data + 4; + if (*ptr == 0) + ptr++; + + memmove(data, ptr, n_len); + memmove(data+n_len, data + *len - n_len, n_len); + + *len = n_len * 2; } diff --git a/ykcs11/utils.h b/ykcs11/utils.h index 8ada4dc..af6f82a 100644 --- a/ykcs11/utils.h +++ b/ykcs11/utils.h @@ -11,4 +11,6 @@ void destroy_token(ykcs11_slot_t *slot); CK_BBOOL is_valid_key_id(CK_BYTE id); +void strip_DER_encoding_from_ECSIG(CK_BYTE_PTR data, CK_ULONG_PTR len); + #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 1fa0643..6a83375 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1490,6 +1490,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( DBG(("Got %lu bytes back", *pulSignatureLen)); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); + if (!is_RSA_mechanism(op_info.mechanism.mechanism)) { + // ECDSA, we must remove the DER encoding and only return R,S + // as required by the specs + strip_DER_encoding_from_ECSIG(pSignature, pulSignatureLen); + + DBG(("After removing DER encoding %lu", *pulSignatureLen)); + dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); + } + op_info.type = YKCS11_NOOP; // TODO: anything to clear here? DOUT; From 5f306a8d1c1b5559fe1d9f2e39ee97352901fd87 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 26 Aug 2015 10:54:27 -0400 Subject: [PATCH 081/134] Fixed x509 certificate created during generation to comply with OpenSSL 1.0.1i more strict rules. --- ykcs11/openssl_utils.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 617d6b0..cee91b2 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -36,7 +36,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { } 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) { + CK_BYTE_PTR out, CK_ULONG_PTR out_len) { X509 *cert = NULL; EVP_PKEY *key = NULL; @@ -132,7 +132,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; - // TODO: add more info like issuer? tm = ASN1_TIME_new(); if (tm == NULL) goto create_empty_cert_cleanup; @@ -141,6 +140,16 @@ 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); + // Manually set the signature algorithms. + // OpenSSL 1.0.1i complains about empty DER fields + // 8 => md5WithRsaEncryption + cert->sig_alg->algorithm = OBJ_nid2obj(8); + cert->cert_info->signature->algorithm = OBJ_nid2obj(8); + + // Manually set a signature (same reason as before) + ASN1_BIT_STRING_set_bit(cert->signature, 8, 1); + ASN1_BIT_STRING_set(cert->signature, "\x00", 1); + len = i2d_X509(cert, NULL); if (len < 0) goto create_empty_cert_cleanup; @@ -261,7 +270,7 @@ CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) { RSA_free(rsa); rsa = NULL; - + return key_len; } @@ -422,7 +431,7 @@ CK_RV do_pkcs_1_digest_info(CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_BYTE_PT } CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, - CK_BYTE_PTR out, CK_ULONG_PTR out_len) { + CK_BYTE_PTR out, CK_ULONG_PTR out_len) { unsigned char em[512]; // Max for this is ceil((|key_len_bits| - 1) / 8) OpenSSL_add_all_digests(); From 5a2c00deb777730a7e9b0c42a39e8815e4e2b928 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 25 Aug 2015 15:55:52 +0200 Subject: [PATCH 082/134] Add of DigestInit. --- ykcs11/mechanisms.c | 37 +++++++++++++++++++++++++++++++++++++ ykcs11/mechanisms.h | 2 ++ ykcs11/ykcs11.c | 44 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index fd85abd..a469574 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -30,6 +30,14 @@ static const CK_MECHANISM_TYPE generation_mechanisms[] = { CKM_EC_KEY_PAIR_GEN }; +// Supported mechanisms for hashing +static const CK_MECHANISM_TYPE hash_mechanisms[] = { + CKM_SHA_1, + CKM_SHA256, + CKM_SHA384, + CKM_SHA512 +}; + CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) { CK_ULONG i; @@ -470,3 +478,32 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG return CKR_OK; } + +CK_RV check_hash_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) { + + CK_ULONG i; + CK_BBOOL supported = CK_FALSE; + token_vendor_t token; + CK_MECHANISM_INFO info; + + // Check if the mechanism is supported by the module + for (i = 0; i < sizeof(hash_mechanisms) / sizeof(CK_MECHANISM_TYPE); i++) { + if (m->mechanism == hash_mechanisms[i]) { + supported = CK_TRUE; + break; + } + } + if (supported == CK_FALSE) + return CKR_MECHANISM_INVALID; + + // Check if the mechanism is supported by the token + token = get_token_vendor(s->slot->token->vid); + + if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK) + return CKR_MECHANISM_INVALID; + + // TODO: also check that parametes make sense if any? And key size is in [min max] + + return CKR_OK; + +} diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index c49ca04..af00225 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -16,4 +16,6 @@ CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); +CK_RV check_hash_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); + #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 6a83375..9e6920f 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -217,8 +217,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( ) { DIN; - CK_VERSION ver = {0, 0}; - token_vendor_t token; CK_BYTE buf[64]; if (piv_state == NULL) { @@ -246,8 +244,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( return CKR_TOKEN_NOT_RECOGNIZED; } - token = get_token_vendor(slots[slotID].token->vid); - memcpy(pInfo, &slots[slotID].token->info, sizeof(CK_TOKEN_INFO)); // Overwrite values that are application specific @@ -686,7 +682,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( ) { DIN; - CK_ULONG tries; + CK_ULONG tries = 0; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -1219,7 +1215,43 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)( ) { DIN; - DBG(("TODO!!!")); + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); + return CKR_SESSION_CLOSED; + } + + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); + return CKR_SESSION_HANDLE_INVALID; + } + + if (op_info.type != YKCS11_NOOP) { + DBG(("Other operation in process")); + return CKR_OPERATION_ACTIVE; + } + + if (pMechanism == NULL_PTR) { + DBG(("Wrong/Missing parameter")); + return CKR_ARGUMENTS_BAD; + } + + DBG(("Trying to hash some data with mechanism %lu", pMechanism->mechanism)); + + // Check if mechanism is supported + if (check_hash_mechanism(&session, pMechanism) != CKR_OK) { + DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism)); + return CKR_MECHANISM_INVALID; + } + memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); + + op_info.type = YKCS11_HASH; + DOUT; return CKR_OK; } From 25110ec122b27e1b41d14a0dae02b74e1cf4131d Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 25 Aug 2015 15:59:59 +0200 Subject: [PATCH 083/134] Remove some warnings. --- ykcs11/mechanisms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index a469574..23285e8 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -1,4 +1,6 @@ #include "mechanisms.h" +#include "openssl_utils.h" +#include "utils.h" #include "debug.h" #include @@ -336,7 +338,6 @@ CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) { CK_ULONG i; - CK_BBOOL rsa_mechanism; op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism); @@ -416,7 +417,6 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) { CK_ULONG i; - CK_BBOOL rsa_mechanism; op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism); From d7f5dd35f4e2f92095a8d4f13dbd7d3aa13b000c Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 26 Aug 2015 16:59:03 +0200 Subject: [PATCH 084/134] Squalch more warnings. --- ykcs11/ykcs11.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 9e6920f..3bffaaf 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -4,6 +4,7 @@ #include #include #include "obj_types.h" +#include "objects.h" #include "utils.h" #include "mechanisms.h" #include "openssl_types.h" @@ -217,7 +218,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( ) { DIN; - CK_BYTE buf[64]; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -682,7 +682,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( ) { DIN; - CK_ULONG tries = 0; + CK_ULONG tries = 0; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -1747,8 +1747,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( DIN; CK_RV rv; token_vendor_t token; - CK_ULONG n_objs; - CK_ULONG n_certs; CK_ULONG i; CK_BBOOL is_new; CK_ULONG dobj_id; From 5ca058bdfae4918abef3d7965d549d29a296d269 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 28 Aug 2015 13:47:57 +0200 Subject: [PATCH 085/134] Added certificate import --- ykcs11/mechanisms.h | 4 +- ykcs11/objects.c | 47 ++++++++++++++ ykcs11/objects.h | 3 + ykcs11/openssl_utils.c | 32 ++++++++-- ykcs11/openssl_utils.h | 1 + ykcs11/token_vendors.c | 39 ++++++++++++ ykcs11/token_vendors.h | 2 + ykcs11/ykcs11.c | 138 +++++++++++++++++++++++++++++++++++++++-- 8 files changed, 255 insertions(+), 11 deletions(-) diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index af00225..27bdced 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -13,8 +13,8 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i CK_RV apply_sign_mechanism_finalize(op_info_t *op_info); CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); -CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); -CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); +CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); // TODO: Move to objects.c +CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); // TODO: Move to objects.c CK_RV check_hash_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); diff --git a/ykcs11/objects.c b/ykcs11/objects.c index ecfe714..92e8b70 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -4,6 +4,7 @@ #include #include #include "openssl_utils.h" +#include "utils.h" #include "debug.h" #define IS_CERT(x) (((x) >= PIV_CERT_OBJ_X509_PIV_AUTH && (x) < PIV_CERT_OBJ_LAST) ? CK_TRUE : CK_FALSE) @@ -912,3 +913,49 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) { return CKR_OK; } + +CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, + CK_BYTE_PTR id,CK_BYTE_PTR *value, CK_ULONG_PTR cert_len) { + + CK_ULONG i; + CK_BBOOL has_id = CK_FALSE; + CK_BBOOL has_value = CK_FALSE; + + for (i = 0; i < n; i++) { + switch (templ[i].type) { + case CKA_CLASS: + // Technically redundant check + if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_CERTIFICATE) + return CKR_ATTRIBUTE_VALUE_INVALID; + + break; + + case CKA_ID: + has_id = CK_TRUE; + if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE) + return CKR_ATTRIBUTE_VALUE_INVALID; + + *id = *((CK_BYTE_PTR)templ[i].pValue); + break; + + case CKA_VALUE: + has_value = CK_TRUE; + *value = (CK_BYTE_PTR)templ[i].pValue; + + *cert_len = 0; + *cert_len += get_length(value + 1, cert_len) + 1; + break; + + default: + // Ignore other attributes for now + DBG(("Invalid %lx", templ[i].type)); + return CKR_ATTRIBUTE_TYPE_INVALID; + } + } + + if (has_id == CK_FALSE || + has_value == CK_FALSE) + return CKR_TEMPLATE_INCOMPLETE; + + return CKR_OK; +} diff --git a/ykcs11/objects.h b/ykcs11/objects.h index cbc3b0e..84dded1 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -12,4 +12,7 @@ CK_BBOOL is_private_object(ykcs11_session_t *s, CK_OBJECT_HANDLE obj); CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); +CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, + CK_BYTE_PTR *value, CK_ULONG_PTR cert_len); + #endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index cee91b2..08cf954 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -14,10 +14,16 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { return CKR_HOST_MEMORY;*/ //dump_hex(data, len, stderr, CK_TRUE); - if (*p++ != 0x70) - return CKR_FUNCTION_FAILED; - - p += get_length(p, &cert_len); + if (*p == 0x70) { + // The certificate is in "PIV" format 0x70 len 0x30 len ... + p++; + p += get_length(p, &cert_len); + } + else { + // Raw certificate 0x30 len ... + cert_len = 0; + cert_len += get_length(p + 1, &cert_len) + 1; + } *cert = d2i_X509(NULL, &p, cert_len); if (*cert == NULL) @@ -223,6 +229,24 @@ create_empty_cert_cleanup: return rv; } +CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len) { + + X509 *cert; + const unsigned char *p = in; // Mandatory temp variable required by OpenSSL + int len; + + len = 0; + len += get_length(p + 1, &len) + 1; + + *cert_len = len; + + cert = d2i_X509(NULL, &p, *cert_len); + if (cert == NULL) + return CKR_FUNCTION_FAILED; + + return CKR_OK; +} + CK_RV free_cert(X509 *cert) { X509_free((X509 *) cert); diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 03f0c2a..14f8a28 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -12,6 +12,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); 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); +CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len); CK_RV free_cert(X509 *cert); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 083aea2..4bc9348 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -1,7 +1,9 @@ #include "token_vendors.h" #include "yubico_token.h" +#include "openssl_utils.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]; @@ -85,6 +87,41 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE return CKR_OK; } +static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_BYTE_PTR in) { + + unsigned char certdata[2100]; + unsigned char *certptr; + CK_ULONG cert_len; + + CK_RV rv; + + // Check whether or not we have a valid cert + if ((rv = do_check_cert(in, &cert_len)) != CKR_OK) + return rv; + + if (cert_len > 2100) + return CKR_FUNCTION_FAILED; + + certptr = certdata; + + *certptr++ = 0x70; + certptr += set_length(certptr, cert_len); + memcpy(certptr, in, cert_len); + certptr += cert_len; + + *certptr++ = 0x71; + *certptr++ = 1; + *certptr++ = 0; /* certinfo (gzip etc) */ + *certptr++ = 0xfe; /* LRC */ + *certptr++ = 0; + + // Store the certificate into the token + if (ykpiv_save_object(state, cert_id, certdata, (size_t)(certptr - certdata)) != YKPIV_OK) + return CKR_DEVICE_ERROR; + + return CKR_OK; +} + token_vendor_t get_token_vendor(vendor_id_t vid) { token_vendor_t v; @@ -103,6 +140,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_object_list = YUBICO_get_token_object_list; v.get_token_raw_certificate = YUBICO_get_token_raw_certificate; v.token_generate_key = COMMON_token_generate_key; + v.token_import_cert = COMMON_token_import_cert; break; case UNKNOWN: @@ -120,6 +158,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_object_list = NULL; v.get_token_raw_certificate = NULL; v.token_generate_key = NULL; + v.token_import_cert = NULL; } return v; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 041e2a0..e07f96e 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -21,6 +21,7 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT // Common token functions below typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); +typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); // TODO: replace all the common call with functions defined in .c that use libykpiv @@ -38,6 +39,7 @@ typedef struct { get_t_object_list_f get_token_object_list; get_t_raw_certificate_f get_token_raw_certificate; t_generate_key_f token_generate_key; + t_import_cert_f token_import_cert; } token_vendor_t; token_vendor_t get_token_vendor(vendor_id_t vid); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 3bffaaf..6297040 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -821,7 +821,136 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( ) { DIN; - DBG(("TODO!!!")); + + CK_ULONG i; + CK_RV rv; + CK_OBJECT_CLASS class; + CK_BYTE id; + CK_BYTE_PTR value; + CK_ULONG len; + token_vendor_t token; + CK_BBOOL is_new; + CK_OBJECT_HANDLE object; + CK_ULONG cert_id; + CK_ULONG pvtk_id; + CK_ULONG pubk_id; + piv_obj_id_t *obj_ptr; + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); + return CKR_SESSION_CLOSED; + } + + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); + return CKR_SESSION_HANDLE_INVALID; + } + + if (session.info.state != CKS_RW_SO_FUNCTIONS) { // TODO: does a regular user ever call this function? + DBG(("Authentication required to import objects")); + return CKR_SESSION_READ_ONLY; + } + + if (pTemplate == NULL_PTR || + phObject == NULL_PTR) { + DBG(("Wrong/Missing parameter")); + return CKR_ARGUMENTS_BAD; + } + + class = CKO_VENDOR_DEFINED; // Use this as a known value + for (i = 0; i < ulCount; i++) { + if (pTemplate[i].type == CKA_CLASS) { + class = *((CK_ULONG_PTR)pTemplate[i].pValue); + + // Can only import certificates and private keys + if (*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_CERTIFICATE && + *((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_PUBLIC_KEY) { + DBG(("Unsupported class %lu", class)); + return CKR_ATTRIBUTE_VALUE_INVALID; + } + } + } + + if (class == CKO_VENDOR_DEFINED) { + DBG(("Object class must be specified")); + return CKR_TEMPLATE_INCOMPLETE; + } + + token = get_token_vendor(session.slot->token->vid); + + switch (class) { + case CKO_CERTIFICATE: + DBG(("Importing certificate")); + + rv = check_create_cert(pTemplate, ulCount, &id, &value, &len); + if (rv != CKR_OK) { + DBG(("Certificate template not valid")); + return rv; + } + DBG(("Certificate id is %u", id)); + + object = PIV_CERT_OBJ_X509_PIV_AUTH + id ; + + rv = token.token_import_cert(piv_state, piv_2_ykpiv(object), value); // TODO: make function to get cert id + if (rv != CKR_OK) { + DBG(("Unable to import certificate")); + return rv; + } + + is_new = CK_TRUE; + for (i = 0; i < session.slot->token->n_objects; i++) { + if (session.slot->token->objects[i] == object) + is_new = CK_FALSE; + } + + cert_id = PIV_CERT_OBJ_X509_PIV_AUTH + id; // TODO: make function for these + pvtk_id = PIV_PVTK_OBJ_PIV_AUTH + id; + pubk_id = PIV_PUBK_OBJ_PIV_AUTH + id; + + // Check whether we created a new object or updated an existing one + if (is_new == CK_TRUE) { + // New object created, add it to the object list + + // Each object counts as three, even if we just only added a certificate + session.slot->token->n_objects += 3; + session.slot->token->n_certs++; + + obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); + if (obj_ptr == NULL) { + DBG(("Unable to store new item in the session")); + return CKR_HOST_MEMORY; + } + session.slot->token->objects = obj_ptr; + + obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 3; + *obj_ptr++ = cert_id; + *obj_ptr++ = pvtk_id; + *obj_ptr++ = pubk_id; + } + + rv = store_cert(cert_id, value, len); + if (rv != CKR_OK) { + DBG(("Unable to store certificate data")); + return CKR_FUNCTION_FAILED; + } + + break; + + case CKO_PRIVATE_KEY: + //rv = create_pvt_key(); + return CKR_FUNCTION_FAILED; + break; + + default: + DBG(("Unknown object type")); + return CKR_ATTRIBUTE_TYPE_INVALID; + } + DOUT; return CKR_OK; } @@ -1865,8 +1994,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( if (is_new == CK_TRUE) { // New object created, add it to the object list - // Each object counts as four - session.slot->token->n_objects += 4; + // Each object counts as three (data object is always there) + session.slot->token->n_objects += 3; session.slot->token->n_certs++; obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); @@ -1876,8 +2005,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( } session.slot->token->objects = obj_ptr; - obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 4; - *obj_ptr++ = dobj_id; + obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 3; *obj_ptr++ = cert_id; *obj_ptr++ = pvtk_id; *obj_ptr++ = pubk_id; From d2cefc66b7212bdd899f5c501a977bcbb691e632 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 28 Aug 2015 17:15:11 +0200 Subject: [PATCH 086/134] Initial stab at private key import. --- ykcs11/objects.c | 167 ++++++++++++++++++++++++++++++++++++++++- ykcs11/objects.h | 10 +++ ykcs11/token_vendors.c | 11 +++ ykcs11/token_vendors.h | 6 +- ykcs11/ykcs11.c | 60 +++++++++++++-- 5 files changed, 245 insertions(+), 9 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 92e8b70..3594064 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -942,11 +942,12 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, has_value = CK_TRUE; *value = (CK_BYTE_PTR)templ[i].pValue; - *cert_len = 0; - *cert_len += get_length(value + 1, cert_len) + 1; + /**cert_len = 0; + *cert_len += get_length(value + 1, cert_len) + 1;*/ + *cert_len = templ[i].ulValueLen; break; - default: + default: // TODO: don't error on valid parameters // Ignore other attributes for now DBG(("Invalid %lx", templ[i].type)); return CKR_ATTRIBUTE_TYPE_INVALID; @@ -959,3 +960,163 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, return CKR_OK; } + +CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, + CK_BYTE_PTR *value, CK_ULONG_PTR cert_len, + CK_BYTE_PTR *ec_params, CK_ULONG_PTR ec_params_len) { + + CK_ULONG i; + CK_BBOOL has_id = CK_FALSE; + CK_BBOOL has_value = CK_FALSE; + CK_BBOOL has_params = CK_FALSE; + + for (i = 0; i < n; i++) { + switch (templ[i].type) { + case CKA_CLASS: + if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_PRIVATE_KEY) + return CKR_ATTRIBUTE_VALUE_INVALID; + + break; + + case CKA_KEY_TYPE: + if (*((CK_ULONG_PTR)templ[i].pValue) != CKK_ECDSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + + break; + + case CKA_ID: + has_id = CK_TRUE; + if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE) + return CKR_ATTRIBUTE_VALUE_INVALID; + + *id = *((CK_BYTE_PTR)templ[i].pValue); + break; + + case CKA_VALUE: + has_value = CK_TRUE; + *value = (CK_BYTE_PTR)templ[i].pValue; + *cert_len = templ[i].ulValueLen; + + break; + + case CKA_EC_PARAMS: + has_params = CK_TRUE; + *ec_params = (CK_BYTE_PTR)templ[i].pValue; + *ec_params_len = templ[i].ulValueLen; + + break; + + default: // TODO: don't error on valid parameters + // Ignore other attributes for now + DBG(("Invalid %lx", templ[i].type)); + return CKR_ATTRIBUTE_TYPE_INVALID; + } + } + + if (has_id == CK_FALSE || + has_value == CK_FALSE || + has_params == CK_FALSE) + return CKR_TEMPLATE_INCOMPLETE; + + return CKR_OK; +} + +CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, + CK_BYTE_PTR *e, CK_ULONG_PTR e_len, + CK_BYTE_PTR *p, CK_ULONG_PTR p_len, + CK_BYTE_PTR *q, CK_ULONG_PTR q_len, + CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len, + CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len, + CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len) { + + CK_ULONG i; + CK_BBOOL has_id = CK_FALSE; + CK_BBOOL has_e = CK_FALSE; + CK_BBOOL has_p = CK_FALSE; + CK_BBOOL has_q = CK_FALSE; + CK_BBOOL has_dp = CK_FALSE; + CK_BBOOL has_dq = CK_FALSE; + CK_BBOOL has_qinv = CK_FALSE; + + for (i = 0; i < n; i++) { + switch (templ[i].type) { + case CKA_CLASS: + if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_PRIVATE_KEY) + return CKR_ATTRIBUTE_VALUE_INVALID; + + break; + + case CKA_ID: + has_id = CK_TRUE; + if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE) + return CKR_ATTRIBUTE_VALUE_INVALID; + + *id = *((CK_BYTE_PTR)templ[i].pValue); + break; + + case CKA_KEY_TYPE: + if (*((CK_ULONG_PTR)templ[i].pValue) != CKK_RSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + + break; + + case CKA_PUBLIC_EXPONENT: // TODO: check that it is F4 + has_e = CK_TRUE; + *e = (CK_BYTE_PTR)templ[i].pValue; + *e_len = templ[i].ulValueLen; + + break; + + case CKA_PRIME_1: + has_p = CK_TRUE; + *p = (CK_BYTE_PTR)templ[i].pValue; + *p_len = templ[i].ulValueLen; + + break; + + case CKA_PRIME_2: + has_q = CK_TRUE; + *q = (CK_BYTE_PTR)templ[i].pValue; + *q_len = templ[i].ulValueLen; + + break; + + case CKA_EXPONENT_1: + has_dp = CK_TRUE; + *dp = (CK_BYTE_PTR)templ[i].pValue; + *dp_len = templ[i].ulValueLen; + + break; + + case CKA_EXPONENT_2: + has_dq = CK_TRUE; + *dq = (CK_BYTE_PTR)templ[i].pValue; + *dq_len = templ[i].ulValueLen; + + break; + + case CKA_COEFFICIENT: + has_qinv = CK_TRUE; + *qinv = (CK_BYTE_PTR)templ[i].pValue; + *qinv_len = templ[i].ulValueLen; + + break; + + default: // TODO: don't error on valid parameters + // Ignore other attributes for now + DBG(("Invalid %lx", templ[i].type)); + return CKR_ATTRIBUTE_TYPE_INVALID; + } + } + + if (has_id == CK_FALSE || + has_e == CK_FALSE || + has_p == CK_FALSE || + has_q == CK_FALSE || + has_dp == CK_FALSE || + has_dq == CK_FALSE || + has_qinv == CK_FALSE) + return CKR_TEMPLATE_INCOMPLETE; + + return CKR_OK; +} diff --git a/ykcs11/objects.h b/ykcs11/objects.h index 84dded1..b48cc57 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -14,5 +14,15 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len); +CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, + CK_BYTE_PTR *value, CK_ULONG_PTR cert_len, + CK_BYTE_PTR *ec_params, CK_ULONG_PTR ec_params_len); +CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, + CK_BYTE_PTR *e, CK_ULONG_PTR e_len, + CK_BYTE_PTR *p, CK_ULONG_PTR p_len, + CK_BYTE_PTR *q, CK_ULONG_PTR q_len, + CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len, + CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len, + CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len); #endif diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 4bc9348..bdb5218 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -122,6 +122,15 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B return CKR_OK; } +CK_RV COMMON_token_import_private_key(ykpiv_state *state , CK_BYTE_PTR key_id, CK_BYTE_PTR p, CK_ULONG p_len, + CK_BYTE_PTR q, CK_ULONG q_len, CK_BYTE_PTR dp, CK_ULONG dp_len, + CK_BYTE_PTR dq, CK_ULONG dq_len, CK_BYTE_PTR qinv, CK_ULONG qinv_len, + CK_BYTE_PTR ec_data, CK_ULONG ec_data_len) { + + return CKR_OK; + +} + token_vendor_t get_token_vendor(vendor_id_t vid) { token_vendor_t v; @@ -141,6 +150,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_raw_certificate = YUBICO_get_token_raw_certificate; v.token_generate_key = COMMON_token_generate_key; v.token_import_cert = COMMON_token_import_cert; + v.token_import_private_key = COMMON_token_import_private_key; break; case UNKNOWN: @@ -159,6 +169,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_raw_certificate = NULL; v.token_generate_key = NULL; v.token_import_cert = NULL; + v.token_import_private_key = NULL; } return v; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index e07f96e..5a86be4 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -22,8 +22,11 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT // Common token functions below typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); +typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE_PTR ,CK_BYTE_PTR, CK_ULONG, + CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG, + CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG); -// TODO: replace all the common call with functions defined in .c that use libykpiv +// TODO: replace all the common calls with functions defined in .c that use libykpiv typedef struct { get_t_label_f get_token_label; @@ -40,6 +43,7 @@ typedef struct { get_t_raw_certificate_f get_token_raw_certificate; t_generate_key_f token_generate_key; t_import_cert_f token_import_cert; + t_import_private_key_f token_import_private_key; } token_vendor_t; token_vendor_t get_token_vendor(vendor_id_t vid); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 6297040..b0a326c 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -827,15 +827,31 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_OBJECT_CLASS class; CK_BYTE id; CK_BYTE_PTR value; - CK_ULONG len; + CK_ULONG value_len; + CK_BYTE_PTR ec_params; + CK_ULONG ec_params_len; + CK_BYTE_PTR e; + CK_ULONG e_len; + CK_BYTE_PTR p; + CK_ULONG p_len; + CK_BYTE_PTR q; + CK_ULONG q_len; + CK_BYTE_PTR dp; + CK_ULONG dp_len; + CK_BYTE_PTR dq; + CK_ULONG dq_len; + CK_BYTE_PTR qinv; + CK_ULONG qinv_len; token_vendor_t token; CK_BBOOL is_new; + CK_BBOOL is_rsa; CK_OBJECT_HANDLE object; CK_ULONG cert_id; CK_ULONG pvtk_id; CK_ULONG pubk_id; piv_obj_id_t *obj_ptr; + if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -869,7 +885,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( // Can only import certificates and private keys if (*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_CERTIFICATE && - *((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_PUBLIC_KEY) { + *((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_PRIVATE_KEY) { DBG(("Unsupported class %lu", class)); return CKR_ATTRIBUTE_VALUE_INVALID; } @@ -887,7 +903,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( case CKO_CERTIFICATE: DBG(("Importing certificate")); - rv = check_create_cert(pTemplate, ulCount, &id, &value, &len); + rv = check_create_cert(pTemplate, ulCount, &id, &value, &value_len); if (rv != CKR_OK) { DBG(("Certificate template not valid")); return rv; @@ -933,7 +949,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( *obj_ptr++ = pubk_id; } - rv = store_cert(cert_id, value, len); + rv = store_cert(cert_id, value, value_len); if (rv != CKR_OK) { DBG(("Unable to store certificate data")); return CKR_FUNCTION_FAILED; @@ -942,7 +958,41 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( break; case CKO_PRIVATE_KEY: - //rv = create_pvt_key(); + DBG(("Importing private key")); + + // Try to parse the key as EC + is_rsa = CK_FALSE; + rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &ec_params, &ec_params_len); + if (rv != CKR_OK) { + // Try to parse the key as RSA + is_rsa = CK_TRUE; + rv = check_create_rsa_key(pTemplate, ulCount, &id, &e, &e_len, &p, &p_len, + &q, &q_len, &dp, &dp_len, &dq, &dq_len, &qinv, &qinv_len); + if (rv != CKR_OK) { + DBG(("Private key template not valid")); + return rv; + } + } + + DBG(("Key id is %u", id)); + + if (is_rsa == CK_TRUE) { + DBG(("Key is RSA")); + rv = token.token_import_private_key(piv_state, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0); + if (rv != CKR_OK) { + DBG(("Unable to import RSA private key")); + return rv; + } + } + else { + DBG(("Key is ECDSA")); + rv = token.token_import_private_key(piv_state, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0); + if (rv != CKR_OK) { + DBG(("Unable to import ECDSA private key")); + return rv; + } + } + return CKR_FUNCTION_FAILED; break; From f646ec9dde3bb7d5c079fc04b96fd3d4f829e7af Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 1 Sep 2015 14:08:19 +0200 Subject: [PATCH 087/134] Added key import. --- ykcs11/objects.c | 109 +++++++++++++++++++++++++++-------------- ykcs11/objects.h | 12 ++--- ykcs11/openssl_utils.c | 4 +- ykcs11/token_vendors.c | 62 +++++++++++++++++++++-- ykcs11/token_vendors.h | 5 +- ykcs11/ykcs11.c | 36 ++++++-------- 6 files changed, 154 insertions(+), 74 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 3594064..9ca92c9 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -9,6 +9,9 @@ #define IS_CERT(x) (((x) >= PIV_CERT_OBJ_X509_PIV_AUTH && (x) < PIV_CERT_OBJ_LAST) ? CK_TRUE : CK_FALSE) +#define F4 "\x01\x00\x01" // TODO: already define in mechanisms.c. Move +#define PRIME256V1 "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" // TODO: already define in mechanisms.c. Move + CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); // TODO: static? CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); @@ -942,13 +945,16 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, has_value = CK_TRUE; *value = (CK_BYTE_PTR)templ[i].pValue; - /**cert_len = 0; - *cert_len += get_length(value + 1, cert_len) + 1;*/ *cert_len = templ[i].ulValueLen; break; - default: // TODO: don't error on valid parameters - // Ignore other attributes for now + case CKA_TOKEN: + case CKA_LABEL: + case CKA_SUBJECT: + // Ignore other attributes + break; + + default: DBG(("Invalid %lx", templ[i].type)); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -957,19 +963,21 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, if (has_id == CK_FALSE || has_value == CK_FALSE) return CKR_TEMPLATE_INCOMPLETE; - + return CKR_OK; } CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *value, CK_ULONG_PTR cert_len, - CK_BYTE_PTR *ec_params, CK_ULONG_PTR ec_params_len) { + CK_BYTE_PTR *value, CK_ULONG_PTR value_len) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; CK_BBOOL has_value = CK_FALSE; CK_BBOOL has_params = CK_FALSE; + CK_BYTE_PTR ec_params; + CK_ULONG ec_params_len; + for (i = 0; i < n; i++) { switch (templ[i].type) { case CKA_CLASS: @@ -995,19 +1003,25 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, case CKA_VALUE: has_value = CK_TRUE; *value = (CK_BYTE_PTR)templ[i].pValue; - *cert_len = templ[i].ulValueLen; - + *value_len = templ[i].ulValueLen; break; case CKA_EC_PARAMS: has_params = CK_TRUE; - *ec_params = (CK_BYTE_PTR)templ[i].pValue; - *ec_params_len = templ[i].ulValueLen; + ec_params = (CK_BYTE_PTR)templ[i].pValue; + ec_params_len = templ[i].ulValueLen; break; - default: // TODO: don't error on valid parameters - // Ignore other attributes for now + case CKA_TOKEN: + case CKA_LABEL: + case CKA_SUBJECT: + case CKA_SENSITIVE: + case CKA_DERIVE: + // Ignore other attributes + break; + + default: DBG(("Invalid %lx", templ[i].type)); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -1017,17 +1031,19 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, has_value == CK_FALSE || has_params == CK_FALSE) return CKR_TEMPLATE_INCOMPLETE; - + + if (*value_len != 32) + return CKR_ATTRIBUTE_VALUE_INVALID; + + if (*value_len == 32 && (ec_params_len != 10 || memcmp(ec_params, PRIME256V1, ec_params_len)) != 0) + return CKR_TEMPLATE_INCONSISTENT; + return CKR_OK; } CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *e, CK_ULONG_PTR e_len, - CK_BYTE_PTR *p, CK_ULONG_PTR p_len, - CK_BYTE_PTR *q, CK_ULONG_PTR q_len, - CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len, - CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len, - CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len) { + CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, + CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; @@ -1037,6 +1053,11 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BBOOL has_dp = CK_FALSE; CK_BBOOL has_dq = CK_FALSE; CK_BBOOL has_qinv = CK_FALSE; + CK_ULONG p_len; + CK_ULONG q_len; + CK_ULONG dp_len; + CK_ULONG dq_len; + CK_ULONG qinv_len; for (i = 0; i < n; i++) { switch (templ[i].type) { @@ -1060,50 +1081,57 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, break; - case CKA_PUBLIC_EXPONENT: // TODO: check that it is F4 + case CKA_PUBLIC_EXPONENT: has_e = CK_TRUE; - *e = (CK_BYTE_PTR)templ[i].pValue; - *e_len = templ[i].ulValueLen; - + + if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0) + return CKR_ATTRIBUTE_VALUE_INVALID; break; case CKA_PRIME_1: has_p = CK_TRUE; *p = (CK_BYTE_PTR)templ[i].pValue; - *p_len = templ[i].ulValueLen; - + p_len = templ[i].ulValueLen; + break; case CKA_PRIME_2: has_q = CK_TRUE; *q = (CK_BYTE_PTR)templ[i].pValue; - *q_len = templ[i].ulValueLen; - + q_len = templ[i].ulValueLen; + break; case CKA_EXPONENT_1: has_dp = CK_TRUE; *dp = (CK_BYTE_PTR)templ[i].pValue; - *dp_len = templ[i].ulValueLen; - + dp_len = templ[i].ulValueLen; + break; case CKA_EXPONENT_2: has_dq = CK_TRUE; *dq = (CK_BYTE_PTR)templ[i].pValue; - *dq_len = templ[i].ulValueLen; - + dq_len = templ[i].ulValueLen; + break; case CKA_COEFFICIENT: has_qinv = CK_TRUE; *qinv = (CK_BYTE_PTR)templ[i].pValue; - *qinv_len = templ[i].ulValueLen; + qinv_len = templ[i].ulValueLen; break; - default: // TODO: don't error on valid parameters - // Ignore other attributes for now + case CKA_TOKEN: + case CKA_LABEL: + case CKA_SUBJECT: + case CKA_SENSITIVE: + case CKA_DERIVE: + // Ignore other attributes + break; + + default: DBG(("Invalid %lx", templ[i].type)); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -1117,6 +1145,15 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, has_dq == CK_FALSE || has_qinv == CK_FALSE) return CKR_TEMPLATE_INCOMPLETE; - + + if (p_len != 64 || p_len != 128) + return CKR_ATTRIBUTE_VALUE_INVALID; + + *value_len = p_len; + + if (q_len != p_len || dp_len != p_len || + dq_len != p_len || qinv_len != p_len) + return CKR_ATTRIBUTE_VALUE_INVALID; + return CKR_OK; } diff --git a/ykcs11/objects.h b/ykcs11/objects.h index b48cc57..892cb54 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -15,14 +15,10 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len); CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *value, CK_ULONG_PTR cert_len, - CK_BYTE_PTR *ec_params, CK_ULONG_PTR ec_params_len); + CK_BYTE_PTR *value, CK_ULONG_PTR value_len); CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *e, CK_ULONG_PTR e_len, - CK_BYTE_PTR *p, CK_ULONG_PTR p_len, - CK_BYTE_PTR *q, CK_ULONG_PTR q_len, - CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len, - CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len, - CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len); + CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, + CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len); + #endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 08cf954..1756735 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -42,7 +42,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { } 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) { + CK_BYTE_PTR out, CK_ULONG_PTR out_len) { X509 *cert = NULL; EVP_PKEY *key = NULL; @@ -455,7 +455,7 @@ CK_RV do_pkcs_1_digest_info(CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_BYTE_PT } CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, - CK_BYTE_PTR out, CK_ULONG_PTR out_len) { + CK_BYTE_PTR out, CK_ULONG_PTR out_len) { unsigned char em[512]; // Max for this is ceil((|key_len_bits| - 1) / 8) OpenSSL_add_all_digests(); diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index bdb5218..30b9883 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -122,13 +122,65 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B return CKR_OK; } -CK_RV COMMON_token_import_private_key(ykpiv_state *state , CK_BYTE_PTR key_id, CK_BYTE_PTR p, CK_ULONG p_len, - CK_BYTE_PTR q, CK_ULONG q_len, CK_BYTE_PTR dp, CK_ULONG dp_len, - CK_BYTE_PTR dq, CK_ULONG dq_len, CK_BYTE_PTR qinv, CK_ULONG qinv_len, - CK_BYTE_PTR ec_data, CK_ULONG ec_data_len) { +CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYTE_PTR p, CK_BYTE_PTR q, + CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv, + CK_BYTE_PTR ec_data, CK_ULONG elem_len) { + + unsigned char key_data[1024]; + unsigned char *in_ptr = key_data; + unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, 0, key_id}; + unsigned char data[0xff]; + unsigned long recv_len = sizeof(data); + int sw; + + if (elem_len == 128) + templ[2] = YKPIV_ALGO_RSA2048; + else if (elem_len == 64) + templ[2] = YKPIV_ALGO_RSA1024; + else if(elem_len == 32) + templ[2] = YKPIV_ALGO_ECCP256; + + if (templ[2] == YKPIV_ALGO_RSA1024 ||templ[2] == YKPIV_ALGO_RSA2048) { + *in_ptr++ = 0x01; + in_ptr += set_length(in_ptr, elem_len); + memcpy(in_ptr, p, (size_t)(elem_len)); + in_ptr += elem_len; + + *in_ptr++ = 0x02; + in_ptr += set_length(in_ptr, elem_len); + memcpy(in_ptr, q, (size_t)(elem_len)); + in_ptr += elem_len; + + *in_ptr++ = 0x03; + in_ptr += set_length(in_ptr, elem_len); + memcpy(in_ptr, dp, (size_t)(elem_len)); + in_ptr += elem_len; + + *in_ptr++ = 0x04; + in_ptr += set_length(in_ptr, elem_len); + memcpy(in_ptr, dq, (size_t)(elem_len)); + in_ptr += elem_len; + + *in_ptr++ = 0x05; + in_ptr += set_length(in_ptr, elem_len); + memcpy(in_ptr, qinv, (size_t)(elem_len)); + in_ptr += elem_len; + } + else if(templ[2] == YKPIV_ALGO_ECCP256) { + *in_ptr++ = 0x06; + in_ptr += set_length(in_ptr, elem_len); + memcpy(in_ptr, ec_data, (size_t)(elem_len)); + in_ptr += elem_len; + } + + if(ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK) + return CKR_FUNCTION_FAILED; + + if(sw != 0x9000) + return CKR_DEVICE_ERROR; return CKR_OK; - + } token_vendor_t get_token_vendor(vendor_id_t vid) { diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 5a86be4..a5b6175 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -22,9 +22,8 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT // Common token functions below typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); -typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE_PTR ,CK_BYTE_PTR, CK_ULONG, - CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG, - CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG); +typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, + CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG); // TODO: replace all the common calls with functions defined in .c that use libykpiv diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index b0a326c..f5bacab 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -830,18 +830,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_ULONG value_len; CK_BYTE_PTR ec_params; CK_ULONG ec_params_len; - CK_BYTE_PTR e; - CK_ULONG e_len; CK_BYTE_PTR p; - CK_ULONG p_len; CK_BYTE_PTR q; - CK_ULONG q_len; CK_BYTE_PTR dp; - CK_ULONG dp_len; CK_BYTE_PTR dq; - CK_ULONG dq_len; CK_BYTE_PTR qinv; - CK_ULONG qinv_len; token_vendor_t token; CK_BBOOL is_new; CK_BBOOL is_rsa; @@ -910,7 +903,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( } DBG(("Certificate id is %u", id)); - object = PIV_CERT_OBJ_X509_PIV_AUTH + id ; + object = PIV_CERT_OBJ_X509_PIV_AUTH + id; rv = token.token_import_cert(piv_state, piv_2_ykpiv(object), value); // TODO: make function to get cert id if (rv != CKR_OK) { @@ -962,12 +955,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( // Try to parse the key as EC is_rsa = CK_FALSE; - rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &ec_params, &ec_params_len); + rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len); if (rv != CKR_OK) { // Try to parse the key as RSA is_rsa = CK_TRUE; - rv = check_create_rsa_key(pTemplate, ulCount, &id, &e, &e_len, &p, &p_len, - &q, &q_len, &dp, &dp_len, &dq, &dq_len, &qinv, &qinv_len); + rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len); if (rv != CKR_OK) { DBG(("Private key template not valid")); return rv; @@ -975,25 +967,29 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( } DBG(("Key id is %u", id)); + DBG(("ITEM LENGTH IS %lu", value_len)); + object = PIV_PVTK_OBJ_PIV_AUTH + id; if (is_rsa == CK_TRUE) { DBG(("Key is RSA")); - rv = token.token_import_private_key(piv_state, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0); + rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv, + NULL, + value_len); if (rv != CKR_OK) { DBG(("Unable to import RSA private key")); return rv; } } - else { - DBG(("Key is ECDSA")); - rv = token.token_import_private_key(piv_state, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0); - if (rv != CKR_OK) { - DBG(("Unable to import ECDSA private key")); - return rv; + else { + DBG(("Key is ECDSA")); + rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL, + value, + value_len); + if (rv != CKR_OK) { + DBG(("Unable to import ECDSA private key")); + return rv; } } - - return CKR_FUNCTION_FAILED; break; default: From c13426a2e884e8da281e90893fd4dad9c1167770 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 2 Sep 2015 11:49:17 +0200 Subject: [PATCH 088/134] Fixed typo. --- ykcs11/objects.c | 5 ++--- ykcs11/token_vendors.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 9ca92c9..cef92f6 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -918,7 +918,7 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) { } CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, - CK_BYTE_PTR id,CK_BYTE_PTR *value, CK_ULONG_PTR cert_len) { + CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; @@ -1083,7 +1083,6 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, case CKA_PUBLIC_EXPONENT: has_e = CK_TRUE; - if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0) return CKR_ATTRIBUTE_VALUE_INVALID; break; @@ -1146,7 +1145,7 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, has_qinv == CK_FALSE) return CKR_TEMPLATE_INCOMPLETE; - if (p_len != 64 || p_len != 128) + if (p_len != 64 && p_len != 128) return CKR_ATTRIBUTE_VALUE_INVALID; *value_len = p_len; diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 30b9883..d634f5f 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -133,7 +133,7 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT unsigned long recv_len = sizeof(data); int sw; - if (elem_len == 128) + if (elem_len == 128) // TODO: add a flag to check algo type ? templ[2] = YKPIV_ALGO_RSA2048; else if (elem_len == 64) templ[2] = YKPIV_ALGO_RSA1024; From ee2a364c15146a83e47e7ee61897d3989941ede4 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 2 Sep 2015 16:06:37 +0200 Subject: [PATCH 089/134] More cleanup. --- ykcs11/objects.c | 53 +++++++++++------------------------------------- ykcs11/ykcs11.c | 39 ++++++----------------------------- 2 files changed, 18 insertions(+), 74 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index cef92f6..44e94e5 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -142,21 +142,6 @@ static piv_pubk_obj_t pubkey_objects[] = { {NULL, 1, 1, 0, 0} }; - -/*static void get_object_class(CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS_PTR class) { - if (obj >= 0 && obj < PIV_DATA_OBJ_LAST) - *class = CKO_DATA; - else if (obj > PIV_DATA_OBJ_LAST && obj < PIV_CERT_OBJ_LAST) - *class = CKO_CERTIFICATE; - else - *class = CKO_VENDOR_DEFINED | CKO_DATA; // Invalid value - }*/ - -/*static void get_object_label(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR label) { - strcpy((char *)label, objects[obj].name); -} -*/ - // Next two functions based off the code at // https://github.com/m9aertner/oidConverter/blob/master/oid.c // TODO: how to give credit? OR JUST STORE THE OID ALREADY ENCODED? @@ -173,7 +158,7 @@ static void make_base128(unsigned long l, int first, CK_BYTE_PTR buf, CK_ULONG_P } static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR len) { - CK_CHAR_PTR tmp = strdup((char *)oid); + CK_CHAR_PTR tmp = (CK_BYTE_PTR) strdup((char *)oid); CK_CHAR_PTR p = tmp; CK_BYTE_PTR q = NULL; CK_ULONG n = 0; @@ -229,20 +214,6 @@ static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR free(tmp); } -/*static void get_object_oid(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR oid) { - strcpy((char *)oid, objects[obj].oid); -} - -static void get_object_certificate_type(CK_OBJECT_HANDLE obj, CK_CERTIFICATE_TYPE_PTR type) { - if ((objects[obj].flags & PIV_OBJECT_TYPE_CERT)) - *type = CKC_X_509; -} - -static void get_object_key_id(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR key_id) { - memcpy((char *)key_id, objects[obj].containerid, 2); -} -*/ - static CK_KEY_TYPE get_key_type(EVP_PKEY *key) { return do_get_key_type(key); } @@ -292,13 +263,13 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; - data = piv_objects[obj].label; + data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_APPLICATION: DBG(("APPLICATION")); len = strlen(piv_objects[obj].label) + 1; - data = piv_objects[obj].label; + data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_VALUE: // TODO: this can be done with -r and -d|-a @@ -327,7 +298,7 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Just get the length */ if (template->pValue == NULL_PTR) { - template->ulValueLen = len; // TODO: define? + template->ulValueLen = len; return CKR_OK; } @@ -375,7 +346,7 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; - data = piv_objects[obj].label; + data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_VALUE: @@ -431,7 +402,7 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Just get the length */ if (template->pValue == NULL_PTR) { - template->ulValueLen = len; // TODO: define? + template->ulValueLen = len; return CKR_OK; } @@ -480,7 +451,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; - data = piv_objects[obj].label; + data =(CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_KEY_TYPE: @@ -617,7 +588,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Just get the length */ if (template->pValue == NULL_PTR) { - template->ulValueLen = len; // TODO: define? + template->ulValueLen = len; return CKR_OK; } @@ -666,11 +637,9 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: DBG(("LABEL")); len = strlen(piv_objects[obj].label) + 1; - data = piv_objects[obj].label; + data = (CK_BYTE_PTR)piv_objects[obj].label; break; -// case CKA_VALUE: // TODO: this can be done with -r and -d|-a - case CKA_KEY_TYPE: DBG(("KEY TYPE")); len = sizeof(CK_ULONG); @@ -774,7 +743,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Just get the length */ if (template->pValue == NULL_PTR) { - template->ulValueLen = len; // TODO: define? + template->ulValueLen = len; return CKR_OK; } @@ -913,6 +882,8 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) { // Extract and store the public key as an object rv = do_store_pubk(cert_objects[piv_objects[cert_id].sub_id].data, &pubkey_objects[piv_objects[cert_id].sub_id].data); + if (rv != CKR_OK) + return rv; return CKR_OK; } diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index f5bacab..c795d17 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -110,12 +110,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)( pInfo->cryptokiVersion = function_list.version; memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); - strcpy(pInfo->manufacturerID, YKCS11_MANUFACTURER); + strcpy((char *)pInfo->manufacturerID, YKCS11_MANUFACTURER); pInfo->flags = 0; memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription)); - strcpy(pInfo->libraryDescription, YKCS11_LIBDESC); + strcpy((char *)pInfo->libraryDescription, YKCS11_LIBDESC); pInfo->libraryVersion = ver; @@ -132,7 +132,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)( DBG(("GetFunctionList called with ppFunctionList = NULL")); return CKR_ARGUMENTS_BAD; } - *ppFunctionList = &function_list; + *ppFunctionList = &function_list; // TODO: filter out unsupported functions DOUT; return CKR_OK; @@ -689,7 +689,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_CRYPTOKI_NOT_INITIALIZED; } - if (userType != CKU_SO && // TODO: what can SO do? + if (userType != CKU_SO && userType != CKU_USER && userType != CKU_CONTEXT_SPECIFIC) return CKR_USER_TYPE_INVALID; @@ -828,8 +828,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_BYTE id; CK_BYTE_PTR value; CK_ULONG value_len; - CK_BYTE_PTR ec_params; - CK_ULONG ec_params_len; CK_BYTE_PTR p; CK_BYTE_PTR q; CK_BYTE_PTR dp; @@ -967,7 +965,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( } DBG(("Key id is %u", id)); - DBG(("ITEM LENGTH IS %lu", value_len)); + object = PIV_PVTK_OBJ_PIV_AUTH + id; if (is_rsa == CK_TRUE) { @@ -1067,9 +1065,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( if (pTemplate == NULL_PTR || ulCount == 0) return CKR_ARGUMENTS_BAD; - /*if (find_obj.active != CK_TRUE) - return CKR_OPERATION_NOT_INITIALIZED; actually this can be called from many other functions*/ - rv_final = CKR_OK; for (i = 0; i < ulCount; i++) { @@ -1581,7 +1576,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( } // The buffer contains an uncompressed point of the form 04, len, 04, x, y - // Where len is the |x| + |y| + 1 bytes + // Where len is |x| + |y| + 1 bytes op_info.op.sign.key_len = ((buf[1] - 1) / 2) * 8; @@ -2018,13 +2013,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( return rv; } - /* rv = token.get_token_objects_num(piv_state, &n_objs, &n_certs); */ - /* if (rv != CKR_OK) { */ - /* DBG(("Unable to retrieve token objects")); */ - /* return rv; */ - /* } */ - /* DBG(("There were %lu objs and %lu certs, there are %lu objs and %lu certs", session.slot->token->n_objects, session.slot->token->n_certs, n_objs, n_certs)); */ - is_new = CK_TRUE; for (i = 0; i < session.slot->token->n_objects; i++) { if (session.slot->token->objects[i] == op_info.op.gen.key_id) @@ -2071,21 +2059,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point } - /*session.slot->token->n_objects += 4; - session.slot->token->n_certs++; - - obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); - if (obj_ptr == NULL) { - DBG(("Unable to store new item in the session")); - return CKR_HOST_MEMORY; - } - - obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 4; - *obj_ptr++ = dobj_id; - *obj_ptr++ = cert_id; - *obj_ptr++ = pvtk_id; - *obj_ptr++ = pubk_id;*/ - *phPrivateKey = op_info.op.gen.key_id; *phPublicKey = op_info.op.gen.key_id - PIV_PVTK_OBJ_KM + PIV_PUBK_OBJ_KM; // TODO: make function for these? From 8c411f4473d337f1669fe5f1b1e01d21a17bfb5f Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Mon, 7 Sep 2015 14:33:26 +0200 Subject: [PATCH 090/134] ignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 315c81a..62b80fc 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,5 @@ ykcs11/.libs/ ykcs11/*.o ykcs11/*.lo ykcs11/ykcs11.pc -ykcs11/libykcs11.la \ No newline at end of file +ykcs11/libykcs11.la +ykcs11/ykcs11-version.h From 1a9e62cec8bc42a5ba5d614080ad3f78a6959132 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Mon, 7 Sep 2015 15:54:57 +0200 Subject: [PATCH 091/134] drop ykpiv_connect2() and add ykpiv_list_readers() --- lib/ykpiv.c | 108 +++++++++++++++++++++++++++--------------------- lib/ykpiv.h | 3 +- lib/ykpiv.map | 4 +- ykcs11/ykcs11.c | 7 +++- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index fc60d47..aac931b 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -128,23 +128,20 @@ ykpiv_rc ykpiv_disconnect(ykpiv_state *state) { } ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { - return ykpiv_connect2(state, wanted, NULL, 0); -} - -ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char **readers, unsigned long *len) { unsigned long num_readers = 0; unsigned long active_protocol; char reader_buf[1024]; long rc; - int i; char *reader_ptr; - rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); - if (rc != SCARD_S_SUCCESS) { - if(state->verbose) { - fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); + if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { + rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); + if (rc != SCARD_S_SUCCESS) { + if(state->verbose) { + fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); + } + return YKPIV_PCSC_ERROR; } - return YKPIV_PCSC_ERROR; } rc = SCardListReaders(state->context, NULL, NULL, &num_readers); @@ -170,20 +167,6 @@ ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char ** return YKPIV_PCSC_ERROR; } - // Save available readers (aka PKCS11 slots) - if (readers != NULL) { - *readers = malloc(sizeof(char) * num_readers); - if (*readers == NULL) { - if(state->verbose) { - fprintf (stderr, "error: malloc failed"); - } - SCardReleaseContext(state->context); - return YKPIV_MEMORY_ERROR; - } - memcpy(*readers, reader_buf, num_readers); - *len = num_readers; - } - for(reader_ptr = reader_buf; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) { if(wanted) { if(!strstr(reader_ptr, wanted)) { @@ -245,6 +228,59 @@ ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char ** return YKPIV_GENERIC_ERROR; } +ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len) { + unsigned long num_readers = 0; + char reader_buf[1024]; + long rc; + + if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { + rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); + if (rc != SCARD_S_SUCCESS) { + if(state->verbose) { + fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); + } + return YKPIV_PCSC_ERROR; + } + } + + rc = SCardListReaders(state->context, NULL, NULL, &num_readers); + if (rc != SCARD_S_SUCCESS) { + if(state->verbose) { + fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); + } + SCardReleaseContext(state->context); + return YKPIV_PCSC_ERROR; + } + + if (num_readers > sizeof(reader_buf)) { + num_readers = sizeof(reader_buf); + } + + rc = SCardListReaders(state->context, NULL, reader_buf, &num_readers); + if (rc != SCARD_S_SUCCESS) + { + if(state->verbose) { + fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); + } + SCardReleaseContext(state->context); + return YKPIV_PCSC_ERROR; + } + + // Save available readers (aka PKCS11 slots) + *readers = malloc(sizeof(char) * num_readers); + if (*readers == NULL) { + if(state->verbose) { + fprintf (stderr, "error: malloc failed"); + } + SCardReleaseContext(state->context); + return YKPIV_MEMORY_ERROR; + } + memcpy(*readers, reader_buf, num_readers); + *len = num_readers; + + return YKPIV_OK; +} + ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, const unsigned char *in_data, long in_len, unsigned char *out_data, unsigned long *out_len, int *sw) { @@ -788,27 +824,3 @@ ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id, return YKPIV_GENERIC_ERROR; } } - -ykpiv_rc ykpiv_get_reader_slot_number(ykpiv_state *state, unsigned long *slots, unsigned long *total) { - if (state == NULL) - return YKPIV_MEMORY_ERROR; - - *slots = state->n_readers; - *total = state->tot_readers_len; - - return YKPIV_OK; - -} - -ykpiv_rc ykpiv_get_reader_slot(ykpiv_state *state, unsigned long slot, char *reader) { - if (state == NULL) - return YKPIV_MEMORY_ERROR; - - if (slot >= state->n_readers) - return YKPIV_SIZE_ERROR; - - strcpy(reader, state->readers[slot]); - - return YKPIV_OK; - -} diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 3de24c4..d832283 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -65,8 +65,7 @@ extern "C" ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); ykpiv_rc ykpiv_done(ykpiv_state *state); ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); - ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, - unsigned char **readers, unsigned long *len); // Allow to return a reader string + ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len); ykpiv_rc ykpiv_disconnect(ykpiv_state *state); ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, const unsigned char *in_data, long in_len, diff --git a/lib/ykpiv.map b/lib/ykpiv.map index 0a09fa6..dd817b2 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -53,12 +53,12 @@ YKPIV_0.2.0 { global: ykpiv_decipher_data; - ykpiv_connect2; - ykpiv_sign_data2; } YKPIV_0.1.0; YKPIV_1.1.0 { global: ykpiv_set_mgmkey2; + ykpiv_list_readers; + ykpiv_sign_data2; } YKPIV_0.1.0; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c795d17..4997329 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -60,7 +60,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; // TODO: better error? } - if(ykpiv_connect2(piv_state, NULL, &readers, &len) != YKPIV_OK) { + if (ykpiv_list_readers(piv_state, &readers, &len) != YKPIV_OK) { + DBG(("Unable to list readers")); + return CKR_FUNCTION_FAILED; + } + + if(ykpiv_connect(piv_state, NULL) != YKPIV_OK) { DBG(("Unable to connect to reader")); return CKR_FUNCTION_FAILED; } From 8eb7595d42923c7f979105913ae654f3742d02b1 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 12:26:42 +0200 Subject: [PATCH 092/134] add list-readers action to tool also refactor ykpiv_list_readers() a bit --- lib/ykpiv.c | 19 ++++--------------- lib/ykpiv.h | 2 +- tool/cmdline.ggo | 2 +- tool/yubico-piv-tool.c | 22 ++++++++++++++++++++++ ykcs11/ykcs11.c | 6 +++--- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index aac931b..30c3ba3 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -228,9 +228,8 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { return YKPIV_GENERIC_ERROR; } -ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len) { +ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len) { unsigned long num_readers = 0; - char reader_buf[1024]; long rc; if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { @@ -252,11 +251,11 @@ ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigne return YKPIV_PCSC_ERROR; } - if (num_readers > sizeof(reader_buf)) { - num_readers = sizeof(reader_buf); + if (num_readers > *len) { + num_readers = *len; } - rc = SCardListReaders(state->context, NULL, reader_buf, &num_readers); + rc = SCardListReaders(state->context, NULL, readers, &num_readers); if (rc != SCARD_S_SUCCESS) { if(state->verbose) { @@ -266,16 +265,6 @@ ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigne return YKPIV_PCSC_ERROR; } - // Save available readers (aka PKCS11 slots) - *readers = malloc(sizeof(char) * num_readers); - if (*readers == NULL) { - if(state->verbose) { - fprintf (stderr, "error: malloc failed"); - } - SCardReleaseContext(state->context); - return YKPIV_MEMORY_ERROR; - } - memcpy(*readers, reader_buf, num_readers); *len = num_readers; return YKPIV_OK; diff --git a/lib/ykpiv.h b/lib/ykpiv.h index d832283..ffbee83 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -65,7 +65,7 @@ extern "C" ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); ykpiv_rc ykpiv_done(ykpiv_state *state); ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); - ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len); + ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len); ykpiv_rc ykpiv_disconnect(ykpiv_state *state); ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, const unsigned char *in_data, long in_len, diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index d777748..bdd2a7e 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -32,7 +32,7 @@ option "action" a "Action to take" values="version","generate","set-mgm-key", "reset","pin-retries","import-key","import-certificate","set-chuid", "request-certificate","verify-pin","change-pin","change-puk","unblock-pin", "selfsign-certificate","delete-certificate","read-certificate","status", - "test-signature","test-decipher" enum multiple + "test-signature","test-decipher","list-readers" enum multiple text " Multiple actions may be given at once and will be executed in order for example --action=verify-pin --action=request-certificate\n" diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 1fcbb25..e916be1 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -1569,6 +1569,21 @@ decipher_out: return ret; } +static bool list_readers(ykpiv_state *state) { + char readers[2048]; + char *reader_ptr; + size_t len = sizeof(readers); + ykpiv_rc rc = ykpiv_list_readers(state, readers, &len); + if(rc != YKPIV_OK) { + fprintf(stderr, "Failed listing readers.\n"); + return false; + } + for(reader_ptr = readers; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) { + printf("%s\n", reader_ptr); + } + return true; +} + int main(int argc, char *argv[]) { struct gengetopt_args_info args_info; ykpiv_state *state; @@ -1622,6 +1637,7 @@ int main(int argc, char *argv[]) { case action_arg_version: case action_arg_reset: case action_arg_status: + case action_arg_listMINUS_readers: case action__NULL: default: continue; @@ -1666,6 +1682,7 @@ int main(int argc, char *argv[]) { case action_arg_status: case action_arg_testMINUS_signature: case action_arg_testMINUS_decipher: + case action_arg_listMINUS_readers: case action__NULL: default: if(verbosity) { @@ -1850,6 +1867,11 @@ int main(int argc, char *argv[]) { ret = EXIT_FAILURE; } break; + case action_arg_listMINUS_readers: + if(list_readers(state) == false) { + ret = EXIT_FAILURE; + } + break; case action__NULL: default: fprintf(stderr, "Wrong action. %d.\n", action); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 4997329..a4e6b94 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -47,8 +47,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( ) { DIN; - CK_CHAR_PTR readers; - CK_ULONG len; + char readers[2048]; + CK_ULONG len = sizeof(readers); // TODO: check for locks and mutexes @@ -60,7 +60,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; // TODO: better error? } - if (ykpiv_list_readers(piv_state, &readers, &len) != YKPIV_OK) { + if (ykpiv_list_readers(piv_state, readers, &len) != YKPIV_OK) { DBG(("Unable to list readers")); return CKR_FUNCTION_FAILED; } From 4bbd888f97d4077f822efe5041341d5610784da4 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 12:29:07 +0200 Subject: [PATCH 093/134] let ykpiv_connect() call ykpiv_list_readers() --- lib/ykpiv.c | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 30c3ba3..6e3bc35 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -128,43 +128,15 @@ ykpiv_rc ykpiv_disconnect(ykpiv_state *state) { } ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { - unsigned long num_readers = 0; unsigned long active_protocol; - char reader_buf[1024]; + char reader_buf[2048]; + size_t num_readers = sizeof(reader_buf); long rc; char *reader_ptr; - if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { - rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); - if (rc != SCARD_S_SUCCESS) { - if(state->verbose) { - fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); - } - return YKPIV_PCSC_ERROR; - } - } - - rc = SCardListReaders(state->context, NULL, NULL, &num_readers); - if (rc != SCARD_S_SUCCESS) { - if(state->verbose) { - fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); - } - SCardReleaseContext(state->context); - return YKPIV_PCSC_ERROR; - } - - if (num_readers > sizeof(reader_buf)) { - num_readers = sizeof(reader_buf); - } - - rc = SCardListReaders(state->context, NULL, reader_buf, &num_readers); - if (rc != SCARD_S_SUCCESS) - { - if(state->verbose) { - fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); - } - SCardReleaseContext(state->context); - return YKPIV_PCSC_ERROR; + ykpiv_rc ret = ykpiv_list_readers(state, reader_buf, &num_readers); + if(ret != YKPIV_OK) { + return ret; } for(reader_ptr = reader_buf; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) { From 49eab7dbfa78dd2f55e3bb1e27f2401ab78db4d6 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 15:29:10 +0200 Subject: [PATCH 094/134] drop ykpiv_sign_data2() and change ykpiv_sign_data() to not pad --- lib/ykpiv.c | 17 +++-------------- tool/yubico-piv-tool.c | 33 ++++++++++++++++++++++++--------- ykcs11/ykcs11.c | 2 +- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 6e3bc35..b42aed9 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -533,7 +533,7 @@ ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, static ykpiv_rc _general_authenticate(ykpiv_state *state, const unsigned char *sign_in, size_t in_len, unsigned char *out, size_t *out_len, - unsigned char algorithm, unsigned char key, bool decipher, bool padding) { + unsigned char algorithm, unsigned char key, bool decipher) { unsigned char indata[1024]; unsigned char *dataptr = indata; unsigned char data[1024]; @@ -636,25 +636,14 @@ ykpiv_rc ykpiv_sign_data(ykpiv_state *state, unsigned char algorithm, unsigned char key) { return _general_authenticate(state, raw_in, in_len, sign_out, out_len, - algorithm, key, false, true); + algorithm, key, false); } -ykpiv_rc ykpiv_sign_data2(ykpiv_state *state, - const unsigned char *raw_in, size_t in_len, - unsigned char *sign_out, size_t *out_len, - unsigned char algorithm, unsigned char key, - int padding) { - - return _general_authenticate(state, raw_in, in_len, sign_out, out_len, - algorithm, key, false, padding); -} - - ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *in, size_t in_len, unsigned char *out, size_t *out_len, unsigned char algorithm, unsigned char key) { return _general_authenticate(state, in, in_len, out, out_len, - algorithm, key, true, true); + algorithm, key, true); } ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len) { diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index e916be1..9cebb42 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -85,6 +85,25 @@ static void print_version(ykpiv_state *state, const char *output_file_name) { } } +static bool sign_data(ykpiv_state *state, const unsigned char *in, size_t len, unsigned char *out, + size_t *out_len, unsigned char algorithm, int key) { + + unsigned char signinput[1024]; + if(YKPIV_IS_RSA(algorithm)) { + size_t padlen = algorithm == YKPIV_ALGO_RSA1024 ? 128 : 256; + if(RSA_padding_add_PKCS1_type_1(signinput, padlen, in, len) == 0) { + fprintf(stderr, "Failed adding padding.\n"); + return false; + } + in = signinput; + len = padlen; + } + if(ykpiv_sign_data(state, signinput, len, out, out_len, algorithm, key) == YKPIV_OK) { + return true; + } + return false; +} + static bool generate_key(ykpiv_state *state, const char *slot, enum enum_algorithm algorithm, const char *output_file_name, enum enum_key_format key_format, enum enum_pin_policy pin_policy, @@ -692,8 +711,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for { unsigned char signature[1024]; size_t sig_len = sizeof(signature); - if(ykpiv_sign_data(state, signinput, len, signature, &sig_len, algorithm, key) - != YKPIV_OK) { + if(!sign_data(state, signinput, len, signature, &sig_len, algorithm, key)) { fprintf(stderr, "Failed signing request.\n"); goto request_out; } @@ -845,8 +863,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo { unsigned char signature[1024]; size_t sig_len = sizeof(signature); - if(ykpiv_sign_data(state, signinput, len, signature, &sig_len, algorithm, key) - != YKPIV_OK) { + if(!sign_data(state, signinput, len, signature, &sig_len, algorithm, key)) { fprintf(stderr, "Failed signing certificate.\n"); goto selfsign_out; } @@ -1122,9 +1139,8 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, { unsigned char buf[1024]; size_t len = sizeof(buf); - ykpiv_rc rc = ykpiv_sign_data(state, hashed, hash_len, buf, &len, algo, key); - if(rc != YKPIV_OK) { - fprintf(stderr, "failed signing file: %s\n", ykpiv_strerror(rc)); + if(!sign_data(state, hashed, hash_len, buf, &len, algo, key)) { + fprintf(stderr, "failed signing file\n"); goto out; } @@ -1373,8 +1389,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, } else { enc_len = data_len; } - if(ykpiv_sign_data(state, ptr, enc_len, signature, &sig_len, algorithm, key) - != YKPIV_OK) { + if(!sign_data(state, ptr, enc_len, signature, &sig_len, algorithm, key)) { fprintf(stderr, "Failed signing test data.\n"); goto test_out; } diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index a4e6b94..9b9d0cc 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1690,7 +1690,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE); *pulSignatureLen = sizeof(op_info.buf); - if ((r = ykpiv_sign_data2(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id, 0)) != YKPIV_OK) { + if ((r = ykpiv_sign_data(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id)) != YKPIV_OK) { DBG(("Sign error, %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } From 30ed31124414e3751be8cacfb286cb9b6b7bec4a Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 15:33:15 +0200 Subject: [PATCH 095/134] remove ykpiv_sign_data2() from map --- lib/ykpiv.map | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ykpiv.map b/lib/ykpiv.map index dd817b2..c647a5a 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -60,5 +60,4 @@ YKPIV_1.1.0 global: ykpiv_set_mgmkey2; ykpiv_list_readers; - ykpiv_sign_data2; } YKPIV_0.1.0; From 99ebfdf37c218e6426438d0ac131ea77440e5a26 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 8 Sep 2015 18:00:48 +0200 Subject: [PATCH 096/134] Added support for CKU_CONTEXT_SPECIFIC. --- lib/ykpiv.c | 5 +++- ykcs11/mechanisms.c | 13 ++++++++++ ykcs11/mechanisms.h | 1 + ykcs11/openssl_utils.c | 7 ++++++ ykcs11/openssl_utils.h | 1 + ykcs11/ykcs11.c | 56 +++++++++++++++++++++++++++++++++--------- 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index fc60d47..a152d11 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -602,7 +602,10 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, if(state->verbose) { fprintf(stderr, "Failed sign command with code %x.\n", sw); } - return YKPIV_GENERIC_ERROR; + if (sw == 0x6982) + return YKPIV_AUTHENTICATION_ERROR; + else + return YKPIV_GENERIC_ERROR; } /* skip the first 7c tag */ if(data[0] != 0x7c) { diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 23285e8..ce1ef72 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -244,6 +244,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { case CKM_SHA512_RSA_PKCS_PSS: // Finalize the hash rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + op_info->op.sign.md_ctx = NULL; if (rv != CKR_OK) return CKR_FUNCTION_FAILED; @@ -275,6 +276,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { case CKM_SHA512_RSA_PKCS: // Finalize the hash add digest info rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + op_info->op.sign.md_ctx = NULL; if (rv != CKR_OK) return CKR_FUNCTION_FAILED; @@ -295,6 +297,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { case CKM_ECDSA_SHA256: // Finalize the hash rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + op_info->op.sign.md_ctx = NULL; if (rv != CKR_OK) return CKR_FUNCTION_FAILED; @@ -306,6 +309,16 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { } } +CK_RV sign_mechanism_cleanup(op_info_t *op_info) { + + if (op_info->op.sign.md_ctx != NULL) { + do_md_cleanup(op_info->op.sign.md_ctx); + op_info->op.sign.md_ctx = NULL; + } + + return CKR_OK; +} + CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) { CK_ULONG i; diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index 27bdced..c919dde 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -11,6 +11,7 @@ CK_BBOOL is_hashed_mechanism(CK_MECHANISM_TYPE m); CK_RV apply_sign_mechanism_init(op_info_t *op_info); CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len); CK_RV apply_sign_mechanism_finalize(op_info_t *op_info); +CK_RV sign_mechanism_cleanup(op_info_t *op_info); CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); // TODO: Move to objects.c diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 1756735..17ba0ae 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -557,3 +557,10 @@ CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR out, CK_ULONG_PTR out_len return CKR_OK; } + +CK_RV do_md_cleanup(ykcs11_md_ctx_t *ctx) { + + EVP_MD_CTX_destroy((EVP_MD_CTX *) ctx); + + return CKR_OK; +} diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 14f8a28..6fef0ff 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -32,5 +32,6 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx); CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len); CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int *nid); +CK_RV do_md_cleanup(ykcs11_md_ctx_t *ctx); #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c795d17..b20f06f 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -147,7 +147,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( ) { DIN; - int i; + CK_ULONG i; int j; if (piv_state == NULL) { @@ -765,6 +765,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( break; case CKU_CONTEXT_SPECIFIC: + if (op_info.type == YKCS11_NOOP) { + DBG(("No operation in progress. Context specific user is forbidden.")); + return CKR_USER_TYPE_INVALID; + } + if (op_info.type == YKCS11_SIGN) { + return C_Login(hSession, CKU_USER, pPin, ulPinLen); + } + else + return C_Login(hSession, CKU_SO, pPin, ulPinLen); + default: return CKR_USER_TYPE_INVALID; } @@ -1627,13 +1637,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( { DIN; + ykpiv_rc piv_rv; + CK_RV rv; + if (op_info.type != YKCS11_SIGN) { DBG(("Signature operation not initialized")); - return CKR_OPERATION_NOT_INITIALIZED; + rv = CKR_OPERATION_NOT_INITIALIZED; + goto sign_out; } // TODO: check other conditions - ykpiv_rc r; // TODO: delete this ? if (pSignature == NULL_PTR) { // Just return the size of the signature @@ -1650,7 +1663,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (is_hashed_mechanism(op_info.mechanism.mechanism) == CK_TRUE) { if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { DBG(("Unable to perform signing operation step")); - return CKR_FUNCTION_FAILED; // TODO: every error in here must stop and clear the signing operation + rv = CKR_FUNCTION_FAILED; // TODO: every error in here must stop and clear the signing operation + goto sign_out; } } else { @@ -1658,7 +1672,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( // RSA_X_509 if (ulDataLen > (op_info.op.sign.key_len / 8)) { DBG(("Data must be shorter than key length (%lu bits)", op_info.op.sign.key_len)); - return CKR_FUNCTION_FAILED; + rv = CKR_FUNCTION_FAILED; + goto sign_out; } } else { @@ -1666,7 +1681,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (ulDataLen > 128) { // Specs say ECDSA only supports 1024 bit DBG(("Meximum data length for ECDSA is 128 bytes")); - return CKR_FUNCTION_FAILED; + rv = CKR_FUNCTION_FAILED; + goto sign_out; } } @@ -1674,10 +1690,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( memcpy(op_info.buf, pData, ulDataLen); } - if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) { DBG(("Unable to finalize signing operation")); - return CKR_FUNCTION_FAILED; + rv = CKR_FUNCTION_FAILED; + goto sign_out; } DBG(("Using key %lx", op_info.op.sign.key_id)); @@ -1685,10 +1701,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE); *pulSignatureLen = sizeof(op_info.buf); - if ((r = ykpiv_sign_data2(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id, 0)) != YKPIV_OK) { - DBG(("Sign error, %s", ykpiv_strerror(r))); - return CKR_FUNCTION_FAILED; + piv_rv = ykpiv_sign_data2(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id, 0); + if (piv_rv != YKPIV_OK) { + if (piv_rv == YKPIV_AUTHENTICATION_ERROR) { + DBG(("Operation requires authentication or touch")); + rv = CKR_USER_NOT_LOGGED_IN; + goto sign_out; + } + else { + DBG(("Sign error, %s", ykpiv_strerror(piv_rv))); + rv = CKR_FUNCTION_FAILED; + goto sign_out; + } } + DBG(("Got %lu bytes back", *pulSignatureLen)); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); @@ -1703,8 +1729,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( op_info.type = YKCS11_NOOP; // TODO: anything to clear here? + rv = CKR_OK; + + sign_out: + op_info.type = YKCS11_NOOP; + sign_mechanism_cleanup(&op_info); + DOUT; - return CKR_OK; + return rv; } CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)( From d820c314c4f5a05dc573ba84c35686282c6de1e7 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 9 Sep 2015 13:16:45 +0200 Subject: [PATCH 097/134] Free more. --- ykcs11/ykcs11.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index a4fe887..5fe09d3 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -87,6 +87,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( ) { DIN; + CK_ULONG i; + if (pReserved != NULL_PTR) { DBG(("Finalized called with pReserved != NULL")); return CKR_ARGUMENTS_BAD; @@ -97,6 +99,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( return CKR_CRYPTOKI_NOT_INITIALIZED; } + for (i = 0; i < n_slots; i++) { + destroy_token(slots + i); + } memset(slots, 0, sizeof(slots)); ykpiv_done(piv_state); // TODO: this calls disconnect... @@ -547,6 +552,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( } } + free(cert_ids); + cert_ids = NULL; + session.handle = YKCS11_SESSION_ID; // TODO: KEEP TRACK OF THE APPLICATION (possble to steal a session?) From 22d8f4f9fe904a3ebc7924cdae1e98bbc023e888 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 9 Sep 2015 13:55:50 +0200 Subject: [PATCH 098/134] Minor cleanups. --- ykcs11/objects.c | 3 +-- ykcs11/openssl_utils.c | 34 +++++++++++++--------------------- ykcs11/openssl_utils.h | 2 +- ykcs11/token_vendors.c | 2 +- 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 44e94e5..91b3380 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -186,7 +186,6 @@ static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR p++; } - l = 0; if (*p == '.') { *p = 0; l = (CK_ULONG) atoi((char *)q); @@ -195,7 +194,7 @@ static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR } else { l = (CK_ULONG) atoi((char *)q); - q = p; + // q = p; } /* Digit is in l. */ diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 17ba0ae..1ce68a0 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -9,11 +9,6 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { const unsigned char *p = data; // Mandatory temp variable required by OpenSSL int cert_len; - /**cert = X509_new(); - if (*cert == NULL) - return CKR_HOST_MEMORY;*/ - //dump_hex(data, len, stderr, CK_TRUE); - if (*p == 0x70) { // The certificate is in "PIV" format 0x70 len 0x30 len ... p++; @@ -25,23 +20,18 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { cert_len += get_length(p + 1, &cert_len) + 1; } + if ((CK_ULONG)cert_len > len) + return CKR_ARGUMENTS_BAD; + *cert = d2i_X509(NULL, &p, cert_len); if (*cert == NULL) return CKR_FUNCTION_FAILED; - /* - BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE); - - X509_print_ex(STDout, *cert, 0, 0); - - BIO_free(STDout); - */ - return CKR_OK; } -CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ULONG key_len, +CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { X509 *cert = NULL; @@ -53,7 +43,6 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ EC_GROUP *ecg = NULL; EC_POINT *ecp = NULL; ASN1_TIME *tm = NULL; - time_t t; unsigned char *data_ptr; unsigned char *p; @@ -160,16 +149,16 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ if (len < 0) goto create_empty_cert_cleanup; - if (len > *out_len) { + if ((CK_ULONG)len > *out_len) { rv = CKR_BUFFER_TOO_SMALL; goto create_empty_cert_cleanup; } - p = in; + p = out; if ((*out_len = i2d_X509(cert, &p)) == 0) goto create_empty_cert_cleanup; - /* TODO REMOVE THIS */ + /* TODO: REMOVE THIS */ BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE); X509_print_ex(STDout, cert, 0, 0); @@ -320,7 +309,7 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { rsa = EVP_PKEY_get1_RSA(key); - if (RSA_size(rsa) > *len) { + if ((CK_ULONG)RSA_size(rsa) > *len) { RSA_free(rsa); rsa = NULL; return CKR_BUFFER_TOO_SMALL; @@ -461,13 +450,16 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, OpenSSL_add_all_digests(); // TODO: rand must be seeded first (should be automatic) - if (*out_len < RSA_size(key)) + if (*out_len < (CK_ULONG)RSA_size(key)) CKR_BUFFER_TOO_SMALL; DBG(("Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key))); + if (out != in) + memcpy(out, in, in_len); + // In case of raw PSS (no hash) this function will fail because OpenSSL requires an MD - if (RSA_padding_add_PKCS1_PSS(key, em, in, EVP_get_digestbynid(nid), -2) == 0) { + if (RSA_padding_add_PKCS1_PSS(key, em, out, EVP_get_digestbynid(nid), -2) == 0) { EVP_cleanup(); return CKR_FUNCTION_FAILED; } diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 6fef0ff..12f8dde 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -10,7 +10,7 @@ #include "pkcs11t.h" CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); -CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ULONG key_len, +CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len); CK_RV free_cert(X509 *cert); diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index d634f5f..6d0c2bd 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -58,7 +58,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE // 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) + if ((rv = do_create_empty_cert(data, recv_len, rsa, data, &recv_len)) != CKR_OK) return rv; if (recv_len < 0x80) From 44dae193480142f598d8c0386417c95807110a45 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 9 Sep 2015 15:42:14 +0200 Subject: [PATCH 099/134] Imporve support for multiple readers/cards. --- ykcs11/utils.c | 3 +-- ykcs11/ykcs11.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 05fedfc..756b77b 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -49,8 +49,7 @@ CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); s = slots[*n_slots].info.slotDescription; l = sizeof(slots[*n_slots].info.slotDescription); - if (slot.get_slot_description(s, l) != CKR_OK) - goto failure; + strncpy((char *)s, (char *)p, l); memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID)); s = slots[*n_slots].info.manufacturerID; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 5fe09d3..3ba5ad3 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -47,7 +47,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( ) { DIN; - char readers[2048]; + CK_BYTE readers[2048]; CK_ULONG len = sizeof(readers); // TODO: check for locks and mutexes @@ -60,16 +60,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; // TODO: better error? } - if (ykpiv_list_readers(piv_state, readers, &len) != YKPIV_OK) { + if (ykpiv_list_readers(piv_state, (char*)readers, &len) != YKPIV_OK) { DBG(("Unable to list readers")); return CKR_FUNCTION_FAILED; } - if(ykpiv_connect(piv_state, NULL) != YKPIV_OK) { - DBG(("Unable to connect to reader")); - return CKR_FUNCTION_FAILED; - } - if (parse_readers(readers, len, slots, &n_slots, &n_slots_with_token) != CK_TRUE) CKR_FUNCTION_FAILED; @@ -480,6 +475,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( return CKR_SESSION_PARALLEL_NOT_SUPPORTED; } + // Connect to the slot + if(ykpiv_connect(piv_state, (char *)slots[slotID].info.slotDescription) != YKPIV_OK) { + DBG(("Unable to connect to reader")); + return CKR_FUNCTION_FAILED; + } + token = get_token_vendor(slots[slotID].token->vid); // Store the slot @@ -606,6 +607,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( memset(&session, 0, sizeof(ykcs11_session_t)); session.handle = CK_INVALID_HANDLE; + ykpiv_disconnect(piv_state); + DOUT; return CKR_OK; } From 8f3e9230f346b9e61d2614a5843fdd85d57df3ed Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 9 Sep 2015 15:54:16 +0200 Subject: [PATCH 100/134] Remove get slot description and use the reader string from pcsclite. --- ykcs11/slot_vendors.c | 2 -- ykcs11/slot_vendors.h | 2 -- ykcs11/yubico_slot.c | 11 ----------- ykcs11/yubico_slot.h | 1 - 4 files changed, 16 deletions(-) diff --git a/ykcs11/slot_vendors.c b/ykcs11/slot_vendors.c index 5ce9fed..36f05c7 100644 --- a/ykcs11/slot_vendors.c +++ b/ykcs11/slot_vendors.c @@ -7,7 +7,6 @@ slot_vendor_t get_slot_vendor(vendor_id_t vid) { switch (vid) { case YUBICO: - v.get_slot_description = YUBICO_get_slot_description; v.get_slot_manufacturer = YUBICO_get_slot_manufacturer; v.get_slot_flags = YUBICO_get_slot_flags; v.get_slot_version = YUBICO_get_slot_version; @@ -15,7 +14,6 @@ slot_vendor_t get_slot_vendor(vendor_id_t vid) { case UNKNOWN: default: - v.get_slot_description = NULL; v.get_slot_manufacturer = NULL; v.get_slot_flags = NULL; v.get_slot_version = NULL; diff --git a/ykcs11/slot_vendors.h b/ykcs11/slot_vendors.h index 2426e23..5ab475d 100644 --- a/ykcs11/slot_vendors.h +++ b/ykcs11/slot_vendors.h @@ -4,14 +4,12 @@ #include "pkcs11.h" #include "vendor_ids.h" -typedef CK_RV (*get_s_description_f)(CK_UTF8CHAR_PTR, CK_ULONG); typedef CK_RV (*get_s_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); typedef CK_RV (*get_s_flags_f)(CK_FLAGS_PTR); typedef CK_RV (*get_s_version_f)(CK_VERSION_PTR); typedef struct { - get_s_description_f get_slot_description; get_s_manufacturer_f get_slot_manufacturer; get_s_flags_f get_slot_flags; get_s_version_f get_slot_version; diff --git a/ykcs11/yubico_slot.c b/ykcs11/yubico_slot.c index abfc8aa..d947f50 100644 --- a/ykcs11/yubico_slot.c +++ b/ykcs11/yubico_slot.c @@ -2,21 +2,10 @@ #include "pkcs11.h" #include -static const CK_UTF8CHAR_PTR slot_description = "YubiKey Virtual Reader"; static const CK_UTF8CHAR_PTR slot_manufacturer = "Yubico"; static const CK_FLAGS slot_flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; static const CK_VERSION slot_version = {1, 0}; -CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len) { - - if (strlen(slot_description) > len) - return CKR_BUFFER_TOO_SMALL; - - memcpy(str, slot_description, strlen(slot_description)); - return CKR_OK; - -} - CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len) { if (strlen(slot_manufacturer) > len) diff --git a/ykcs11/yubico_slot.h b/ykcs11/yubico_slot.h index 4bd617d..7f84106 100644 --- a/ykcs11/yubico_slot.h +++ b/ykcs11/yubico_slot.h @@ -3,7 +3,6 @@ #include "pkcs11.h" -CK_RV YUBICO_get_slot_description(CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_slot_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags); CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version); From bd6e6db138939ca00c0f504a21f54348c0abe3b1 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 9 Sep 2015 16:31:25 +0200 Subject: [PATCH 101/134] Add parsing of model number. --- ykcs11/token_vendors.h | 2 +- ykcs11/utils.c | 15 +++++++++------ ykcs11/utils.h | 4 ++-- ykcs11/ykcs11.c | 2 +- ykcs11/yubico_token.c | 19 +++++++++++++++---- ykcs11/yubico_token.h | 2 +- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index a5b6175..791dc91 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -8,7 +8,7 @@ typedef CK_RV (*get_t_label_f)(CK_UTF8CHAR_PTR, CK_ULONG); typedef CK_RV (*get_t_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*get_t_model_f)(CK_UTF8CHAR_PTR, CK_ULONG); +typedef CK_RV (*get_t_model_f)(ykpiv_state *, CK_UTF8CHAR_PTR, CK_ULONG); typedef CK_RV (*get_t_flags_f)(CK_FLAGS_PTR); typedef CK_RV (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG, CK_VERSION_PTR); typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG); diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 756b77b..8efc89d 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -8,7 +8,7 @@ CK_BBOOL has_token(const ykcs11_slot_t *slot) { } -CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, +CK_RV parse_readers(ykpiv_state *state, const CK_BYTE_PTR readers, const CK_ULONG len, ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token) { CK_BYTE i; @@ -49,7 +49,7 @@ CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); s = slots[*n_slots].info.slotDescription; l = sizeof(slots[*n_slots].info.slotDescription); - strncpy((char *)s, (char *)p, l); + strncpy((char *)s, (char*)p, l); memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID)); s = slots[*n_slots].info.manufacturerID; @@ -71,7 +71,7 @@ CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, // Save token information (*n_with_token)++; - if (create_token(p, slots + *n_slots) != CKR_OK) + if (create_token(state, p, slots + *n_slots) != CKR_OK) goto failure; } } @@ -90,7 +90,7 @@ failure: return CKR_FUNCTION_FAILED; } -CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { +CK_RV create_token(ykpiv_state *state, CK_BYTE_PTR p, ykcs11_slot_t *slot) { token_vendor_t token; CK_TOKEN_INFO_PTR t_info; @@ -112,9 +112,12 @@ CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) { if(token.get_token_manufacturer(t_info->manufacturerID, sizeof(t_info->manufacturerID)) != CKR_OK) return CKR_FUNCTION_FAILED; - memset(t_info->model, ' ', sizeof(t_info->model)); - if(token.get_token_model(t_info->model, sizeof(t_info->model)) != CKR_OK) + if (ykpiv_connect(state, (char *)p) != YKPIV_OK) return CKR_FUNCTION_FAILED; + memset(t_info->model, ' ', sizeof(t_info->model)); + if(token.get_token_model(state, t_info->model, sizeof(t_info->model)) != CKR_OK) + return CKR_FUNCTION_FAILED; + ykpiv_disconnect(state); memset(t_info->serialNumber, ' ', sizeof(t_info->serialNumber)); if(token.get_token_serial(t_info->serialNumber, sizeof(t_info->serialNumber)) != CKR_OK) diff --git a/ykcs11/utils.h b/ykcs11/utils.h index af6f82a..509b2d5 100644 --- a/ykcs11/utils.h +++ b/ykcs11/utils.h @@ -4,9 +4,9 @@ #include "ykcs11.h" CK_BBOOL has_token(const ykcs11_slot_t *slot); -CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len, +CK_RV parse_readers(ykpiv_state *state,const CK_BYTE_PTR readers, const CK_ULONG len, ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token); -CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot); +CK_RV create_token(ykpiv_state *state, CK_BYTE_PTR p, ykcs11_slot_t *slot); void destroy_token(ykcs11_slot_t *slot); CK_BBOOL is_valid_key_id(CK_BYTE id); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 3ba5ad3..1b11abd 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -65,7 +65,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; } - if (parse_readers(readers, len, slots, &n_slots, &n_slots_with_token) != CK_TRUE) + if (parse_readers(piv_state, readers, len, slots, &n_slots, &n_slots_with_token) != CK_TRUE) CKR_FUNCTION_FAILED; DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token)); diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index b005d3a..f5848f5 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -10,9 +10,9 @@ #define MIN_ECC_KEY_SIZE 256 #define MAX_ECC_KEY_SIZE 384 -static const CK_UTF8CHAR_PTR token_label = "YubiKey PIV X"; -static const CK_UTF8CHAR_PTR token_manufacturer = "Yubico"; -static const CK_UTF8CHAR_PTR token_model = "YubiKey MODEL"; +static const char* token_label = "YubiKey PIV"; +static const char* token_manufacturer = "Yubico"; +static const char* token_model = "YubiKey XXX"; static const CK_FLAGS token_flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; static const CK_BYTE_PTR token_serial = "1234"; static const CK_MECHANISM_TYPE token_mechanisms[] = { // KEEP ALIGNED WITH token_mechanism_infos @@ -124,13 +124,24 @@ CK_RV YUBICO_get_token_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len) { return CKR_OK; } +#include "debug.h" +CK_RV YUBICO_get_token_model(ykpiv_state *state, CK_UTF8CHAR_PTR str, CK_ULONG len) { -CK_RV YUBICO_get_token_model(CK_UTF8CHAR_PTR str, CK_ULONG len) { + char buf[16]; if (strlen(token_model) > len) return CKR_BUFFER_TOO_SMALL; + if (ykpiv_get_version(state, buf, sizeof(buf)) != YKPIV_OK) + return CKR_FUNCTION_FAILED; + memcpy(str, token_model, strlen(token_model)); + + if (buf[0] >= '4') + memcpy(str + strlen(token_model) - 3, "YK4", 3); + else + memcpy(str + strlen(token_model) - 3, "NEO", 3); + return CKR_OK; } diff --git a/ykcs11/yubico_token.h b/ykcs11/yubico_token.h index 09e57ea..e95c8e3 100644 --- a/ykcs11/yubico_token.h +++ b/ykcs11/yubico_token.h @@ -7,7 +7,7 @@ CK_RV YUBICO_get_token_label(CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_token_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len); -CK_RV YUBICO_get_token_model(CK_UTF8CHAR_PTR str, CK_ULONG len); +CK_RV YUBICO_get_token_model(ykpiv_state *state, CK_UTF8CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_token_flags(CK_FLAGS_PTR flags); CK_RV YUBICO_get_token_serial(CK_CHAR_PTR str, CK_ULONG len); CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VERSION_PTR version); From a6a6c0900c6bdd53d658b6302948b80cbe57e530 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 9 Sep 2015 16:33:04 +0200 Subject: [PATCH 102/134] Fix some warnings. --- ykcs11/yubico_token.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index f5848f5..f2df6e2 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -10,11 +10,11 @@ #define MIN_ECC_KEY_SIZE 256 #define MAX_ECC_KEY_SIZE 384 -static const char* token_label = "YubiKey PIV"; -static const char* token_manufacturer = "Yubico"; -static const char* token_model = "YubiKey XXX"; +static const char *token_label = "YubiKey PIV"; +static const char *token_manufacturer = "Yubico"; +static const char *token_model = "YubiKey XXX"; static const CK_FLAGS token_flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; -static const CK_BYTE_PTR token_serial = "1234"; +static const char *token_serial = "1234"; static const CK_MECHANISM_TYPE token_mechanisms[] = { // KEEP ALIGNED WITH token_mechanism_infos CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, @@ -156,7 +156,7 @@ CK_RV YUBICO_get_token_flags(CK_FLAGS_PTR flags) { CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG len, CK_VERSION_PTR version) { CK_VERSION v = {0, 0}; - int i = 0; + unsigned int i = 0; while (i < len && v_str[i] != '.') { v.major *= 10; From b597374498b8daf4f4b501c3adab1f746af6e35d Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 11 Sep 2015 14:09:07 +0200 Subject: [PATCH 103/134] add ykcs11 to cppcheck --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 77c0d62..039a8f9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,7 +57,7 @@ endif if ENABLE_CPPCHECK cppcheck: - $(CPPCHECK) -q -v -f --enable=all -i tool/cmdline.c lib tool + $(CPPCHECK) -q -v -f --enable=all -i tool/cmdline.c lib tool ykcs11 endif # Maintainer rules. From 2ea35bbd18ff936daebf0d34f61b3339fdac4fac Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 17 Sep 2015 16:31:21 +0200 Subject: [PATCH 104/134] Export more public key parameters. --- ykcs11/objects.c | 79 +++++++++++++++++++++++++++++++++++++++++- ykcs11/openssl_utils.c | 17 +++++++++ ykcs11/openssl_utils.h | 1 + 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 91b3380..c9780a8 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -221,6 +221,10 @@ static CK_ULONG get_modulus_bits(EVP_PKEY *key) { return do_get_rsa_modulus_length(key); } +static CK_ULONG get_public_exponent(EVP_PKEY *key) { + return do_get_public_exponent(key); +} + static CK_RV get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { return do_get_public_key(key, data, len); } @@ -520,6 +524,14 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_MODULUS: DBG(("MODULUS")); len = sizeof(b_tmp); + + // Make sure that this is an RSA key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_RSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; data = b_tmp; @@ -538,13 +550,37 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_MODULUS_BITS: DBG(("MODULUS BITS")); len = sizeof(CK_ULONG); + + // Make sure that this is an RSA key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_RSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == 0) return CKR_FUNCTION_FAILED; data = (CK_BYTE_PTR) &ul_tmp; break; - /* case CKA_PUBLIC_EXPONENT: */ + case CKA_PUBLIC_EXPONENT: + DBG(("PUBLIC EXPONENT")); + len = sizeof(CK_ULONG); + + // Make sure that this is an RSA key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_RSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + + ul_tmp = get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == 0) + return CKR_FUNCTION_FAILED; + data = (CK_BYTE_PTR) &ul_tmp; + break; + /* case CKA_PRIVATE_EXPONENT: */ /* case CKA_PRIME_1: */ /* case CKA_PRIME_2: */ @@ -714,15 +750,56 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { data = b_tmp; break; + case CKA_MODULUS: + DBG(("MODULUS")); + len = sizeof(b_tmp); + + // Make sure that this is an RSA key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_RSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + + if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + data = b_tmp; + break; + case CKA_MODULUS_BITS: DBG(("MODULUS BITS")); len = sizeof(CK_ULONG); + + // Make sure that this is an RSA key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_RSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == 0) return CKR_FUNCTION_FAILED; data = (CK_BYTE_PTR) &ul_tmp; break; + case CKA_PUBLIC_EXPONENT: + DBG(("PUBLIC EXPONENT")); + len = sizeof(CK_ULONG); + + // Make sure that this is an RSA key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_RSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + + ul_tmp = get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == 0) + return CKR_FUNCTION_FAILED; + data = (CK_BYTE_PTR) &ul_tmp; + break; + case CKA_LOCAL: DBG(("LOCAL TODO")); // Required return CKR_FUNCTION_FAILED; diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 1ce68a0..7a11896 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -288,6 +288,23 @@ CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) { } +CK_ULONG do_get_public_exponent(EVP_PKEY *key) { + + CK_ULONG e = 0; + RSA *rsa; + + rsa = EVP_PKEY_get1_RSA(key); + if (rsa == NULL) + return 0; + + BN_bn2bin(rsa->e, (unsigned char *)&e); + + RSA_free(rsa); + rsa = NULL; + + return e; +} + /* #include */ /* #include */ /* ERR_load_crypto_strings(); */ diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 12f8dde..8ded6f2 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -18,6 +18,7 @@ CK_RV free_cert(X509 *cert); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); CK_KEY_TYPE do_get_key_type(EVP_PKEY *key); CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key); +CK_ULONG do_get_public_exponent(EVP_PKEY *key); CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key); CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); From bae1005fb41a979f94ec46e186b0d00a4fd82b38 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 17 Sep 2015 16:46:04 +0200 Subject: [PATCH 105/134] Export more info for EC keys too. --- ykcs11/objects.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index c9780a8..3767ca9 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -538,15 +538,39 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_EC_POINT: - // We're trying to get the key length, get the ec point of the PUBLIC key - // TODO: or just give an error and explicitly fetch the pubk len when needed DBG(("EC_POINT")); len = sizeof(b_tmp); + + // Make sure that this is an EC key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_ECDSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; data = b_tmp; break; + case CKA_EC_PARAMS: + // Here we want the curve parameters (DER encoded OID) + DBG(("EC_PARAMS")); + len = sizeof(b_tmp); + + // Make sure that this is an EC key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_ECDSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + + if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + + data = b_tmp; + break; + case CKA_MODULUS_BITS: DBG(("MODULUS BITS")); len = sizeof(CK_ULONG); @@ -732,9 +756,16 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { return CKR_FUNCTION_FAILED; case CKA_EC_POINT: - // We're trying to get the key length, get the ec point of the PUBLIC key DBG(("EC_POINT")); len = sizeof(b_tmp); + + // Make sure that this is an EC key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_ECDSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; data = b_tmp; @@ -744,6 +775,14 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { // Here we want the curve parameters (DER encoded OID) DBG(("EC_PARAMS")); len = sizeof(b_tmp); + + // Make sure that this is an EC key + ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk + if (ul_tmp == CKK_VENDOR_DEFINED) + return CKR_FUNCTION_FAILED; + if (ul_tmp != CKK_ECDSA) + return CKR_ATTRIBUTE_VALUE_INVALID; + if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; From 4b668502eefd4dcf43a9da210f86721504ad74d5 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 17 Sep 2015 17:05:29 +0200 Subject: [PATCH 106/134] Minor fixes. --- ykcs11/openssl_utils.c | 8 ++++---- ykcs11/vendors.c | 1 - ykcs11/ykcs11.c | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 7a11896..5d59599 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -220,9 +220,9 @@ create_empty_cert_cleanup: CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len) { - X509 *cert; + X509 *cert; const unsigned char *p = in; // Mandatory temp variable required by OpenSSL - int len; + int len; len = 0; len += get_length(p + 1, &len) + 1; @@ -434,7 +434,7 @@ CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PT // TODO: rand must be seeded first (should be automatic) if (*out_len < key_len) - CKR_BUFFER_TOO_SMALL; + return CKR_BUFFER_TOO_SMALL; if (RSA_padding_add_PKCS1_type_1(buffer, key_len, in, in_len) == 0) return CKR_FUNCTION_FAILED; @@ -468,7 +468,7 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, // TODO: rand must be seeded first (should be automatic) if (*out_len < (CK_ULONG)RSA_size(key)) - CKR_BUFFER_TOO_SMALL; + return CKR_BUFFER_TOO_SMALL; DBG(("Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key))); diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index 25683f5..982208d 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -2,7 +2,6 @@ #include vendor_id_t get_vendor_id(char *vendor_name) { - vendor_id_t vid; if (strstr(vendor_name, "Yubico") != NULL) return YUBICO; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 1b11abd..9bed06a 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -66,7 +66,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( } if (parse_readers(piv_state, readers, len, slots, &n_slots, &n_slots_with_token) != CK_TRUE) - CKR_FUNCTION_FAILED; + return CKR_FUNCTION_FAILED; DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token)); From 809e0ebdb7ab80159d3660ae268488844d350850 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 18 Sep 2015 11:04:47 +0200 Subject: [PATCH 107/134] use in, not signinput to actually sign anything in the ecc case --- tool/yubico-piv-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 9cebb42..fd0e8a0 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -98,7 +98,7 @@ static bool sign_data(ykpiv_state *state, const unsigned char *in, size_t len, u in = signinput; len = padlen; } - if(ykpiv_sign_data(state, signinput, len, out, out_len, algorithm, key) == YKPIV_OK) { + if(ykpiv_sign_data(state, in, len, out, out_len, algorithm, key) == YKPIV_OK) { return true; } return false; From 29bddc33b456a2c8e3c81ce7f757f6a0d5efac41 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 24 Sep 2015 11:39:47 +0200 Subject: [PATCH 108/134] Fix return value check on parse_readers. --- ykcs11/ykcs11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 9bed06a..66f2569 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -65,7 +65,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; } - if (parse_readers(piv_state, readers, len, slots, &n_slots, &n_slots_with_token) != CK_TRUE) + if (parse_readers(piv_state, readers, len, slots, &n_slots, &n_slots_with_token) != CKR_OK) return CKR_FUNCTION_FAILED; DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token)); From a24727fd44deb21ed3e3d433a12506a9f77faff4 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 24 Sep 2015 11:40:17 +0200 Subject: [PATCH 109/134] Move login into common functions. --- ykcs11/token_vendors.c | 29 +++++++++++++++++++++++++++++ ykcs11/token_vendors.h | 2 ++ ykcs11/ykcs11.c | 33 ++++++++++++++------------------- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 6d0c2bd..4cd4bf7 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -4,6 +4,33 @@ #include #include "debug.h" +static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { + + int tries = 0; // TODO: this is effectively disregarded, should we add a better value in ykpiv_verify? + unsigned char key[24]; + size_t key_len = sizeof(key); + + if (user == CKU_USER) { + if (ykpiv_verify(state, (char *)pin, &tries) != YKPIV_OK) { + DBG(("Failed to login")); + return CKR_PIN_INCORRECT; + } + } + else if (user == CKU_SO) { + if(ykpiv_hex_decode((char *)pin, pin_len, key, &key_len) != YKPIV_OK) { + DBG(("Failed decoding key")); + return CKR_FUNCTION_FAILED; + } + + if(ykpiv_authenticate(state, key) != YKPIV_OK) { + DBG(("Failed to authenticate")); + return CKR_PIN_INCORRECT; + } + } + + return CKR_OK; +} + 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]; @@ -200,6 +227,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_objects_num = YUBICO_get_token_objects_num; v.get_token_object_list = YUBICO_get_token_object_list; v.get_token_raw_certificate = YUBICO_get_token_raw_certificate; + v.token_login = COMMON_token_login; v.token_generate_key = COMMON_token_generate_key; v.token_import_cert = COMMON_token_import_cert; v.token_import_private_key = COMMON_token_import_private_key; @@ -219,6 +247,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.get_token_objects_num = NULL; v.get_token_object_list = NULL; v.get_token_raw_certificate = NULL; + v.token_login = NULL; v.token_generate_key = NULL; v.token_import_cert = NULL; v.token_import_private_key = NULL; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 791dc91..ed555b9 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -20,6 +20,7 @@ typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG_PTR); // Common token functions below +typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG); typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, @@ -40,6 +41,7 @@ typedef struct { get_t_objects_num_f get_token_objects_num; get_t_object_list_f get_token_object_list; get_t_raw_certificate_f get_token_raw_certificate; + t_login_f token_login; t_generate_key_f token_generate_key; t_import_cert_f token_import_cert; t_import_private_key_f token_import_private_key; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 66f2569..fa67b6c 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -698,7 +698,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( ) { DIN; - CK_ULONG tries = 0; + CK_RV rv; + token_vendor_t token; if (piv_state == NULL) { DBG(("libykpiv is not initialized or already finalized")); @@ -727,6 +728,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_SESSION_READ_ONLY_EXISTS; } + token = get_token_vendor(session.slot->token->vid); + switch (userType) { case CKU_USER: if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN) @@ -742,13 +745,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } - tries = 0; - if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { // TODO: call this from vendors.c - DBG(("You loose! %lu", tries)); - return CKR_PIN_INCORRECT; + rv = token.token_login(piv_state, CKU_USER, pPin, ulPinLen); + if (rv != CKR_OK) { + DBG(("Unable to login as regular user")); + return rv; } - if ((session.info.flags & CKF_RW_SESSION) == 0) // TODO: double check with the if line 678 for R/O + if ((session.info.flags & CKF_RW_SESSION) == 0) session.info.state = CKS_RO_USER_FUNCTIONS; else session.info.state = CKS_RW_USER_FUNCTIONS; @@ -763,20 +766,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( session.info.state == CKS_RW_USER_FUNCTIONS) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; - /***** TODO: replace this with a token function *****/ - unsigned char key[24]; - size_t key_len = sizeof(key); - if(ykpiv_hex_decode(pPin, ulPinLen, key, &key_len) != YKPIV_OK) { - DBG(("Failed decoding key")); - return CKR_FUNCTION_FAILED; + rv = token.token_login(piv_state, CKU_SO, pPin, ulPinLen); + if (rv != CKR_OK) { + DBG(("Unable to login as SO")); + return rv; } - if(ykpiv_authenticate(piv_state, key) != YKPIV_OK) { - DBG(("Failed to authenticate")); - return CKR_PIN_INCORRECT; - } - /***************************************************/ - session.info.state = CKS_RW_SO_FUNCTIONS; break; @@ -795,7 +790,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_USER_TYPE_INVALID; } - DBG(("You win! %lu", tries)); + DBG(("Successfully logged in")); DOUT; return CKR_OK; From aff57db279563203ad6d56ba2ca5ff2354bc26d1 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 23 Oct 2015 00:08:24 +0200 Subject: [PATCH 110/134] export functions for mac correctly C_ matches what we should export for pkcs11 --- ykcs11/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykcs11/Makefile.am b/ykcs11/Makefile.am index 6d7845a..137df27 100644 --- a/ykcs11/Makefile.am +++ b/ykcs11/Makefile.am @@ -65,7 +65,7 @@ libykcs11_la_LDFLAGS += -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) if HAVE_LD_VERSION_SCRIPT libykcs11_la_LDFLAGS += -Wl,--version-script=$(srcdir)/ykcs11.map else -libykcs11_la_LDFLAGS += -export-symbols-regex '^ykcs11_.*' +libykcs11_la_LDFLAGS += -export-symbols-regex '^C_.*' endif pkgconfigdir = $(libdir)/pkgconfig From 4f12dc41e9107169871ce719f7354c3df70b7e27 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 23 Oct 2015 19:43:36 +0200 Subject: [PATCH 111/134] YKCS11: Added raw certificate extraction. --- ykcs11/objects.c | 55 ++++++++++++++++++++++++------------------ ykcs11/openssl_utils.c | 20 +++++++++++++++ ykcs11/openssl_utils.h | 1 + 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 3767ca9..fa7f09b 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -233,6 +233,10 @@ static CK_RV get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR return do_get_curve_parameters(key, data, len); } +static CK_RV get_raw_cert(X509 *cert, CK_BYTE_PTR data, CK_ULONG_PTR len) { + return do_get_raw_cert(cert, data, len); +} + /* Get data object attribute */ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; @@ -319,31 +323,32 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Get certificate object attribute */ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; - CK_BYTE tmp[64]; + CK_BYTE b_tmp[1024]; + CK_ULONG ul_tmp; CK_ULONG len = 0; DBG(("For certificate object %lu, get ", obj)); - switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above? + switch (template->type) { case CKA_CLASS: DBG(("CLASS")); - len = 1; - tmp[0] = CKO_CERTIFICATE; - data = tmp; + len = sizeof(CK_ULONG); + ul_tmp = CKO_CERTIFICATE; + data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_TOKEN: // Technically all these objects are token objects DBG(("TOKEN")); - len = 1; - tmp[0] = piv_objects[obj].token; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].token; + data = b_tmp; break; case CKA_PRIVATE: DBG(("PRIVATE")); - len = 1; - tmp[0] = piv_objects[obj].private; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].private; + data = b_tmp; break; case CKA_LABEL: @@ -353,14 +358,18 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_VALUE: - DBG(("VALUE TODO")); - return CKR_FUNCTION_FAILED; + DBG(("VALUE")); + len = sizeof(b_tmp); + if (get_raw_cert(cert_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + data = b_tmp; + break; case CKA_CERTIFICATE_TYPE: DBG(("CERTIFICATE TYPE")); - len = 1; - tmp[0] = CKC_X_509; // Support only X.509 certs - data = tmp; + len = sizeof(CK_ULONG); + ul_tmp = CKC_X_509; // Support only X.509 certs + data = (CK_BYTE_PTR) ul_tmp; break; case CKA_ISSUER: @@ -377,9 +386,9 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_ID: DBG(("ID")); - len = 1; - tmp[0] = piv_objects[obj].sub_id; - data = tmp; + len = sizeof(CK_BYTE); + b_tmp[0] = piv_objects[obj].sub_id; + data = b_tmp; break; case CKA_START_DATE: @@ -392,9 +401,9 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_MODIFIABLE: DBG(("MODIFIABLE")); - len = 1; - tmp[0] = piv_objects[obj].modifiable; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].modifiable; + data = b_tmp; break; default: // TODO: there are other attributes for a (x509) certificate @@ -666,7 +675,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; CK_BYTE b_tmp[1024]; - CK_ULONG ul_tmp; // TODO: fix elsewhere too + CK_ULONG ul_tmp; CK_ULONG len = 0; DBG(("For public key object %lu, get ", obj)); diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 5d59599..8b68c2d 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -236,6 +236,26 @@ CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len) { return CKR_OK; } +CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { + + CK_BYTE_PTR p; + int len; + + len = i2d_X509(cert, NULL); + + if (len < 0) + return CKR_FUNCTION_FAILED; + + if ((CK_ULONG)len > *out_len) + return CKR_BUFFER_TOO_SMALL; + + p = out; + if ((*out_len = i2d_X509(cert, &p)) == 0) + return CKR_FUNCTION_FAILED; + + return CKR_OK; +} + CK_RV free_cert(X509 *cert) { X509_free((X509 *) cert); diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 8ded6f2..09f6482 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -13,6 +13,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len); +CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV free_cert(X509 *cert); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); From a9ddf3e3b231787edae6bb8c75c7082e2f2547c2 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 27 Oct 2015 17:33:30 +0100 Subject: [PATCH 112/134] Added support for touch and change policy during key import. --- ykcs11/mechanisms.c | 1 + ykcs11/objects.c | 16 ++++++++++++++-- ykcs11/objects.h | 4 ++-- ykcs11/pkcs11t.h | 7 +++++++ ykcs11/token_vendors.c | 28 ++++++++++++++++++++++++---- ykcs11/token_vendors.h | 2 +- ykcs11/ykcs11.c | 9 +++++---- ykcs11/ykcs11.h | 2 +- 8 files changed, 55 insertions(+), 14 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index ce1ef72..b7b4886 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -163,6 +163,7 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) { case CKM_RSA_X_509: case CKM_ECDSA: // No hash required for this mechanism + op_info->op.sign.md_ctx = NULL; return CKR_OK; case CKM_SHA1_RSA_PKCS: diff --git a/ykcs11/objects.c b/ykcs11/objects.c index fa7f09b..99e6519 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1063,7 +1063,7 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, } CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *value, CK_ULONG_PTR value_len) { + CK_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; @@ -1073,6 +1073,8 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR ec_params; CK_ULONG ec_params_len; + *vendor_defined = 0; + for (i = 0; i < n; i++) { switch (templ[i].type) { case CKA_CLASS: @@ -1108,6 +1110,10 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, break; + case CKA_VENDOR_DEFINED: + *vendor_defined = *((CK_ULONG_PTR)templ[i].pValue); + break; + case CKA_TOKEN: case CKA_LABEL: case CKA_SUBJECT: @@ -1138,7 +1144,7 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, - CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len) { + CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; @@ -1154,6 +1160,8 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_ULONG dq_len; CK_ULONG qinv_len; + *vendor_defined = 0; + for (i = 0; i < n; i++) { switch (templ[i].type) { case CKA_CLASS: @@ -1217,6 +1225,10 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, break; + case CKA_VENDOR_DEFINED: + *vendor_defined = *((CK_ULONG_PTR)templ[i].pValue); + break; + case CKA_TOKEN: case CKA_LABEL: case CKA_SUBJECT: diff --git a/ykcs11/objects.h b/ykcs11/objects.h index 892cb54..860f3a8 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -15,10 +15,10 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len); CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *value, CK_ULONG_PTR value_len); + CK_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, - CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len); + CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); #endif diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index f793cfe..bcdd9e0 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -1183,4 +1183,11 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; /* undo packing */ //#include "pkcs11u.h" // TODO: msc specific? +// YUBICO specific attributes +#define CKA_TOUCH_PIN_DEFAULT 0x00000000U +#define CKA_TOUCH_ALWAYS 0x00000001U +#define CKA_PIN_ONCE 0x00000002U +#define CKA_PIN_ALWAYS 0x00000004U + + #endif diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 4cd4bf7..99dfd7e 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -151,7 +151,7 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYTE_PTR p, CK_BYTE_PTR q, CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv, - CK_BYTE_PTR ec_data, CK_ULONG elem_len) { + CK_BYTE_PTR ec_data, CK_ULONG elem_len, CK_ULONG vendor_defined) { unsigned char key_data[1024]; unsigned char *in_ptr = key_data; @@ -193,17 +193,37 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT memcpy(in_ptr, qinv, (size_t)(elem_len)); in_ptr += elem_len; } - else if(templ[2] == YKPIV_ALGO_ECCP256) { + else if (templ[2] == YKPIV_ALGO_ECCP256) { *in_ptr++ = 0x06; in_ptr += set_length(in_ptr, elem_len); memcpy(in_ptr, ec_data, (size_t)(elem_len)); in_ptr += elem_len; } - if(ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK) + // PIN policy and touch + if (vendor_defined != 0) { + if (vendor_defined & CKA_PIN_ONCE) { + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ONCE; + } + else if (vendor_defined & CKA_PIN_ALWAYS) { + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; + } + + if (vendor_defined & CKA_TOUCH_ALWAYS) { + *in_ptr++ = YKPIV_TOUCHPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS; + } + } + + if (ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK) return CKR_FUNCTION_FAILED; - if(sw != 0x9000) + if (sw != 0x9000) return CKR_DEVICE_ERROR; return CKR_OK; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index ed555b9..c59f376 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -24,7 +24,7 @@ typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULON typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, - CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG); + CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG); // TODO: replace all the common calls with functions defined in .c that use libykpiv diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index fa67b6c..c026e28 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -854,6 +854,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_BYTE_PTR dp; CK_BYTE_PTR dq; CK_BYTE_PTR qinv; + CK_ULONG vendor_defined; token_vendor_t token; CK_BBOOL is_new; CK_BBOOL is_rsa; @@ -974,11 +975,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( // Try to parse the key as EC is_rsa = CK_FALSE; - rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len); + rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &vendor_defined); if (rv != CKR_OK) { // Try to parse the key as RSA is_rsa = CK_TRUE; - rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len); + rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len, &vendor_defined); if (rv != CKR_OK) { DBG(("Private key template not valid")); return rv; @@ -993,7 +994,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( DBG(("Key is RSA")); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv, NULL, - value_len); + value_len, vendor_defined); if (rv != CKR_OK) { DBG(("Unable to import RSA private key")); return rv; @@ -1003,7 +1004,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( DBG(("Key is ECDSA")); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL, value, - value_len); + value_len, vendor_defined); if (rv != CKR_OK) { DBG(("Unable to import ECDSA private key")); return rv; diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 057c155..0793432 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -6,7 +6,7 @@ #include "openssl_types.h" #include "vendors.h" -#define YKCS11_OP_BUFSIZE 4096 +#define YKCS11_OP_BUFSIZE 4096 typedef struct { vendor_id_t vid; From b7c0e8ea6bb1cdb294213293ba3cd40e2321bb81 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 28 Oct 2015 11:33:20 +0100 Subject: [PATCH 113/134] YKCS11: added support for touch and PIN policy during generate. --- ykcs11/mechanisms.c | 8 ++++++-- ykcs11/token_vendors.c | 44 ++++++++++++++++++++++++++++++++---------- ykcs11/token_vendors.h | 2 +- ykcs11/ykcs11.c | 2 +- ykcs11/ykcs11.h | 8 ++++---- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index b7b4886..de642ff 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -420,7 +420,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG default: DBG(("Invalid attribute %lx in public key template", templ[i].type)); - return CKR_ATTRIBUTE_VALUE_INVALID; + return CKR_ATTRIBUTE_TYPE_INVALID; } } @@ -433,6 +433,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG CK_ULONG i; op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism); + op_info->op.gen.vendor_defined = 0; for (i = 0; i < n; i++) { switch (templ[i].type) { @@ -473,6 +474,9 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue); break; + case CKA_VENDOR_DEFINED: + op_info->op.gen.vendor_defined = (*((CK_ULONG_PTR)templ[i].pValue)); + case CKA_SENSITIVE: case CKA_DECRYPT: case CKA_UNWRAP: @@ -485,7 +489,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG default: DBG(("Invalid attribute %lx in private key template", templ[i].type)); - return CKR_ATTRIBUTE_VALUE_INVALID; + return CKR_ATTRIBUTE_TYPE_INVALID; } } diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 99dfd7e..0fd7198 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -31,9 +31,11 @@ static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CH return CKR_OK; } -static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE key, CK_ULONG key_len) { +static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, + CK_BYTE key, CK_ULONG key_len, CK_ULONG vendor_defined) { // TODO: make a function in ykpiv for this - unsigned char in_data[5]; + unsigned char in_data[11]; + unsigned char *in_ptr = in_data; unsigned char data[1024]; unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0}; unsigned char *certptr; @@ -45,10 +47,10 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE templ[3] = key; - in_data[0] = 0xac; - in_data[1] = 3; - in_data[2] = 0x80; - in_data[3] = 1; + *in_ptr++ = 0xac; + *in_ptr++ = 3; + *in_ptr++ = 0x80; + *in_ptr++ = 1; switch(key_len) { case 2048: @@ -61,7 +63,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE case 1024: if (rsa == CK_TRUE) - in_data[4] = YKPIV_ALGO_RSA1024; + *in_ptr++ = YKPIV_ALGO_RSA1024; else return CKR_FUNCTION_FAILED; @@ -69,7 +71,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE case 256: if (rsa == CK_FALSE) - in_data[4] = YKPIV_ALGO_ECCP256; + *in_ptr++ = YKPIV_ALGO_ECCP256; else return CKR_FUNCTION_FAILED; @@ -78,8 +80,30 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE default: return CKR_FUNCTION_FAILED; } - //DBG(("Generating key %x with algorithm %u and length %lu", templ[3], in_data[4], key_len)); - if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, &recv_len, &sw) != YKPIV_OK || + // PIN policy and touch + if (vendor_defined != 0) { + if (vendor_defined & CKA_PIN_ONCE) { + in_data[1] += 3; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ONCE; + } + else if (vendor_defined & CKA_PIN_ALWAYS) { + in_data[1] += 3; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; + } + + if (vendor_defined & CKA_TOUCH_ALWAYS) { + in_data[1] += 3; + *in_ptr++ = YKPIV_TOUCHPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS; + } + } + + if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK || sw != 0x9000) return CKR_DEVICE_ERROR; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index c59f376..9513063 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -21,7 +21,7 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT // Common token functions below typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); +typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c026e28..4025524 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -2053,7 +2053,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( token = get_token_vendor(session.slot->token->vid); - if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len)) != CKR_OK) { + if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len, op_info.op.gen.vendor_defined)) != CKR_OK) { DBG(("Unable to generate key pair")); return rv; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 0793432..e29b24b 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -28,7 +28,6 @@ typedef struct { ykcs11_slot_t *slot; } ykcs11_session_t; - typedef enum { YKCS11_NOOP, YKCS11_GEN, @@ -38,9 +37,10 @@ typedef enum { } ykcs11_op_type_t; typedef struct { - CK_BBOOL rsa; // RSA or EC key - CK_BYTE key_id; // Key id - CK_ULONG key_len; // Length in bits + CK_BBOOL rsa; // RSA or EC key + CK_BYTE key_id; // Key id + CK_ULONG key_len; // Length in bits + CK_ULONG vendor_defined; // Additional parameters (touch and PIN policy) } gen_info_t; typedef struct { From 12e05944063f53e15d157282f7030190349eaa39 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 28 Oct 2015 11:36:55 +0100 Subject: [PATCH 114/134] Indent. --- ykcs11/token_vendors.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 0fd7198..6fc452d 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -227,14 +227,14 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT // PIN policy and touch if (vendor_defined != 0) { if (vendor_defined & CKA_PIN_ONCE) { - *in_ptr++ = YKPIV_PINPOLICY_TAG; - *in_ptr++ = 0x01; - *in_ptr++ = YKPIV_PINPOLICY_ONCE; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ONCE; } else if (vendor_defined & CKA_PIN_ALWAYS) { - *in_ptr++ = YKPIV_PINPOLICY_TAG; - *in_ptr++ = 0x01; - *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; } if (vendor_defined & CKA_TOUCH_ALWAYS) { @@ -255,7 +255,7 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT } token_vendor_t get_token_vendor(vendor_id_t vid) { - token_vendor_t v; + token_vendor_t v; switch (vid) { case YUBICO: From e6bca9b332ce537401043b2af3d4b9ba056bd847 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 28 Oct 2015 11:43:41 +0100 Subject: [PATCH 115/134] YKCS11: Suppress some warnings. --- ykcs11/token_vendors.c | 3 +++ ykcs11/ykcs11.c | 3 +++ ykcs11/yubico_token.c | 1 + 3 files changed, 7 insertions(+) diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 6fc452d..c185f7e 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -4,6 +4,9 @@ #include #include "debug.h" +#include +#include "../tool/util.h" + static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { int tries = 0; // TODO: this is effectively disregarded, should we add a better value in ykpiv_verify? diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 4025524..32715c0 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -10,6 +10,9 @@ #include "openssl_types.h" #include "debug.h" +#include +#include "../tool/util.h" + #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index f2df6e2..11a8897 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -2,6 +2,7 @@ #include "pkcs11.h" #include #include "debug.h" +#include "objects.h" #define YUBICO_MECHANISMS_NUM 5 From 651280ca8baad2a22a9d07e6221bf10dd6c2cec5 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 2 Nov 2015 15:17:25 +0100 Subject: [PATCH 116/134] Initialize context to -1 and always call establish context. --- lib/ykpiv.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index ae6dc67..538b632 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -103,6 +103,7 @@ ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose) { } memset(s, 0, sizeof(ykpiv_state)); s->verbose = verbose; + s->context = -1; *state = s; return YKPIV_OK; } @@ -204,14 +205,12 @@ ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len) { unsigned long num_readers = 0; long rc; - if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { - rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); - if (rc != SCARD_S_SUCCESS) { - if(state->verbose) { - fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); - } - return YKPIV_PCSC_ERROR; + rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); + if (rc != SCARD_S_SUCCESS) { + if(state->verbose) { + fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); } + return YKPIV_PCSC_ERROR; } rc = SCardListReaders(state->context, NULL, NULL, &num_readers); From dcc2545a4c2776e17bd7dd1527cc3f0f17ef07cf Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 4 Nov 2015 14:02:29 +0100 Subject: [PATCH 117/134] YKCS11: added certificate deletion. --- ykcs11/objects.c | 26 +++++++++++++ ykcs11/objects.h | 3 +- ykcs11/openssl_utils.c | 26 +++++++++++-- ykcs11/openssl_utils.h | 6 ++- ykcs11/pkcs11t.h | 2 + ykcs11/token_vendors.c | 10 +++++ ykcs11/token_vendors.h | 2 + ykcs11/ykcs11.c | 88 +++++++++++++++++++++++++++++++++++++++++- 8 files changed, 155 insertions(+), 8 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 99e6519..876bc57 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1012,6 +1012,22 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) { return CKR_OK; } +CK_RV delete_cert(piv_obj_id_t cert_id) { + CK_RV rv; + + // Clear the object containing the certificate + rv = do_delete_cert(&cert_objects[piv_objects[cert_id].sub_id].data); + if (rv != CKR_OK) + return rv; + + // Clear the object containing the public key + rv = do_delete_pubk(&pubkey_objects[piv_objects[cert_id].sub_id].data); + if (rv != CKR_OK) + return rv; + + return CKR_OK; +} + CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len) { @@ -1263,3 +1279,13 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, return CKR_OK; } + +CK_RV check_delete_cert(CK_OBJECT_HANDLE hObject, CK_BYTE_PTR id) { + + if (hObject < PIV_CERT_OBJ_X509_PIV_AUTH || hObject >= PIV_CERT_OBJ_LAST) + return CKR_ACTION_PROHIBITED; + + *id = hObject - PIV_CERT_OBJ_X509_PIV_AUTH; + + return CKR_OK; +} diff --git a/ykcs11/objects.h b/ykcs11/objects.h index 860f3a8..be9db19 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -11,6 +11,7 @@ CK_BBOOL is_private_object(ykcs11_session_t *s, CK_OBJECT_HANDLE obj); CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); +CK_RV delete_cert(piv_obj_id_t cert_id); CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len); @@ -19,6 +20,6 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); - +CK_RV check_delete_cert(CK_OBJECT_HANDLE hObject, CK_BYTE_PTR id); #endif diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 8b68c2d..cc2085a 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -256,12 +256,21 @@ CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { return CKR_OK; } -CK_RV free_cert(X509 *cert) { +CK_RV do_delete_cert(X509 **cert) { + + X509_free(*cert); + cert = NULL; + + return CKR_OK; + +} + +/*CK_RV free_cert(X509 *cert) { X509_free((X509 *) cert); return CKR_OK; -} +}*/ CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key) { @@ -438,13 +447,22 @@ CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) return CKR_OK; } -CK_RV free_key(EVP_PKEY *key) { +CK_RV do_delete_pubk(EVP_PKEY **key) { + + EVP_PKEY_free(*key); + key = NULL; + + return CKR_OK; + +} + +/*CK_RV free_key(EVP_PKEY *key) { EVP_PKEY_free(key); return CKR_OK; -} + }*/ CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len) { unsigned char buffer[512]; diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 09f6482..35461a5 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -14,7 +14,8 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len); CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len); -CK_RV free_cert(X509 *cert); +CK_RV do_delete_cert(X509 **cert); +//CK_RV free_cert(X509 *cert); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); CK_KEY_TYPE do_get_key_type(EVP_PKEY *key); @@ -23,7 +24,8 @@ CK_ULONG do_get_public_exponent(EVP_PKEY *key); CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key); CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len); -CK_RV free_key(EVP_PKEY *key); +CK_RV do_delete_pubk(EVP_PKEY **key); +//CK_RV free_key(EVP_PKEY *key); CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, CK_ULONG key_len); CK_RV do_pkcs_1_digest_info(CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_BYTE_PTR out, CK_ULONG_PTR out_len); diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index bcdd9e0..d357092 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -755,6 +755,8 @@ typedef CK_ULONG CK_RV; #define CKR_ATTRIBUTE_SENSITIVE 0x00000011UL #define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012UL #define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013UL +#define CKR_COPY_PROHIBITED 0x0000001AUL +#define CKR_ACTION_PROHIBITED 0x0000001BUL #define CKR_DATA_INVALID 0x00000020UL #define CKR_DATA_LEN_RANGE 0x00000021UL #define CKR_DEVICE_ERROR 0x00000030UL diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index c185f7e..cb62e83 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -257,6 +257,14 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT } +CK_RV COMMON_token_delete_cert(ykpiv_state *state, CK_ULONG cert_id) { + + if (ykpiv_save_object(state, cert_id, NULL, 0) != YKPIV_OK) + return CKR_DEVICE_ERROR; + + return CKR_OK; +} + token_vendor_t get_token_vendor(vendor_id_t vid) { token_vendor_t v; @@ -278,6 +286,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.token_generate_key = COMMON_token_generate_key; v.token_import_cert = COMMON_token_import_cert; v.token_import_private_key = COMMON_token_import_private_key; + v.token_delete_cert = COMMON_token_delete_cert; break; case UNKNOWN: @@ -298,6 +307,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) { v.token_generate_key = NULL; v.token_import_cert = NULL; v.token_import_private_key = NULL; + v.token_delete_cert = NULL; } return v; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 9513063..3b57209 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -25,6 +25,7 @@ typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG, CK typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG); +typedef CK_RV (*t_delete_cert_f)(ykpiv_state *, CK_ULONG); // TODO: replace all the common calls with functions defined in .c that use libykpiv @@ -45,6 +46,7 @@ typedef struct { t_generate_key_f token_generate_key; t_import_cert_f token_import_cert; t_import_private_key_f token_import_private_key; + t_delete_cert_f token_delete_cert; } token_vendor_t; token_vendor_t get_token_vendor(vendor_id_t vid); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 32715c0..4d76606 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1044,7 +1044,93 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( ) { DIN; - DBG(("TODO!!!")); + + CK_RV rv; + token_vendor_t token; + CK_ULONG i; + CK_ULONG j; + CK_BYTE id; + CK_ULONG cert_id; + CK_ULONG pvtk_id; + CK_ULONG pubk_id; + piv_obj_id_t *obj_ptr; + + DBG(("Deleting object %lu", hObject)); + + if (piv_state == NULL) { + DBG(("libykpiv is not initialized or already finalized")); + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); + return CKR_SESSION_CLOSED; + } + + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); + return CKR_SESSION_HANDLE_INVALID; + } + + // Only certificates can be deleted + // SO must be logged in + if (session.info.state != CKS_RW_SO_FUNCTIONS) { + DBG(("Unable to delete objects, SO must be logged in")); + return CKR_ACTION_PROHIBITED; + } + + rv = check_delete_cert(hObject, &id); + if (rv != CKR_OK) { + DBG(("Object %lu can not be deleted", hObject)); + return rv; + } + + token = get_token_vendor(session.slot->token->vid); + + rv = token.token_delete_cert(piv_state, piv_2_ykpiv(hObject)); + if (rv != CKR_OK) { + DBG(("Unable to delete object %lu", hObject)); + return rv; + } + + // Remove the object from the session + // Do it in a slightly inefficient way but preserve ordering + + cert_id = PIV_CERT_OBJ_X509_PIV_AUTH + id; // TODO: make function for these + pvtk_id = PIV_PVTK_OBJ_PIV_AUTH + id; + pubk_id = PIV_PUBK_OBJ_PIV_AUTH + id; + + obj_ptr = malloc((session.slot->token->n_objects - 3) * sizeof(piv_obj_id_t)); + if (obj_ptr == NULL) { + DBG(("Unable to allocate memory")); + return CKR_HOST_MEMORY; + } + + i = 0; + j = 0; + while (i < session.slot->token->n_objects) { + if (session.slot->token->objects[i] == cert_id || + session.slot->token->objects[i] == pvtk_id || + session.slot->token->objects[i] == pubk_id) { + i++; + continue; + } + + obj_ptr[j++] = session.slot->token->objects[i++]; + } + + rv = delete_cert(cert_id); + if (rv != CKR_OK) { + DBG(("Unable to delete certificate data")); + return CKR_FUNCTION_FAILED; + } + + free(session.slot->token->objects); + + session.slot->token->n_objects -= 3; + session.slot->token->n_certs--; + session.slot->token->objects = obj_ptr; + DOUT; return CKR_OK; } From 83099997c0045c6d28c64d3c869e9d55eee33cc3 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 4 Nov 2015 17:19:56 +0100 Subject: [PATCH 118/134] YKCS11: fix type typo. --- ykcs11/objects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 876bc57..6f9b75b 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -369,7 +369,7 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { DBG(("CERTIFICATE TYPE")); len = sizeof(CK_ULONG); ul_tmp = CKC_X_509; // Support only X.509 certs - data = (CK_BYTE_PTR) ul_tmp; + data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_ISSUER: From f3bd82710087eea9a8ba8049fba97612fd430d07 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 14:09:09 +0100 Subject: [PATCH 119/134] YKCS11: add more precondition checks during SingInit. --- ykcs11/ykcs11.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 4d76606..701a2e7 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1747,7 +1747,30 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( goto sign_out; } - // TODO: check other conditions + if (session.handle != YKCS11_SESSION_ID) { + DBG(("Session is not open")); + rv = CKR_SESSION_CLOSED; + goto sign_out; + } + + if (hSession != session.handle) { + DBG(("Unknown session %lu", hSession)); + rv = CKR_SESSION_HANDLE_INVALID; + goto sign_out; + } + + if (op_info.type != YKCS11_SIGN) { + DBG(("Operation not initialized")); + rv = CKR_OPERATION_NOT_INITIALIZED; + goto sign_out; + } + + if (session.info.state == CKS_RO_PUBLIC_SESSION || + session.info.state == CKS_RW_PUBLIC_SESSION) { + DBG(("User is not logged in")); + rv = CKR_USER_NOT_LOGGED_IN; + goto sign_out; + } if (pSignature == NULL_PTR) { // Just return the size of the signature From 98f3462e5ebb62ce644e4c73bebfc5b09f8445ae Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 12:07:14 +0100 Subject: [PATCH 120/134] YKCS11: Remove some useless comments. --- ykcs11/ykcs11.c | 63 +++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 701a2e7..439b425 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1,5 +1,4 @@ #include "ykcs11.h" -//#include "pkcs11.h" #include #include #include @@ -18,6 +17,7 @@ #define PIV_MIN_PIN_LEN 6 #define PIV_MAX_PIN_LEN 8 +#define PIV_MGM_KEY_LEN 48 #define YKCS11_MAX_SLOTS 16 #define YKCS11_MAX_SIG_BUF_LEN 1024 @@ -26,11 +26,11 @@ static ykpiv_state *piv_state = NULL; -static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; // TODO: build at runtime? +static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; static CK_ULONG n_slots = 0; static CK_ULONG n_slots_with_token = 0; -static ykcs11_session_t session; // TODO: support multiple sessions? +static ykcs11_session_t session; static struct { CK_BBOOL active; @@ -41,7 +41,7 @@ static struct { op_info_t op_info; -extern CK_FUNCTION_LIST function_list; // TODO: check all return values +extern CK_FUNCTION_LIST function_list; /* General Purpose */ @@ -53,14 +53,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( CK_BYTE readers[2048]; CK_ULONG len = sizeof(readers); - // TODO: check for locks and mutexes - if (piv_state != NULL) return CKR_CRYPTOKI_ALREADY_INITIALIZED; if (ykpiv_init(&piv_state, YKCS11_DBG) != YKPIV_OK) { DBG(("Unable to initialize libykpiv")); - return CKR_FUNCTION_FAILED; // TODO: better error? + return CKR_FUNCTION_FAILED; } if (ykpiv_list_readers(piv_state, (char*)readers, &len) != YKPIV_OK) { @@ -102,7 +100,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( } memset(slots, 0, sizeof(slots)); - ykpiv_done(piv_state); // TODO: this calls disconnect... + ykpiv_done(piv_state); piv_state = NULL; DOUT; @@ -140,7 +138,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)( DBG(("GetFunctionList called with ppFunctionList = NULL")); return CKR_ARGUMENTS_BAD; } - *ppFunctionList = &function_list; // TODO: filter out unsupported functions + *ppFunctionList = &function_list; DOUT; return CKR_OK; @@ -183,7 +181,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( for (j = 0, i = 0; i < n_slots; i++) { if (tokenPresent) { - if (has_token(slots + i)) // TODO: use more to check if TOKEN_REMOVED + if (has_token(slots + i)) pSlotList[j++] = i; } else @@ -255,14 +253,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( memcpy(pInfo, &slots[slotID].token->info, sizeof(CK_TOKEN_INFO)); // Overwrite values that are application specific - pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? - pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token - + pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1? + pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token pInfo->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION; // maximum number of read/write sessions that can be opened with the token at one time by a single TODO: should this be 1? - - pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token - pInfo->ulMaxPinLen = PIV_MAX_PIN_LEN; // maximum length in bytes of the PIN - pInfo->ulMinPinLen = PIV_MIN_PIN_LEN; // minimum length in bytes of the PIN + pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token + pInfo->ulMaxPinLen = PIV_MAX_PIN_LEN; // maximum length in bytes of the PIN + pInfo->ulMinPinLen = PIV_MIN_PIN_LEN; // minimum length in bytes of the PIN pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; @@ -560,7 +556,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( cert_ids = NULL; session.handle = YKCS11_SESSION_ID; - // TODO: KEEP TRACK OF THE APPLICATION (possble to steal a session?) *phSession = session.handle; @@ -738,10 +733,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN) return CKR_ARGUMENTS_BAD; - /*if (session.info.state == CKS_RW_USER_FUNCTIONS) { // TODO: make sure to set session default state as not logged + /*if (session.info.state == CKS_RW_USER_FUNCTIONS) { DBG(("This user type is already logged in")); return CKR_USER_ALREADY_LOGGED_IN; - }*/ //TODO: TEMPORARY FIX TO ALLOW MULTIPLE LOGIN. THIS MUST GO BACK IN! + }*/ //TODO: FIx to allow multiple login. Decide on context specific. if (session.info.state == CKS_RW_SO_FUNCTIONS) { DBG(("A different uyser type is already logged in")); @@ -761,7 +756,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( break; case CKU_SO: - // TODO: check for mgmt key length? + if (ulPinLen != PIV_MGM_KEY_LEN) + return CKR_ARGUMENTS_BAD; + if (session.info.state == CKS_RW_SO_FUNCTIONS) return CKR_USER_ALREADY_LOGGED_IN; @@ -820,8 +817,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( return CKR_SESSION_HANDLE_INVALID; } - // TODO: check more conditions - if (session.info.state == CKS_RO_PUBLIC_SESSION || session.info.state == CKS_RW_PUBLIC_SESSION) return CKR_USER_NOT_LOGGED_IN; @@ -831,8 +826,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( else session.info.state = CKS_RW_PUBLIC_SESSION; - // TODO: more things to clean? - DOUT; return CKR_OK; } @@ -883,7 +876,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( return CKR_SESSION_HANDLE_INVALID; } - if (session.info.state != CKS_RW_SO_FUNCTIONS) { // TODO: does a regular user ever call this function? + if (session.info.state != CKS_RW_SO_FUNCTIONS) { DBG(("Authentication required to import objects")); return CKR_SESSION_READ_ONLY; } @@ -1694,14 +1687,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( if (op_info.op.sign.key_len == 256) op_info.op.sign.algo = YKPIV_ALGO_ECCP256; /*else - op_info.algo = ;*/ + op_info.op.sign.algo = YKPIV_ALGO_ECCP384;*/ // TODO: add support for P384 } - //op_info.hash = get_mechanism_hash(pMechanism->mechanism); - DBG(("Key length is %lu bit", op_info.op.sign.key_len)); - op_info.op.sign.key_id = piv_2_ykpiv(hKey); // TODO: have to set this!!! + op_info.op.sign.key_id = piv_2_ykpiv(hKey); if (op_info.op.sign.key_id == 0) { DBG(("Incorrect key %lu", hKey)); return CKR_KEY_HANDLE_INVALID; @@ -1804,7 +1795,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( // ECDSA if (ulDataLen > 128) { // Specs say ECDSA only supports 1024 bit - DBG(("Meximum data length for ECDSA is 128 bytes")); + DBG(("Maximum data length for ECDSA is 128 bytes")); rv = CKR_FUNCTION_FAILED; goto sign_out; } @@ -1852,7 +1843,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); } - op_info.type = YKCS11_NOOP; // TODO: anything to clear here? + op_info.type = YKCS11_NOOP; rv = CKR_OK; @@ -2202,18 +2193,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( *obj_ptr++ = pubk_id; } - // Write/Update the object + // Write/Update the object cert_len = sizeof(cert_data); - rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, &cert_len); // TODO: double check len here (check inside, never changed but used below). One more time above + rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, &cert_len); if (rv != CKR_OK) { DBG(("Unable to get certificate data from token")); - return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point + return CKR_FUNCTION_FAILED; } rv = store_cert(cert_id, cert_data, cert_len); if (rv != CKR_OK) { DBG(("Unable to store certificate data")); - return CKR_FUNCTION_FAILED; // TODO: although key generation succeeded at this point + return CKR_FUNCTION_FAILED; } *phPrivateKey = op_info.op.gen.key_id; From 602208bf200d83289d8b87058b080c9cdcfdae7c Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 15:26:59 +0100 Subject: [PATCH 121/134] YKCS11: Change DBG to print to stderr. --- ykcs11/debug.h | 10 +- ykcs11/mechanisms.c | 8 +- ykcs11/objects.c | 152 +++++++------- ykcs11/openssl_utils.c | 4 +- ykcs11/token_vendors.c | 6 +- ykcs11/ykcs11.c | 446 ++++++++++++++++++++--------------------- ykcs11/yubico_token.c | 10 +- 7 files changed, 318 insertions(+), 318 deletions(-) diff --git a/ykcs11/debug.h b/ykcs11/debug.h index 1fbe740..1848af6 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -4,15 +4,15 @@ #define YKCS11_DBG 1 // General debug, must be either 1 or 0 #define YKCS11_DINOUT 1 // Function in/out debug, must be either 1 or 0 -#define D(x) do { \ - printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ - printf x; \ - printf ("\n"); \ +#define D(x...) do { \ + fprintf (stderr, "debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ + fprintf (stderr, x); \ + fprintf (stderr, "\n"); \ } while (0) #if YKCS11_DBG #include -#define DBG(x) D(x); +#define DBG(x...) D(x); #else #define DBG(x) #endif diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index de642ff..98cdf02 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -376,7 +376,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG // Only support F4 if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0) { - DBG(("Unsupported public exponent")); + DBG("Unsupported public exponent"); return CKR_ATTRIBUTE_VALUE_INVALID; } @@ -388,7 +388,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG if (*((CK_ULONG_PTR) templ[i].pValue) != 1024 && *((CK_ULONG_PTR) templ[i].pValue) != 2048) { // TODO: make define? - DBG(("Unsupported MODULUS_BITS (key length)")); + DBG("Unsupported MODULUS_BITS (key length)"); return CKR_ATTRIBUTE_VALUE_INVALID; } @@ -419,7 +419,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG break; default: - DBG(("Invalid attribute %lx in public key template", templ[i].type)); + DBG("Invalid attribute %lx in public key template", templ[i].type); return CKR_ATTRIBUTE_TYPE_INVALID; } } @@ -488,7 +488,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG break; default: - DBG(("Invalid attribute %lx in private key template", templ[i].type)); + DBG("Invalid attribute %lx in private key template", templ[i].type); return CKR_ATTRIBUTE_TYPE_INVALID; } } diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 6f9b75b..d2c07a4 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -242,11 +242,11 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; CK_BYTE tmp[64]; CK_ULONG len = 0; - DBG(("For data object %lu, get ", obj)); + DBG("For data object %lu, get ", obj); switch (template->type) { case CKA_CLASS: - DBG(("CLASS")); + DBG("CLASS"); len = 1; tmp[0] = CKO_DATA; data = tmp; @@ -254,51 +254,51 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN")); + DBG("TOKEN"); len = 1; tmp[0] = piv_objects[obj].token; data = tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE")); + DBG("PRIVATE"); len = 1; tmp[0] = piv_objects[obj].private; data = tmp; break; case CKA_LABEL: - DBG(("LABEL")); + DBG("LABEL"); len = strlen(piv_objects[obj].label) + 1; data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_APPLICATION: - DBG(("APPLICATION")); + DBG("APPLICATION"); len = strlen(piv_objects[obj].label) + 1; data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_VALUE: // TODO: this can be done with -r and -d|-a - DBG(("VALUE TODO!!!")); + DBG("VALUE TODO!!!"); return CKR_FUNCTION_FAILED; case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? - DBG(("OID")); + DBG("OID"); strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid); asn1_encode_oid(tmp, tmp, &len); data = tmp; break; case CKA_MODIFIABLE: - DBG(("MODIFIABLE")); + DBG("MODIFIABLE"); len = 1; tmp[0] = piv_objects[obj].modifiable; data = tmp; break; default: - DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); + DBG("UNKNOWN ATTRIBUTE %lx", template[0].type); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -326,11 +326,11 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE b_tmp[1024]; CK_ULONG ul_tmp; CK_ULONG len = 0; - DBG(("For certificate object %lu, get ", obj)); + DBG("For certificate object %lu, get ", obj); switch (template->type) { case CKA_CLASS: - DBG(("CLASS")); + DBG("CLASS"); len = sizeof(CK_ULONG); ul_tmp = CKO_CERTIFICATE; data = (CK_BYTE_PTR) &ul_tmp; @@ -338,27 +338,27 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN")); + DBG("TOKEN"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].token; data = b_tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE")); + DBG("PRIVATE"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].private; data = b_tmp; break; case CKA_LABEL: - DBG(("LABEL")); + DBG("LABEL"); len = strlen(piv_objects[obj].label) + 1; data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_VALUE: - DBG(("VALUE")); + DBG("VALUE"); len = sizeof(b_tmp); if (get_raw_cert(cert_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) return CKR_FUNCTION_FAILED; @@ -366,48 +366,48 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_CERTIFICATE_TYPE: - DBG(("CERTIFICATE TYPE")); + DBG("CERTIFICATE TYPE"); len = sizeof(CK_ULONG); ul_tmp = CKC_X_509; // Support only X.509 certs data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_ISSUER: - DBG(("ISSUER TODO")); // Default empty + DBG("ISSUER TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_SERIAL_NUMBER: - DBG(("SERIAL NUMBER TODO")); // Default empty + DBG("SERIAL NUMBER TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_SUBJECT: - DBG(("SUBJECT TODO")); // Required + DBG("SUBJECT TODO"); // Required return CKR_FUNCTION_FAILED; case CKA_ID: - DBG(("ID")); + DBG("ID"); len = sizeof(CK_BYTE); b_tmp[0] = piv_objects[obj].sub_id; data = b_tmp; break; case CKA_START_DATE: - DBG(("START DATE TODO")); // Default empty + DBG("START DATE TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - DBG(("END DATE TODO")); // Default empty + DBG("END DATE TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_MODIFIABLE: - DBG(("MODIFIABLE")); + DBG("MODIFIABLE"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].modifiable; data = b_tmp; break; default: // TODO: there are other attributes for a (x509) certificate - DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); + DBG("UNKNOWN ATTRIBUTE %lx", template[0].type); template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -435,11 +435,11 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE b_tmp[1024]; CK_ULONG ul_tmp; // TODO: fix elsewhere too CK_ULONG len = 0; - DBG(("For private key object %lu, get ", obj)); + DBG("For private key object %lu, get ", obj); switch (template->type) { case CKA_CLASS: - DBG(("CLASS")); + DBG("CLASS"); len = sizeof(CK_ULONG); ul_tmp = CKO_PRIVATE_KEY; data = (CK_BYTE_PTR) &ul_tmp; @@ -447,27 +447,27 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN")); + DBG("TOKEN"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].token; data = b_tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE")); + DBG("PRIVATE"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].private; data = b_tmp; break; case CKA_LABEL: - DBG(("LABEL")); + DBG("LABEL"); len = strlen(piv_objects[obj].label) + 1; data =(CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_KEY_TYPE: - DBG(("KEY TYPE")); + DBG("KEY TYPE"); len = sizeof(CK_ULONG); ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk if (ul_tmp == CKK_VENDOR_DEFINED) @@ -476,62 +476,62 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_SUBJECT: - DBG(("SUBJECT TODO")); // Default empty + DBG("SUBJECT TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_ID: - DBG(("ID")); + DBG("ID"); len = sizeof(CK_BYTE); ul_tmp = piv_objects[obj].sub_id; data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_SENSITIVE: - DBG(("SENSITIVE TODO")); // Default empty + DBG("SENSITIVE TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_DECRYPT: - DBG(("DECRYPT")); // Default empty + DBG("DECRYPT"); // Default empy len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].decrypt; data = b_tmp; break; case CKA_UNWRAP: - DBG(("UNWRAP")); // Default empty + DBG("UNWRAP"); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].unwrap; data = b_tmp; break; case CKA_SIGN: - DBG(("SIGN")); // Default empty + DBG("SIGN"); // Default empty len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].sign; data = b_tmp; break; case CKA_SIGN_RECOVER: - DBG(("SIGN RECOVER TODO")); // Default empty + DBG("SIGN RECOVER TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_DERIVE: - DBG(("DERIVE")); // Default false + DBG("DERIVE"); // Default false len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].derive; data = b_tmp; break; case CKA_START_DATE: - DBG(("START DATE TODO")); // Default empty + DBG("START DATE TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - DBG(("END DATE TODO")); // Default empty + DBG("END DATE TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_MODULUS: - DBG(("MODULUS")); + DBG("MODULUS"); len = sizeof(b_tmp); // Make sure that this is an RSA key @@ -547,7 +547,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_EC_POINT: - DBG(("EC_POINT")); + DBG("EC_POINT"); len = sizeof(b_tmp); // Make sure that this is an EC key @@ -564,7 +564,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_EC_PARAMS: // Here we want the curve parameters (DER encoded OID) - DBG(("EC_PARAMS")); + DBG("EC_PARAMS"); len = sizeof(b_tmp); // Make sure that this is an EC key @@ -581,7 +581,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_MODULUS_BITS: - DBG(("MODULUS BITS")); + DBG("MODULUS BITS"); len = sizeof(CK_ULONG); // Make sure that this is an RSA key @@ -598,7 +598,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_PUBLIC_EXPONENT: - DBG(("PUBLIC EXPONENT")); + DBG("PUBLIC EXPONENT"); len = sizeof(CK_ULONG); // Make sure that this is an RSA key @@ -627,21 +627,21 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* case CKA_VALUE_LEN: */ /* case CKA_EXTRACTABLE: */ case CKA_LOCAL: - DBG(("LOCAL TODO")); // Required + DBG("LOCAL TODO"); // Required return CKR_FUNCTION_FAILED; /* case CKA_NEVER_EXTRACTABLE: */ /*case CKA_ALWAYS_SENSITIVE:*/ case CKA_ALWAYS_AUTHENTICATE: - DBG(("ALWAYS AUTHENTICATE")); + DBG("ALWAYS AUTHENTICATE"); len = sizeof(CK_BBOOL); b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].always_auth; data = b_tmp; break; case CKA_MODIFIABLE: - DBG(("MODIFIABLE")); + DBG("MODIFIABLE"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].modifiable; data = b_tmp; @@ -649,7 +649,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /*case CKA_VENDOR_DEFINED:*/ default: - DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); // TODO: there are other parameters for public keys, plus there is more if the key is RSA + DBG("UNKNOWN ATTRIBUTE %lx", template[0].type); // TODO: there are other parameters for public keys, plus there is more if the key is RSA template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -677,11 +677,11 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE b_tmp[1024]; CK_ULONG ul_tmp; CK_ULONG len = 0; - DBG(("For public key object %lu, get ", obj)); + DBG("For public key object %lu, get ", obj); switch (template->type) { case CKA_CLASS: - DBG(("CLASS")); + DBG("CLASS"); len = sizeof(CK_ULONG); ul_tmp = CKO_PUBLIC_KEY; data = (CK_BYTE_PTR) &ul_tmp; @@ -689,27 +689,27 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_TOKEN: // Technically all these objects are token objects - DBG(("TOKEN")); + DBG("TOKEN"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].token; data = b_tmp; break; case CKA_PRIVATE: - DBG(("PRIVATE")); + DBG("PRIVATE"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].private; data = b_tmp; break; case CKA_LABEL: - DBG(("LABEL")); + DBG("LABEL"); len = strlen(piv_objects[obj].label) + 1; data = (CK_BYTE_PTR)piv_objects[obj].label; break; case CKA_KEY_TYPE: - DBG(("KEY TYPE")); + DBG("KEY TYPE"); len = sizeof(CK_ULONG); ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); if (ul_tmp == CKK_VENDOR_DEFINED) // This value is used as an error here @@ -718,54 +718,54 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_SUBJECT: - DBG(("SUBJECT TODO")); // Default empty + DBG("SUBJECT TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_ID: - DBG(("ID")); + DBG("ID"); len = sizeof(CK_BYTE); b_tmp[0] = piv_objects[obj].sub_id; data = b_tmp; break; case CKA_ENCRYPT: - DBG(("ENCRYPT")); + DBG("ENCRYPT"); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].encrypt; data = b_tmp; break; case CKA_VERIFY: // TODO: what about verify recover ? - DBG(("VERIFY")); + DBG("VERIFY"); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].verify; data = b_tmp; break; case CKA_WRAP: - DBG(("WRAP")); + DBG("WRAP"); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].wrap; data = b_tmp; break; case CKA_DERIVE: - DBG(("DERIVE")); + DBG("DERIVE"); len = sizeof(CK_BBOOL); b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].derive; data = b_tmp; break; case CKA_START_DATE: - DBG(("START DATE TODO")); // Default empty + DBG("START DATE TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_END_DATE: - DBG(("END DATE TODO")); // Default empty + DBG("END DATE TODO"); // Default empty return CKR_FUNCTION_FAILED; case CKA_EC_POINT: - DBG(("EC_POINT")); + DBG("EC_POINT"); len = sizeof(b_tmp); // Make sure that this is an EC key @@ -782,7 +782,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_EC_PARAMS: // Here we want the curve parameters (DER encoded OID) - DBG(("EC_PARAMS")); + DBG("EC_PARAMS"); len = sizeof(b_tmp); // Make sure that this is an EC key @@ -799,7 +799,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_MODULUS: - DBG(("MODULUS")); + DBG("MODULUS"); len = sizeof(b_tmp); // Make sure that this is an RSA key @@ -815,7 +815,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_MODULUS_BITS: - DBG(("MODULUS BITS")); + DBG("MODULUS BITS"); len = sizeof(CK_ULONG); // Make sure that this is an RSA key @@ -832,7 +832,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_PUBLIC_EXPONENT: - DBG(("PUBLIC EXPONENT")); + DBG("PUBLIC EXPONENT"); len = sizeof(CK_ULONG); // Make sure that this is an RSA key @@ -849,18 +849,18 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_LOCAL: - DBG(("LOCAL TODO")); // Required + DBG("LOCAL TODO"); // Required return CKR_FUNCTION_FAILED; case CKA_MODIFIABLE: - DBG(("MODIFIABLE")); + DBG("MODIFIABLE"); len = sizeof(CK_BBOOL); b_tmp[0] = piv_objects[obj].modifiable; data = b_tmp; break; default: - DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); // TODO: there are other parameters for public keys + DBG("UNKNOWN ATTRIBUTE %lx", template[0].type); // TODO: there are other parameters for public keys template->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -990,7 +990,7 @@ CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE) cert_ids[j++] = s->slot->token->objects[i]; - DBG(("Just to check: %lu %lu", j, n_certs)); + DBG("Just to check: %lu %lu", j, n_certs); return CKR_OK; } @@ -1066,7 +1066,7 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, break; default: - DBG(("Invalid %lx", templ[i].type)); + DBG("Invalid %lx", templ[i].type); return CKR_ATTRIBUTE_TYPE_INVALID; } } @@ -1139,7 +1139,7 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, break; default: - DBG(("Invalid %lx", templ[i].type)); + DBG("Invalid %lx", templ[i].type); return CKR_ATTRIBUTE_TYPE_INVALID; } } @@ -1254,7 +1254,7 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, break; default: - DBG(("Invalid %lx", templ[i].type)); + DBG("Invalid %lx", templ[i].type); return CKR_ATTRIBUTE_TYPE_INVALID; } } diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index cc2085a..9bd3883 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -468,7 +468,7 @@ CK_RV do_pkcs_1_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PT unsigned char buffer[512]; key_len /= 8; - DBG(("Apply padding to %lu bytes and get %lu\n", in_len, key_len)); + DBG("Apply padding to %lu bytes and get %lu\n", in_len, key_len); // TODO: rand must be seeded first (should be automatic) if (*out_len < key_len) @@ -508,7 +508,7 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, if (*out_len < (CK_ULONG)RSA_size(key)) return CKR_BUFFER_TOO_SMALL; - DBG(("Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key))); + DBG("Apply PSS padding to %lu bytes and get %d\n", in_len, RSA_size(key)); if (out != in) memcpy(out, in, in_len); diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index cb62e83..25db6d7 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -15,18 +15,18 @@ static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CH if (user == CKU_USER) { if (ykpiv_verify(state, (char *)pin, &tries) != YKPIV_OK) { - DBG(("Failed to login")); + DBG("Failed to login"); return CKR_PIN_INCORRECT; } } else if (user == CKU_SO) { if(ykpiv_hex_decode((char *)pin, pin_len, key, &key_len) != YKPIV_OK) { - DBG(("Failed decoding key")); + DBG("Failed decoding key"); return CKR_FUNCTION_FAILED; } if(ykpiv_authenticate(state, key) != YKPIV_OK) { - DBG(("Failed to authenticate")); + DBG("Failed to authenticate"); return CKR_PIN_INCORRECT; } } diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 439b425..35b27ea 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -57,19 +57,19 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_CRYPTOKI_ALREADY_INITIALIZED; if (ykpiv_init(&piv_state, YKCS11_DBG) != YKPIV_OK) { - DBG(("Unable to initialize libykpiv")); + DBG("Unable to initialize libykpiv"); return CKR_FUNCTION_FAILED; } if (ykpiv_list_readers(piv_state, (char*)readers, &len) != YKPIV_OK) { - DBG(("Unable to list readers")); + DBG("Unable to list readers"); return CKR_FUNCTION_FAILED; } if (parse_readers(piv_state, readers, len, slots, &n_slots, &n_slots_with_token) != CKR_OK) return CKR_FUNCTION_FAILED; - DBG(("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token)); + DBG("Found %lu slot(s) of which %lu tokenless/unsupported", n_slots, n_slots - n_slots_with_token); find_obj.active = CK_FALSE; // TODO: FILL OUT INIT ARGS; @@ -86,12 +86,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( CK_ULONG i; if (pReserved != NULL_PTR) { - DBG(("Finalized called with pReserved != NULL")); + DBG("Finalized called with pReserved != NULL"); return CKR_ARGUMENTS_BAD; } if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } @@ -135,7 +135,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)( { DIN; if(ppFunctionList == NULL_PTR) { - DBG(("GetFunctionList called with ppFunctionList = NULL")); + DBG("GetFunctionList called with ppFunctionList = NULL"); return CKR_ARGUMENTS_BAD; } *ppFunctionList = &function_list; @@ -157,7 +157,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( int j; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } @@ -175,7 +175,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( } if ((tokenPresent && *pulCount < n_slots_with_token) || (!tokenPresent && *pulCount < n_slots)) { - DBG(("Buffer too small: needed %lu, provided %lu", n_slots, *pulCount)); + DBG("Buffer too small: needed %lu, provided %lu", n_slots, *pulCount); return CKR_BUFFER_TOO_SMALL; } @@ -188,8 +188,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( pSlotList[i] = i; } - DBG(("token present is %d", tokenPresent)); - DBG(("number of slot(s) is %lu", *pulCount)); + DBG("token present is %d", tokenPresent); + DBG("number of slot(s) is %lu", *pulCount); DOUT; return CKR_OK; @@ -203,12 +203,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu", slotID)); + DBG("Invalid slot ID %lu", slotID); return CKR_SLOT_ID_INVALID; } @@ -226,27 +226,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu", slotID)); + DBG("Invalid slot ID %lu", slotID); return CKR_SLOT_ID_INVALID; } if (slots[slotID].vid == UNKNOWN) { - DBG(("No support for slot %lu", slotID)); + DBG("No support for slot %lu", slotID); return CKR_SLOT_ID_INVALID; } if (!has_token(slots + slotID)) { - DBG(("Slot %lu has no token inserted", slotID)); + DBG("Slot %lu has no token inserted", slotID); return CKR_TOKEN_NOT_PRESENT; } if (slots[slotID].token->vid == UNKNOWN) { - DBG(("No support for token in slot %lu", slotID)); + DBG("No support for token in slot %lu", slotID); return CKR_TOKEN_NOT_RECOGNIZED; } @@ -275,7 +275,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -291,22 +291,22 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( CK_ULONG count; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu", slotID)); + DBG("Invalid slot ID %lu", slotID); return CKR_SLOT_ID_INVALID; } if (pulCount == NULL_PTR) { - DBG(("Wrong/Missing parameter")); + DBG("Wrong/Missing parameter"); return CKR_ARGUMENTS_BAD; } if (slots[slotID].vid == UNKNOWN) { - DBG(("Slot %lu is tokenless/unsupported", slotID)); + DBG("Slot %lu is tokenless/unsupported", slotID); return CKR_SLOT_ID_INVALID; } @@ -319,18 +319,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( if (pMechanismList == NULL_PTR) { *pulCount = count; - DBG(("Found %lu mechanisms", *pulCount)); + DBG("Found %lu mechanisms", *pulCount); DOUT; return CKR_OK; } if (*pulCount < count) { - DBG(("Buffer too small: needed %lu, provided %lu", count, *pulCount)); + DBG("Buffer too small: needed %lu, provided %lu", count, *pulCount); return CKR_BUFFER_TOO_SMALL; } if (token.get_token_mechanism_list(pMechanismList, *pulCount) != CKR_OK) { - DBG(("Unable to retrieve mechanism list")); + DBG("Unable to retrieve mechanism list"); return CKR_FUNCTION_FAILED; } @@ -348,29 +348,29 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( token_vendor_t token; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu", slotID)); + DBG("Invalid slot ID %lu", slotID); return CKR_SLOT_ID_INVALID; } if (pInfo == NULL_PTR) { - DBG(("Wrong/Missing parameter")); + DBG("Wrong/Missing parameter"); return CKR_ARGUMENTS_BAD; } if (slots[slotID].vid == UNKNOWN) { - DBG(("Slot %lu is tokenless/unsupported", slotID)); + DBG("Slot %lu is tokenless/unsupported", slotID); return CKR_SLOT_ID_INVALID; } token = get_token_vendor(slots[slotID].vid); if (token.get_token_mechanism_info(type, pInfo) != CKR_OK) { - DBG(("Unable to retrieve mechanism information")); + DBG("Unable to retrieve mechanism information"); return CKR_MECHANISM_INVALID; } @@ -386,7 +386,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_InitToken)( ) { DIN; - DBG(("Token initialization unsupported")); + DBG("Token initialization unsupported"); DOUT; return CKR_FUNCTION_FAILED; } @@ -398,7 +398,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)( ) { DIN; - DBG(("PIN initialization unsupported")); + DBG("PIN initialization unsupported"); DOUT; return CKR_FUNCTION_FAILED; } @@ -412,7 +412,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -435,48 +435,48 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( CK_ULONG cert_len = sizeof(cert_data); if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= n_slots) { - DBG(("Invalid slot ID %lu", slotID)); + DBG("Invalid slot ID %lu", slotID); return CKR_SLOT_ID_INVALID; } if (phSession == NULL_PTR) { - DBG(("Wrong/Missing parameter")); + DBG("Wrong/Missing parameter"); return CKR_ARGUMENTS_BAD; } if (slots[slotID].vid == UNKNOWN) { - DBG(("No support for slot %lu", slotID)); + DBG("No support for slot %lu", slotID); return CKR_TOKEN_NOT_RECOGNIZED; } if (slots[slotID].token->vid == UNKNOWN) { - DBG(("No support for token in slot %lu", slotID)); + DBG("No support for token in slot %lu", slotID); return CKR_TOKEN_NOT_RECOGNIZED; } if (!has_token(slots + slotID)) { - DBG(("Slot %lu has no token inserted", slotID)); + DBG("Slot %lu has no token inserted", slotID); return CKR_TOKEN_NOT_PRESENT; } if (session.handle != CK_INVALID_HANDLE) { - DBG(("A session with this or another token already exists")); + DBG("A session with this or another token already exists"); return CKR_SESSION_COUNT; } if ((flags & CKF_SERIAL_SESSION) == 0) { - DBG(("Open session called without CKF_SERIAL_SESSION set")); // Reuired by specs + DBG("Open session called without CKF_SERIAL_SESSION set"); // Reuired by spes return CKR_SESSION_PARALLEL_NOT_SUPPORTED; } // Connect to the slot if(ykpiv_connect(piv_state, (char *)slots[slotID].info.slotDescription) != YKPIV_OK) { - DBG(("Unable to connect to reader")); + DBG("Unable to connect to reader"); return CKR_FUNCTION_FAILED; } @@ -504,35 +504,35 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( // Get the number of token objects rv = token.get_token_objects_num(piv_state, &session.slot->token->n_objects, &session.slot->token->n_certs); if (rv != CKR_OK) { - DBG(("Unable to retrieve number of token objects")); + DBG("Unable to retrieve number of token objects"); return rv; } // Get memory for the objects session.slot->token->objects = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_objects); if (session.slot->token->objects == NULL) { - DBG(("Unable to allocate memory for token object ids")); + DBG("Unable to allocate memory for token object ids"); return CKR_HOST_MEMORY; } // Get memory for the certificates cert_ids = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_certs); if (cert_ids == NULL) { - DBG(("Unable to allocate memory for token certificate ids")); + DBG("Unable to allocate memory for token certificate ids"); return CKR_HOST_MEMORY; } // Save a list of all the available objects in the token rv = token.get_token_object_list(piv_state, session.slot->token->objects, session.slot->token->n_objects); if (rv != CKR_OK) { - DBG(("Unable to retrieve token objects")); + DBG("Unable to retrieve token objects"); goto failure; } // Get a list of object ids for available certificates object from the session rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); if (rv != CKR_OK) { - DBG(("Unable to retrieve certificate ids from the session")); + DBG("Unable to retrieve certificate ids from the session"); goto failure; } @@ -541,13 +541,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( cert_len = sizeof(cert_data); rv = token.get_token_raw_certificate(piv_state, cert_ids[i], cert_data, &cert_len); if (rv != CKR_OK) { - DBG(("Unable to get certificate data from token")); + DBG("Unable to get certificate data from token"); goto failure; } rv = store_cert(cert_ids[i], cert_data, cert_len); if (rv != CKR_OK) { - DBG(("Unable to store certificate data")); + DBG("Unable to store certificate data"); goto failure; } } @@ -585,17 +585,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle == CK_INVALID_HANDLE) { - DBG(("Trying to close a session, but there is no existing one")); + DBG("Trying to close a session, but there is no existing one"); return CKR_SESSION_CLOSED; } if (hSession != YKCS11_SESSION_ID) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } @@ -619,12 +619,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( CK_RV rv; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.slot != slots + slotID) { - DBG(("Invalid slot ID %lu", slotID)); + DBG("Invalid slot ID %lu", slotID); return CKR_SLOT_ID_INVALID; } @@ -642,17 +642,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (pInfo == NULL) { - DBG(("Wrong/Missing parameter")); + DBG("Wrong/Missing parameter"); return CKR_ARGUMENTS_BAD; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } @@ -669,7 +669,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -683,7 +683,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -700,7 +700,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( token_vendor_t token; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } @@ -709,20 +709,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( userType != CKU_CONTEXT_SPECIFIC) return CKR_USER_TYPE_INVALID; - DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); + DBG("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen); if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? - DBG(("Tried to log-in to a read-only session")); + DBG("Tried to log-in to a read-only session"); return CKR_SESSION_READ_ONLY_EXISTS; } @@ -734,18 +734,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_ARGUMENTS_BAD; /*if (session.info.state == CKS_RW_USER_FUNCTIONS) { - DBG(("This user type is already logged in")); + DBG("This user type is already logged in"); return CKR_USER_ALREADY_LOGGED_IN; }*/ //TODO: FIx to allow multiple login. Decide on context specific. if (session.info.state == CKS_RW_SO_FUNCTIONS) { - DBG(("A different uyser type is already logged in")); + DBG("A different uyser type is already logged in"); return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } rv = token.token_login(piv_state, CKU_USER, pPin, ulPinLen); if (rv != CKR_OK) { - DBG(("Unable to login as regular user")); + DBG("Unable to login as regular user"); return rv; } @@ -768,7 +768,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( rv = token.token_login(piv_state, CKU_SO, pPin, ulPinLen); if (rv != CKR_OK) { - DBG(("Unable to login as SO")); + DBG("Unable to login as SO"); return rv; } @@ -777,7 +777,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( case CKU_CONTEXT_SPECIFIC: if (op_info.type == YKCS11_NOOP) { - DBG(("No operation in progress. Context specific user is forbidden.")); + DBG("No operation in progress. Context specific user is forbidden."); return CKR_USER_TYPE_INVALID; } if (op_info.type == YKCS11_SIGN) { @@ -790,7 +790,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( return CKR_USER_TYPE_INVALID; } - DBG(("Successfully logged in")); + DBG("Successfully logged in"); DOUT; return CKR_OK; @@ -803,17 +803,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_Logout)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } @@ -862,28 +862,28 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } if (session.info.state != CKS_RW_SO_FUNCTIONS) { - DBG(("Authentication required to import objects")); + DBG("Authentication required to import objects"); return CKR_SESSION_READ_ONLY; } if (pTemplate == NULL_PTR || phObject == NULL_PTR) { - DBG(("Wrong/Missing parameter")); + DBG("Wrong/Missing parameter"); return CKR_ARGUMENTS_BAD; } @@ -895,14 +895,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( // Can only import certificates and private keys if (*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_CERTIFICATE && *((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_PRIVATE_KEY) { - DBG(("Unsupported class %lu", class)); + DBG("Unsupported class %lu", class); return CKR_ATTRIBUTE_VALUE_INVALID; } } } if (class == CKO_VENDOR_DEFINED) { - DBG(("Object class must be specified")); + DBG("Object class must be specified"); return CKR_TEMPLATE_INCOMPLETE; } @@ -910,20 +910,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( switch (class) { case CKO_CERTIFICATE: - DBG(("Importing certificate")); + DBG("Importing certificate"); rv = check_create_cert(pTemplate, ulCount, &id, &value, &value_len); if (rv != CKR_OK) { - DBG(("Certificate template not valid")); + DBG("Certificate template not valid"); return rv; } - DBG(("Certificate id is %u", id)); + DBG("Certificate id is %u", id); object = PIV_CERT_OBJ_X509_PIV_AUTH + id; rv = token.token_import_cert(piv_state, piv_2_ykpiv(object), value); // TODO: make function to get cert id if (rv != CKR_OK) { - DBG(("Unable to import certificate")); + DBG("Unable to import certificate"); return rv; } @@ -947,7 +947,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); if (obj_ptr == NULL) { - DBG(("Unable to store new item in the session")); + DBG("Unable to store new item in the session"); return CKR_HOST_MEMORY; } session.slot->token->objects = obj_ptr; @@ -960,14 +960,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( rv = store_cert(cert_id, value, value_len); if (rv != CKR_OK) { - DBG(("Unable to store certificate data")); + DBG("Unable to store certificate data"); return CKR_FUNCTION_FAILED; } break; case CKO_PRIVATE_KEY: - DBG(("Importing private key")); + DBG("Importing private key"); // Try to parse the key as EC is_rsa = CK_FALSE; @@ -977,39 +977,39 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( is_rsa = CK_TRUE; rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len, &vendor_defined); if (rv != CKR_OK) { - DBG(("Private key template not valid")); + DBG("Private key template not valid"); return rv; } } - DBG(("Key id is %u", id)); + DBG("Key id is %u", id); object = PIV_PVTK_OBJ_PIV_AUTH + id; if (is_rsa == CK_TRUE) { - DBG(("Key is RSA")); + DBG("Key is RSA"); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv, NULL, value_len, vendor_defined); if (rv != CKR_OK) { - DBG(("Unable to import RSA private key")); + DBG("Unable to import RSA private key"); return rv; } } else { - DBG(("Key is ECDSA")); + DBG("Key is ECDSA"); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL, value, value_len, vendor_defined); if (rv != CKR_OK) { - DBG(("Unable to import ECDSA private key")); + DBG("Unable to import ECDSA private key"); return rv; } } break; default: - DBG(("Unknown object type")); + DBG("Unknown object type"); return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -1026,7 +1026,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1048,33 +1048,33 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( CK_ULONG pubk_id; piv_obj_id_t *obj_ptr; - DBG(("Deleting object %lu", hObject)); + DBG("Deleting object %lu", hObject); if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } // Only certificates can be deleted // SO must be logged in if (session.info.state != CKS_RW_SO_FUNCTIONS) { - DBG(("Unable to delete objects, SO must be logged in")); + DBG("Unable to delete objects, SO must be logged in"); return CKR_ACTION_PROHIBITED; } rv = check_delete_cert(hObject, &id); if (rv != CKR_OK) { - DBG(("Object %lu can not be deleted", hObject)); + DBG("Object %lu can not be deleted", hObject); return rv; } @@ -1082,7 +1082,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( rv = token.token_delete_cert(piv_state, piv_2_ykpiv(hObject)); if (rv != CKR_OK) { - DBG(("Unable to delete object %lu", hObject)); + DBG("Unable to delete object %lu", hObject); return rv; } @@ -1095,7 +1095,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( obj_ptr = malloc((session.slot->token->n_objects - 3) * sizeof(piv_obj_id_t)); if (obj_ptr == NULL) { - DBG(("Unable to allocate memory")); + DBG("Unable to allocate memory"); return CKR_HOST_MEMORY; } @@ -1114,7 +1114,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( rv = delete_cert(cert_id); if (rv != CKR_OK) { - DBG(("Unable to delete certificate data")); + DBG("Unable to delete certificate data"); return CKR_FUNCTION_FAILED; } @@ -1135,7 +1135,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1152,17 +1152,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( CK_RV rv, rv_final; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } @@ -1176,7 +1176,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( // TODO: this function has some complex cases for return vlaue. Make sure to check them. if (rv != CKR_OK) { - DBG(("Unable to get attribute 0x%lx of object %lu", (pTemplate + i)->type, hObject)); + DBG("Unable to get attribute 0x%lx of object %lu", (pTemplate + i)->type, hObject); rv_final = rv; } } @@ -1193,7 +1193,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1212,17 +1212,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } @@ -1238,22 +1238,22 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( // Check if we should remove private objects if (session.info.state == CKS_RO_PUBLIC_SESSION || session.info.state == CKS_RW_PUBLIC_SESSION) { - DBG(("Removing private objects because state is %lu", session.info.state)); + DBG("Removing private objects because state is %lu", session.info.state); private = CK_FALSE; } else { - DBG(("Keeping private objects")); + DBG("Keeping private objects"); private = CK_TRUE; } find_obj.objects = malloc(sizeof(piv_obj_id_t) * find_obj.num); if (find_obj.objects == NULL) { - DBG(("Unable to allocate memory for finding objects")); + DBG("Unable to allocate memory for finding objects"); return CKR_HOST_MEMORY; } memcpy(find_obj.objects, session.slot->token->objects, sizeof(piv_obj_id_t) * find_obj.num); - DBG(("Initialized search with %lu parameters", ulCount)); + DBG("Initialized search with %lu parameters", ulCount); // Match parameters total = find_obj.num; @@ -1265,27 +1265,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( // Strip away private objects if needed if (private == CK_FALSE) if (is_private_object(&session, find_obj.objects[i]) == CK_TRUE) { - DBG(("Stripping away private object %u", find_obj.objects[i])); + DBG("Stripping away private object %u", find_obj.objects[i]); find_obj.objects[i] = OBJECT_INVALID; total--; continue; } for (j = 0; j < ulCount; j++) { - DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", j, pTemplate[j].type, *((CK_ULONG_PTR)pTemplate[j].pValue), pTemplate[j].ulValueLen)); + DBG("Parameter %lu\nType: %lu Value: %lu Len: %lu", j, pTemplate[j].type, *((CK_ULONG_PTR)pTemplate[j].pValue), pTemplate[j].ulValueLen); if (attribute_match(&session, find_obj.objects[i], pTemplate + j) == CK_FALSE) { - DBG(("Removing object %u from the list", find_obj.objects[i])); + DBG("Removing object %u from the list", find_obj.objects[i]); find_obj.objects[i] = OBJECT_INVALID; // Object not matching, mark it total--; break; } else - DBG(("Keeping object %u in the list", find_obj.objects[i])); + DBG("Keeping object %u in the list", find_obj.objects[i]); } } - DBG(("%lu object(s) left after attribute matching", total)); + DBG("%lu object(s) left after attribute matching", total); find_obj.active = CK_TRUE; @@ -1303,17 +1303,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } @@ -1325,7 +1325,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( if (find_obj.active != CK_TRUE) return CKR_OPERATION_NOT_INITIALIZED; - DBG(("Can return %lu object(s)", ulMaxObjectCount)); + DBG("Can return %lu object(s)", ulMaxObjectCount); // Return the next object, if any while(find_obj.idx < find_obj.num && @@ -1341,7 +1341,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( *phObject = find_obj.objects[find_obj.idx++]; *pulObjectCount = 1; - DBG(("Returning object %lu", *phObject)); + DBG("Returning object %lu", *phObject); return CKR_OK; } @@ -1353,17 +1353,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } @@ -1386,7 +1386,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1400,7 +1400,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1414,7 +1414,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1426,7 +1426,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1438,7 +1438,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1452,7 +1452,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1466,7 +1466,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1478,7 +1478,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1491,35 +1491,35 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)( DIN; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } if (op_info.type != YKCS11_NOOP) { - DBG(("Other operation in process")); + DBG("Other operation in process"); return CKR_OPERATION_ACTIVE; } if (pMechanism == NULL_PTR) { - DBG(("Wrong/Missing parameter")); + DBG("Wrong/Missing parameter"); return CKR_ARGUMENTS_BAD; } - DBG(("Trying to hash some data with mechanism %lu", pMechanism->mechanism)); + DBG("Trying to hash some data with mechanism %lu", pMechanism->mechanism); // Check if mechanism is supported if (check_hash_mechanism(&session, pMechanism) != CKR_OK) { - DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism)); + DBG("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism); return CKR_MECHANISM_INVALID; } memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); @@ -1539,7 +1539,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Digest)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1551,7 +1551,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1562,7 +1562,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1574,7 +1574,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1597,22 +1597,22 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( }; if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } if (op_info.type != YKCS11_NOOP) { - DBG(("Other operation in process")); + DBG("Other operation in process"); return CKR_OPERATION_ACTIVE; } @@ -1620,28 +1620,28 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( hKey == NULL_PTR) return CKR_ARGUMENTS_BAD; - DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey)); + DBG("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey); // Check if mechanism is supported if (check_sign_mechanism(&session, pMechanism) != CKR_OK) { - DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism)); + DBG("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism); return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that } memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); // Get key algorithm if (get_attribute(&session, hKey, template) != CKR_OK) { - DBG(("Unable to get key type")); + DBG("Unable to get key type"); return CKR_KEY_HANDLE_INVALID; } - DBG(("Key type is %lu\n", type)); + DBG("Key type is %lu\n", type); // Get key length and algorithm type if (type == CKK_RSA) { // RSA key if (get_attribute(&session, hKey, template + 1) != CKR_OK) { - DBG(("Unable to get key length")); + DBG("Unable to get key length"); return CKR_KEY_HANDLE_INVALID; } @@ -1662,7 +1662,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( template[2].ulValueLen = key_len; if (get_attribute(&session, hKey, template + 2) != CKR_OK) { - DBG(("Unable to get public key")); + DBG("Unable to get public key"); return CKR_KEY_HANDLE_INVALID; } @@ -1675,7 +1675,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( else { // ECDSA key if (get_attribute(&session, hKey, template + 3) != CKR_OK) { - DBG(("Unable to get key length")); + DBG("Unable to get key length"); return CKR_KEY_HANDLE_INVALID; } @@ -1690,19 +1690,19 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( op_info.op.sign.algo = YKPIV_ALGO_ECCP384;*/ // TODO: add support for P384 } - DBG(("Key length is %lu bit", op_info.op.sign.key_len)); + DBG("Key length is %lu bit", op_info.op.sign.key_len); op_info.op.sign.key_id = piv_2_ykpiv(hKey); if (op_info.op.sign.key_id == 0) { - DBG(("Incorrect key %lu", hKey)); + DBG("Incorrect key %lu", hKey); return CKR_KEY_HANDLE_INVALID; } - DBG(("Algorithm is %d", op_info.op.sign.algo)); + DBG("Algorithm is %d", op_info.op.sign.algo); // Make sure that both mechanism and key have the same algorithm if ((is_RSA_mechanism(pMechanism->mechanism) && op_info.op.sign.algo == YKPIV_ALGO_ECCP256) || (!is_RSA_mechanism(pMechanism->mechanism) && (op_info.op.sign.algo != YKPIV_ALGO_ECCP256))) { - DBG(("Key and mechanism algorithm do not match")); + DBG("Key and mechanism algorithm do not match"); return CKR_ARGUMENTS_BAD; } @@ -1711,7 +1711,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( // TODO: check mechanism parameters and key length and key supported parameters if (apply_sign_mechanism_init(&op_info) != CKR_OK) { - DBG(("Unable to initialize signing operation")); + DBG("Unable to initialize signing operation"); return CKR_FUNCTION_FAILED; } @@ -1733,32 +1733,32 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( CK_RV rv; if (op_info.type != YKCS11_SIGN) { - DBG(("Signature operation not initialized")); + DBG("Signature operation not initialized"); rv = CKR_OPERATION_NOT_INITIALIZED; goto sign_out; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); rv = CKR_SESSION_CLOSED; goto sign_out; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); rv = CKR_SESSION_HANDLE_INVALID; goto sign_out; } if (op_info.type != YKCS11_SIGN) { - DBG(("Operation not initialized")); + DBG("Operation not initialized"); rv = CKR_OPERATION_NOT_INITIALIZED; goto sign_out; } if (session.info.state == CKS_RO_PUBLIC_SESSION || session.info.state == CKS_RW_PUBLIC_SESSION) { - DBG(("User is not logged in")); + DBG("User is not logged in"); rv = CKR_USER_NOT_LOGGED_IN; goto sign_out; } @@ -1766,18 +1766,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (pSignature == NULL_PTR) { // Just return the size of the signature *pulSignatureLen = op_info.op.sign.key_len / 8 * 2 + 32; // Approximate the size of the signature. Specs agree with this. - DBG(("The size of the signature will be %lu", *pulSignatureLen)); + DBG("The size of the signature will be %lu", *pulSignatureLen); DOUT; return CKR_OK; } - DBG(("Sending %lu bytes to sign", ulDataLen)); + DBG("Sending %lu bytes to sign", ulDataLen); dump_hex(pData, ulDataLen, stderr, CK_TRUE); if (is_hashed_mechanism(op_info.mechanism.mechanism) == CK_TRUE) { if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { - DBG(("Unable to perform signing operation step")); + DBG("Unable to perform signing operation step"); rv = CKR_FUNCTION_FAILED; // TODO: every error in here must stop and clear the signing operation goto sign_out; } @@ -1786,7 +1786,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (is_RSA_mechanism(op_info.mechanism.mechanism)) { // RSA_X_509 if (ulDataLen > (op_info.op.sign.key_len / 8)) { - DBG(("Data must be shorter than key length (%lu bits)", op_info.op.sign.key_len)); + DBG("Data must be shorter than key length (%lu bits)", op_info.op.sign.key_len); rv = CKR_FUNCTION_FAILED; goto sign_out; } @@ -1795,7 +1795,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( // ECDSA if (ulDataLen > 128) { // Specs say ECDSA only supports 1024 bit - DBG(("Maximum data length for ECDSA is 128 bytes")); + DBG("Maximum data length for ECDSA is 128 bytes"); rv = CKR_FUNCTION_FAILED; goto sign_out; } @@ -1806,13 +1806,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( } if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) { - DBG(("Unable to finalize signing operation")); + DBG("Unable to finalize signing operation"); rv = CKR_FUNCTION_FAILED; goto sign_out; } - DBG(("Using key %lx", op_info.op.sign.key_id)); - DBG(("After padding and transformation there are %lu bytes", op_info.buf_len)); + DBG("Using key %lx", op_info.op.sign.key_id); + DBG("After padding and transformation there are %lu bytes", op_info.buf_len); dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE); *pulSignatureLen = sizeof(op_info.buf); @@ -1820,18 +1820,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( piv_rv = ykpiv_sign_data(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id); if (piv_rv != YKPIV_OK) { if (piv_rv == YKPIV_AUTHENTICATION_ERROR) { - DBG(("Operation requires authentication or touch")); + DBG("Operation requires authentication or touch"); rv = CKR_USER_NOT_LOGGED_IN; goto sign_out; } else { - DBG(("Sign error, %s", ykpiv_strerror(piv_rv))); + DBG("Sign error, %s", ykpiv_strerror(piv_rv)); rv = CKR_FUNCTION_FAILED; goto sign_out; } } - DBG(("Got %lu bytes back", *pulSignatureLen)); + DBG("Got %lu bytes back", *pulSignatureLen); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); if (!is_RSA_mechanism(op_info.mechanism.mechanism)) { @@ -1839,7 +1839,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( // as required by the specs strip_DER_encoding_from_ECSIG(pSignature, pulSignatureLen); - DBG(("After removing DER encoding %lu", *pulSignatureLen)); + DBG("After removing DER encoding %lu", *pulSignatureLen); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); } @@ -1862,7 +1862,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1874,7 +1874,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1886,7 +1886,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1900,7 +1900,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1912,7 +1912,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1926,7 +1926,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Verify)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1938,7 +1938,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1950,7 +1950,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1962,7 +1962,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1976,7 +1976,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -1990,7 +1990,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2004,7 +2004,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2018,7 +2018,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2032,7 +2032,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2046,7 +2046,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2077,27 +2077,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( if (piv_state == NULL) { - DBG(("libykpiv is not initialized or already finalized")); + DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (session.handle != YKCS11_SESSION_ID) { - DBG(("Session is not open")); + DBG("Session is not open"); return CKR_SESSION_CLOSED; } if (hSession != session.handle) { - DBG(("Unknown session %lu", hSession)); + DBG("Unknown session %lu", hSession); return CKR_SESSION_HANDLE_INVALID; } if (session.info.state != CKS_RW_SO_FUNCTIONS) { - DBG(("Authentication required to generate keys")); + DBG("Authentication required to generate keys"); return CKR_SESSION_READ_ONLY; } if (op_info.type != YKCS11_NOOP) { - DBG(("Other operation in process")); + DBG("Other operation in process"); return CKR_OPERATION_ACTIVE; } @@ -2106,17 +2106,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( pPrivateKeyTemplate == NULL_PTR || phPublicKey == NULL_PTR || phPrivateKey == NULL_PTR) { - DBG(("Wrong/Missing parameter")); + DBG("Wrong/Missing parameter"); return CKR_ARGUMENTS_BAD; } - DBG(("Trying to generate a key pair with mechanism %lx", pMechanism->mechanism)); + DBG("Trying to generate a key pair with mechanism %lx", pMechanism->mechanism); - DBG(("Found %lu attributes for the public key and %lu attributes for the private key", ulPublicKeyAttributeCount, ulPrivateKeyAttributeCount)); + DBG("Found %lu attributes for the public key and %lu attributes for the private key", ulPublicKeyAttributeCount, ulPrivateKeyAttributeCount); // Check if mechanism is supported if ((rv = check_generation_mechanism(&session, pMechanism)) != CKR_OK) { - DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism)); + DBG("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism); return rv; } memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); @@ -2127,37 +2127,37 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( // Check the template for the public key if ((rv = check_pubkey_template(&op_info, pPublicKeyTemplate, ulPublicKeyAttributeCount)) != CKR_OK) { - DBG(("Invalid public key template")); + DBG("Invalid public key template"); return rv; } // Check the template for the private key if ((rv = check_pvtkey_template(&op_info, pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) != CKR_OK) { - DBG(("Invalid private key template")); + DBG("Invalid private key template"); return rv; } if (op_info.op.gen.key_len == 0) { - DBG(("Key length not specified")); + DBG("Key length not specified"); return CKR_TEMPLATE_INCOMPLETE; } if (op_info.op.gen.key_id == 0) { - DBG(("Key id not specified")); + DBG("Key id not specified"); return CKR_TEMPLATE_INCOMPLETE; } if (op_info.op.gen.rsa) { - DBG(("Generating %lu bit RSA key in object %u", op_info.op.gen.key_len, op_info.op.gen.key_id)); + DBG("Generating %lu bit RSA key in object %u", op_info.op.gen.key_len, op_info.op.gen.key_id); } else { - DBG(("Generating %lu bit EC key in object %u", op_info.op.gen.key_len, op_info.op.gen.key_id)); + DBG("Generating %lu bit EC key in object %u", op_info.op.gen.key_len, op_info.op.gen.key_id); } token = get_token_vendor(session.slot->token->vid); if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len, op_info.op.gen.vendor_defined)) != CKR_OK) { - DBG(("Unable to generate key pair")); + DBG("Unable to generate key pair"); return rv; } @@ -2182,7 +2182,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); if (obj_ptr == NULL) { - DBG(("Unable to store new item in the session")); + DBG("Unable to store new item in the session"); return CKR_HOST_MEMORY; } session.slot->token->objects = obj_ptr; @@ -2197,13 +2197,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( cert_len = sizeof(cert_data); rv = token.get_token_raw_certificate(piv_state, cert_id, cert_data, &cert_len); if (rv != CKR_OK) { - DBG(("Unable to get certificate data from token")); + DBG("Unable to get certificate data from token"); return CKR_FUNCTION_FAILED; } rv = store_cert(cert_id, cert_data, cert_len); if (rv != CKR_OK) { - DBG(("Unable to store certificate data")); + DBG("Unable to store certificate data"); return CKR_FUNCTION_FAILED; } @@ -2224,7 +2224,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2241,7 +2241,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2256,7 +2256,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2270,7 +2270,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2282,7 +2282,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2292,7 +2292,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } @@ -2302,7 +2302,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)( ) { DIN; - DBG(("TODO!!!")); + DBG("TODO!!!"); DOUT; return CKR_OK; } diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index 11a8897..4245ba7 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -247,7 +247,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_PIV_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_PIV_AUTH; n_cert++; - DBG(("Found AUTH cert (9a)")); + DBG("Found AUTH cert (9a)"); } buf_len = sizeof(buf); @@ -256,7 +256,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_CARD_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_CARD_AUTH; n_cert++; - DBG(("Found CARD AUTH cert (9e)")); + DBG("Found CARD AUTH cert (9e)"); } buf_len = sizeof(buf); @@ -265,7 +265,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_DS; pubkeys[n_cert] = PIV_PUBK_OBJ_DS; n_cert++; - DBG(("Found SIGNATURE cert (9c)")); + DBG("Found SIGNATURE cert (9c)"); } buf_len = sizeof(buf); @@ -274,10 +274,10 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, pvtkeys[n_cert] = PIV_PVTK_OBJ_KM; pubkeys[n_cert] = PIV_PUBK_OBJ_KM; n_cert++; - DBG(("Found KMK cert (9d)")); + DBG("Found KMK cert (9d)"); } - DBG(("The total number of objects for this token is %lu", (n_cert * 3) + token_objects_num)); + DBG("The total number of objects for this token is %lu", (n_cert * 3) + token_objects_num); if (num_only == CK_TRUE) { // We just want the number of objects From 69184eeb86efe78fa84a4dc36503ba2690a4cde6 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 16:46:54 +0100 Subject: [PATCH 122/134] YKCS11: remove more messsages --- ykcs11/objects.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index d2c07a4..94fbd64 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -990,8 +990,6 @@ CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE) cert_ids[j++] = s->slot->token->objects[i]; - DBG("Just to check: %lu %lu", j, n_certs); - return CKR_OK; } From 90acdad4819409fad15e975d7bdca7fd2dea6bfa Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 16:48:19 +0100 Subject: [PATCH 123/134] YKCS11: makde DBG variadic in every case. --- ykcs11/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykcs11/debug.h b/ykcs11/debug.h index 1848af6..84ab9ce 100644 --- a/ykcs11/debug.h +++ b/ykcs11/debug.h @@ -14,7 +14,7 @@ #include #define DBG(x...) D(x); #else -#define DBG(x) +#define DBG(x...) #endif #if YKCS11_DINOUT From 79e651fe58ac68ce2c2b9731e5e9bdc63bdf308b Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 17:05:09 +0100 Subject: [PATCH 124/134] YKCS11: initialize more. --- ykcs11/objects.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 94fbd64..e0a4214 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1084,8 +1084,8 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BBOOL has_value = CK_FALSE; CK_BBOOL has_params = CK_FALSE; - CK_BYTE_PTR ec_params; - CK_ULONG ec_params_len; + CK_BYTE_PTR ec_params = NULL; + CK_ULONG ec_params_len = 0; *vendor_defined = 0; @@ -1168,11 +1168,11 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BBOOL has_dp = CK_FALSE; CK_BBOOL has_dq = CK_FALSE; CK_BBOOL has_qinv = CK_FALSE; - CK_ULONG p_len; - CK_ULONG q_len; - CK_ULONG dp_len; - CK_ULONG dq_len; - CK_ULONG qinv_len; + CK_ULONG p_len = 0; + CK_ULONG q_len = 0; + CK_ULONG dp_len = 0; + CK_ULONG dq_len = 0; + CK_ULONG qinv_len = 0; *vendor_defined = 0; From b7be3be4b447c297e817c2b9e59544e1f35f4ae1 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 17:14:04 +0100 Subject: [PATCH 125/134] YKCS11: add check on buffer length. --- ykcs11/objects.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index e0a4214..7b52286 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -985,6 +985,9 @@ CK_BBOOL is_private_object(ykcs11_session_t *s, CK_OBJECT_HANDLE obj) { CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs) { CK_ULONG i, j; + if (n_certs > s->slot->token->n_objects) + return CKR_BUFFER_TOO_SMALL; + j = 0; for (i = 0; i < s->slot->token->n_objects; i++) if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE) From bb28ae1f78c26cc97787fab9a546a97552a4de3d Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 17:30:51 +0100 Subject: [PATCH 126/134] Drop Wmudflap --- m4/manywarnings.m4 | 1 - 1 file changed, 1 deletion(-) diff --git a/m4/manywarnings.m4 b/m4/manywarnings.m4 index 864fc85..840550b 100644 --- a/m4/manywarnings.m4 +++ b/m4/manywarnings.m4 @@ -132,7 +132,6 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC], -Wstack-protector \ -Woverlength-strings \ -Wbuiltin-macro-redefined \ - -Wmudflap \ -Wpacked-bitfield-compat \ -Wsync-nand \ ; do From 8fa80be0b122c5c659426df6adf19ad0aa381c18 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Thu, 5 Nov 2015 17:31:21 +0100 Subject: [PATCH 127/134] Constify. Whitespace. --- ykcs11/obj_types.h | 2 +- ykcs11/objects.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ykcs11/obj_types.h b/ykcs11/obj_types.h index 7c94f29..ca4fc09 100644 --- a/ykcs11/obj_types.h +++ b/ykcs11/obj_types.h @@ -126,7 +126,7 @@ typedef struct { CK_BBOOL token; // TODO: not used yet CK_BBOOL private; CK_BBOOL modifiable; - char *label; + const char *label; CK_BBOOL copyable; // TODO: Optional, not used so far (default TRUE) CK_BBOOL destroyable; // TODO: Optional, not used so far (default TRUE) get_attr_f get_attribute; diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 7b52286..b18fee4 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -463,7 +463,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: DBG("LABEL"); len = strlen(piv_objects[obj].label) + 1; - data =(CK_BYTE_PTR) piv_objects[obj].label; + data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_KEY_TYPE: @@ -705,7 +705,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_LABEL: DBG("LABEL"); len = strlen(piv_objects[obj].label) + 1; - data = (CK_BYTE_PTR)piv_objects[obj].label; + data = (CK_BYTE_PTR) piv_objects[obj].label; break; case CKA_KEY_TYPE: From 045860fd6b30db047fa459d3220c6dd0e1c1b17f Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 6 Nov 2015 10:51:05 +0100 Subject: [PATCH 128/134] for travis: set -e later and hope for the best.. --- build-and-test.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build-and-test.sh b/build-and-test.sh index 956d835..d4d3106 100755 --- a/build-and-test.sh +++ b/build-and-test.sh @@ -1,7 +1,5 @@ #!/bin/sh -set -e - autoreconf -i if [ "x$TRAVIS_OS_NAME" != "xosx" ]; then @@ -19,6 +17,9 @@ else brew install gnu-tar TAR=gtar fi + +set -e + if [ "x$ARCH" != "x" ]; then version=`cat NEWS | grep unreleased | cut -d' ' -f3` set +e From fc9ebe996fa60c1ad041a84619d5a3cc7ec8ccc9 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 6 Nov 2015 10:43:49 +0100 Subject: [PATCH 129/134] YKCS11: remove some warnings. --- ykcs11/openssl_utils.c | 24 +++++++++---------- ykcs11/ykcs11.c | 54 +++++++++++++++++++++++++----------------- ykcs11/yubico_token.c | 2 -- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 9bd3883..353c29f 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -155,15 +155,15 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, } p = out; - if ((*out_len = i2d_X509(cert, &p)) == 0) + if ((*out_len = (CK_ULONG) i2d_X509(cert, &p)) == 0) goto create_empty_cert_cleanup; - /* TODO: REMOVE THIS */ - BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE); + /********************/ + /*BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE); X509_print_ex(STDout, cert, 0, 0); - BIO_free(STDout); + BIO_free(STDout);*/ /********************/ rv = CKR_OK; @@ -227,9 +227,9 @@ CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len) { len = 0; len += get_length(p + 1, &len) + 1; - *cert_len = len; + *cert_len = (CK_ULONG) len; - cert = d2i_X509(NULL, &p, *cert_len); + cert = d2i_X509(NULL, &p, (long) *cert_len); if (cert == NULL) return CKR_FUNCTION_FAILED; @@ -250,7 +250,7 @@ CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { return CKR_BUFFER_TOO_SMALL; p = out; - if ((*out_len = i2d_X509(cert, &p)) == 0) + if ((*out_len = (CK_ULONG) i2d_X509(cert, &p)) == 0) return CKR_FUNCTION_FAILED; return CKR_OK; @@ -308,7 +308,7 @@ CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) { if (rsa == NULL) return 0; - key_len = RSA_size(rsa) * 8; // There is also RSA_bits but only in >= 1.1.0 + key_len = (CK_ULONG) (RSA_size(rsa) * 8); // There is also RSA_bits but only in >= 1.1.0 RSA_free(rsa); rsa = NULL; @@ -363,7 +363,7 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { p = data; - if ((*len = i2d_RSAPublicKey(rsa, &p)) == 0) { + if ((*len = (CK_ULONG) i2d_RSAPublicKey(rsa, &p)) == 0) { RSA_free(rsa); rsa = NULL; return CKR_FUNCTION_FAILED; @@ -417,7 +417,7 @@ CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key) { if (data == NULL) return CKR_ARGUMENTS_BAD; - if ((*key = d2i_RSAPublicKey(NULL, &p, len)) == NULL) + if ((*key = d2i_RSAPublicKey(NULL, &p, (long) len)) == NULL) return CKR_FUNCTION_FAILED; return CKR_OK; @@ -435,7 +435,7 @@ CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) p = data; - if ((*len = i2d_ECPKParameters(ecg, &p)) == 0) { + if ((*len = (CK_ULONG) i2d_ECPKParameters(ecg, &p)) == 0) { EC_KEY_free(eck); eck = NULL; return CKR_FUNCTION_FAILED; @@ -519,7 +519,7 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, return CKR_FUNCTION_FAILED; } - *out_len = RSA_size(key); + *out_len = (CK_ULONG) RSA_size(key); EVP_cleanup(); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 35b27ea..6900320 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -20,7 +20,7 @@ #define PIV_MGM_KEY_LEN 48 #define YKCS11_MAX_SLOTS 16 -#define YKCS11_MAX_SIG_BUF_LEN 1024 +//#define YKCS11_MAX_SIG_BUF_LEN 1024 #define YKCS11_SESSION_ID 5355104 @@ -49,10 +49,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( CK_VOID_PTR pInitArgs ) { - DIN; CK_BYTE readers[2048]; CK_ULONG len = sizeof(readers); + DIN; + if (piv_state != NULL) return CKR_CRYPTOKI_ALREADY_INITIALIZED; @@ -82,9 +83,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Finalize)( CK_VOID_PTR pReserved ) { - DIN; CK_ULONG i; + DIN; + if (pReserved != NULL_PTR) { DBG("Finalized called with pReserved != NULL"); return CKR_ARGUMENTS_BAD; @@ -111,8 +113,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)( CK_INFO_PTR pInfo ) { - DIN; CK_VERSION ver = {0, 0}; // TODO: set version number + + DIN; + pInfo->cryptokiVersion = function_list.version; memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID)); @@ -134,6 +138,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)( ) { DIN; + if(ppFunctionList == NULL_PTR) { DBG("GetFunctionList called with ppFunctionList = NULL"); return CKR_ARGUMENTS_BAD; @@ -152,10 +157,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( CK_ULONG_PTR pulCount ) { - DIN; CK_ULONG i; int j; + DIN; + if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -286,10 +292,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)( CK_ULONG_PTR pulCount ) { - DIN; token_vendor_t token; CK_ULONG count; + DIN; + if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -344,9 +351,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)( CK_MECHANISM_INFO_PTR pInfo ) { - DIN; token_vendor_t token; + DIN; + if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -425,8 +433,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( CK_SESSION_HANDLE_PTR phSession ) { - DIN; // TODO: pApplication and Notify - token_vendor_t token; CK_RV rv; piv_obj_id_t *cert_ids; @@ -434,6 +440,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)( CK_BYTE cert_data[2100]; // Max cert value for ykpiv CK_ULONG cert_len = sizeof(cert_data); + DIN; // TODO: pApplication and Notify + if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -615,9 +623,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)( CK_SLOT_ID slotID ) { - DIN; CK_RV rv; + DIN; + if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -837,8 +846,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_OBJECT_HANDLE_PTR phObject ) { - DIN; - CK_ULONG i; CK_RV rv; CK_OBJECT_CLASS class; @@ -860,6 +867,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_ULONG pubk_id; piv_obj_id_t *obj_ptr; + DIN; if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); @@ -1036,8 +1044,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( CK_OBJECT_HANDLE hObject ) { - DIN; - CK_RV rv; token_vendor_t token; CK_ULONG i; @@ -1048,6 +1054,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)( CK_ULONG pubk_id; piv_obj_id_t *obj_ptr; + DIN; + DBG("Deleting object %lu", hObject); if (piv_state == NULL) { @@ -1147,10 +1155,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)( CK_ULONG ulCount ) { - DIN; CK_ULONG i; CK_RV rv, rv_final; + DIN; + if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -1204,12 +1213,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( CK_ULONG ulCount ) { - DIN; CK_ULONG i; CK_ULONG j; CK_ULONG total; CK_BBOOL private; + DIN; if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); @@ -1585,8 +1594,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( CK_OBJECT_HANDLE hKey ) { - DIN; - CK_KEY_TYPE type = 0; // TODO: replace these with sign_info's fields? + CK_KEY_TYPE type = 0; CK_ULONG key_len = 0; CK_BYTE buf[1024]; CK_ATTRIBUTE template[] = { @@ -1596,6 +1604,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( {CKA_EC_POINT, buf, sizeof(buf)}, }; + DIN; + if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); return CKR_CRYPTOKI_NOT_INITIALIZED; @@ -1682,7 +1692,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)( // The buffer contains an uncompressed point of the form 04, len, 04, x, y // Where len is |x| + |y| + 1 bytes - op_info.op.sign.key_len = ((buf[1] - 1) / 2) * 8; + op_info.op.sign.key_len = (CK_ULONG) (((buf[1] - 1) / 2) * 8); if (op_info.op.sign.key_len == 256) op_info.op.sign.algo = YKPIV_ALGO_ECCP256; @@ -1727,11 +1737,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( CK_ULONG_PTR pulSignatureLen ) { - DIN; - ykpiv_rc piv_rv; CK_RV rv; + DIN; + if (op_info.type != YKCS11_SIGN) { DBG("Signature operation not initialized"); rv = CKR_OPERATION_NOT_INITIALIZED; @@ -2062,7 +2072,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( CK_OBJECT_HANDLE_PTR phPrivateKey ) { - DIN; CK_RV rv; token_vendor_t token; CK_ULONG i; @@ -2075,6 +2084,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( CK_BYTE cert_data[2100]; CK_ULONG cert_len; + DIN; if (piv_state == NULL) { DBG("libykpiv is not initialized or already finalized"); diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index 4245ba7..25da01a 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -4,8 +4,6 @@ #include "debug.h" #include "objects.h" -#define YUBICO_MECHANISMS_NUM 5 - #define MIN_RSA_KEY_SIZE 1024 #define MAX_RSA_KEY_SIZE 2048 #define MIN_ECC_KEY_SIZE 256 From b3a9b6dc8c320630e7522379f722e7d86acd6589 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 6 Nov 2015 11:00:41 +0100 Subject: [PATCH 130/134] fixup ykcs11-version.h with the correct symbols. --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 6940d18..f51533e 100644 --- a/configure.ac +++ b/configure.ac @@ -187,6 +187,11 @@ AC_SUBST(YKPIV_VERSION_MINOR, `echo $PACKAGE_VERSION | sed 's/.*\.\(.*\)\..*/\1/ AC_SUBST(YKPIV_VERSION_PATCH, `echo $PACKAGE_VERSION | sed 's/.*\..*\.\(.*\)/\1/g'`) AC_SUBST(YKPIV_VERSION_NUMBER, `printf "0x%02x%02x%02x" $YKPIV_VERSION_MAJOR $YKPIV_VERSION_MINOR $YKPIV_VERSION_PATCH`) +AC_SUBST(YKCS11_VERSION_MAJOR, `echo $PACKAGE_VERSION | sed 's/\(.*\)\..*\..*/\1/g'`) +AC_SUBST(YKCS11_VERSION_MINOR, `echo $PACKAGE_VERSION | sed 's/.*\.\(.*\)\..*/\1/g'`) +AC_SUBST(YKCS11_VERSION_PATCH, `echo $PACKAGE_VERSION | sed 's/.*\..*\.\(.*\)/\1/g'`) +AC_SUBST(YKCS11_VERSION_NUMBER, `printf "0x%02x%02x%02x" $YKCS11_VERSION_MAJOR $YKCS11_VERSION_MINOR $YKCS11_VERSION_PATCH`) + AC_CONFIG_FILES([ Makefile lib/Makefile From 71bd376a394e5e4c925e420db4985b1da2eb8c74 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 6 Nov 2015 11:01:10 +0100 Subject: [PATCH 131/134] YKCS11: expose module version. --- ykcs11/ykcs11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 6900320..9b6bf51 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1,4 +1,5 @@ #include "ykcs11.h" +#include "ykcs11-version.h" #include #include #include @@ -113,7 +114,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)( CK_INFO_PTR pInfo ) { - CK_VERSION ver = {0, 0}; // TODO: set version number + CK_VERSION ver = {YKCS11_VERSION_MAJOR, (YKCS11_VERSION_MINOR * 100) + YKCS11_VERSION_PATCH}; DIN; From d38df01c6c8ad9b3916240622a60adb51b77ec83 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 6 Nov 2015 13:14:52 +0100 Subject: [PATCH 132/134] Change applet to application. --- README | 2 +- doc/Certificate_Authority_with_NEO.adoc | 2 +- doc/OS_X_code_signing.adoc | 4 ++-- doc/SSH_with_PIV_and_PKCS11.adoc | 2 +- doc/Windows_certificate.adoc | 2 +- doc/YubiKey_NEO_PIV_introduction.adoc | 10 +++++----- lib/error.c | 2 +- lib/ykpiv.c | 2 +- tool/yubico-piv-tool.adoc | 2 +- tool/yubico-piv-tool.c | 12 ++++++------ tool/yubico-piv-tool.h2m | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README b/README index 72766b2..bf95820 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ Introduction ------------ The Yubico PIV tool is used for interacting with the Privilege and -Identification Card (PIV) applet on a https://www.yubico.com[YubiKey NEO]. +Identification Card (PIV) application on a https://www.yubico.com[YubiKey NEO]. With it you may generate keys on the device, importing keys and certificates, and create certificate requests, and other operations. diff --git a/doc/Certificate_Authority_with_NEO.adoc b/doc/Certificate_Authority_with_NEO.adoc index b607b74..dd0687c 100644 --- a/doc/Certificate_Authority_with_NEO.adoc +++ b/doc/Certificate_Authority_with_NEO.adoc @@ -39,7 +39,7 @@ offline machine, booted from a LiveCD. Some additional packages may be required (pcscd, etc, see below) and will have to be transferred on a USB stick. -You need a YubiKey NEO with the PIV applet on, which you can purchase +You need a YubiKey NEO with the PIV application on, which you can purchase from Yubico. You need to install the PKCS#11 Engine: diff --git a/doc/OS_X_code_signing.adoc b/doc/OS_X_code_signing.adoc index 33d804f..3ccf833 100644 --- a/doc/OS_X_code_signing.adoc +++ b/doc/OS_X_code_signing.adoc @@ -8,7 +8,7 @@ certificate in the Neo and use it for code signing. Prerequisites ------------- -* a YubiKey Neo with the PIV applet loaded +* a YubiKey Neo with the PIV application loaded * the yubico-piv-tool software * the OpenSC software * membership in the mac developer program @@ -45,7 +45,7 @@ Steps + NOTE: -K DER is available from version 0.1.3, with earlier convert to PEM and import. -8. Set a new chuid in the applet to make sure nothing is cached for the key: +8. Set a new chuid in the application to make sure nothing is cached for the key: $ yubico-piv-tool -a set-chuid diff --git a/doc/SSH_with_PIV_and_PKCS11.adoc b/doc/SSH_with_PIV_and_PKCS11.adoc index 525c5d9..e2e2b69 100644 --- a/doc/SSH_with_PIV_and_PKCS11.adoc +++ b/doc/SSH_with_PIV_and_PKCS11.adoc @@ -8,7 +8,7 @@ Primarily on a OS X or Linux system. Prerequisites ------------- -* a YubiKey Neo with the PIV applet loaded +* a YubiKey Neo with the PIV application loaded * the yubico-piv-tool software * the OpenSC software * OpenSSH diff --git a/doc/Windows_certificate.adoc b/doc/Windows_certificate.adoc index f178c70..e7b7ea3 100644 --- a/doc/Windows_certificate.adoc +++ b/doc/Windows_certificate.adoc @@ -8,7 +8,7 @@ and then load the certificate in the Neo. Prerequisites ------------- -* a YubiKey Neo with the PIV applet loaded +* a YubiKey Neo with the PIV application loaded * the yubico-piv-tool software * credentials to request certs from a Windows CA diff --git a/doc/YubiKey_NEO_PIV_introduction.adoc b/doc/YubiKey_NEO_PIV_introduction.adoc index 51c8d4d..28863a7 100644 --- a/doc/YubiKey_NEO_PIV_introduction.adoc +++ b/doc/YubiKey_NEO_PIV_introduction.adoc @@ -1,5 +1,5 @@ -Introduction to the YubiKey NEO PIV Applet -========================================== +Introduction to the YubiKey NEO PIV Application +=============================================== The YubiKey NEO supports the Personal Identity Verification (PIV) card interface specified in NIST SP 800-73 document "Cryptographic @@ -33,7 +33,7 @@ Preparing a NEO for real use ---------------------------- You would typically change the management key to make sure nobody but -you can modify the state of the PIV applet on the NEO. Make sure to +you can modify the state of the PIV application on the NEO. Make sure to keep a copy of the key around for later use. key=`dd if=/dev/random bs=1 count=24 2>/dev/null | hexdump -v -e '/1 "%02X"'` @@ -63,7 +63,7 @@ To reset PIN/PUK retry counter AND codes (default pin 123456 puk yubico-piv-tool -k $key -a verify -P $pin -a pin-retries --pin-retries 3 --puk-retries 3 -To reset the applet (PIN/PUK need to be blocked hence trying a couple +To reset the application (PIN/PUK need to be blocked hence trying a couple of times -- you need to modify this if you have changed the default number of PIN/PUK retries). @@ -94,7 +94,7 @@ middleware. Card Holder Unique Identifier ----------------------------- -For the applet to be usable in windows the object CHUID (Card Holder +For the application to be usable in windows the object CHUID (Card Holder Unique Identifier) has to be set and unique. The card contents are also aggressively cached so the CHUID has to be changed if the card contents change. diff --git a/lib/error.c b/lib/error.c index ce2ac80..a812ed4 100644 --- a/lib/error.c +++ b/lib/error.c @@ -46,7 +46,7 @@ static const err_t errors[] = { ERR (YKPIV_MEMORY_ERROR, "Error allocating memory"), ERR (YKPIV_PCSC_ERROR, "Error in PCSC call"), ERR (YKPIV_SIZE_ERROR, "Wrong buffer size"), - ERR (YKPIV_APPLET_ERROR, "No PIV applet found"), + ERR (YKPIV_APPLET_ERROR, "No PIV application found"), ERR (YKPIV_AUTHENTICATION_ERROR, "Error during authentication"), ERR (YKPIV_RANDOMNESS_ERROR, "Error getting randomness"), ERR (YKPIV_GENERIC_ERROR, "Something went wrong."), diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 538b632..0a8e830 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -184,7 +184,7 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { return YKPIV_OK; } else { if(state->verbose) { - fprintf(stderr, "Failed selecting applet: %04x\n", sw); + fprintf(stderr, "Failed selecting application: %04x\n", sw); } } } diff --git a/tool/yubico-piv-tool.adoc b/tool/yubico-piv-tool.adoc index e918907..cbe17e5 100644 --- a/tool/yubico-piv-tool.adoc +++ b/tool/yubico-piv-tool.adoc @@ -30,7 +30,7 @@ For more information about what's happening --verbose can be added to any command. For much more information --verbose=2 may be used. -Display what version of the applet is running on the YubiKey Neo: +Display what version of the application is running on the YubiKey Neo: yubico-piv-tool -a version diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index b611340..01a6690 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -75,9 +75,9 @@ static void print_version(ykpiv_state *state, const char *output_file_name) { } if(ykpiv_get_version(state, version, sizeof(version)) == YKPIV_OK) { - fprintf(output_file, "Applet version %s found.\n", version); + fprintf(output_file, "Application version %s found.\n", version); } else { - fprintf(stderr, "Failed to retrieve applet version.\n"); + fprintf(stderr, "Failed to retrieve application version.\n"); } if(output_file != stdout) { @@ -993,7 +993,7 @@ static bool change_pin(ykpiv_state *state, enum enum_action action, const char * if(action == action_arg_changeMINUS_pin) { fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n"); } else { - fprintf(stderr, "The puk code is blocked, you will have to reinitialize the applet.\n"); + fprintf(stderr, "The puk code is blocked, you will have to reinitialize the application.\n"); } } else { fprintf(stderr, "Failed changing/unblocking code, error: %x\n", sw); @@ -1723,11 +1723,11 @@ int main(int argc, char *argv[]) { } if(ykpiv_authenticate(state, key) != YKPIV_OK) { - fprintf(stderr, "Failed authentication with the applet.\n"); + fprintf(stderr, "Failed authentication with the application.\n"); return EXIT_FAILURE; } if(verbosity) { - fprintf(stderr, "Successful applet authentication.\n"); + fprintf(stderr, "Successful application authentication.\n"); } break; } @@ -1791,7 +1791,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Reset failed, are pincodes blocked?\n"); ret = EXIT_FAILURE; } else { - fprintf(stderr, "Successfully reset the applet.\n"); + fprintf(stderr, "Successfully reset the application.\n"); } break; case action_arg_pinMINUS_retries: diff --git a/tool/yubico-piv-tool.h2m b/tool/yubico-piv-tool.h2m index eda9546..f4925fc 100644 --- a/tool/yubico-piv-tool.h2m +++ b/tool/yubico-piv-tool.h2m @@ -30,7 +30,7 @@ For more information about what's happening \-\-verbose can be added to any command. For much more information \-\-verbose=2 may be used. -Display what version of the applet is running on the YubiKey Neo: +Display what version of the application is running on the YubiKey Neo: yubico\-piv\-tool \-a version From f5b1081f002f173f449afa02b0f8c27ca2077956 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 6 Nov 2015 13:39:21 +0100 Subject: [PATCH 133/134] Replace YubiKey NEO with YubiKey. --- Makefile.am | 2 +- README | 2 +- ...th_NEO.adoc => Certificate_Authority.adoc} | 28 +++++++++---------- doc/OS_X_code_signing.adoc | 8 +++--- doc/SSH_with_PIV_and_PKCS11.adoc | 4 +-- doc/Windows_certificate.adoc | 8 +++--- ...ion.adoc => YubiKey_PIV_introduction.adoc} | 8 +++--- tool/yubico-piv-tool.adoc | 2 +- tool/yubico-piv-tool.h2m | 2 +- 9 files changed, 32 insertions(+), 32 deletions(-) rename doc/{Certificate_Authority_with_NEO.adoc => Certificate_Authority.adoc} (90%) rename doc/{YubiKey_NEO_PIV_introduction.adoc => YubiKey_PIV_introduction.adoc} (93%) diff --git a/Makefile.am b/Makefile.am index 039a8f9..88d5fc4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,7 +31,7 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = windows.mk mac.mk tool/tests/basic.sh tools/fasc.pl -EXTRA_DIST += doc/Certificate_Authority_with_NEO.adoc doc/OS_X_code_signing.adoc doc/SSH_with_PIV_and_PKCS11.adoc doc/Windows_certificate.adoc doc/YubiKey_NEO_PIV_introduction.adoc +EXTRA_DIST += doc/Certificate_Authority.adoc doc/OS_X_code_signing.adoc doc/SSH_with_PIV_and_PKCS11.adoc doc/Windows_certificate.adoc doc/YubiKey_PIV_introduction.adoc if ENABLE_COV cov-reset: diff --git a/README b/README index bf95820..0215259 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ Introduction ------------ The Yubico PIV tool is used for interacting with the Privilege and -Identification Card (PIV) application on a https://www.yubico.com[YubiKey NEO]. +Identification Card (PIV) application on a https://www.yubico.com[YubiKey]. With it you may generate keys on the device, importing keys and certificates, and create certificate requests, and other operations. diff --git a/doc/Certificate_Authority_with_NEO.adoc b/doc/Certificate_Authority.adoc similarity index 90% rename from doc/Certificate_Authority_with_NEO.adoc rename to doc/Certificate_Authority.adoc index dd0687c..7847cb4 100644 --- a/doc/Certificate_Authority_with_NEO.adoc +++ b/doc/Certificate_Authority.adoc @@ -1,8 +1,8 @@ -Certificate Authority with NEO +Certificate Authority with ------------------------------ This document explains how to set up a Certificate Authority (CA) with -Sub-CA private keys stored on YubiKey NEOs. Typical use for this is +Sub-CA private keys stored on YubiKeys. Typical use for this is to generate HTTPS certificates for internal servers. Considerations @@ -10,12 +10,12 @@ Considerations For our example, we have chosen to use one root CA with a private key stored in an offline machine, that signs sub-CAs with private keys -stored on YubiKey NEOs, which signs end-entity (EE) certs. We'll +stored on YubiKeys, which signs end-entity (EE) certs. We'll generate the Sub-CA private keys on an offline host and save a copy of those keys. We have chosen to use a RSA 3744 bit root CA key, and RSA 2048 bit -keys for the NEO Sub-CAs and EE certificates. The NEO is limited to +keys for the Sub-CAs and EE certificates. The is limited to RSA 1k and 2k keys (it supports ECDSA too but we chose to not use that here). @@ -39,7 +39,7 @@ offline machine, booted from a LiveCD. Some additional packages may be required (pcscd, etc, see below) and will have to be transferred on a USB stick. -You need a YubiKey NEO with the PIV application on, which you can purchase +You need a YubiKey with the PIV application on, which you can purchase from Yubico. You need to install the PKCS#11 Engine: @@ -89,15 +89,15 @@ You may inspect the newly generated root CA with: openssl x509 -text < yubico-internal-https-ca-crt.pem -Preparing a Sub-CA NEO +Preparing a Sub-CA ---------------------- We need to change the management key, PIN and PUK code following the -YubiKey-NEO-PIV-Introduction.txt document. We also want to save a +YubiKey-PIV-Introduction.txt document. We also want to save a copy of these values. Here are the steps that are needed to be done -for each new Sub-CA NEO. +for each new Sub-CA. -This step is parametrized with the name of the YubiKey NEO user. +This step is parametrized with the name of the YubiKey user. Generate new management code, PIN and PUK as follows: user=Simon @@ -108,7 +108,7 @@ Generate new management code, PIN and PUK as follows: puk=`dd if=/dev/random bs=1 count=6 2>/dev/null | hexdump -v -e '/1 "%u"'|cut -c1-8` echo $puk > yubico-internal-https-$user-puk.txt -Configure a fresh NEO with these parameters as follows: +Configure a fresh with these parameters as follows: yubico-piv-tool -a set-mgm-key -n $key yubico-piv-tool -k $key -a change-pin -P 123456 -N $pin @@ -117,7 +117,7 @@ Configure a fresh NEO with these parameters as follows: Creating a Sub-CA ----------------- -This step is parametrized with the name of the YubiKey NEO user. This +This step is parametrized with the name of the YubiKey user. This means we will have one Sub-CA for every person authorized to sign certificates in our CA. @@ -157,11 +157,11 @@ You may inspect the newly generated EE cert with this command: openssl x509 -text < yubico-internal-https-subca-$user-crt.pem -Import Sub-CA key to NEO: +Import Sub-CA key to: yubico-piv-tool -k $key -a import-key -s 9c < yubico-internal-https-subca-$user-key.pem -Import Sub-CA cert to NEO: +Import Sub-CA cert to: yubico-piv-tool -k $key -a import-certificate -s 9c < yubico-internal-https-subca-$user-crt.pem @@ -190,7 +190,7 @@ Then generate a new private key and certificate request: EOF openssl req -sha256 -new -config yubico-internal-https-ee-$host-csr.conf -key yubico-internal-https-ee-$host-key.pem -nodes -out yubico-internal-https-ee-$host-csr.pem -Then sign the certificate using the NEO: +Then sign the certificate using the: cat>yubico-internal-https-ee-$host-crt.conf</dev/null | hexdump -v -e '/1 "%02X"'` diff --git a/tool/yubico-piv-tool.adoc b/tool/yubico-piv-tool.adoc index cbe17e5..1ed8ad9 100644 --- a/tool/yubico-piv-tool.adoc +++ b/tool/yubico-piv-tool.adoc @@ -30,7 +30,7 @@ For more information about what's happening --verbose can be added to any command. For much more information --verbose=2 may be used. -Display what version of the application is running on the YubiKey Neo: +Display what version of the application is running on the YubiKey: yubico-piv-tool -a version diff --git a/tool/yubico-piv-tool.h2m b/tool/yubico-piv-tool.h2m index f4925fc..8987cf1 100644 --- a/tool/yubico-piv-tool.h2m +++ b/tool/yubico-piv-tool.h2m @@ -30,7 +30,7 @@ For more information about what's happening \-\-verbose can be added to any command. For much more information \-\-verbose=2 may be used. -Display what version of the application is running on the YubiKey Neo: +Display what version of the application is running on the YubiKey: yubico\-piv\-tool \-a version From a8825c99f32860120af9e2d8a6f8100e8fefb974 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 6 Nov 2015 13:58:46 +0100 Subject: [PATCH 134/134] YKCS11: added release notes. --- doc/YKCS11_release_notes.adoc | 132 ++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 doc/YKCS11_release_notes.adoc diff --git a/doc/YKCS11_release_notes.adoc b/doc/YKCS11_release_notes.adoc new file mode 100644 index 0000000..e53609d --- /dev/null +++ b/doc/YKCS11_release_notes.adoc @@ -0,0 +1,132 @@ +YKCS11 +------ + +This is a PKCS#11 module that allows to communicate with the PIV +application running on a YubiKey. + +BUILDING +~~~~~~~~ + +YKCS11 is automatically built as part of `yubico-piv-tool` and the +following command will suffice + +---- +yubico-piv-tool$ autoreconf --install +yubico-piv-tool$ ./configure +yubico-piv-tool$ make +yubico-piv-tool$ sudo make install +---- + +More info about building yubico-piv-tool can be found in the related +`README` file or over at +https://developers.yubico.com/yubico-piv-tool/. + +Once installed, the module will be found by default in +/usr/local/lib/libykcs11.so otherwise it will be built locally in +yubico-piv-tool/ykcs11/.libs/libykcs11.so + +PORTABILITY +~~~~~~~~~~~ + +The module has been developed and tested using Debian GNU/Linux and +Ubuntu Linux. It is however possible to cross-compile it for Windows +and Mac OS X using the relative makefiles (windows.mk and mac.mk). +Both use PCSC as a backend. + +Keep in mind that communication with the YubiKey is carried out over +the CCID transport. Hence, on Mac OS X the YubiKey should be +whitelisted (more info at https://github.com/Yubico/ifd-yubico). + +Further testing at this stage has *not* been carried out, so +additional tweaks might be needed to use operating systems different +from Linux. + +SUPPORTED FUNCTIONALITY AND KNOWN ISSUES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +YKCS11 is not a full implementation of PKCS#11. Some functionality are +not present and others are not yet implemented. + +In its current form YKCS11 implements a smaller subset of +functionality: + +- RSA key generation + + 1024 or 2048 bit keys can be generated; + +- EC key generation + + curve prime256v1 is supported (256 bit keys); + +- RSA signature + + supported mechanisms are RSA-X-509 (raw RSA), PKCS1 (unhashed), + PKCS1 with SHA1/256/384/512 and PSS with SHA1/256/384/512. The + latter is implemented but has not been tested, hence is provided as + is; + +- ECDSA signature + + supported mechanism are ECDSA (raw) and ECDSA with SHA1; + +- RSA and EC public key (X.509 certificate) import; + +- RSA and EC private key import + + with possibility of setting individual PIN policies and touch to + sign (where supported); + +- Public key deletion. + +PKCS#11 defines two types of users: a regular user and a security +officer (SO). These have been mapped to perform regular usage of the +private key material (PIN-associated operations) and device management +(management-key associated operations). + +Key Mapping +^^^^^^^^^^^ + +The module provides four main keys that can be used. These correspond +to the four main keys in PIV and accessible through yubico-piv-tool. +The mapping is as follows: + +[cols="2*^", options="header"] +|=== +|ykcs11 id|PIV +|0|9a +|1|9e +|2|9c +|3|9d +|=== + +PINs and Management Key +^^^^^^^^^^^^^^^^^^^^^^ + +The default user PIN for the YubiKey is `123456`. + +The default management key is +`010203040506070801020304050607080102030405060708`. + +All the YubiKey personalization (e.g. changing PIN, changing +management key, resetting PINs, resetting the application) is +currently done using yubico-piv-tool. + +In order to perform operations involving the private keys, a regular +user must be logged in (i.e. using the PIN). However, given the +different PIN policies for different keys, subsequent operations might +require a new login. Currently this is supported by the module +allowing multiple _Login_ operations with the appropriate user. +According to PKCS#11 however, a special user called `CONTEXT_SPECIFIC` +should be used for such operations. This is also supported and *might +become the only available mechanism in the future*. + +Key Generation +^^^^^^^^^^^^^^ + +Key pair generation is a particular operation, in the sense that +within PIV this is the only moment where the newly created public key +is given back to the user. To prevent the key from being lost it is +automatically stored within the YubiKey by wrapping it in an X.509 +certificate. This certificate is however empty. It does not have other +valid information except for the public key. + +DEBUGGING +^^^^^^^^^ + +By default the module has debugging enabled. This is _highly_ verbose +and might be confusing. In order to disable it, the two macros +`YKCS11_DBG` and `YKCS11_DINOUT` in the file `debug.h` should be set +to `0`. Once this is done the module must be recompiled.