From 64bbdc81a2629a3b748051716788527779d8245d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 3 Nov 2020 18:12:33 +0100 Subject: [PATCH] sdcp-device: Use a key DB for testing --- libfprint/fp-sdcp-device-private.h | 14 ++- libfprint/fp-sdcp-device.c | 5 +- libfprint/fpi-sdcp-device.c | 136 ++++++++++++++++++----------- meson.build | 6 -- tests/meson.build | 3 + tests/sdcp-key-db/cert9.db | Bin 0 -> 28672 bytes tests/sdcp-key-db/key4.db | Bin 0 -> 36864 bytes 7 files changed, 93 insertions(+), 71 deletions(-) create mode 100644 tests/sdcp-key-db/cert9.db create mode 100644 tests/sdcp-key-db/key4.db 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 -#pragma GCC diagnostic push -/* blapi.h is missing a void in a function declaration with no arguments */ -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#include -#pragma GCC diagnostic pop #include #include #include @@ -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,46 +423,85 @@ 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 - }; + /* 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); + } - r = EC_NewKeyFromSeed (&ec_parameters, - &priv->host_key_private, - ecdsa_known_seed, - sizeof (ecdsa_known_seed)); +#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; - PORT_FreeArena (arena, FALSE); - arena = NULL; + priv->host_key_private = PK11_GenerateKeyPair (priv->slot, CKM_EC_KEY_PAIR_GEN, + (SECItem *) &SDCPECParamsDER, + &priv->host_key_public, + FALSE, TRUE, + 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 8ce72da..b5ad747 100644 --- a/meson.build +++ b/meson.build @@ -223,13 +223,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 60f9225..2672f47 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -75,6 +75,7 @@ if get_option('introspection') suite: ut_suite, depends: libfprint_typelib, env: envs, + workdir: meson.current_source_dir(), ) endforeach else @@ -115,6 +116,7 @@ if get_option('introspection') suite: ut_suite, depends: libfprint_typelib, env: sdcp_envs, + workdir: meson.current_source_dir(), ) endforeach else @@ -139,6 +141,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 0000000000000000000000000000000000000000..221ac06e5992db71412cc80a171e2bcb5e9ae59c GIT binary patch literal 28672 zcmeI4UuauZ9LLY?O_OD96DgD6AIL!v%-H0ddvDV0L0#HK4c4~nTC{?co8)$6rX5>S z7(U4K!6Bmfus6ZsgY(Z2hM*Q?;EO(r*cTr}d~!v>hxy`Upy&6y_a<%J9(~Eax4Ea^ z^ZT9O_nh;|ZQwR-P8^?YbpyF}`s}*jm9Dr)Se7^{r4VA&oGEk02lW$i$9%VT={w0$ z@#s?@O=SNP$^AQG?9c2sV^_ycjU6-{93TJ!AOHd&00JNY0wC}|5;&Sn=5l#!rM1xv z&NW{0Tg{D5XJND6ZZ%Rfi`B|fRo3Q?RiBrflk;=3mzR(DS~-QsN7-SS9ol|9X!k}W z_c(BF(7`PnOC)m-yrx^Q9MO6Br->+SWfUvCG!@}3xpe3mNHv(?=kT1~mISbMgzxFVmauE^!N+VSNo z%`h`R_vCDCW=U42=NFd_Nne>$o6|9;OPT`|(G)6Ew@lqKcWFr3qoznriJB>D%G4a8 z#;2xknj>tb!j>Hsd1w{RLoQm8jaKBN6&YzoPFj(bR^+7>nQ7IaHdvFBjwI$A$I9uXuiL<3J%g!Zsp5l>ANi!yg_vv#wM@k0f)|yd}bymNRX0N5ATCc29GEwfA$qs(aEl zFSYyV<#xiHR_3NK4;&x>0w4eaAOHd&00JNY0w4eaATWFcUQ1XnCk|vXa&T)0COwfc zUqWOunaRn)G=Ogq^zaz5vME<+?lEBVE00ck)1V8`;KmY_l00ck)1crt{&i2x``)I*`0V}4oUH||9 literal 0 HcmV?d00001 diff --git a/tests/sdcp-key-db/key4.db b/tests/sdcp-key-db/key4.db new file mode 100644 index 0000000000000000000000000000000000000000..b27f777bd59e0e5fa1ea125f46a2ffe646b042e3 GIT binary patch literal 36864 zcmeI5du&rx9LMi%yLRoic8*~kbMX!xvdQDzN4r8Wu$2OXJ-ZQ}vAf;6S=TXGJHTiR z9fn6l0ud7g;~>aj5LrOQp%O_5qW_3-21Ic9h%hlhAw0w&c+R=^dbf;4{13nUl=GIAPAe|*R&jn`d2xZ)H-^K1nKtsulaM<;(d_hQu}pYTZD@IPNdz|r6#lz>W_Oljeb~d}di5@cDKvxFUN;zzL{9X=RL1CG{Y78eM zyyN303wRfarU4S+NytO09#ZwtD(T{pNZ}%dn-uw^@Q`8xDP&RvaWR2fA*G~_hQ-8*vzt2S)1H(PPcaE}y#gX*1-f2=<}A{< zNaG@nOEeA_8t;N zv~x|!B}$@;bWkPfph_~kDoF~eB&$^=S+Xh#QB@MGills0sSl&1)Tlnp-Dem%Bua;T zJ%@ZP2e+OtmRi18YJIWn(^s1qN40#h)F#GKn;1)NVl2t2MsmQCoNuZmC!H#5bs5rS z-9M6^G)mu~o=%XYQ|ppZZ4jYc(O`B?&mQatqy8Nn;B{@pzfls&Zx{*AbX z8*nQ(Ab#(GxP8RMC7rmxk!8F^Tr3ogg%{PM_;%E2w&tyxvFb(&n~;L4QGs4fMv{rU z9Zkv0cw$)DxOpw@mBSXWC7Ux+d(w7n_+;V!<9p4YdkrjWU^!$nCn_!mE6Oxmt5?ln zLq-#uXR@FA<$~?A#S<4)Sx@g;cgBR;(=YDXw(;?+ug69tMl5g4Kf3YFzalTL?d*Ky z&O^b9yx%9-zFz%X&Ec$-$2wa_GCPAL=bg;_#^oPuy0AU;=Qqi1Tg&GhDBtkW;db1_ zGAwSy5B#P(%hDvic-qKXOkLfDy(>m0UlKOm`E|vs^}!?JE5f00e*l z5C8&{fYHcUmFxeTjN>Li0Rlh(2mk>f00e*l5C8%|00;m9AOHl0909X2&5Hk@K)L?E z!Z@xBxfQ~KfB+Bx0zd!=00AHX1b_e#00KY&2t2?9QjDBczcqq#{ol(tdLLjUuyh~* z1b_e#00KY&2mk>f00e*l5C8&0gn-j1S?_jlL300pgZ(|mF&7uG0RbQY1b_e#00KY& z2mk>f00e*l5V(&B#Ip?vlUvi6Xt+Mm5PCkq%ON?Rm+J!RM-uWVz5*@OZ}4wNWdrW_ zzwXRLXWNrawhr&16XP;23)hd_EX>ULY1G^MoR(|1I@a9fe*b;${cqx4KK<_Y$|Xym z?SA;iHF3Y|*x4;xO8mzqkA2QF{P}O=mGK-lAxmmaUo1zX%bJ>N&t=YBm~*ge-?H{? z-<|w%%ctX#W1|CoVU%-k#XdQ+VWD-N9*#OO`c`k2w4vPXFO9 zY4-nEg3(iB_3J<0yug!-WEm&3gT6XqNHS(wwbv#71_Pn10RR91 literal 0 HcmV?d00001