Back to home page

OSCL-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/kernel.h>
0041 #include <linux/module.h>
0042 #include <linux/slab.h>
0043 #include <linux/time.h>
0044 #include <crypto/internal/rng.h>
0045 
0046 #include "jitterentropy.h"
0047 
0048 /***************************************************************************
0049  * Helper function
0050  ***************************************************************************/
0051 
0052 void *jent_zalloc(unsigned int len)
0053 {
0054     return kzalloc(len, GFP_KERNEL);
0055 }
0056 
0057 void jent_zfree(void *ptr)
0058 {
0059     kfree_sensitive(ptr);
0060 }
0061 
0062 void jent_panic(char *s)
0063 {
0064     panic("%s", s);
0065 }
0066 
0067 void jent_memcpy(void *dest, const void *src, unsigned int n)
0068 {
0069     memcpy(dest, src, n);
0070 }
0071 
0072 /*
0073  * Obtain a high-resolution time stamp value. The time stamp is used to measure
0074  * the execution time of a given code path and its variations. Hence, the time
0075  * stamp must have a sufficiently high resolution.
0076  *
0077  * Note, if the function returns zero because a given architecture does not
0078  * implement a high-resolution time stamp, the RNG code's runtime test
0079  * will detect it and will not produce output.
0080  */
0081 void jent_get_nstime(__u64 *out)
0082 {
0083     __u64 tmp = 0;
0084 
0085     tmp = random_get_entropy();
0086 
0087     /*
0088      * If random_get_entropy does not return a value, i.e. it is not
0089      * implemented for a given architecture, use a clock source.
0090      * hoping that there are timers we can work with.
0091      */
0092     if (tmp == 0)
0093         tmp = ktime_get_ns();
0094 
0095     *out = tmp;
0096 }
0097 
0098 /***************************************************************************
0099  * Kernel crypto API interface
0100  ***************************************************************************/
0101 
0102 struct jitterentropy {
0103     spinlock_t jent_lock;
0104     struct rand_data *entropy_collector;
0105     unsigned int reset_cnt;
0106 };
0107 
0108 static int jent_kcapi_init(struct crypto_tfm *tfm)
0109 {
0110     struct jitterentropy *rng = crypto_tfm_ctx(tfm);
0111     int ret = 0;
0112 
0113     rng->entropy_collector = jent_entropy_collector_alloc(1, 0);
0114     if (!rng->entropy_collector)
0115         ret = -ENOMEM;
0116 
0117     spin_lock_init(&rng->jent_lock);
0118     return ret;
0119 }
0120 
0121 static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
0122 {
0123     struct jitterentropy *rng = crypto_tfm_ctx(tfm);
0124 
0125     spin_lock(&rng->jent_lock);
0126     if (rng->entropy_collector)
0127         jent_entropy_collector_free(rng->entropy_collector);
0128     rng->entropy_collector = NULL;
0129     spin_unlock(&rng->jent_lock);
0130 }
0131 
0132 static int jent_kcapi_random(struct crypto_rng *tfm,
0133                  const u8 *src, unsigned int slen,
0134                  u8 *rdata, unsigned int dlen)
0135 {
0136     struct jitterentropy *rng = crypto_rng_ctx(tfm);
0137     int ret = 0;
0138 
0139     spin_lock(&rng->jent_lock);
0140 
0141     /* Return a permanent error in case we had too many resets in a row. */
0142     if (rng->reset_cnt > (1<<10)) {
0143         ret = -EFAULT;
0144         goto out;
0145     }
0146 
0147     ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
0148 
0149     /* Reset RNG in case of health failures */
0150     if (ret < -1) {
0151         pr_warn_ratelimited("Reset Jitter RNG due to health test failure: %s failure\n",
0152                     (ret == -2) ? "Repetition Count Test" :
0153                           "Adaptive Proportion Test");
0154 
0155         rng->reset_cnt++;
0156 
0157         ret = -EAGAIN;
0158     } else {
0159         rng->reset_cnt = 0;
0160 
0161         /* Convert the Jitter RNG error into a usable error code */
0162         if (ret == -1)
0163             ret = -EINVAL;
0164     }
0165 
0166 out:
0167     spin_unlock(&rng->jent_lock);
0168 
0169     return ret;
0170 }
0171 
0172 static int jent_kcapi_reset(struct crypto_rng *tfm,
0173                 const u8 *seed, unsigned int slen)
0174 {
0175     return 0;
0176 }
0177 
0178 static struct rng_alg jent_alg = {
0179     .generate       = jent_kcapi_random,
0180     .seed           = jent_kcapi_reset,
0181     .seedsize       = 0,
0182     .base           = {
0183         .cra_name               = "jitterentropy_rng",
0184         .cra_driver_name        = "jitterentropy_rng",
0185         .cra_priority           = 100,
0186         .cra_ctxsize            = sizeof(struct jitterentropy),
0187         .cra_module             = THIS_MODULE,
0188         .cra_init               = jent_kcapi_init,
0189         .cra_exit               = jent_kcapi_cleanup,
0190 
0191     }
0192 };
0193 
0194 static int __init jent_mod_init(void)
0195 {
0196     int ret = 0;
0197 
0198     ret = jent_entropy_init();
0199     if (ret) {
0200         pr_info("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
0201         return -EFAULT;
0202     }
0203     return crypto_register_rng(&jent_alg);
0204 }
0205 
0206 static void __exit jent_mod_exit(void)
0207 {
0208     crypto_unregister_rng(&jent_alg);
0209 }
0210 
0211 module_init(jent_mod_init);
0212 module_exit(jent_mod_exit);
0213 
0214 MODULE_LICENSE("Dual BSD/GPL");
0215 MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
0216 MODULE_DESCRIPTION("Non-physical True Random Number Generator based on CPU Jitter");
0217 MODULE_ALIAS_CRYPTO("jitterentropy_rng");