2 * AMCC SoC PPC4xx Crypto Driver
4 * Copyright (c) 2008 Applied Micro Circuits Corporation.
5 * All rights reserved. James Hsiao <jhsiao@amcc.com>
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.
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.
17 * This file implements the Linux crypto algorithms.
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"
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
,
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
;
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
)
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
;
72 int crypto4xx_encrypt(struct ablkcipher_request
*req
)
74 struct crypto4xx_ctx
*ctx
= crypto_tfm_ctx(req
->base
.tfm
);
76 ctx
->direction
= DIR_OUTBOUND
;
81 return crypto4xx_build_pd(&req
->base
, ctx
, req
->src
, req
->dst
,
82 req
->nbytes
, req
->info
,
83 get_dynamic_sa_iv_size(ctx
));
86 int crypto4xx_decrypt(struct ablkcipher_request
*req
)
88 struct crypto4xx_ctx
*ctx
= crypto_tfm_ctx(req
->base
.tfm
);
90 ctx
->direction
= DIR_INBOUND
;
95 return crypto4xx_build_pd(&req
->base
, ctx
, req
->src
, req
->dst
,
96 req
->nbytes
, req
->info
,
97 get_dynamic_sa_iv_size(ctx
));
103 static int crypto4xx_setkey_aes(struct crypto_ablkcipher
*cipher
,
109 struct crypto_tfm
*tfm
= crypto_ablkcipher_tfm(cipher
);
110 struct crypto4xx_ctx
*ctx
= crypto_tfm_ctx(tfm
);
111 struct dynamic_sa_ctl
*sa
;
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
);
122 if (ctx
->sa_in_dma_addr
|| ctx
->sa_out_dma_addr
)
123 crypto4xx_free_sa(ctx
);
125 rc
= crypto4xx_alloc_sa(ctx
, SA_AES128_LEN
+ (keylen
-16) / 4);
129 if (ctx
->state_record_dma_addr
== 0) {
130 rc
= crypto4xx_alloc_state_record(ctx
);
132 crypto4xx_free_sa(ctx
);
137 sa
= (struct dynamic_sa_ctl
*) ctx
->sa_in
;
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
,
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
,
152 crypto4xx_memcpy_le(ctx
->sa_in
+ get_dynamic_sa_offset_key_field(ctx
),
154 sa
->sa_contents
= SA_AES_CONTENTS
| (keylen
<< 2);
155 sa
->sa_command_1
.bf
.key_len
= keylen
>> 3;
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
);
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
;
169 int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher
*cipher
,
170 const u8
*key
, unsigned int keylen
)
172 return crypto4xx_setkey_aes(cipher
, key
, keylen
, CRYPTO_MODE_CBC
,
173 CRYPTO_FEEDBACK_MODE_NO_FB
);
177 * HASH SHA1 Functions
179 static int crypto4xx_hash_alg_init(struct crypto_tfm
*tfm
,
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
;
191 ctx
->dev
= my_alg
->dev
;
196 if (ctx
->sa_in_dma_addr
|| ctx
->sa_out_dma_addr
)
197 crypto4xx_free_sa(ctx
);
199 rc
= crypto4xx_alloc_sa(ctx
, sa_len
);
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
);
211 tfm
->crt_ahash
.reqsize
= sizeof(struct crypto4xx_ctx
);
212 sa
= (struct dynamic_sa_ctl
*) ctx
->sa_in
;
213 set_dynamic_sa_command_0(sa
, SA_SAVE_HASH
, SA_NOT_SAVE_IV
,
214 SA_NOT_LOAD_HASH
, SA_LOAD_IV_FROM_SA
,
215 SA_NO_HEADER_PROC
, ha
, SA_CIPHER_ALG_NULL
,
216 SA_PAD_TYPE_ZERO
, SA_OP_GROUP_BASIC
,
217 SA_OPCODE_HASH
, DIR_INBOUND
);
218 set_dynamic_sa_command_1(sa
, 0, SA_HASH_MODE_HASH
,
219 CRYPTO_FEEDBACK_MODE_NO_FB
, SA_EXTENDED_SN_OFF
,
220 SA_SEQ_MASK_OFF
, SA_MC_ENABLE
,
221 SA_NOT_COPY_PAD
, SA_NOT_COPY_PAYLOAD
,
223 ctx
->direction
= DIR_INBOUND
;
224 sa
->sa_contents
= SA_HASH160_CONTENTS
;
225 sa_in
= (struct dynamic_sa_hash160
*) ctx
->sa_in
;
226 /* Need to zero hash digest in SA */
227 memset(sa_in
->inner_digest
, 0, sizeof(sa_in
->inner_digest
));
228 memset(sa_in
->outer_digest
, 0, sizeof(sa_in
->outer_digest
));
229 sa_in
->state_ptr
= ctx
->state_record_dma_addr
;
230 ctx
->offset_to_sr_ptr
= get_dynamic_sa_offset_state_ptr_field(ctx
);
235 int crypto4xx_hash_init(struct ahash_request
*req
)
237 struct crypto4xx_ctx
*ctx
= crypto_tfm_ctx(req
->base
.tfm
);
239 struct dynamic_sa_ctl
*sa
;
241 sa
= (struct dynamic_sa_ctl
*) ctx
->sa_in
;
242 ds
= crypto_ahash_digestsize(
243 __crypto_ahash_cast(req
->base
.tfm
));
244 sa
->sa_command_0
.bf
.digest_len
= ds
>> 2;
245 sa
->sa_command_0
.bf
.load_hash_state
= SA_LOAD_HASH_FROM_SA
;
247 ctx
->direction
= DIR_INBOUND
;
252 int crypto4xx_hash_update(struct ahash_request
*req
)
254 struct crypto4xx_ctx
*ctx
= crypto_tfm_ctx(req
->base
.tfm
);
259 ctx
->direction
= DIR_INBOUND
;
261 return crypto4xx_build_pd(&req
->base
, ctx
, req
->src
,
262 (struct scatterlist
*) req
->result
,
263 req
->nbytes
, NULL
, 0);
266 int crypto4xx_hash_final(struct ahash_request
*req
)
271 int crypto4xx_hash_digest(struct ahash_request
*req
)
273 struct crypto4xx_ctx
*ctx
= crypto_tfm_ctx(req
->base
.tfm
);
277 ctx
->direction
= DIR_INBOUND
;
279 return crypto4xx_build_pd(&req
->base
, ctx
, req
->src
,
280 (struct scatterlist
*) req
->result
,
281 req
->nbytes
, NULL
, 0);
287 int crypto4xx_sha1_alg_init(struct crypto_tfm
*tfm
)
289 return crypto4xx_hash_alg_init(tfm
, SA_HASH160_LEN
, SA_HASH_ALG_SHA1
,