Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/crypto/amcc/crypto4xx_alg.c
15111 views
1
/**
2
* AMCC SoC PPC4xx Crypto Driver
3
*
4
* Copyright (c) 2008 Applied Micro Circuits Corporation.
5
* All rights reserved. James Hsiao <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* This file implements the Linux crypto algorithms.
18
*/
19
20
#include <linux/kernel.h>
21
#include <linux/interrupt.h>
22
#include <linux/spinlock_types.h>
23
#include <linux/scatterlist.h>
24
#include <linux/crypto.h>
25
#include <linux/hash.h>
26
#include <crypto/internal/hash.h>
27
#include <linux/dma-mapping.h>
28
#include <crypto/algapi.h>
29
#include <crypto/aes.h>
30
#include <crypto/sha.h>
31
#include "crypto4xx_reg_def.h"
32
#include "crypto4xx_sa.h"
33
#include "crypto4xx_core.h"
34
35
void set_dynamic_sa_command_0(struct dynamic_sa_ctl *sa, u32 save_h,
36
u32 save_iv, u32 ld_h, u32 ld_iv, u32 hdr_proc,
37
u32 h, u32 c, u32 pad_type, u32 op_grp, u32 op,
38
u32 dir)
39
{
40
sa->sa_command_0.w = 0;
41
sa->sa_command_0.bf.save_hash_state = save_h;
42
sa->sa_command_0.bf.save_iv = save_iv;
43
sa->sa_command_0.bf.load_hash_state = ld_h;
44
sa->sa_command_0.bf.load_iv = ld_iv;
45
sa->sa_command_0.bf.hdr_proc = hdr_proc;
46
sa->sa_command_0.bf.hash_alg = h;
47
sa->sa_command_0.bf.cipher_alg = c;
48
sa->sa_command_0.bf.pad_type = pad_type & 3;
49
sa->sa_command_0.bf.extend_pad = pad_type >> 2;
50
sa->sa_command_0.bf.op_group = op_grp;
51
sa->sa_command_0.bf.opcode = op;
52
sa->sa_command_0.bf.dir = dir;
53
}
54
55
void set_dynamic_sa_command_1(struct dynamic_sa_ctl *sa, u32 cm, u32 hmac_mc,
56
u32 cfb, u32 esn, u32 sn_mask, u32 mute,
57
u32 cp_pad, u32 cp_pay, u32 cp_hdr)
58
{
59
sa->sa_command_1.w = 0;
60
sa->sa_command_1.bf.crypto_mode31 = (cm & 4) >> 2;
61
sa->sa_command_1.bf.crypto_mode9_8 = cm & 3;
62
sa->sa_command_1.bf.feedback_mode = cfb,
63
sa->sa_command_1.bf.sa_rev = 1;
64
sa->sa_command_1.bf.extended_seq_num = esn;
65
sa->sa_command_1.bf.seq_num_mask = sn_mask;
66
sa->sa_command_1.bf.mutable_bit_proc = mute;
67
sa->sa_command_1.bf.copy_pad = cp_pad;
68
sa->sa_command_1.bf.copy_payload = cp_pay;
69
sa->sa_command_1.bf.copy_hdr = cp_hdr;
70
}
71
72
int crypto4xx_encrypt(struct ablkcipher_request *req)
73
{
74
struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
75
76
ctx->direction = DIR_OUTBOUND;
77
ctx->hash_final = 0;
78
ctx->is_hash = 0;
79
ctx->pd_ctl = 0x1;
80
81
return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
82
req->nbytes, req->info,
83
get_dynamic_sa_iv_size(ctx));
84
}
85
86
int crypto4xx_decrypt(struct ablkcipher_request *req)
87
{
88
struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
89
90
ctx->direction = DIR_INBOUND;
91
ctx->hash_final = 0;
92
ctx->is_hash = 0;
93
ctx->pd_ctl = 1;
94
95
return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
96
req->nbytes, req->info,
97
get_dynamic_sa_iv_size(ctx));
98
}
99
100
/**
101
* AES Functions
102
*/
103
static int crypto4xx_setkey_aes(struct crypto_ablkcipher *cipher,
104
const u8 *key,
105
unsigned int keylen,
106
unsigned char cm,
107
u8 fb)
108
{
109
struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
110
struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
111
struct dynamic_sa_ctl *sa;
112
int rc;
113
114
if (keylen != AES_KEYSIZE_256 &&
115
keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_128) {
116
crypto_ablkcipher_set_flags(cipher,
117
CRYPTO_TFM_RES_BAD_KEY_LEN);
118
return -EINVAL;
119
}
120
121
/* Create SA */
122
if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
123
crypto4xx_free_sa(ctx);
124
125
rc = crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4);
126
if (rc)
127
return rc;
128
129
if (ctx->state_record_dma_addr == 0) {
130
rc = crypto4xx_alloc_state_record(ctx);
131
if (rc) {
132
crypto4xx_free_sa(ctx);
133
return rc;
134
}
135
}
136
/* Setup SA */
137
sa = (struct dynamic_sa_ctl *) ctx->sa_in;
138
ctx->hash_final = 0;
139
140
set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
141
SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
142
SA_NO_HEADER_PROC, SA_HASH_ALG_NULL,
143
SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
144
SA_OP_GROUP_BASIC, SA_OPCODE_DECRYPT,
145
DIR_INBOUND);
146
147
set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH,
148
fb, SA_EXTENDED_SN_OFF,
149
SA_SEQ_MASK_OFF, SA_MC_ENABLE,
150
SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
151
SA_NOT_COPY_HDR);
152
crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
153
key, keylen);
154
sa->sa_contents = SA_AES_CONTENTS | (keylen << 2);
155
sa->sa_command_1.bf.key_len = keylen >> 3;
156
ctx->is_hash = 0;
157
ctx->direction = DIR_INBOUND;
158
memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
159
(void *)&ctx->state_record_dma_addr, 4);
160
ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx);
161
162
memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
163
sa = (struct dynamic_sa_ctl *) ctx->sa_out;
164
sa->sa_command_0.bf.dir = DIR_OUTBOUND;
165
166
return 0;
167
}
168
169
int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
170
const u8 *key, unsigned int keylen)
171
{
172
return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CBC,
173
CRYPTO_FEEDBACK_MODE_NO_FB);
174
}
175
176
/**
177
* HASH SHA1 Functions
178
*/
179
static int crypto4xx_hash_alg_init(struct crypto_tfm *tfm,
180
unsigned int sa_len,
181
unsigned char ha,
182
unsigned char hm)
183
{
184
struct crypto_alg *alg = tfm->__crt_alg;
185
struct crypto4xx_alg *my_alg = crypto_alg_to_crypto4xx_alg(alg);
186
struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
187
struct dynamic_sa_ctl *sa;
188
struct dynamic_sa_hash160 *sa_in;
189
int rc;
190
191
ctx->dev = my_alg->dev;
192
ctx->is_hash = 1;
193
ctx->hash_final = 0;
194
195
/* Create SA */
196
if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
197
crypto4xx_free_sa(ctx);
198
199
rc = crypto4xx_alloc_sa(ctx, sa_len);
200
if (rc)
201
return rc;
202
203
if (ctx->state_record_dma_addr == 0) {
204
crypto4xx_alloc_state_record(ctx);
205
if (!ctx->state_record_dma_addr) {
206
crypto4xx_free_sa(ctx);
207
return -ENOMEM;
208
}
209
}
210
211
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
212
sizeof(struct crypto4xx_ctx));
213
sa = (struct dynamic_sa_ctl *) ctx->sa_in;
214
set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
215
SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
216
SA_NO_HEADER_PROC, ha, SA_CIPHER_ALG_NULL,
217
SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
218
SA_OPCODE_HASH, DIR_INBOUND);
219
set_dynamic_sa_command_1(sa, 0, SA_HASH_MODE_HASH,
220
CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
221
SA_SEQ_MASK_OFF, SA_MC_ENABLE,
222
SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
223
SA_NOT_COPY_HDR);
224
ctx->direction = DIR_INBOUND;
225
sa->sa_contents = SA_HASH160_CONTENTS;
226
sa_in = (struct dynamic_sa_hash160 *) ctx->sa_in;
227
/* Need to zero hash digest in SA */
228
memset(sa_in->inner_digest, 0, sizeof(sa_in->inner_digest));
229
memset(sa_in->outer_digest, 0, sizeof(sa_in->outer_digest));
230
sa_in->state_ptr = ctx->state_record_dma_addr;
231
ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx);
232
233
return 0;
234
}
235
236
int crypto4xx_hash_init(struct ahash_request *req)
237
{
238
struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
239
int ds;
240
struct dynamic_sa_ctl *sa;
241
242
sa = (struct dynamic_sa_ctl *) ctx->sa_in;
243
ds = crypto_ahash_digestsize(
244
__crypto_ahash_cast(req->base.tfm));
245
sa->sa_command_0.bf.digest_len = ds >> 2;
246
sa->sa_command_0.bf.load_hash_state = SA_LOAD_HASH_FROM_SA;
247
ctx->is_hash = 1;
248
ctx->direction = DIR_INBOUND;
249
250
return 0;
251
}
252
253
int crypto4xx_hash_update(struct ahash_request *req)
254
{
255
struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
256
257
ctx->is_hash = 1;
258
ctx->hash_final = 0;
259
ctx->pd_ctl = 0x11;
260
ctx->direction = DIR_INBOUND;
261
262
return crypto4xx_build_pd(&req->base, ctx, req->src,
263
(struct scatterlist *) req->result,
264
req->nbytes, NULL, 0);
265
}
266
267
int crypto4xx_hash_final(struct ahash_request *req)
268
{
269
return 0;
270
}
271
272
int crypto4xx_hash_digest(struct ahash_request *req)
273
{
274
struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
275
276
ctx->hash_final = 1;
277
ctx->pd_ctl = 0x11;
278
ctx->direction = DIR_INBOUND;
279
280
return crypto4xx_build_pd(&req->base, ctx, req->src,
281
(struct scatterlist *) req->result,
282
req->nbytes, NULL, 0);
283
}
284
285
/**
286
* SHA1 Algorithm
287
*/
288
int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm)
289
{
290
return crypto4xx_hash_alg_init(tfm, SA_HASH160_LEN, SA_HASH_ALG_SHA1,
291
SA_HASH_MODE_HASH);
292
}
293
294
295
296