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/random.h> 2658771c1cSSalvatore Benedetto #include <linux/scatterlist.h> 2758771c1cSSalvatore Benedetto #include <crypto/kpp.h> 2858771c1cSSalvatore Benedetto #include <crypto/ecdh.h> 2958771c1cSSalvatore Benedetto 3058771c1cSSalvatore Benedetto struct ecdh_completion { 3158771c1cSSalvatore Benedetto struct completion completion; 3258771c1cSSalvatore Benedetto int err; 3358771c1cSSalvatore Benedetto }; 3458771c1cSSalvatore Benedetto 3558771c1cSSalvatore Benedetto static void ecdh_complete(struct crypto_async_request *req, int err) 3658771c1cSSalvatore Benedetto { 3758771c1cSSalvatore Benedetto struct ecdh_completion *res = req->data; 3858771c1cSSalvatore Benedetto 3958771c1cSSalvatore Benedetto if (err == -EINPROGRESS) 4058771c1cSSalvatore Benedetto return; 4158771c1cSSalvatore Benedetto 4258771c1cSSalvatore Benedetto res->err = err; 4358771c1cSSalvatore Benedetto complete(&res->completion); 4458771c1cSSalvatore Benedetto } 4558771c1cSSalvatore Benedetto 4658771c1cSSalvatore Benedetto static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits) 4758771c1cSSalvatore Benedetto { 4858771c1cSSalvatore Benedetto int i; 4958771c1cSSalvatore Benedetto 5058771c1cSSalvatore Benedetto for (i = 0; i < ndigits; i++) 5158771c1cSSalvatore Benedetto out[i] = __swab64(in[ndigits - 1 - i]); 5258771c1cSSalvatore Benedetto } 5358771c1cSSalvatore Benedetto 5458771c1cSSalvatore Benedetto bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32], 5558771c1cSSalvatore Benedetto u8 secret[32]) 5658771c1cSSalvatore Benedetto { 5758771c1cSSalvatore Benedetto struct crypto_kpp *tfm; 5858771c1cSSalvatore Benedetto struct kpp_request *req; 5958771c1cSSalvatore Benedetto struct ecdh p; 6058771c1cSSalvatore Benedetto struct ecdh_completion result; 6158771c1cSSalvatore Benedetto struct scatterlist src, dst; 62763d9a30SSalvatore Benedetto u8 *tmp, *buf; 6358771c1cSSalvatore Benedetto unsigned int buf_len; 6458771c1cSSalvatore Benedetto int err = -ENOMEM; 6558771c1cSSalvatore Benedetto 66763d9a30SSalvatore Benedetto tmp = kmalloc(64, GFP_KERNEL); 67763d9a30SSalvatore Benedetto if (!tmp) 68763d9a30SSalvatore Benedetto return false; 69763d9a30SSalvatore Benedetto 7058771c1cSSalvatore Benedetto tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0); 7158771c1cSSalvatore Benedetto if (IS_ERR(tfm)) { 7258771c1cSSalvatore Benedetto pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n", 7358771c1cSSalvatore Benedetto PTR_ERR(tfm)); 74763d9a30SSalvatore Benedetto goto free_tmp; 7558771c1cSSalvatore Benedetto } 7658771c1cSSalvatore Benedetto 7758771c1cSSalvatore Benedetto req = kpp_request_alloc(tfm, GFP_KERNEL); 7858771c1cSSalvatore Benedetto if (!req) 7958771c1cSSalvatore Benedetto goto free_kpp; 8058771c1cSSalvatore Benedetto 8158771c1cSSalvatore Benedetto init_completion(&result.completion); 8258771c1cSSalvatore Benedetto 8358771c1cSSalvatore Benedetto /* Security Manager Protocol holds digits in litte-endian order 8458771c1cSSalvatore Benedetto * while ECC API expect big-endian data 8558771c1cSSalvatore Benedetto */ 8658771c1cSSalvatore Benedetto swap_digits((u64 *)private_key, (u64 *)tmp, 4); 8758771c1cSSalvatore Benedetto p.key = (char *)tmp; 8858771c1cSSalvatore Benedetto p.key_size = 32; 8958771c1cSSalvatore Benedetto /* Set curve_id */ 9058771c1cSSalvatore Benedetto p.curve_id = ECC_CURVE_NIST_P256; 9158771c1cSSalvatore Benedetto buf_len = crypto_ecdh_key_len(&p); 9258771c1cSSalvatore Benedetto buf = kmalloc(buf_len, GFP_KERNEL); 9358771c1cSSalvatore Benedetto if (!buf) { 9458771c1cSSalvatore Benedetto pr_err("alg: kpp: Failed to allocate %d bytes for buf\n", 9558771c1cSSalvatore Benedetto buf_len); 9658771c1cSSalvatore Benedetto goto free_req; 9758771c1cSSalvatore Benedetto } 9858771c1cSSalvatore Benedetto crypto_ecdh_encode_key(buf, buf_len, &p); 9958771c1cSSalvatore Benedetto 10058771c1cSSalvatore Benedetto /* Set A private Key */ 10158771c1cSSalvatore Benedetto err = crypto_kpp_set_secret(tfm, (void *)buf, buf_len); 10258771c1cSSalvatore Benedetto if (err) 10358771c1cSSalvatore Benedetto goto free_all; 10458771c1cSSalvatore Benedetto 10558771c1cSSalvatore Benedetto swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */ 10658771c1cSSalvatore Benedetto swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */ 10758771c1cSSalvatore Benedetto 10858771c1cSSalvatore Benedetto sg_init_one(&src, tmp, 64); 10958771c1cSSalvatore Benedetto sg_init_one(&dst, secret, 32); 11058771c1cSSalvatore Benedetto kpp_request_set_input(req, &src, 64); 11158771c1cSSalvatore Benedetto kpp_request_set_output(req, &dst, 32); 11258771c1cSSalvatore Benedetto kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 11358771c1cSSalvatore Benedetto ecdh_complete, &result); 11458771c1cSSalvatore Benedetto err = crypto_kpp_compute_shared_secret(req); 11558771c1cSSalvatore Benedetto if (err == -EINPROGRESS) { 11658771c1cSSalvatore Benedetto wait_for_completion(&result.completion); 11758771c1cSSalvatore Benedetto err = result.err; 11858771c1cSSalvatore Benedetto } 11958771c1cSSalvatore Benedetto if (err < 0) { 12058771c1cSSalvatore Benedetto pr_err("alg: ecdh: compute shared secret failed. err %d\n", 12158771c1cSSalvatore Benedetto err); 12258771c1cSSalvatore Benedetto goto free_all; 12358771c1cSSalvatore Benedetto } 12458771c1cSSalvatore Benedetto 12558771c1cSSalvatore Benedetto swap_digits((u64 *)secret, (u64 *)tmp, 4); 12658771c1cSSalvatore Benedetto memcpy(secret, tmp, 32); 12758771c1cSSalvatore Benedetto 12858771c1cSSalvatore Benedetto free_all: 12958771c1cSSalvatore Benedetto kzfree(buf); 13058771c1cSSalvatore Benedetto free_req: 13158771c1cSSalvatore Benedetto kpp_request_free(req); 13258771c1cSSalvatore Benedetto free_kpp: 13358771c1cSSalvatore Benedetto crypto_free_kpp(tfm); 134763d9a30SSalvatore Benedetto free_tmp: 135763d9a30SSalvatore Benedetto kfree(tmp); 13658771c1cSSalvatore Benedetto return (err == 0); 13758771c1cSSalvatore Benedetto } 13858771c1cSSalvatore Benedetto 13958771c1cSSalvatore Benedetto bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32]) 14058771c1cSSalvatore Benedetto { 14158771c1cSSalvatore Benedetto struct crypto_kpp *tfm; 14258771c1cSSalvatore Benedetto struct kpp_request *req; 14358771c1cSSalvatore Benedetto struct ecdh p; 14458771c1cSSalvatore Benedetto struct ecdh_completion result; 14558771c1cSSalvatore Benedetto struct scatterlist dst; 146763d9a30SSalvatore Benedetto u8 *tmp, *buf; 14758771c1cSSalvatore Benedetto unsigned int buf_len; 14858771c1cSSalvatore Benedetto int err = -ENOMEM; 14958771c1cSSalvatore Benedetto const unsigned short max_tries = 16; 15058771c1cSSalvatore Benedetto unsigned short tries = 0; 15158771c1cSSalvatore Benedetto 152763d9a30SSalvatore Benedetto tmp = kmalloc(64, GFP_KERNEL); 153763d9a30SSalvatore Benedetto if (!tmp) 154763d9a30SSalvatore Benedetto return false; 155763d9a30SSalvatore Benedetto 15658771c1cSSalvatore Benedetto tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0); 15758771c1cSSalvatore Benedetto if (IS_ERR(tfm)) { 15858771c1cSSalvatore Benedetto pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n", 15958771c1cSSalvatore Benedetto PTR_ERR(tfm)); 160763d9a30SSalvatore Benedetto goto free_tmp; 16158771c1cSSalvatore Benedetto } 16258771c1cSSalvatore Benedetto 16358771c1cSSalvatore Benedetto req = kpp_request_alloc(tfm, GFP_KERNEL); 16458771c1cSSalvatore Benedetto if (!req) 16558771c1cSSalvatore Benedetto goto free_kpp; 16658771c1cSSalvatore Benedetto 16758771c1cSSalvatore Benedetto init_completion(&result.completion); 16858771c1cSSalvatore Benedetto 16958771c1cSSalvatore Benedetto /* Set curve_id */ 17058771c1cSSalvatore Benedetto p.curve_id = ECC_CURVE_NIST_P256; 17158771c1cSSalvatore Benedetto p.key_size = 32; 17258771c1cSSalvatore Benedetto buf_len = crypto_ecdh_key_len(&p); 17358771c1cSSalvatore Benedetto buf = kmalloc(buf_len, GFP_KERNEL); 17458771c1cSSalvatore Benedetto if (!buf) { 17558771c1cSSalvatore Benedetto pr_err("alg: kpp: Failed to allocate %d bytes for buf\n", 17658771c1cSSalvatore Benedetto buf_len); 17758771c1cSSalvatore Benedetto goto free_req; 17858771c1cSSalvatore Benedetto } 17958771c1cSSalvatore Benedetto 18058771c1cSSalvatore Benedetto do { 18158771c1cSSalvatore Benedetto if (tries++ >= max_tries) 18258771c1cSSalvatore Benedetto goto free_all; 18358771c1cSSalvatore Benedetto 18458771c1cSSalvatore Benedetto get_random_bytes(private_key, 32); 18558771c1cSSalvatore Benedetto 18658771c1cSSalvatore Benedetto /* Set private Key */ 18758771c1cSSalvatore Benedetto p.key = (char *)private_key; 18858771c1cSSalvatore Benedetto crypto_ecdh_encode_key(buf, buf_len, &p); 18958771c1cSSalvatore Benedetto err = crypto_kpp_set_secret(tfm, buf, buf_len); 19058771c1cSSalvatore Benedetto if (err) 19158771c1cSSalvatore Benedetto goto free_all; 19258771c1cSSalvatore Benedetto 19358771c1cSSalvatore Benedetto sg_init_one(&dst, tmp, 64); 194*f9583153SMarcel Holtmann kpp_request_set_input(req, NULL, 0); 19558771c1cSSalvatore Benedetto kpp_request_set_output(req, &dst, 64); 19658771c1cSSalvatore Benedetto kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 19758771c1cSSalvatore Benedetto ecdh_complete, &result); 19858771c1cSSalvatore Benedetto 19958771c1cSSalvatore Benedetto err = crypto_kpp_generate_public_key(req); 20058771c1cSSalvatore Benedetto 20158771c1cSSalvatore Benedetto if (err == -EINPROGRESS) { 20258771c1cSSalvatore Benedetto wait_for_completion(&result.completion); 20358771c1cSSalvatore Benedetto err = result.err; 20458771c1cSSalvatore Benedetto } 20558771c1cSSalvatore Benedetto 20658771c1cSSalvatore Benedetto /* Private key is not valid. Regenerate */ 20758771c1cSSalvatore Benedetto if (err == -EINVAL) 20858771c1cSSalvatore Benedetto continue; 20958771c1cSSalvatore Benedetto 21058771c1cSSalvatore Benedetto if (err < 0) 21158771c1cSSalvatore Benedetto goto free_all; 21258771c1cSSalvatore Benedetto else 21358771c1cSSalvatore Benedetto break; 21458771c1cSSalvatore Benedetto 21558771c1cSSalvatore Benedetto } while (true); 21658771c1cSSalvatore Benedetto 21758771c1cSSalvatore Benedetto /* Keys are handed back in little endian as expected by Security 21858771c1cSSalvatore Benedetto * Manager Protocol 21958771c1cSSalvatore Benedetto */ 22058771c1cSSalvatore Benedetto swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */ 22158771c1cSSalvatore Benedetto swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */ 22258771c1cSSalvatore Benedetto swap_digits((u64 *)private_key, (u64 *)tmp, 4); 22358771c1cSSalvatore Benedetto memcpy(private_key, tmp, 32); 22458771c1cSSalvatore Benedetto 22558771c1cSSalvatore Benedetto free_all: 22658771c1cSSalvatore Benedetto kzfree(buf); 22758771c1cSSalvatore Benedetto free_req: 22858771c1cSSalvatore Benedetto kpp_request_free(req); 22958771c1cSSalvatore Benedetto free_kpp: 23058771c1cSSalvatore Benedetto crypto_free_kpp(tfm); 231763d9a30SSalvatore Benedetto free_tmp: 232763d9a30SSalvatore Benedetto kfree(tmp); 23358771c1cSSalvatore Benedetto return (err == 0); 23458771c1cSSalvatore Benedetto } 235