Skip to content

Commit 37b5c83

Browse files
Merge pull request #276 from gilles-peskine-arm/psa-key_derivation-relax_inputs
Relax input restrictions for key derivation
2 parents 5a627c5 + 178c9aa commit 37b5c83

File tree

6 files changed

+242
-75
lines changed

6 files changed

+242
-75
lines changed

include/psa/crypto.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3229,9 +3229,12 @@ psa_status_t psa_key_derivation_set_capacity(
32293229
* Refer to the documentation of each key derivation or key agreement
32303230
* algorithm for information.
32313231
*
3232-
* This function passes direct inputs. Some inputs must be passed as keys
3233-
* using psa_key_derivation_input_key() instead of this function. Refer to
3234-
* the documentation of individual step types for information.
3232+
* This function passes direct inputs, which is usually correct for
3233+
* non-secret inputs. To pass a secret input, which should be in a key
3234+
* object, call psa_key_derivation_input_key() instead of this function.
3235+
* Refer to the documentation of individual step types
3236+
* (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t)
3237+
* for more information.
32353238
*
32363239
* If this function returns an error status, the operation enters an error
32373240
* state and must be aborted by calling psa_key_derivation_abort().
@@ -3274,10 +3277,13 @@ psa_status_t psa_key_derivation_input_bytes(
32743277
* Refer to the documentation of each key derivation or key agreement
32753278
* algorithm for information.
32763279
*
3277-
* This function passes key inputs. Some inputs must be passed as keys
3278-
* of the appropriate type using this function, while others must be
3279-
* passed as direct inputs using psa_key_derivation_input_bytes(). Refer to
3280-
* the documentation of individual step types for information.
3280+
* This function obtains input from a key object, which is usually correct for
3281+
* secret inputs or for non-secret personalization strings kept in the key
3282+
* store. To pass a non-secret parameter which is not in the key store,
3283+
* call psa_key_derivation_input_bytes() instead of this function.
3284+
* Refer to the documentation of individual step types
3285+
* (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t)
3286+
* for more information.
32813287
*
32823288
* If this function returns an error status, the operation enters an error
32833289
* state and must be aborted by calling psa_key_derivation_abort().
@@ -3298,7 +3304,8 @@ psa_status_t psa_key_derivation_input_bytes(
32983304
* \retval #PSA_ERROR_INVALID_ARGUMENT
32993305
* \c step is not compatible with the operation's algorithm.
33003306
* \retval #PSA_ERROR_INVALID_ARGUMENT
3301-
* \c step does not allow key inputs.
3307+
* \c step does not allow key inputs of the given type
3308+
* or does not allow key inputs at all.
33023309
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
33033310
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
33043311
* \retval #PSA_ERROR_HARDWARE_FAILURE
@@ -3368,6 +3375,8 @@ psa_status_t psa_key_derivation_input_key(
33683375
* \c private_key.
33693376
* \retval #PSA_ERROR_NOT_SUPPORTED
33703377
* \c alg is not supported or is not a key derivation algorithm.
3378+
* \retval #PSA_ERROR_INVALID_ARGUMENT
3379+
* \c step does not allow an input resulting from a key agreement.
33713380
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
33723381
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
33733382
* \retval #PSA_ERROR_HARDWARE_FAILURE
@@ -3518,6 +3527,11 @@ psa_status_t psa_key_derivation_output_bytes(
35183527
* In all cases, the data that is read is discarded from the operation.
35193528
* The operation's capacity is decreased by the number of bytes read.
35203529
*
3530+
* For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET,
3531+
* the input to that step must be provided with psa_key_derivation_input_key().
3532+
* Future versions of this specification may include additional restrictions
3533+
* on the derived key based on the attributes and strength of the secret key.
3534+
*
35213535
* \param[in] attributes The attributes for the new key.
35223536
* \param[in,out] operation The key derivation operation object to read from.
35233537
* \param[out] handle On success, a handle to the newly created key.
@@ -3540,6 +3554,9 @@ psa_status_t psa_key_derivation_output_bytes(
35403554
* implementation in general or in this particular location.
35413555
* \retval #PSA_ERROR_INVALID_ARGUMENT
35423556
* The provided key attributes are not valid for the operation.
3557+
* \retval #PSA_ERROR_NOT_PERMITTED
3558+
* The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through
3559+
* a key.
35433560
* \retval #PSA_ERROR_BAD_STATE
35443561
* The operation state is not valid (it must be active and completed
35453562
* all required input steps).

include/psa/crypto_struct.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ typedef struct psa_tls12_prf_key_derivation_s
255255
struct psa_key_derivation_s
256256
{
257257
psa_algorithm_t alg;
258+
unsigned int can_output_key : 1;
258259
size_t capacity;
259260
union
260261
{
@@ -268,7 +269,7 @@ struct psa_key_derivation_s
268269
};
269270

270271
/* This only zeroes out the first byte in the union, the rest is unspecified. */
271-
#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, {0}}
272+
#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}}
272273
static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void )
273274
{
274275
const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT;

include/psa/crypto_values.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,31 +1618,43 @@
16181618

16191619
/** A secret input for key derivation.
16201620
*
1621-
* This must be a key of type #PSA_KEY_TYPE_DERIVE.
1621+
* This should be a key of type #PSA_KEY_TYPE_DERIVE
1622+
* (passed to psa_key_derivation_input_key())
1623+
* or the shared secret resulting from a key agreement
1624+
* (obtained via psa_key_derivation_key_agreement()).
1625+
*
1626+
* The secret can also be a direct input (passed to
1627+
* key_derivation_input_bytes()). In this case, the derivation operation
1628+
* may not be used to derive keys: the operation will only allow
1629+
* psa_key_derivation_output_bytes(), not psa_key_derivation_output_key().
16221630
*/
16231631
#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101)
16241632

16251633
/** A label for key derivation.
16261634
*
1627-
* This must be a direct input.
1635+
* This should be a direct input.
1636+
* It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.
16281637
*/
16291638
#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201)
16301639

16311640
/** A salt for key derivation.
16321641
*
1633-
* This must be a direct input.
1642+
* This should be a direct input.
1643+
* It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.
16341644
*/
16351645
#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202)
16361646

16371647
/** An information string for key derivation.
16381648
*
1639-
* This must be a direct input.
1649+
* This should be a direct input.
1650+
* It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.
16401651
*/
16411652
#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203)
16421653

16431654
/** A seed for key derivation.
16441655
*
1645-
* This must be a direct input.
1656+
* This should be a direct input.
1657+
* It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.
16461658
*/
16471659
#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204)
16481660

library/psa_crypto.c

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4787,6 +4787,9 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut
47874787
if( psa_get_key_bits( attributes ) == 0 )
47884788
return( PSA_ERROR_INVALID_ARGUMENT );
47894789

4790+
if( ! operation->can_output_key )
4791+
return( PSA_ERROR_NOT_PERMITTED );
4792+
47904793
status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE,
47914794
attributes, handle, &slot, &driver );
47924795
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -5076,15 +5079,54 @@ static psa_status_t psa_tls12_prf_psk_to_ms_input(
50765079
}
50775080
#endif /* MBEDTLS_MD_C */
50785081

5082+
/** Check whether the given key type is acceptable for the given
5083+
* input step of a key derivation.
5084+
*
5085+
* Secret inputs must have the type #PSA_KEY_TYPE_DERIVE.
5086+
* Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA.
5087+
* Both secret and non-secret inputs can alternatively have the type
5088+
* #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning
5089+
* that the input was passed as a buffer rather than via a key object.
5090+
*/
5091+
static int psa_key_derivation_check_input_type(
5092+
psa_key_derivation_step_t step,
5093+
psa_key_type_t key_type )
5094+
{
5095+
switch( step )
5096+
{
5097+
case PSA_KEY_DERIVATION_INPUT_SECRET:
5098+
if( key_type == PSA_KEY_TYPE_DERIVE )
5099+
return( PSA_SUCCESS );
5100+
if( key_type == PSA_KEY_TYPE_NONE )
5101+
return( PSA_SUCCESS );
5102+
break;
5103+
case PSA_KEY_DERIVATION_INPUT_LABEL:
5104+
case PSA_KEY_DERIVATION_INPUT_SALT:
5105+
case PSA_KEY_DERIVATION_INPUT_INFO:
5106+
case PSA_KEY_DERIVATION_INPUT_SEED:
5107+
if( key_type == PSA_KEY_TYPE_RAW_DATA )
5108+
return( PSA_SUCCESS );
5109+
if( key_type == PSA_KEY_TYPE_NONE )
5110+
return( PSA_SUCCESS );
5111+
break;
5112+
}
5113+
return( PSA_ERROR_INVALID_ARGUMENT );
5114+
}
5115+
50795116
static psa_status_t psa_key_derivation_input_internal(
50805117
psa_key_derivation_operation_t *operation,
50815118
psa_key_derivation_step_t step,
5119+
psa_key_type_t key_type,
50825120
const uint8_t *data,
50835121
size_t data_length )
50845122
{
50855123
psa_status_t status;
50865124
psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation );
50875125

5126+
status = psa_key_derivation_check_input_type( step, key_type );
5127+
if( status != PSA_SUCCESS )
5128+
goto exit;
5129+
50885130
#if defined(MBEDTLS_MD_C)
50895131
if( PSA_ALG_IS_HKDF( kdf_alg ) )
50905132
{
@@ -5111,6 +5153,7 @@ static psa_status_t psa_key_derivation_input_internal(
51115153
return( PSA_ERROR_BAD_STATE );
51125154
}
51135155

5156+
exit:
51145157
if( status != PSA_SUCCESS )
51155158
psa_key_derivation_abort( operation );
51165159
return( status );
@@ -5122,10 +5165,8 @@ psa_status_t psa_key_derivation_input_bytes(
51225165
const uint8_t *data,
51235166
size_t data_length )
51245167
{
5125-
if( step == PSA_KEY_DERIVATION_INPUT_SECRET )
5126-
return( PSA_ERROR_INVALID_ARGUMENT );
5127-
51285168
return( psa_key_derivation_input_internal( operation, step,
5169+
PSA_KEY_TYPE_NONE,
51295170
data, data_length ) );
51305171
}
51315172

@@ -5136,23 +5177,23 @@ psa_status_t psa_key_derivation_input_key(
51365177
{
51375178
psa_key_slot_t *slot;
51385179
psa_status_t status;
5180+
51395181
status = psa_get_transparent_key( handle, &slot,
51405182
PSA_KEY_USAGE_DERIVE,
51415183
operation->alg );
51425184
if( status != PSA_SUCCESS )
5185+
{
5186+
psa_key_derivation_abort( operation );
51435187
return( status );
5144-
if( slot->attr.type != PSA_KEY_TYPE_DERIVE )
5145-
return( PSA_ERROR_INVALID_ARGUMENT );
5146-
/* Don't allow a key to be used as an input that is usually public.
5147-
* This is debatable. It's ok from a cryptographic perspective to
5148-
* use secret material as an input that is usually public. However
5149-
* the material should be dedicated to a particular input step,
5150-
* otherwise this may allow the key to be used in an unintended way
5151-
* and leak values derived from the key. So be conservative. */
5152-
if( step != PSA_KEY_DERIVATION_INPUT_SECRET )
5153-
return( PSA_ERROR_INVALID_ARGUMENT );
5188+
}
5189+
5190+
/* Passing a key object as a SECRET input unlocks the permission
5191+
* to output to a key object. */
5192+
if( step == PSA_KEY_DERIVATION_INPUT_SECRET )
5193+
operation->can_output_key = 1;
5194+
51545195
return( psa_key_derivation_input_internal( operation,
5155-
step,
5196+
step, slot->attr.type,
51565197
slot->data.raw.data,
51575198
slot->data.raw.bytes ) );
51585199
}
@@ -5265,8 +5306,10 @@ static psa_status_t psa_key_agreement_internal( psa_key_derivation_operation_t *
52655306
goto exit;
52665307

52675308
/* Step 2: set up the key derivation to generate key material from
5268-
* the shared secret. */
5309+
* the shared secret. A shared secret is permitted wherever a key
5310+
* of type DERIVE is permitted. */
52695311
status = psa_key_derivation_input_internal( operation, step,
5312+
PSA_KEY_TYPE_DERIVE,
52705313
shared_secret,
52715314
shared_secret_length );
52725315

0 commit comments

Comments
 (0)