mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-04-01 04:20:45 +00:00
Add generator API
Add an API for byte generators: psa_crypto_generator_t, PSA_CRYPTO_GENERATOR_INIT, psa_crypto_generator_init, psa_get_generator_capacity, psa_generator_read, psa_generator_import_key, psa_generator_abort. This commit does not yet implement any generator algorithm, it only provides the framework. This code may not compile with -Wunused.
This commit is contained in:
parent
9aa369eafb
commit
eab56e4159
@ -285,12 +285,18 @@ typedef int32_t psa_status_t;
|
|||||||
* depend on the validity of the padding. */
|
* depend on the validity of the padding. */
|
||||||
#define PSA_ERROR_INVALID_PADDING ((psa_status_t)16)
|
#define PSA_ERROR_INVALID_PADDING ((psa_status_t)16)
|
||||||
|
|
||||||
|
/** The generator has insufficient capacity left.
|
||||||
|
*
|
||||||
|
* Once a function returns this error, attempts to read from the
|
||||||
|
* generator will always return this error. */
|
||||||
|
#define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)17)
|
||||||
|
|
||||||
/** An error occurred that does not correspond to any defined
|
/** An error occurred that does not correspond to any defined
|
||||||
* failure cause.
|
* failure cause.
|
||||||
*
|
*
|
||||||
* Implementations may use this error code if none of the other standard
|
* Implementations may use this error code if none of the other standard
|
||||||
* error codes are applicable. */
|
* error codes are applicable. */
|
||||||
#define PSA_ERROR_UNKNOWN_ERROR ((psa_status_t)17)
|
#define PSA_ERROR_UNKNOWN_ERROR ((psa_status_t)18)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Library initialization.
|
* \brief Library initialization.
|
||||||
@ -2440,6 +2446,175 @@ psa_status_t psa_asymmetric_decrypt(psa_key_slot_t key,
|
|||||||
|
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
|
/** \defgroup generation Generators
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** The type of the state data structure for generators.
|
||||||
|
*
|
||||||
|
* Before calling any function on a generator, the application must
|
||||||
|
* initialize it by any of the following means:
|
||||||
|
* - Set the structure to all-bits-zero, for example:
|
||||||
|
* \code
|
||||||
|
* psa_crypto_generator_t generator;
|
||||||
|
* memset(&generator, 0, sizeof(generator));
|
||||||
|
* \endcode
|
||||||
|
* - Initialize the structure to logical zero values, for example:
|
||||||
|
* \code
|
||||||
|
* psa_crypto_generator_t generator = {0};
|
||||||
|
* \endcode
|
||||||
|
* - Initialize the structure to the initializer #PSA_CRYPTO_GENERATOR_INIT,
|
||||||
|
* for example:
|
||||||
|
* \code
|
||||||
|
* psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
|
||||||
|
* \endcode
|
||||||
|
* - Assign the result of the function psa_crypto_generator_init()
|
||||||
|
* to the structure, for example:
|
||||||
|
* \code
|
||||||
|
* psa_crypto_generator_t generator;
|
||||||
|
* generator = psa_crypto_generator_init();
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* This is an implementation-defined \c struct. Applications should not
|
||||||
|
* make any assumptions about the content of this structure except
|
||||||
|
* as directed by the documentation of a specific implementation.
|
||||||
|
*/
|
||||||
|
typedef struct psa_crypto_generator_s psa_crypto_generator_t;
|
||||||
|
|
||||||
|
/** \def PSA_CRYPTO_GENERATOR_INIT
|
||||||
|
*
|
||||||
|
* This macro returns a suitable initializer for a generator object
|
||||||
|
* of type #psa_crypto_generator_t.
|
||||||
|
*/
|
||||||
|
#ifdef __DOXYGEN_ONLY__
|
||||||
|
/* This is an example definition for documentation purposes.
|
||||||
|
* Implementations should define a suitable value in `crypto_struct.h`.
|
||||||
|
*/
|
||||||
|
#define PSA_CRYPTO_GENERATOR_INIT {0}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Return an initial value for a generator object.
|
||||||
|
*/
|
||||||
|
static psa_crypto_generator_t psa_crypto_generator_init(void);
|
||||||
|
|
||||||
|
/** Retrieve the current capacity of a generator.
|
||||||
|
*
|
||||||
|
* The capacity of a generator is the maximum number of bytes that it can
|
||||||
|
* return. Reading *N* bytes from a generator reduces its capacity by *N*.
|
||||||
|
*
|
||||||
|
* \param[in] generator The generator to query.
|
||||||
|
* \param[out] capacity On success, the capacity of the generator.
|
||||||
|
*
|
||||||
|
* \retval PSA_SUCCESS
|
||||||
|
* \retval PSA_ERROR_BAD_STATE
|
||||||
|
* \retval PSA_ERROR_COMMUNICATION_FAILURE
|
||||||
|
*/
|
||||||
|
psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator,
|
||||||
|
size_t *capacity);
|
||||||
|
|
||||||
|
/** Read some data from a generator.
|
||||||
|
*
|
||||||
|
* This function reads and returns a sequence of bytes from a generator.
|
||||||
|
* The data that is read is discarded from the generator. The generator's
|
||||||
|
* capacity is decreased by the number of bytes read.
|
||||||
|
*
|
||||||
|
* \param[in,out] generator The generator object to read from.
|
||||||
|
* \param[out] output Buffer where the generator output will be
|
||||||
|
* written.
|
||||||
|
* \param output_length Number of bytes to output.
|
||||||
|
*
|
||||||
|
* \retval PSA_SUCCESS
|
||||||
|
* \retval PSA_ERROR_INSUFFICIENT_CAPACITY
|
||||||
|
* There were fewer than \p output_length bytes
|
||||||
|
* in the generator. Note that in this case, no
|
||||||
|
* output is written to the output buffer.
|
||||||
|
* The generator's capacity is set to 0, thus
|
||||||
|
* subsequent calls to this function will not
|
||||||
|
* succeed, even with a smaller output buffer.
|
||||||
|
* \retval PSA_ERROR_BAD_STATE
|
||||||
|
* \retval PSA_ERROR_INSUFFICIENT_MEMORY
|
||||||
|
* \retval PSA_ERROR_COMMUNICATION_FAILURE
|
||||||
|
* \retval PSA_ERROR_HARDWARE_FAILURE
|
||||||
|
* \retval PSA_ERROR_TAMPERING_DETECTED
|
||||||
|
*/
|
||||||
|
psa_status_t psa_generator_read(psa_crypto_generator_t *generator,
|
||||||
|
uint8_t *output,
|
||||||
|
size_t output_length);
|
||||||
|
|
||||||
|
/** Create a symmetric key from data read from a generator.
|
||||||
|
*
|
||||||
|
* This function reads a sequence of bytes from a generator and imports
|
||||||
|
* these bytes as a key.
|
||||||
|
* The data that is read is discarded from the generator. The generator's
|
||||||
|
* capacity is decreased by the number of bytes read.
|
||||||
|
*
|
||||||
|
* This function is equivalent to calling #psa_generator_read and
|
||||||
|
* passing the resulting output to #psa_import_key, but
|
||||||
|
* if the implementation provides an isolation boundary then
|
||||||
|
* the key material is not exposed outside the isolation boundary.
|
||||||
|
*
|
||||||
|
* \param key Slot where the key will be stored. This must be a
|
||||||
|
* valid slot for a key of the chosen type. It must
|
||||||
|
* be unoccupied.
|
||||||
|
* \param type Key type (a \c PSA_KEY_TYPE_XXX value).
|
||||||
|
* This must be a symmetric key type.
|
||||||
|
* \param bits Key size in bits.
|
||||||
|
* \param[in,out] generator The generator object to read from.
|
||||||
|
*
|
||||||
|
* \retval PSA_SUCCESS
|
||||||
|
* Success.
|
||||||
|
* \retval PSA_ERROR_INSUFFICIENT_CAPACITY
|
||||||
|
* There were fewer than \p output_length bytes
|
||||||
|
* in the generator. Note that in this case, no
|
||||||
|
* output is written to the output buffer.
|
||||||
|
* The generator's capacity is set to 0, thus
|
||||||
|
* subsequent calls to this function will not
|
||||||
|
* succeed, even with a smaller output buffer.
|
||||||
|
* \retval PSA_ERROR_NOT_SUPPORTED
|
||||||
|
* The key type or key size is not supported, either by the
|
||||||
|
* implementation in general or in this particular slot.
|
||||||
|
* \retval PSA_ERROR_BAD_STATE
|
||||||
|
* \retval PSA_ERROR_INVALID_ARGUMENT
|
||||||
|
* The key slot is invalid.
|
||||||
|
* \retval PSA_ERROR_OCCUPIED_SLOT
|
||||||
|
* There is already a key in the specified slot.
|
||||||
|
* \retval PSA_ERROR_INSUFFICIENT_MEMORY
|
||||||
|
* \retval PSA_ERROR_INSUFFICIENT_STORAGE
|
||||||
|
* \retval PSA_ERROR_COMMUNICATION_FAILURE
|
||||||
|
* \retval PSA_ERROR_HARDWARE_FAILURE
|
||||||
|
* \retval PSA_ERROR_TAMPERING_DETECTED
|
||||||
|
*/
|
||||||
|
psa_status_t psa_generator_import_key(psa_key_slot_t key,
|
||||||
|
psa_key_type_t type,
|
||||||
|
size_t bits,
|
||||||
|
psa_crypto_generator_t *generator);
|
||||||
|
|
||||||
|
/** Abort a generator.
|
||||||
|
*
|
||||||
|
* Once a generator has been aborted, its capacity is zero.
|
||||||
|
* Aborting a generator frees all associated resources except for the
|
||||||
|
* \c generator structure itself.
|
||||||
|
*
|
||||||
|
* This function may be called at any time as long as the generator
|
||||||
|
* object has been initialized to #PSA_CRYPTO_GENERATOR_INIT, to
|
||||||
|
* psa_crypto_generator_init() or a zero value. In particular, it is valid
|
||||||
|
* to call psa_generator_abort() twice, or to call psa_generator_abort()
|
||||||
|
* on a generator that has not been set up.
|
||||||
|
*
|
||||||
|
* Once aborted, the generator object may be called.
|
||||||
|
*
|
||||||
|
* \param[in,out] generator The generator to abort.
|
||||||
|
*
|
||||||
|
* \retval PSA_SUCCESS
|
||||||
|
* \retval PSA_ERROR_BAD_STATE
|
||||||
|
* \retval PSA_ERROR_COMMUNICATION_FAILURE
|
||||||
|
* \retval PSA_ERROR_HARDWARE_FAILURE
|
||||||
|
* \retval PSA_ERROR_TAMPERING_DETECTED
|
||||||
|
*/
|
||||||
|
psa_status_t psa_generator_abort(psa_crypto_generator_t *generator);
|
||||||
|
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
/** \defgroup generation Key generation
|
/** \defgroup generation Key generation
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
@ -130,6 +130,27 @@ struct psa_cipher_operation_s
|
|||||||
} ctx;
|
} ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct psa_crypto_generator_s
|
||||||
|
{
|
||||||
|
psa_algorithm_t alg;
|
||||||
|
size_t capacity;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t *data;
|
||||||
|
size_t size;
|
||||||
|
} buffer;
|
||||||
|
} ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PSA_CRYPTO_GENERATOR_INIT {0, 0, {{0, 0}}}
|
||||||
|
static inline struct psa_crypto_generator_s psa_crypto_generator_init( void )
|
||||||
|
{
|
||||||
|
const struct psa_crypto_generator_s v = PSA_CRYPTO_GENERATOR_INIT;
|
||||||
|
return( v );
|
||||||
|
}
|
||||||
|
|
||||||
struct psa_key_policy_s
|
struct psa_key_policy_s
|
||||||
{
|
{
|
||||||
psa_key_usage_t usage;
|
psa_key_usage_t usage;
|
||||||
|
@ -2988,7 +2988,105 @@ psa_status_t psa_aead_decrypt( psa_key_slot_t key,
|
|||||||
|
|
||||||
|
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
/* Key generation */
|
/* Generators */
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
psa_status_t psa_generator_abort( psa_crypto_generator_t *generator )
|
||||||
|
{
|
||||||
|
psa_status_t status = PSA_SUCCESS;
|
||||||
|
if( generator->alg == 0 )
|
||||||
|
{
|
||||||
|
/* The object has (apparently) been initialized but it is not
|
||||||
|
* in use. It's ok to call abort on such an object, and there's
|
||||||
|
* nothing to do. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = PSA_ERROR_BAD_STATE;
|
||||||
|
}
|
||||||
|
memset( generator, 0, sizeof( *generator ) );
|
||||||
|
return( status );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator,
|
||||||
|
size_t *capacity)
|
||||||
|
{
|
||||||
|
*capacity = generator->capacity;
|
||||||
|
return( PSA_SUCCESS );
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_status_t psa_generator_read( psa_crypto_generator_t *generator,
|
||||||
|
uint8_t *output,
|
||||||
|
size_t output_length )
|
||||||
|
{
|
||||||
|
psa_status_t status;
|
||||||
|
|
||||||
|
if( output_length > generator->capacity )
|
||||||
|
{
|
||||||
|
generator->capacity = 0;
|
||||||
|
/* Go through the error path to wipe all confidential data now
|
||||||
|
* that the generator object is useless. */
|
||||||
|
status = PSA_ERROR_INSUFFICIENT_CAPACITY;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if( output_length == 0 &&
|
||||||
|
generator->capacity == 0 && generator->alg == 0 )
|
||||||
|
{
|
||||||
|
/* Edge case: this is a blank or finished generator, and 0
|
||||||
|
* bytes were requested. The right error in this case could
|
||||||
|
* be either INSUFFICIENT_CAPACITY or BAD_STATE. Return
|
||||||
|
* INSUFFICIENT_CAPACITY, which is right for a finished
|
||||||
|
* generator, for consistency with the case when
|
||||||
|
* output_length > 0. */
|
||||||
|
return( PSA_ERROR_INSUFFICIENT_CAPACITY );
|
||||||
|
}
|
||||||
|
generator->capacity -= output_length;
|
||||||
|
|
||||||
|
{
|
||||||
|
return( PSA_ERROR_BAD_STATE );
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
{
|
||||||
|
psa_generator_abort( generator );
|
||||||
|
memset( output, '!', output_length );
|
||||||
|
}
|
||||||
|
return( status );
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_status_t psa_generator_import_key( psa_key_slot_t key,
|
||||||
|
psa_key_type_t type,
|
||||||
|
size_t bits,
|
||||||
|
psa_crypto_generator_t *generator )
|
||||||
|
{
|
||||||
|
uint8_t *data = NULL;
|
||||||
|
size_t bytes = PSA_BITS_TO_BYTES( bits );
|
||||||
|
psa_status_t status;
|
||||||
|
|
||||||
|
if( ! key_type_is_raw_bytes( type ) )
|
||||||
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||||
|
if( bits % 8 != 0 )
|
||||||
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||||
|
data = mbedtls_calloc( 1, bytes );
|
||||||
|
if( data == NULL )
|
||||||
|
return( PSA_ERROR_INSUFFICIENT_MEMORY );
|
||||||
|
|
||||||
|
status = psa_generator_read( generator, data, bytes );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
goto exit;
|
||||||
|
status = psa_import_key( key, type, data, bytes );
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mbedtls_free( data );
|
||||||
|
return( status );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************/
|
||||||
|
/* Random generation */
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
|
|
||||||
psa_status_t psa_generate_random( uint8_t *output,
|
psa_status_t psa_generate_random( uint8_t *output,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user