atmel-ecc.c (10337B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Microchip / Atmel ECC (I2C) driver. 4 * 5 * Copyright (c) 2017, Microchip Technology Inc. 6 * Author: Tudor Ambarus <tudor.ambarus@microchip.com> 7 */ 8 9#include <linux/delay.h> 10#include <linux/device.h> 11#include <linux/err.h> 12#include <linux/errno.h> 13#include <linux/i2c.h> 14#include <linux/init.h> 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/of_device.h> 18#include <linux/scatterlist.h> 19#include <linux/slab.h> 20#include <linux/workqueue.h> 21#include <crypto/internal/kpp.h> 22#include <crypto/ecdh.h> 23#include <crypto/kpp.h> 24#include "atmel-i2c.h" 25 26static struct atmel_ecc_driver_data driver_data; 27 28/** 29 * struct atmel_ecdh_ctx - transformation context 30 * @client : pointer to i2c client device 31 * @fallback : used for unsupported curves or when user wants to use its own 32 * private key. 33 * @public_key : generated when calling set_secret(). It's the responsibility 34 * of the user to not call set_secret() while 35 * generate_public_key() or compute_shared_secret() are in flight. 36 * @curve_id : elliptic curve id 37 * @do_fallback: true when the device doesn't support the curve or when the user 38 * wants to use its own private key. 39 */ 40struct atmel_ecdh_ctx { 41 struct i2c_client *client; 42 struct crypto_kpp *fallback; 43 const u8 *public_key; 44 unsigned int curve_id; 45 bool do_fallback; 46}; 47 48static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq, 49 int status) 50{ 51 struct kpp_request *req = areq; 52 struct atmel_i2c_cmd *cmd = &work_data->cmd; 53 size_t copied, n_sz; 54 55 if (status) 56 goto free_work_data; 57 58 /* might want less than we've got */ 59 n_sz = min_t(size_t, ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len); 60 61 /* copy the shared secret */ 62 copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, n_sz), 63 &cmd->data[RSP_DATA_IDX], n_sz); 64 if (copied != n_sz) 65 status = -EINVAL; 66 67 /* fall through */ 68free_work_data: 69 kfree_sensitive(work_data); 70 kpp_request_complete(req, status); 71} 72 73/* 74 * A random private key is generated and stored in the device. The device 75 * returns the pair public key. 76 */ 77static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, 78 unsigned int len) 79{ 80 struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); 81 struct atmel_i2c_cmd *cmd; 82 void *public_key; 83 struct ecdh params; 84 int ret = -ENOMEM; 85 86 /* free the old public key, if any */ 87 kfree(ctx->public_key); 88 /* make sure you don't free the old public key twice */ 89 ctx->public_key = NULL; 90 91 if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) { 92 dev_err(&ctx->client->dev, "crypto_ecdh_decode_key failed\n"); 93 return -EINVAL; 94 } 95 96 if (params.key_size) { 97 /* fallback to ecdh software implementation */ 98 ctx->do_fallback = true; 99 return crypto_kpp_set_secret(ctx->fallback, buf, len); 100 } 101 102 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); 103 if (!cmd) 104 return -ENOMEM; 105 106 /* 107 * The device only supports NIST P256 ECC keys. The public key size will 108 * always be the same. Use a macro for the key size to avoid unnecessary 109 * computations. 110 */ 111 public_key = kmalloc(ATMEL_ECC_PUBKEY_SIZE, GFP_KERNEL); 112 if (!public_key) 113 goto free_cmd; 114 115 ctx->do_fallback = false; 116 117 atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2); 118 119 ret = atmel_i2c_send_receive(ctx->client, cmd); 120 if (ret) 121 goto free_public_key; 122 123 /* save the public key */ 124 memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE); 125 ctx->public_key = public_key; 126 127 kfree(cmd); 128 return 0; 129 130free_public_key: 131 kfree(public_key); 132free_cmd: 133 kfree(cmd); 134 return ret; 135} 136 137static int atmel_ecdh_generate_public_key(struct kpp_request *req) 138{ 139 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 140 struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); 141 size_t copied, nbytes; 142 int ret = 0; 143 144 if (ctx->do_fallback) { 145 kpp_request_set_tfm(req, ctx->fallback); 146 return crypto_kpp_generate_public_key(req); 147 } 148 149 if (!ctx->public_key) 150 return -EINVAL; 151 152 /* might want less than we've got */ 153 nbytes = min_t(size_t, ATMEL_ECC_PUBKEY_SIZE, req->dst_len); 154 155 /* public key was saved at private key generation */ 156 copied = sg_copy_from_buffer(req->dst, 157 sg_nents_for_len(req->dst, nbytes), 158 ctx->public_key, nbytes); 159 if (copied != nbytes) 160 ret = -EINVAL; 161 162 return ret; 163} 164 165static int atmel_ecdh_compute_shared_secret(struct kpp_request *req) 166{ 167 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 168 struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); 169 struct atmel_i2c_work_data *work_data; 170 gfp_t gfp; 171 int ret; 172 173 if (ctx->do_fallback) { 174 kpp_request_set_tfm(req, ctx->fallback); 175 return crypto_kpp_compute_shared_secret(req); 176 } 177 178 /* must have exactly two points to be on the curve */ 179 if (req->src_len != ATMEL_ECC_PUBKEY_SIZE) 180 return -EINVAL; 181 182 gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : 183 GFP_ATOMIC; 184 185 work_data = kmalloc(sizeof(*work_data), gfp); 186 if (!work_data) 187 return -ENOMEM; 188 189 work_data->ctx = ctx; 190 work_data->client = ctx->client; 191 192 ret = atmel_i2c_init_ecdh_cmd(&work_data->cmd, req->src); 193 if (ret) 194 goto free_work_data; 195 196 atmel_i2c_enqueue(work_data, atmel_ecdh_done, req); 197 198 return -EINPROGRESS; 199 200free_work_data: 201 kfree(work_data); 202 return ret; 203} 204 205static struct i2c_client *atmel_ecc_i2c_client_alloc(void) 206{ 207 struct atmel_i2c_client_priv *i2c_priv, *min_i2c_priv = NULL; 208 struct i2c_client *client = ERR_PTR(-ENODEV); 209 int min_tfm_cnt = INT_MAX; 210 int tfm_cnt; 211 212 spin_lock(&driver_data.i2c_list_lock); 213 214 if (list_empty(&driver_data.i2c_client_list)) { 215 spin_unlock(&driver_data.i2c_list_lock); 216 return ERR_PTR(-ENODEV); 217 } 218 219 list_for_each_entry(i2c_priv, &driver_data.i2c_client_list, 220 i2c_client_list_node) { 221 tfm_cnt = atomic_read(&i2c_priv->tfm_count); 222 if (tfm_cnt < min_tfm_cnt) { 223 min_tfm_cnt = tfm_cnt; 224 min_i2c_priv = i2c_priv; 225 } 226 if (!min_tfm_cnt) 227 break; 228 } 229 230 if (min_i2c_priv) { 231 atomic_inc(&min_i2c_priv->tfm_count); 232 client = min_i2c_priv->client; 233 } 234 235 spin_unlock(&driver_data.i2c_list_lock); 236 237 return client; 238} 239 240static void atmel_ecc_i2c_client_free(struct i2c_client *client) 241{ 242 struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); 243 244 atomic_dec(&i2c_priv->tfm_count); 245} 246 247static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm) 248{ 249 const char *alg = kpp_alg_name(tfm); 250 struct crypto_kpp *fallback; 251 struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); 252 253 ctx->curve_id = ECC_CURVE_NIST_P256; 254 ctx->client = atmel_ecc_i2c_client_alloc(); 255 if (IS_ERR(ctx->client)) { 256 pr_err("tfm - i2c_client binding failed\n"); 257 return PTR_ERR(ctx->client); 258 } 259 260 fallback = crypto_alloc_kpp(alg, 0, CRYPTO_ALG_NEED_FALLBACK); 261 if (IS_ERR(fallback)) { 262 dev_err(&ctx->client->dev, "Failed to allocate transformation for '%s': %ld\n", 263 alg, PTR_ERR(fallback)); 264 return PTR_ERR(fallback); 265 } 266 267 crypto_kpp_set_flags(fallback, crypto_kpp_get_flags(tfm)); 268 ctx->fallback = fallback; 269 270 return 0; 271} 272 273static void atmel_ecdh_exit_tfm(struct crypto_kpp *tfm) 274{ 275 struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); 276 277 kfree(ctx->public_key); 278 crypto_free_kpp(ctx->fallback); 279 atmel_ecc_i2c_client_free(ctx->client); 280} 281 282static unsigned int atmel_ecdh_max_size(struct crypto_kpp *tfm) 283{ 284 struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); 285 286 if (ctx->fallback) 287 return crypto_kpp_maxsize(ctx->fallback); 288 289 /* 290 * The device only supports NIST P256 ECC keys. The public key size will 291 * always be the same. Use a macro for the key size to avoid unnecessary 292 * computations. 293 */ 294 return ATMEL_ECC_PUBKEY_SIZE; 295} 296 297static struct kpp_alg atmel_ecdh_nist_p256 = { 298 .set_secret = atmel_ecdh_set_secret, 299 .generate_public_key = atmel_ecdh_generate_public_key, 300 .compute_shared_secret = atmel_ecdh_compute_shared_secret, 301 .init = atmel_ecdh_init_tfm, 302 .exit = atmel_ecdh_exit_tfm, 303 .max_size = atmel_ecdh_max_size, 304 .base = { 305 .cra_flags = CRYPTO_ALG_NEED_FALLBACK, 306 .cra_name = "ecdh-nist-p256", 307 .cra_driver_name = "atmel-ecdh", 308 .cra_priority = ATMEL_ECC_PRIORITY, 309 .cra_module = THIS_MODULE, 310 .cra_ctxsize = sizeof(struct atmel_ecdh_ctx), 311 }, 312}; 313 314static int atmel_ecc_probe(struct i2c_client *client, 315 const struct i2c_device_id *id) 316{ 317 struct atmel_i2c_client_priv *i2c_priv; 318 int ret; 319 320 ret = atmel_i2c_probe(client, id); 321 if (ret) 322 return ret; 323 324 i2c_priv = i2c_get_clientdata(client); 325 326 spin_lock(&driver_data.i2c_list_lock); 327 list_add_tail(&i2c_priv->i2c_client_list_node, 328 &driver_data.i2c_client_list); 329 spin_unlock(&driver_data.i2c_list_lock); 330 331 ret = crypto_register_kpp(&atmel_ecdh_nist_p256); 332 if (ret) { 333 spin_lock(&driver_data.i2c_list_lock); 334 list_del(&i2c_priv->i2c_client_list_node); 335 spin_unlock(&driver_data.i2c_list_lock); 336 337 dev_err(&client->dev, "%s alg registration failed\n", 338 atmel_ecdh_nist_p256.base.cra_driver_name); 339 } else { 340 dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\n"); 341 } 342 343 return ret; 344} 345 346static int atmel_ecc_remove(struct i2c_client *client) 347{ 348 struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); 349 350 /* Return EBUSY if i2c client already allocated. */ 351 if (atomic_read(&i2c_priv->tfm_count)) { 352 dev_err(&client->dev, "Device is busy\n"); 353 return -EBUSY; 354 } 355 356 crypto_unregister_kpp(&atmel_ecdh_nist_p256); 357 358 spin_lock(&driver_data.i2c_list_lock); 359 list_del(&i2c_priv->i2c_client_list_node); 360 spin_unlock(&driver_data.i2c_list_lock); 361 362 return 0; 363} 364 365#ifdef CONFIG_OF 366static const struct of_device_id atmel_ecc_dt_ids[] = { 367 { 368 .compatible = "atmel,atecc508a", 369 }, { 370 /* sentinel */ 371 } 372}; 373MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids); 374#endif 375 376static const struct i2c_device_id atmel_ecc_id[] = { 377 { "atecc508a", 0 }, 378 { } 379}; 380MODULE_DEVICE_TABLE(i2c, atmel_ecc_id); 381 382static struct i2c_driver atmel_ecc_driver = { 383 .driver = { 384 .name = "atmel-ecc", 385 .of_match_table = of_match_ptr(atmel_ecc_dt_ids), 386 }, 387 .probe = atmel_ecc_probe, 388 .remove = atmel_ecc_remove, 389 .id_table = atmel_ecc_id, 390}; 391 392static int __init atmel_ecc_init(void) 393{ 394 spin_lock_init(&driver_data.i2c_list_lock); 395 INIT_LIST_HEAD(&driver_data.i2c_client_list); 396 return i2c_add_driver(&atmel_ecc_driver); 397} 398 399static void __exit atmel_ecc_exit(void) 400{ 401 atmel_i2c_flush_queue(); 402 i2c_del_driver(&atmel_ecc_driver); 403} 404 405module_init(atmel_ecc_init); 406module_exit(atmel_ecc_exit); 407 408MODULE_AUTHOR("Tudor Ambarus <tudor.ambarus@microchip.com>"); 409MODULE_DESCRIPTION("Microchip / Atmel ECC (I2C) driver"); 410MODULE_LICENSE("GPL v2");