1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) Foundries Ltd. 2022. 4 * Author: Jorge Ramirez <jorge@foundries.io> 5 */ 6 7 #include <drvcrypt.h> 8 #include <drvcrypt_acipher.h> 9 #include <crypto/crypto_impl.h> 10 #include <ecc.h> 11 #include <initcall.h> 12 #include <kernel/panic.h> 13 #include <mm/core_memprot.h> 14 #include <string.h> 15 #include <tee/cache.h> 16 #include <tee/tee_cryp_utl.h> 17 #include <util.h> 18 19 /* Software based ECDSA operations */ 20 static const struct crypto_ecc_keypair_ops *pair_ops; 21 static const struct crypto_ecc_public_ops *pub_ops; 22 23 static TEE_Result shared_secret(struct ecc_keypair *private_key, 24 struct ecc_public_key *public_key, 25 void *secret, size_t *secret_len) 26 { 27 return pair_ops->shared_secret(private_key, public_key, 28 secret, secret_len); 29 } 30 31 static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) 32 { 33 return shared_secret(sdata->key_priv, 34 sdata->key_pub, 35 sdata->secret.data, 36 &sdata->secret.length); 37 } 38 39 static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) 40 { 41 TEE_Result ret = TEE_SUCCESS; 42 43 ret = versal_ecc_sign(sdata->algo, 44 sdata->key, 45 sdata->message.data, 46 sdata->message.length, 47 sdata->signature.data, 48 &sdata->signature.length); 49 50 if (ret == TEE_ERROR_NOT_SUPPORTED) { 51 /* Fallback to software */ 52 return pair_ops->sign(sdata->algo, sdata->key, 53 sdata->message.data, 54 sdata->message.length, 55 sdata->signature.data, 56 &sdata->signature.length); 57 } 58 59 return ret; 60 } 61 62 static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) 63 { 64 TEE_Result ret = TEE_SUCCESS; 65 66 ret = versal_ecc_verify(sdata->algo, 67 sdata->key, 68 sdata->message.data, 69 sdata->message.length, 70 sdata->signature.data, 71 sdata->signature.length); 72 73 if (ret == TEE_ERROR_NOT_SUPPORTED) { 74 /* Fallback to software */ 75 return pub_ops->verify(sdata->algo, sdata->key, 76 sdata->message.data, 77 sdata->message.length, 78 sdata->signature.data, 79 sdata->signature.length); 80 } 81 82 return ret; 83 } 84 85 static TEE_Result do_gen_keypair(struct ecc_keypair *s, size_t size_bits) 86 { 87 TEE_Result ret = TEE_SUCCESS; 88 89 /* 90 * Versal requires little endian so need to versal_memcpy_swp on Versal 91 * IP ops. We chose not to do it here because some tests might be using 92 * their own keys 93 */ 94 ret = versal_ecc_gen_keypair(s); 95 96 if (ret == TEE_ERROR_NOT_SUPPORTED) 97 /* Fallback to software */ 98 return pair_ops->generate(s, size_bits); 99 100 #ifdef CFG_VERSAL_PKI_PWCT 101 if (ret) 102 return ret; 103 104 /* Perform a pairwise consistencty test on the generated key pair */ 105 ret = versal_ecc_keypair_pwct(s); 106 if (ret) 107 DMSG("Pair-wise consistency test failed (0x%" PRIx32 ")", ret); 108 #endif 109 110 return ret; 111 } 112 113 static TEE_Result do_alloc_keypair(struct ecc_keypair *s, 114 uint32_t type, size_t size_bits) 115 { 116 TEE_Result ret = TEE_SUCCESS; 117 118 /* This driver only supports ECDH/ECDSA */ 119 if (type != TEE_TYPE_ECDSA_KEYPAIR && 120 type != TEE_TYPE_ECDH_KEYPAIR) 121 return TEE_ERROR_NOT_IMPLEMENTED; 122 123 ret = crypto_asym_alloc_ecc_keypair(s, TEE_TYPE_ECDSA_KEYPAIR, 124 size_bits); 125 if (ret) 126 return TEE_ERROR_NOT_IMPLEMENTED; 127 128 /* 129 * Ignore the software operations, the crypto API will populate 130 * this interface. 131 */ 132 s->ops = NULL; 133 134 return TEE_SUCCESS; 135 } 136 137 static TEE_Result do_alloc_publickey(struct ecc_public_key *s, 138 uint32_t type, size_t size_bits) 139 { 140 TEE_Result ret = TEE_SUCCESS; 141 142 /* This driver only supports ECDH/ECDSA */ 143 if (type != TEE_TYPE_ECDSA_PUBLIC_KEY && 144 type != TEE_TYPE_ECDH_PUBLIC_KEY) 145 return TEE_ERROR_NOT_IMPLEMENTED; 146 147 ret = crypto_asym_alloc_ecc_public_key(s, TEE_TYPE_ECDSA_PUBLIC_KEY, 148 size_bits); 149 if (ret) 150 return TEE_ERROR_NOT_IMPLEMENTED; 151 152 /* 153 * Ignore the software operations, the crypto API will populate 154 * this interface. 155 */ 156 s->ops = NULL; 157 158 return TEE_SUCCESS; 159 } 160 161 static void do_free_publickey(struct ecc_public_key *s) 162 { 163 return pub_ops->free(s); 164 } 165 166 static struct drvcrypt_ecc driver_ecc = { 167 .shared_secret = do_shared_secret, 168 .alloc_publickey = do_alloc_publickey, 169 .free_publickey = do_free_publickey, 170 .alloc_keypair = do_alloc_keypair, 171 .gen_keypair = do_gen_keypair, 172 .verify = do_verify, 173 .sign = do_sign, 174 }; 175 176 static TEE_Result ecc_init(void) 177 { 178 TEE_Result ret = TEE_SUCCESS; 179 180 /* HW initialization if needed */ 181 ret = versal_ecc_hw_init(); 182 if (ret) 183 return ret; 184 185 /* Run KAT self-tests */ 186 ret = versal_ecc_kat_test(); 187 if (ret) 188 return ret; 189 190 /* Initialize fallback to software implementations, if needed later */ 191 pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR); 192 if (!pair_ops) 193 return TEE_ERROR_GENERIC; 194 195 pub_ops = crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDSA_PUBLIC_KEY); 196 if (!pub_ops) 197 return TEE_ERROR_GENERIC; 198 199 /* This driver supports both ECDH and ECDSA */ 200 assert((pub_ops == 201 crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDH_PUBLIC_KEY)) && 202 (pair_ops == 203 crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR))); 204 205 return drvcrypt_register_ecc(&driver_ecc); 206 } 207 208 driver_init(ecc_init); 209