sdcp-device: Use predictable keys and random numbers for testing
If FP_DEVICE_EMULATION is set, then switch to using predictable EC ephemeral key and random numbers. This should allow recording and replaying real device interactions using umockdev.
This commit is contained in:
parent
4f100956ac
commit
d6dc3403d8
2 changed files with 84 additions and 19 deletions
|
@ -23,6 +23,7 @@
|
||||||
#include <sechash.h>
|
#include <sechash.h>
|
||||||
#include <cert.h>
|
#include <cert.h>
|
||||||
|
|
||||||
|
#include "fpi-compat.h"
|
||||||
#include "fp-sdcp-device-private.h"
|
#include "fp-sdcp-device-private.h"
|
||||||
#include "fpi-sdcp-device.h"
|
#include "fpi-sdcp-device.h"
|
||||||
#include "fpi-print.h"
|
#include "fpi-print.h"
|
||||||
|
@ -156,6 +157,47 @@ fp_sdcp_device_get_instance_private (FpSdcpDevice *self)
|
||||||
g_type_class_get_instance_private_offset (sdcp_class));
|
g_type_class_get_instance_private_offset (sdcp_class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_generate_random:
|
||||||
|
* @buffer: Buffer to place random bytes into
|
||||||
|
* @len: Number of bytes to generate
|
||||||
|
* @error: Error out
|
||||||
|
*
|
||||||
|
* Returns: #TRUE on success
|
||||||
|
**/
|
||||||
|
FP_GNUC_ACCESS (write_only, 1, 2)
|
||||||
|
static gboolean
|
||||||
|
fpi_sdcp_generate_random (guint8 *buffer, gsize len, GError **error)
|
||||||
|
{
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
static guint8 emulation_rand = 0;
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
buffer[i] = emulation_rand;
|
||||||
|
emulation_rand += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generating random numbers is basic enough to assume it works */
|
||||||
|
if (PK11_GenerateRandom (buffer, len) != SECSuccess)
|
||||||
|
{
|
||||||
|
g_propagate_error (error,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
|
"Error generating random numbers using NSS!"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_sdcp_kdf:
|
* fpi_sdcp_kdf:
|
||||||
* @self: The #FpSdcpDevice
|
* @self: The #FpSdcpDevice
|
||||||
|
@ -236,7 +278,6 @@ fpi_sdcp_kdf (FpSdcpDevice *self,
|
||||||
data_param[kdf_params.ulNumberOfDataParams].ulValueLen = sizeof (length_format);
|
data_param[kdf_params.ulNumberOfDataParams].ulValueLen = sizeof (length_format);
|
||||||
kdf_params.ulNumberOfDataParams += 1;
|
kdf_params.ulNumberOfDataParams += 1;
|
||||||
|
|
||||||
/* TODO: support a second key out (may be discarded) */
|
|
||||||
kdf_params.ulAdditionalDerivedKeys = 0;
|
kdf_params.ulAdditionalDerivedKeys = 0;
|
||||||
kdf_params.pAdditionalDerivedKeys = NULL;
|
kdf_params.pAdditionalDerivedKeys = NULL;
|
||||||
if (out_key_2)
|
if (out_key_2)
|
||||||
|
@ -362,6 +403,7 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
|
||||||
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
PLArenaPool *arena = NULL;
|
PLArenaPool *arena = NULL;
|
||||||
ECParams ec_parameters = { NULL };
|
ECParams ec_parameters = { NULL };
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
SECStatus r = SECSuccess;
|
SECStatus r = SECSuccess;
|
||||||
|
|
||||||
|
@ -397,7 +439,30 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
|
||||||
|
|
||||||
arena = PORT_NewArena (NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
arena = PORT_NewArena (NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||||
EC_FillParams (arena, &SDCPECParamsDER, &ec_parameters);
|
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));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
r = EC_NewKey (&ec_parameters, &priv->host_key_private);
|
r = EC_NewKey (&ec_parameters, &priv->host_key_private);
|
||||||
|
}
|
||||||
|
|
||||||
PORT_FreeArena (arena, FALSE);
|
PORT_FreeArena (arena, FALSE);
|
||||||
arena = NULL;
|
arena = NULL;
|
||||||
|
|
||||||
|
@ -405,9 +470,13 @@ fpi_sdcp_device_connect (FpSdcpDevice *self)
|
||||||
goto nss_error;
|
goto nss_error;
|
||||||
|
|
||||||
/* SDCP Connect: 3.ii. Generate host random */
|
/* SDCP Connect: 3.ii. Generate host random */
|
||||||
r = PK11_GenerateRandom (priv->host_random, sizeof (priv->host_random));
|
if (!fpi_sdcp_generate_random (priv->host_random, sizeof (priv->host_random), &error))
|
||||||
if (r != SECSuccess)
|
{
|
||||||
goto nss_error;
|
fpi_sdcp_device_connect_complete (self,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* SDCP Connect: 3.iii. Send the Connect message */
|
/* SDCP Connect: 3.iii. Send the Connect message */
|
||||||
cls->connect (self);
|
cls->connect (self);
|
||||||
|
@ -428,16 +497,13 @@ fpi_sdcp_device_reconnect (FpSdcpDevice *self)
|
||||||
{
|
{
|
||||||
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);
|
||||||
SECStatus r;
|
GError *error = NULL;
|
||||||
|
|
||||||
/* SDCP Reconnect: 2.i. Generate host random */
|
/* SDCP Reconnect: 2.i. Generate host random */
|
||||||
r = PK11_GenerateRandom (priv->host_random, sizeof (priv->host_random));
|
if (!fpi_sdcp_generate_random (priv->host_random, sizeof (priv->host_random), &error))
|
||||||
if (r != SECSuccess)
|
|
||||||
{
|
{
|
||||||
fpi_sdcp_device_reconnect_complete (self,
|
fpi_sdcp_device_reconnect_complete (self, NULL, error);
|
||||||
NULL,
|
return;
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
||||||
"Error calling NSS crypto routine: %d", r));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SDCP Reconnect: 2.ii. Send the Reconnect message */
|
/* SDCP Reconnect: 2.ii. Send the Reconnect message */
|
||||||
|
@ -473,7 +539,7 @@ fpi_sdcp_device_identify (FpSdcpDevice *self)
|
||||||
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
FpiDeviceAction action;
|
FpiDeviceAction action;
|
||||||
SECStatus r;
|
GError *error = NULL;
|
||||||
|
|
||||||
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||||
|
@ -481,12 +547,9 @@ fpi_sdcp_device_identify (FpSdcpDevice *self)
|
||||||
g_return_if_fail (action == FPI_DEVICE_ACTION_IDENTIFY || action == FPI_DEVICE_ACTION_VERIFY);
|
g_return_if_fail (action == FPI_DEVICE_ACTION_IDENTIFY || action == FPI_DEVICE_ACTION_VERIFY);
|
||||||
|
|
||||||
/* Generate a new nonce. */
|
/* Generate a new nonce. */
|
||||||
r = PK11_GenerateRandom (priv->host_random, sizeof (priv->host_random));
|
if (!fpi_sdcp_generate_random (priv->host_random, sizeof (priv->host_random), &error))
|
||||||
if (r != SECSuccess)
|
|
||||||
{
|
{
|
||||||
fpi_device_action_error (FP_DEVICE (self),
|
fpi_device_action_error (FP_DEVICE (self), error);
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
||||||
"Error calling NSS crypto routine: %d", r));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,8 @@ if get_option('introspection')
|
||||||
unit_tests = ['virtual-sdcp']
|
unit_tests = ['virtual-sdcp']
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
sdcp_envs = envs
|
||||||
|
sdcp_envs.set('FP_DEVICE_EMULATION', '0')
|
||||||
foreach ut: unit_tests
|
foreach ut: unit_tests
|
||||||
ut_suite = suite
|
ut_suite = suite
|
||||||
ut_args = base_args
|
ut_args = base_args
|
||||||
|
@ -112,7 +114,7 @@ if get_option('introspection')
|
||||||
args: ut_args,
|
args: ut_args,
|
||||||
suite: ut_suite,
|
suite: ut_suite,
|
||||||
depends: libfprint_typelib,
|
depends: libfprint_typelib,
|
||||||
env: envs,
|
env: sdcp_envs,
|
||||||
)
|
)
|
||||||
endforeach
|
endforeach
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue