Blame view

crypto/geniv.c 3.81 KB
20cc01baa   Herbert Xu   crypto: aead - Sp...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  // SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * geniv: Shared IV generator code
   *
   * This file provides common code to IV generators such as seqiv.
   *
   * Copyright (c) 2007-2019 Herbert Xu <herbert@gondor.apana.org.au>
   */
  
  #include <crypto/internal/geniv.h>
  #include <crypto/internal/rng.h>
  #include <crypto/null.h>
  #include <linux/err.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/rtnetlink.h>
  #include <linux/slab.h>
  
  static int aead_geniv_setkey(struct crypto_aead *tfm,
  			     const u8 *key, unsigned int keylen)
  {
  	struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
  
  	return crypto_aead_setkey(ctx->child, key, keylen);
  }
  
  static int aead_geniv_setauthsize(struct crypto_aead *tfm,
  				  unsigned int authsize)
  {
  	struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
  
  	return crypto_aead_setauthsize(ctx->child, authsize);
  }
0f8f6d86d   Eric Biggers   crypto: geniv - c...
34
35
36
37
38
  static void aead_geniv_free(struct aead_instance *inst)
  {
  	crypto_drop_aead(aead_instance_ctx(inst));
  	kfree(inst);
  }
20cc01baa   Herbert Xu   crypto: aead - Sp...
39
  struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
e72b48c5e   Eric Biggers   crypto: geniv - r...
40
  				       struct rtattr **tb)
20cc01baa   Herbert Xu   crypto: aead - Sp...
41
  {
20cc01baa   Herbert Xu   crypto: aead - Sp...
42
  	struct crypto_aead_spawn *spawn;
20cc01baa   Herbert Xu   crypto: aead - Sp...
43
44
45
46
  	struct aead_instance *inst;
  	struct aead_alg *alg;
  	unsigned int ivsize;
  	unsigned int maxauthsize;
e72b48c5e   Eric Biggers   crypto: geniv - r...
47
  	u32 mask;
20cc01baa   Herbert Xu   crypto: aead - Sp...
48
  	int err;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
49
50
51
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
  	if (err)
  		return ERR_PTR(err);
20cc01baa   Herbert Xu   crypto: aead - Sp...
52

20cc01baa   Herbert Xu   crypto: aead - Sp...
53
54
55
56
57
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
  		return ERR_PTR(-ENOMEM);
  
  	spawn = aead_instance_ctx(inst);
cd900f0ca   Eric Biggers   crypto: aead - pa...
58
  	err = crypto_grab_aead(spawn, aead_crypto_instance(inst),
e72b48c5e   Eric Biggers   crypto: geniv - r...
59
  			       crypto_attr_alg_name(tb[1]), 0, mask);
20cc01baa   Herbert Xu   crypto: aead - Sp...
60
61
62
63
64
65
66
67
68
69
  	if (err)
  		goto err_free_inst;
  
  	alg = crypto_spawn_aead_alg(spawn);
  
  	ivsize = crypto_aead_alg_ivsize(alg);
  	maxauthsize = crypto_aead_alg_maxauthsize(alg);
  
  	err = -EINVAL;
  	if (ivsize < sizeof(u64))
376ffe1ac   Eric Biggers   crypto: geniv - s...
70
  		goto err_free_inst;
20cc01baa   Herbert Xu   crypto: aead - Sp...
71
72
73
74
75
  
  	err = -ENAMETOOLONG;
  	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  		     "%s(%s)", tmpl->name, alg->base.cra_name) >=
  	    CRYPTO_MAX_ALG_NAME)
376ffe1ac   Eric Biggers   crypto: geniv - s...
76
  		goto err_free_inst;
20cc01baa   Herbert Xu   crypto: aead - Sp...
77
78
79
  	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
  		     "%s(%s)", tmpl->name, alg->base.cra_driver_name) >=
  	    CRYPTO_MAX_ALG_NAME)
376ffe1ac   Eric Biggers   crypto: geniv - s...
80
  		goto err_free_inst;
20cc01baa   Herbert Xu   crypto: aead - Sp...
81

20cc01baa   Herbert Xu   crypto: aead - Sp...
82
83
84
85
86
87
88
89
90
91
  	inst->alg.base.cra_priority = alg->base.cra_priority;
  	inst->alg.base.cra_blocksize = alg->base.cra_blocksize;
  	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
  	inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
  
  	inst->alg.setkey = aead_geniv_setkey;
  	inst->alg.setauthsize = aead_geniv_setauthsize;
  
  	inst->alg.ivsize = ivsize;
  	inst->alg.maxauthsize = maxauthsize;
0f8f6d86d   Eric Biggers   crypto: geniv - c...
92
  	inst->free = aead_geniv_free;
20cc01baa   Herbert Xu   crypto: aead - Sp...
93
94
  out:
  	return inst;
20cc01baa   Herbert Xu   crypto: aead - Sp...
95
  err_free_inst:
376ffe1ac   Eric Biggers   crypto: geniv - s...
96
  	aead_geniv_free(inst);
20cc01baa   Herbert Xu   crypto: aead - Sp...
97
98
99
100
  	inst = ERR_PTR(err);
  	goto out;
  }
  EXPORT_SYMBOL_GPL(aead_geniv_alloc);
20cc01baa   Herbert Xu   crypto: aead - Sp...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  int aead_init_geniv(struct crypto_aead *aead)
  {
  	struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead);
  	struct aead_instance *inst = aead_alg_instance(aead);
  	struct crypto_aead *child;
  	int err;
  
  	spin_lock_init(&ctx->lock);
  
  	err = crypto_get_default_rng();
  	if (err)
  		goto out;
  
  	err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
  				   crypto_aead_ivsize(aead));
  	crypto_put_default_rng();
  	if (err)
  		goto out;
  
  	ctx->sknull = crypto_get_default_null_skcipher();
  	err = PTR_ERR(ctx->sknull);
  	if (IS_ERR(ctx->sknull))
  		goto out;
  
  	child = crypto_spawn_aead(aead_instance_ctx(inst));
  	err = PTR_ERR(child);
  	if (IS_ERR(child))
  		goto drop_null;
  
  	ctx->child = child;
  	crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) +
  				      sizeof(struct aead_request));
  
  	err = 0;
  
  out:
  	return err;
  
  drop_null:
  	crypto_put_default_null_skcipher();
  	goto out;
  }
  EXPORT_SYMBOL_GPL(aead_init_geniv);
  
  void aead_exit_geniv(struct crypto_aead *tfm)
  {
  	struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
  
  	crypto_free_aead(ctx->child);
  	crypto_put_default_null_skcipher();
  }
  EXPORT_SYMBOL_GPL(aead_exit_geniv);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Shared IV generator code");