Skip to content

Commit 5bae227

Browse files
committed
psa: Add initializers for cipher operation objects
Add new initializers for cipher operation objects and use them in our tests and library code. Prefer using the macro initializers due to their straightforwardness.
1 parent 5a5dc77 commit 5bae227

File tree

4 files changed

+101
-17
lines changed

4 files changed

+101
-17
lines changed

include/psa/crypto.h

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,18 +1228,60 @@ psa_status_t psa_mac_abort(psa_mac_operation_t *operation);
12281228
*/
12291229

12301230
/** The type of the state data structure for multipart cipher operations.
1231+
*
1232+
* Before calling any function on a cipher operation object, the application
1233+
* must initialize it by any of the following means:
1234+
* - Set the structure to all-bits-zero, for example:
1235+
* \code
1236+
* psa_cipher_operation_t operation;
1237+
* memset(&operation, 0, sizeof(operation));
1238+
* \endcode
1239+
* - Initialize the structure to logical zero values, for example:
1240+
* \code
1241+
* psa_cipher_operation_t operation = {0};
1242+
* \endcode
1243+
* - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT,
1244+
* for example:
1245+
* \code
1246+
* psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
1247+
* \endcode
1248+
* - Assign the result of the function psa_cipher_operation_init()
1249+
* to the structure, for example:
1250+
* \code
1251+
* psa_cipher_operation_t operation;
1252+
* operation = psa_cipher_operation_init();
1253+
* \endcode
12311254
*
12321255
* This is an implementation-defined \c struct. Applications should not
12331256
* make any assumptions about the content of this structure except
12341257
* as directed by the documentation of a specific implementation. */
12351258
typedef struct psa_cipher_operation_s psa_cipher_operation_t;
12361259

1260+
/** \def PSA_CIPHER_OPERATION_INIT
1261+
*
1262+
* This macro returns a suitable initializer for a cipher operation object of
1263+
* type #psa_cipher_operation_t.
1264+
*/
1265+
#ifdef __DOXYGEN_ONLY__
1266+
/* This is an example definition for documentation purposes.
1267+
* Implementations should define a suitable value in `crypto_struct.h`.
1268+
*/
1269+
#define PSA_CIPHER_OPERATION_INIT {0}
1270+
#endif
1271+
1272+
/** Return an initial value for a cipher operation object.
1273+
*/
1274+
static psa_cipher_operation_t psa_cipher_operation_init(void);
1275+
12371276
/** Set the key for a multipart symmetric encryption operation.
12381277
*
12391278
* The sequence of operations to encrypt a message with a symmetric cipher
12401279
* is as follows:
12411280
* -# Allocate an operation object which will be passed to all the functions
12421281
* listed here.
1282+
* -# Initialize the operation object with one of the methods described in the
1283+
* documentation for #psa_cipher_operation_t, e.g.
1284+
* PSA_CIPHER_OPERATION_INIT.
12431285
* -# Call psa_cipher_encrypt_setup() to specify the algorithm and key.
12441286
* The key remains associated with the operation even if the content
12451287
* of the key slot changes.
@@ -1252,7 +1294,7 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t;
12521294
* -# Call psa_cipher_finish().
12531295
*
12541296
* The application may call psa_cipher_abort() at any time after the operation
1255-
* has been initialized with psa_cipher_encrypt_setup().
1297+
* has been initialized.
12561298
*
12571299
* After a successful call to psa_cipher_encrypt_setup(), the application must
12581300
* eventually terminate the operation. The following events terminate an
@@ -1261,7 +1303,9 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t;
12611303
* or psa_cipher_update().
12621304
* - A call to psa_cipher_finish() or psa_cipher_abort().
12631305
*
1264-
* \param[out] operation The operation object to use.
1306+
* \param[in,out] operation The operation object to set up. It must have
1307+
* been initialized as per the documentation for
1308+
* #psa_cipher_operation_t and not yet in use.
12651309
* \param handle Handle to the key to use for the operation.
12661310
* \param alg The cipher algorithm to compute
12671311
* (\c PSA_ALG_XXX value such that
@@ -1295,6 +1339,9 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
12951339
* is as follows:
12961340
* -# Allocate an operation object which will be passed to all the functions
12971341
* listed here.
1342+
* -# Initialize the operation object with one of the methods described in the
1343+
* documentation for #psa_cipher_operation_t, e.g.
1344+
* PSA_CIPHER_OPERATION_INIT.
12981345
* -# Call psa_cipher_decrypt_setup() to specify the algorithm and key.
12991346
* The key remains associated with the operation even if the content
13001347
* of the key slot changes.
@@ -1307,15 +1354,17 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
13071354
* -# Call psa_cipher_finish().
13081355
*
13091356
* The application may call psa_cipher_abort() at any time after the operation
1310-
* has been initialized with psa_cipher_decrypt_setup().
1357+
* has been initialized.
13111358
*
13121359
* After a successful call to psa_cipher_decrypt_setup(), the application must
13131360
* eventually terminate the operation. The following events terminate an
13141361
* operation:
13151362
* - A failed call to psa_cipher_update().
13161363
* - A call to psa_cipher_finish() or psa_cipher_abort().
13171364
*
1318-
* \param[out] operation The operation object to use.
1365+
* \param[in,out] operation The operation object to set up. It must have
1366+
* been initialized as per the documentation for
1367+
* #psa_cipher_operation_t and not yet in use.
13191368
* \param handle Handle to the key to use for the operation.
13201369
* \param alg The cipher algorithm to compute
13211370
* (\c PSA_ALG_XXX value such that

include/psa/crypto_struct.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,13 @@ struct psa_cipher_operation_s
145145
} ctx;
146146
};
147147

148+
#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}}
149+
static inline struct psa_cipher_operation_s psa_cipher_operation_init( void )
150+
{
151+
const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;
152+
return( v );
153+
}
154+
148155
#if defined(MBEDTLS_MD_C)
149156
typedef struct
150157
{

tests/suites/test_suite_psa_crypto.data

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,9 @@ PSA MAC verify: CMAC-AES-128, truncated to 4 bytes
755755
depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
756756
mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 4):"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747"
757757

758+
Cipher operation object initializers zero properly
759+
cipher_operation_init:
760+
758761
PSA cipher setup: good, AES-CTR
759762
depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
760763
cipher_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CTR:PSA_SUCCESS

tests/suites/test_suite_psa_crypto.function

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static int exercise_cipher_key( psa_key_handle_t handle,
165165
psa_key_usage_t usage,
166166
psa_algorithm_t alg )
167167
{
168-
psa_cipher_operation_t operation;
168+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
169169
unsigned char iv[16] = {0};
170170
size_t iv_length = sizeof( iv );
171171
const unsigned char plaintext[16] = "Hello, world...";
@@ -1153,7 +1153,7 @@ void cipher_with_no_key_activity( )
11531153
psa_key_handle_t handle = 0;
11541154
psa_status_t status;
11551155
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
1156-
psa_cipher_operation_t operation;
1156+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
11571157
int exercise_alg = PSA_ALG_CTR;
11581158

11591159
PSA_ASSERT( psa_crypto_init( ) );
@@ -1210,7 +1210,7 @@ void cipher_after_import_failure( data_t *data, int type_arg,
12101210
int expected_import_status_arg )
12111211
{
12121212
psa_key_handle_t handle = 0;
1213-
psa_cipher_operation_t operation;
1213+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
12141214
psa_key_type_t type = type_arg;
12151215
psa_status_t status;
12161216
psa_status_t expected_import_status = expected_import_status_arg;
@@ -1492,7 +1492,7 @@ void cipher_key_policy( int policy_usage,
14921492
{
14931493
psa_key_handle_t handle = 0;
14941494
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
1495-
psa_cipher_operation_t operation;
1495+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
14961496
psa_status_t status;
14971497

14981498
PSA_ASSERT( psa_crypto_init( ) );
@@ -2082,6 +2082,31 @@ exit:
20822082
}
20832083
/* END_CASE */
20842084

