2 * Copyright (c) 2016, Intel Corporation
3 * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
10 #include <linux/kernel.h>
11 #include <linux/export.h>
12 #include <linux/err.h>
13 #include <linux/string.h>
14 #include <crypto/dh.h>
15 #include <crypto/kpp.h>
17 #define DH_KPP_SECRET_MIN_SIZE (sizeof(struct kpp_secret) + 3 * sizeof(int))
19 static inline u8
*dh_pack_data(void *dst
, const void *src
, size_t size
)
21 memcpy(dst
, src
, size
);
25 static inline const u8
*dh_unpack_data(void *dst
, const void *src
, size_t size
)
27 memcpy(dst
, src
, size
);
31 static inline unsigned int dh_data_size(const struct dh
*p
)
33 return p
->key_size
+ p
->p_size
+ p
->g_size
;
36 unsigned int crypto_dh_key_len(const struct dh
*p
)
38 return DH_KPP_SECRET_MIN_SIZE
+ dh_data_size(p
);
40 EXPORT_SYMBOL_GPL(crypto_dh_key_len
);
42 int crypto_dh_encode_key(char *buf
, unsigned int len
, const struct dh
*params
)
45 struct kpp_secret secret
= {
46 .type
= CRYPTO_KPP_SECRET_TYPE_DH
,
53 if (len
!= crypto_dh_key_len(params
))
56 ptr
= dh_pack_data(ptr
, &secret
, sizeof(secret
));
57 ptr
= dh_pack_data(ptr
, ¶ms
->key_size
, sizeof(params
->key_size
));
58 ptr
= dh_pack_data(ptr
, ¶ms
->p_size
, sizeof(params
->p_size
));
59 ptr
= dh_pack_data(ptr
, ¶ms
->g_size
, sizeof(params
->g_size
));
60 ptr
= dh_pack_data(ptr
, params
->key
, params
->key_size
);
61 ptr
= dh_pack_data(ptr
, params
->p
, params
->p_size
);
62 dh_pack_data(ptr
, params
->g
, params
->g_size
);
66 EXPORT_SYMBOL_GPL(crypto_dh_encode_key
);
68 int crypto_dh_decode_key(const char *buf
, unsigned int len
, struct dh
*params
)
71 struct kpp_secret secret
;
73 if (unlikely(!buf
|| len
< DH_KPP_SECRET_MIN_SIZE
))
76 ptr
= dh_unpack_data(&secret
, ptr
, sizeof(secret
));
77 if (secret
.type
!= CRYPTO_KPP_SECRET_TYPE_DH
)
80 ptr
= dh_unpack_data(¶ms
->key_size
, ptr
, sizeof(params
->key_size
));
81 ptr
= dh_unpack_data(¶ms
->p_size
, ptr
, sizeof(params
->p_size
));
82 ptr
= dh_unpack_data(¶ms
->g_size
, ptr
, sizeof(params
->g_size
));
83 if (secret
.len
!= crypto_dh_key_len(params
))
87 * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since
88 * some drivers assume otherwise.
90 if (params
->key_size
> params
->p_size
||
91 params
->g_size
> params
->p_size
)
94 /* Don't allocate memory. Set pointers to data within
97 params
->key
= (void *)ptr
;
98 params
->p
= (void *)(ptr
+ params
->key_size
);
99 params
->g
= (void *)(ptr
+ params
->key_size
+ params
->p_size
);
102 * Don't permit 'p' to be 0. It's not a prime number, and it's subject
103 * to corner cases such as 'mod 0' being undefined or
104 * crypto_kpp_maxsize() returning 0.
106 if (memchr_inv(params
->p
, 0, params
->p_size
) == NULL
)
111 EXPORT_SYMBOL_GPL(crypto_dh_decode_key
);