signature-params: Add helper struct for signature scheme and parameters
This commit is contained in:
@@ -18,6 +18,147 @@
|
|||||||
#include <asn1/oid.h>
|
#include <asn1/oid.h>
|
||||||
#include <asn1/asn1_parser.h>
|
#include <asn1/asn1_parser.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the salt length in case it is not configured
|
||||||
|
*/
|
||||||
|
static ssize_t rsa_pss_salt_length(rsa_pss_params_t *pss)
|
||||||
|
{
|
||||||
|
ssize_t salt_len = pss->salt_len;
|
||||||
|
|
||||||
|
if (salt_len <= RSA_PSS_SALT_LEN_DEFAULT)
|
||||||
|
{
|
||||||
|
salt_len = hasher_hash_size(pss->hash);
|
||||||
|
if (!salt_len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return salt_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two signature schemes and their parameters
|
||||||
|
*/
|
||||||
|
static bool compare_params(signature_params_t *a, signature_params_t *b,
|
||||||
|
bool strict)
|
||||||
|
{
|
||||||
|
if (!a && !b)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (!a || !b)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (a->scheme != b->scheme)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!a->params && !b->params)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (a->params && b->params)
|
||||||
|
{
|
||||||
|
switch (a->scheme)
|
||||||
|
{
|
||||||
|
case SIGN_RSA_EMSA_PSS:
|
||||||
|
{
|
||||||
|
rsa_pss_params_t *pss_a = a->params, *pss_b = b->params;
|
||||||
|
|
||||||
|
return pss_a->hash == pss_b->hash &&
|
||||||
|
pss_a->mgf1_hash == pss_b->mgf1_hash &&
|
||||||
|
(!strict ||
|
||||||
|
rsa_pss_salt_length(pss_a) == rsa_pss_salt_length(pss_b));
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
bool signature_params_equal(signature_params_t *a, signature_params_t *b)
|
||||||
|
{
|
||||||
|
return compare_params(a, b, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
bool signature_params_comply(signature_params_t *c, signature_params_t *s)
|
||||||
|
{ /* the salt is variable, so it does not necessarily have to be the same */
|
||||||
|
return compare_params(c, s, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
signature_params_t *signature_params_clone(signature_params_t *this)
|
||||||
|
{
|
||||||
|
signature_params_t *clone;
|
||||||
|
|
||||||
|
if (!this)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT(clone,
|
||||||
|
.scheme = this->scheme,
|
||||||
|
);
|
||||||
|
if (this->params)
|
||||||
|
{
|
||||||
|
switch (this->scheme)
|
||||||
|
{
|
||||||
|
case SIGN_RSA_EMSA_PSS:
|
||||||
|
{
|
||||||
|
rsa_pss_params_t *pss, *pss_clone;
|
||||||
|
|
||||||
|
pss = this->params;
|
||||||
|
INIT(pss_clone,
|
||||||
|
.hash = pss->hash,
|
||||||
|
.mgf1_hash = pss->mgf1_hash,
|
||||||
|
.salt_len = pss->salt_len,
|
||||||
|
/* ignore salt as only used for unit tests */
|
||||||
|
);
|
||||||
|
clone->params = pss_clone;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
void signature_params_destroy(signature_params_t *this)
|
||||||
|
{
|
||||||
|
if (this)
|
||||||
|
{
|
||||||
|
free(this->params);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
void signature_params_clear(signature_params_t *this)
|
||||||
|
{
|
||||||
|
if (this)
|
||||||
|
{
|
||||||
|
free(this->params);
|
||||||
|
this->params = NULL;
|
||||||
|
this->scheme = SIGN_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASN.1 definition of RSASSA-PSS-params
|
* ASN.1 definition of RSASSA-PSS-params
|
||||||
*/
|
*/
|
||||||
@@ -119,6 +260,7 @@ end:
|
|||||||
bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
|
bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
|
||||||
{
|
{
|
||||||
chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty;
|
chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty;
|
||||||
|
ssize_t salt_len;
|
||||||
int alg;
|
int alg;
|
||||||
|
|
||||||
if (params->hash != HASH_SHA1)
|
if (params->hash != HASH_SHA1)
|
||||||
@@ -141,23 +283,16 @@ bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
|
|||||||
mgf = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_MGF1),
|
mgf = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_MGF1),
|
||||||
asn1_algorithmIdentifier(alg));
|
asn1_algorithmIdentifier(alg));
|
||||||
}
|
}
|
||||||
if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
|
salt_len = rsa_pss_salt_length(params);
|
||||||
|
if (salt_len < 0)
|
||||||
{
|
{
|
||||||
if (params->salt_len != HASH_SIZE_SHA1)
|
chunk_free(&hash);
|
||||||
{
|
chunk_free(&mgf);
|
||||||
slen = asn1_integer("m", asn1_integer_from_uint64(params->salt_len));
|
return FALSE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (params->hash != HASH_SHA1)
|
else if (salt_len != HASH_SIZE_SHA1)
|
||||||
{
|
{
|
||||||
size_t hlen = hasher_hash_size(params->hash);
|
slen = asn1_integer("m", asn1_integer_from_uint64(salt_len));
|
||||||
if (!hlen)
|
|
||||||
{
|
|
||||||
chunk_free(&hash);
|
|
||||||
chunk_free(&mgf);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
slen = asn1_integer("m", asn1_integer_from_uint64(hlen));
|
|
||||||
}
|
}
|
||||||
*asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm",
|
*asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm",
|
||||||
hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty,
|
hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty,
|
||||||
|
|||||||
@@ -21,10 +21,56 @@
|
|||||||
#ifndef SIGNATURE_PARAMS_H_
|
#ifndef SIGNATURE_PARAMS_H_
|
||||||
#define SIGNATURE_PARAMS_H_
|
#define SIGNATURE_PARAMS_H_
|
||||||
|
|
||||||
|
typedef struct signature_params_t signature_params_t;
|
||||||
typedef struct rsa_pss_params_t rsa_pss_params_t;
|
typedef struct rsa_pss_params_t rsa_pss_params_t;
|
||||||
|
|
||||||
#include <crypto/hashers/hasher.h>
|
#include <crypto/hashers/hasher.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature scheme with parameters
|
||||||
|
*/
|
||||||
|
struct signature_params_t {
|
||||||
|
/** Signature scheme */
|
||||||
|
signature_scheme_t scheme;
|
||||||
|
/** Parameters, depending on scheme */
|
||||||
|
void *params;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two signature schemes and their parameters
|
||||||
|
*
|
||||||
|
* @param a first scheme
|
||||||
|
* @param b second scheme
|
||||||
|
* @return TRUE if schemes and parameters are equal
|
||||||
|
*/
|
||||||
|
bool signature_params_equal(signature_params_t *a, signature_params_t *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two signature schemes and their parameters
|
||||||
|
*
|
||||||
|
* @param c constraint
|
||||||
|
* @param s scheme
|
||||||
|
* @return TRUE if scheme complies to constraint
|
||||||
|
*/
|
||||||
|
bool signature_params_comply(signature_params_t *c, signature_params_t *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the given scheme and parameters, if any
|
||||||
|
*
|
||||||
|
* @return cloned object
|
||||||
|
*/
|
||||||
|
signature_params_t *signature_params_clone(signature_params_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the given scheme and parameters, if any
|
||||||
|
*/
|
||||||
|
void signature_params_destroy(signature_params_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the given parameters, if any, sets the scheme to SIGN_UNKNOWN
|
||||||
|
*/
|
||||||
|
void signature_params_clear(signature_params_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters for SIGN_RSA_EMSA_PSS signature scheme
|
* Parameters for SIGN_RSA_EMSA_PSS signature scheme
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#include <asn1/asn1.h>
|
#include <asn1/asn1.h>
|
||||||
#include <credentials/keys/signature_params.h>
|
#include <credentials/keys/signature_params.h>
|
||||||
|
|
||||||
struct {
|
static struct {
|
||||||
chunk_t aid;
|
chunk_t aid;
|
||||||
rsa_pss_params_t params;
|
rsa_pss_params_t params;
|
||||||
} rsa_pss_parse_tests[] = {
|
} rsa_pss_parse_tests[] = {
|
||||||
@@ -125,7 +125,7 @@ START_TEST(test_rsa_pss_params_parse_invalid)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
struct {
|
static struct {
|
||||||
chunk_t aid;
|
chunk_t aid;
|
||||||
rsa_pss_params_t params;
|
rsa_pss_params_t params;
|
||||||
} rsa_pss_build_tests[] = {
|
} rsa_pss_build_tests[] = {
|
||||||
@@ -209,6 +209,111 @@ START_TEST(test_rsa_pss_params_build_invalid)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
static rsa_pss_params_t rsa_pss_params_sha1 = { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, };
|
||||||
|
static rsa_pss_params_t rsa_pss_params_sha256 = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA256, };
|
||||||
|
static rsa_pss_params_t rsa_pss_params_sha256_mgf1 = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA512, .salt_len = HASH_SIZE_SHA256, };
|
||||||
|
static rsa_pss_params_t rsa_pss_params_sha256_salt = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 10, };
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
bool equal;
|
||||||
|
bool complies;
|
||||||
|
signature_params_t a;
|
||||||
|
signature_params_t b;
|
||||||
|
} params_compare_tests[] = {
|
||||||
|
{ TRUE, TRUE, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, },
|
||||||
|
{ FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA1, }, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, },
|
||||||
|
{ TRUE, TRUE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, },
|
||||||
|
{ FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, .params = &rsa_pss_params_sha256 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, .params = &rsa_pss_params_sha256 }, },
|
||||||
|
{ FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_mgf1 }, },
|
||||||
|
{ FALSE, TRUE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_salt }, },
|
||||||
|
{ FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha1 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, },
|
||||||
|
{ FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PSS, }, },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_params_compare)
|
||||||
|
{
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
res = signature_params_equal(¶ms_compare_tests[_i].a,
|
||||||
|
¶ms_compare_tests[_i].b);
|
||||||
|
ck_assert(res == params_compare_tests[_i].equal);
|
||||||
|
res = signature_params_comply(¶ms_compare_tests[_i].a,
|
||||||
|
¶ms_compare_tests[_i].b);
|
||||||
|
ck_assert(res == params_compare_tests[_i].complies);
|
||||||
|
res = signature_params_comply(¶ms_compare_tests[_i].b,
|
||||||
|
¶ms_compare_tests[_i].a);
|
||||||
|
ck_assert(res == params_compare_tests[_i].complies);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_params_compare_null)
|
||||||
|
{
|
||||||
|
ck_assert(signature_params_equal(NULL, NULL));
|
||||||
|
ck_assert(!signature_params_equal(¶ms_compare_tests[0].a, NULL));
|
||||||
|
ck_assert(!signature_params_equal(NULL, ¶ms_compare_tests[0].a));
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
signature_params_t src;
|
||||||
|
signature_params_t res;
|
||||||
|
} params_clone_tests[] = {
|
||||||
|
{ { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, },
|
||||||
|
{ { .scheme = SIGN_RSA_EMSA_PSS }, { .scheme = SIGN_RSA_EMSA_PSS }, },
|
||||||
|
{ { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, },
|
||||||
|
{ { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_salt },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_salt }, },
|
||||||
|
{ { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, .params = &rsa_pss_params_sha256 },
|
||||||
|
{ .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256 }, },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_params_clone)
|
||||||
|
{
|
||||||
|
signature_params_t *clone = NULL;
|
||||||
|
|
||||||
|
clone = signature_params_clone(¶ms_clone_tests[_i].src);
|
||||||
|
ck_assert(signature_params_equal(clone, ¶ms_clone_tests[_i].res));
|
||||||
|
signature_params_destroy(clone);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_params_clone_null)
|
||||||
|
{
|
||||||
|
signature_params_t *clone = NULL;
|
||||||
|
|
||||||
|
clone = signature_params_clone(clone);
|
||||||
|
ck_assert(!clone);
|
||||||
|
signature_params_destroy(clone);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_params_clear)
|
||||||
|
{
|
||||||
|
signature_params_t *clone;
|
||||||
|
|
||||||
|
clone = signature_params_clone(¶ms_clone_tests[_i].src);
|
||||||
|
signature_params_clear(clone);
|
||||||
|
ck_assert_int_eq(clone->scheme, SIGN_UNKNOWN);
|
||||||
|
ck_assert(!clone->params);
|
||||||
|
free(clone);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_params_clear_null)
|
||||||
|
{
|
||||||
|
signature_params_t *clone = NULL;
|
||||||
|
|
||||||
|
signature_params_clear(clone);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
Suite *signature_params_suite_create()
|
Suite *signature_params_suite_create()
|
||||||
{
|
{
|
||||||
Suite *s;
|
Suite *s;
|
||||||
@@ -216,15 +321,30 @@ Suite *signature_params_suite_create()
|
|||||||
|
|
||||||
s = suite_create("signature params");
|
s = suite_create("signature params");
|
||||||
|
|
||||||
tc = tcase_create("parse");
|
tc = tcase_create("rsa/pss parse");
|
||||||
tcase_add_loop_test(tc, test_rsa_pss_params_parse, 0, countof(rsa_pss_parse_tests));
|
tcase_add_loop_test(tc, test_rsa_pss_params_parse, 0, countof(rsa_pss_parse_tests));
|
||||||
tcase_add_loop_test(tc, test_rsa_pss_params_parse_invalid, 0, countof(rsa_pss_parse_invalid_tests));
|
tcase_add_loop_test(tc, test_rsa_pss_params_parse_invalid, 0, countof(rsa_pss_parse_invalid_tests));
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("build");
|
tc = tcase_create("rsa/pss build");
|
||||||
tcase_add_loop_test(tc, test_rsa_pss_params_build, 0, countof(rsa_pss_build_tests));
|
tcase_add_loop_test(tc, test_rsa_pss_params_build, 0, countof(rsa_pss_build_tests));
|
||||||
tcase_add_loop_test(tc, test_rsa_pss_params_build_invalid, 0, countof(rsa_pss_build_invalid_tests));
|
tcase_add_loop_test(tc, test_rsa_pss_params_build_invalid, 0, countof(rsa_pss_build_invalid_tests));
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("params compare");
|
||||||
|
tcase_add_loop_test(tc, test_params_compare, 0, countof(params_compare_tests));
|
||||||
|
tcase_add_test(tc, test_params_compare_null);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("params clone");
|
||||||
|
tcase_add_loop_test(tc, test_params_clone, 0, countof(params_clone_tests));
|
||||||
|
tcase_add_test(tc, test_params_clone_null);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("params clear");
|
||||||
|
tcase_add_loop_test(tc, test_params_clear, 0, countof(params_clone_tests));
|
||||||
|
tcase_add_test(tc, test_params_clear_null);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user