apm821xx: backport accepted linux-crypto patches
[oweals/openwrt.git] / target / linux / apm821xx / patches-4.14 / 023-0006-crypto-crypto4xx-add-prng-crypto-support.patch
1 From d072bfa4885354fff86aa1fb1dbc4f1533c9e0bf Mon Sep 17 00:00:00 2001
2 From: Christian Lamparter <chunkeey@gmail.com>
3 Date: Sun, 23 Dec 2018 02:16:13 +0100
4 Subject: [PATCH 06/15] crypto: crypto4xx - add prng crypto support
5
6 This patch adds support for crypto4xx's ANSI X9.17 Annex C compliant
7 pseudo random number generator which provides a pseudo random source
8 for the purpose of generating  Initialization Vectors (IV's) for AES
9 algorithms to the Packet Engine and other pseudo random number
10 requirements.
11
12 Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
13 Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
14 ---
15  drivers/crypto/amcc/crypto4xx_core.c    | 87 +++++++++++++++++++++++++
16  drivers/crypto/amcc/crypto4xx_core.h    |  4 ++
17  drivers/crypto/amcc/crypto4xx_reg_def.h |  1 +
18  3 files changed, 92 insertions(+)
19
20 --- a/drivers/crypto/amcc/crypto4xx_core.c
21 +++ b/drivers/crypto/amcc/crypto4xx_core.c
22 @@ -40,9 +40,11 @@
23  #include <crypto/ctr.h>
24  #include <crypto/gcm.h>
25  #include <crypto/sha.h>
26 +#include <crypto/rng.h>
27  #include <crypto/scatterwalk.h>
28  #include <crypto/skcipher.h>
29  #include <crypto/internal/aead.h>
30 +#include <crypto/internal/rng.h>
31  #include <crypto/internal/skcipher.h>
32  #include "crypto4xx_reg_def.h"
33  #include "crypto4xx_core.h"
34 @@ -1035,6 +1037,10 @@ static int crypto4xx_register_alg(struct
35                         rc = crypto_register_ahash(&alg->alg.u.hash);
36                         break;
37  
38 +               case CRYPTO_ALG_TYPE_RNG:
39 +                       rc = crypto_register_rng(&alg->alg.u.rng);
40 +                       break;
41 +
42                 default:
43                         rc = crypto_register_skcipher(&alg->alg.u.cipher);
44                         break;
45 @@ -1064,6 +1070,10 @@ static void crypto4xx_unregister_alg(str
46                         crypto_unregister_aead(&alg->alg.u.aead);
47                         break;
48  
49 +               case CRYPTO_ALG_TYPE_RNG:
50 +                       crypto_unregister_rng(&alg->alg.u.rng);
51 +                       break;
52 +
53                 default:
54                         crypto_unregister_skcipher(&alg->alg.u.cipher);
55                 }
56 @@ -1122,6 +1132,69 @@ static irqreturn_t crypto4xx_ce_interrup
57                 PPC4XX_TMO_ERR_INT);
58  }
59  
60 +static int ppc4xx_prng_data_read(struct crypto4xx_device *dev,
61 +                                u8 *data, unsigned int max)
62 +{
63 +       unsigned int i, curr = 0;
64 +       u32 val[2];
65 +
66 +       do {
67 +               /* trigger PRN generation */
68 +               writel(PPC4XX_PRNG_CTRL_AUTO_EN,
69 +                      dev->ce_base + CRYPTO4XX_PRNG_CTRL);
70 +
71 +               for (i = 0; i < 1024; i++) {
72 +                       /* usually 19 iterations are enough */
73 +                       if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) &
74 +                            CRYPTO4XX_PRNG_STAT_BUSY))
75 +                               continue;
76 +
77 +                       val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0);
78 +                       val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1);
79 +                       break;
80 +               }
81 +               if (i == 1024)
82 +                       return -ETIMEDOUT;
83 +
84 +               if ((max - curr) >= 8) {
85 +                       memcpy(data, &val, 8);
86 +                       data += 8;
87 +                       curr += 8;
88 +               } else {
89 +                       /* copy only remaining bytes */
90 +                       memcpy(data, &val, max - curr);
91 +                       break;
92 +               }
93 +       } while (curr < max);
94 +
95 +       return curr;
96 +}
97 +
98 +static int crypto4xx_prng_generate(struct crypto_rng *tfm,
99 +                                  const u8 *src, unsigned int slen,
100 +                                  u8 *dstn, unsigned int dlen)
101 +{
102 +       struct rng_alg *alg = crypto_rng_alg(tfm);
103 +       struct crypto4xx_alg *amcc_alg;
104 +       struct crypto4xx_device *dev;
105 +       int ret;
106 +
107 +       amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng);
108 +       dev = amcc_alg->dev;
109 +
110 +       mutex_lock(&dev->core_dev->rng_lock);
111 +       ret = ppc4xx_prng_data_read(dev, dstn, dlen);
112 +       mutex_unlock(&dev->core_dev->rng_lock);
113 +       return ret;
114 +}
115 +
116 +
117 +static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed,
118 +                       unsigned int slen)
119 +{
120 +       return 0;
121 +}
122 +
123  /**
124   * Supported Crypto Algorithms
125   */
126 @@ -1291,6 +1364,18 @@ static struct crypto4xx_alg_common crypt
127                         .cra_module     = THIS_MODULE,
128                 },
129         } },
130 +       { .type = CRYPTO_ALG_TYPE_RNG, .u.rng = {
131 +               .base = {
132 +                       .cra_name               = "stdrng",
133 +                       .cra_driver_name        = "crypto4xx_rng",
134 +                       .cra_priority           = 300,
135 +                       .cra_ctxsize            = 0,
136 +                       .cra_module             = THIS_MODULE,
137 +               },
138 +               .generate               = crypto4xx_prng_generate,
139 +               .seed                   = crypto4xx_prng_seed,
140 +               .seedsize               = 0,
141 +       } },
142  };
143  
144  /**
145 @@ -1360,6 +1445,7 @@ static int crypto4xx_probe(struct platfo
146         core_dev->dev->core_dev = core_dev;
147         core_dev->dev->is_revb = is_revb;
148         core_dev->device = dev;
149 +       mutex_init(&core_dev->rng_lock);
150         spin_lock_init(&core_dev->lock);
151         INIT_LIST_HEAD(&core_dev->dev->alg_list);
152         ratelimit_default_init(&core_dev->dev->aead_ratelimit);
153 @@ -1439,6 +1525,7 @@ static int crypto4xx_remove(struct platf
154         tasklet_kill(&core_dev->tasklet);
155         /* Un-register with Linux CryptoAPI */
156         crypto4xx_unregister_alg(core_dev->dev);
157 +       mutex_destroy(&core_dev->rng_lock);
158         /* Free all allocated memory */
159         crypto4xx_stop_all(core_dev);
160  
161 --- a/drivers/crypto/amcc/crypto4xx_core.h
162 +++ b/drivers/crypto/amcc/crypto4xx_core.h
163 @@ -23,8 +23,10 @@
164  #define __CRYPTO4XX_CORE_H__
165  
166  #include <linux/ratelimit.h>
167 +#include <linux/mutex.h>
168  #include <crypto/internal/hash.h>
169  #include <crypto/internal/aead.h>
170 +#include <crypto/internal/rng.h>
171  #include <crypto/internal/skcipher.h>
172  #include "crypto4xx_reg_def.h"
173  #include "crypto4xx_sa.h"
174 @@ -119,6 +121,7 @@ struct crypto4xx_core_device {
175         u32 irq;
176         struct tasklet_struct tasklet;
177         spinlock_t lock;
178 +       struct mutex rng_lock;
179  };
180  
181  struct crypto4xx_ctx {
182 @@ -143,6 +146,7 @@ struct crypto4xx_alg_common {
183                 struct skcipher_alg cipher;
184                 struct ahash_alg hash;
185                 struct aead_alg aead;
186 +               struct rng_alg rng;
187         } u;
188  };
189  
190 --- a/drivers/crypto/amcc/crypto4xx_reg_def.h
191 +++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
192 @@ -100,6 +100,7 @@
193  #define CRYPTO4XX_ENDIAN_CFG                   0x000600d8
194  
195  #define CRYPTO4XX_PRNG_STAT                    0x00070000
196 +#define CRYPTO4XX_PRNG_STAT_BUSY               0x1
197  #define CRYPTO4XX_PRNG_CTRL                    0x00070004
198  #define CRYPTO4XX_PRNG_SEED_L                  0x00070008
199  #define CRYPTO4XX_PRNG_SEED_H                  0x0007000c