8484
8585#define ATMEL_AES_DMA_THRESHOLD 256
8686
87-
87+ /**
88+ * struct atmel_aes_caps: at91 aes capabilities
89+ * @has_dualbuff: dual buffer support
90+ * @has_cfb64: cfb64 support
91+ * @has_gcm: gcm support
92+ * @has_xts: xts suppport
93+ * @has_authenc: authentication support
94+ * @max_burst_size: max DMA bust size
95+ * @has_6words_limitation: some versions of IP have a 6 word headder limitation
96+ */
8897struct atmel_aes_caps {
8998 bool has_dualbuff ;
9099 bool has_cfb64 ;
91100 bool has_gcm ;
92101 bool has_xts ;
93102 bool has_authenc ;
94103 u32 max_burst_size ;
104+ bool has_6words_limitation ;
95105};
96106
97107struct atmel_aes_dev ;
@@ -150,6 +160,8 @@ struct atmel_aes_xts_ctx {
150160struct atmel_aes_authenc_ctx {
151161 struct atmel_aes_base_ctx base ;
152162 struct atmel_sha_authenc_ctx * auth ;
163+
164+ struct crypto_aead * fallback ;
153165};
154166#endif
155167
@@ -2120,6 +2132,12 @@ static int atmel_aes_authenc_setkey(struct crypto_aead *tfm, const u8 *key,
21202132 memcpy (ctx -> base .key , keys .enckey , keys .enckeylen );
21212133
21222134 memzero_explicit (& keys , sizeof (keys ));
2135+
2136+ if (ctx -> base .dd -> caps .has_6words_limitation ) {
2137+ crypto_aead_clear_flags (ctx -> fallback , CRYPTO_TFM_REQ_MASK );
2138+ crypto_aead_set_flags (ctx -> fallback , crypto_aead_get_flags (tfm ) & CRYPTO_TFM_REQ_MASK );
2139+ crypto_aead_setkey (ctx -> fallback , key , keylen );
2140+ }
21232141 return 0 ;
21242142
21252143badkey :
@@ -2132,15 +2150,27 @@ static int atmel_aes_authenc_init_tfm(struct crypto_aead *tfm,
21322150{
21332151 struct atmel_aes_authenc_ctx * ctx = crypto_aead_ctx (tfm );
21342152 unsigned int auth_reqsize = atmel_sha_authenc_get_reqsize ();
2153+ struct aead_alg * alg = crypto_aead_alg (tfm );
21352154 struct atmel_aes_dev * dd ;
21362155
21372156 dd = atmel_aes_dev_alloc (& ctx -> base );
21382157 if (!dd )
21392158 return - ENODEV ;
21402159
2160+ if (dd -> caps .has_6words_limitation ) {
2161+ ctx -> fallback = crypto_alloc_aead (alg -> base .cra_name , 0 ,
2162+ CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ASYNC );
2163+ if (IS_ERR (ctx -> fallback )) {
2164+ dev_err (dd -> dev , "fallback driver fail %s\n" , alg -> base .cra_name );
2165+ return PTR_ERR (ctx -> fallback );
2166+ }
2167+ }
21412168 ctx -> auth = atmel_sha_authenc_spawn (auth_mode );
2142- if (IS_ERR (ctx -> auth ))
2169+ if (IS_ERR (ctx -> auth )) {
2170+ if (dd -> caps .has_6words_limitation )
2171+ crypto_free_aead (ctx -> fallback );
21432172 return PTR_ERR (ctx -> auth );
2173+ }
21442174
21452175 crypto_aead_set_reqsize (tfm , (sizeof (struct atmel_aes_authenc_reqctx ) +
21462176 auth_reqsize ));
@@ -2180,6 +2210,8 @@ static void atmel_aes_authenc_exit_tfm(struct crypto_aead *tfm)
21802210 struct atmel_aes_authenc_ctx * ctx = crypto_aead_ctx (tfm );
21812211
21822212 atmel_sha_authenc_free (ctx -> auth );
2213+ if (ctx -> base .dd -> caps .has_6words_limitation )
2214+ crypto_free_aead (ctx -> fallback );
21832215}
21842216
21852217static int atmel_aes_authenc_crypt (struct aead_request * req ,
@@ -2188,8 +2220,10 @@ static int atmel_aes_authenc_crypt(struct aead_request *req,
21882220 struct atmel_aes_authenc_reqctx * rctx = aead_request_ctx (req );
21892221 struct crypto_aead * tfm = crypto_aead_reqtfm (req );
21902222 struct atmel_aes_base_ctx * ctx = crypto_aead_ctx (tfm );
2223+ struct atmel_aes_authenc_ctx * actx = crypto_aead_ctx (tfm );
21912224 u32 authsize = crypto_aead_authsize (tfm );
21922225 bool enc = (mode & AES_FLAGS_ENCRYPT );
2226+ bool limitation = ctx -> dd -> caps .has_6words_limitation ;
21932227
21942228 /* Compute text length. */
21952229 if (!enc && req -> cryptlen < authsize )
@@ -2203,6 +2237,26 @@ static int atmel_aes_authenc_crypt(struct aead_request *req,
22032237 */
22042238 if (!rctx -> textlen && !req -> assoclen )
22052239 return - EINVAL ;
2240+ /*
2241+ *Check if data size triggers the HW limitation and
2242+ * run fallback functions
2243+ */
2244+ if ((req -> assoclen != 16 ) && limitation ) {
2245+ struct aead_request * subreq = aead_request_ctx (req );
2246+ int ret ;
2247+
2248+ aead_request_set_tfm (subreq , actx -> fallback );
2249+ aead_request_set_callback (subreq , req -> base .flags ,
2250+ req -> base .complete , req -> base .data );
2251+ aead_request_set_crypt (subreq , req -> src , req -> dst ,
2252+ req -> cryptlen , req -> iv );
2253+ aead_request_set_ad (subreq , req -> assoclen );
2254+
2255+ if (enc )
2256+ return crypto_aead_encrypt (subreq );
2257+ else
2258+ return crypto_aead_decrypt (subreq );
2259+ }
22062260
22072261 rctx -> base .mode = mode ;
22082262 ctx -> block_size = AES_BLOCK_SIZE ;
@@ -2500,10 +2554,13 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
25002554 dd -> caps .has_xts = 0 ;
25012555 dd -> caps .has_authenc = 0 ;
25022556 dd -> caps .max_burst_size = 1 ;
2557+ dd -> caps .has_6words_limitation = 0 ;
25032558
25042559 /* keep only major version number */
25052560 switch (dd -> hw_version & 0xff0 ) {
25062561 case 0x700 :
2562+ case 0x600 :
2563+ dd -> caps .has_6words_limitation = 1 ;
25072564 case 0x500 :
25082565 dd -> caps .has_dualbuff = 1 ;
25092566 dd -> caps .has_cfb64 = 1 ;
0 commit comments