1b0fbc02aSNicolas Toromanoff /* 26a187a00SLionel Debieve * Copyright (c) 2022-2023, STMicroelectronics - All Rights Reserved 3b0fbc02aSNicolas Toromanoff * 4b0fbc02aSNicolas Toromanoff * SPDX-License-Identifier: BSD-3-Clause 5b0fbc02aSNicolas Toromanoff */ 6b0fbc02aSNicolas Toromanoff 7b0fbc02aSNicolas Toromanoff #include <assert.h> 8b0fbc02aSNicolas Toromanoff #include <errno.h> 9b0fbc02aSNicolas Toromanoff #include <stdint.h> 10b0fbc02aSNicolas Toromanoff 11b0fbc02aSNicolas Toromanoff #include <drivers/clk.h> 12b0fbc02aSNicolas Toromanoff #include <drivers/delay_timer.h> 13b0fbc02aSNicolas Toromanoff #include <drivers/st/stm32_pka.h> 14b0fbc02aSNicolas Toromanoff #include <drivers/st/stm32mp_reset.h> 15b0fbc02aSNicolas Toromanoff #include <lib/mmio.h> 16b0fbc02aSNicolas Toromanoff #include <lib/utils.h> 17b0fbc02aSNicolas Toromanoff #include <libfdt.h> 18b0fbc02aSNicolas Toromanoff #include <plat/common/platform.h> 19b0fbc02aSNicolas Toromanoff 20b0fbc02aSNicolas Toromanoff #include <platform_def.h> 21b0fbc02aSNicolas Toromanoff 226a187a00SLionel Debieve #if !PKA_USE_NIST_P256 && !PKA_USE_BRAINPOOL_P256R1 && !PKA_USE_BRAINPOOL_P256T1 && \ 236a187a00SLionel Debieve !PKA_USE_NIST_P521 246a187a00SLionel Debieve #error "At least one ECDSA curve needs to be selected" 256a187a00SLionel Debieve #endif 266a187a00SLionel Debieve 27b0fbc02aSNicolas Toromanoff /* 28b0fbc02aSNicolas Toromanoff * For our comprehension in this file 29b0fbc02aSNicolas Toromanoff * _len are in BITs 30b0fbc02aSNicolas Toromanoff * _size are in BYTEs 31b0fbc02aSNicolas Toromanoff * _nbw are in number of PKA_word (PKA_word = u64) 32b0fbc02aSNicolas Toromanoff */ 33b0fbc02aSNicolas Toromanoff 34b0fbc02aSNicolas Toromanoff #define UINT8_LEN 8U 35b0fbc02aSNicolas Toromanoff #define UINT64_LEN (UINT8_LEN * sizeof(uint64_t)) 36*007433d8SBoyan Karatotev #define PKA_WORD_SIZE (sizeof(uint64_t)) 37b0fbc02aSNicolas Toromanoff #define OP_NBW_FROM_LEN(len) (DIV_ROUND_UP_2EVAL((len), UINT64_LEN) + 1) 38b0fbc02aSNicolas Toromanoff #define OP_NBW_FROM_SIZE(s) OP_NBW_FROM_LEN((s) * UINT8_LEN) 39*007433d8SBoyan Karatotev #define OP_SIZE_FROM_SIZE(s) (OP_NBW_FROM_SIZE(s) * PKA_WORD_SIZE) 40b0fbc02aSNicolas Toromanoff 41b0fbc02aSNicolas Toromanoff #define DT_PKA_COMPAT "st,stm32-pka64" 42b0fbc02aSNicolas Toromanoff 43b0fbc02aSNicolas Toromanoff #define MAX_ECC_SIZE_LEN 640U 44b0fbc02aSNicolas Toromanoff #define MAX_EO_NBW OP_NBW_FROM_LEN(MAX_ECC_SIZE_LEN) 45b0fbc02aSNicolas Toromanoff 46b0fbc02aSNicolas Toromanoff /* PKA registers */ 47b0fbc02aSNicolas Toromanoff /* PKA control register */ 48b0fbc02aSNicolas Toromanoff #define _PKA_CR 0x0U 49b0fbc02aSNicolas Toromanoff /* PKA status register */ 50b0fbc02aSNicolas Toromanoff #define _PKA_SR 0x4U 51b0fbc02aSNicolas Toromanoff /* PKA clear flag register */ 52b0fbc02aSNicolas Toromanoff #define _PKA_CLRFR 0x8U 53b0fbc02aSNicolas Toromanoff /* PKA version register */ 54b0fbc02aSNicolas Toromanoff #define _PKA_VERR 0x1FF4U 55b0fbc02aSNicolas Toromanoff /* PKA identification register */ 56b0fbc02aSNicolas Toromanoff #define _PKA_IPIDR 0x1FF8U 57b0fbc02aSNicolas Toromanoff 58b0fbc02aSNicolas Toromanoff /* PKA control register fields */ 59b0fbc02aSNicolas Toromanoff #define _PKA_CR_MODE_MASK GENMASK(13, 8) 60b0fbc02aSNicolas Toromanoff #define _PKA_CR_MODE_SHIFT 8U 61b0fbc02aSNicolas Toromanoff #define _PKA_CR_MODE_ADD 0x9U 62b0fbc02aSNicolas Toromanoff #define _PKA_CR_MODE_ECDSA_VERIF 0x26U 63b0fbc02aSNicolas Toromanoff #define _PKA_CR_START BIT(1) 64b0fbc02aSNicolas Toromanoff #define _PKA_CR_EN BIT(0) 65b0fbc02aSNicolas Toromanoff 66b0fbc02aSNicolas Toromanoff /* PKA status register fields */ 67b0fbc02aSNicolas Toromanoff #define _PKA_SR_BUSY BIT(16) 68b0fbc02aSNicolas Toromanoff #define _PKA_SR_LMF BIT(1) 69b0fbc02aSNicolas Toromanoff #define _PKA_SR_INITOK BIT(0) 70b0fbc02aSNicolas Toromanoff 71b0fbc02aSNicolas Toromanoff /* PKA it flag fields (used in CR, SR and CLRFR) */ 72b0fbc02aSNicolas Toromanoff #define _PKA_IT_MASK (GENMASK(21, 19) | BIT(17)) 73b0fbc02aSNicolas Toromanoff #define _PKA_IT_SHIFT 17U 74b0fbc02aSNicolas Toromanoff #define _PKA_IT_OPERR BIT(21) 75b0fbc02aSNicolas Toromanoff #define _PKA_IT_ADDRERR BIT(20) 76b0fbc02aSNicolas Toromanoff #define _PKA_IT_RAMERR BIT(19) 77b0fbc02aSNicolas Toromanoff #define _PKA_IT_PROCEND BIT(17) 78b0fbc02aSNicolas Toromanoff 79b0fbc02aSNicolas Toromanoff /* PKA version register fields */ 80b0fbc02aSNicolas Toromanoff #define _PKA_VERR_MAJREV_MASK GENMASK(7, 4) 81b0fbc02aSNicolas Toromanoff #define _PKA_VERR_MAJREV_SHIFT 4U 82b0fbc02aSNicolas Toromanoff #define _PKA_VERR_MINREV_MASK GENMASK(3, 0) 83b0fbc02aSNicolas Toromanoff #define _PKA_VERR_MINREV_SHIFT 0U 84b0fbc02aSNicolas Toromanoff 85b0fbc02aSNicolas Toromanoff /* RAM magic offset */ 86b0fbc02aSNicolas Toromanoff #define _PKA_RAM_START 0x400U 87b0fbc02aSNicolas Toromanoff #define _PKA_RAM_SIZE 5336U 88b0fbc02aSNicolas Toromanoff 89b0fbc02aSNicolas Toromanoff /* ECDSA verification */ 90b0fbc02aSNicolas Toromanoff #define _PKA_RAM_N_LEN 0x408U /* 64 */ 91b0fbc02aSNicolas Toromanoff #define _PKA_RAM_P_LEN 0x4C8U /* 64 */ 92b0fbc02aSNicolas Toromanoff #define _PKA_RAM_A_SIGN 0x468U /* 64 */ 93b0fbc02aSNicolas Toromanoff #define _PKA_RAM_A 0x470U /* EOS */ 94b0fbc02aSNicolas Toromanoff #define _PKA_RAM_P 0x4D0U /* EOS */ 95b0fbc02aSNicolas Toromanoff #define _PKA_RAM_XG 0x678U /* EOS */ 96b0fbc02aSNicolas Toromanoff #define _PKA_RAM_YG 0x6D0U /* EOS */ 97b0fbc02aSNicolas Toromanoff #define _PKA_RAM_XQ 0x12F8U /* EOS */ 98b0fbc02aSNicolas Toromanoff #define _PKA_RAM_YQ 0x1350U /* EOS */ 99b0fbc02aSNicolas Toromanoff #define _PKA_RAM_SIGN_R 0x10E0U /* EOS */ 100b0fbc02aSNicolas Toromanoff #define _PKA_RAM_SIGN_S 0xC68U /* EOS */ 101b0fbc02aSNicolas Toromanoff #define _PKA_RAM_HASH_Z 0x13A8U /* EOS */ 102b0fbc02aSNicolas Toromanoff #define _PKA_RAM_PRIME_N 0x1088U /* EOS */ 103b0fbc02aSNicolas Toromanoff #define _PKA_RAM_ECDSA_VERIFY 0x5D0U /* 64 */ 104b0fbc02aSNicolas Toromanoff #define _PKA_RAM_ECDSA_VERIFY_VALID 0xD60DULL 105b0fbc02aSNicolas Toromanoff #define _PKA_RAM_ECDSA_VERIFY_INVALID 0xA3B7ULL 106b0fbc02aSNicolas Toromanoff 107b0fbc02aSNicolas Toromanoff #define PKA_TIMEOUT_US 1000000U 108b0fbc02aSNicolas Toromanoff #define TIMEOUT_US_1MS 1000U 109b0fbc02aSNicolas Toromanoff #define PKA_RESET_DELAY 20U 110b0fbc02aSNicolas Toromanoff 111b0fbc02aSNicolas Toromanoff struct curve_parameters { 112b0fbc02aSNicolas Toromanoff uint32_t a_sign; /* 0 positive, 1 negative */ 113b0fbc02aSNicolas Toromanoff uint8_t *a; /* Curve coefficient |a| */ 114b0fbc02aSNicolas Toromanoff size_t a_size; 115b0fbc02aSNicolas Toromanoff uint8_t *p; /* Curve modulus value */ 116b0fbc02aSNicolas Toromanoff uint32_t p_len; 117b0fbc02aSNicolas Toromanoff uint8_t *xg; /* Curve base point G coordinate x */ 118b0fbc02aSNicolas Toromanoff size_t xg_size; 119b0fbc02aSNicolas Toromanoff uint8_t *yg; /* Curve base point G coordinate y */ 120b0fbc02aSNicolas Toromanoff size_t yg_size; 121b0fbc02aSNicolas Toromanoff uint8_t *n; /* Curve prime order n */ 122b0fbc02aSNicolas Toromanoff uint32_t n_len; 123b0fbc02aSNicolas Toromanoff }; 124b0fbc02aSNicolas Toromanoff 125b0fbc02aSNicolas Toromanoff static const struct curve_parameters curve_def[] = { 126b0fbc02aSNicolas Toromanoff #if PKA_USE_NIST_P256 127b0fbc02aSNicolas Toromanoff [PKA_NIST_P256] = { 128b0fbc02aSNicolas Toromanoff .p_len = 256U, 129b0fbc02aSNicolas Toromanoff .n_len = 256U, 130b0fbc02aSNicolas Toromanoff .p = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 131b0fbc02aSNicolas Toromanoff 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 132b0fbc02aSNicolas Toromanoff 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 133b0fbc02aSNicolas Toromanoff 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 134b0fbc02aSNicolas Toromanoff .n = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 135b0fbc02aSNicolas Toromanoff 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 136b0fbc02aSNicolas Toromanoff 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 137b0fbc02aSNicolas Toromanoff 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}, 138b0fbc02aSNicolas Toromanoff .a_sign = 1U, 139b0fbc02aSNicolas Toromanoff .a = (uint8_t[]){0x03}, 140b0fbc02aSNicolas Toromanoff .a_size = 1U, 141b0fbc02aSNicolas Toromanoff .xg = (uint8_t[]){0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 142b0fbc02aSNicolas Toromanoff 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 143b0fbc02aSNicolas Toromanoff 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 144b0fbc02aSNicolas Toromanoff 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96}, 145b0fbc02aSNicolas Toromanoff .xg_size = 32U, 146b0fbc02aSNicolas Toromanoff .yg = (uint8_t[]){0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 147b0fbc02aSNicolas Toromanoff 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 148b0fbc02aSNicolas Toromanoff 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 149b0fbc02aSNicolas Toromanoff 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5}, 150b0fbc02aSNicolas Toromanoff .yg_size = 32U, 151b0fbc02aSNicolas Toromanoff }, 152b0fbc02aSNicolas Toromanoff #endif 153b0fbc02aSNicolas Toromanoff #if PKA_USE_BRAINPOOL_P256R1 154b0fbc02aSNicolas Toromanoff [PKA_BRAINPOOL_P256R1] = { 155b0fbc02aSNicolas Toromanoff .p_len = 256, 156b0fbc02aSNicolas Toromanoff .n_len = 256, 157b0fbc02aSNicolas Toromanoff .p = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 158b0fbc02aSNicolas Toromanoff 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, 159b0fbc02aSNicolas Toromanoff 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, 160b0fbc02aSNicolas Toromanoff 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77}, 161b0fbc02aSNicolas Toromanoff .n = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 162b0fbc02aSNicolas Toromanoff 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71, 163b0fbc02aSNicolas Toromanoff 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, 164b0fbc02aSNicolas Toromanoff 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7}, 165b0fbc02aSNicolas Toromanoff .a = (uint8_t[]){0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, 166b0fbc02aSNicolas Toromanoff 0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7, 167b0fbc02aSNicolas Toromanoff 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C, 168b0fbc02aSNicolas Toromanoff 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9}, 169b0fbc02aSNicolas Toromanoff .a_size = 32U, 170b0fbc02aSNicolas Toromanoff .xg = (uint8_t[]){0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB, 171b0fbc02aSNicolas Toromanoff 0x2C, 0x4B, 0x48, 0x2F, 0xFC, 0x81, 0xB7, 0xAF, 172b0fbc02aSNicolas Toromanoff 0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2, 173b0fbc02aSNicolas Toromanoff 0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62}, 174b0fbc02aSNicolas Toromanoff .xg_size = 32U, 175b0fbc02aSNicolas Toromanoff .yg = (uint8_t[]){0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD, 176b0fbc02aSNicolas Toromanoff 0x97, 0xF8, 0x46, 0x1A, 0x14, 0x61, 0x1D, 0xC9, 177b0fbc02aSNicolas Toromanoff 0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54, 178b0fbc02aSNicolas Toromanoff 0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97}, 179b0fbc02aSNicolas Toromanoff .yg_size = 32U, 180b0fbc02aSNicolas Toromanoff }, 181b0fbc02aSNicolas Toromanoff #endif 182b0fbc02aSNicolas Toromanoff #if PKA_USE_BRAINPOOL_P256T1 183b0fbc02aSNicolas Toromanoff [PKA_BRAINPOOL_P256T1] = { 184b0fbc02aSNicolas Toromanoff .p_len = 256, 185b0fbc02aSNicolas Toromanoff .n_len = 256, 186b0fbc02aSNicolas Toromanoff .p = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 187b0fbc02aSNicolas Toromanoff 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, 188b0fbc02aSNicolas Toromanoff 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, 189b0fbc02aSNicolas Toromanoff 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77}, 190b0fbc02aSNicolas Toromanoff .n = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 191b0fbc02aSNicolas Toromanoff 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71, 192b0fbc02aSNicolas Toromanoff 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, 193b0fbc02aSNicolas Toromanoff 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7}, 194b0fbc02aSNicolas Toromanoff .a = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 195b0fbc02aSNicolas Toromanoff 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, 196b0fbc02aSNicolas Toromanoff 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, 197b0fbc02aSNicolas Toromanoff 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x74}, 198b0fbc02aSNicolas Toromanoff .a_size = 32U, 199b0fbc02aSNicolas Toromanoff .xg = (uint8_t[]){0xA3, 0xE8, 0xEB, 0x3C, 0xC1, 0xCF, 0xE7, 0xB7, 200b0fbc02aSNicolas Toromanoff 0x73, 0x22, 0x13, 0xB2, 0x3A, 0x65, 0x61, 0x49, 201b0fbc02aSNicolas Toromanoff 0xAF, 0xA1, 0x42, 0xC4, 0x7A, 0xAF, 0xBC, 0x2B, 202b0fbc02aSNicolas Toromanoff 0x79, 0xA1, 0x91, 0x56, 0x2E, 0x13, 0x05, 0xF4}, 203b0fbc02aSNicolas Toromanoff .xg_size = 32U, 204b0fbc02aSNicolas Toromanoff .yg = (uint8_t[]){0x2D, 0x99, 0x6C, 0x82, 0x34, 0x39, 0xC5, 0x6D, 205b0fbc02aSNicolas Toromanoff 0x7F, 0x7B, 0x22, 0xE1, 0x46, 0x44, 0x41, 0x7E, 206b0fbc02aSNicolas Toromanoff 0x69, 0xBC, 0xB6, 0xDE, 0x39, 0xD0, 0x27, 0x00, 207b0fbc02aSNicolas Toromanoff 0x1D, 0xAB, 0xE8, 0xF3, 0x5B, 0x25, 0xC9, 0xBE}, 208b0fbc02aSNicolas Toromanoff .yg_size = 32U, 209b0fbc02aSNicolas Toromanoff }, 210b0fbc02aSNicolas Toromanoff #endif 211b0fbc02aSNicolas Toromanoff #if PKA_USE_NIST_P521 212b0fbc02aSNicolas Toromanoff [PKA_NIST_P521] = { 213b0fbc02aSNicolas Toromanoff .p_len = 521, 214b0fbc02aSNicolas Toromanoff .n_len = 521, 215b0fbc02aSNicolas Toromanoff .p = (uint8_t[]){ 0x01, 0xff, 216b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 217b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 218b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 219b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 220b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 221b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 222b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 223b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 224b0fbc02aSNicolas Toromanoff .n = (uint8_t[]){ 0x01, 0xff, 225b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 226b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 227b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 228b0fbc02aSNicolas Toromanoff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 229b0fbc02aSNicolas Toromanoff 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 230b0fbc02aSNicolas Toromanoff 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, 231b0fbc02aSNicolas Toromanoff 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, 232b0fbc02aSNicolas Toromanoff 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09}, 233b0fbc02aSNicolas Toromanoff .a_sign = 1, 234b0fbc02aSNicolas Toromanoff .a = (uint8_t[]){0x03}, 235b0fbc02aSNicolas Toromanoff .a_size = 1U, 236b0fbc02aSNicolas Toromanoff .xg = (uint8_t[]){ 0xc6, 237b0fbc02aSNicolas Toromanoff 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 238b0fbc02aSNicolas Toromanoff 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 239b0fbc02aSNicolas Toromanoff 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 240b0fbc02aSNicolas Toromanoff 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 241b0fbc02aSNicolas Toromanoff 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 242b0fbc02aSNicolas Toromanoff 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, 243b0fbc02aSNicolas Toromanoff 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 244b0fbc02aSNicolas Toromanoff 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66}, 245b0fbc02aSNicolas Toromanoff .xg_size = 65U, 246b0fbc02aSNicolas Toromanoff .yg = (uint8_t[]){ 0x01, 0x18, 247b0fbc02aSNicolas Toromanoff 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 248b0fbc02aSNicolas Toromanoff 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 249b0fbc02aSNicolas Toromanoff 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 250b0fbc02aSNicolas Toromanoff 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 251b0fbc02aSNicolas Toromanoff 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 252b0fbc02aSNicolas Toromanoff 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 253b0fbc02aSNicolas Toromanoff 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 254b0fbc02aSNicolas Toromanoff 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50}, 255b0fbc02aSNicolas Toromanoff .yg_size = 66U, 256b0fbc02aSNicolas Toromanoff }, 257b0fbc02aSNicolas Toromanoff #endif 258b0fbc02aSNicolas Toromanoff }; 259b0fbc02aSNicolas Toromanoff 260b0fbc02aSNicolas Toromanoff static struct stm32_pka_platdata pka_pdata; 261b0fbc02aSNicolas Toromanoff 262b0fbc02aSNicolas Toromanoff static int stm32_pka_parse_fdt(void) 263b0fbc02aSNicolas Toromanoff { 264b0fbc02aSNicolas Toromanoff int node; 265b0fbc02aSNicolas Toromanoff struct dt_node_info info; 266b0fbc02aSNicolas Toromanoff void *fdt; 267b0fbc02aSNicolas Toromanoff 268b0fbc02aSNicolas Toromanoff if (fdt_get_address(&fdt) == 0) { 269b0fbc02aSNicolas Toromanoff return -FDT_ERR_NOTFOUND; 270b0fbc02aSNicolas Toromanoff } 271b0fbc02aSNicolas Toromanoff 272b0fbc02aSNicolas Toromanoff node = dt_get_node(&info, -1, DT_PKA_COMPAT); 273b0fbc02aSNicolas Toromanoff if (node < 0) { 274b0fbc02aSNicolas Toromanoff ERROR("No PKA entry in DT\n"); 275b0fbc02aSNicolas Toromanoff return -FDT_ERR_NOTFOUND; 276b0fbc02aSNicolas Toromanoff } 277b0fbc02aSNicolas Toromanoff 278b0fbc02aSNicolas Toromanoff if (info.status == DT_DISABLED) { 279b0fbc02aSNicolas Toromanoff return -FDT_ERR_NOTFOUND; 280b0fbc02aSNicolas Toromanoff } 281b0fbc02aSNicolas Toromanoff 282b0fbc02aSNicolas Toromanoff if ((info.base == 0) || (info.clock < 0) || (info.reset < 0)) { 283b0fbc02aSNicolas Toromanoff return -FDT_ERR_BADVALUE; 284b0fbc02aSNicolas Toromanoff } 285b0fbc02aSNicolas Toromanoff 286b0fbc02aSNicolas Toromanoff pka_pdata.base = (uintptr_t)info.base; 287b0fbc02aSNicolas Toromanoff pka_pdata.clock_id = (unsigned long)info.clock; 288b0fbc02aSNicolas Toromanoff pka_pdata.reset_id = (unsigned int)info.reset; 289b0fbc02aSNicolas Toromanoff 290b0fbc02aSNicolas Toromanoff return 0; 291b0fbc02aSNicolas Toromanoff } 292b0fbc02aSNicolas Toromanoff 293b0fbc02aSNicolas Toromanoff static int pka_wait_bit(uintptr_t base, uint32_t bit) 294b0fbc02aSNicolas Toromanoff { 295b0fbc02aSNicolas Toromanoff uint64_t timeout = timeout_init_us(PKA_TIMEOUT_US); 296b0fbc02aSNicolas Toromanoff 297b0fbc02aSNicolas Toromanoff while ((mmio_read_32(base + _PKA_SR) & bit) != bit) { 298b0fbc02aSNicolas Toromanoff if (timeout_elapsed(timeout)) { 299b0fbc02aSNicolas Toromanoff WARN("timeout waiting %x\n", bit); 300b0fbc02aSNicolas Toromanoff return -ETIMEDOUT; 301b0fbc02aSNicolas Toromanoff } 302b0fbc02aSNicolas Toromanoff } 303b0fbc02aSNicolas Toromanoff 304b0fbc02aSNicolas Toromanoff return 0; 305b0fbc02aSNicolas Toromanoff 306b0fbc02aSNicolas Toromanoff } 307b0fbc02aSNicolas Toromanoff 308b0fbc02aSNicolas Toromanoff static void pka_disable(uintptr_t base) 309b0fbc02aSNicolas Toromanoff { 310b0fbc02aSNicolas Toromanoff mmio_clrbits_32(base + _PKA_CR, _PKA_CR_EN); 311b0fbc02aSNicolas Toromanoff } 312b0fbc02aSNicolas Toromanoff 313b0fbc02aSNicolas Toromanoff static int pka_enable(uintptr_t base, uint32_t mode) 314b0fbc02aSNicolas Toromanoff { 315b0fbc02aSNicolas Toromanoff /* Set mode and disable interrupts */ 316b0fbc02aSNicolas Toromanoff mmio_clrsetbits_32(base + _PKA_CR, _PKA_IT_MASK | _PKA_CR_MODE_MASK, 317b0fbc02aSNicolas Toromanoff _PKA_CR_MODE_MASK & (mode << _PKA_CR_MODE_SHIFT)); 318b0fbc02aSNicolas Toromanoff 319b0fbc02aSNicolas Toromanoff mmio_setbits_32(base + _PKA_CR, _PKA_CR_EN); 320b0fbc02aSNicolas Toromanoff 321b0fbc02aSNicolas Toromanoff return pka_wait_bit(base, _PKA_SR_INITOK); 322b0fbc02aSNicolas Toromanoff } 323b0fbc02aSNicolas Toromanoff 324b0fbc02aSNicolas Toromanoff /* 325b0fbc02aSNicolas Toromanoff * Data are already loaded in PKA internal RAM 326b0fbc02aSNicolas Toromanoff * MODE is set 327b0fbc02aSNicolas Toromanoff * We start process, and wait for its end. 328b0fbc02aSNicolas Toromanoff */ 329b0fbc02aSNicolas Toromanoff static int stm32_pka_process(uintptr_t base) 330b0fbc02aSNicolas Toromanoff { 331b0fbc02aSNicolas Toromanoff mmio_setbits_32(base + _PKA_CR, _PKA_CR_START); 332b0fbc02aSNicolas Toromanoff 333b0fbc02aSNicolas Toromanoff return pka_wait_bit(base, _PKA_IT_PROCEND); 334b0fbc02aSNicolas Toromanoff } 335b0fbc02aSNicolas Toromanoff 336b0fbc02aSNicolas Toromanoff /** 337b0fbc02aSNicolas Toromanoff * @brief Write ECC operand to PKA RAM. 338b0fbc02aSNicolas Toromanoff * @note PKA expect to write u64 word, each u64 are: the least significant bit is 339b0fbc02aSNicolas Toromanoff * bit 0; the most significant bit is bit 63. 340b0fbc02aSNicolas Toromanoff * We write eo_nbw (ECC operand Size) u64, value that depends of the chosen 341b0fbc02aSNicolas Toromanoff * prime modulus length in bits. 342b0fbc02aSNicolas Toromanoff * First less signicant u64 is written to low address 343b0fbc02aSNicolas Toromanoff * Most significant u64 to higher address. 344b0fbc02aSNicolas Toromanoff * And at last address we write a u64(0x0) 345b0fbc02aSNicolas Toromanoff * @note This function doesn't only manage endianness (as bswap64 do), but also 346b0fbc02aSNicolas Toromanoff * complete most significant incomplete u64 with 0 (if data is not a u64 347b0fbc02aSNicolas Toromanoff * multiple), and fill u64 last address with 0. 348b0fbc02aSNicolas Toromanoff * @param addr: PKA_RAM address to write the buffer 'data' 349b0fbc02aSNicolas Toromanoff * @param data: is a BYTE list with most significant bytes first 350b0fbc02aSNicolas Toromanoff * @param data_size: nb of byte in data 351b0fbc02aSNicolas Toromanoff * @param eo_nbw: is ECC Operand size in 64bits word (including the extra 0) 352b0fbc02aSNicolas Toromanoff * (note it depends of the prime modulus length, not the data size) 353b0fbc02aSNicolas Toromanoff * @retval 0 if OK. 354b0fbc02aSNicolas Toromanoff * -EINVAL if data_size and eo_nbw are inconsistent, ie data doesn't 355b0fbc02aSNicolas Toromanoff * fit in defined eo_nbw, or eo_nbw bigger than hardware limit. 356b0fbc02aSNicolas Toromanoff */ 357b0fbc02aSNicolas Toromanoff static int write_eo_data(uintptr_t addr, uint8_t *data, unsigned int data_size, 358b0fbc02aSNicolas Toromanoff unsigned int eo_nbw) 359b0fbc02aSNicolas Toromanoff { 360b0fbc02aSNicolas Toromanoff uint32_t word_index; 361b0fbc02aSNicolas Toromanoff int data_index; 362b0fbc02aSNicolas Toromanoff 363b0fbc02aSNicolas Toromanoff if ((eo_nbw < OP_NBW_FROM_SIZE(data_size)) || (eo_nbw > MAX_EO_NBW)) { 364b0fbc02aSNicolas Toromanoff return -EINVAL; 365b0fbc02aSNicolas Toromanoff } 366b0fbc02aSNicolas Toromanoff 367b0fbc02aSNicolas Toromanoff /* Fill value */ 368b0fbc02aSNicolas Toromanoff data_index = (int)data_size - 1; 369b0fbc02aSNicolas Toromanoff for (word_index = 0U; word_index < eo_nbw; word_index++) { 370b0fbc02aSNicolas Toromanoff uint64_t tmp = 0ULL; 371b0fbc02aSNicolas Toromanoff unsigned int i = 0U; /* index in the tmp U64 word */ 372b0fbc02aSNicolas Toromanoff 373b0fbc02aSNicolas Toromanoff /* Stop if end of tmp or end of data */ 374b0fbc02aSNicolas Toromanoff while ((i < sizeof(tmp)) && (data_index >= 0)) { 375b0fbc02aSNicolas Toromanoff tmp |= (uint64_t)(data[data_index]) << (UINT8_LEN * i); 376b0fbc02aSNicolas Toromanoff i++; /* Move byte index in current (u64)tmp */ 377b0fbc02aSNicolas Toromanoff data_index--; /* Move to just next most significat byte */ 378b0fbc02aSNicolas Toromanoff } 379b0fbc02aSNicolas Toromanoff 380b0fbc02aSNicolas Toromanoff mmio_write_64(addr + word_index * sizeof(tmp), tmp); 381b0fbc02aSNicolas Toromanoff } 382b0fbc02aSNicolas Toromanoff 383b0fbc02aSNicolas Toromanoff return 0; 384b0fbc02aSNicolas Toromanoff } 385b0fbc02aSNicolas Toromanoff 386b0fbc02aSNicolas Toromanoff static unsigned int get_ecc_op_nbword(enum stm32_pka_ecdsa_curve_id cid) 387b0fbc02aSNicolas Toromanoff { 388b0fbc02aSNicolas Toromanoff if (cid >= ARRAY_SIZE(curve_def)) { 389b0fbc02aSNicolas Toromanoff ERROR("CID %u is out of boundaries\n", cid); 390b0fbc02aSNicolas Toromanoff panic(); 391b0fbc02aSNicolas Toromanoff } 392b0fbc02aSNicolas Toromanoff 393b0fbc02aSNicolas Toromanoff return OP_NBW_FROM_LEN(curve_def[cid].n_len); 394b0fbc02aSNicolas Toromanoff } 395b0fbc02aSNicolas Toromanoff 396b0fbc02aSNicolas Toromanoff static int stm32_pka_ecdsa_verif_configure_curve(uintptr_t base, enum stm32_pka_ecdsa_curve_id cid) 397b0fbc02aSNicolas Toromanoff { 398b0fbc02aSNicolas Toromanoff int ret; 399b0fbc02aSNicolas Toromanoff unsigned int eo_nbw = get_ecc_op_nbword(cid); 400b0fbc02aSNicolas Toromanoff 401b0fbc02aSNicolas Toromanoff mmio_write_64(base + _PKA_RAM_N_LEN, curve_def[cid].n_len); 402b0fbc02aSNicolas Toromanoff mmio_write_64(base + _PKA_RAM_P_LEN, curve_def[cid].p_len); 403b0fbc02aSNicolas Toromanoff mmio_write_64(base + _PKA_RAM_A_SIGN, curve_def[cid].a_sign); 404b0fbc02aSNicolas Toromanoff 405b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_A, curve_def[cid].a, curve_def[cid].a_size, eo_nbw); 406b0fbc02aSNicolas Toromanoff if (ret < 0) { 407b0fbc02aSNicolas Toromanoff return ret; 408b0fbc02aSNicolas Toromanoff } 409b0fbc02aSNicolas Toromanoff 410b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_PRIME_N, 411b0fbc02aSNicolas Toromanoff curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN), 412b0fbc02aSNicolas Toromanoff eo_nbw); 413b0fbc02aSNicolas Toromanoff if (ret < 0) { 414b0fbc02aSNicolas Toromanoff return ret; 415b0fbc02aSNicolas Toromanoff } 416b0fbc02aSNicolas Toromanoff 417b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_P, curve_def[cid].p, 418b0fbc02aSNicolas Toromanoff div_round_up(curve_def[cid].p_len, UINT8_LEN), eo_nbw); 419b0fbc02aSNicolas Toromanoff if (ret < 0) { 420b0fbc02aSNicolas Toromanoff return ret; 421b0fbc02aSNicolas Toromanoff } 422b0fbc02aSNicolas Toromanoff 423b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_XG, curve_def[cid].xg, curve_def[cid].xg_size, eo_nbw); 424b0fbc02aSNicolas Toromanoff if (ret < 0) { 425b0fbc02aSNicolas Toromanoff return ret; 426b0fbc02aSNicolas Toromanoff } 427b0fbc02aSNicolas Toromanoff 428b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_YG, curve_def[cid].yg, curve_def[cid].yg_size, eo_nbw); 429b0fbc02aSNicolas Toromanoff if (ret < 0) { 430b0fbc02aSNicolas Toromanoff return ret; 431b0fbc02aSNicolas Toromanoff } 432b0fbc02aSNicolas Toromanoff 433b0fbc02aSNicolas Toromanoff return 0; 434b0fbc02aSNicolas Toromanoff } 435b0fbc02aSNicolas Toromanoff 436b0fbc02aSNicolas Toromanoff static int stm32_pka_ecdsa_verif_check_return(uintptr_t base) 437b0fbc02aSNicolas Toromanoff { 438b0fbc02aSNicolas Toromanoff uint64_t value; 439b0fbc02aSNicolas Toromanoff uint32_t sr; 440b0fbc02aSNicolas Toromanoff 441b0fbc02aSNicolas Toromanoff sr = mmio_read_32(base + _PKA_SR); 442b0fbc02aSNicolas Toromanoff if ((sr & (_PKA_IT_OPERR | _PKA_IT_ADDRERR | _PKA_IT_RAMERR)) != 0) { 443b0fbc02aSNicolas Toromanoff WARN("Detected error(s): %s%s%s\n", 444b0fbc02aSNicolas Toromanoff (sr & _PKA_IT_OPERR) ? "Operation " : "", 445b0fbc02aSNicolas Toromanoff (sr & _PKA_IT_ADDRERR) ? "Address " : "", 446b0fbc02aSNicolas Toromanoff (sr & _PKA_IT_RAMERR) ? "RAM" : ""); 447b0fbc02aSNicolas Toromanoff return -EINVAL; 448b0fbc02aSNicolas Toromanoff } 449b0fbc02aSNicolas Toromanoff 450b0fbc02aSNicolas Toromanoff value = mmio_read_64(base + _PKA_RAM_ECDSA_VERIFY); 451b0fbc02aSNicolas Toromanoff if (value == _PKA_RAM_ECDSA_VERIFY_VALID) { 452b0fbc02aSNicolas Toromanoff return 0; 453b0fbc02aSNicolas Toromanoff } 454b0fbc02aSNicolas Toromanoff 455b0fbc02aSNicolas Toromanoff if (value == _PKA_RAM_ECDSA_VERIFY_INVALID) { 456b0fbc02aSNicolas Toromanoff return -EAUTH; 457b0fbc02aSNicolas Toromanoff } 458b0fbc02aSNicolas Toromanoff 459b0fbc02aSNicolas Toromanoff return -EINVAL; 460b0fbc02aSNicolas Toromanoff } 461b0fbc02aSNicolas Toromanoff 462b0fbc02aSNicolas Toromanoff /** 463b0fbc02aSNicolas Toromanoff * @brief Check if BigInt stored in data is 0 464b0fbc02aSNicolas Toromanoff * 465b0fbc02aSNicolas Toromanoff * @param data: a BYTE array with most significant bytes first 466b0fbc02aSNicolas Toromanoff * @param size: data size 467b0fbc02aSNicolas Toromanoff * 468b0fbc02aSNicolas Toromanoff * @retval: true: if data represents a 0 value (ie all bytes == 0) 469b0fbc02aSNicolas Toromanoff * false: if data represents a non-zero value. 470b0fbc02aSNicolas Toromanoff */ 471b0fbc02aSNicolas Toromanoff static bool is_zero(uint8_t *data, unsigned int size) 472b0fbc02aSNicolas Toromanoff { 473b0fbc02aSNicolas Toromanoff unsigned int i; 474b0fbc02aSNicolas Toromanoff 475b0fbc02aSNicolas Toromanoff for (i = 0U; i < size; i++) { 476b0fbc02aSNicolas Toromanoff if (data[i] != 0U) { 477b0fbc02aSNicolas Toromanoff return false; 478b0fbc02aSNicolas Toromanoff } 479b0fbc02aSNicolas Toromanoff } 480b0fbc02aSNicolas Toromanoff 481b0fbc02aSNicolas Toromanoff return true; 482b0fbc02aSNicolas Toromanoff } 483b0fbc02aSNicolas Toromanoff 484b0fbc02aSNicolas Toromanoff /** 485b0fbc02aSNicolas Toromanoff * @brief Compare two BigInt: 486b0fbc02aSNicolas Toromanoff * @param xdata_a: a BYTE array with most significant bytes first 487b0fbc02aSNicolas Toromanoff * @param size_a: nb of Byte of 'a' 488b0fbc02aSNicolas Toromanoff * @param data_b: a BYTE array with most significant bytes first 489b0fbc02aSNicolas Toromanoff * @param size_b: nb of Byte of 'b' 490b0fbc02aSNicolas Toromanoff * 491b0fbc02aSNicolas Toromanoff * @retval: true if data_a < data_b 492b0fbc02aSNicolas Toromanoff * false if data_a >= data_b 493b0fbc02aSNicolas Toromanoff */ 494b0fbc02aSNicolas Toromanoff static bool is_smaller(uint8_t *data_a, unsigned int size_a, 495b0fbc02aSNicolas Toromanoff uint8_t *data_b, unsigned int size_b) 496b0fbc02aSNicolas Toromanoff { 497b0fbc02aSNicolas Toromanoff unsigned int i; 498b0fbc02aSNicolas Toromanoff 499b0fbc02aSNicolas Toromanoff i = MAX(size_a, size_b) + 1U; 500b0fbc02aSNicolas Toromanoff do { 501b0fbc02aSNicolas Toromanoff uint8_t a, b; 502b0fbc02aSNicolas Toromanoff 503b0fbc02aSNicolas Toromanoff i--; 504b0fbc02aSNicolas Toromanoff if (size_a < i) { 505b0fbc02aSNicolas Toromanoff a = 0U; 506b0fbc02aSNicolas Toromanoff } else { 507b0fbc02aSNicolas Toromanoff a = data_a[size_a - i]; 508b0fbc02aSNicolas Toromanoff } 509b0fbc02aSNicolas Toromanoff 510b0fbc02aSNicolas Toromanoff if (size_b < i) { 511b0fbc02aSNicolas Toromanoff b = 0U; 512b0fbc02aSNicolas Toromanoff } else { 513b0fbc02aSNicolas Toromanoff b = data_b[size_b - i]; 514b0fbc02aSNicolas Toromanoff } 515b0fbc02aSNicolas Toromanoff 516b0fbc02aSNicolas Toromanoff if (a < b) { 517b0fbc02aSNicolas Toromanoff return true; 518b0fbc02aSNicolas Toromanoff } 519b0fbc02aSNicolas Toromanoff 520b0fbc02aSNicolas Toromanoff if (a > b) { 521b0fbc02aSNicolas Toromanoff return false; 522b0fbc02aSNicolas Toromanoff } 523b0fbc02aSNicolas Toromanoff } while (i != 0U); 524b0fbc02aSNicolas Toromanoff 525b0fbc02aSNicolas Toromanoff return false; 526b0fbc02aSNicolas Toromanoff } 527b0fbc02aSNicolas Toromanoff 528b0fbc02aSNicolas Toromanoff static int stm32_pka_ecdsa_check_param(void *sig_r_ptr, unsigned int sig_r_size, 529b0fbc02aSNicolas Toromanoff void *sig_s_ptr, unsigned int sig_s_size, 530b0fbc02aSNicolas Toromanoff void *pk_x_ptr, unsigned int pk_x_size, 531b0fbc02aSNicolas Toromanoff void *pk_y_ptr, unsigned int pk_y_size, 532b0fbc02aSNicolas Toromanoff enum stm32_pka_ecdsa_curve_id cid) 533b0fbc02aSNicolas Toromanoff { 534b0fbc02aSNicolas Toromanoff /* Public Key check */ 535b0fbc02aSNicolas Toromanoff /* Check Xq < p */ 536b0fbc02aSNicolas Toromanoff if (!is_smaller(pk_x_ptr, pk_x_size, 537b0fbc02aSNicolas Toromanoff curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) { 538b0fbc02aSNicolas Toromanoff WARN("%s Xq < p inval\n", __func__); 539b0fbc02aSNicolas Toromanoff return -EINVAL; 540b0fbc02aSNicolas Toromanoff } 541b0fbc02aSNicolas Toromanoff 542b0fbc02aSNicolas Toromanoff /* Check Yq < p */ 543b0fbc02aSNicolas Toromanoff if (!is_smaller(pk_y_ptr, pk_y_size, 544b0fbc02aSNicolas Toromanoff curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) { 545b0fbc02aSNicolas Toromanoff WARN("%s Yq < p inval\n", __func__); 546b0fbc02aSNicolas Toromanoff return -EINVAL; 547b0fbc02aSNicolas Toromanoff } 548b0fbc02aSNicolas Toromanoff 549b0fbc02aSNicolas Toromanoff /* Signature check */ 550b0fbc02aSNicolas Toromanoff /* Check 0 < r < n */ 551b0fbc02aSNicolas Toromanoff if (!is_smaller(sig_r_ptr, sig_r_size, 552b0fbc02aSNicolas Toromanoff curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) && 553b0fbc02aSNicolas Toromanoff !is_zero(sig_r_ptr, sig_r_size)) { 554b0fbc02aSNicolas Toromanoff WARN("%s 0< r < n inval\n", __func__); 555b0fbc02aSNicolas Toromanoff return -EINVAL; 556b0fbc02aSNicolas Toromanoff } 557b0fbc02aSNicolas Toromanoff 558b0fbc02aSNicolas Toromanoff /* Check 0 < s < n */ 559b0fbc02aSNicolas Toromanoff if (!is_smaller(sig_s_ptr, sig_s_size, 560b0fbc02aSNicolas Toromanoff curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) && 561b0fbc02aSNicolas Toromanoff !is_zero(sig_s_ptr, sig_s_size)) { 562b0fbc02aSNicolas Toromanoff WARN("%s 0< s < n inval\n", __func__); 563b0fbc02aSNicolas Toromanoff return -EINVAL; 564b0fbc02aSNicolas Toromanoff } 565b0fbc02aSNicolas Toromanoff 566b0fbc02aSNicolas Toromanoff return 0; 567b0fbc02aSNicolas Toromanoff } 568b0fbc02aSNicolas Toromanoff 569b0fbc02aSNicolas Toromanoff /* 570b0fbc02aSNicolas Toromanoff * @brief Initialize the PKA driver. 571b0fbc02aSNicolas Toromanoff * @param None. 572b0fbc02aSNicolas Toromanoff * @retval 0 if OK, negative value else. 573b0fbc02aSNicolas Toromanoff */ 574b0fbc02aSNicolas Toromanoff int stm32_pka_init(void) 575b0fbc02aSNicolas Toromanoff { 576b0fbc02aSNicolas Toromanoff int err; 577b0fbc02aSNicolas Toromanoff #if LOG_LEVEL >= LOG_LEVEL_VERBOSE 578b0fbc02aSNicolas Toromanoff uint32_t ver; 579b0fbc02aSNicolas Toromanoff uint32_t id; 580b0fbc02aSNicolas Toromanoff #endif 581b0fbc02aSNicolas Toromanoff 582b0fbc02aSNicolas Toromanoff err = stm32_pka_parse_fdt(); 583b0fbc02aSNicolas Toromanoff if (err != 0) { 584b0fbc02aSNicolas Toromanoff return err; 585b0fbc02aSNicolas Toromanoff } 586b0fbc02aSNicolas Toromanoff 587b0fbc02aSNicolas Toromanoff clk_enable(pka_pdata.clock_id); 588b0fbc02aSNicolas Toromanoff 589b0fbc02aSNicolas Toromanoff if (stm32mp_reset_assert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) { 590b0fbc02aSNicolas Toromanoff panic(); 591b0fbc02aSNicolas Toromanoff } 592b0fbc02aSNicolas Toromanoff 593b0fbc02aSNicolas Toromanoff udelay(PKA_RESET_DELAY); 594b0fbc02aSNicolas Toromanoff if (stm32mp_reset_deassert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) { 595b0fbc02aSNicolas Toromanoff panic(); 596b0fbc02aSNicolas Toromanoff } 597b0fbc02aSNicolas Toromanoff 598b0fbc02aSNicolas Toromanoff #if LOG_LEVEL >= LOG_LEVEL_VERBOSE 599b0fbc02aSNicolas Toromanoff id = mmio_read_32(pka_pdata.base + _PKA_IPIDR); 600b0fbc02aSNicolas Toromanoff ver = mmio_read_32(pka_pdata.base + _PKA_VERR); 601b0fbc02aSNicolas Toromanoff 602b0fbc02aSNicolas Toromanoff VERBOSE("STM32 PKA[%x] V%u.%u\n", id, 603b0fbc02aSNicolas Toromanoff (ver & _PKA_VERR_MAJREV_MASK) >> _PKA_VERR_MAJREV_SHIFT, 604b0fbc02aSNicolas Toromanoff (ver & _PKA_VERR_MINREV_MASK) >> _PKA_VERR_MINREV_SHIFT); 605b0fbc02aSNicolas Toromanoff #endif 606b0fbc02aSNicolas Toromanoff return 0; 607b0fbc02aSNicolas Toromanoff } 608b0fbc02aSNicolas Toromanoff 609b0fbc02aSNicolas Toromanoff int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size, 610b0fbc02aSNicolas Toromanoff void *sig_r_ptr, unsigned int sig_r_size, 611b0fbc02aSNicolas Toromanoff void *sig_s_ptr, unsigned int sig_s_size, 612b0fbc02aSNicolas Toromanoff void *pk_x_ptr, unsigned int pk_x_size, 613b0fbc02aSNicolas Toromanoff void *pk_y_ptr, unsigned int pk_y_size, 614b0fbc02aSNicolas Toromanoff enum stm32_pka_ecdsa_curve_id cid) 615b0fbc02aSNicolas Toromanoff { 616b0fbc02aSNicolas Toromanoff int ret; 617b0fbc02aSNicolas Toromanoff uintptr_t base = pka_pdata.base; 618b0fbc02aSNicolas Toromanoff unsigned int eo_nbw = get_ecc_op_nbword(cid); 619b0fbc02aSNicolas Toromanoff 620b0fbc02aSNicolas Toromanoff if ((hash == NULL) || (sig_r_ptr == NULL) || (sig_s_ptr == NULL) || 621b0fbc02aSNicolas Toromanoff (pk_x_ptr == NULL) || (pk_y_ptr == NULL)) { 622b0fbc02aSNicolas Toromanoff INFO("%s invalid input param\n", __func__); 623b0fbc02aSNicolas Toromanoff return -EINVAL; 624b0fbc02aSNicolas Toromanoff } 625b0fbc02aSNicolas Toromanoff 626b0fbc02aSNicolas Toromanoff ret = stm32_pka_ecdsa_check_param(sig_r_ptr, sig_r_size, 627b0fbc02aSNicolas Toromanoff sig_s_ptr, sig_s_size, 628b0fbc02aSNicolas Toromanoff pk_x_ptr, pk_x_size, 629b0fbc02aSNicolas Toromanoff pk_y_ptr, pk_y_size, 630b0fbc02aSNicolas Toromanoff cid); 631b0fbc02aSNicolas Toromanoff if (ret < 0) { 632b0fbc02aSNicolas Toromanoff INFO("%s check param error %d\n", __func__, ret); 633b0fbc02aSNicolas Toromanoff goto out; 634b0fbc02aSNicolas Toromanoff } 635b0fbc02aSNicolas Toromanoff 636b0fbc02aSNicolas Toromanoff if ((mmio_read_32(base + _PKA_SR) & _PKA_SR_BUSY) == _PKA_SR_BUSY) { 637b0fbc02aSNicolas Toromanoff INFO("%s busy\n", __func__); 638b0fbc02aSNicolas Toromanoff ret = -EBUSY; 639b0fbc02aSNicolas Toromanoff goto out; 640b0fbc02aSNicolas Toromanoff } 641b0fbc02aSNicolas Toromanoff 642b0fbc02aSNicolas Toromanoff /* Fill PKA RAM */ 643b0fbc02aSNicolas Toromanoff /* With curve id values */ 644b0fbc02aSNicolas Toromanoff ret = stm32_pka_ecdsa_verif_configure_curve(base, cid); 645b0fbc02aSNicolas Toromanoff if (ret < 0) { 646b0fbc02aSNicolas Toromanoff goto out; 647b0fbc02aSNicolas Toromanoff } 648b0fbc02aSNicolas Toromanoff 649b0fbc02aSNicolas Toromanoff /* With pubkey */ 650b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_XQ, pk_x_ptr, pk_x_size, eo_nbw); 651b0fbc02aSNicolas Toromanoff if (ret < 0) { 652b0fbc02aSNicolas Toromanoff goto out; 653b0fbc02aSNicolas Toromanoff } 654b0fbc02aSNicolas Toromanoff 655b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_YQ, pk_y_ptr, pk_y_size, eo_nbw); 656b0fbc02aSNicolas Toromanoff if (ret < 0) { 657b0fbc02aSNicolas Toromanoff goto out; 658b0fbc02aSNicolas Toromanoff } 659b0fbc02aSNicolas Toromanoff 660b0fbc02aSNicolas Toromanoff /* With hash */ 661b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_HASH_Z, hash, hash_size, eo_nbw); 662b0fbc02aSNicolas Toromanoff if (ret < 0) { 663b0fbc02aSNicolas Toromanoff goto out; 664b0fbc02aSNicolas Toromanoff } 665b0fbc02aSNicolas Toromanoff 666b0fbc02aSNicolas Toromanoff /* With signature */ 667b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_SIGN_R, sig_r_ptr, sig_r_size, eo_nbw); 668b0fbc02aSNicolas Toromanoff if (ret < 0) { 669b0fbc02aSNicolas Toromanoff goto out; 670b0fbc02aSNicolas Toromanoff } 671b0fbc02aSNicolas Toromanoff 672b0fbc02aSNicolas Toromanoff ret = write_eo_data(base + _PKA_RAM_SIGN_S, sig_s_ptr, sig_s_size, eo_nbw); 673b0fbc02aSNicolas Toromanoff if (ret < 0) { 674b0fbc02aSNicolas Toromanoff goto out; 675b0fbc02aSNicolas Toromanoff } 676b0fbc02aSNicolas Toromanoff 677b0fbc02aSNicolas Toromanoff /* Set mode to ecdsa signature verification */ 678b0fbc02aSNicolas Toromanoff ret = pka_enable(base, _PKA_CR_MODE_ECDSA_VERIF); 679b0fbc02aSNicolas Toromanoff if (ret < 0) { 680b0fbc02aSNicolas Toromanoff WARN("%s set mode pka error %d\n", __func__, ret); 681b0fbc02aSNicolas Toromanoff goto out; 682b0fbc02aSNicolas Toromanoff } 683b0fbc02aSNicolas Toromanoff 684b0fbc02aSNicolas Toromanoff /* Start processing and wait end */ 685b0fbc02aSNicolas Toromanoff ret = stm32_pka_process(base); 686b0fbc02aSNicolas Toromanoff if (ret < 0) { 687b0fbc02aSNicolas Toromanoff WARN("%s process error %d\n", __func__, ret); 688b0fbc02aSNicolas Toromanoff goto out; 689b0fbc02aSNicolas Toromanoff } 690b0fbc02aSNicolas Toromanoff 691b0fbc02aSNicolas Toromanoff /* Check return status */ 692b0fbc02aSNicolas Toromanoff ret = stm32_pka_ecdsa_verif_check_return(base); 693b0fbc02aSNicolas Toromanoff 694b0fbc02aSNicolas Toromanoff /* Unset end proc */ 695b0fbc02aSNicolas Toromanoff mmio_setbits_32(base + _PKA_CLRFR, _PKA_IT_PROCEND); 696b0fbc02aSNicolas Toromanoff 697b0fbc02aSNicolas Toromanoff out: 6981b491eeaSElyes Haouas /* Disable PKA (will stop all pending process and reset RAM) */ 699b0fbc02aSNicolas Toromanoff pka_disable(base); 700b0fbc02aSNicolas Toromanoff 701b0fbc02aSNicolas Toromanoff return ret; 702b0fbc02aSNicolas Toromanoff } 703