/** * struct atmel_ecdh_ctx - transformation context * @client : pointer to i2c client device * @fallback : used for unsupported curves or when user wants to use its own * private key. * @public_key : generated when calling set_secret(). It's the responsibility * of the user to not call set_secret() while * generate_public_key() or compute_shared_secret() are in flight. * @curve_id : elliptic curve id * @do_fallback: true when the device doesn't support the curve or when the user * wants to use its own private key.
*/ struct atmel_ecdh_ctx { struct i2c_client *client; struct crypto_kpp *fallback; const u8 *public_key; unsignedint curve_id; bool do_fallback;
};
/* might want less than we've got */
n_sz = min_t(size_t, ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len);
/* copy the shared secret */
copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, n_sz),
&cmd->data[RSP_DATA_IDX], n_sz); if (copied != n_sz)
status = -EINVAL;
/* fall through */
free_work_data:
kfree_sensitive(work_data);
kpp_request_complete(req, status);
}
/* * A random private key is generated and stored in the device. The device * returns the pair public key.
*/ staticint atmel_ecdh_set_secret(struct crypto_kpp *tfm, constvoid *buf, unsignedint len)
{ struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); struct atmel_i2c_cmd *cmd; void *public_key; struct ecdh params; int ret = -ENOMEM;
/* free the old public key, if any */
kfree(ctx->public_key); /* make sure you don't free the old public key twice */
ctx->public_key = NULL;
if (params.key_size) { /* fallback to ecdh software implementation */
ctx->do_fallback = true; return crypto_kpp_set_secret(ctx->fallback, buf, len);
}
cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM;
/* * The device only supports NIST P256 ECC keys. The public key size will * always be the same. Use a macro for the key size to avoid unnecessary * computations.
*/
public_key = kmalloc(ATMEL_ECC_PUBKEY_SIZE, GFP_KERNEL); if (!public_key) goto free_cmd;
ctx->do_fallback = false;
atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2);
ret = atmel_i2c_send_receive(ctx->client, cmd); if (ret) goto free_public_key;
/* save the public key */
memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE);
ctx->public_key = public_key;
if (ctx->do_fallback) {
kpp_request_set_tfm(req, ctx->fallback); return crypto_kpp_generate_public_key(req);
}
if (!ctx->public_key) return -EINVAL;
/* might want less than we've got */
nbytes = min_t(size_t, ATMEL_ECC_PUBKEY_SIZE, req->dst_len);
/* public key was saved at private key generation */
copied = sg_copy_from_buffer(req->dst,
sg_nents_for_len(req->dst, nbytes),
ctx->public_key, nbytes); if (copied != nbytes)
ret = -EINVAL;
if (ctx->fallback) return crypto_kpp_maxsize(ctx->fallback);
/* * The device only supports NIST P256 ECC keys. The public key size will * always be the same. Use a macro for the key size to avoid unnecessary * computations.
*/ return ATMEL_ECC_PUBKEY_SIZE;
}
ret = crypto_register_kpp(&atmel_ecdh_nist_p256); if (ret) {
spin_lock(&driver_data.i2c_list_lock);
list_del(&i2c_priv->i2c_client_list_node);
spin_unlock(&driver_data.i2c_list_lock);
/* Return EBUSY if i2c client already allocated. */ if (atomic_read(&i2c_priv->tfm_count)) { /* * After we return here, the memory backing the device is freed. * That happens no matter what the return value of this function * is because in the Linux device model there is no error * handling for unbinding a driver. * If there is still some action pending, it probably involves * accessing the freed memory.
*/
dev_emerg(&client->dev, "Device is busy, expect memory corruption.\n"); return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.