port to low level EC key functions
This will allow creating a fixed key for testing
This commit is contained in:
parent
ac5736a90f
commit
4f100956ac
4 changed files with 56 additions and 48 deletions
|
@ -22,6 +22,11 @@
|
||||||
#include "fpi-sdcp-device.h"
|
#include "fpi-sdcp-device.h"
|
||||||
|
|
||||||
#include <nss.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 <keyhi.h>
|
||||||
#include <keythi.h>
|
#include <keythi.h>
|
||||||
#include <pk11pub.h>
|
#include <pk11pub.h>
|
||||||
|
@ -36,12 +41,11 @@ typedef struct
|
||||||
GPtrArray *intermediate_cas;
|
GPtrArray *intermediate_cas;
|
||||||
|
|
||||||
/* Host random for the connection */
|
/* Host random for the connection */
|
||||||
guint8 host_random[32];
|
guint8 host_random[32];
|
||||||
|
|
||||||
NSSInitContext *nss_init_context;
|
NSSInitContext *nss_init_context;
|
||||||
PK11SlotInfo *slot;
|
PK11SlotInfo *slot;
|
||||||
SECKEYPrivateKey *host_key_private;
|
ECPrivateKey *host_key_private;
|
||||||
SECKEYPublicKey *host_key_public;
|
|
||||||
|
|
||||||
/* Master secret is required for reconnects.
|
/* Master secret is required for reconnects.
|
||||||
* TODO: We probably want to serialize this to disk so it can survive
|
* TODO: We probably want to serialize this to disk so it can survive
|
||||||
|
|
|
@ -84,11 +84,12 @@ fp_sdcp_device_finalize (GObject *object)
|
||||||
|
|
||||||
g_clear_pointer (&priv->intermediate_cas, g_ptr_array_unref);
|
g_clear_pointer (&priv->intermediate_cas, g_ptr_array_unref);
|
||||||
g_clear_pointer (&priv->slot, PK11_FreeSlot);
|
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->master_secret, PK11_FreeSymKey);
|
||||||
g_clear_pointer (&priv->mac_secret, PK11_FreeSymKey);
|
g_clear_pointer (&priv->mac_secret, PK11_FreeSymKey);
|
||||||
g_clear_pointer (&priv->nss_init_context, NSS_ShutdownContext);
|
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);
|
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,8 +360,9 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
|
||||||
G_GNUC_UNUSED g_autofree void * ec_params_data = NULL;
|
G_GNUC_UNUSED g_autofree void * ec_params_data = NULL;
|
||||||
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
SECOidData * oid_data;
|
PLArenaPool *arena = NULL;
|
||||||
SECKEYECParams ec_parameters;
|
ECParams ec_parameters = { NULL };
|
||||||
|
|
||||||
SECStatus r = SECSuccess;
|
SECStatus r = SECSuccess;
|
||||||
|
|
||||||
/* Disable loading p11-kit's user configuration */
|
/* Disable loading p11-kit's user configuration */
|
||||||
|
@ -382,8 +383,9 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
|
||||||
goto nss_error;
|
goto nss_error;
|
||||||
|
|
||||||
g_clear_pointer (&priv->slot, PK11_FreeSlot);
|
g_clear_pointer (&priv->slot, PK11_FreeSlot);
|
||||||
g_clear_pointer (&priv->host_key_private, SECKEY_DestroyPrivateKey);
|
if (priv->host_key_private)
|
||||||
g_clear_pointer (&priv->host_key_public, SECKEY_DestroyPublicKey);
|
PORT_FreeArena (priv->host_key_private->ecParams.arena, TRUE);
|
||||||
|
priv->host_key_private = NULL;
|
||||||
|
|
||||||
/* Create a slot for PK11 operation */
|
/* Create a slot for PK11 operation */
|
||||||
priv->slot = PK11_GetBestSlot (CKM_EC_KEY_PAIR_GEN, NULL);
|
priv->slot = PK11_GetBestSlot (CKM_EC_KEY_PAIR_GEN, NULL);
|
||||||
|
@ -392,24 +394,14 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
|
||||||
|
|
||||||
/* SDCP Connect: 3.i. Generate an ephemeral ECDH key pair */
|
/* SDCP Connect: 3.i. Generate an ephemeral ECDH key pair */
|
||||||
/* Look up the OID data for our curve. */
|
/* Look up the OID data for our curve. */
|
||||||
oid_data = SECOID_FindOIDByTag (SEC_OID_SECG_EC_SECP256R1);
|
|
||||||
if (!oid_data)
|
|
||||||
goto nss_error;
|
|
||||||
|
|
||||||
/* Copy into EC parameters */
|
arena = PORT_NewArena (NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||||
ec_parameters.len = oid_data->oid.len + 2;
|
EC_FillParams (arena, &SDCPECParamsDER, &ec_parameters);
|
||||||
ec_parameters.data = ec_params_data = g_malloc0 (oid_data->oid.len + 2);
|
r = EC_NewKey (&ec_parameters, &priv->host_key_private);
|
||||||
ec_parameters.data[0] = SEC_ASN1_OBJECT_ID;
|
PORT_FreeArena (arena, FALSE);
|
||||||
ec_parameters.data[1] = oid_data->oid.len;
|
arena = NULL;
|
||||||
memcpy (ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len);
|
|
||||||
|
|
||||||
priv->host_key_private = PK11_GenerateKeyPair (priv->slot, CKM_EC_KEY_PAIR_GEN,
|
if (r != SECSuccess)
|
||||||
&ec_parameters,
|
|
||||||
&priv->host_key_public,
|
|
||||||
FALSE, TRUE,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!priv->host_key_private || !priv->host_key_public)
|
|
||||||
goto nss_error;
|
goto nss_error;
|
||||||
|
|
||||||
/* SDCP Connect: 3.ii. Generate host random */
|
/* SDCP Connect: 3.ii. Generate host random */
|
||||||
|
@ -547,8 +539,8 @@ fpi_sdcp_device_get_connect_data (FpSdcpDevice *self,
|
||||||
|
|
||||||
*r_h = g_bytes_new (priv->host_random, sizeof (priv->host_random));
|
*r_h = g_bytes_new (priv->host_random, sizeof (priv->host_random));
|
||||||
|
|
||||||
g_assert (priv->host_key_public->u.ec.publicValue.len == 65);
|
g_assert (priv->host_key_private->publicValue.len == 65);
|
||||||
*pk_h = g_bytes_new (priv->host_key_public->u.ec.publicValue.data, priv->host_key_public->u.ec.publicValue.len);
|
*pk_h = g_bytes_new (priv->host_key_private->publicValue.data, priv->host_key_private->publicValue.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -776,13 +768,14 @@ fpi_sdcp_device_connect_complete (FpSdcpDevice *self,
|
||||||
g_autoptr(GBytes) claim_hash_bytes = NULL;
|
g_autoptr(GBytes) claim_hash_bytes = NULL;
|
||||||
g_autoptr(GBytes) claim_mac = NULL;
|
g_autoptr(GBytes) claim_mac = NULL;
|
||||||
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
SECKEYPublicKey firmware_key_public = { 0, };
|
SECItem pk_f;
|
||||||
SECKEYPublicKey device_key_public = { 0, };
|
SECKEYPublicKey device_key_public = { 0, };
|
||||||
SECKEYPublicKey *model_key_public = NULL;
|
SECKEYPublicKey *model_key_public = NULL;
|
||||||
HASHContext *hash_ctx;
|
HASHContext *hash_ctx;
|
||||||
guint8 hash_out[SHA256_LENGTH];
|
guint8 hash_out[SHA256_LENGTH];
|
||||||
guint hash_len = 0;
|
guint hash_len = 0;
|
||||||
FpiDeviceAction action;
|
FpiDeviceAction action;
|
||||||
|
SECItem a_raw = { 0 };
|
||||||
PK11SymKey *a = NULL;
|
PK11SymKey *a = NULL;
|
||||||
PK11SymKey *enc_secret = NULL;
|
PK11SymKey *enc_secret = NULL;
|
||||||
gsize length;
|
gsize length;
|
||||||
|
@ -823,26 +816,30 @@ fpi_sdcp_device_connect_complete (FpSdcpDevice *self,
|
||||||
|
|
||||||
/* Device key is of same type as host key */
|
/* Device key is of same type as host key */
|
||||||
g_assert (g_bytes_get_size (claim->pk_f) == 65);
|
g_assert (g_bytes_get_size (claim->pk_f) == 65);
|
||||||
firmware_key_public.keyType = priv->host_key_public->keyType;
|
pk_f.len = 65;
|
||||||
firmware_key_public.u.ec.DEREncodedParams = priv->host_key_public->u.ec.DEREncodedParams;
|
pk_f.data = (guint8 *) g_bytes_get_data (claim->pk_f, NULL);
|
||||||
firmware_key_public.u.ec.size = priv->host_key_public->u.ec.size;
|
|
||||||
firmware_key_public.u.ec.publicValue.len = 65;
|
|
||||||
firmware_key_public.u.ec.publicValue.type = priv->host_key_public->u.ec.publicValue.type;
|
|
||||||
firmware_key_public.u.ec.publicValue.data = (guint8 *) g_bytes_get_data (claim->pk_f, NULL);
|
|
||||||
|
|
||||||
/* SDCP Connect: 5.i. Perform key agreement */
|
/* SDCP Connect: 5.i. Perform key agreement */
|
||||||
a = PK11_PubDeriveWithKDF (priv->host_key_private,
|
r = ECDH_Derive (&pk_f,
|
||||||
&firmware_key_public,
|
&priv->host_key_private->ecParams,
|
||||||
TRUE,
|
&priv->host_key_private->privateValue,
|
||||||
NULL,
|
FALSE,
|
||||||
NULL,
|
&a_raw);
|
||||||
CKM_ECDH1_DERIVE,
|
if (r != SECSuccess)
|
||||||
CKM_SP800_108_COUNTER_KDF,
|
{
|
||||||
CKA_DERIVE,
|
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
32, /* 256 bit (HMAC) secret */
|
"Key agreement failed");
|
||||||
CKD_NULL,
|
goto out;
|
||||||
NULL,
|
}
|
||||||
NULL);
|
|
||||||
|
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;
|
||||||
|
|
||||||
if (!a)
|
if (!a)
|
||||||
{
|
{
|
||||||
|
|
|
@ -223,7 +223,13 @@ foreach i : driver_helpers
|
||||||
error('nss >=3.55 is required for SDCP support (@0@ and possibly others)'.format(driver))
|
error('nss >=3.55 is required for SDCP support (@0@ and possibly others)'.format(driver))
|
||||||
endif
|
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 += nss_dep
|
||||||
|
optional_deps += freebl_dep
|
||||||
elif i == 'udev'
|
elif i == 'udev'
|
||||||
install_udev_rules = true
|
install_udev_rules = true
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue