psa: Disallow use of invalid cipher contexts

Ensure that when doing cipher operations out of order,
PSA_ERROR_BAD_STATE is returned as documented in crypto.h and the PSA
Crypto specification.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 9bfe8d2..4075c65 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -3073,6 +3073,12 @@
     psa_status_t status;
     int ret;
     size_t expected_output_size;
+
+    if( operation->alg == 0 )
+    {
+        return( PSA_ERROR_BAD_STATE );
+    }
+
     if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) )
     {
         /* Take the unprocessed partial block left over from previous
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 489389a..098e3f9 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -926,6 +926,10 @@
 # Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
 cipher_setup:PSA_KEY_TYPE_ARC4:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CTR:PSA_ERROR_NOT_SUPPORTED
 
+PSA cipher: bad order function calls
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+cipher_bad_order:
+
 PSA symmetric encrypt: AES-CBC-nopad, 16 bytes, good
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 37b4d8d..d1364b9 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -2447,6 +2447,9 @@
 /* BEGIN_CASE */
 void cipher_operation_init( )
 {
+    const uint8_t input[1] = { 0 };
+    unsigned char output[1] = { 0 };
+    size_t output_length;
     /* Test each valid way of initializing the object, except for `= {0}`, as
      * Clang 5 complains when `-Wmissing-field-initializers` is used, even
      * though it's OK by the C standard. We could test for this, but we'd need
@@ -2457,6 +2460,23 @@
 
     memset( &zero, 0, sizeof( zero ) );
 
+    /* A freshly-initialized cipher operation should not be usable. */
+    TEST_EQUAL( psa_cipher_update( &func,
+                                   input, sizeof( input ),
+                                   output, sizeof( output ),
+                                   &output_length ),
+                PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( psa_cipher_update( &init,
+                                   input, sizeof( input ),
+                                   output, sizeof( output ),
+                                   &output_length ),
+                PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( psa_cipher_update( &zero,
+                                   input, sizeof( input ),
+                                   output, sizeof( output ),
+                                   &output_length ),
+                PSA_ERROR_BAD_STATE );
+
     /* A default cipher operation should be abortable without error. */
     PSA_ASSERT( psa_cipher_abort( &func ) );
     PSA_ASSERT( psa_cipher_abort( &init ) );
@@ -2498,6 +2518,147 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void cipher_bad_order( )
+{
+    psa_key_handle_t handle = 0;
+    psa_key_type_t key_type = PSA_KEY_TYPE_AES;
+    psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
+    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    unsigned char iv[PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES)] = { 0 };
+    const uint8_t key[] = {
+        0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+        0xaa, 0xaa, 0xaa, 0xaa };
+    const uint8_t text[] = {
+        0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+        0xbb, 0xbb, 0xbb, 0xbb };
+    uint8_t buffer[PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES)] = { 0 };
+    size_t length = 0;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    PSA_ASSERT( psa_allocate_key( &handle ) );
+    psa_key_policy_set_usage( &policy,
+                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
+                              alg );
+    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    PSA_ASSERT( psa_import_key( handle, key_type,
+                                key, sizeof(key) ) );
+
+
+    /* Generate an IV without calling setup beforehand. */
+    TEST_EQUAL( psa_cipher_generate_iv( &operation,
+                                        buffer, sizeof( buffer ),
+                                        &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Generate an IV twice in a row. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) );
+    PSA_ASSERT( psa_cipher_generate_iv( &operation,
+                                        buffer, sizeof( buffer ),
+                                        &length ) );
+    TEST_EQUAL( psa_cipher_generate_iv( &operation,
+                                        buffer, sizeof( buffer ),
+                                        &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Generate an IV after it's already set. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) );
+    PSA_ASSERT( psa_cipher_set_iv( &operation,
+                                   iv, sizeof( iv ) ) );
+    TEST_EQUAL( psa_cipher_generate_iv( &operation,
+                                        buffer, sizeof( buffer ),
+                                        &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Set an IV without calling setup beforehand. */
+    TEST_EQUAL( psa_cipher_set_iv( &operation,
+                                   iv, sizeof( iv ) ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Set an IV after it's already set. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) );
+    PSA_ASSERT( psa_cipher_set_iv( &operation,
+                                   iv, sizeof( iv ) ) );
+    TEST_EQUAL( psa_cipher_set_iv( &operation,
+                                   iv, sizeof( iv ) ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Set an IV after it's already generated. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) );
+    PSA_ASSERT( psa_cipher_generate_iv( &operation,
+                                        buffer, sizeof( buffer ),
+                                        &length ) );
+    TEST_EQUAL( psa_cipher_set_iv( &operation,
+                                   iv, sizeof( iv ) ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Call update without calling setup beforehand. */
+    TEST_EQUAL( psa_cipher_update( &operation,
+                                   text, sizeof( text ),
+                                   buffer, sizeof( buffer ),
+                                   &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Call update without an IV where an IV is required. */
+    TEST_EQUAL( psa_cipher_update( &operation,
+                                   text, sizeof( text ),
+                                   buffer, sizeof( buffer ),
+                                   &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Call update after finish. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) );
+    PSA_ASSERT( psa_cipher_set_iv( &operation,
+                                   iv, sizeof( iv ) ) );
+    PSA_ASSERT( psa_cipher_finish( &operation,
+                                   buffer, sizeof( buffer ), &length ) );
+    TEST_EQUAL( psa_cipher_update( &operation,
+                                   text, sizeof( text ),
+                                   buffer, sizeof( buffer ),
+                                   &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Call finish without calling setup beforehand. */
+    TEST_EQUAL( psa_cipher_finish( &operation,
+                                   buffer, sizeof( buffer ), &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Call finish without an IV where an IV is required. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) );
+    /* Not calling update means we are encrypting an empty buffer, which is OK
+     * for cipher modes with padding. */
+    TEST_EQUAL( psa_cipher_finish( &operation,
+                                   buffer, sizeof( buffer ), &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+    /* Call finish twice in a row. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) );
+    PSA_ASSERT( psa_cipher_set_iv( &operation,
+                                   iv, sizeof( iv ) ) );
+    PSA_ASSERT( psa_cipher_finish( &operation,
+                                   buffer, sizeof( buffer ), &length ) );
+    TEST_EQUAL( psa_cipher_finish( &operation,
+                                   buffer, sizeof( buffer ), &length ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+exit:
+    mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void cipher_encrypt( int alg_arg, int key_type_arg,
                      data_t *key,
                      data_t *input, data_t *expected_output,