Skip to content

Commit 6562dd3

Browse files
Merge pull request #128 from gilles-peskine-arm/psa-policy_alg2-api
Implementation-specific extension: Keys may allow a second algorithm Implemented over API 1.0 beta3.
2 parents 4719db3 + 3027ba6 commit 6562dd3

10 files changed

+340
-117
lines changed

include/psa/crypto_extra.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,50 @@ extern "C" {
6262
MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( PSA_ERROR_INSUFFICIENT_DATA )
6363
#endif
6464

65+
/** \addtogroup attributes
66+
* @{
67+
*/
68+
69+
/** \brief Declare the enrollment algorithm for a key.
70+
*
71+
* An operation on a key may indifferently use the algorithm set with
72+
* psa_set_key_algorithm() or with this function.
73+
*
74+
* \param[out] attributes The attribute structure to write to.
75+
* \param alg2 A second algorithm that the key may be used
76+
* for, in addition to the algorithm set with
77+
* psa_set_key_algorithm().
78+
*
79+
* \warning Setting an enrollment algorithm is not recommended, because
80+
* using the same key with different algorithms can allow some
81+
* attacks based on arithmetic relations between different
82+
* computations made with the same key, or can escalate harmless
83+
* side channels into exploitable ones. Use this function only
84+
* if it is necessary to support a protocol for which it has been
85+
* verified that the usage of the key with multiple algorithms
86+
* is safe.
87+
*/
88+
static inline void psa_set_key_enrollment_algorithm(
89+
psa_key_attributes_t *attributes,
90+
psa_algorithm_t alg2)
91+
{
92+
attributes->policy.alg2 = alg2;
93+
}
94+
95+
/** Retrieve the enrollment algorithm policy from key attributes.
96+
*
97+
* \param[in] attributes The key attribute structure to query.
98+
*
99+
* \return The enrollment algorithm stored in the attribute structure.
100+
*/
101+
static inline psa_algorithm_t psa_get_key_enrollment_algorithm(
102+
const psa_key_attributes_t *attributes)
103+
{
104+
return( attributes->policy.alg2 );
105+
}
106+
107+
/**@}*/
108+
65109
/**
66110
* \brief Library deinitialization.
67111
*

include/psa/crypto_struct.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,11 @@ struct psa_key_policy_s
251251
{
252252
psa_key_usage_t usage;
253253
psa_algorithm_t alg;
254+
psa_algorithm_t alg2;
254255
};
255256
typedef struct psa_key_policy_s psa_key_policy_t;
256257

257-
#define PSA_KEY_POLICY_INIT {0, 0}
258+
#define PSA_KEY_POLICY_INIT {0, 0, 0}
258259
static inline struct psa_key_policy_s psa_key_policy_init( void )
259260
{
260261
const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT;
@@ -272,7 +273,7 @@ struct psa_key_attributes_s
272273
size_t domain_parameters_size;
273274
};
274275

275-
#define PSA_KEY_ATTRIBUTES_INIT {0, 0, {0, 0}, 0, 0, NULL, 0}
276+
#define PSA_KEY_ATTRIBUTES_INIT {0, 0, {0, 0, 0}, 0, 0, NULL, 0}
276277
static inline struct psa_key_attributes_s psa_key_attributes_init( void )
277278
{
278279
const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;

library/psa_crypto.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ static psa_algorithm_t psa_key_policy_algorithm_intersection(
768768
psa_algorithm_t alg1,
769769
psa_algorithm_t alg2 )
770770
{
771-
/* Common case: the policy only allows alg. */
771+
/* Common case: both sides actually specify the same policy. */
772772
if( alg1 == alg2 )
773773
return( alg1 );
774774
/* If the policies are from the same hash-and-sign family, check
@@ -786,27 +786,34 @@ static psa_algorithm_t psa_key_policy_algorithm_intersection(
786786
return( 0 );
787787
}
788788

789+
static int psa_key_algorithm_permits( psa_algorithm_t policy_alg,
790+
psa_algorithm_t requested_alg )
791+
{
792+
/* Common case: the policy only allows requested_alg. */
793+
if( requested_alg == policy_alg )
794+
return( 1 );
795+
/* If policy_alg is a hash-and-sign with a wildcard for the hash,
796+
* and requested_alg is the same hash-and-sign family with any hash,
797+
* then requested_alg is compliant with policy_alg. */
798+
if( PSA_ALG_IS_HASH_AND_SIGN( requested_alg ) &&
799+
PSA_ALG_SIGN_GET_HASH( policy_alg ) == PSA_ALG_ANY_HASH )
800+
{
801+
return( ( policy_alg & ~PSA_ALG_HASH_MASK ) ==
802+
( requested_alg & ~PSA_ALG_HASH_MASK ) );
803+
}
804+
/* If it isn't permitted, it's forbidden. */
805+
return( 0 );
806+
}
807+
789808
/** Test whether a policy permits an algorithm.
790809
*
791810
* The caller must test usage flags separately.
792811
*/
793812
static int psa_key_policy_permits( const psa_key_policy_t *policy,
794813
psa_algorithm_t alg )
795814
{
796-
/* Common case: the policy only allows alg. */
797-
if( alg == policy->alg )
798-
return( 1 );
799-
/* If policy->alg is a hash-and-sign with a wildcard for the hash,
800-
* and alg is the same hash-and-sign family with any hash,
801-
* then alg is compliant with policy->alg. */
802-
if( PSA_ALG_IS_HASH_AND_SIGN( alg ) &&
803-
PSA_ALG_SIGN_GET_HASH( policy->alg ) == PSA_ALG_ANY_HASH )
804-
{
805-
return( ( policy->alg & ~PSA_ALG_HASH_MASK ) ==
806-
( alg & ~PSA_ALG_HASH_MASK ) );
807-
}
808-
/* If it isn't permitted, it's forbidden. */
809-
return( 0 );
815+
return( psa_key_algorithm_permits( policy->alg, alg ) ||
816+
psa_key_algorithm_permits( policy->alg2, alg ) );
810817
}
811818

