1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2016, Intel Corporation 4 * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com> 5 */ 6 #include <linux/kernel.h> 7 #include <linux/export.h> 8 #include <linux/err.h> 9 #include <linux/string.h> 10 #include <crypto/ecdh.h> 11 #include <crypto/kpp.h> 12 13 #define ECDH_KPP_SECRET_MIN_SIZE (sizeof(struct kpp_secret) + 2 * sizeof(short)) 14 15 static inline u8 *ecdh_pack_data(void *dst, const void *src, size_t sz) 16 { 17 memcpy(dst, src, sz); 18 return dst + sz; 19 } 20 21 static inline const u8 *ecdh_unpack_data(void *dst, const void *src, size_t sz) 22 { 23 memcpy(dst, src, sz); 24 return src + sz; 25 } 26 27 unsigned int crypto_ecdh_key_len(const struct ecdh *params) 28 { 29 return ECDH_KPP_SECRET_MIN_SIZE + params->key_size; 30 } 31 EXPORT_SYMBOL_GPL(crypto_ecdh_key_len); 32 33 int crypto_ecdh_encode_key(char *buf, unsigned int len, 34 const struct ecdh *params) 35 { 36 u8 *ptr = buf; 37 struct kpp_secret secret = { 38 .type = CRYPTO_KPP_SECRET_TYPE_ECDH, 39 .len = len 40 }; 41 42 if (unlikely(!buf)) 43 return -EINVAL; 44 45 if (len != crypto_ecdh_key_len(params)) 46 return -EINVAL; 47 48 ptr = ecdh_pack_data(ptr, &secret, sizeof(secret)); 49 ptr = ecdh_pack_data(ptr, ¶ms->curve_id, sizeof(params->curve_id)); 50 ptr = ecdh_pack_data(ptr, ¶ms->key_size, sizeof(params->key_size)); 51 ecdh_pack_data(ptr, params->key, params->key_size); 52 53 return 0; 54 } 55 EXPORT_SYMBOL_GPL(crypto_ecdh_encode_key); 56 57 int crypto_ecdh_decode_key(const char *buf, unsigned int len, 58 struct ecdh *params) 59 { 60 const u8 *ptr = buf; 61 struct kpp_secret secret; 62 63 if (unlikely(!buf || len < ECDH_KPP_SECRET_MIN_SIZE)) 64 return -EINVAL; 65 66 ptr = ecdh_unpack_data(&secret, ptr, sizeof(secret)); 67 if (secret.type != CRYPTO_KPP_SECRET_TYPE_ECDH) 68 return -EINVAL; 69 70 ptr = ecdh_unpack_data(¶ms->curve_id, ptr, sizeof(params->curve_id)); 71 ptr = ecdh_unpack_data(¶ms->key_size, ptr, sizeof(params->key_size)); 72 if (secret.len != crypto_ecdh_key_len(params)) 73 return -EINVAL; 74 75 /* Don't allocate memory. Set pointer to data 76 * within the given buffer 77 */ 78 params->key = (void *)ptr; 79 80 return 0; 81 } 82 EXPORT_SYMBOL_GPL(crypto_ecdh_decode_key); 83