Back to home page

LXR

 
 

    


0001 /*
0002  * Copyright (c) 2016, Intel Corporation
0003  * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
0004  *
0005  * This program is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU General Public Licence
0007  * as published by the Free Software Foundation; either version
0008  * 2 of the Licence, or (at your option) any later version.
0009  */
0010 #include <linux/kernel.h>
0011 #include <linux/export.h>
0012 #include <linux/err.h>
0013 #include <linux/string.h>
0014 #include <crypto/dh.h>
0015 #include <crypto/kpp.h>
0016 
0017 #define DH_KPP_SECRET_MIN_SIZE (sizeof(struct kpp_secret) + 3 * sizeof(int))
0018 
0019 static inline u8 *dh_pack_data(void *dst, const void *src, size_t size)
0020 {
0021     memcpy(dst, src, size);
0022     return dst + size;
0023 }
0024 
0025 static inline const u8 *dh_unpack_data(void *dst, const void *src, size_t size)
0026 {
0027     memcpy(dst, src, size);
0028     return src + size;
0029 }
0030 
0031 static inline int dh_data_size(const struct dh *p)
0032 {
0033     return p->key_size + p->p_size + p->g_size;
0034 }
0035 
0036 int crypto_dh_key_len(const struct dh *p)
0037 {
0038     return DH_KPP_SECRET_MIN_SIZE + dh_data_size(p);
0039 }
0040 EXPORT_SYMBOL_GPL(crypto_dh_key_len);
0041 
0042 int crypto_dh_encode_key(char *buf, unsigned int len, const struct dh *params)
0043 {
0044     u8 *ptr = buf;
0045     struct kpp_secret secret = {
0046         .type = CRYPTO_KPP_SECRET_TYPE_DH,
0047         .len = len
0048     };
0049 
0050     if (unlikely(!buf))
0051         return -EINVAL;
0052 
0053     if (len != crypto_dh_key_len(params))
0054         return -EINVAL;
0055 
0056     ptr = dh_pack_data(ptr, &secret, sizeof(secret));
0057     ptr = dh_pack_data(ptr, &params->key_size, sizeof(params->key_size));
0058     ptr = dh_pack_data(ptr, &params->p_size, sizeof(params->p_size));
0059     ptr = dh_pack_data(ptr, &params->g_size, sizeof(params->g_size));
0060     ptr = dh_pack_data(ptr, params->key, params->key_size);
0061     ptr = dh_pack_data(ptr, params->p, params->p_size);
0062     dh_pack_data(ptr, params->g, params->g_size);
0063 
0064     return 0;
0065 }
0066 EXPORT_SYMBOL_GPL(crypto_dh_encode_key);
0067 
0068 int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
0069 {
0070     const u8 *ptr = buf;
0071     struct kpp_secret secret;
0072 
0073     if (unlikely(!buf || len < DH_KPP_SECRET_MIN_SIZE))
0074         return -EINVAL;
0075 
0076     ptr = dh_unpack_data(&secret, ptr, sizeof(secret));
0077     if (secret.type != CRYPTO_KPP_SECRET_TYPE_DH)
0078         return -EINVAL;
0079 
0080     ptr = dh_unpack_data(&params->key_size, ptr, sizeof(params->key_size));
0081     ptr = dh_unpack_data(&params->p_size, ptr, sizeof(params->p_size));
0082     ptr = dh_unpack_data(&params->g_size, ptr, sizeof(params->g_size));
0083     if (secret.len != crypto_dh_key_len(params))
0084         return -EINVAL;
0085 
0086     /* Don't allocate memory. Set pointers to data within
0087      * the given buffer
0088      */
0089     params->key = (void *)ptr;
0090     params->p = (void *)(ptr + params->key_size);
0091     params->g = (void *)(ptr + params->key_size + params->p_size);
0092 
0093     return 0;
0094 }
0095 EXPORT_SYMBOL_GPL(crypto_dh_decode_key);