aboutsummaryrefslogtreecommitdiff
path: root/pkcs11.c
diff options
context:
space:
mode:
Diffstat (limited to 'pkcs11.c')
-rw-r--r--pkcs11.c662
1 files changed, 518 insertions, 144 deletions
diff --git a/pkcs11.c b/pkcs11.c
index 9d61927..36ecefc 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -159,9 +159,9 @@ typedef struct p11_session {
sign_key_handle, /* Key for C_Sign*() */
verify_key_handle; /* Key for C_Verify() */
hal_hash_state_t
- digest_state, /* Hash state for C_Digest*() */
- sign_digest_state, /* Hash state for C_Sign*() */
- verify_digest_state; /* Hash state for C_Verify*() */
+ *digest_state, /* Hash state for C_Digest*() */
+ *sign_digest_state, /* Hash state for C_Sign*() */
+ *verify_digest_state; /* Hash state for C_Verify*() */
} p11_session_t;
/*
@@ -475,6 +475,37 @@ static CK_RV posix_mutex_unlock(CK_VOID_PTR pMutex)
/*
+ * Translate between libhal EC curve names and OIDs.
+ */
+#warning Perhaps this should be a utility routine in libhal instead of here
+
+static int ec_curve_oid_to_name(const uint8_t * const oid, const size_t oid_len, hal_ecdsa_curve_t *curve)
+{
+ static uint8_t ec_curve_oid_p256[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
+ static uint8_t ec_curve_oid_p384[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 };
+ static uint8_t ec_curve_oid_p521[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23 };
+
+ if (oid == NULL || curve == NULL)
+ return 0;
+
+ else if (oid_len == sizeof(ec_curve_oid_p256) && memcmp(oid, ec_curve_oid_p256, oid_len) == 0)
+ *curve = HAL_ECDSA_CURVE_P256;
+
+ else if (oid_len == sizeof(ec_curve_oid_p384) && memcmp(oid, ec_curve_oid_p384, oid_len) == 0)
+ *curve = HAL_ECDSA_CURVE_P384;
+
+ else if (oid_len == sizeof(ec_curve_oid_p521) && memcmp(oid, ec_curve_oid_p521, oid_len) == 0)
+ *curve = HAL_ECDSA_CURVE_P521;
+
+ else
+ return 0;
+
+ return 1;
+}
+
+
+
+/*
* Initialize KEK. If we had proper hardware support the KEK would be
* living in special RAM where we could wipe it if anything triggered
* our tamper circuitry. But we have no such at the moment, so we
@@ -1129,17 +1160,19 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
}
/*
- * Store an RSA private key.
+ * Store a private key.
*
- * Write the key as PKCS #1.5 RSAPrivateKey DER, encrypt that using
- * AES key wrap, and store the result as an SQL blob.
+ * Write the key as DER, encrypt that using AES key wrap, and store
+ * the result as an SQL blob.
*
* We jump through a few minor hoops to let us do all the encoding and
* wrapping in place in a single buffer.
*/
-static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
- const hal_rsa_key_t key)
+static int p11_object_set_generic_private_key(const CK_OBJECT_HANDLE object_handle,
+ const void * const key,
+ const size_t key_der_len,
+ hal_error_t (*to_der)(const void * const, uint8_t *, size_t *, const size_t))
{
static const char select_kek[] =
" SELECT kek FROM global";
@@ -1148,17 +1181,18 @@ static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
" UPDATE %s_object SET private_key = ?1"
" WHERE %s_object_id = (SELECT %s_object_id FROM object WHERE object_handle = ?2)";
- uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(hal_rsa_key_to_der_len(key))];
+ uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(key_der_len)];
const char *flavor = is_token_handle(object_handle) ? "token" : "session";
size_t der_len, wrapbuf_len = sizeof(wrapbuf);
sqlite3_stmt *q = NULL;
int ok = 0;
+ assert(to_der);
+
if (!sql_check_ok(sql_prepare(&q, select_kek)) ||
!sql_check_row(sqlite3_step(q)) ||
sqlite3_column_type(q, 0) == SQLITE_NULL ||
- !hal_check(hal_rsa_key_to_der(key, wrapbuf+8, &der_len,
- sizeof(wrapbuf)-8)) ||
+ !hal_check(to_der(key, wrapbuf + 8, &der_len, sizeof(wrapbuf) - 8)) ||
!hal_check(hal_aes_keywrap(sqlite3_column_blob(q, 0),
sqlite3_column_bytes(q, 0),
wrapbuf+8, der_len, wrapbuf, &wrapbuf_len)) ||
@@ -1178,18 +1212,67 @@ static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
}
/*
- * Fetch an RSA private key.
+ * Store an RSA private key.
+ *
+ * Use p11_object_set_generic_private_key() to wrap the PKCS #1.5
+ * RSAPrivateKey encoding of the private key.
+ */
+
+static hal_error_t p11_object_encode_rsa_key(const void * const key,
+ uint8_t * der,
+ size_t *der_len,
+ const size_t der_max)
+{
+ return hal_rsa_key_to_der(key, der, der_len, der_max);
+}
+
+static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
+ const hal_rsa_key_t * const key)
+{
+ return p11_object_set_generic_private_key(object_handle,
+ key,
+ hal_rsa_key_to_der_len(key),
+ p11_object_encode_rsa_key);
+}
+
+/*
+ * Store an EC private key.
+ *
+ * Use p11_object_set_generic_private_key() to wrap the RFC 5915
+ * ECPrivateKey encoding of the private key.
+ */
+
+static hal_error_t p11_object_encode_ec_key(const void * const key,
+ uint8_t * der,
+ size_t *der_len,
+ const size_t der_max)
+{
+ return hal_ecdsa_key_to_der(key, der, der_len, der_max);
+}
+
+static int p11_object_set_ec_private_key(const CK_OBJECT_HANDLE object_handle,
+ const hal_ecdsa_key_t * const key)
+{
+ return p11_object_set_generic_private_key(object_handle,
+ key,
+ hal_ecdsa_key_to_der_len(key),
+ p11_object_encode_ec_key);
+}
+
+/*
+ * Fetch a private key.
*
* Retrieve SQL blob from the object, unwrap that to get the DER
- * encoding of a PKCS #1.5 RSAPrivateKey object, load the key from
- * that.
+ * encoding, load the key from that.
*
* If the key isn't set, we return success with null key.
*/
-static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
- hal_rsa_key_t *key,
- uint8_t *keybuf, const size_t keybuf_len)
+static int p11_object_get_generic_private_key(const CK_OBJECT_HANDLE object_handle,
+ void **key,
+ uint8_t *keybuf, const size_t keybuf_len,
+ hal_error_t (*from_der)(void **, void *,
+ const size_t, const uint8_t * const, const size_t))
{
static const char select_format[] =
" SELECT kek, private_key FROM global, %s_object NATURAL JOIN object WHERE object_handle = ?1";
@@ -1212,7 +1295,7 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
}
else if (sqlite3_column_type(q, 1) == SQLITE_NULL) {
- key->key = NULL;
+ *key = NULL;
ok = 1;
}
@@ -1225,30 +1308,88 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
uint8_t wrapbuf[pkey_len];
ok = (hal_check(hal_aes_keyunwrap(kek, kek_len, pkey, pkey_len, wrapbuf, &wrapbuf_len)) &&
- hal_check(hal_rsa_key_from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len)));
+ hal_check(from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len)));
memset(wrapbuf, 0, sizeof(wrapbuf));
}
- if (!ok || key->key == NULL)
+ if (!ok || *key == NULL)
memset(keybuf, 0, keybuf_len);
sqlite3_finalize(q);
return ok;
}
-#warning Revisit return semantics of p11_object_get_rsa_private_key() and p11_object_get_rsa_public_key()
+/*
+ * Fetch an RSA private key.
+ *
+ * Use p11_object_get_generic_private_key() to unwrap the DER encoding
+ * of a PKCS #1.5 RSAPrivateKey object.
+ */
+
+static hal_error_t p11_object_decode_rsa_key(void **key_,
+ void *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len)
+{
+ assert(key_ != NULL);
+ hal_rsa_key_t *key = NULL;
+ hal_error_t err = hal_rsa_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ *key_ = key;
+ return err;
+}
+
+static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
+ hal_rsa_key_t **key,
+ uint8_t *keybuf, const size_t keybuf_len)
+{
+ assert(key != NULL);
+ void *key_ = NULL;
+ int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_rsa_key);
+ *key = key_;
+ return ok;
+}
+
+/*
+ * Fetch an EC private key.
+ *
+ * Use p11_object_get_generic_private_key() to unwrap the DER encoding
+ * of an RFC 5915 ECPrivateKey object.
+ */
+
+static hal_error_t p11_object_decode_ec_key(void **key_,
+ void *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len)
+{
+ assert(key_ != NULL);
+ hal_ecdsa_key_t *key = NULL;
+ hal_error_t err = hal_ecdsa_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ *key_ = key;
+ return err;
+}
+
+static int p11_object_get_ec_private_key(const CK_OBJECT_HANDLE object_handle,
+ hal_ecdsa_key_t **key,
+ uint8_t *keybuf, const size_t keybuf_len)
+{
+ assert(key != NULL);
+ void *key_ = NULL;
+ int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_ec_key);
+ *key = key_;
+ return ok;
+}
+
+#warning Revisit return semantics of p11_object_get_*_private_key() and p11_object_*_rsa_public_key()
/*
* Fetch an RSA public key.
*
* Public keys aren't stored separately the way that private keys are,
* so we're looking for the public components so we can load them into
- * a key objet.
+ * a key object.
*/
static int p11_object_get_rsa_public_key(const CK_OBJECT_HANDLE object_handle,
- hal_rsa_key_t *key,
+ hal_rsa_key_t **key,
uint8_t *keybuf, const size_t keybuf_len)
{
static const char select_format[] =
@@ -1277,6 +1418,47 @@ static int p11_object_get_rsa_public_key(const CK_OBJECT_HANDLE object_handle,
return ok;
}
+/*
+ * Fetch an EC public key.
+ *
+ * Public keys aren't stored separately the way that private keys are,
+ * so we're looking for the public components so we can load them into
+ * a key object.
+ */
+
+static int p11_object_get_ec_public_key(const CK_OBJECT_HANDLE object_handle,
+ hal_ecdsa_key_t **key,
+ uint8_t *keybuf, const size_t keybuf_len)
+{
+ static const char select_format[] =
+ " WITH a (type, value) "
+ " AS (SELECT type, value FROM %s_attribute NATURAL JOIN object WHERE object_handle = ?1)"
+ " SELECT a1.value, a2.value FROM a AS a1, a AS a2 WHERE a1.type = %u AND a2.type = %u";
+
+ const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ sqlite3_stmt *q = NULL;
+ hal_ecdsa_curve_t curve;
+
+ assert(key != NULL && keybuf != NULL);
+
+ const int ok = (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, keybuf_len,
+ sqlite3_column_blob( q, 1),
+ sqlite3_column_bytes(q, 1),
+ curve)));
+
+ sqlite3_finalize(q);
+ return ok;
+}
+
/*
@@ -1703,152 +1885,223 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
}
/*
- * CKM_RSA_PKCS_KEY_PAIR_GEN key pair generation implemetation.
- *
- * Much mechanism-independent code has already been factored out of
- * this function, no doubt much remains that will require further
- * refactoring once we implement other mechanisms.
+ * CKM_RSA_PKCS_KEY_PAIR_GEN key pair generation handler.
*/
static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
- const CK_MECHANISM_PTR pMechanism,
const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
const CK_ULONG ulPublicKeyAttributeCount,
const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
const CK_ULONG ulPrivateKeyAttributeCount,
- CK_OBJECT_HANDLE_PTR phPublicKey,
- CK_OBJECT_HANDLE_PTR phPrivateKey)
+ const CK_OBJECT_HANDLE private_handle,
+ const CK_OBJECT_HANDLE public_handle)
{
- CK_OBJECT_HANDLE private_handle = CK_INVALID_HANDLE;
- CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE;
- handle_flavor_t public_handle_flavor = handle_flavor_session_object;
- handle_flavor_t private_handle_flavor = handle_flavor_session_object;
- uint8_t
- keybuf[hal_rsa_key_t_size],
- modulus[hal_rsa_key_t_size/8],
- public_exponent[hal_rsa_key_t_size/8];
- size_t modulus_len;
- CK_ULONG public_exponent_len;
- hal_rsa_key_t key = { NULL };
+ const uint8_t *public_exponent = const_0x010001;
+ size_t public_exponent_len = sizeof(const_0x010001);
+ uint8_t keybuf[hal_rsa_key_t_size];
+ hal_rsa_key_t *key = NULL;
CK_ULONG keysize = 0;
+ size_t modulus_len;
CK_RV rv;
int i;
- /*
- * Do mechanism-independent checks before anything else.
- */
-
- rv = p11_check_keypair_attributes(session,
- pPublicKeyTemplate, ulPublicKeyAttributeCount, &p11_descriptor_rsa_public_key,
- pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &p11_descriptor_rsa_private_key);
- if (rv != CKR_OK)
- return rv;
-
- assert(session != NULL && pMechanism != NULL &&
- pPublicKeyTemplate != NULL && phPublicKey != NULL &&
- pPrivateKeyTemplate != NULL && phPrivateKey != NULL);
-
- /*
- * Grab values and perform mechanism-specific checks.
- */
+ assert(pPublicKeyTemplate != NULL && pPrivateKeyTemplate);
for (i = 0; i < ulPublicKeyAttributeCount; i++) {
const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type;
const void * const val = pPublicKeyTemplate[i].pValue;
-#if 0
const size_t len = pPublicKeyTemplate[i].ulValueLen;
-#endif
-
- assert(val != NULL);
switch (type) {
- case CKA_TOKEN: /* Object stored on token */
- public_handle_flavor = p11_handle_flavor_from_cka_token(val);
- continue;
-
case CKA_MODULUS_BITS: /* Keysize in bits -- only allow multiples of 8 */
keysize = *(CK_ULONG *) val;
if ((keysize & 7) != 0)
return CKR_ATTRIBUTE_VALUE_INVALID;
continue;
+ case CKA_PUBLIC_EXPONENT:
+ public_exponent = val;
+ public_exponent_len = len;
+ continue;
}
}
- for (i = 0; i < ulPrivateKeyAttributeCount; i++) {
- const CK_ATTRIBUTE_TYPE type = pPrivateKeyTemplate[i].type;
- const void * const val = pPrivateKeyTemplate[i].pValue;
-#if 0
- const size_t len = pPrivateKeyTemplate[i].ulValueLen;
-#endif
+ if (keysize == 0)
+ return CKR_TEMPLATE_INCOMPLETE;
+
+ memset(keybuf, 0, sizeof(keybuf));
+
+ if (!hal_check(hal_rsa_key_gen(&key, keybuf, sizeof(keybuf), keysize / 8,
+ public_exponent, public_exponent_len)))
+ lose(CKR_FUNCTION_FAILED);
+
+ if (!p11_object_set_rsa_private_key(private_handle, key))
+ lose(CKR_FUNCTION_FAILED);
+
+ if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &modulus_len, 0)))
+ lose(CKR_FUNCTION_FAILED);
+
+ {
+ uint8_t modulus[modulus_len];
+
+ if (!hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus))) ||
+ !p11_attribute_set(public_handle, CKA_MODULUS, modulus, modulus_len) ||
+ !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len))
+ lose(CKR_FUNCTION_FAILED);
+ }
+
+ rv = CKR_OK;
+
+ fail:
+ hal_rsa_key_clear(key);
+ return rv;
+}
+
+/*
+ * CKM_EC_KEY_PAIR_GEN key pair generation handler.
+ */
+
+static CK_RV generate_keypair_ec(p11_session_t *session,
+ const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ const CK_ULONG ulPublicKeyAttributeCount,
+ const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ const CK_ULONG ulPrivateKeyAttributeCount,
+ const CK_OBJECT_HANDLE private_handle,
+ const CK_OBJECT_HANDLE public_handle)
+{
+ uint8_t keybuf[hal_ecdsa_key_t_size];
+ hal_ecdsa_key_t *key = NULL;
+ const CK_BYTE *params = NULL;
+ hal_ecdsa_curve_t curve;
+ size_t params_len;
+ CK_RV rv;
+ int i;
- assert (val != NULL);
+ assert(session != NULL && pPublicKeyTemplate != NULL && pPrivateKeyTemplate != NULL);
+
+ for (i = 0; i < ulPublicKeyAttributeCount; i++) {
+ const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type;
+ const void * const val = pPublicKeyTemplate[i].pValue;
+ const size_t len = pPublicKeyTemplate[i].ulValueLen;
switch (type) {
- case CKA_TOKEN: /* Object stored on token */
- private_handle_flavor = p11_handle_flavor_from_cka_token(val);
+ case CKA_EC_PARAMS:
+ params = val;
+ params_len = len;
continue;
-
}
}
- /*
- * We require a key size.
- */
- if (keysize == 0)
+ if (!ec_curve_oid_to_name(params, params_len, &curve))
return CKR_TEMPLATE_INCOMPLETE;
- /*
- * Create the PKCS #11 objects and generate the keypair.
- */
+ memset(keybuf, 0, sizeof(keybuf));
+
+ if (!hal_check(hal_ecdsa_key_gen(&key, keybuf, sizeof(keybuf), curve)) ||
+ !p11_object_set_ec_private_key(private_handle, key) ||
+ !p11_attribute_set(public_handle, CKA_EC_PARAMS, params, params_len) ||
+ !p11_attribute_set(private_handle, CKA_EC_PARAMS, params, params_len))
+ lose(CKR_FUNCTION_FAILED);
+
+ {
+ uint8_t point[hal_ecdsa_key_to_ecpoint_len(key)];
- if (!sql_exec("BEGIN") ||
- (public_handle = p11_object_create(session, public_handle_flavor,
+ if (!hal_check(hal_ecdsa_key_to_ecpoint(key, point, NULL, sizeof(point))) ||
+ !p11_attribute_set(public_handle, CKA_EC_POINT, point, sizeof(point)))
+ lose(CKR_FUNCTION_FAILED);
+ }
+
+ rv = CKR_OK;
+
+ fail:
+ hal_ecdsa_key_clear(key);
+ return rv;
+}
+
+/*
+ * Key pair generation. This needs a mechanism-specific function to
+ * do the inner bits, but there's a lot of boilerplate.
+ */
+
+static CK_RV generate_keypair(p11_session_t *session,
+ const CK_MECHANISM_PTR pMechanism,
+ const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ const CK_ULONG ulPublicKeyAttributeCount,
+ const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ const CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_RV (*mechanism_handler)(p11_session_t *session,
+ const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ const CK_ULONG ulPublicKeyAttributeCount,
+ const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ const CK_ULONG ulPrivateKeyAttributeCount,
+ const CK_OBJECT_HANDLE private_handle,
+ const CK_OBJECT_HANDLE public_handle),
+ const p11_descriptor_t * const public_descriptor,
+ const p11_descriptor_t * const private_descriptor)
+{
+ CK_OBJECT_HANDLE private_handle = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE;
+ handle_flavor_t public_handle_flavor = handle_flavor_session_object;
+ handle_flavor_t private_handle_flavor = handle_flavor_session_object;
+ CK_RV rv;
+ int i;
+
+ rv = p11_check_keypair_attributes(session,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount, public_descriptor,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount, private_descriptor);
+ if (rv != CKR_OK)
+ return rv;
+
+ assert(session != NULL && pMechanism != NULL &&
+ pPublicKeyTemplate != NULL && phPublicKey != NULL &&
+ pPrivateKeyTemplate != NULL && phPrivateKey != NULL);
+
+ for (i = 0; i < ulPublicKeyAttributeCount; i++)
+ if (pPublicKeyTemplate[i].type == CKA_TOKEN)
+ public_handle_flavor = p11_handle_flavor_from_cka_token(pPublicKeyTemplate[i].pValue);
+
+ for (i = 0; i < ulPrivateKeyAttributeCount; i++)
+ if (pPrivateKeyTemplate[i].type == CKA_TOKEN)
+ private_handle_flavor = p11_handle_flavor_from_cka_token(pPrivateKeyTemplate[i].pValue);
+
+ if (!sql_exec("BEGIN"))
+ lose(CKR_FUNCTION_FAILED);
+
+ if ((public_handle = p11_object_create(session, public_handle_flavor,
pPublicKeyTemplate, ulPublicKeyAttributeCount,
- &p11_descriptor_rsa_public_key,
- pMechanism)) == CK_INVALID_HANDLE ||
- (private_handle = p11_object_create(session, private_handle_flavor,
- pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
- &p11_descriptor_rsa_private_key,
- pMechanism)) == CK_INVALID_HANDLE ||
- !p11_attribute_get(public_handle, CKA_PUBLIC_EXPONENT,
- public_exponent, &public_exponent_len, sizeof(public_exponent)) ||
- !hal_check(hal_rsa_key_gen(&key, keybuf, sizeof(keybuf), keysize/8,
- public_exponent, (size_t) public_exponent_len)) ||
- !p11_object_set_rsa_private_key(private_handle, key) ||
- !hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus))) ||
- !p11_attribute_set(public_handle, CKA_MODULUS, modulus, modulus_len) ||
- !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len))
+ public_descriptor, pMechanism)) == CK_INVALID_HANDLE)
lose(CKR_FUNCTION_FAILED);
- hal_rsa_key_clear(key);
+ if ((private_handle = p11_object_create(session, private_handle_flavor,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ private_descriptor, pMechanism)) == CK_INVALID_HANDLE)
+ lose(CKR_FUNCTION_FAILED);
- /*
- * Commit the SQL transaction.
- */
+ if ((rv = mechanism_handler(session,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ private_handle, public_handle)) != CKR_OK)
+ goto fail;
if (!sql_exec("COMMIT"))
lose(CKR_FUNCTION_FAILED);
- /*
- * All went well, return handles and we're done.
- */
*phPublicKey = public_handle;
*phPrivateKey = private_handle;
return CKR_OK;
fail:
-
- memset(keybuf, 0, sizeof(keybuf));
-
if (!sql_exec("ROLLBACK"))
rv = CKR_GENERAL_ERROR;
-
return rv;
}
+
+
/*
* Construct a PKCS #1 DigestInfo object. This requires some (very
* basic) ASN.1 encoding, which we perform inline.
@@ -1859,7 +2112,7 @@ static int pkcs1_construct_digestinfo(const hal_hash_descriptor_t * const desc,
uint8_t *digest_info, const size_t digest_info_len)
{
uint8_t statebuf[desc->hash_state_length];
- hal_hash_state_t state = { NULL };
+ hal_hash_state_t *state = NULL;
uint8_t *d = digest_info;
/*
@@ -1949,7 +2202,7 @@ static int pkcs1_5_pad(const uint8_t * const data, const size_t data_len,
* (decryption) operation (both use the private key as exponent).
*/
-static CK_RV sign_rsa_pkcs(hal_rsa_key_t key,
+static CK_RV sign_rsa_pkcs(const hal_rsa_key_t * const key,
const uint8_t * const digest_info, const size_t digest_info_len,
uint8_t *signature, const size_t signature_len)
{
@@ -1980,7 +2233,7 @@ static CK_RV sign_rsa_pkcs(hal_rsa_key_t key,
* unnecessary, but it's also harmless.
*/
-static CK_RV verify_rsa_pkcs(hal_rsa_key_t key,
+static CK_RV verify_rsa_pkcs(const hal_rsa_key_t * const key,
const uint8_t * const digest_info, const size_t digest_info_len,
const uint8_t * const signature, const size_t signature_len)
{
@@ -3039,7 +3292,7 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
if (session->digest_descriptor == NULL)
lose(CKR_OPERATION_NOT_INITIALIZED);
- if (session->digest_state.state != NULL)
+ if (session->digest_state != NULL)
lose(CKR_OPERATION_ACTIVE);
rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK;
@@ -3054,7 +3307,7 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
{
uint8_t statebuf[session->digest_descriptor->hash_state_length];
- hal_hash_state_t state = { NULL };
+ hal_hash_state_t *state = NULL;
if (!hal_check(hal_hash_initialize(session->digest_descriptor,
&state, statebuf, sizeof(statebuf))) ||
@@ -3094,7 +3347,7 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession,
if (!session->digest_descriptor->can_restore_state)
lose(CKR_FUNCTION_FAILED);
- if (session->digest_state.state == NULL) {
+ if (session->digest_state == NULL) {
hal_error_t err = hal_hash_initialize(session->digest_descriptor,
&session->digest_state, NULL, 0);
if (err == HAL_ERROR_ALLOCATION_FAILURE)
@@ -3133,7 +3386,7 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession,
if (pulDigestLen == NULL)
lose(CKR_ARGUMENTS_BAD);
- if (session->digest_descriptor == NULL || session->digest_state.state == NULL)
+ if (session->digest_descriptor == NULL || session->digest_state == NULL)
lose(CKR_OPERATION_NOT_INITIALIZED);
rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK;
@@ -3166,6 +3419,9 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
ENTER_PUBLIC_FUNCTION(C_SignInit);
p11_session_t *session;
+ CK_OBJECT_CLASS key_class;
+ CK_KEY_TYPE key_type;
+ CK_BBOOL key_sign;
CK_RV rv = CKR_OK;
mutex_lock_or_return_failure(p11_global_mutex);
@@ -3182,20 +3438,59 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
goto fail;
- /*
- * Will need to check key algorithm type here once we add support
- * for signature algorithms other than RSA.
- */
+ if (!p11_attribute_get_ulong(hKey, CKA_CLASS, &key_class) ||
+ !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type) ||
+ !p11_attribute_get_bbool(hKey, CKA_SIGN, &key_sign) ||
+ key_class != CKO_PRIVATE_KEY)
+ lose(CKR_KEY_HANDLE_INVALID);
+
+ if (!key_sign)
+ lose(CKR_KEY_FUNCTION_NOT_PERMITTED);
+
+ switch (pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_SHA512_RSA_PKCS:
+ if (key_type != CKK_RSA)
+ lose(CKR_KEY_TYPE_INCONSISTENT);
+ break;
+ case CKM_ECDSA:
+ case CKM_ECDSA_SHA256:
+ case CKM_ECDSA_SHA384:
+ case CKM_ECDSA_SHA512:
+ if (key_type != CKK_EC)
+ lose(CKR_KEY_TYPE_INCONSISTENT);
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
session->sign_key_handle = hKey;
switch (pMechanism->mechanism) {
- case CKM_RSA_PKCS: session->sign_digest_descriptor = NULL; break;
- case CKM_SHA1_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha1; break;
- case CKM_SHA256_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha256; break;
- case CKM_SHA384_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha384; break;
- case CKM_SHA512_RSA_PKCS: session->sign_digest_descriptor = hal_hash_sha512; break;
- default: return CKR_MECHANISM_INVALID;
+ case CKM_RSA_PKCS:
+ case CKM_ECDSA:
+ session->sign_digest_descriptor = NULL;
+ break;
+ case CKM_SHA1_RSA_PKCS:
+ session->sign_digest_descriptor = hal_hash_sha1;
+ break;
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_ECDSA_SHA256:
+ session->sign_digest_descriptor = hal_hash_sha256;
+ break;
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_ECDSA_SHA384:
+ session->sign_digest_descriptor = hal_hash_sha384;
+ break;
+ case CKM_SHA512_RSA_PKCS:
+ case CKM_ECDSA_SHA512:
+ session->sign_digest_descriptor = hal_hash_sha512;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
}
return mutex_unlock(p11_global_mutex);
@@ -3217,7 +3512,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
ENTER_PUBLIC_FUNCTION(C_Sign);
uint8_t keybuf[hal_rsa_key_t_size];
- hal_rsa_key_t key = { NULL };
+ hal_rsa_key_t *key = NULL;
p11_session_t *session;
size_t signature_len;
CK_RV rv;
@@ -3237,6 +3532,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
* From here down this function is RSA-specific, and will need
* rewriting when we add support for other algorithms.
*/
+#warning RSA-specific
if (!p11_object_get_rsa_private_key(session->sign_key_handle,
&key, keybuf, sizeof(keybuf)))
@@ -3246,6 +3542,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
* Retrieve signature length. For RSA this is just the modulus
* length, other algorithms will need a more generic solution.
*/
+#warning RSA-specific
if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &signature_len, 0)))
lose(CKR_FUNCTION_FAILED);
@@ -3302,6 +3599,9 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
ENTER_PUBLIC_FUNCTION(C_VerifyInit);
p11_session_t *session;
+ CK_OBJECT_CLASS key_class;
+ CK_KEY_TYPE key_type;
+ CK_BBOOL key_verify;
CK_RV rv = CKR_OK;
mutex_lock_or_return_failure(p11_global_mutex);
@@ -3318,20 +3618,59 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
goto fail;
- /*
- * Will need to check key algorithm type here once we add support
- * for signature algorithms other than RSA.
- */
+ if (!p11_attribute_get_ulong(hKey, CKA_CLASS, &key_class) ||
+ !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type) ||
+ !p11_attribute_get_bbool(hKey, CKA_SIGN, &key_verify) ||
+ key_class != CKO_PRIVATE_KEY)
+ lose(CKR_KEY_HANDLE_INVALID);
+
+ if (!key_verify)
+ lose(CKR_KEY_FUNCTION_NOT_PERMITTED);
+
+ switch (pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_SHA512_RSA_PKCS:
+ if (key_type != CKK_RSA)
+ lose(CKR_KEY_TYPE_INCONSISTENT);
+ break;
+ case CKM_ECDSA:
+ case CKM_ECDSA_SHA256:
+ case CKM_ECDSA_SHA384:
+ case CKM_ECDSA_SHA512:
+ if (key_type != CKK_EC)
+ lose(CKR_KEY_TYPE_INCONSISTENT);
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
session->verify_key_handle = hKey;
switch (pMechanism->mechanism) {
- case CKM_RSA_PKCS: session->verify_digest_descriptor = NULL; break;
- case CKM_SHA1_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha1; break;
- case CKM_SHA256_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha256; break;
- case CKM_SHA384_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha384; break;
- case CKM_SHA512_RSA_PKCS: session->verify_digest_descriptor = hal_hash_sha512; break;
- default: return CKR_MECHANISM_INVALID;
+ case CKM_RSA_PKCS:
+ case CKM_ECDSA:
+ session->verify_digest_descriptor = NULL;
+ break;
+ case CKM_SHA1_RSA_PKCS:
+ session->verify_digest_descriptor = hal_hash_sha1;
+ break;
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_ECDSA_SHA256:
+ session->verify_digest_descriptor = hal_hash_sha256;
+ break;
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_ECDSA_SHA384:
+ session->verify_digest_descriptor = hal_hash_sha384;
+ break;
+ case CKM_SHA512_RSA_PKCS:
+ case CKM_ECDSA_SHA512:
+ session->verify_digest_descriptor = hal_hash_sha512;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
}
return mutex_unlock(p11_global_mutex);
@@ -3353,7 +3692,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
ENTER_PUBLIC_FUNCTION(C_Verify);
uint8_t keybuf[hal_rsa_key_t_size];
- hal_rsa_key_t key = { NULL };
+ hal_rsa_key_t *key = NULL;
p11_session_t *session;
CK_RV rv;
@@ -3372,6 +3711,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
* From here down this function is RSA-specific, and will need
* rewriting when we add support for other algorithms.
*/
+#warning RSA-specific
if (!p11_object_get_rsa_public_key(session->verify_key_handle,
&key, keybuf, sizeof(keybuf)))
@@ -3444,10 +3784,23 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
switch (pMechanism->mechanism) {
case CKM_RSA_PKCS_KEY_PAIR_GEN:
- rv = generate_keypair_rsa_pkcs(session, pMechanism,
- pPublicKeyTemplate, ulPublicKeyAttributeCount,
- pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
- phPublicKey, phPrivateKey);
+ rv = generate_keypair(session, pMechanism,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ generate_keypair_rsa_pkcs,
+ &p11_descriptor_rsa_public_key,
+ &p11_descriptor_rsa_private_key);
+ break;
+
+ case CKM_EC_KEY_PAIR_GEN:
+ rv = generate_keypair(session, pMechanism,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ generate_keypair_ec,
+ &p11_descriptor_ec_public_key,
+ &p11_descriptor_ec_private_key);
break;
default:
@@ -3502,6 +3855,8 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
const CK_ULONG rsa_key_min = 1024;
const CK_ULONG rsa_key_max = 8192;
+ const CK_ULONG ec_key_min = 256;
+ const CK_ULONG ec_key_max = 521;
/*
* No locking here, no obvious need for it.
@@ -3518,6 +3873,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
case CKM_SHA_1:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA_1_HMAC:
+ case CKM_ECDSA_SHA1:
if (hal_hash_core_present(hal_hash_sha1) != HAL_OK)
return CKR_MECHANISM_INVALID;
break;
@@ -3525,6 +3881,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
case CKM_SHA256:
case CKM_SHA256_RSA_PKCS:
case CKM_SHA256_HMAC:
+ case CKM_ECDSA_SHA256:
if (hal_hash_core_present(hal_hash_sha256) != HAL_OK)
return CKR_MECHANISM_INVALID;
break;
@@ -3532,6 +3889,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
case CKM_SHA384:
case CKM_SHA384_RSA_PKCS:
case CKM_SHA384_HMAC:
+ case CKM_ECDSA_SHA384:
if (hal_hash_core_present(hal_hash_sha384) != HAL_OK)
return CKR_MECHANISM_INVALID;
break;
@@ -3539,6 +3897,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
case CKM_SHA512:
case CKM_SHA512_RSA_PKCS:
case CKM_SHA512_HMAC:
+ case CKM_ECDSA_SHA512:
if (hal_hash_core_present(hal_hash_sha512) != HAL_OK)
return CKR_MECHANISM_INVALID;
break;
@@ -3555,6 +3914,12 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR;
break;
+ case CKM_EC_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = ec_key_min;
+ pInfo->ulMaxKeySize = ec_key_max;
+ pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR | CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS;
+ break;
+
case CKM_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
@@ -3565,6 +3930,15 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY;
break;
+ case CKM_ECDSA:
+ case CKM_ECDSA_SHA256:
+ case CKM_ECDSA_SHA384:
+ case CKM_ECDSA_SHA512:
+ pInfo->ulMinKeySize = ec_key_min;
+ pInfo->ulMaxKeySize = ec_key_max;
+ pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS;
+ break;
+
case CKM_SHA_1:
case CKM_SHA256:
case CKM_SHA384: