feat(torture_sk): add functions to validate security key signatures and to create PKI context

Signed-off-by: Praneeth Sarode <praneethsarode@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
This commit is contained in:
Praneeth Sarode
2025-10-23 22:31:20 +05:30
parent 1241a3a8c9
commit 5937b5ba4e
2 changed files with 193 additions and 2 deletions

View File

@@ -23,6 +23,7 @@
#include "torture_sk.h"
#include "libssh/pki.h"
#include "libssh/pki_priv.h"
#include "libssh/sk_api.h" /* For SSH_SK_* flag definitions */
void assert_sk_key_valid(ssh_key key,
@@ -100,6 +101,150 @@ void assert_sk_key_valid(ssh_key key,
}
}
void assert_sk_signature_valid(ssh_signature signature,
enum ssh_keytypes_e expected_type,
ssh_key signing_key,
const uint8_t *data,
size_t data_len)
{
uint8_t valid_flags;
const char *expected_type_str = NULL;
ssh_string sig_blob = NULL;
ssh_signature reconstructed = NULL;
ssh_buffer sk_sig_buffer = NULL;
int rc;
/* Basic null and type validation */
assert_non_null(signature);
assert_int_equal(signature->type, expected_type);
/* Validate hash type is appropriate for security keys */
switch (expected_type) {
case SSH_KEYTYPE_SK_ECDSA:
assert_int_equal(signature->hash_type, SSH_DIGEST_SHA256);
break;
case SSH_KEYTYPE_SK_ED25519:
assert_int_equal(signature->hash_type, SSH_DIGEST_AUTO);
break;
default:
/* Should not reach here */
assert_true(0);
break;
}
expected_type_str = ssh_key_type_to_char(expected_type);
assert_non_null(signature->type_c);
assert_string_equal(signature->type_c, expected_type_str);
/* Check that only valid SK flags are set */
valid_flags = SSH_SK_USER_PRESENCE_REQD | SSH_SK_USER_VERIFICATION_REQD;
assert_int_equal(signature->sk_flags & ~valid_flags, 0);
assert_true(signature->sk_flags & SSH_SK_USER_PRESENCE_REQD);
assert_true(signature->sk_counter > 0);
assert_non_null(signature->raw_sig);
assert_true(ssh_string_len(signature->raw_sig) > 0);
rc = ssh_pki_export_signature_blob(signature, &sig_blob);
assert_int_equal(rc, SSH_OK);
assert_non_null(sig_blob);
assert_non_null(signing_key);
rc = ssh_pki_import_signature_blob(sig_blob, signing_key, &reconstructed);
assert_int_equal(rc, SSH_OK);
assert_non_null(reconstructed);
rc = pki_sk_signature_buffer_prepare(signing_key,
reconstructed,
data,
data_len,
&sk_sig_buffer);
assert_int_equal(rc, SSH_OK);
assert_non_null(sk_sig_buffer);
rc = pki_verify_data_signature(reconstructed,
signing_key,
ssh_buffer_get(sk_sig_buffer),
ssh_buffer_get_len(sk_sig_buffer));
assert_int_equal(rc, SSH_OK);
SSH_BUFFER_FREE(sk_sig_buffer);
ssh_signature_free(reconstructed);
ssh_string_free(sig_blob);
}
ssh_pki_ctx
torture_create_sk_pki_ctx(const char *application,
uint8_t flags,
const void *challenge_data,
size_t challenge_len,
ssh_auth_callback pin_callback,
const char *device_path,
const char *user_id,
const struct ssh_sk_callbacks_struct *sk_callbacks)
{
ssh_pki_ctx ctx = NULL;
ssh_buffer challenge_buffer = NULL;
int rc;
ctx = ssh_pki_ctx_new();
assert_non_null(ctx);
rc = ssh_pki_ctx_options_set(ctx,
SSH_PKI_OPTION_SK_APPLICATION,
application);
assert_int_equal(rc, SSH_OK);
rc = ssh_pki_ctx_options_set(ctx, SSH_PKI_OPTION_SK_FLAGS, &flags);
assert_int_equal(rc, SSH_OK);
if (challenge_data != NULL && challenge_len > 0) {
challenge_buffer = ssh_buffer_new();
assert_non_null(challenge_buffer);
rc = ssh_buffer_add_data(challenge_buffer,
challenge_data,
challenge_len);
assert_int_equal(rc, SSH_OK);
}
rc = ssh_pki_ctx_options_set(ctx,
SSH_PKI_OPTION_SK_CHALLENGE,
challenge_buffer);
assert_int_equal(rc, SSH_OK);
SSH_BUFFER_FREE(challenge_buffer);
rc = ssh_pki_ctx_set_sk_pin_callback(ctx, pin_callback, NULL);
assert_int_equal(rc, SSH_OK);
if (device_path != NULL) {
rc = ssh_pki_ctx_sk_callbacks_option_set(ctx,
SSH_SK_OPTION_NAME_DEVICE_PATH,
device_path,
false);
assert_int_equal(rc, SSH_OK);
}
if (user_id != NULL) {
rc = ssh_pki_ctx_sk_callbacks_option_set(ctx,
SSH_SK_OPTION_NAME_USER_ID,
user_id,
false);
assert_int_equal(rc, SSH_OK);
}
if (sk_callbacks != NULL) {
rc = ssh_pki_ctx_options_set(ctx,
SSH_PKI_OPTION_SK_CALLBACKS,
sk_callbacks);
assert_int_equal(rc, SSH_OK);
}
return ctx;
}
void assert_sk_enroll_response(struct sk_enroll_response *response, int flags)
{
assert_non_null(response);

View File

@@ -28,9 +28,10 @@
#define LIBSSH_STATIC
#include "torture.h"
#include "libssh/callbacks.h"
#include "libssh/pki.h"
#include "torture.h"
#include "torture_pki.h"
/**
* @brief Validate a security key (ssh_key) structure
@@ -46,6 +47,51 @@ void assert_sk_key_valid(ssh_key key,
enum ssh_keytypes_e expected_type,
bool private);
/**
* @brief Validate a security key signature structure
*
* Checks that the signature is not NULL, matches the expected key type, and
* other internal fields. Also verifies that the signature was produced by the
* given signing key.
*
* @param[in] signature The signature to validate
* @param[in] expected_type The expected key type (e.g., SSH_KEYTYPE_SK_ECDSA)
* @param[in] signing_key The key that should have produced the signature
* @param[in] data The signed data buffer
* @param[in] data_len Length of the signed data
*/
void assert_sk_signature_valid(ssh_signature signature,
enum ssh_keytypes_e expected_type,
ssh_key signing_key,
const uint8_t *data,
size_t data_len);
/**
* @brief Create and initialize a PKI context configured for security key
* operations.
*
* Parameters:
* @param[in] application Application string
* @param[in] flags SK flags
* @param[in] challenge_data Optional challenge bytes (may be NULL)
* @param[in] challenge_len Length of challenge_data
* @param[in] pin_callback Callback used to obtain the PIN (may be NULL)
* @param[in] device_path Optional device path (may be NULL)
* @param[in] user_id Optional user_id string (may be NULL)
* @param[in] sk_callbacks Pointer to SK callbacks (may be NULL)
*
* @return A configured ssh_pki_ctx on success, or NULL on allocation failure.
*/
ssh_pki_ctx
torture_create_sk_pki_ctx(const char *application,
uint8_t flags,
const void *challenge_data,
size_t challenge_len,
ssh_auth_callback pin_callback,
const char *device_path,
const char *user_id,
const struct ssh_sk_callbacks_struct *sk_callbacks);
/**
* @brief Validate a security key enrollment response structure
*