812819
/** Restrict a key policy based on a constraint.
@@ -827,10 +834,15 @@ static psa_status_t psa_restrict_key_policy(
827834
{
828835
psa_algorithm_t intersection_alg =
829836
psa_key_policy_algorithm_intersection( policy->alg, constraint->alg );
837+
psa_algorithm_t intersection_alg2 =
838+
psa_key_policy_algorithm_intersection( policy->alg2, constraint->alg2 );
830839
if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 )
831840
return( PSA_ERROR_INVALID_ARGUMENT );
841+
if( intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0 )
842+
return( PSA_ERROR_INVALID_ARGUMENT );
832843
policy->usage &= constraint->usage;
833844
policy->alg = intersection_alg;
845+
policy->alg2 = intersection_alg2;
834846
return( PSA_SUCCESS );
835847
}
836848

library/psa_crypto_storage.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ void psa_format_key_data_for_storage( const uint8_t *data,
269269
PUT_UINT32_LE(type, storage_format->type, 0);
270270
PUT_UINT32_LE(policy->usage, storage_format->policy, 0);
271271
PUT_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
272+
PUT_UINT32_LE(policy->alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
272273
PUT_UINT32_LE(data_length, storage_format->data_len, 0);
273274
memcpy( storage_format->key_data, data, data_length );
274275
}
@@ -324,6 +325,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
324325
GET_UINT32_LE(*type, storage_format->type, 0);
325326
GET_UINT32_LE(policy->usage, storage_format->policy, 0);
326327
GET_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
328+
GET_UINT32_LE(policy->alg2, storage_format->policy, 2 * sizeof( uint32_t ));
327329

328330
return( PSA_SUCCESS );
329331
}

0 commit comments

Comments
 (0)