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) + 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->key_size, sizeof(params->key_size)); 50 ecdh_pack_data(ptr, params->key, params->key_size); 51 52 return 0; 53 } 54 EXPORT_SYMBOL_GPL(crypto_ecdh_encode_key); 55 56 int crypto_ecdh_decode_key(const char *buf, unsigned int len, 57 struct ecdh *params) 58 { 59 const u8 *ptr = buf; 60 struct kpp_secret secret; 61 62 if (unlikely(!buf || len < ECDH_KPP_SECRET_MIN_SIZE)) 63 return -EINVAL; 64 65 ptr = ecdh_unpack_data(&secret, ptr, sizeof(secret)); 66 if (secret.type != CRYPTO_KPP_SECRET_TYPE_ECDH) 67 return -EINVAL; 68 69 if (unlikely(len < secret.len)) 70 return -EINVAL; 71 72 ptr = ecdh_unpack_data(¶ms->key_size, ptr, sizeof(params->key_size)); 73 if (secret.len != crypto_ecdh_key_len(params)) 74 return -EINVAL; 75 76 /* Don't allocate memory. Set pointer to data 77 * within the given buffer 78 */ 79 params->key = (void *)ptr; 80 81 return 0; 82 } 83 EXPORT_SYMBOL_GPL(crypto_ecdh_decode_key); 84