/** ****************************************************************************** * @file ECC/ECDSA_SignVerify/Src/main.c * @author MCD Application Team * @brief This example provides a short description of how to use the * STM32 Cryptographic Library ****************************************************************************** * @attention * * Copyright (c) 2021 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file in * the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include #include "main.h" #include "cmox_crypto.h" /* Global variables ----------------------------------------------------------*/ /* ECC context */ cmox_ecc_handle_t Ecc_Ctx; /* ECC working buffer */ uint8_t Working_Buffer[2000]; /* Random data buffer */ uint32_t Computed_Random[8]; /* RNG peripheral handle */ RNG_HandleTypeDef hrng; __IO TestStatus glob_status = FAILED; /* Private typedef -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/ /* Private macros ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ // https://github.com/pyca/cryptography/blob/main/vectors/cryptography_vectors/asymmetric/ECDSA/SECP256K1/SigGen.txt#L6314 // [K-256,SHA-256] // Msg = 5c868fedb8026979ebd26f1ba07c27eedf4ff6d10443505a96ecaf21ba8c4f0937b3cd23ffdc3dd429d4cd1905fb8dbcceeff1350020e18b58d2ba70887baa3a9b783ad30d3fbf210331cdd7df8d77defa398cdacdfc2e359c7ba4cae46bb74401deb417f8b912a1aa966aeeba9c39c7dd22479ae2b30719dca2f2206c5eb4b7 // d = 42202a98374f6dca439c0af88140e41f8eced3062682ec7f9fc8ac9ea83c7cb2 // Qx = 131ca4e5811267fa90fc631d6298c2d7a4ecccc45cc60d378e0660b61f82fe8d // Qy = cf5acf8ed3e0bbf735308cc415604bd34ab8f7fc8b4a22741117a7fbc72a7949 // R = d89f9586070230bb03e625cca18c89bb3117cd472ff6ee2a50809f0e89039309 // S = 45972842e92e3a41abeea1089d812eb5343ca8f075ac9c66e13f3db287048638 static uint8_t msg[] = { // Message 0x5c,0x86,0x8f,0xed,0xb8,0x02,0x69,0x79,0xeb,0xd2,0x6f,0x1b,0xa0,0x7c,0x27,0xee, // Msg 0xdf,0x4f,0xf6,0xd1,0x04,0x43,0x50,0x5a,0x96,0xec,0xaf,0x21,0xba,0x8c,0x4f,0x09, 0x37,0xb3,0xcd,0x23,0xff,0xdc,0x3d,0xd4,0x29,0xd4,0xcd,0x19,0x05,0xfb,0x8d,0xbc, 0xce,0xef,0xf1,0x35,0x00,0x20,0xe1,0x8b,0x58,0xd2,0xba,0x70,0x88,0x7b,0xaa,0x3a, 0x9b,0x78,0x3a,0xd3,0x0d,0x3f,0xbf,0x21,0x03,0x31,0xcd,0xd7,0xdf,0x8d,0x77,0xde, 0xfa,0x39,0x8c,0xda,0xcd,0xfc,0x2e,0x35,0x9c,0x7b,0xa4,0xca,0xe4,0x6b,0xb7,0x44, 0x01,0xde,0xb4,0x17,0xf8,0xb9,0x12,0xa1,0xaa,0x96,0x6a,0xee,0xba,0x9c,0x39,0xc7, 0xdd,0x22,0x47,0x9a,0xe2,0xb3,0x07,0x19,0xdc,0xa2,0xf2,0x20,0x6c,0x5e,0xb4,0xb7 }; static uint8_t digest[] = { // Digest (sha256) Actual 0x5a,0xe8,0x31,0x7d,0x34,0xd1,0xe5,0x95,0xe3,0xfa,0x72,0x47,0xdb,0x80,0xc0,0xaf, // sha256(Msg) 0x43,0x20,0xcc,0xe1,0x11,0x6d,0xe1,0x87,0xf8,0xf7,0xe2,0xe0,0x99,0xc0,0xd8,0xd0 }; const uint8_t Known_Random[] = /* = k - 1 */ { 0x58, 0xf7, 0x41, 0x77, 0x16, 0x20, 0xbd, 0xc4, 0x28, 0xe9, 0x1a, 0x32, 0xd8, 0x6d, 0x23, 0x08, 0x73, 0xe9, 0x14, 0x03, 0x36, 0xfc, 0xfb, 0x1e, 0x12, 0x28, 0x92, 0xee, 0x1d, 0x50, 0x1b, 0xdb }; static uint8_t keyprivate[] = { // Private Key 0x42,0x20,0x2a,0x98,0x37,0x4f,0x6d,0xca,0x43,0x9c,0x0a,0xf8,0x81,0x40,0xe4,0x1f, // d 0x8e,0xce,0xd3,0x06,0x26,0x82,0xec,0x7f,0x9f,0xc8,0xac,0x9e,0xa8,0x3c,0x7c,0xb2 }; static uint8_t key[] = { // Public Key 0x13,0x1c,0xa4,0xe5,0x81,0x12,0x67,0xfa,0x90,0xfc,0x63,0x1d,0x62,0x98,0xc2,0xd7, // Qx 0xa4,0xec,0xcc,0xc4,0x5c,0xc6,0x0d,0x37,0x8e,0x06,0x60,0xb6,0x1f,0x82,0xfe,0x8d, 0xcf,0x5a,0xcf,0x8e,0xd3,0xe0,0xbb,0xf7,0x35,0x30,0x8c,0xc4,0x15,0x60,0x4b,0xd3, // Qy 0x4a,0xb8,0xf7,0xfc,0x8b,0x4a,0x22,0x74,0x11,0x17,0xa7,0xfb,0xc7,0x2a,0x79,0x49 }; static uint8_t signature[] = { // Signature (sha256) 0xd8,0x9f,0x95,0x86,0x07,0x02,0x30,0xbb,0x03,0xe6,0x25,0xcc,0xa1,0x8c,0x89,0xbb, // R 0x31,0x17,0xcd,0x47,0x2f,0xf6,0xee,0x2a,0x50,0x80,0x9f,0x0e,0x89,0x03,0x93,0x09, 0x45,0x97,0x28,0x42,0xe9,0x2e,0x3a,0x41,0xab,0xee,0xa1,0x08,0x9d,0x81,0x2e,0xb5, // S 0x34,0x3c,0xa8,0xf0,0x75,0xac,0x9c,0x66,0xe1,0x3f,0x3d,0xb2,0x87,0x04,0x86,0x38 }; char sQx[] = "131ca4e5811267fa90fc631d6298c2d7a4ecccc45cc60d378e0660b61f82fe8d"; char sQy[] = "cf5acf8ed3e0bbf735308cc415604bd34ab8f7fc8b4a22741117a7fbc72a7949"; /* Computed data buffer */ uint8_t Computed_Hash[CMOX_SHA256_SIZE]; uint8_t Computed_Signature[CMOX_ECC_SECP256K1_SIG_LEN]; cmox_hash_retval_t hretval; cmox_ecc_retval_t retval; /* Private function prototypes -----------------------------------------------*/ static void SystemClock_Config(void); static void Error_Handler(void); /* Functions Definition ------------------------------------------------------*/ /** * @brief Main program * @param None * @retval None */ int main(void) { size_t computed_size; /* Fault check verification variable */ uint32_t fault_check = CMOX_ECC_AUTH_FAIL; /* STM32G4xx HAL library initialization: - Configure the Flash prefetch - Systick timer is configured by default as source of time base, but user can eventually implement his proper time base source (a general purpose timer for example or other time source), keeping in mind that Time base duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and handled in milliseconds basis. - Set NVIC Group Priority to 4 - Low Level Initialization */ HAL_Init(); /* Configure the System clock */ SystemClock_Config(); /* Configure LED2 */ BSP_LED_Init(LED2); /* Initialize cryptographic library */ if (cmox_initialize(NULL) != CMOX_INIT_SUCCESS) { Error_Handler(); } /* Compute directly the digest passing all the needed parameters */ hretval = cmox_hash_compute(CMOX_SHA256_ALGO, /* Use SHA224 algorithm */ msg, sizeof(msg), /* Message to digest */ Computed_Hash, /* Data buffer to receive digest data */ CMOX_SHA256_SIZE, /* Expected digest size */ &computed_size); /* Size of computed digest */ /* Verify API returned value */ if (hretval != CMOX_HASH_SUCCESS) { Error_Handler(); } /* Verify generated data size is the expected one */ if (computed_size != CMOX_SHA256_SIZE) { Error_Handler(); } /* -------------------------------------------------------------------------- * KNOWN RANDOM USAGE * -------------------------------------------------------------------------- */ /* Construct a ECC context, specifying mathematics implementation and working buffer for later processing */ /* Note: CMOX_ECC256_MATH_FUNCS refer to the default mathematics implementation * selected in cmox_default_config.h. To use a specific implementation, user can * directly choose: * - CMOX_MATH_FUNCS_SMALL to select the mathematics small implementation * - CMOX_MATH_FUNCS_FAST to select the mathematics fast implementation * - CMOX_MATH_FUNCS_SUPERFAST256 to select the mathematics fast implementation optimized for 256 bits computation */ cmox_ecc_construct(&Ecc_Ctx, CMOX_ECC256_MATH_FUNCS, Working_Buffer, sizeof(Working_Buffer)); /* Compute directly the signature passing all the needed parameters */ /* Note: CMOX_ECC_CURVE_SECP256R1 refer to the default SECP256R1 definition * selected in cmox_default_config.h. To use a specific definition, user can * directly choose: * - CMOX_ECC_SECP256R1_LOWMEM to select the low RAM usage definition (slower computing) * - CMOX_ECC_SECP256R1_HIGHMEM to select the high RAM usage definition (faster computing) */ retval = cmox_ecdsa_sign(&Ecc_Ctx, /* ECC context */ CMOX_ECC_SECP256K1_LOWMEM, /* SECP256R1 ECC curve selected */ Known_Random, sizeof(Known_Random), /* Random data buffer */ keyprivate, sizeof(keyprivate), /* Private key for signature */ Computed_Hash, CMOX_SHA256_SIZE, /* Digest to sign */ Computed_Signature, &computed_size); /* Data buffer to receive signature */ /* Verify API returned value */ if (retval != CMOX_ECC_SUCCESS) { Error_Handler(); } /* Verify generated data size is the expected one */ if (computed_size != sizeof(Computed_Signature)) { Error_Handler(); } // /* Verify generated data are the expected ones */ // if (memcmp(Computed_Signature, Known_Signature, computed_size) != 0) // { // Error_Handler(); // } // /* Cleanup context */ cmox_ecc_cleanup(&Ecc_Ctx); /* Construct a ECC context, specifying mathematics implementation and working buffer for later processing */ /* Note: CMOX_ECC256_MATH_FUNCS refer to the default mathematics implementation * selected in cmox_default_config.h. To use a specific implementation, user can * directly choose: * - CMOX_MATH_FUNCS_SMALL to select the mathematics small implementation * - CMOX_MATH_FUNCS_FAST to select the mathematics fast implementation * - CMOX_MATH_FUNCS_SUPERFAST256 to select the mathematics fast implementation optimized for 256 bits computation */ cmox_ecc_construct(&Ecc_Ctx, CMOX_ECC256_MATH_FUNCS, Working_Buffer, sizeof(Working_Buffer)); /* Verify directly the signature passing all the needed parameters */ /* Note: CMOX_ECC_CURVE_SECP256R1 refer to the default SECP256R1 definition * selected in cmox_default_config.h. To use a specific definition, user can * directly choose: * - CMOX_ECC_SECP256R1_LOWMEM to select the low RAM usage definition (slower computing) * - CMOX_ECC_SECP256R1_HIGHMEM to select the high RAM usage definition (faster computing) */ retval = cmox_ecdsa_verify(&Ecc_Ctx, /* ECC context */ CMOX_ECC_SECP256K1_LOWMEM, /* SECP256R1 ECC curve selected */ key, sizeof(key), /* Public key for verification */ Computed_Hash, CMOX_SHA256_SIZE, /* Digest to verify */ signature, sizeof(signature), /* Data buffer to receive signature */ &fault_check); /* Fault check variable: to ensure no fault injection occurs during this API call */ /* Verify API returned value */ if (retval != CMOX_ECC_AUTH_SUCCESS) { Error_Handler(); } /* Verify Fault check variable value */ if (fault_check != CMOX_ECC_AUTH_SUCCESS) { Error_Handler(); } /* Cleanup context */ cmox_ecc_cleanup(&Ecc_Ctx); /* Turn on LED2 in an infinite loop in case of ECC ECDSA operations are successful */ BSP_LED_On(LED2); glob_status = PASSED; while (1) {} } /** * @brief System Clock Configuration * The system Clock is configured as follow : * System Clock source = PLL (HSI) * SYSCLK(Hz) = 170000000 * HCLK(Hz) = 170000000 * AHB Prescaler = 1 * APB1 Prescaler = 1 * APB2 Prescaler = 1 * HSI Frequency(Hz) = 16000000 * PLL_M = 4 * PLL_N = 85 * PLL_P = 2 * PLL_Q = 2 * PLL_R = 2 * Flash Latency(WS) = 8 * @param None * @retval None */ static void SystemClock_Config(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; /* Enable voltage range 1 boost mode for frequency above 150 Mhz */ __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); __HAL_RCC_PWR_CLK_DISABLE(); /* Activate PLL with HSI as source */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4; RCC_OscInitStruct.PLL.PLLN = 85; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { /* Initialization Error */ while (1); } /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | \ RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8) != HAL_OK) { /* Initialization Error */ while (1); } } /** * @brief This function is executed in case of error occurrence * @param None * @retval None */ static void Error_Handler(void) { /* User may add here some code to deal with this error */ /* Toggle LED2 @2Hz to notify error condition */ while (1) { BSP_LED_Toggle(LED2); HAL_Delay(250); } } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) {} } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/