2085+
/* BEGIN_CASE */
2086+
void cipher_operation_init( )
2087+
{
2088+
/* Test each valid way of initializing the object, except for `= {0}`, as
2089+
* Clang 5 complains when `-Wmissing-field-initializers` is used, even
2090+
* though it's OK by the C standard. We could test for this, but we'd need
2091+
* to supress the Clang warning for the test. */
2092+
psa_cipher_operation_t func = psa_cipher_operation_init( );
2093+
psa_cipher_operation_t init = PSA_CIPHER_OPERATION_INIT;
2094+
psa_cipher_operation_t zero;
2095+
2096+
memset( &zero, 0, sizeof( zero ) );
2097+
2098+
/* Although not technically guaranteed by the C standard nor the PSA Crypto
2099+
* specification, we test that all valid ways of initializing the object
2100+
* have the same bit pattern. This is a stronger requirement that may not
2101+
* be valid on all platforms or PSA Crypto implementations, but implies the
2102+
* weaker actual requirement is met: that a freshly initialized object, no
2103+
* matter how it was initialized, acts the same as any other valid
2104+
* initialization. */
2105+
TEST_EQUAL( memcmp( &func, &zero, sizeof( zero ) ), 0 );
2106+
TEST_EQUAL( memcmp( &init, &zero, sizeof( zero ) ), 0 );
2107+
}
2108+
/* END_CASE */
2109+
20852110
/* BEGIN_CASE */
20862111
void cipher_setup( int key_type_arg,
20872112
data_t *key,
@@ -2092,7 +2117,7 @@ void cipher_setup( int key_type_arg,
20922117
psa_key_type_t key_type = key_type_arg;
20932118
psa_algorithm_t alg = alg_arg;
20942119
psa_status_t expected_status = expected_status_arg;
2095-
psa_cipher_operation_t operation;
2120+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
20962121
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
20972122
psa_status_t status;
20982123

@@ -2133,7 +2158,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg,
21332158
size_t output_buffer_size = 0;
21342159
size_t function_output_length = 0;
21352160
size_t total_output_length = 0;
2136-
psa_cipher_operation_t operation;
2161+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
21372162
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
21382163

21392164
iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
@@ -2200,7 +2225,7 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg,
22002225
size_t output_buffer_size = 0;
22012226
size_t function_output_length = 0;
22022227
size_t total_output_length = 0;
2203-
psa_cipher_operation_t operation;
2228+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
22042229
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
22052230

22062231
iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
@@ -2270,7 +2295,7 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg,
22702295
size_t output_buffer_size = 0;
22712296
size_t function_output_length = 0;
22722297
size_t total_output_length = 0;
2273-
psa_cipher_operation_t operation;
2298+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
22742299
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
22752300

22762301
iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
@@ -2342,7 +2367,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg,
23422367
size_t output_buffer_size = 0;
23432368
size_t function_output_length = 0;
23442369
size_t total_output_length = 0;
2345-
psa_cipher_operation_t operation;
2370+
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
23462371
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
23472372

23482373
iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
@@ -2412,8 +2437,8 @@ void cipher_verify_output( int alg_arg, int key_type_arg,
24122437
size_t output2_size = 0;
24132438
size_t output2_length = 0;
24142439
size_t function_output_length = 0;
2415-
psa_cipher_operation_t operation1;
2416-
psa_cipher_operation_t operation2;
2440+
psa_cipher_operation_t operation1 = PSA_CIPHER_OPERATION_INIT;
2441+
psa_cipher_operation_t operation2 = PSA_CIPHER_OPERATION_INIT;
24172442
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
24182443

24192444
PSA_ASSERT( psa_crypto_init( ) );
@@ -2497,8 +2522,8 @@ void cipher_verify_output_multipart( int alg_arg,
24972522
size_t output2_buffer_size = 0;
24982523
size_t output2_length = 0;
24992524
size_t function_output_length;
2500-
psa_cipher_operation_t operation1;
2501-
psa_cipher_operation_t operation2;
2525+
psa_cipher_operation_t operation1 = PSA_CIPHER_OPERATION_INIT;
2526+
psa_cipher_operation_t operation2 = PSA_CIPHER_OPERATION_INIT;
25022527
psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
25032528

25042529
PSA_ASSERT( psa_crypto_init( ) );

0 commit comments

Comments
 (0)