diff options
author | Rob Austein <sra@hactrn.net> | 2016-05-18 15:37:51 -0400 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2016-05-18 15:37:51 -0400 |
commit | d77efd2f3abd3b7381351c388adae9fabba41361 (patch) | |
tree | 8ad09e85ed90bc0409f20edf9fd543ca5212a6f5 | |
parent | 00b2adefccab211bb853c79ac84315dbd40ee05d (diff) |
Refactor object creation code.
-rw-r--r-- | pkcs11.c | 252 |
1 files changed, 105 insertions, 147 deletions
@@ -1416,64 +1416,29 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session, } /* - * Construct and store libhal type code for a key object. - */ - -static int p11_object_pkey_type(const CK_OBJECT_HANDLE object_handle, - hal_key_type_t *pkey_type) -{ - static const char update_pkey_type[] = - " UPDATE object SET hal_pkey_type = ?2 WHERE object_handle = ?1"; - - assert(pkey_type != NULL); - - CK_OBJECT_CLASS cka_class; - CK_KEY_TYPE cka_key_type; - - if (!p11_attribute_get_ulong(object_handle, CKA_CLASS, &cka_class) || - !p11_attribute_get_ulong(object_handle, CKA_KEY_TYPE, &cka_key_type)) - return 0; - - else if (cka_class == CKO_PRIVATE_KEY && cka_key_type == CKK_RSA) - *pkey_type = HAL_KEY_TYPE_RSA_PRIVATE; - - else if (cka_class == CKO_PRIVATE_KEY && cka_key_type == CKK_EC) - *pkey_type = HAL_KEY_TYPE_EC_PRIVATE; - - else if (cka_class == CKO_PUBLIC_KEY && cka_key_type == CKK_RSA) - *pkey_type = HAL_KEY_TYPE_RSA_PUBLIC; - - else if (cka_class == CKO_PUBLIC_KEY && cka_key_type == CKK_EC) - *pkey_type = HAL_KEY_TYPE_EC_PUBLIC; - - else - *pkey_type = HAL_KEY_TYPE_NONE; - - sqlite3_stmt *q = NULL; - - int ok = (sql_check_ok(sql_prepare(&q, update_pkey_type)) && - sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) && - sql_check_ok(sqlite3_bind_int64(q, 2, *pkey_type)) && - sql_check_done(sqlite3_step(q))); - - sqlite3_finalize(q); - return ok; -} - -/* - * Construct and store SKI (key hash) for a key object. + * Bind PKCS #11 objects to keystore objects. + * + * This requires storing the pkey type (supplied) and the SKI + * (calcualted from supplied public key DER) of the key. We return + * the calculated SKI so that the caller can use it as the pkey name. + * + * We don't work with pkey handles here because that would create a + * chicken-and-egg problem, given that the values calculated and + * stored by this function are what we use to look up a pkey given + * a PKCS #11 key object. */ -static int p11_object_pkey_ski(const p11_session_t * const session, - const CK_OBJECT_HANDLE object_handle_1, - const CK_OBJECT_HANDLE object_handle_2, - const uint8_t * const der, const size_t der_len, - uint8_t *ski, const size_t ski_len) +static int p11_object_bind_pkey(const p11_session_t * const session, + const hal_key_type_t pkey_type, + const CK_OBJECT_HANDLE object_handle_1, + const CK_OBJECT_HANDLE object_handle_2, + const uint8_t * const der, const size_t der_len, + uint8_t *ski, const size_t ski_len) { assert(session != NULL && der != NULL && ski != NULL); static const char update_pkey_ski[] = - " UPDATE object SET hal_pkey_ski = ?2 WHERE object_handle = ?1"; + " UPDATE object SET hal_pkey_type = ?1, hal_pkey_ski = ?2 WHERE object_handle = ?3 OR object_handle = ?4"; hal_hash_handle_t hash = {HAL_HANDLE_NONE}; @@ -1491,33 +1456,24 @@ static int p11_object_pkey_ski(const p11_session_t * const session, sqlite3_stmt *q = NULL; - ok = (sql_check_ok(sql_prepare(&q, update_pkey_ski)) && - sql_check_ok(sqlite3_bind_int64(q, 1, - object_handle_1)) && - sql_check_ok(sqlite3_bind_blob( q, 2, - ski, ski_len, NULL)) && + ok = (sql_check_ok(sql_prepare(&q, update_pkey_ski)) && + sql_check_ok(sqlite3_bind_int64(q, 1, pkey_type)) && + sql_check_ok(sqlite3_bind_blob( q, 2, ski, ski_len, NULL)) && + sql_check_ok(sqlite3_bind_int64(q, 3, object_handle_1)) && + sql_check_ok(sqlite3_bind_int64(q, 4, object_handle_2)) && sql_check_done(sqlite3_step(q))); - if (ok && object_handle_2 != CK_INVALID_HANDLE) - ok = (sql_check_ok(sqlite3_reset(q)) && - sql_check_ok(sqlite3_bind_int64(q, 1, - object_handle_2)) && - sql_check_done(sqlite3_step(q))); - sqlite3_finalize(q); return ok; } /* - * Fetch the libhal pkey handle for a key object. + * Create pkeys to go with PKCS #11 public key objects loaded by C_CreateObject(). */ -#warning Should do something about key usage flags in p11_object_get_*_public_key() - -static inline int p11_object_get_rsa_public_key(const p11_session_t * const session, - const CK_OBJECT_HANDLE object_handle, - hal_pkey_handle_t *pkey_handle, - const hal_key_flags_t flags) +static inline int p11_object_create_rsa_public_key(const p11_session_t * const session, + const CK_OBJECT_HANDLE object_handle, + const hal_key_flags_t flags) { static const char select_format[] = " WITH a (type, value) " @@ -1526,20 +1482,19 @@ static inline int p11_object_get_rsa_public_key(const p11_session_t * const sess const char *flavor = is_token_handle(object_handle) ? "token" : "session"; + hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; uint8_t keybuf[hal_rsa_key_t_size]; hal_rsa_key_t *key = NULL; sqlite3_stmt *q = NULL; size_t ski_len = 0; int ok - = (hal_check(hal_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM, - &ski_len)) && - sql_check_ok(sql_prepare(&q, select_format, flavor, - CKA_MODULUS, CKA_PUBLIC_EXPONENT)) && - sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) && - sql_check_row(sqlite3_step(q)) && - sqlite3_column_type(q, 0) == SQLITE_BLOB && - sqlite3_column_type(q, 1) == SQLITE_BLOB && + = (hal_check(hal_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM, &ski_len)) && + sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_MODULUS, CKA_PUBLIC_EXPONENT)) && + sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) && + sql_check_row(sqlite3_step(q)) && + sqlite3_column_type(q, 0) == SQLITE_BLOB && + sqlite3_column_type(q, 1) == SQLITE_BLOB && hal_check(hal_rsa_key_load_public(&key, keybuf, sizeof(keybuf), sqlite3_column_blob( q, 0), sqlite3_column_bytes(q, 0), @@ -1548,24 +1503,24 @@ static inline int p11_object_get_rsa_public_key(const p11_session_t * const sess if (ok) { uint8_t der[hal_rsa_public_key_to_der_len(key)], ski[ski_len]; - ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) && - p11_object_pkey_ski(session, object_handle, CK_INVALID_HANDLE, - der, sizeof(der), ski, sizeof(ski)) && + ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) && + p11_object_bind_pkey(session, HAL_KEY_TYPE_RSA_PUBLIC, + object_handle, CK_INVALID_HANDLE, + der, sizeof(der), ski, sizeof(ski)) && hal_check(hal_rpc_pkey_load(p11_session_hal_client(session), p11_session_hal_session(session), - pkey_handle, HAL_KEY_TYPE_RSA_PUBLIC, - HAL_CURVE_NONE, ski, sizeof(ski), - der, sizeof(der), flags))); + &pkey, HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE, + ski, sizeof(ski), der, sizeof(der), flags))); } + (void) hal_rpc_pkey_close(pkey); sqlite3_finalize(q); return ok; } -static inline int p11_object_get_ec_public_key(const p11_session_t * const session, - const CK_OBJECT_HANDLE object_handle, - hal_pkey_handle_t *pkey_handle, - const hal_key_flags_t flags) +static inline int p11_object_create_ec_public_key(const p11_session_t * const session, + const CK_OBJECT_HANDLE object_handle, + const hal_key_flags_t flags) { static const char select_format[] = " WITH a (type, value) " @@ -1574,6 +1529,7 @@ static inline int p11_object_get_ec_public_key(const p11_session_t * const sessi const char *flavor = is_token_handle(object_handle) ? "token" : "session"; + hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; uint8_t keybuf[hal_ecdsa_key_t_size]; hal_ecdsa_key_t *key = NULL; hal_curve_name_t curve; @@ -1581,17 +1537,13 @@ static inline int p11_object_get_ec_public_key(const p11_session_t * const sessi size_t ski_len = 0; int ok - = (hal_check(hal_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM, - &ski_len)) && - sql_check_ok(sql_prepare(&q, select_format, flavor, - CKA_EC_PARAMS, CKA_EC_POINT)) && - sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) && - sql_check_row(sqlite3_step(q)) && - sqlite3_column_type(q, 0) == SQLITE_BLOB && - sqlite3_column_type(q, 1) == SQLITE_BLOB && - ec_curve_oid_to_name(sqlite3_column_blob( q, 0), - sqlite3_column_bytes(q, 0), - &curve) && + = (hal_check(hal_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM, &ski_len)) && + sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_EC_PARAMS, CKA_EC_POINT)) && + sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) && + sql_check_row(sqlite3_step(q)) && + sqlite3_column_type(q, 0) == SQLITE_BLOB && + sqlite3_column_type(q, 1) == SQLITE_BLOB && + ec_curve_oid_to_name(sqlite3_column_blob( q, 0), sqlite3_column_bytes(q, 0), &curve) && hal_check(hal_ecdsa_key_from_ecpoint(&key, keybuf, sizeof(keybuf), sqlite3_column_blob( q, 1), sqlite3_column_bytes(q, 1), @@ -1599,20 +1551,25 @@ static inline int p11_object_get_ec_public_key(const p11_session_t * const sessi if (ok) { uint8_t der[hal_ecdsa_public_key_to_der_len(key)], ski[ski_len]; - ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) && - p11_object_pkey_ski(session, object_handle, CK_INVALID_HANDLE, - der, sizeof(der), ski, sizeof(ski)) && + ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) && + p11_object_bind_pkey(session, HAL_KEY_TYPE_EC_PUBLIC, + object_handle, CK_INVALID_HANDLE, + der, sizeof(der), ski, sizeof(ski)) && hal_check(hal_rpc_pkey_load(p11_session_hal_client(session), p11_session_hal_session(session), - pkey_handle, HAL_KEY_TYPE_EC_PUBLIC, - curve, ski, sizeof(ski), - der, sizeof(der), flags))); + &pkey, HAL_KEY_TYPE_EC_PUBLIC, curve, + ski, sizeof(ski), der, sizeof(der), flags))); } + (void) hal_rpc_pkey_close(pkey); sqlite3_finalize(q); return ok; } +/* + * Given a PKCS #11 object, obtain a libhal pkey handle. + */ + static int p11_object_get_pkey_handle(const p11_session_t * const session, const CK_OBJECT_HANDLE object_handle, hal_pkey_handle_t *pkey_handle) @@ -1621,49 +1578,24 @@ static int p11_object_get_pkey_handle(const p11_session_t * const session, " SELECT hal_pkey_type, hal_pkey_ski FROM object WHERE object_handle = ?1"; hal_key_flags_t flags = is_token_handle(object_handle) ? 0 : HAL_KEY_FLAG_PROXIMATE; - hal_key_type_t pkey_type; sqlite3_stmt *q = NULL; - hal_error_t err; int ok = 0; assert(pkey_handle != NULL); if (!sql_check_ok(sql_prepare(&q, select_query)) || !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) || - !sql_check_row(sqlite3_step(q))) - goto fail; - - const int column_0_type = sqlite3_column_type(q, 0); - const int column_1_type = sqlite3_column_type(q, 1); - - if (column_0_type == SQLITE_INTEGER) - pkey_type = (hal_key_type_t) sqlite3_column_int64(q, 0); - - else if (column_0_type != SQLITE_NULL || !p11_object_pkey_type(object_handle, &pkey_type)) - goto fail; - - if (column_1_type == SQLITE_BLOB) - err = hal_whine_allow(hal_rpc_pkey_find(p11_session_hal_client(session), p11_session_hal_session(session), pkey_handle, - pkey_type, sqlite3_column_blob(q, 1), sqlite3_column_bytes(q, 1), flags), - HAL_ERROR_KEY_NOT_FOUND); - - else if (column_1_type == SQLITE_NULL) - err = hal_whine(HAL_ERROR_KEY_NOT_FOUND); - - else + !sql_check_row(sqlite3_step(q)) || + sqlite3_column_type(q, 0) != SQLITE_INTEGER || + sqlite3_column_type(q, 1) != SQLITE_BLOB) goto fail; - if (err == HAL_OK) - ok = 1; - - else if (err == HAL_ERROR_KEY_NOT_FOUND && pkey_type == HAL_KEY_TYPE_RSA_PUBLIC) - ok = p11_object_get_rsa_public_key(session, object_handle, pkey_handle, flags); + const hal_key_type_t pkey_type = sqlite3_column_int64(q, 0); + const uint8_t * const ski = sqlite3_column_blob( q, 1); + const size_t ski_len = sqlite3_column_bytes(q, 1); - else if (err == HAL_ERROR_KEY_NOT_FOUND && pkey_type == HAL_KEY_TYPE_EC_PUBLIC) - ok = p11_object_get_ec_public_key(session, object_handle, pkey_handle, flags); - - else - ok = 0; + ok = hal_check(hal_rpc_pkey_find(p11_session_hal_client(session), p11_session_hal_session(session), + pkey_handle, pkey_type, ski, ski_len, flags)); fail: sqlite3_finalize(q); @@ -2167,8 +2099,8 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, hal_rsa_key_t *key = NULL; if (!hal_check(hal_rpc_pkey_get_public_key(pkey, der, &der_len, sizeof(der))) || - !p11_object_pkey_ski(session, private_handle, public_handle, - der, sizeof(der), ski, sizeof(ski)) || + !p11_object_bind_pkey(session, HAL_KEY_TYPE_RSA_PRIVATE, private_handle, public_handle, + der, sizeof(der), ski, sizeof(ski)) || !hal_check(hal_rpc_pkey_rename(pkey, ski, sizeof(ski))) || !hal_check(hal_rsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)) || !hal_check(hal_rsa_key_get_modulus(key, NULL, &modulus_len, 0))) @@ -2247,8 +2179,8 @@ static CK_RV generate_keypair_ec(p11_session_t *session, size_t der_len; if (!hal_check(hal_rpc_pkey_get_public_key(pkey, der, &der_len, sizeof(der))) || - !p11_object_pkey_ski(session, private_handle, public_handle, - der, sizeof(der), ski, sizeof(ski)) || + !p11_object_bind_pkey(session, HAL_KEY_TYPE_EC_PRIVATE, private_handle, public_handle, + der, sizeof(der), ski, sizeof(ski)) || !hal_check(hal_rpc_pkey_rename(pkey, ski, sizeof(ski))) || !hal_check(hal_ecdsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len))) lose(CKR_FUNCTION_FAILED); @@ -3201,19 +3133,34 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, if ((rv = p11_check_create_attributes(session, pTemplate, ulCount, descriptor)) != CKR_OK) goto fail; + const handle_flavor_t flavor + = cka_token == NULL ? handle_flavor_session_object : p11_handle_flavor_from_cka_token(cka_token); + switch (session->state) { case CKS_RO_PUBLIC_SESSION: case CKS_RO_USER_FUNCTIONS: - if (cka_token != NULL && *cka_token) + if (flavor == handle_flavor_token_object) lose(CKR_SESSION_READ_ONLY); } + /* + * The above checks notwithstanding, we don't (yet) know how to + * create anything but CKO_PUBLIC_KEY objects here. + * + * The main problem issue is that we need to be very sure that + * sensitive attributes don't get put in publicly-readable storage, + * which will require filtering creation of sensitive attributes in + * p11_object_create(). + * + * Which we need to do anyway, eventually, but let's get handling of + * keys we generate ourselves working properly (again) first. + */ + if (*cka_class != CKO_PUBLIC_KEY) + lose(CKR_TEMPLATE_INCONSISTENT); + if (!sql_exec("BEGIN")) lose(CKR_FUNCTION_FAILED); - const handle_flavor_t flavor - = cka_token == NULL ? handle_flavor_session_object : p11_handle_flavor_from_cka_token(cka_token); - if ((handle = p11_object_create(session, flavor, pTemplate, ulCount, descriptor, NULL)) == CK_INVALID_HANDLE) lose(CKR_FUNCTION_FAILED); @@ -3228,7 +3175,18 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, lose(CKR_FUNCTION_FAILED); } -#warning Somewhere around here we need to create a libhal key object from supplied components + hal_key_flags_t flags = flavor == handle_flavor_session_object ? HAL_KEY_FLAG_PROXIMATE : 0; + + for (int i = 0; i < ulCount; i++) + p11_attribute_apply_keyusage(&flags, pTemplate[i].type, pTemplate[i].pValue); + + if (*cka_class == CKO_PUBLIC_KEY && *cka_key_type == CKK_RSA && + !p11_object_create_rsa_public_key(session, handle, flags)) + goto fail; + + if (*cka_class == CKO_PUBLIC_KEY && *cka_key_type == CKK_EC && + !p11_object_create_ec_public_key(session, handle, flags)) + goto fail; if (!sql_exec("COMMIT")) lose(CKR_FUNCTION_FAILED); |