Back to home page

LXR

 
 

    


0001 /*
0002  * Non-physical true random number generator based on timing jitter --
0003  * Linux Kernel Crypto API specific code
0004  *
0005  * Copyright Stephan Mueller <smueller@chronox.de>, 2015
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, and the entire permission notice in its entirety,
0012  *    including the disclaimer of warranties.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  * 3. The name of the author may not be used to endorse or promote
0017  *    products derived from this software without specific prior
0018  *    written permission.
0019  *
0020  * ALTERNATIVELY, this product may be distributed under the terms of
0021  * the GNU General Public License, in which case the provisions of the GPL2 are
0022  * required INSTEAD OF the above restrictions.  (This clause is
0023  * necessary due to a potential bad interaction between the GPL and
0024  * the restrictions contained in a BSD-style copyright.)
0025  *
0026  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
0027  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0028  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
0029  * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0032  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0033  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0034  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
0036  * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
0037  * DAMAGE.
0038  */
0039 
0040 #include <linux/module.h>
0041 #include <linux/slab.h>
0042 #include <linux/fips.h>
0043 #include <linux/time.h>
0044 #include <linux/crypto.h>
0045 #include <crypto/internal/rng.h>
0046 
0047 struct rand_data;
0048 int jent_read_entropy(struct rand_data *ec, unsigned char *data,
0049               unsigned int len);
0050 int jent_entropy_init(void);
0051 struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
0052                            unsigned int flags);
0053 void jent_entropy_collector_free(struct rand_data *entropy_collector);
0054 
0055 /***************************************************************************
0056  * Helper function
0057  ***************************************************************************/
0058 
0059 __u64 jent_rol64(__u64 word, unsigned int shift)
0060 {
0061     return rol64(word, shift);
0062 }
0063 
0064 void *jent_zalloc(unsigned int len)
0065 {
0066     return kzalloc(len, GFP_KERNEL);
0067 }
0068 
0069 void jent_zfree(void *ptr)
0070 {
0071     kzfree(ptr);
0072 }
0073 
0074 int jent_fips_enabled(void)
0075 {
0076     return fips_enabled;
0077 }
0078 
0079 void jent_panic(char *s)
0080 {
0081     panic("%s", s);
0082 }
0083 
0084 void jent_memcpy(void *dest, const void *src, unsigned int n)
0085 {
0086     memcpy(dest, src, n);
0087 }
0088 
0089 /*
0090  * Obtain a high-resolution time stamp value. The time stamp is used to measure
0091  * the execution time of a given code path and its variations. Hence, the time
0092  * stamp must have a sufficiently high resolution.
0093  *
0094  * Note, if the function returns zero because a given architecture does not
0095  * implement a high-resolution time stamp, the RNG code's runtime test
0096  * will detect it and will not produce output.
0097  */
0098 void jent_get_nstime(__u64 *out)
0099 {
0100     __u64 tmp = 0;
0101 
0102     tmp = random_get_entropy();
0103 
0104     /*
0105      * If random_get_entropy does not return a value, i.e. it is not
0106      * implemented for a given architecture, use a clock source.
0107      * hoping that there are timers we can work with.
0108      */
0109     if (tmp == 0)
0110         tmp = ktime_get_ns();
0111 
0112     *out = tmp;
0113 }
0114 
0115 /***************************************************************************
0116  * Kernel crypto API interface
0117  ***************************************************************************/
0118 
0119 struct jitterentropy {
0120     spinlock_t jent_lock;
0121     struct rand_data *entropy_collector;
0122 };
0123 
0124 static int jent_kcapi_init(struct crypto_tfm *tfm)
0125 {
0126     struct jitterentropy *rng = crypto_tfm_ctx(tfm);
0127     int ret = 0;
0128 
0129     rng->entropy_collector = jent_entropy_collector_alloc(1, 0);
0130     if (!rng->entropy_collector)
0131         ret = -ENOMEM;
0132 
0133     spin_lock_init(&rng->jent_lock);
0134     return ret;
0135 }
0136 
0137 static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
0138 {
0139     struct jitterentropy *rng = crypto_tfm_ctx(tfm);
0140 
0141     spin_lock(&rng->jent_lock);
0142     if (rng->entropy_collector)
0143         jent_entropy_collector_free(rng->entropy_collector);
0144     rng->entropy_collector = NULL;
0145     spin_unlock(&rng->jent_lock);
0146 }
0147 
0148 static int jent_kcapi_random(struct crypto_rng *tfm,
0149                  const u8 *src, unsigned int slen,
0150                  u8 *rdata, unsigned int dlen)
0151 {
0152     struct jitterentropy *rng = crypto_rng_ctx(tfm);
0153     int ret = 0;
0154 
0155     spin_lock(&rng->jent_lock);
0156     ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
0157     spin_unlock(&rng->jent_lock);
0158 
0159     return ret;
0160 }
0161 
0162 static int jent_kcapi_reset(struct crypto_rng *tfm,
0163                 const u8 *seed, unsigned int slen)
0164 {
0165     return 0;
0166 }
0167 
0168 static struct rng_alg jent_alg = {
0169     .generate       = jent_kcapi_random,
0170     .seed           = jent_kcapi_reset,
0171     .seedsize       = 0,
0172     .base           = {
0173         .cra_name               = "jitterentropy_rng",
0174         .cra_driver_name        = "jitterentropy_rng",
0175         .cra_priority           = 100,
0176         .cra_ctxsize            = sizeof(struct jitterentropy),
0177         .cra_module             = THIS_MODULE,
0178         .cra_init               = jent_kcapi_init,
0179         .cra_exit               = jent_kcapi_cleanup,
0180 
0181     }
0182 };
0183 
0184 static int __init jent_mod_init(void)
0185 {
0186     int ret = 0;
0187 
0188     ret = jent_entropy_init();
0189     if (ret) {
0190         pr_info("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
0191         return -EFAULT;
0192     }
0193     return crypto_register_rng(&jent_alg);
0194 }
0195 
0196 static void __exit jent_mod_exit(void)
0197 {
0198     crypto_unregister_rng(&jent_alg);
0199 }
0200 
0201 module_init(jent_mod_init);
0202 module_exit(jent_mod_exit);
0203 
0204 MODULE_LICENSE("Dual BSD/GPL");
0205 MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
0206 MODULE_DESCRIPTION("Non-physical True Random Number Generator based on CPU Jitter");
0207 MODULE_ALIAS_CRYPTO("jitterentropy_rng");