aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-09-07 18:40:55 -0400
committerRob Austein <sra@hactrn.net>2015-09-07 18:40:55 -0400
commit92325a4ca95c99e164257528514c24cbb982ea7a (patch)
tree09ecf31d05720b9f2e0a2319cfcd40bdc8f8d98d
parentb2d4db9254788a0d84b247ba14692eb4291d8f9a (diff)
Checkpoint of partial support for ECDSA. Compiles, not yet tested,
probably doesn't work. Probably should merge state_access branch before going much further with this.
-rw-r--r--pkcs11.c630
1 files changed, 502 insertions, 128 deletions
diff --git a/pkcs11.c b/pkcs11.c
index 93e051a..ff5304a 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -478,6 +478,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
@@ -1132,17 +1163,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 * const 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";
@@ -1151,17 +1184,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)) ||
@@ -1181,18 +1215,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";
@@ -1228,7 +1311,7 @@ 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));
}
@@ -1240,14 +1323,72 @@ static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
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,
@@ -1280,6 +1421,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;
+}
+
/*
@@ -1704,152 +1886,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;
+ 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;
- assert (val != NULL);
+ 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(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);
- if (!sql_exec("BEGIN") ||
- (public_handle = p11_object_create(session, public_handle_flavor,
+ {
+ uint8_t point[hal_ecdsa_key_to_ecpoint_len(key)];
+
+ 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.
@@ -3076,6 +3329,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);
@@ -3092,20 +3348,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);
@@ -3147,6 +3442,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)))
@@ -3156,6 +3452,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);
@@ -3212,6 +3509,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);
@@ -3228,20 +3528,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);
@@ -3282,6 +3621,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)))
@@ -3354,10 +3694,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:
@@ -3412,6 +3765,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.
@@ -3428,6 +3783,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;
@@ -3435,6 +3791,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;
@@ -3442,6 +3799,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;
@@ -3449,6 +3807,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;
@@ -3465,6 +3824,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:
@@ -3475,6 +3840,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: