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