Back to home page

LXR

 
 

    


0001 /*  Diffie-Hellman Key Agreement Method [RFC2631]
0002  *
0003  * Copyright (c) 2016, Intel Corporation
0004  * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public Licence
0008  * as published by the Free Software Foundation; either version
0009  * 2 of the Licence, or (at your option) any later version.
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <crypto/internal/kpp.h>
0014 #include <crypto/kpp.h>
0015 #include <crypto/dh.h>
0016 #include <linux/mpi.h>
0017 
0018 struct dh_ctx {
0019     MPI p;
0020     MPI g;
0021     MPI xa;
0022 };
0023 
0024 static inline void dh_clear_params(struct dh_ctx *ctx)
0025 {
0026     mpi_free(ctx->p);
0027     mpi_free(ctx->g);
0028     ctx->p = NULL;
0029     ctx->g = NULL;
0030 }
0031 
0032 static void dh_free_ctx(struct dh_ctx *ctx)
0033 {
0034     dh_clear_params(ctx);
0035     mpi_free(ctx->xa);
0036     ctx->xa = NULL;
0037 }
0038 
0039 /*
0040  * If base is g we compute the public key
0041  *  ya = g^xa mod p; [RFC2631 sec 2.1.1]
0042  * else if base if the counterpart public key we compute the shared secret
0043  *  ZZ = yb^xa mod p; [RFC2631 sec 2.1.1]
0044  */
0045 static int _compute_val(const struct dh_ctx *ctx, MPI base, MPI val)
0046 {
0047     /* val = base^xa mod p */
0048     return mpi_powm(val, base, ctx->xa, ctx->p);
0049 }
0050 
0051 static inline struct dh_ctx *dh_get_ctx(struct crypto_kpp *tfm)
0052 {
0053     return kpp_tfm_ctx(tfm);
0054 }
0055 
0056 static int dh_check_params_length(unsigned int p_len)
0057 {
0058     return (p_len < 1536) ? -EINVAL : 0;
0059 }
0060 
0061 static int dh_set_params(struct dh_ctx *ctx, struct dh *params)
0062 {
0063     if (unlikely(!params->p || !params->g))
0064         return -EINVAL;
0065 
0066     if (dh_check_params_length(params->p_size << 3))
0067         return -EINVAL;
0068 
0069     ctx->p = mpi_read_raw_data(params->p, params->p_size);
0070     if (!ctx->p)
0071         return -EINVAL;
0072 
0073     ctx->g = mpi_read_raw_data(params->g, params->g_size);
0074     if (!ctx->g) {
0075         mpi_free(ctx->p);
0076         return -EINVAL;
0077     }
0078 
0079     return 0;
0080 }
0081 
0082 static int dh_set_secret(struct crypto_kpp *tfm, void *buf, unsigned int len)
0083 {
0084     struct dh_ctx *ctx = dh_get_ctx(tfm);
0085     struct dh params;
0086 
0087     if (crypto_dh_decode_key(buf, len, &params) < 0)
0088         return -EINVAL;
0089 
0090     if (dh_set_params(ctx, &params) < 0)
0091         return -EINVAL;
0092 
0093     ctx->xa = mpi_read_raw_data(params.key, params.key_size);
0094     if (!ctx->xa) {
0095         dh_clear_params(ctx);
0096         return -EINVAL;
0097     }
0098 
0099     return 0;
0100 }
0101 
0102 static int dh_compute_value(struct kpp_request *req)
0103 {
0104     struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
0105     struct dh_ctx *ctx = dh_get_ctx(tfm);
0106     MPI base, val = mpi_alloc(0);
0107     int ret = 0;
0108     int sign;
0109 
0110     if (!val)
0111         return -ENOMEM;
0112 
0113     if (unlikely(!ctx->xa)) {
0114         ret = -EINVAL;
0115         goto err_free_val;
0116     }
0117 
0118     if (req->src) {
0119         base = mpi_read_raw_from_sgl(req->src, req->src_len);
0120         if (!base) {
0121             ret = -EINVAL;
0122             goto err_free_val;
0123         }
0124     } else {
0125         base = ctx->g;
0126     }
0127 
0128     ret = _compute_val(ctx, base, val);
0129     if (ret)
0130         goto err_free_base;
0131 
0132     ret = mpi_write_to_sgl(val, req->dst, req->dst_len, &sign);
0133     if (ret)
0134         goto err_free_base;
0135 
0136     if (sign < 0)
0137         ret = -EBADMSG;
0138 err_free_base:
0139     if (req->src)
0140         mpi_free(base);
0141 err_free_val:
0142     mpi_free(val);
0143     return ret;
0144 }
0145 
0146 static int dh_max_size(struct crypto_kpp *tfm)
0147 {
0148     struct dh_ctx *ctx = dh_get_ctx(tfm);
0149 
0150     return mpi_get_size(ctx->p);
0151 }
0152 
0153 static void dh_exit_tfm(struct crypto_kpp *tfm)
0154 {
0155     struct dh_ctx *ctx = dh_get_ctx(tfm);
0156 
0157     dh_free_ctx(ctx);
0158 }
0159 
0160 static struct kpp_alg dh = {
0161     .set_secret = dh_set_secret,
0162     .generate_public_key = dh_compute_value,
0163     .compute_shared_secret = dh_compute_value,
0164     .max_size = dh_max_size,
0165     .exit = dh_exit_tfm,
0166     .base = {
0167         .cra_name = "dh",
0168         .cra_driver_name = "dh-generic",
0169         .cra_priority = 100,
0170         .cra_module = THIS_MODULE,
0171         .cra_ctxsize = sizeof(struct dh_ctx),
0172     },
0173 };
0174 
0175 static int dh_init(void)
0176 {
0177     return crypto_register_kpp(&dh);
0178 }
0179 
0180 static void dh_exit(void)
0181 {
0182     crypto_unregister_kpp(&dh);
0183 }
0184 
0185 module_init(dh_init);
0186 module_exit(dh_exit);
0187 MODULE_ALIAS_CRYPTO("dh");
0188 MODULE_LICENSE("GPL");
0189 MODULE_DESCRIPTION("DH generic algorithm");