Skip to content

Implementation-specific extension: Keys may allow a second algorithm #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
44 changes: 44 additions & 0 deletions include/psa/crypto_extra.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,50 @@ extern "C" {
MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( PSA_ERROR_INSUFFICIENT_DATA )
#endif

/** \addtogroup attributes
* @{
*/

/** \brief Declare the enrollment algorithm for a key.
*
* An operation on a key may indifferently use the algorithm set with
* psa_set_key_algorithm() or with this function.
*
* \param[out] attributes The attribute structure to write to.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in rebase. No other changes.

* \param alg2 A second algorithm that the key may be used
* for, in addition to the algorithm set with
* psa_set_key_algorithm().
*
* \warning Setting an enrollment algorithm is not recommended, because
* using the same key with different algorithms can allow some
* attacks based on arithmetic relations between different
* computations made with the same key, or can escalate harmless
* side channels into exploitable ones. Use this function only
* if it is necessary to support a protocol for which it has been
* verified that the usage of the key with multiple algorithms
* is safe.
*/
static inline void psa_set_key_enrollment_algorithm(
psa_key_attributes_t *attributes,
psa_algorithm_t alg2)
{
attributes->policy.alg2 = alg2;
}

/** Retrieve the enrollment algorithm policy from key attributes.
*
* \param[in] attributes The key attribute structure to query.
*
* \return The enrollment algorithm stored in the attribute structure.
*/
static inline psa_algorithm_t psa_get_key_enrollment_algorithm(
const psa_key_attributes_t *attributes)
{
return( attributes->policy.alg2 );
}

/**@}*/

/**
* \brief Library deinitialization.
*
Expand Down
5 changes: 3 additions & 2 deletions include/psa/crypto_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,11 @@ struct psa_key_policy_s
{
psa_key_usage_t usage;
psa_algorithm_t alg;
psa_algorithm_t alg2;
};
typedef struct psa_key_policy_s psa_key_policy_t;

#define PSA_KEY_POLICY_INIT {0, 0}
#define PSA_KEY_POLICY_INIT {0, 0, 0}
static inline struct psa_key_policy_s psa_key_policy_init( void )
{
const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT;
Expand All @@ -272,7 +273,7 @@ struct psa_key_attributes_s
size_t domain_parameters_size;
};

#define PSA_KEY_ATTRIBUTES_INIT {0, 0, {0, 0}, 0, 0, NULL, 0}
#define PSA_KEY_ATTRIBUTES_INIT {0, 0, {0, 0, 0}, 0, 0, NULL, 0}
static inline struct psa_key_attributes_s psa_key_attributes_init( void )
{
const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;
Expand Down
42 changes: 27 additions & 15 deletions library/psa_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ static psa_algorithm_t psa_key_policy_algorithm_intersection(
psa_algorithm_t alg1,
psa_algorithm_t alg2 )
{
/* Common case: the policy only allows alg. */
/* Common case: both sides actually specify the same policy. */
if( alg1 == alg2 )
return( alg1 );
/* If the policies are from the same hash-and-sign family, check
Expand All @@ -786,27 +786,34 @@ static psa_algorithm_t psa_key_policy_algorithm_intersection(
return( 0 );
}

static int psa_key_algorithm_permits( psa_algorithm_t policy_alg,
psa_algorithm_t requested_alg )
{
/* Common case: the policy only allows requested_alg. */
if( requested_alg == policy_alg )
return( 1 );
/* If policy_alg is a hash-and-sign with a wildcard for the hash,
* and requested_alg is the same hash-and-sign family with any hash,
* then requested_alg is compliant with policy_alg. */
if( PSA_ALG_IS_HASH_AND_SIGN( requested_alg ) &&
PSA_ALG_SIGN_GET_HASH( policy_alg ) == PSA_ALG_ANY_HASH )
{
return( ( policy_alg & ~PSA_ALG_HASH_MASK ) ==
( requested_alg & ~PSA_ALG_HASH_MASK ) );
}
/* If it isn't permitted, it's forbidden. */
return( 0 );
}

/** Test whether a policy permits an algorithm.
*
* The caller must test usage flags separately.
*/
static int psa_key_policy_permits( const psa_key_policy_t *policy,
psa_algorithm_t alg )
{
/* Common case: the policy only allows alg. */
if( alg == policy->alg )
return( 1 );
/* If policy->alg is a hash-and-sign with a wildcard for the hash,
* and alg is the same hash-and-sign family with any hash,
* then alg is compliant with policy->alg. */
if( PSA_ALG_IS_HASH_AND_SIGN( alg ) &&
PSA_ALG_SIGN_GET_HASH( policy->alg ) == PSA_ALG_ANY_HASH )
{
return( ( policy->alg & ~PSA_ALG_HASH_MASK ) ==
( alg & ~PSA_ALG_HASH_MASK ) );
}
/* If it isn't permitted, it's forbidden. */
return( 0 );
return( psa_key_algorithm_permits( policy->alg, alg ) ||
psa_key_algorithm_permits( policy->alg2, alg ) );
}

/** Restrict a key policy based on a constraint.
Expand All @@ -827,10 +834,15 @@ static psa_status_t psa_restrict_key_policy(
{
psa_algorithm_t intersection_alg =
psa_key_policy_algorithm_intersection( policy->alg, constraint->alg );
psa_algorithm_t intersection_alg2 =
psa_key_policy_algorithm_intersection( policy->alg2, constraint->alg2 );
if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
if( intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
policy->usage &= constraint->usage;
policy->alg = intersection_alg;
policy->alg2 = intersection_alg2;
return( PSA_SUCCESS );
}

Expand Down
2 changes: 2 additions & 0 deletions library/psa_crypto_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ void psa_format_key_data_for_storage( const uint8_t *data,
PUT_UINT32_LE(type, storage_format->type, 0);
PUT_UINT32_LE(policy->usage, storage_format->policy, 0);
PUT_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
PUT_UINT32_LE(policy->alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
PUT_UINT32_LE(data_length, storage_format->data_len, 0);
memcpy( storage_format->key_data, data, data_length );
}
Expand Down Expand Up @@ -324,6 +325,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
GET_UINT32_LE(*type, storage_format->type, 0);
GET_UINT32_LE(policy->usage, storage_format->policy, 0);
GET_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
GET_UINT32_LE(policy->alg2, storage_format->policy, 2 * sizeof( uint32_t ));

return( PSA_SUCCESS );
}
Expand Down
Loading