Merge commit 'key-sig-schemes'

This adds the ability to return supported signature schemes (and
parameters) from a private key.

This is useful for keys on a TPM 2.0 as these can be used only with a
particular scheme (the hash algorithm and for RSA even the padding scheme
is fixed).  For RSA with PSS padding there is an additional complication
because different TPMs use different salt lengths, which we have to know
beforehand to correctly produce e.g. a certificate request (the signature
covers the algorithm identifier that describes the signature scheme).

It turned out that the new method is also useful for the agent plugin.
Newer ssh/gpg-agents support SHA-256 and SHA-512 for RSA signatures, but
not SHA-384, which we can now convey to the pubkey authenticator.
Unfortunately, older agents ignore the flags that request a SHA2 signature
and just return one with SHA-1, in such scenarios IKEv2 signature
authentication has to be disabled.
This commit is contained in:
Tobias Brunner
2018-10-26 10:59:38 +02:00
31 changed files with 672 additions and 130 deletions
+4
View File
@@ -1,6 +1,10 @@
charon.plugins.tpm.use_rng = no
Whether the TPM should be used as RNG.
charon.plugins.tpm.fips_186_4 = no
Is the TPM 2.0 FIPS-186-4 compliant, forcing e.g. the use of the default
salt length instead of maximum salt length with RSAPSS padding.
charon.plugins.tpm.tcti.name = device|tabrmd
Name of TPM 2.0 TCTI library. Valid values: _tabrmd_, _device_ or _mssim_.
Defaults are _device_ if the _/dev/tpmrm0_ in-kernel TPM 2.0 resource manager
+23 -2
View File
@@ -32,6 +32,28 @@ build_botan()
cd -
}
build_tss2()
{
TSS2_REV=2.1.0
TSS2_PKG=tpm2-tss-$TSS2_REV
TSS2_DIR=$TRAVIS_BUILD_DIR/../$TSS2_PKG
TSS2_SRC=https://github.com/tpm2-software/tpm2-tss/releases/download/$TSS2_REV/$TSS2_PKG.tar.gz
if test -d "$TSS2_DIR"; then
return
fi
# the default version of libgcrypt in Ubuntu 14.04 is too old
sudo apt-get update -qq && \
sudo apt-get install -qq libgcrypt20-dev &&
curl -L $TSS2_SRC | tar xz -C $TRAVIS_BUILD_DIR/.. &&
cd $TSS2_DIR &&
./configure &&
sudo make -j4 install >/dev/null &&
sudo ldconfig || exit $?
cd -
}
if test -z $TRAVIS_BUILD_DIR; then
TRAVIS_BUILD_DIR=$PWD
fi
@@ -79,8 +101,6 @@ all|coverage|sonarcloud)
--disable-systemd --disable-soup --disable-unwind-backtraces
--disable-svc --disable-dbghelp-backtraces --disable-socket-win
--disable-kernel-wfp --disable-kernel-iph --disable-winhttp"
# Ubuntu 14.04 does provide a too old libtss2-dev
CONFIG="$CONFIG --disable-tss-tss2"
# Ubuntu 14.04 does not provide libnm
CONFIG="$CONFIG --disable-nm"
# not enabled on the build server
@@ -98,6 +118,7 @@ all|coverage|sonarcloud)
PYDEPS="pytest"
if test "$1" = "deps"; then
build_botan
build_tss2
fi
;;
win*)
@@ -135,11 +135,7 @@ static bool set_pss_params(private_private_key_t *this, JNIEnv *env,
{
return FALSE;
}
slen = hasher_hash_size(pss->hash);
if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
slen = pss->salt_len;
}
slen = pss->salt_len;
obj = (*env)->NewObject(env, cls, method_id, jhash, jmgf1, obj, slen, 1);
if (!obj)
{
@@ -110,6 +110,40 @@ static bool build_signature_auth_data(chunk_t *auth_data,
return TRUE;
}
/**
* Check if the given scheme is supported by the key and, if so, add it to the
* first array (we add the scheme supported by the key in case the parameters
* are different)
*/
static void add_scheme_if_supported(array_t *selected, array_t *supported,
signature_params_t *config)
{
signature_params_t *sup;
int i;
if (!supported)
{
array_insert(selected, ARRAY_TAIL, signature_params_clone(config));
return;
}
for (i = 0; i < array_count(supported); i++)
{
array_get(supported, i, &sup);
if (signature_params_comply(sup, config))
{
array_insert(selected, ARRAY_TAIL, signature_params_clone(sup));
return;
}
}
}
CALLBACK(destroy_scheme, void,
signature_params_t *params, int idx, void *user)
{
signature_params_destroy(params);
}
/**
* Selects possible signature schemes based on our configuration, the other
* peer's capabilities and the private key
@@ -123,10 +157,32 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat,
auth_rule_t rule;
key_type_t key_type;
bool have_config = FALSE;
array_t *selected;
array_t *supported = NULL, *selected;
selected = array_create(0, 0);
key_type = private->get_type(private);
if (private->supported_signature_schemes)
{
enumerator = private->supported_signature_schemes(private);
while (enumerator->enumerate(enumerator, &config))
{
if (keymat->hash_algorithm_supported(keymat,
hasher_from_signature_scheme(config->scheme,
config->params)))
{
array_insert_create(&supported, ARRAY_TAIL,
signature_params_clone(config));
}
}
enumerator->destroy(enumerator);
if (!supported)
{
return selected;
}
}
enumerator = auth->create_enumerator(auth);
while (enumerator->enumerate(enumerator, &rule, &config))
{
@@ -134,21 +190,32 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat,
{
continue;
}
have_config = TRUE;
if (key_type == key_type_from_signature_scheme(config->scheme) &&
keymat->hash_algorithm_supported(keymat,
hasher_from_signature_scheme(config->scheme,
config->params)))
{
array_insert(selected, ARRAY_TAIL, signature_params_clone(config));
add_scheme_if_supported(selected, supported, config);
}
have_config = TRUE;
}
enumerator->destroy(enumerator);
if (!have_config)
if (have_config)
{
/* if no specific configuration, find schemes appropriate for the key
* and supported by the other peer */
array_destroy_function(supported, destroy_scheme, NULL);
}
else
{
/* if we have no config, return either whatever schemes the key (and
* peer) support or.. */
if (supported)
{
array_destroy(selected);
return supported;
}
/* ...find schemes appropriate for the key and supported by the peer */
enumerator = signature_schemes_for_key(key_type,
private->get_keysize(private));
while (enumerator->enumerate(enumerator, &config))
@@ -207,12 +274,6 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat,
return selected;
}
CALLBACK(destroy_scheme, void,
signature_params_t *params, int idx, void *user)
{
signature_params_destroy(params);
}
/**
* Adds the given auth data to the message, either in an AUTH payload or
* a NO_PPK_AUTH notify.
@@ -310,9 +371,9 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
if (params->scheme == SIGN_RSA_EMSA_PSS)
{
rsa_pss_params_t *pss = params->params;
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N_%N %s", id,
signature_scheme_names, params->scheme,
hash_algorithm_short_names_upper, pss->hash,
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N_%N_SALT_%zd "
"%s", id, signature_scheme_names, params->scheme,
hash_algorithm_short_names_upper, pss->hash, pss->salt_len,
status == SUCCESS ? "successful" : "failed");
}
else
@@ -586,9 +647,9 @@ METHOD(authenticator_t, process, status_t,
else if (params->scheme == SIGN_RSA_EMSA_PSS)
{
rsa_pss_params_t *pss = params->params;
DBG1(DBG_IKE, "authentication of '%Y' with %N_%N successful",
id, signature_scheme_names, params->scheme,
hash_algorithm_short_names_upper, pss->hash);
DBG1(DBG_IKE, "authentication of '%Y' with %N_%N_SALT_%zd "
"successful", id, signature_scheme_names, params->scheme,
hash_algorithm_short_names_upper, pss->hash, pss->salt_len);
}
else
{
+1
View File
@@ -551,6 +551,7 @@ static signature_params_t *create_rsa_pss_constraint(char *token)
.scheme = SIGN_RSA_EMSA_PSS,
.params = &pss,
};
rsa_pss_params_set_salt_len(&pss, 0);
params = signature_params_clone(&pss_params);
}
return params;
@@ -39,6 +39,19 @@ struct private_key_t {
*/
key_type_t (*get_type)(private_key_t *this);
/**
* Get signature schemes supported by this key.
*
* This is useful for keys that only support certain hash algorithms or
* require specific parameters for RSA/PSS signatures.
*
* @note Implementing this method is optional. If multiple schemes are
* returned, they should be ordered by decreasing preference.
*
* @return enumerator over signature_params_t*
*/
enumerator_t *(*supported_signature_schemes)(private_key_t *this);
/**
* Create a signature over a chunk of data.
*
@@ -250,7 +250,7 @@ int signature_scheme_to_oid(signature_scheme_t scheme)
#define PSS_PARAMS(bits) static rsa_pss_params_t pss_params_sha##bits = { \
.hash = HASH_SHA##bits, \
.mgf1_hash = HASH_SHA##bits, \
.salt_len = RSA_PSS_SALT_LEN_DEFAULT, \
.salt_len = HASH_SIZE_SHA##bits, \
}
PSS_PARAMS(256);
@@ -18,22 +18,43 @@
#include <asn1/oid.h>
#include <asn1/asn1_parser.h>
/**
* Determine the salt length in case it is not configured
/*
* Described in header
*/
static ssize_t rsa_pss_salt_length(rsa_pss_params_t *pss)
bool rsa_pss_params_set_salt_len(rsa_pss_params_t *params, size_t modbits)
{
ssize_t salt_len = pss->salt_len;
size_t hash_len;
if (salt_len <= RSA_PSS_SALT_LEN_DEFAULT)
if (params->salt_len < 0)
{
salt_len = hasher_hash_size(pss->hash);
if (!salt_len)
hash_len = hasher_hash_size(params->hash);
if (!hash_len)
{
return -1;
return FALSE;
}
switch (params->salt_len)
{
case RSA_PSS_SALT_LEN_DEFAULT:
params->salt_len = hash_len;
break;
case RSA_PSS_SALT_LEN_MAX:
if (modbits)
{
/* emBits = modBits - 1 */
modbits -= 1;
/* emLen = ceil(emBits/8) */
modbits = (modbits+7) / BITS_PER_BYTE;
/* account for 0x01 separator in DB, 0xbc trailing byte */
params->salt_len = max(0, (ssize_t)(modbits - hash_len - 2));
break;
}
return FALSE;
default:
return FALSE;
}
}
return salt_len;
return TRUE;
}
/**
@@ -68,8 +89,7 @@ static bool compare_params(signature_params_t *a, signature_params_t *b,
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));
(!strict || pss_a->salt_len == pss_b->salt_len);
}
default:
break;
@@ -328,7 +348,6 @@ end:
bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
{
chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty;
ssize_t salt_len;
int alg;
if (params->hash != HASH_SHA1)
@@ -351,16 +370,15 @@ bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
mgf = asn1_algorithmIdentifier_params(OID_MGF1,
asn1_algorithmIdentifier(alg));
}
salt_len = rsa_pss_salt_length(params);
if (salt_len < 0)
if (params->salt_len < 0)
{
chunk_free(&hash);
chunk_free(&mgf);
return FALSE;
}
else if (salt_len != HASH_SIZE_SHA1)
else if (params->salt_len != HASH_SIZE_SHA1)
{
slen = asn1_integer("m", asn1_integer_from_uint64(salt_len));
slen = asn1_integer("m", asn1_integer_from_uint64(params->salt_len));
}
*asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm",
hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty,
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Tobias Brunner
* Copyright (C) 2017-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -100,11 +100,15 @@ struct rsa_pss_params_t {
hash_algorithm_t hash;
/** Hash for the MGF1 function */
hash_algorithm_t mgf1_hash;
/** Salt length, use RSA_PSS_SALT_LEN_DEFAULT for length equal to hash */
/** Salt length, use the constants below for special lengths resolved
* via rsa_pss_params_set_salt_len() */
ssize_t salt_len;
/** Salt value, for unit tests (not all implementations support this) */
chunk_t salt;
/** Use a salt length equal to the length of the hash */
#define RSA_PSS_SALT_LEN_DEFAULT -1
/** Use the maximum salt length depending on the hash and key length */
#define RSA_PSS_SALT_LEN_MAX -2
};
/**
@@ -126,4 +130,15 @@ bool rsa_pss_params_parse(chunk_t asn1, int level0, rsa_pss_params_t *params);
*/
bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1);
/**
* Determine and set the salt length for the given params in case constants
* are used
*
* @param params parameters to update
* @param modbits RSA modulus length in bits (required if RSA_PSS_SALT_LEN_MAX
* is used)
* @return salt length to use, negative on error
*/
bool rsa_pss_params_set_salt_len(rsa_pss_params_t *params, size_t modbits);
#endif /** SIGNATURE_PARAMS_H_ @}*/
@@ -81,6 +81,14 @@ enum agent_msg_type_t {
SSH_AGENT_SIGN_RESPONSE = 14,
};
/**
* Flags for signatures
*/
enum agent_signature_flags_t {
SSH_AGENT_FLAG_SHA2_256 = 2,
SSH_AGENT_FLAG_SHA2_512 = 4,
};
/**
* read a byte from a blob
*/
@@ -217,12 +225,29 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey)
}
static bool scheme_supported(private_agent_private_key_t *this,
signature_scheme_t scheme)
signature_scheme_t scheme, uint32_t *flags,
char **prefix)
{
switch (this->pubkey->get_type(this->pubkey))
{
case KEY_RSA:
return scheme == SIGN_RSA_EMSA_PKCS1_SHA1;
switch (scheme)
{
case SIGN_RSA_EMSA_PKCS1_SHA1:
*prefix = "ssh-rsa";
return TRUE;
case SIGN_RSA_EMSA_PKCS1_SHA2_256:
*flags |= SSH_AGENT_FLAG_SHA2_256;
*prefix = "rsa-sha2-256";
return TRUE;
case SIGN_RSA_EMSA_PKCS1_SHA2_512:
*flags |= SSH_AGENT_FLAG_SHA2_512;
*prefix = "rsa-sha2-512";
return TRUE;
default:
break;
}
return FALSE;
case KEY_ECDSA:
return scheme == SIGN_ECDSA_256 ||
scheme == SIGN_ECDSA_384 ||
@@ -236,11 +261,11 @@ METHOD(private_key_t, sign, bool,
private_agent_private_key_t *this, signature_scheme_t scheme, void *params,
chunk_t data, chunk_t *signature)
{
uint32_t len, flags;
char buf[2048];
uint32_t len, flags = 0;
char buf[2048], *prefix = NULL;
chunk_t blob;
if (!scheme_supported(this, scheme))
if (!scheme_supported(this, scheme, &flags, &prefix))
{
DBG1(DBG_LIB, "signature scheme %N not supported by ssh-agent",
signature_scheme_names, scheme);
@@ -272,7 +297,7 @@ METHOD(private_key_t, sign, bool,
return FALSE;
}
flags = htonl(0);
flags = htonl(flags);
if (write(this->socket, &flags, sizeof(flags)) != sizeof(flags))
{
DBG1(DBG_LIB, "writing to ssh-agent failed");
@@ -290,9 +315,15 @@ METHOD(private_key_t, sign, bool,
}
/* parse length */
blob = read_string(&blob);
/* check sig type */
if (chunk_equals(read_string(&blob), chunk_from_str("ssh-rsa")))
{ /* for RSA the signature has no special encoding */
/* verify type */
if (prefix && !chunk_equals(read_string(&blob), chunk_from_str(prefix)))
{
DBG1(DBG_LIB, "ssh-agent didn't return requested %s signature", prefix);
return FALSE;
}
if (this->pubkey->get_type(this->pubkey) == KEY_RSA)
{ /* for RSA, the signature has no special encoding */
blob = read_string(&blob);
if (blob.len)
{
@@ -301,7 +332,7 @@ METHOD(private_key_t, sign, bool,
}
}
else
{ /* anything else is treated as ECSDA for now */
{ /* parse ECDSA signatures */
blob = read_string(&blob);
if (blob.len)
{
@@ -340,6 +371,76 @@ METHOD(private_key_t, get_keysize, int,
return this->pubkey->get_keysize(this->pubkey);
}
/**
* Private data for RSA scheme enumerator
*/
typedef struct {
enumerator_t public;
int index;
bool reverse;
} scheme_enumerator_t;
static signature_params_t rsa_schemes[] = {
{ .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256 },
{ .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_512 },
};
METHOD(enumerator_t, enumerate_rsa_scheme, bool,
scheme_enumerator_t *this, va_list args)
{
signature_params_t **params;
VA_ARGS_VGET(args, params);
if ((this->reverse && --this->index >= 0) ||
(!this->reverse && ++this->index < countof(rsa_schemes)))
{
*params = &rsa_schemes[this->index];
return TRUE;
}
return FALSE;
}
/**
* Create an enumerator for the supported RSA signature schemes
*/
static enumerator_t *create_rsa_enumerator(private_agent_private_key_t *this)
{
scheme_enumerator_t *enumerator;
INIT(enumerator,
.public = {
.enumerate = enumerator_enumerate_default,
.venumerate = _enumerate_rsa_scheme,
.destroy = (void*)free,
},
.index = -1,
.reverse = FALSE,
);
/* propose SHA-512 first for larger keys */
if (get_keysize(this) > 3072)
{
enumerator->index = countof(rsa_schemes);
enumerator->reverse = TRUE;
}
return &enumerator->public;
}
METHOD(private_key_t, supported_signature_schemes, enumerator_t*,
private_agent_private_key_t *this)
{
switch (get_type(this))
{
case KEY_RSA:
return create_rsa_enumerator(this);
case KEY_ECDSA:
return signature_schemes_for_key(KEY_ECDSA, get_keysize(this));
default:
break;
}
return enumerator_create_empty();
}
METHOD(private_key_t, get_public_key, public_key_t*,
private_agent_private_key_t *this)
{
@@ -413,6 +514,7 @@ agent_private_key_t *agent_private_key_open(key_type_t type, va_list args)
.public = {
.key = {
.get_type = _get_type,
.supported_signature_schemes = _supported_signature_schemes,
.sign = _sign,
.decrypt = _decrypt,
.get_keysize = _get_keysize,
@@ -84,13 +84,8 @@ bool botan_emsa_pss_identifier(rsa_pss_params_t *params, char *id, size_t len)
{
return FALSE;
}
if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
return snprintf(id, len, "EMSA-PSS(%s,MGF1,%zd)", hash,
params->salt_len) < len;
}
return snprintf(id, len, "EMSA-PSS(%s,MGF1)", hash) < len;
return snprintf(id, len, "EMSA-PSS(%s,MGF1,%zd)", hash,
params->salt_len) < len;
}
/**
@@ -187,11 +187,7 @@ static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this,
}
else
{
u_int slen = hasher_hash_size(hash_algorithm);
if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
slen = pss->salt_len;
}
u_int slen = pss->salt_len;
err = gcry_sexp_build(&in, NULL,
"(data(flags pss)(salt-length %u)(hash %s %b))",
slen, hash_name, hash.len, hash.ptr);
@@ -139,11 +139,7 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this,
if (pss)
{
u_int slen = hasher_hash_size(algorithm);
if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
slen = pss->salt_len;
}
u_int slen = pss->salt_len;
err = gcry_sexp_build(&in, NULL,
"(data(flags pss)(salt-length %u)(hash %s %b))",
slen, hash_name, hash.len, hash.ptr);
@@ -393,15 +393,11 @@ static bool build_emsa_pss_signature(private_gmp_rsa_private_key_t *this,
goto error;
}
salt.len = hash.len;
salt.len = params->salt_len;
if (params->salt.len)
{
salt = params->salt;
}
else if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
salt.len = params->salt_len;
}
if (emlen < (hash.len + salt.len + 2))
{ /* too long */
goto error;
@@ -205,12 +205,7 @@ static bool verify_emsa_pss_signature(private_gmp_rsa_public_key_t *this,
{
goto error;
}
/* determine salt length */
salt.len = hash.len;
if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
salt.len = params->salt_len;
}
salt.len = params->salt_len;
/* verify general structure of EM */
maskbits = (8 * em.len) - embits;
if (em.len < (hash.len + salt.len + 2) || em.ptr[em.len-1] != 0xbc ||
@@ -103,13 +103,8 @@ static bool build_signature(private_openssl_rsa_private_key_t *this,
if (pss)
{
const EVP_MD *mgf1md = openssl_get_md(pss->mgf1_hash);
int slen = EVP_MD_size(md);
if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
slen = pss->salt_len;
}
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, slen) <= 0 ||
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, pss->salt_len) <= 0 ||
EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md) <= 0)
{
goto error;
@@ -95,13 +95,8 @@ static bool verify_signature(private_openssl_rsa_public_key_t *this,
if (pss)
{
const EVP_MD *mgf1md = openssl_get_md(pss->mgf1_hash);
int slen = EVP_MD_size(md);
if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
slen = pss->salt_len;
}
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, slen) <= 0 ||
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, pss->salt_len) <= 0 ||
EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md) <= 0)
{
goto error;
+1 -1
View File
@@ -40,7 +40,7 @@ static signature_scheme_t schemes[] = {
static rsa_pss_params_t default_pss_params = {
.hash = HASH_SHA256,
.mgf1_hash = HASH_SHA256,
.salt_len = RSA_PSS_SALT_LEN_DEFAULT,
.salt_len = HASH_SIZE_SHA256,
};
/**
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Tobias Brunner
* Copyright (C) 2017-2018 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -138,27 +138,27 @@ static struct {
0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa2,0x03,
0x02,0x01,0x20),
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA256, }},
/* default salt length: SHA-1 */
{ chunk_from_chars(0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x00),
{ .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
{ .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }},
/* default salt length: SHA-224 */
{ chunk_from_chars(0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x16,0xa0,
0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,
0xa2,0x03,0x02,0x01,0x1c),
{ .hash = HASH_SHA224, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
{ .hash = HASH_SHA224, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA224, }},
/* default salt length: SHA-384 */
{ chunk_from_chars(0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x16,0xa0,
0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,
0xa2,0x03,0x02,0x01,0x30),
{ .hash = HASH_SHA384, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
{ .hash = HASH_SHA384, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA384, }},
/* SHA-512 */
{ chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,
0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0xa2,0x03,
0x02,0x01,0x40),
{ .hash = HASH_SHA512, .mgf1_hash = HASH_SHA512, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
{ .hash = HASH_SHA512, .mgf1_hash = HASH_SHA512, .salt_len = HASH_SIZE_SHA512, }},
/* SHA-256, no salt */
{ chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,
@@ -199,6 +199,8 @@ rsa_pss_params_t rsa_pss_build_invalid_tests[] = {
{ .hash = HASH_UNKNOWN, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, },
/* invalid mgf */
{ .hash = HASH_SHA256, .mgf1_hash = HASH_UNKNOWN, .salt_len = HASH_SIZE_SHA256, },
/* undetermined salt */
{ .hash = HASH_UNKNOWN, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, },
};
START_TEST(test_rsa_pss_params_build_invalid)
@@ -209,6 +211,49 @@ START_TEST(test_rsa_pss_params_build_invalid)
}
END_TEST
static struct {
ssize_t expected;
size_t modbits;
rsa_pss_params_t params;
} rsa_pss_salt_len_tests[] = {
{ HASH_SIZE_SHA256, 0,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
{ HASH_SIZE_SHA256, 3072,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
{ -1, 0,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }},
{ 0, 256,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }},
{ 350, 3071,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }},
{ 350, 3072,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }},
{ 350, 3073,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }},
{ 478, 4096,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }},
{ 10, 0,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 10, }},
{ 10, 3072,
{ .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 10, }},
};
START_TEST(test_rsa_pss_params_set_salt_len)
{
if (rsa_pss_params_set_salt_len(&rsa_pss_salt_len_tests[_i].params,
rsa_pss_salt_len_tests[_i].modbits))
{
ck_assert_int_eq(rsa_pss_salt_len_tests[_i].expected,
rsa_pss_salt_len_tests[_i].params.salt_len);
}
else
{
ck_assert(rsa_pss_salt_len_tests[_i].expected < 0);
}
}
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, };
@@ -430,6 +475,10 @@ Suite *signature_params_suite_create()
tcase_add_loop_test(tc, test_rsa_pss_params_build_invalid, 0, countof(rsa_pss_build_invalid_tests));
suite_add_tcase(s, tc);
tc = tcase_create("rsa/pss salt len");
tcase_add_loop_test(tc, test_rsa_pss_params_set_salt_len, 0, countof(rsa_pss_salt_len_tests));
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);
+9 -1
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2017 Andreas Steffen
* Copyright (C) 2018 Tobias Brunner
* Copyright (C) 2017-2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -75,6 +76,12 @@ METHOD(private_key_t, get_keysize, int,
return this->pubkey->get_keysize(this->pubkey);
}
METHOD(private_key_t, supported_signature_schemes, enumerator_t*,
private_tpm_private_key_t *this)
{
return this->tpm->supported_signature_schemes(this->tpm, this->handle);
}
METHOD(private_key_t, sign, bool,
private_tpm_private_key_t *this, signature_scheme_t scheme, void *params,
chunk_t data, chunk_t *signature)
@@ -201,6 +208,7 @@ tpm_private_key_t *tpm_private_key_connect(key_type_t type, va_list args)
.sign = _sign,
.decrypt = _decrypt,
.get_keysize = _get_keysize,
.supported_signature_schemes = _supported_signature_schemes,
.get_public_key = _get_public_key,
.equals = private_key_equals,
.belongs_to = private_key_belongs_to,
+11 -1
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016 Andreas Steffen
* Copyright (C) 2018 Tobias Brunner
* Copyright (C) 2016-2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -79,6 +80,15 @@ struct tpm_tss_t {
*/
chunk_t (*get_public)(tpm_tss_t *this, uint32_t handle);
/**
* Return signature schemes supported by the given key (TPM 2.0 only)
*
* @param handle key object handle
* @return enumerator over signature_params_t*
*/
enumerator_t *(*supported_signature_schemes)(tpm_tss_t *this,
uint32_t handle);
/**
* Retrieve the current value of a PCR register in a given PCR bank
*
+7
View File
@@ -390,6 +390,12 @@ METHOD(tpm_tss_t, get_public, chunk_t,
return aik_pubkey;
}
METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
private_tpm_tss_trousers_t *this, uint32_t handle)
{
return enumerator_create_empty();
}
METHOD(tpm_tss_t, read_pcr, bool,
private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
hash_algorithm_t alg)
@@ -642,6 +648,7 @@ tpm_tss_t *tpm_tss_trousers_create()
.get_version_info = _get_version_info,
.generate_aik = _generate_aik,
.get_public = _get_public,
.supported_signature_schemes = _supported_signature_schemes,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote = _quote,
+121 -12
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2018 Tobias Brunner
* Copyright (C) 2016-2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -68,6 +69,12 @@ struct private_tpm_tss_tss2_t {
* List of supported algorithms
*/
TPM_ALG_ID supported_algs[TPM_PT_ALGORITHM_SET];
/**
* Is TPM FIPS 186-4 compliant ?
*/
bool fips_186_4;
};
/**
@@ -153,6 +160,7 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this)
TPMS_TAGGED_PROPERTY tp;
TPMI_YES_NO more_data;
TPM_ALG_ID alg;
bool fips_140_2 = FALSE;
uint32_t rval, i, offset, revision = 0, year = 0;
size_t len = BUF_LEN;
char buf[BUF_LEN], manufacturer[5], vendor_string[17];
@@ -193,12 +201,25 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this)
offset = 4 * (tp.property - TPM_PT_VENDOR_STRING_1);
htoun32(vendor_string + offset, tp.value);
break;
case TPM_PT_MODES:
if (tp.value & TPMA_MODES_FIPS_140_2)
{
this->fips_186_4 = fips_140_2 = TRUE;
}
break;
default:
break;
}
}
DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u", LABEL, manufacturer,
vendor_string, (float)revision/100, year);
if (!fips_140_2)
{
this->fips_186_4 = lib->settings->get_bool(lib->settings,
"%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
}
DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u %s", LABEL,
manufacturer, vendor_string, (float)revision/100, year,
fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
/* get supported algorithms */
rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ALGS,
@@ -400,7 +421,7 @@ METHOD(tpm_tss_t, get_version_info, chunk_t,
}
/**
* read the public key portion of a TSS 2.0 AIK key from NVRAM
* read the public key portion of a TSS 2.0 key from NVRAM
*/
bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
TPM2B_PUBLIC *public)
@@ -450,9 +471,9 @@ METHOD(tpm_tss_t, get_public, chunk_t,
}
aik_blob = chunk_create((u_char*)&public, sizeof(public));
DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_blob);
DBG3(DBG_LIB, "%s public key blob: %B", LABEL, &aik_blob);
/* convert TSS 2.0 AIK public key blot into PKCS#1 format */
/* convert TSS 2.0 public key blot into PKCS#1 format */
switch (public.t.publicArea.type)
{
case TPM_ALG_RSA:
@@ -469,12 +490,12 @@ METHOD(tpm_tss_t, get_public, chunk_t,
aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
/* subjectPublicKeyInfo encoding of AIK RSA key */
/* subjectPublicKeyInfo encoding of RSA public key */
if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
{
DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key "
DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
"failed", LABEL);
return chunk_empty;
}
@@ -505,7 +526,7 @@ METHOD(tpm_tss_t, get_public, chunk_t,
pos += ecc->x.t.size;
/* copy y coordinate of ECC point */
memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
/* subjectPublicKeyInfo encoding of AIK ECC key */
/* subjectPublicKeyInfo encoding of ECC public key */
aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_build_known_oid(OID_EC_PUBLICKEY),
@@ -515,14 +536,101 @@ METHOD(tpm_tss_t, get_public, chunk_t,
break;
}
default:
DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
DBG1(DBG_PTS, "%s unsupported key type", LABEL);
return chunk_empty;
}
DBG1(DBG_PTS, "AIK signature algorithm is %N with %N hash",
DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
return aik_pubkey;
}
METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
private_tpm_tss_tss2_t *this, uint32_t handle)
{
TPM2B_PUBLIC public = { { 0, } };
hash_algorithm_t digest;
signature_params_t supported_scheme;
if (!read_public(this, handle, &public))
{
return enumerator_create_empty();
}
switch (public.t.publicArea.type)
{
case TPM_ALG_RSA:
{
TPMS_RSA_PARMS *rsa;
TPMT_RSA_SCHEME *scheme;
rsa = &public.t.publicArea.parameters.rsaDetail;
scheme = &rsa->scheme;
digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
switch (scheme->scheme)
{
case TPM_ALG_RSAPSS:
{
ssize_t salt_len;
salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
RSA_PSS_SALT_LEN_MAX;
rsa_pss_params_t pss_params = {
.hash = digest,
.mgf1_hash = digest,
.salt_len = salt_len,
};
supported_scheme = (signature_params_t){
.scheme = SIGN_RSA_EMSA_PSS,
.params = &pss_params,
};
if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
{
return enumerator_create_empty();
}
break;
}
case TPM_ALG_RSASSA:
supported_scheme = (signature_params_t){
.scheme = signature_scheme_from_oid(
hasher_signature_algorithm_to_oid(digest,
KEY_RSA)),
};
break;
default:
return enumerator_create_empty();
}
break;
}
case TPM_ALG_ECC:
{
TPMT_ECC_SCHEME *scheme;
scheme = &public.t.publicArea.parameters.eccDetail.scheme;
digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
switch (scheme->scheme)
{
case TPM_ALG_ECDSA:
supported_scheme = (signature_params_t){
.scheme = signature_scheme_from_oid(
hasher_signature_algorithm_to_oid(digest,
KEY_ECDSA)),
};
break;
default:
return enumerator_create_empty();
}
break;
}
default:
DBG1(DBG_PTS, "%s unsupported key type", LABEL);
return enumerator_create_empty();
}
return enumerator_create_single(signature_params_clone(&supported_scheme),
(void*)signature_params_destroy);
}
/**
* Configure a PCR Selection assuming a maximum of 24 registers
*/
@@ -809,7 +917,7 @@ METHOD(tpm_tss_t, quote, bool,
DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
LABEL, tpm_alg_id_names, sig.sigAlg);
return FALSE;
};
}
DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
@@ -1036,7 +1144,7 @@ METHOD(tpm_tss_t, sign, bool,
DBG1(DBG_PTS, "%s unsupported %N signature scheme",
LABEL, signature_scheme_names, scheme);
return FALSE;
};
}
return TRUE;
}
@@ -1174,6 +1282,7 @@ tpm_tss_t *tpm_tss_tss2_create()
.get_version_info = _get_version_info,
.generate_aik = _generate_aik,
.get_public = _get_public,
.supported_signature_schemes = _supported_signature_schemes,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote = _quote,
+121 -12
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2018 Tobias Brunner
* Copyright (C) 2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -64,6 +65,12 @@ struct private_tpm_tss_tss2_t {
* List of supported algorithms
*/
TPM2_ALG_ID supported_algs[TPM2_PT_ALGORITHM_SET];
/**
* Is TPM FIPS 186-4 compliant ?
*/
bool fips_186_4;
};
/**
@@ -152,6 +159,7 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this)
TPMS_TAGGED_PROPERTY tp;
TPMI_YES_NO more_data;
TPM2_ALG_ID alg;
bool fips_140_2 = FALSE;
uint32_t rval, i, offset, revision = 0, year = 0;
size_t len = BUF_LEN;
char buf[BUF_LEN], manufacturer[5], vendor_string[17];
@@ -193,12 +201,25 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this)
offset = 4 * (tp.property - TPM2_PT_VENDOR_STRING_1);
htoun32(vendor_string + offset, tp.value);
break;
case TPM2_PT_MODES:
if (tp.value & TPMA_MODES_FIPS_140_2)
{
this->fips_186_4 = fips_140_2 = TRUE;
}
break;
default:
break;
}
}
DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u", LABEL, manufacturer,
vendor_string, (float)revision/100, year);
if (!fips_140_2)
{
this->fips_186_4 = lib->settings->get_bool(lib->settings,
"%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
}
DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u %s", LABEL,
manufacturer, vendor_string, (float)revision/100, year,
fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
/* get supported algorithms */
rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ALGS,
@@ -360,7 +381,7 @@ METHOD(tpm_tss_t, get_version_info, chunk_t,
}
/**
* read the public key portion of a TSS 2.0 AIK key from NVRAM
* read the public key portion of a TSS 2.0 key from NVRAM
*/
bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
TPM2B_PUBLIC *public)
@@ -404,9 +425,9 @@ METHOD(tpm_tss_t, get_public, chunk_t,
}
aik_blob = chunk_create((u_char*)&public, sizeof(public));
DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_blob);
DBG3(DBG_LIB, "%s public key blob: %B", LABEL, &aik_blob);
/* convert TSS 2.0 AIK public key blot into PKCS#1 format */
/* convert TSS 2.0 public key blot into PKCS#1 format */
switch (public.publicArea.type)
{
case TPM2_ALG_RSA:
@@ -423,12 +444,12 @@ METHOD(tpm_tss_t, get_public, chunk_t,
aik_modulus = chunk_create(rsa->buffer, rsa->size);
aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
/* subjectPublicKeyInfo encoding of AIK RSA key */
/* subjectPublicKeyInfo encoding of RSA public key */
if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
{
DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key "
DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
"failed", LABEL);
return chunk_empty;
}
@@ -459,7 +480,7 @@ METHOD(tpm_tss_t, get_public, chunk_t,
pos += ecc->x.size;
/* copy y coordinate of ECC point */
memcpy(pos, ecc->y.buffer, ecc->y.size);
/* subjectPublicKeyInfo encoding of AIK ECC key */
/* subjectPublicKeyInfo encoding of ECC public key */
aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_build_known_oid(OID_EC_PUBLICKEY),
@@ -469,14 +490,101 @@ METHOD(tpm_tss_t, get_public, chunk_t,
break;
}
default:
DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
DBG1(DBG_PTS, "%s unsupported key type", LABEL);
return chunk_empty;
}
DBG1(DBG_PTS, "AIK signature algorithm is %N with %N hash",
DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
return aik_pubkey;
}
METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
private_tpm_tss_tss2_t *this, uint32_t handle)
{
TPM2B_PUBLIC public = { 0, };
hash_algorithm_t digest;
signature_params_t supported_scheme;
if (!read_public(this, handle, &public))
{
return enumerator_create_empty();
}
switch (public.publicArea.type)
{
case TPM2_ALG_RSA:
{
TPMS_RSA_PARMS *rsa;
TPMT_RSA_SCHEME *scheme;
rsa = &public.publicArea.parameters.rsaDetail;
scheme = &rsa->scheme;
digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
switch (scheme->scheme)
{
case TPM2_ALG_RSAPSS:
{
ssize_t salt_len;
salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
RSA_PSS_SALT_LEN_MAX;
rsa_pss_params_t pss_params = {
.hash = digest,
.mgf1_hash = digest,
.salt_len = salt_len,
};
supported_scheme = (signature_params_t){
.scheme = SIGN_RSA_EMSA_PSS,
.params = &pss_params,
};
if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
{
return enumerator_create_empty();
}
break;
}
case TPM2_ALG_RSASSA:
supported_scheme = (signature_params_t){
.scheme = signature_scheme_from_oid(
hasher_signature_algorithm_to_oid(digest,
KEY_RSA)),
};
break;
default:
return enumerator_create_empty();
}
break;
}
case TPM2_ALG_ECC:
{
TPMT_ECC_SCHEME *scheme;
scheme = &public.publicArea.parameters.eccDetail.scheme;
digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
switch (scheme->scheme)
{
case TPM2_ALG_ECDSA:
supported_scheme = (signature_params_t){
.scheme = signature_scheme_from_oid(
hasher_signature_algorithm_to_oid(digest,
KEY_ECDSA)),
};
break;
default:
return enumerator_create_empty();
}
break;
}
default:
DBG1(DBG_PTS, "%s unsupported key type", LABEL);
return enumerator_create_empty();
}
return enumerator_create_single(signature_params_clone(&supported_scheme),
(void*)signature_params_destroy);
}
/**
* Configure a PCR Selection assuming a maximum of 24 registers
*/
@@ -729,7 +837,7 @@ METHOD(tpm_tss_t, quote, bool,
DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
LABEL, tpm_alg_id_names, sig.sigAlg);
return FALSE;
};
}
DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
@@ -940,7 +1048,7 @@ METHOD(tpm_tss_t, sign, bool,
DBG1(DBG_PTS, "%s unsupported %N signature scheme",
LABEL, signature_scheme_names, scheme);
return FALSE;
};
}
return TRUE;
}
@@ -1061,6 +1169,7 @@ tpm_tss_t *tpm_tss_tss2_create()
.get_version_info = _get_version_info,
.generate_aik = _generate_aik,
.get_public = _get_public,
.supported_signature_schemes = _supported_signature_schemes,
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote = _quote,
+5
View File
@@ -228,6 +228,11 @@ static int acert()
goto end;
}
scheme = get_signature_scheme(private, digest, pss);
if (!scheme)
{
error = "no signature scheme found";
goto end;
}
ac = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509_AC,
+5
View File
@@ -536,6 +536,11 @@ static int issue()
chunk_from_chars(ASN1_SEQUENCE, 0));
}
scheme = get_signature_scheme(private, digest, pss);
if (!scheme)
{
error = "no signature scheme found";
goto end;
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_SIGNING_KEY, private, BUILD_SIGNING_CERT, ca,
+5
View File
@@ -168,6 +168,11 @@ static int req()
goto end;
}
scheme = get_signature_scheme(private, digest, pss);
if (!scheme)
{
error = "no signature scheme found";
goto end;
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PKCS10_REQUEST,
BUILD_SIGNING_KEY, private,
+5
View File
@@ -378,6 +378,11 @@ static int self()
rng->destroy(rng);
}
scheme = get_signature_scheme(private, digest, pss);
if (!scheme)
{
error = "no signature scheme found";
goto end;
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_SIGNING_KEY, private, BUILD_PUBLIC_KEY, public,
+6
View File
@@ -399,6 +399,12 @@ static int sign_crl()
chunk_increment(crl_serial);
scheme = get_signature_scheme(private, digest, pss);
if (!scheme)
{
error = "no signature scheme found";
goto error;
}
enumerator = enumerator_create_filter(list->create_enumerator(list),
filter, NULL, NULL);
crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+26 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2017 Tobias Brunner
* Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -264,7 +264,30 @@ static hash_algorithm_t get_default_digest(private_key_t *private)
signature_params_t *get_signature_scheme(private_key_t *private,
hash_algorithm_t digest, bool pss)
{
signature_params_t *scheme;
signature_params_t *scheme, *selected = NULL;
enumerator_t *enumerator;
if (private->supported_signature_schemes)
{
enumerator = private->supported_signature_schemes(private);
while (enumerator->enumerate(enumerator, &scheme))
{
if (private->get_type(private) == KEY_RSA &&
pss != (scheme->scheme == SIGN_RSA_EMSA_PSS))
{
continue;
}
if (digest == HASH_UNKNOWN ||
digest == hasher_from_signature_scheme(scheme->scheme,
scheme->params))
{
selected = signature_params_clone(scheme);
break;
}
}
enumerator->destroy(enumerator);
return selected;
}
if (digest == HASH_UNKNOWN)
{
@@ -281,6 +304,7 @@ signature_params_t *get_signature_scheme(private_key_t *private,
.scheme = SIGN_RSA_EMSA_PSS,
.params = &pss_params,
};
rsa_pss_params_set_salt_len(&pss_params, 0);
scheme = signature_params_clone(&pss_scheme);
}
else
+2 -1
View File
@@ -65,7 +65,8 @@ void set_file_mode(FILE *stream, cred_encoding_type_t enc);
* @param digest hash algorithm (if HASH_UNKNOWN a default is determined
* based on the key)
* @param pss use PSS padding for RSA keys
* @return allocated signature scheme and parameters
* @return allocated signature scheme and parameters (NULL if none
* found)
*/
signature_params_t *get_signature_scheme(private_key_t *private,
hash_algorithm_t digest, bool pss);