From d52a62ab76003fffd04dfaee686aa1956e7b56a7 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 7 Apr 2017 13:57:56 -0400 Subject: Enforce key usage flags. --- libhal.py | 2 +- rpc_pkey.c | 14 +++++++++++++- unit-tests.py | 55 +++++++++++++++++++++++-------------------------------- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/libhal.py b/libhal.py index 92f3987..2bc80f4 100644 --- a/libhal.py +++ b/libhal.py @@ -567,7 +567,7 @@ class HSM(object): logger.debug("Opened pkey %s", pkey.uuid) return pkey - def pkey_generate_rsa(self, keylen, exponent = "\x01\x00\x01", flags = 0, client = 0, session = 0): + def pkey_generate_rsa(self, keylen, flags = 0, exponent = "\x01\x00\x01", client = 0, session = 0): with self.rpc(RPC_FUNC_PKEY_GENERATE_RSA, session, keylen, exponent, flags, client = client) as r: pkey = PKey(self, r.unpack_uint(), UUID(bytes = r.unpack_bytes())) logger.debug("Generated RSA pkey %s", pkey.uuid) diff --git a/rpc_pkey.c b/rpc_pkey.c index e55ebf8..dca054f 100644 --- a/rpc_pkey.c +++ b/rpc_pkey.c @@ -268,7 +268,7 @@ static inline hal_error_t ks_open_from_flags(hal_ks_t **ks, const hal_key_flags_ * return a key handle and the name. */ -#warning Convert hal_rpc_pkey_load() to use hal-asn1_guess_key_type()? +#warning Convert hal_rpc_pkey_load() to use hal_asn1_guess_key_type()? static hal_error_t pkey_local_load(const hal_client_handle_t client, const hal_session_handle_t session, @@ -809,6 +809,9 @@ static hal_error_t pkey_local_sign(const hal_pkey_handle_t pkey, return HAL_ERROR_UNSUPPORTED_KEY; } + if ((slot->flags & HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) == 0) + return HAL_ERROR_FORBIDDEN; + uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; @@ -957,6 +960,9 @@ static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey, return HAL_ERROR_UNSUPPORTED_KEY; } + if ((slot->flags & HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) == 0) + return HAL_ERROR_FORBIDDEN; + uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; @@ -1084,6 +1090,9 @@ static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle, if ((pkey->flags & HAL_KEY_FLAG_EXPORTABLE) == 0) return HAL_ERROR_FORBIDDEN; + if ((kekek->flags & HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT) == 0) + return HAL_ERROR_FORBIDDEN; + if (kekek->type != HAL_KEY_TYPE_RSA_PRIVATE && kekek->type != HAL_KEY_TYPE_RSA_PUBLIC) return HAL_ERROR_UNSUPPORTED_KEY; @@ -1189,6 +1198,9 @@ static hal_error_t pkey_local_import(const hal_client_handle_t client, if (kekek == NULL) return HAL_ERROR_KEY_NOT_FOUND; + if ((kekek->flags & HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT) == 0) + return HAL_ERROR_FORBIDDEN; + if (kekek->type != HAL_KEY_TYPE_RSA_PRIVATE) return HAL_ERROR_UNSUPPORTED_KEY; diff --git a/unit-tests.py b/unit-tests.py index 2480506..83260e6 100644 --- a/unit-tests.py +++ b/unit-tests.py @@ -258,16 +258,18 @@ class TestPKeyGen(TestCaseLoggedIn): k2.verify(signature = sig, data = data) def gen_sign_verify_rsa(self, hashalg, keylen): - k1 = hsm.pkey_generate_rsa(keylen) + k1 = hsm.pkey_generate_rsa(keylen, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k1.delete) - k2 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE, k1.public_key) + k2 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE, k1.public_key, + HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k2.delete) self.sign_verify(hashalg, k1, k2) def gen_sign_verify_ecdsa(self, hashalg, curve): - k1 = hsm.pkey_generate_ec(curve) + k1 = hsm.pkey_generate_ec(curve, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k1.delete) - k2 = hsm.pkey_load(HAL_KEY_TYPE_EC_PUBLIC, curve, k1.public_key) + k2 = hsm.pkey_load(HAL_KEY_TYPE_EC_PUBLIC, curve, k1.public_key, + HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k2.delete) self.sign_verify(hashalg, k1, k2) @@ -302,19 +304,23 @@ class TestPKeyHashing(TestCaseLoggedIn): def load_sign_verify_rsa(self, alg, keylen, method): k1 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PRIVATE, HAL_CURVE_NONE, - PreloadedKey.db[HAL_KEY_TYPE_RSA_PRIVATE, keylen].der) + PreloadedKey.db[HAL_KEY_TYPE_RSA_PRIVATE, keylen].der, + HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k1.delete) k2 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE, - PreloadedKey.db[HAL_KEY_TYPE_RSA_PUBLIC, keylen].der) + PreloadedKey.db[HAL_KEY_TYPE_RSA_PUBLIC, keylen].der, + HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k2.delete) method(alg, k1, k2) def load_sign_verify_ecdsa(self, alg, curve, method): k1 = hsm.pkey_load(HAL_KEY_TYPE_EC_PRIVATE, curve, - PreloadedKey.db[HAL_KEY_TYPE_EC_PRIVATE, curve].der) + PreloadedKey.db[HAL_KEY_TYPE_EC_PRIVATE, curve].der, + HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k1.delete) k2 = hsm.pkey_load(HAL_KEY_TYPE_EC_PUBLIC, curve, - PreloadedKey.db[HAL_KEY_TYPE_EC_PUBLIC, curve].der) + PreloadedKey.db[HAL_KEY_TYPE_EC_PUBLIC, curve].der, + HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k2.delete) method(alg, k1, k2) @@ -484,9 +490,9 @@ class TestPKeyRSAInterop(TestCaseLoggedIn): hamster = "Your mother was a hamster" sk = PreloadedKey.db[HAL_KEY_TYPE_RSA_PRIVATE, keylen] vk = PreloadedKey.db[HAL_KEY_TYPE_RSA_PUBLIC, keylen] - k1 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PRIVATE, HAL_CURVE_NONE, sk.der) + k1 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PRIVATE, HAL_CURVE_NONE, sk.der, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k1.delete) - k2 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE, vk.der) + k2 = hsm.pkey_load(HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE, vk.der, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k2.delete) sig1 = k1.sign(hash = self.h(alg, hamster)) sig2 = sk.sign(hamster, pyhash) @@ -519,9 +525,9 @@ class TestPKeyECDSAInterop(TestCaseLoggedIn): hamster = "Your mother was a hamster" sk = PreloadedKey.db[HAL_KEY_TYPE_EC_PRIVATE, curve] vk = PreloadedKey.db[HAL_KEY_TYPE_EC_PUBLIC, curve] - k1 = hsm.pkey_load(HAL_KEY_TYPE_EC_PRIVATE, curve, sk.der) + k1 = hsm.pkey_load(HAL_KEY_TYPE_EC_PRIVATE, curve, sk.der, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k1.delete) - k2 = hsm.pkey_load(HAL_KEY_TYPE_EC_PUBLIC, curve, vk.der) + k2 = hsm.pkey_load(HAL_KEY_TYPE_EC_PUBLIC, curve, vk.der, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k2.delete) sig1 = k1.sign(hash = self.h(alg, hamster)) sig2 = sk.sign(hamster, pyhash) @@ -827,7 +833,7 @@ class TestPkeyECDSAVerificationNIST(TestCaseLoggedIn): def verify(self, Qx, Qy, H, r, s, hal_curve, py_curve, py_hash): Q = ECDSA_VerifyingKey.from_public_point(Point(py_curve.curve, Qx, Qy), py_curve, py_hash).to_der() - k = hsm.pkey_load(HAL_KEY_TYPE_EC_PUBLIC, hal_curve, Q) + k = hsm.pkey_load(HAL_KEY_TYPE_EC_PUBLIC, hal_curve, Q, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE) self.addCleanup(k.delete) k.verify(signature = (r + s).decode("hex"), data = H.decode("hex")) @@ -854,18 +860,6 @@ class TestPkeyECDSAVerificationNIST(TestCaseLoggedIn): py_hash = SHA384) -# Entire classes of tests still missing: -# -# * pkey attribute functions -# -# * pkey list and match functions -# -# * token vs session key tests -# -# Preloaded keys should suffice for all of these. - - - class Pinwheel(object): """ Activity pinwheel, as needed. @@ -891,13 +885,10 @@ class Pinwheel(object): class PreloadedKey(object): """ Keys for preload tests, here at the end because they're large. - For the moment, we use PKCS #1.5 format for RSA and secg format - for ECDSA, because those are the formats that everything - (including our own ASN.1 code) supports. Arguably, we should be - using PKCS #8 to get a single, consistent, self-identifying - private key format, but we're not there yet and it's not - particularly urgent given widespread availablity of conversion - tools (eg, "openssl pkcs8"). + These are now in PKCS #8 format, which gives us a single, + consistent, self-identifying private key format. See tools + like "openssl pkcs8" if you need to convert from some other format + (eg, PKCS #1 or secg). """ db = {} -- cgit v1.2.3