158771c1cSSalvatore Benedetto /* 258771c1cSSalvatore Benedetto * ECDH helper functions - KPP wrappings 358771c1cSSalvatore Benedetto * 458771c1cSSalvatore Benedetto * Copyright (C) 2017 Intel Corporation 558771c1cSSalvatore Benedetto * 658771c1cSSalvatore Benedetto * This program is free software; you can redistribute it and/or modify 758771c1cSSalvatore Benedetto * it under the terms of the GNU General Public License version 2 as 858771c1cSSalvatore Benedetto * published by the Free Software Foundation; 958771c1cSSalvatore Benedetto * 1058771c1cSSalvatore Benedetto * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1158771c1cSSalvatore Benedetto * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1258771c1cSSalvatore Benedetto * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 1358771c1cSSalvatore Benedetto * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 1458771c1cSSalvatore Benedetto * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 1558771c1cSSalvatore Benedetto * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1658771c1cSSalvatore Benedetto * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1758771c1cSSalvatore Benedetto * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1858771c1cSSalvatore Benedetto * 1958771c1cSSalvatore Benedetto * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 2058771c1cSSalvatore Benedetto * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 2158771c1cSSalvatore Benedetto * SOFTWARE IS DISCLAIMED. 2258771c1cSSalvatore Benedetto */ 2358771c1cSSalvatore Benedetto #include "ecdh_helper.h" 2458771c1cSSalvatore Benedetto 2558771c1cSSalvatore Benedetto #include <linux/scatterlist.h> 2658771c1cSSalvatore Benedetto #include <crypto/ecdh.h> 2758771c1cSSalvatore Benedetto 2858771c1cSSalvatore Benedetto struct ecdh_completion { 2958771c1cSSalvatore Benedetto struct completion completion; 3058771c1cSSalvatore Benedetto int err; 3158771c1cSSalvatore Benedetto }; 3258771c1cSSalvatore Benedetto 3358771c1cSSalvatore Benedetto static void ecdh_complete(struct crypto_async_request *req, int err) 3458771c1cSSalvatore Benedetto { 3558771c1cSSalvatore Benedetto struct ecdh_completion *res = req->data; 3658771c1cSSalvatore Benedetto 3758771c1cSSalvatore Benedetto if (err == -EINPROGRESS) 3858771c1cSSalvatore Benedetto return; 3958771c1cSSalvatore Benedetto 4058771c1cSSalvatore Benedetto res->err = err; 4158771c1cSSalvatore Benedetto complete(&res->completion); 4258771c1cSSalvatore Benedetto } 4358771c1cSSalvatore Benedetto 4458771c1cSSalvatore Benedetto static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits) 4558771c1cSSalvatore Benedetto { 4658771c1cSSalvatore Benedetto int i; 4758771c1cSSalvatore Benedetto 4858771c1cSSalvatore Benedetto for (i = 0; i < ndigits; i++) 4958771c1cSSalvatore Benedetto out[i] = __swab64(in[ndigits - 1 - i]); 5058771c1cSSalvatore Benedetto } 5158771c1cSSalvatore Benedetto 52*47eb2ac8STudor Ambarus bool compute_ecdh_secret(struct crypto_kpp *tfm, const u8 public_key[64], 53*47eb2ac8STudor Ambarus const u8 private_key[32], u8 secret[32]) 5458771c1cSSalvatore Benedetto { 5558771c1cSSalvatore Benedetto struct kpp_request *req; 5658771c1cSSalvatore Benedetto struct ecdh p; 5758771c1cSSalvatore Benedetto struct ecdh_completion result; 5858771c1cSSalvatore Benedetto struct scatterlist src, dst; 59763d9a30SSalvatore Benedetto u8 *tmp, *buf; 6058771c1cSSalvatore Benedetto unsigned int buf_len; 6158771c1cSSalvatore Benedetto int err = -ENOMEM; 6258771c1cSSalvatore Benedetto 63763d9a30SSalvatore Benedetto tmp = kmalloc(64, GFP_KERNEL); 64763d9a30SSalvatore Benedetto if (!tmp) 65763d9a30SSalvatore Benedetto return false; 66763d9a30SSalvatore Benedetto 6758771c1cSSalvatore Benedetto req = kpp_request_alloc(tfm, GFP_KERNEL); 6858771c1cSSalvatore Benedetto if (!req) 69*47eb2ac8STudor Ambarus goto free_tmp; 7058771c1cSSalvatore Benedetto 7158771c1cSSalvatore Benedetto init_completion(&result.completion); 7258771c1cSSalvatore Benedetto 7358771c1cSSalvatore Benedetto /* Security Manager Protocol holds digits in litte-endian order 7458771c1cSSalvatore Benedetto * while ECC API expect big-endian data 7558771c1cSSalvatore Benedetto */ 7658771c1cSSalvatore Benedetto swap_digits((u64 *)private_key, (u64 *)tmp, 4); 7758771c1cSSalvatore Benedetto p.key = (char *)tmp; 7858771c1cSSalvatore Benedetto p.key_size = 32; 7958771c1cSSalvatore Benedetto /* Set curve_id */ 8058771c1cSSalvatore Benedetto p.curve_id = ECC_CURVE_NIST_P256; 8158771c1cSSalvatore Benedetto buf_len = crypto_ecdh_key_len(&p); 8258771c1cSSalvatore Benedetto buf = kmalloc(buf_len, GFP_KERNEL); 835d4acfc1SMarkus Elfring if (!buf) 8458771c1cSSalvatore Benedetto goto free_req; 855d4acfc1SMarkus Elfring 8658771c1cSSalvatore Benedetto crypto_ecdh_encode_key(buf, buf_len, &p); 8758771c1cSSalvatore Benedetto 8858771c1cSSalvatore Benedetto /* Set A private Key */ 8958771c1cSSalvatore Benedetto err = crypto_kpp_set_secret(tfm, (void *)buf, buf_len); 9058771c1cSSalvatore Benedetto if (err) 9158771c1cSSalvatore Benedetto goto free_all; 9258771c1cSSalvatore Benedetto 9358771c1cSSalvatore Benedetto swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */ 9458771c1cSSalvatore Benedetto swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */ 9558771c1cSSalvatore Benedetto 9658771c1cSSalvatore Benedetto sg_init_one(&src, tmp, 64); 9758771c1cSSalvatore Benedetto sg_init_one(&dst, secret, 32); 9858771c1cSSalvatore Benedetto kpp_request_set_input(req, &src, 64); 9958771c1cSSalvatore Benedetto kpp_request_set_output(req, &dst, 32); 10058771c1cSSalvatore Benedetto kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 10158771c1cSSalvatore Benedetto ecdh_complete, &result); 10258771c1cSSalvatore Benedetto err = crypto_kpp_compute_shared_secret(req); 10358771c1cSSalvatore Benedetto if (err == -EINPROGRESS) { 10458771c1cSSalvatore Benedetto wait_for_completion(&result.completion); 10558771c1cSSalvatore Benedetto err = result.err; 10658771c1cSSalvatore Benedetto } 10758771c1cSSalvatore Benedetto if (err < 0) { 10858771c1cSSalvatore Benedetto pr_err("alg: ecdh: compute shared secret failed. err %d\n", 10958771c1cSSalvatore Benedetto err); 11058771c1cSSalvatore Benedetto goto free_all; 11158771c1cSSalvatore Benedetto } 11258771c1cSSalvatore Benedetto 11358771c1cSSalvatore Benedetto swap_digits((u64 *)secret, (u64 *)tmp, 4); 11458771c1cSSalvatore Benedetto memcpy(secret, tmp, 32); 11558771c1cSSalvatore Benedetto 11658771c1cSSalvatore Benedetto free_all: 11758771c1cSSalvatore Benedetto kzfree(buf); 11858771c1cSSalvatore Benedetto free_req: 11958771c1cSSalvatore Benedetto kpp_request_free(req); 120763d9a30SSalvatore Benedetto free_tmp: 121763d9a30SSalvatore Benedetto kfree(tmp); 12258771c1cSSalvatore Benedetto return (err == 0); 12358771c1cSSalvatore Benedetto } 12458771c1cSSalvatore Benedetto 125*47eb2ac8STudor Ambarus bool generate_ecdh_keys(struct crypto_kpp *tfm, u8 public_key[64], 126*47eb2ac8STudor Ambarus u8 private_key[32]) 12758771c1cSSalvatore Benedetto { 12858771c1cSSalvatore Benedetto struct kpp_request *req; 12958771c1cSSalvatore Benedetto struct ecdh p; 13058771c1cSSalvatore Benedetto struct ecdh_completion result; 13158771c1cSSalvatore Benedetto struct scatterlist dst; 132763d9a30SSalvatore Benedetto u8 *tmp, *buf; 13358771c1cSSalvatore Benedetto unsigned int buf_len; 13458771c1cSSalvatore Benedetto int err = -ENOMEM; 13558771c1cSSalvatore Benedetto const unsigned short max_tries = 16; 13658771c1cSSalvatore Benedetto unsigned short tries = 0; 13758771c1cSSalvatore Benedetto 138763d9a30SSalvatore Benedetto tmp = kmalloc(64, GFP_KERNEL); 139763d9a30SSalvatore Benedetto if (!tmp) 140763d9a30SSalvatore Benedetto return false; 141763d9a30SSalvatore Benedetto 14258771c1cSSalvatore Benedetto req = kpp_request_alloc(tfm, GFP_KERNEL); 14358771c1cSSalvatore Benedetto if (!req) 144*47eb2ac8STudor Ambarus goto free_tmp; 14558771c1cSSalvatore Benedetto 14658771c1cSSalvatore Benedetto init_completion(&result.completion); 14758771c1cSSalvatore Benedetto 14858771c1cSSalvatore Benedetto /* Set curve_id */ 14958771c1cSSalvatore Benedetto p.curve_id = ECC_CURVE_NIST_P256; 15058771c1cSSalvatore Benedetto p.key_size = 32; 15158771c1cSSalvatore Benedetto buf_len = crypto_ecdh_key_len(&p); 15258771c1cSSalvatore Benedetto buf = kmalloc(buf_len, GFP_KERNEL); 1535d4acfc1SMarkus Elfring if (!buf) 15458771c1cSSalvatore Benedetto goto free_req; 15558771c1cSSalvatore Benedetto 15658771c1cSSalvatore Benedetto do { 15758771c1cSSalvatore Benedetto if (tries++ >= max_tries) 15858771c1cSSalvatore Benedetto goto free_all; 15958771c1cSSalvatore Benedetto 16058771c1cSSalvatore Benedetto /* Set private Key */ 16158771c1cSSalvatore Benedetto p.key = (char *)private_key; 16258771c1cSSalvatore Benedetto crypto_ecdh_encode_key(buf, buf_len, &p); 16358771c1cSSalvatore Benedetto err = crypto_kpp_set_secret(tfm, buf, buf_len); 16458771c1cSSalvatore Benedetto if (err) 16558771c1cSSalvatore Benedetto goto free_all; 16658771c1cSSalvatore Benedetto 16758771c1cSSalvatore Benedetto sg_init_one(&dst, tmp, 64); 168f9583153SMarcel Holtmann kpp_request_set_input(req, NULL, 0); 16958771c1cSSalvatore Benedetto kpp_request_set_output(req, &dst, 64); 17058771c1cSSalvatore Benedetto kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 17158771c1cSSalvatore Benedetto ecdh_complete, &result); 17258771c1cSSalvatore Benedetto 17358771c1cSSalvatore Benedetto err = crypto_kpp_generate_public_key(req); 17458771c1cSSalvatore Benedetto 17558771c1cSSalvatore Benedetto if (err == -EINPROGRESS) { 17658771c1cSSalvatore Benedetto wait_for_completion(&result.completion); 17758771c1cSSalvatore Benedetto err = result.err; 17858771c1cSSalvatore Benedetto } 17958771c1cSSalvatore Benedetto 18058771c1cSSalvatore Benedetto /* Private key is not valid. Regenerate */ 18158771c1cSSalvatore Benedetto if (err == -EINVAL) 18258771c1cSSalvatore Benedetto continue; 18358771c1cSSalvatore Benedetto 18458771c1cSSalvatore Benedetto if (err < 0) 18558771c1cSSalvatore Benedetto goto free_all; 18658771c1cSSalvatore Benedetto else 18758771c1cSSalvatore Benedetto break; 18858771c1cSSalvatore Benedetto 18958771c1cSSalvatore Benedetto } while (true); 19058771c1cSSalvatore Benedetto 19158771c1cSSalvatore Benedetto /* Keys are handed back in little endian as expected by Security 19258771c1cSSalvatore Benedetto * Manager Protocol 19358771c1cSSalvatore Benedetto */ 19458771c1cSSalvatore Benedetto swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */ 19558771c1cSSalvatore Benedetto swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */ 19658771c1cSSalvatore Benedetto swap_digits((u64 *)private_key, (u64 *)tmp, 4); 19758771c1cSSalvatore Benedetto memcpy(private_key, tmp, 32); 19858771c1cSSalvatore Benedetto 19958771c1cSSalvatore Benedetto free_all: 20058771c1cSSalvatore Benedetto kzfree(buf); 20158771c1cSSalvatore Benedetto free_req: 20258771c1cSSalvatore Benedetto kpp_request_free(req); 203763d9a30SSalvatore Benedetto free_tmp: 204763d9a30SSalvatore Benedetto kfree(tmp); 20558771c1cSSalvatore Benedetto return (err == 0); 20658771c1cSSalvatore Benedetto } 207