/** * \brief Test AES state interface functions * * This test verifies that the functions used to check the state of the module * are working, and that the clear functions work correctly. * * \param test Current test case */ static void run_aes_state_interface_test(const struct test_case *test) { /* We first reset the module */ aes_software_reset(); /* The module should not be busy or in error */ test_assert_true(test, aes_is_busy(), "Module should not be busy!"); test_assert_true(test, !aes_is_error(), "Module should not be in error!"); /* Get the module into error by trying to start the module before loading * values into state memory */ aes_start(); /* Module should now be in error */ test_assert_true(test, aes_is_error(), "Module should be in error!"); /* Clear the flag and check that it has been cleared */ aes_clear_error_flag(); test_assert_true(test, !aes_is_error(), "Module error flag should have been cleared!"); /* Load up dummy data into the module and do a cycle, then check that * the aes_is_busy() function actually works */ aes_software_reset(); aes_configure(AES_ENCRYPT, AES_MANUAL, AES_XOR_OFF); aes_set_key(encryption_key); aes_write_inputdata(dummy_data); aes_start(); /* Check that the module is busy, the module uses more CPU cycles to * complete than it takes to see if it is busy */ test_assert_true(test, aes_is_busy(), "AES module should be busy!"); do { /* Wait until the module is finished */ } while(aes_is_busy()); /* The module now has data in the status register. We want to clear the * flag without reading the data. First verify that the flag is set */ test_assert_true(test, AES.STATUS & AES_SRIF_bm, "State ready interrupt flag is not set!"); aes_clear_interrupt_flag(); /* Now, check that we have cleared the flag */ test_assert_true(test, !(AES.STATUS & AES_SRIF_bm), "State ready interrupt flag should not be set!"); }
/** * \brief Test AES decryption function. * * This test decrypts the pre-encrypted data and checks * whether it is correct. * * \param test Current test case. */ static void run_aes_decryption_test(const struct test_case *test) { t_key decrypted_data; bool success; set_buffer(decrypted_data, 0x00); set_buffer(lastsubkey, 0x00); /* Call helper function to generate a last subkey for decryption */ if (!aes_lastsubkey_generate(encryption_key, lastsubkey)) { success = false; test_assert_true(test, !success, "Could not generate last subkey"); } else { /* Configure module for manual decryption */ aes_software_reset(); aes_set_key(lastsubkey); aes_configure(AES_DECRYPT, AES_MANUAL, AES_XOR_OFF); aes_write_inputdata(pre_encrypted_data); aes_start(); do { /* Wait until AES is finished or an error occurs. */ } while (aes_is_busy()); aes_read_outputdata(decrypted_data); /* Verify that the decrypted data is correct */ success = compare_data_block(decrypted_data, encryption_data); test_assert_true(test, success, "Decrypted values do not match excepted values"); } }
/** * \brief Generate AES sub key * * Get AES sub key by encryption of dummy data. * * \param key Pointer to AES key input. * \param last_sub_key Pointer to AES sub key output. * */ static bool aes_lastsubkey_generate(t_key key, t_key last_sub_key) { bool keygen_ok; aes_software_reset(); /* Set AES encryption of a single block in manual mode. */ aes_configure(AES_ENCRYPT, AES_MANUAL, AES_XOR_OFF); /* Load key into AES key memory. */ aes_set_key(key); /* Load dummy data into AES state memory. It isn't important what is * written, just that a write cycle occurs. */ aes_write_inputdata(dummy_data); /* Start encryption. */ aes_start(); do { /* Wait until AES is finished or an error occurs. */ } while (aes_is_busy()); /* If not error. */ if (!aes_is_error()) { /* Store the last subkey. */ aes_get_key(last_sub_key); aes_clear_interrupt_flag(); keygen_ok = true; } else { aes_clear_error_flag(); keygen_ok = false; } return keygen_ok; }
/** * \brief Generate AES sub key * * \note Get AES sub key by encryption of dummy data. * * \param key Pointer to AES key input. * \param last_sub_key Pointer to AES sub key output. * */ static bool aes_lastsubkey_generate(t_key key, t_key last_sub_key) { bool keygen_ok; uint8_t i; /* Before using the AES it is recommended to do an AES software reset to * put the module in known state, in case other parts of your code has * accessed the AES module. */ aes_software_reset(); /* Set AES encryption of a single block in manual mode. */ aes_configure(AES_ENCRYPT, AES_MANUAL, AES_XOR_OFF); /* Load key into AES key memory. */ aes_set_key(key); /* Load dummy data into AES state memory. */ for (i = 0; i < BLOCK_LENGTH; i++) { AES.STATE = 0x00; } /* Start encryption. */ aes_start(); do { /* Wait until AES is finished or an error occurs. */ } while (aes_is_busy()); /* If not error. */ if (!aes_is_error()) { /* Store the last subkey. */ aes_get_key(last_sub_key); aes_clear_interrupt_flag(); keygen_ok = true; } else { aes_clear_error_flag(); keygen_ok = false; } return keygen_ok; }
/** * \brief Test AES encryption function * * This test generates an encrypted byte string from a key and input, * and compares it to a pre-encrypted value. * * \param test Current test case. */ static void run_aes_encryption_test(const struct test_case *test) { t_data encrypted_data; bool success; /* Zero out the output data storage */ set_buffer(encrypted_data, 0x00); /* Reset the module */ aes_software_reset(); /* * Configure AES module to encrypt, triggered by software, * with no XOR */ aes_configure(AES_ENCRYPT, AES_MANUAL, AES_XOR_OFF); aes_set_key(encryption_key); aes_write_inputdata(encryption_data); aes_start(); do { /* Wait until AES is finished or an error occurs. */ } while (aes_is_busy()); aes_read_outputdata(encrypted_data); /* Verify that this data is correct by comparing it * to our pre-encrypted value */ success = compare_data_block(encrypted_data, pre_encrypted_data); test_assert_true(test, success, "Encrypted values do not match pre-encrypted" " values"); }
int main( void ) { uint8_t i; board_init(); sysclk_init(); sleepmgr_init(); /* Assume that everything is ok*/ success = true; /* Enable the AES clock. */ sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_AES); /* Do AES encryption of a single block with DMA support. */ //******************************************************** // CIPHER IN MANUAL MODE: // - 128bit cryptographic key and data // - ECB cipher mode // - XOR disable // - DMA support for AES input and output //******************************************************** /* Before using the AES it is recommended to do an AES software reset to * put the module in known state, in case other parts of your code has * accessed the AES module. */ aes_software_reset(); /* Set AES encryption of a single block in manual mode. */ aes_configure(AES_ENCRYPT, AES_MANUAL, AES_XOR_OFF); /* Disable the AES interrupt. */ aes_isr_configure(AES_INTLVL_OFF); /* Set KEY and write STATE using DMA channel 0. */ aes_dma_input(); /* Start encryption. */ aes_start(); do { /* Wait until AES is finished or an error occurs. */ } while (aes_is_busy()); /* Store the result if not error. */ if (!aes_is_error()){ /* Read STATE using DMA channel 0. */ aes_dma_output(); } else { success = false; } /* Check if encrypted answer is equal to cipher result. */ for (i = 0; i < BLOCK_LENGTH ; i++ ) { if (cipher_text[i] != single_ans[i]) { success = false; } } /* Disable the AES clock. */ sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_AES); /* Indicate final result by lighting LED. */ if (success) { /* If the example ends up here every thing is ok. */ ioport_set_pin_low(LED0_GPIO); } else { /* If the example ends up here something is wrong. */ ioport_set_pin_low(LED1_GPIO); } while (true) { /* Go to sleep. */ sleepmgr_enter_sleep(); } }
int main( void ) { uint8_t i; board_init(); sysclk_init(); sleepmgr_init(); /* Assume that everything is ok */ success = true; /* Enable the AES clock. */ sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_AES); /* Do AES encryption and decryption of a single block. */ //******************************************************** // CIPHER IN MANUAL MODE: // - 128bit cryptographic key and data // - ECB cipher mode // - XOR disable // - Polling AES State Ready Interrupt flag //******************************************************** /* Before using the AES it is recommended to do an AES software reset to * put the module in known state, in case other parts of your code has * accessed the AES module. */ aes_software_reset(); /* Set AES encryption of a single block in manual mode. */ aes_configure(AES_ENCRYPT, AES_MANUAL, AES_XOR_OFF); /* Disable the AES interrupt. */ aes_isr_configure(AES_INTLVL_OFF); /* Load key into AES key memory. */ aes_set_key(key); /* Load data into AES state memory. */ aes_write_inputdata(plain_text); /* Start encryption. */ aes_start(); do { /* Wait until AES is finished or an error occurs. */ } while (aes_is_busy()); /* Store the result if not error. */ if (!aes_is_error()) { aes_read_outputdata(single_ans); } else { success = false; } /* Check if encrypted answer is equal to cipher result. */ for (i = 0; i < BLOCK_LENGTH ; i++ ) { if (cipher_text[i] != single_ans[i]) { success = false; } } //******************************************************** // DECIPHER IN AUTO MODE: // - 128bit cryptographic key and data // - ECB cipher mode // - XOR disable // - Polling AES State Ready Interrupt flag //******************************************************** /* Generate last subkey. */ if (!aes_lastsubkey_generate(key, lastsubkey)) { success = false; } /* Before using the AES it is recommended to do an AES software reset to * put the module in known state, in case other parts of your code has * accessed the AES module. */ aes_software_reset(); /* Set AES decryption of a single block in auto mode. */ aes_configure(AES_DECRYPT, AES_AUTO, AES_XOR_OFF); /* Disable the AES interrupt. */ aes_isr_configure(AES_INTLVL_OFF); /* Load key into AES key memory. */ aes_set_key(lastsubkey); /* Load data into AES state memory. */ aes_write_inputdata(cipher_text); // NOTE: since we're in auto mode, the ciphering process will start as soon // as the correct number of input data is written. In this case, the // process should start when we write the sixteenth byte. do { /* Wait until AES is finished or an error occurs. */ } while (aes_is_busy()); /* Store the result if not error. */ if (!aes_is_error()) { aes_read_outputdata(single_ans); } else { success = false; } /* Check if decrypted answer is equal to plaintext. */ for (i = 0; i < BLOCK_LENGTH ; i++ ) { if (plain_text[i] != single_ans[i]) { success = false; } } /* Disable the AES clock. */ sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_AES); /* Indicate final result by lighting LED. */ if (success) { /* If the example ends up here every thing is ok. */ ioport_set_pin_low(LED0_GPIO); } else { /* If the example ends up here something is wrong. */ ioport_set_pin_low(LED1_GPIO); } while (true) { /* Go to sleep. */ sleepmgr_enter_sleep(); } }
/** * \brief CTR mode encryption and decryption test. */ static void ctr_mode_test(void) { printf("\r\n-----------------------------------\r\n"); printf("- 128bit cryptographic key\r\n"); printf("- CTR cipher mode\r\n"); printf("- Auto start mode\r\n"); printf("- 4 32bit words\r\n"); printf("-----------------------------------\r\n"); state = false; /* Configure the AES. */ g_aes_cfg.encrypt_mode = AES_ENCRYPTION; g_aes_cfg.key_size = AES_KEY_SIZE_128; g_aes_cfg.start_mode = AES_AUTO_START; g_aes_cfg.opmode = AES_CTR_MODE; g_aes_cfg.cfb_size = AES_CFB_SIZE_128; g_aes_cfg.lod = false; aes_set_config(&aes_instance,AES, &g_aes_cfg); /* Set the cryptographic key. */ aes_write_key(&aes_instance, key128); /* Set the initialization vector. */ aes_write_init_vector(&aes_instance, init_vector_ctr); aes_set_new_message(&aes_instance); /* Write the data to be ciphered to the input data registers. */ aes_write_input_data(&aes_instance, ref_plain_text); aes_clear_new_message(&aes_instance); /* Wait for the end of the encryption process. */ while (false == state) { } /* check the result. */ if ((ref_cipher_text_ctr[0] != output_data[0]) || (ref_cipher_text_ctr[1] != output_data[1]) || (ref_cipher_text_ctr[2] != output_data[2]) || (ref_cipher_text_ctr[3] != output_data[3])) { printf("\r\nKO!!!\r\n"); } else { printf("\r\nOK!!!\r\n"); } printf("\r\n-----------------------------------\r\n"); printf("- 128bit cryptographic key\r\n"); printf("- CTR decipher mode\r\n"); printf("- Auto start mode\r\n"); printf("- 4 32bit words\r\n"); printf("-----------------------------------\r\n"); state = false; /* Configure the AES. */ g_aes_cfg.encrypt_mode = AES_DECRYPTION; g_aes_cfg.key_size = AES_KEY_SIZE_128; g_aes_cfg.start_mode = AES_MANUAL_START; g_aes_cfg.opmode = AES_CTR_MODE; g_aes_cfg.cfb_size = AES_CFB_SIZE_128; g_aes_cfg.lod = false; aes_set_config(&aes_instance,AES, &g_aes_cfg); /* Set the cryptographic key. */ aes_write_key(&aes_instance, key128); /* Set the initialization vector. */ aes_write_init_vector(&aes_instance, init_vector_ctr); /* Write the data to be deciphered to the input data registers. */ aes_write_input_data(&aes_instance, ref_cipher_text_ctr); aes_set_new_message(&aes_instance); aes_start(&aes_instance); aes_clear_new_message(&aes_instance); /* Wait for the end of the decryption process. */ while (false == state) { } /* check the result. */ if ((ref_plain_text[0] != output_data[0]) || (ref_plain_text[1] != output_data[1]) || (ref_plain_text[2] != output_data[2]) || (ref_plain_text[3] != output_data[3])) { printf("\r\nKO!!!\r\n"); } else { printf("\r\nOK!!!\r\n"); } }
int main( void ) { uint16_t i; /* Enable all three interrupt levels of the PMIC. */ pmic_init(); board_init(); sysclk_init(); sleepmgr_init(); /* Assume that everything is ok*/ success = true; /* Enable the AES clock. */ sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_AES); /* Do AES decryption of a single block with AES interrupt handler. */ //******************************************************** // DECIPHER IN MANUAL MODE: // - 128bit cryptographic key and data // - ECB cipher mode // - XOR disable // - Interrupt call back handler //******************************************************** /* Generate last subkey. */ if (!aes_lastsubkey_generate(key, lastsubkey)) { success = false; } /* Enable global interrupts. */ cpu_irq_enable(); /* Assume no interrupt is finished. */ int_end = false; byte_count = 0; /* Set AES interrupt call back function. */ aes_set_callback(&aes_isr_handler); /* Before using the AES it is recommended to do an AES software reset to * put the module in known state, in case other parts of your code has * accessed the AES module. */ aes_software_reset(); /* Set AES encryption of a single block in manual mode. */ aes_configure(AES_DECRYPT, AES_MANUAL, AES_XOR_OFF); /* Enable the AES low level interrupt. */ aes_isr_configure(AES_INTLVL_LO); /* Load key into AES key memory. */ aes_set_key(lastsubkey); /* Load data into AES state memory. */ aes_write_inputdata(cipher_text); /* Start encryption. */ aes_start(); do{ /* Wait until the AES interrupt is finished. */ } while (!int_end); /* Do AES encryption and decryption of multi blocks. */ //******************************************************** // CIPHER IN AUTO MODE: // - 128bit cryptographic key and data // - CBC cipher mode // - XOR on // - Interrupt call back handler //******************************************************** /* Assume no interrupt is finished. */ int_end = false; byte_count = 0; /* Set AES interrupt call back function. */ aes_set_callback(&aes_isr_cbc_encrypt_handler); /* Before using the AES it is recommended to do an AES software reset to * put the module in known state, in case other parts of your code has * accessed the AES module. */ aes_software_reset(); /* Load initial vector into AES state memory. */ aes_write_inputdata(init); /* Set AES encryption of a single block in auto mode. */ aes_configure(AES_ENCRYPT, AES_AUTO, AES_XOR_ON); /* Enable the AES low level interrupt. */ aes_isr_configure(AES_INTLVL_LO); /* Load key into AES key memory. */ aes_set_key(key); /* Load data into AES state memory. */ aes_write_inputdata(data_block); // NOTE: since we're in auto mode, the ciphering process will start as soon // as the correct number of input data is written. In this case, the // process should start when we write the sixteenth byte. do{ /* Wait until the AES interrupt is finished. */ } while (!int_end); //******************************************************** // DECIPHER IN AUTO MODE: // - 128bit cryptographic key and data // - CBC cipher mode // - XOR off // - Interrupt call back handler //******************************************************** /* Generate last subkey. */ if (!aes_lastsubkey_generate(key, lastsubkey)) { success = false; } /* Assume no interrupt is finished. */ int_end = false; byte_count = 0; /* Set AES interrupt call back function. */ aes_set_callback(&aes_isr_cbc_decrypt_handler); /* Before using the AES it is recommended to do an AES software reset to * put the module in known state, in case other parts of your code has * accessed the AES module. */ aes_software_reset(); /* Set AES decryption of a single block in auto mode. */ aes_configure(AES_DECRYPT, AES_AUTO, AES_XOR_OFF); /* Enable the AES low level interrupt. */ aes_isr_configure(AES_INTLVL_LO); /* Load key into AES key memory. */ aes_set_key(lastsubkey); /* Load data into AES state memory. */ aes_write_inputdata(cipher_block_ans); // NOTE: since we're in auto mode, the ciphering process will start as soon // as the correct number of input data is written. In this case, the // process should start when we write the sixteenth byte. do{ /* Wait until the AES interrupt is finished. */ } while (!int_end); /* Check if decrypted answer is equal to plaintext. */ for (i = 0; i < BLOCK_LENGTH * BLOCK_COUNT ; i++) { if (data_block[i] != plain_block_ans[i]){ success = false; } } /* Disable the AES clock. */ sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_AES); /* Indicate final result by lighting LED. */ if (success) { /* If the example ends up here every thing is ok. */ ioport_set_pin_low(LED0_GPIO); } else { /* If the example ends up here something is wrong. */ ioport_set_pin_low(LED1_GPIO); } while (true) { /* Go to sleep. */ sleepmgr_enter_sleep(); } }