summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2020-11-03 18:12:33 +0100
committerBenjamin Berg <bberg@redhat.com>2022-02-14 17:20:00 +0100
commitf2dfa2ae0a1d85643aacd86878a5fe7b3fc97574 (patch)
treeffde9bb8effcfa95bfe10b9e1ceadb0d0087c05b
parent67723675d2cd15488826c261b252ebd003502be5 (diff)
sdcp-device: Use a key DB for testingfeature/sdcp
-rw-r--r--libfprint/fp-sdcp-device-private.h14
-rw-r--r--libfprint/fp-sdcp-device.c5
-rw-r--r--libfprint/fpi-sdcp-device.c138
-rw-r--r--meson.build6
-rw-r--r--tests/meson.build3
-rw-r--r--tests/sdcp-key-db/cert9.dbbin0 -> 28672 bytes
-rw-r--r--tests/sdcp-key-db/key4.dbbin0 -> 36864 bytes
7 files changed, 94 insertions, 72 deletions
diff --git a/libfprint/fp-sdcp-device-private.h b/libfprint/fp-sdcp-device-private.h
index 22f9482..249c33c 100644
--- a/libfprint/fp-sdcp-device-private.h
+++ b/libfprint/fp-sdcp-device-private.h
@@ -22,11 +22,6 @@
#include "fpi-sdcp-device.h"
#include <nss.h>
-#pragma GCC diagnostic push
-/* blapi.h is missing a void in a function declaration with no arguments */
-#pragma GCC diagnostic ignored "-Wstrict-prototypes"
-#include <blapi.h>
-#pragma GCC diagnostic pop
#include <keyhi.h>
#include <keythi.h>
#include <pk11pub.h>
@@ -41,11 +36,12 @@ typedef struct
GPtrArray *intermediate_cas;
/* Host random for the connection */
- guint8 host_random[32];
+ guint8 host_random[32];
- NSSInitContext *nss_init_context;
- PK11SlotInfo *slot;
- ECPrivateKey *host_key_private;
+ NSSInitContext *nss_init_context;
+ PK11SlotInfo *slot;
+ SECKEYPrivateKey *host_key_private;
+ SECKEYPublicKey *host_key_public;
/* Master secret is required for reconnects.
* TODO: We probably want to serialize this to disk so it can survive
diff --git a/libfprint/fp-sdcp-device.c b/libfprint/fp-sdcp-device.c
index 43378d8..4cdac4e 100644
--- a/libfprint/fp-sdcp-device.c
+++ b/libfprint/fp-sdcp-device.c
@@ -84,12 +84,11 @@ fp_sdcp_device_finalize (GObject *object)
g_clear_pointer (&priv->intermediate_cas, g_ptr_array_unref);
g_clear_pointer (&priv->slot, PK11_FreeSlot);
+ g_clear_pointer (&priv->host_key_private, SECKEY_DestroyPrivateKey);
+ g_clear_pointer (&priv->host_key_public, SECKEY_DestroyPublicKey);
g_clear_pointer (&priv->master_secret, PK11_FreeSymKey);
g_clear_pointer (&priv->mac_secret, PK11_FreeSymKey);
g_clear_pointer (&priv->nss_init_context, NSS_ShutdownContext);
- if (priv->host_key_private)
- PORT_FreeArena (priv->host_key_private->ecParams.arena, TRUE);
- priv->host_key_private = NULL;
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->finalize (object);
}
diff --git a/libfprint/fpi-sdcp-device.c b/libfprint/fpi-sdcp-device.c
index 3a6e9fe..f594cca 100644
--- a/libfprint/fpi-sdcp-device.c
+++ b/libfprint/fpi-sdcp-device.c
@@ -401,8 +401,6 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
G_GNUC_UNUSED g_autofree void * ec_params_data = NULL;
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
- PLArenaPool *arena = NULL;
- ECParams ec_parameters = { NULL };
GError *error = NULL;
SECStatus r = SECSuccess;
@@ -425,47 +423,86 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
goto nss_error;
g_clear_pointer (&priv->slot, PK11_FreeSlot);
- if (priv->host_key_private)
- PORT_FreeArena (priv->host_key_private->ecParams.arena, TRUE);
+ g_clear_pointer (&priv->host_key_private, SECKEY_DestroyPrivateKey);
+ g_clear_pointer (&priv->host_key_public, SECKEY_DestroyPublicKey);
priv->host_key_private = NULL;
- /* Create a slot for PK11 operation */
- priv->slot = PK11_GetBestSlot (CKM_EC_KEY_PAIR_GEN, NULL);
- if (priv->slot == NULL)
- goto nss_error;
-
/* SDCP Connect: 3.i. Generate an ephemeral ECDH key pair */
/* Look up the OID data for our curve. */
- arena = PORT_NewArena (NSS_FREEBL_DEFAULT_CHUNKSIZE);
- EC_FillParams (arena, &SDCPECParamsDER, &ec_parameters);
-
/* Just use a counter in emulation mode. Not random, but all
* we need is something predictable and not repeating immediately.
*/
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
{
- /* ECDSA Known Seed info for curves nistp256 and nistk283 */
- static const PRUint8 ecdsa_known_seed[] = {
- 0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11,
- 0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1,
- 0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc,
- 0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f
- };
-
- r = EC_NewKeyFromSeed (&ec_parameters,
- &priv->host_key_private,
- ecdsa_known_seed,
- sizeof (ecdsa_known_seed));
+ /* To generate, use the #if 0 code below and remove the readOnly flag */
+ priv->slot = SECMOD_OpenUserDB ("configdir='sdcp-key-db' tokenDescription='libfprint CI testing' flags=readOnly");
+ if (!priv->slot)
+ {
+ g_message ("Could not open key DB for testing");
+ exit (77);
+ }
+
+#if 0
+ if (PK11_NeedUserInit (priv->slot))
+ if (PK11_InitPin (priv->slot, "", "") != SECSuccess)
+ goto nss_error;
+
+ if (priv->slot == NULL)
+ goto nss_error;
+ g_debug ("logged in: %i, need: %i", PK11_IsLoggedIn (priv->slot, NULL), PK11_NeedLogin (priv->slot));
+ g_debug ("read only: %i", PK11_IsReadOnly (priv->slot));
+ g_debug ("need user init: %i", PK11_NeedUserInit (priv->slot));
+ //PK11_SetPasswordFunc (pwfunc);
+
+ /* SDCP Connect: 3.i. Generate an ephemeral ECDH key pair */
+ /* Look up the OID data for our curve. */
+ oid_data = SECOID_FindOIDByTag (SEC_OID_SECG_EC_SECP256R1);
+ if (!oid_data)
+ goto nss_error;
+
+ priv->host_key_private = PK11_GenerateKeyPair (priv->slot, CKM_EC_KEY_PAIR_GEN,
+ (SECItem *) &SDCPECParamsDER,
+ &priv->host_key_public,
+ TRUE, FALSE,
+ NULL);
+
+ PK11_SetPrivateKeyNickname (priv->host_key_private, "CI testing");
+ PK11_SetPublicKeyNickname (priv->host_key_public, "CI testing");
+#else
+
+ g_assert (!PK11_NeedUserInit (priv->slot));
+ g_assert (PK11_IsReadOnly (priv->slot));
+
+ SECKEYPrivateKeyList *priv_key_list = NULL;
+ SECKEYPublicKeyList *pub_key_list = NULL;
+
+ priv_key_list = PK11_ListPrivKeysInSlot (priv->slot, (char *) "CI testing", NULL);
+ pub_key_list = PK11_ListPublicKeysInSlot (priv->slot, (char *) "CI testing");
+ g_assert (priv_key_list != NULL && pub_key_list != NULL);
+ g_assert (!PR_CLIST_IS_EMPTY (&priv_key_list->list) && !PR_CLIST_IS_EMPTY (&pub_key_list->list));
+
+ priv->host_key_private = SECKEY_CopyPrivateKey (((SECKEYPrivateKeyListNode *) PR_LIST_HEAD (&priv_key_list->list))->key);
+ priv->host_key_public = SECKEY_CopyPublicKey (((SECKEYPublicKeyListNode *) PR_LIST_HEAD (&pub_key_list->list))->key);
+
+ SECKEY_DestroyPrivateKeyList (priv_key_list);
+ SECKEY_DestroyPublicKeyList (pub_key_list);
+#endif
}
else
{
- r = EC_NewKey (&ec_parameters, &priv->host_key_private);
+ /* Create a slot for PK11 operation */
+ priv->slot = PK11_GetBestSlot (CKM_EC_KEY_PAIR_GEN, NULL);
+ if (priv->slot == NULL)
+ goto nss_error;
+
+ priv->host_key_private = PK11_GenerateKeyPair (priv->slot, CKM_EC_KEY_PAIR_GEN,
+ (SECItem *) &SDCPECParamsDER,
+ &priv->host_key_public,
+ FALSE, TRUE,
+ NULL);
}
- PORT_FreeArena (arena, FALSE);
- arena = NULL;
-
if (r != SECSuccess)
goto nss_error;
@@ -602,8 +639,8 @@ fpi_sdcp_device_get_connect_data (FpSdcpDevice *self,
*r_h = g_bytes_new (priv->host_random, sizeof (priv->host_random));
- g_assert (priv->host_key_private->publicValue.len == 65);
- *pk_h = g_bytes_new (priv->host_key_private->publicValue.data, priv->host_key_private->publicValue.len);
+ g_assert (priv->host_key_public->u.ec.publicValue.len == 65);
+ *pk_h = g_bytes_new (priv->host_key_public->u.ec.publicValue.data, priv->host_key_public->u.ec.publicValue.len);
}
/**
@@ -831,14 +868,13 @@ fpi_sdcp_device_connect_complete (FpSdcpDevice *self,
g_autoptr(GBytes) claim_hash_bytes = NULL;
g_autoptr(GBytes) claim_mac = NULL;
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
- SECItem pk_f;
+ SECKEYPublicKey firmware_key_public = { 0, };
SECKEYPublicKey device_key_public = { 0, };
SECKEYPublicKey *model_key_public = NULL;
HASHContext *hash_ctx;
guint8 hash_out[SHA256_LENGTH];
guint hash_len = 0;
FpiDeviceAction action;
- SECItem a_raw = { 0 };
PK11SymKey *a = NULL;
PK11SymKey *enc_secret = NULL;
gsize length;
@@ -879,30 +915,24 @@ fpi_sdcp_device_connect_complete (FpSdcpDevice *self,
/* Device key is of same type as host key */
g_assert (g_bytes_get_size (claim->pk_f) == 65);
- pk_f.len = 65;
- pk_f.data = (guint8 *) g_bytes_get_data (claim->pk_f, NULL);
+ firmware_key_public.keyType = ecKey;
+ firmware_key_public.u.ec.DEREncodedParams = SDCPECParamsDER;
+ firmware_key_public.u.ec.publicValue.len = 65;
+ firmware_key_public.u.ec.publicValue.data = (guint8 *) g_bytes_get_data (claim->pk_f, NULL);
/* SDCP Connect: 5.i. Perform key agreement */
- r = ECDH_Derive (&pk_f,
- &priv->host_key_private->ecParams,
- &priv->host_key_private->privateValue,
- FALSE,
- &a_raw);
- if (r != SECSuccess)
- {
- error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
- "Key agreement failed");
- goto out;
- }
-
- a = PK11_ImportSymKey (priv->slot,
- CKM_SP800_108_COUNTER_KDF,
- PK11_OriginDerive,
- CKA_DERIVE,
- &a_raw,
- NULL);
- g_clear_pointer (&a_raw.data, PORT_Free);
- a_raw.len = 0;
+ a = PK11_PubDeriveWithKDF (priv->host_key_private,
+ &firmware_key_public,
+ TRUE,
+ NULL,
+ NULL,
+ CKM_ECDH1_DERIVE,
+ CKM_SP800_108_COUNTER_KDF,
+ CKA_DERIVE,
+ 32, /* 256 bit (HMAC) secret */
+ CKD_NULL,
+ NULL,
+ NULL);
if (!a)
{
diff --git a/meson.build b/meson.build
index 9232c31..944d899 100644
--- a/meson.build
+++ b/meson.build
@@ -225,13 +225,7 @@ foreach i : driver_helpers
error('nss >=3.55 is required for SDCP support (@0@ and possibly others)'.format(driver))
endif
- freebl_dep = cc.find_library('freebl', required: false)
- if not freebl_dep.found()
- error('The static freebl library from nss is required for SDCP support (@0@ and possibly others)'.format(driver))
- endif
-
optional_deps += nss_dep
- optional_deps += freebl_dep
elif i == 'udev'
install_udev_rules = true
diff --git a/tests/meson.build b/tests/meson.build
index c56f32d..b39a608 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -91,6 +91,7 @@ if get_option('introspection')
suite: ut_suite,
depends: libfprint_typelib,
env: envs,
+ workdir: meson.current_source_dir(),
)
endforeach
else
@@ -131,6 +132,7 @@ if get_option('introspection')
suite: ut_suite,
depends: libfprint_typelib,
env: sdcp_envs,
+ workdir: meson.current_source_dir(),
)
endforeach
else
@@ -151,6 +153,7 @@ if get_option('introspection')
find_program('umockdev-test.py'),
args: join_paths(meson.current_source_dir(), driver_test),
env: driver_envs,
+ workdir: meson.current_source_dir(),
suite: ['drivers'],
timeout: 15,
depends: libfprint_typelib,
diff --git a/tests/sdcp-key-db/cert9.db b/tests/sdcp-key-db/cert9.db
new file mode 100644
index 0000000..221ac06
--- /dev/null
+++ b/tests/sdcp-key-db/cert9.db
Binary files differ
diff --git a/tests/sdcp-key-db/key4.db b/tests/sdcp-key-db/key4.db
new file mode 100644
index 0000000..b27f777
--- /dev/null
+++ b/tests/sdcp-key-db/key4.db
Binary files differ