[brcm63xx] rework imagetag firmware generator and MTD partition parser to accomodate...
[openwrt.git] / target / linux / generic-2.6 / files / crypto / ocf / ep80579 / icp_sym.c
1 /***************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
22 * The full GNU General Public License is included in this distribution
23 * in the file called LICENSE.GPL.
24 *
25 * Contact Information:
26 * Intel Corporation
27 *
28 * BSD LICENSE
29 *
30 * Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
31 * All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 *
37 * * Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * * Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in
41 * the documentation and/or other materials provided with the
42 * distribution.
43 * * Neither the name of Intel Corporation nor the names of its
44 * contributors may be used to endorse or promote products derived
45 * from this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
50 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
51 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 *
59 *
60 * version: Security.L.1.0.130
61 *
62 ***************************************************************************/
63 /*
64 * An OCF module that uses the API for IntelĀ® QuickAssist Technology to do the
65 * cryptography.
66 *
67 * This driver requires the ICP Access Library that is available from Intel in
68 * order to operate.
69 */
70
71 #include "icp_ocf.h"
72
73 /*This is the call back function for all symmetric cryptographic processes.
74 Its main functionality is to free driver crypto operation structure and to
75 call back to OCF*/
76 static void
77 icp_ocfDrvSymCallBack(void *callbackTag,
78 CpaStatus status,
79 const CpaCySymOp operationType,
80 void *pOpData,
81 CpaBufferList * pDstBuffer, CpaBoolean verifyResult);
82
83 /*This function is used to extract crypto processing information from the OCF
84 inputs, so as that it may be passed onto LAC*/
85 static int
86 icp_ocfDrvProcessDataSetup(struct icp_drvOpData *drvOpData,
87 struct cryptodesc *crp_desc);
88
89 /*This function checks whether the crp_desc argument pertains to a digest or a
90 cipher operation*/
91 static int icp_ocfDrvAlgCheck(struct cryptodesc *crp_desc);
92
93 /*This function copies all the passed in session context information and stores
94 it in a LAC context structure*/
95 static int
96 icp_ocfDrvAlgorithmSetup(struct cryptoini *cri,
97 CpaCySymSessionSetupData * lacSessCtx);
98
99 /*This top level function is used to find a pointer to where a digest is
100 stored/needs to be inserted. */
101 static uint8_t *icp_ocfDrvDigestPointerFind(struct icp_drvOpData *drvOpData,
102 struct cryptodesc *crp_desc);
103
104 /*This function is called when a digest pointer has to be found within a
105 SKBUFF.*/
106 static inline uint8_t *icp_ocfDrvSkbuffDigestPointerFind(struct icp_drvOpData
107 *drvOpData,
108 int offsetInBytes,
109 uint32_t
110 digestSizeInBytes);
111
112 /*The following two functions are called if the SKBUFF digest pointer is not
113 positioned in the linear portion of the buffer (i.e. it is in a linked SKBUFF
114 or page fragment).*/
115 /*This function takes care of the page fragment case.*/
116 static inline uint8_t *icp_ocfDrvDigestSkbNRFragsCheck(struct sk_buff *skb,
117 struct skb_shared_info
118 *skb_shared,
119 int offsetInBytes,
120 uint32_t
121 digestSizeInBytes);
122
123 /*This function takes care of the linked list case.*/
124 static inline uint8_t *icp_ocfDrvDigestSkbFragListCheck(struct sk_buff *skb,
125 struct skb_shared_info
126 *skb_shared,
127 int offsetInBytes,
128 uint32_t
129 digestSizeInBytes);
130
131 /*This function is used to free an OCF->OCF_DRV session object*/
132 static void icp_ocfDrvFreeOCFSession(struct icp_drvSessionData *sessionData);
133
134 /*max IOV buffs supported in a UIO structure*/
135 #define NUM_IOV_SUPPORTED (1)
136
137 /* Name : icp_ocfDrvSymCallBack
138 *
139 * Description : When this function returns it signifies that the LAC
140 * component has completed the relevant symmetric operation.
141 *
142 * Notes : The callbackTag is a pointer to an icp_drvOpData. This memory
143 * object was passed to LAC for the cryptographic processing and contains all
144 * the relevant information for cleaning up buffer handles etc. so that the
145 * OCF Tolapai Driver portion of this crypto operation can be fully completed.
146 */
147 static void
148 icp_ocfDrvSymCallBack(void *callbackTag,
149 CpaStatus status,
150 const CpaCySymOp operationType,
151 void *pOpData,
152 CpaBufferList * pDstBuffer, CpaBoolean verifyResult)
153 {
154 struct cryptop *crp = NULL;
155 struct icp_drvOpData *temp_drvOpData =
156 (struct icp_drvOpData *)callbackTag;
157 uint64_t *tempBasePtr = NULL;
158 uint32_t tempLen = 0;
159
160 if (NULL == temp_drvOpData) {
161 DPRINTK("%s(): The callback from the LAC component"
162 " has failed due to Null userOpaque data"
163 "(status == %d).\n", __FUNCTION__, status);
164 DPRINTK("%s(): Unable to call OCF back! \n", __FUNCTION__);
165 return;
166 }
167
168 crp = temp_drvOpData->crp;
169 crp->crp_etype = ICP_OCF_DRV_NO_CRYPTO_PROCESS_ERROR;
170
171 if (NULL == pOpData) {
172 DPRINTK("%s(): The callback from the LAC component"
173 " has failed due to Null Symmetric Op data"
174 "(status == %d).\n", __FUNCTION__, status);
175 crp->crp_etype = ECANCELED;
176 crypto_done(crp);
177 return;
178 }
179
180 if (NULL == pDstBuffer) {
181 DPRINTK("%s(): The callback from the LAC component"
182 " has failed due to Null Dst Bufferlist data"
183 "(status == %d).\n", __FUNCTION__, status);
184 crp->crp_etype = ECANCELED;
185 crypto_done(crp);
186 return;
187 }
188
189 if (CPA_STATUS_SUCCESS == status) {
190
191 if (temp_drvOpData->bufferType == CRYPTO_F_SKBUF) {
192 if (ICP_OCF_DRV_STATUS_SUCCESS !=
193 icp_ocfDrvBufferListToSkBuff(pDstBuffer,
194 (struct sk_buff **)
195 &(crp->crp_buf))) {
196 EPRINTK("%s(): BufferList to SkBuff "
197 "conversion error.\n", __FUNCTION__);
198 crp->crp_etype = EPERM;
199 }
200 } else {
201 icp_ocfDrvBufferListToPtrAndLen(pDstBuffer,
202 (void **)&tempBasePtr,
203 &tempLen);
204 crp->crp_olen = (int)tempLen;
205 }
206
207 } else {
208 DPRINTK("%s(): The callback from the LAC component has failed"
209 "(status == %d).\n", __FUNCTION__, status);
210
211 crp->crp_etype = ECANCELED;
212 }
213
214 if (temp_drvOpData->numBufferListArray >
215 ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) {
216 kfree(pDstBuffer->pBuffers);
217 }
218 icp_ocfDrvFreeMetaData(pDstBuffer);
219 kmem_cache_free(drvOpData_zone, temp_drvOpData);
220
221 /* Invoke the OCF callback function */
222 crypto_done(crp);
223
224 return;
225 }
226
227 /* Name : icp_ocfDrvNewSession
228 *
229 * Description : This function will create a new Driver<->OCF session
230 *
231 * Notes : LAC session registration happens during the first perform call.
232 * That is the first time we know all information about a given session.
233 */
234 int icp_ocfDrvNewSession(device_t dev, uint32_t * sid, struct cryptoini *cri)
235 {
236 struct icp_drvSessionData *sessionData = NULL;
237 uint32_t delete_session = 0;
238
239 /* The SID passed in should be our driver ID. We can return the */
240 /* local ID (LID) which is a unique identifier which we can use */
241 /* to differentiate between the encrypt/decrypt LAC session handles */
242 if (NULL == sid) {
243 EPRINTK("%s(): Invalid input parameters - NULL sid.\n",
244 __FUNCTION__);
245 return EINVAL;
246 }
247
248 if (NULL == cri) {
249 EPRINTK("%s(): Invalid input parameters - NULL cryptoini.\n",
250 __FUNCTION__);
251 return EINVAL;
252 }
253
254 if (icp_ocfDrvDriverId != *sid) {
255 EPRINTK("%s(): Invalid input parameters - bad driver ID\n",
256 __FUNCTION__);
257 EPRINTK("\t sid = 0x08%p \n \t cri = 0x08%p \n", sid, cri);
258 return EINVAL;
259 }
260
261 sessionData = kmem_cache_zalloc(drvSessionData_zone, GFP_ATOMIC);
262 if (NULL == sessionData) {
263 DPRINTK("%s():No memory for Session Data\n", __FUNCTION__);
264 return ENOMEM;
265 }
266
267 /*ENTER CRITICAL SECTION */
268 spin_lock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
269 /*put this check in the spinlock so no new sessions can be added to the
270 linked list when we are exiting */
271 if (CPA_TRUE == atomic_read(&icp_ocfDrvIsExiting)) {
272 delete_session++;
273
274 } else if (NO_OCF_TO_DRV_MAX_SESSIONS != max_sessions) {
275 if (atomic_read(&num_ocf_to_drv_registered_sessions) >=
276 (max_sessions -
277 atomic_read(&lac_session_failed_dereg_count))) {
278 delete_session++;
279 } else {
280 atomic_inc(&num_ocf_to_drv_registered_sessions);
281 /* Add to session data linked list */
282 list_add(&(sessionData->listNode),
283 &icp_ocfDrvGlobalSymListHead);
284 }
285
286 } else if (NO_OCF_TO_DRV_MAX_SESSIONS == max_sessions) {
287 list_add(&(sessionData->listNode),
288 &icp_ocfDrvGlobalSymListHead);
289 }
290
291 sessionData->inUse = ICP_SESSION_INITIALISED;
292
293 /*EXIT CRITICAL SECTION */
294 spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
295
296 if (delete_session) {
297 DPRINTK("%s():No Session handles available\n", __FUNCTION__);
298 kmem_cache_free(drvSessionData_zone, sessionData);
299 return EPERM;
300 }
301
302 if (ICP_OCF_DRV_STATUS_SUCCESS !=
303 icp_ocfDrvAlgorithmSetup(cri, &(sessionData->lacSessCtx))) {
304 DPRINTK("%s():algorithm not supported\n", __FUNCTION__);
305 icp_ocfDrvFreeOCFSession(sessionData);
306 return EINVAL;
307 }
308
309 if (cri->cri_next) {
310 if (cri->cri_next->cri_next != NULL) {
311 DPRINTK("%s():only two chained algorithms supported\n",
312 __FUNCTION__);
313 icp_ocfDrvFreeOCFSession(sessionData);
314 return EPERM;
315 }
316
317 if (ICP_OCF_DRV_STATUS_SUCCESS !=
318 icp_ocfDrvAlgorithmSetup(cri->cri_next,
319 &(sessionData->lacSessCtx))) {
320 DPRINTK("%s():second algorithm not supported\n",
321 __FUNCTION__);
322 icp_ocfDrvFreeOCFSession(sessionData);
323 return EINVAL;
324 }
325
326 sessionData->lacSessCtx.symOperation =
327 CPA_CY_SYM_OP_ALGORITHM_CHAINING;
328 }
329
330 *sid = (uint32_t) sessionData;
331
332 return ICP_OCF_DRV_STATUS_SUCCESS;
333 }
334
335 /* Name : icp_ocfDrvAlgorithmSetup
336 *
337 * Description : This function builds the session context data from the
338 * information supplied through OCF. Algorithm chain order and whether the
339 * session is Encrypt/Decrypt can only be found out at perform time however, so
340 * the session is registered with LAC at that time.
341 */
342 static int
343 icp_ocfDrvAlgorithmSetup(struct cryptoini *cri,
344 CpaCySymSessionSetupData * lacSessCtx)
345 {
346
347 lacSessCtx->sessionPriority = CPA_CY_PRIORITY_NORMAL;
348
349 switch (cri->cri_alg) {
350
351 case CRYPTO_NULL_CBC:
352 DPRINTK("%s(): NULL CBC\n", __FUNCTION__);
353 lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
354 lacSessCtx->cipherSetupData.cipherAlgorithm =
355 CPA_CY_SYM_CIPHER_NULL;
356 lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
357 cri->cri_klen / NUM_BITS_IN_BYTE;
358 lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
359 break;
360
361 case CRYPTO_DES_CBC:
362 DPRINTK("%s(): DES CBC\n", __FUNCTION__);
363 lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
364 lacSessCtx->cipherSetupData.cipherAlgorithm =
365 CPA_CY_SYM_CIPHER_DES_CBC;
366 lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
367 cri->cri_klen / NUM_BITS_IN_BYTE;
368 lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
369 break;
370
371 case CRYPTO_3DES_CBC:
372 DPRINTK("%s(): 3DES CBC\n", __FUNCTION__);
373 lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
374 lacSessCtx->cipherSetupData.cipherAlgorithm =
375 CPA_CY_SYM_CIPHER_3DES_CBC;
376 lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
377 cri->cri_klen / NUM_BITS_IN_BYTE;
378 lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
379 break;
380
381 case CRYPTO_AES_CBC:
382 DPRINTK("%s(): AES CBC\n", __FUNCTION__);
383 lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
384 lacSessCtx->cipherSetupData.cipherAlgorithm =
385 CPA_CY_SYM_CIPHER_AES_CBC;
386 lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
387 cri->cri_klen / NUM_BITS_IN_BYTE;
388 lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
389 break;
390
391 case CRYPTO_ARC4:
392 DPRINTK("%s(): ARC4\n", __FUNCTION__);
393 lacSessCtx->symOperation = CPA_CY_SYM_OP_CIPHER;
394 lacSessCtx->cipherSetupData.cipherAlgorithm =
395 CPA_CY_SYM_CIPHER_ARC4;
396 lacSessCtx->cipherSetupData.cipherKeyLenInBytes =
397 cri->cri_klen / NUM_BITS_IN_BYTE;
398 lacSessCtx->cipherSetupData.pCipherKey = cri->cri_key;
399 break;
400
401 case CRYPTO_SHA1:
402 DPRINTK("%s(): SHA1\n", __FUNCTION__);
403 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
404 lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1;
405 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
406 lacSessCtx->hashSetupData.digestResultLenInBytes =
407 (cri->cri_mlen ?
408 cri->cri_mlen : ICP_SHA1_DIGEST_SIZE_IN_BYTES);
409
410 break;
411
412 case CRYPTO_SHA1_HMAC:
413 DPRINTK("%s(): SHA1_HMAC\n", __FUNCTION__);
414 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
415 lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1;
416 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
417 lacSessCtx->hashSetupData.digestResultLenInBytes =
418 (cri->cri_mlen ?
419 cri->cri_mlen : ICP_SHA1_DIGEST_SIZE_IN_BYTES);
420 lacSessCtx->hashSetupData.authModeSetupData.authKey =
421 cri->cri_key;
422 lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
423 cri->cri_klen / NUM_BITS_IN_BYTE;
424 lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
425
426 break;
427
428 case CRYPTO_SHA2_256:
429 DPRINTK("%s(): SHA256\n", __FUNCTION__);
430 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
431 lacSessCtx->hashSetupData.hashAlgorithm =
432 CPA_CY_SYM_HASH_SHA256;
433 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
434 lacSessCtx->hashSetupData.digestResultLenInBytes =
435 (cri->cri_mlen ?
436 cri->cri_mlen : ICP_SHA256_DIGEST_SIZE_IN_BYTES);
437
438 break;
439
440 case CRYPTO_SHA2_256_HMAC:
441 DPRINTK("%s(): SHA256_HMAC\n", __FUNCTION__);
442 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
443 lacSessCtx->hashSetupData.hashAlgorithm =
444 CPA_CY_SYM_HASH_SHA256;
445 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
446 lacSessCtx->hashSetupData.digestResultLenInBytes =
447 (cri->cri_mlen ?
448 cri->cri_mlen : ICP_SHA256_DIGEST_SIZE_IN_BYTES);
449 lacSessCtx->hashSetupData.authModeSetupData.authKey =
450 cri->cri_key;
451 lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
452 cri->cri_klen / NUM_BITS_IN_BYTE;
453 lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
454
455 break;
456
457 case CRYPTO_SHA2_384:
458 DPRINTK("%s(): SHA384\n", __FUNCTION__);
459 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
460 lacSessCtx->hashSetupData.hashAlgorithm =
461 CPA_CY_SYM_HASH_SHA384;
462 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
463 lacSessCtx->hashSetupData.digestResultLenInBytes =
464 (cri->cri_mlen ?
465 cri->cri_mlen : ICP_SHA384_DIGEST_SIZE_IN_BYTES);
466
467 break;
468
469 case CRYPTO_SHA2_384_HMAC:
470 DPRINTK("%s(): SHA384_HMAC\n", __FUNCTION__);
471 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
472 lacSessCtx->hashSetupData.hashAlgorithm =
473 CPA_CY_SYM_HASH_SHA384;
474 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
475 lacSessCtx->hashSetupData.digestResultLenInBytes =
476 (cri->cri_mlen ?
477 cri->cri_mlen : ICP_SHA384_DIGEST_SIZE_IN_BYTES);
478 lacSessCtx->hashSetupData.authModeSetupData.authKey =
479 cri->cri_key;
480 lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
481 cri->cri_klen / NUM_BITS_IN_BYTE;
482 lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
483
484 break;
485
486 case CRYPTO_SHA2_512:
487 DPRINTK("%s(): SHA512\n", __FUNCTION__);
488 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
489 lacSessCtx->hashSetupData.hashAlgorithm =
490 CPA_CY_SYM_HASH_SHA512;
491 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
492 lacSessCtx->hashSetupData.digestResultLenInBytes =
493 (cri->cri_mlen ?
494 cri->cri_mlen : ICP_SHA512_DIGEST_SIZE_IN_BYTES);
495
496 break;
497
498 case CRYPTO_SHA2_512_HMAC:
499 DPRINTK("%s(): SHA512_HMAC\n", __FUNCTION__);
500 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
501 lacSessCtx->hashSetupData.hashAlgorithm =
502 CPA_CY_SYM_HASH_SHA512;
503 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
504 lacSessCtx->hashSetupData.digestResultLenInBytes =
505 (cri->cri_mlen ?
506 cri->cri_mlen : ICP_SHA512_DIGEST_SIZE_IN_BYTES);
507 lacSessCtx->hashSetupData.authModeSetupData.authKey =
508 cri->cri_key;
509 lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
510 cri->cri_klen / NUM_BITS_IN_BYTE;
511 lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
512
513 break;
514
515 case CRYPTO_MD5:
516 DPRINTK("%s(): MD5\n", __FUNCTION__);
517 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
518 lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_MD5;
519 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN;
520 lacSessCtx->hashSetupData.digestResultLenInBytes =
521 (cri->cri_mlen ?
522 cri->cri_mlen : ICP_MD5_DIGEST_SIZE_IN_BYTES);
523
524 break;
525
526 case CRYPTO_MD5_HMAC:
527 DPRINTK("%s(): MD5_HMAC\n", __FUNCTION__);
528 lacSessCtx->symOperation = CPA_CY_SYM_OP_HASH;
529 lacSessCtx->hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_MD5;
530 lacSessCtx->hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;
531 lacSessCtx->hashSetupData.digestResultLenInBytes =
532 (cri->cri_mlen ?
533 cri->cri_mlen : ICP_MD5_DIGEST_SIZE_IN_BYTES);
534 lacSessCtx->hashSetupData.authModeSetupData.authKey =
535 cri->cri_key;
536 lacSessCtx->hashSetupData.authModeSetupData.authKeyLenInBytes =
537 cri->cri_klen / NUM_BITS_IN_BYTE;
538 lacSessCtx->hashSetupData.authModeSetupData.aadLenInBytes = 0;
539
540 break;
541
542 default:
543 DPRINTK("%s(): ALG Setup FAIL\n", __FUNCTION__);
544 return ICP_OCF_DRV_STATUS_FAIL;
545 }
546
547 return ICP_OCF_DRV_STATUS_SUCCESS;
548 }
549
550 /* Name : icp_ocfDrvFreeOCFSession
551 *
552 * Description : This function deletes all existing Session data representing
553 * the Cryptographic session established between OCF and this driver. This
554 * also includes freeing the memory allocated for the session context. The
555 * session object is also removed from the session linked list.
556 */
557 static void icp_ocfDrvFreeOCFSession(struct icp_drvSessionData *sessionData)
558 {
559
560 sessionData->inUse = ICP_SESSION_DEREGISTERED;
561
562 /*ENTER CRITICAL SECTION */
563 spin_lock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
564
565 if (CPA_TRUE == atomic_read(&icp_ocfDrvIsExiting)) {
566 /*If the Driver is exiting, allow that process to
567 handle any deletions */
568 /*EXIT CRITICAL SECTION */
569 spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
570 return;
571 }
572
573 atomic_dec(&num_ocf_to_drv_registered_sessions);
574
575 list_del(&(sessionData->listNode));
576
577 /*EXIT CRITICAL SECTION */
578 spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
579
580 if (NULL != sessionData->sessHandle) {
581 kfree(sessionData->sessHandle);
582 }
583 kmem_cache_free(drvSessionData_zone, sessionData);
584 }
585
586 /* Name : icp_ocfDrvFreeLACSession
587 *
588 * Description : This attempts to deregister a LAC session. If it fails, the
589 * deregistation retry function is called.
590 */
591 int icp_ocfDrvFreeLACSession(device_t dev, uint64_t sid)
592 {
593 CpaCySymSessionCtx sessionToDeregister = NULL;
594 struct icp_drvSessionData *sessionData = NULL;
595 CpaStatus lacStatus = CPA_STATUS_SUCCESS;
596 int retval = 0;
597
598 sessionData = (struct icp_drvSessionData *)CRYPTO_SESID2LID(sid);
599 if (NULL == sessionData) {
600 EPRINTK("%s(): OCF Free session called with Null Session ID.\n",
601 __FUNCTION__);
602 return EINVAL;
603 }
604
605 sessionToDeregister = sessionData->sessHandle;
606
607 if (ICP_SESSION_INITIALISED == sessionData->inUse) {
608 DPRINTK("%s() Session not registered with LAC\n", __FUNCTION__);
609 } else if (NULL == sessionData->sessHandle) {
610 EPRINTK
611 ("%s(): OCF Free session called with Null Session Handle.\n",
612 __FUNCTION__);
613 return EINVAL;
614 } else {
615 lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
616 sessionToDeregister);
617 if (CPA_STATUS_RETRY == lacStatus) {
618 if (ICP_OCF_DRV_STATUS_SUCCESS !=
619 icp_ocfDrvDeregRetry(&sessionToDeregister)) {
620 /* the retry function increments the
621 dereg failed count */
622 DPRINTK("%s(): LAC failed to deregister the "
623 "session. (localSessionId= %p)\n",
624 __FUNCTION__, sessionToDeregister);
625 retval = EPERM;
626 }
627
628 } else if (CPA_STATUS_SUCCESS != lacStatus) {
629 DPRINTK("%s(): LAC failed to deregister the session. "
630 "localSessionId= %p, lacStatus = %d\n",
631 __FUNCTION__, sessionToDeregister, lacStatus);
632 atomic_inc(&lac_session_failed_dereg_count);
633 retval = EPERM;
634 }
635 }
636
637 icp_ocfDrvFreeOCFSession(sessionData);
638 return retval;
639
640 }
641
642 /* Name : icp_ocfDrvAlgCheck
643 *
644 * Description : This function checks whether the cryptodesc argument pertains
645 * to a sym or hash function
646 */
647 static int icp_ocfDrvAlgCheck(struct cryptodesc *crp_desc)
648 {
649
650 if (crp_desc->crd_alg == CRYPTO_3DES_CBC ||
651 crp_desc->crd_alg == CRYPTO_AES_CBC ||
652 crp_desc->crd_alg == CRYPTO_DES_CBC ||
653 crp_desc->crd_alg == CRYPTO_NULL_CBC ||
654 crp_desc->crd_alg == CRYPTO_ARC4) {
655 return ICP_OCF_DRV_ALG_CIPHER;
656 }
657
658 return ICP_OCF_DRV_ALG_HASH;
659 }
660
661 /* Name : icp_ocfDrvSymProcess
662 *
663 * Description : This function will map symmetric functionality calls from OCF
664 * to the LAC API. It will also allocate memory to store the session context.
665 *
666 * Notes: If it is the first perform call for a given session, then a LAC
667 * session is registered. After the session is registered, no checks as
668 * to whether session paramaters have changed (e.g. alg chain order) are
669 * done.
670 */
671 int icp_ocfDrvSymProcess(device_t dev, struct cryptop *crp, int hint)
672 {
673 struct icp_drvSessionData *sessionData = NULL;
674 struct icp_drvOpData *drvOpData = NULL;
675 CpaStatus lacStatus = CPA_STATUS_SUCCESS;
676 Cpa32U sessionCtxSizeInBytes = 0;
677 uint16_t numBufferListArray = 0;
678
679 if (NULL == crp) {
680 DPRINTK("%s(): Invalid input parameters, cryptop is NULL\n",
681 __FUNCTION__);
682 return EINVAL;
683 }
684
685 if (NULL == crp->crp_desc) {
686 DPRINTK("%s(): Invalid input parameters, no crp_desc attached "
687 "to crp\n", __FUNCTION__);
688 crp->crp_etype = EINVAL;
689 return EINVAL;
690 }
691
692 if (NULL == crp->crp_buf) {
693 DPRINTK("%s(): Invalid input parameters, no buffer attached "
694 "to crp\n", __FUNCTION__);
695 crp->crp_etype = EINVAL;
696 return EINVAL;
697 }
698
699 if (CPA_TRUE == atomic_read(&icp_ocfDrvIsExiting)) {
700 crp->crp_etype = EFAULT;
701 return EFAULT;
702 }
703
704 sessionData = (struct icp_drvSessionData *)
705 (CRYPTO_SESID2LID(crp->crp_sid));
706 if (NULL == sessionData) {
707 DPRINTK("%s(): Invalid input parameters, Null Session ID \n",
708 __FUNCTION__);
709 crp->crp_etype = EINVAL;
710 return EINVAL;
711 }
712
713 /*If we get a request against a deregisted session, cancel operation*/
714 if (ICP_SESSION_DEREGISTERED == sessionData->inUse) {
715 DPRINTK("%s(): Session ID %d was deregistered \n",
716 __FUNCTION__, (int)(CRYPTO_SESID2LID(crp->crp_sid)));
717 crp->crp_etype = EFAULT;
718 return EFAULT;
719 }
720
721 /*If none of the session states are set, then the session structure was either
722 not initialised properly or we are reading from a freed memory area (possible
723 due to OCF batch mode not removing queued requests against deregistered
724 sessions*/
725 if (ICP_SESSION_INITIALISED != sessionData->inUse &&
726 ICP_SESSION_RUNNING != sessionData->inUse) {
727 DPRINTK("%s(): Session - ID %d - not properly initialised or "
728 "memory freed back to the kernel \n",
729 __FUNCTION__, (int)(CRYPTO_SESID2LID(crp->crp_sid)));
730 crp->crp_etype = EINVAL;
731 return EINVAL;
732 }
733
734 /*For the below checks, remember error checking is already done in LAC.
735 We're not validating inputs subsequent to registration */
736 if (sessionData->inUse == ICP_SESSION_INITIALISED) {
737 DPRINTK("%s(): Initialising session\n", __FUNCTION__);
738
739 if (NULL != crp->crp_desc->crd_next) {
740 if (ICP_OCF_DRV_ALG_CIPHER ==
741 icp_ocfDrvAlgCheck(crp->crp_desc)) {
742
743 sessionData->lacSessCtx.algChainOrder =
744 CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH;
745
746 if (crp->crp_desc->crd_flags & CRD_F_ENCRYPT) {
747 sessionData->lacSessCtx.cipherSetupData.
748 cipherDirection =
749 CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT;
750 } else {
751 sessionData->lacSessCtx.cipherSetupData.
752 cipherDirection =
753 CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT;
754 }
755 } else {
756 sessionData->lacSessCtx.algChainOrder =
757 CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER;
758
759 if (crp->crp_desc->crd_next->crd_flags &
760 CRD_F_ENCRYPT) {
761 sessionData->lacSessCtx.cipherSetupData.
762 cipherDirection =
763 CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT;
764 } else {
765 sessionData->lacSessCtx.cipherSetupData.
766 cipherDirection =
767 CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT;
768 }
769
770 }
771
772 } else if (ICP_OCF_DRV_ALG_CIPHER ==
773 icp_ocfDrvAlgCheck(crp->crp_desc)) {
774 if (crp->crp_desc->crd_flags & CRD_F_ENCRYPT) {
775 sessionData->lacSessCtx.cipherSetupData.
776 cipherDirection =
777 CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT;
778 } else {
779 sessionData->lacSessCtx.cipherSetupData.
780 cipherDirection =
781 CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT;
782 }
783
784 }
785
786 /*No action required for standalone Auth here */
787
788 /* Allocate memory for SymSessionCtx before the Session Registration */
789 lacStatus =
790 cpaCySymSessionCtxGetSize(CPA_INSTANCE_HANDLE_SINGLE,
791 &(sessionData->lacSessCtx),
792 &sessionCtxSizeInBytes);
793 if (CPA_STATUS_SUCCESS != lacStatus) {
794 EPRINTK("%s(): cpaCySymSessionCtxGetSize failed - %d\n",
795 __FUNCTION__, lacStatus);
796 return EINVAL;
797 }
798 sessionData->sessHandle =
799 kmalloc(sessionCtxSizeInBytes, GFP_ATOMIC);
800 if (NULL == sessionData->sessHandle) {
801 EPRINTK
802 ("%s(): Failed to get memory for SymSessionCtx\n",
803 __FUNCTION__);
804 return ENOMEM;
805 }
806
807 lacStatus = cpaCySymInitSession(CPA_INSTANCE_HANDLE_SINGLE,
808 icp_ocfDrvSymCallBack,
809 &(sessionData->lacSessCtx),
810 sessionData->sessHandle);
811
812 if (CPA_STATUS_SUCCESS != lacStatus) {
813 EPRINTK("%s(): cpaCySymInitSession failed -%d \n",
814 __FUNCTION__, lacStatus);
815 return EFAULT;
816 }
817
818 sessionData->inUse = ICP_SESSION_RUNNING;
819 }
820
821 drvOpData = kmem_cache_zalloc(drvOpData_zone, GFP_ATOMIC);
822 if (NULL == drvOpData) {
823 EPRINTK("%s():Failed to get memory for drvOpData\n",
824 __FUNCTION__);
825 crp->crp_etype = ENOMEM;
826 return ENOMEM;
827 }
828
829 drvOpData->lacOpData.pSessionCtx = sessionData->sessHandle;
830 drvOpData->digestSizeInBytes = sessionData->lacSessCtx.hashSetupData.
831 digestResultLenInBytes;
832 drvOpData->crp = crp;
833
834 /* Set the default buffer list array memory allocation */
835 drvOpData->srcBuffer.pBuffers = drvOpData->bufferListArray;
836 drvOpData->numBufferListArray = ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS;
837
838 /*
839 * Allocate buffer list array memory allocation if the
840 * data fragment is more than the default allocation
841 */
842 if (crp->crp_flags & CRYPTO_F_SKBUF) {
843 numBufferListArray = icp_ocfDrvGetSkBuffFrags((struct sk_buff *)
844 crp->crp_buf);
845 if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS < numBufferListArray) {
846 DPRINTK("%s() numBufferListArray more than default\n",
847 __FUNCTION__);
848 drvOpData->srcBuffer.pBuffers = NULL;
849 drvOpData->srcBuffer.pBuffers =
850 kmalloc(numBufferListArray *
851 sizeof(CpaFlatBuffer), GFP_ATOMIC);
852 if (NULL == drvOpData->srcBuffer.pBuffers) {
853 EPRINTK("%s() Failed to get memory for "
854 "pBuffers\n", __FUNCTION__);
855 kmem_cache_free(drvOpData_zone, drvOpData);
856 crp->crp_etype = ENOMEM;
857 return ENOMEM;
858 }
859 drvOpData->numBufferListArray = numBufferListArray;
860 }
861 }
862
863 /*
864 * Check the type of buffer structure we got and convert it into
865 * CpaBufferList format.
866 */
867 if (crp->crp_flags & CRYPTO_F_SKBUF) {
868 if (ICP_OCF_DRV_STATUS_SUCCESS !=
869 icp_ocfDrvSkBuffToBufferList((struct sk_buff *)crp->crp_buf,
870 &(drvOpData->srcBuffer))) {
871 EPRINTK("%s():Failed to translate from SK_BUF "
872 "to bufferlist\n", __FUNCTION__);
873 crp->crp_etype = EINVAL;
874 goto err;
875 }
876
877 drvOpData->bufferType = CRYPTO_F_SKBUF;
878 } else if (crp->crp_flags & CRYPTO_F_IOV) {
879 /* OCF only supports IOV of one entry. */
880 if (NUM_IOV_SUPPORTED ==
881 ((struct uio *)(crp->crp_buf))->uio_iovcnt) {
882
883 icp_ocfDrvPtrAndLenToBufferList(((struct uio *)(crp->
884 crp_buf))->
885 uio_iov[0].iov_base,
886 ((struct uio *)(crp->
887 crp_buf))->
888 uio_iov[0].iov_len,
889 &(drvOpData->
890 srcBuffer));
891
892 drvOpData->bufferType = CRYPTO_F_IOV;
893
894 } else {
895 DPRINTK("%s():Unable to handle IOVs with lengths of "
896 "greater than one!\n", __FUNCTION__);
897 crp->crp_etype = EINVAL;
898 goto err;
899 }
900
901 } else {
902 icp_ocfDrvPtrAndLenToBufferList(crp->crp_buf,
903 crp->crp_ilen,
904 &(drvOpData->srcBuffer));
905
906 drvOpData->bufferType = CRYPTO_BUF_CONTIG;
907 }
908
909 if (ICP_OCF_DRV_STATUS_SUCCESS !=
910 icp_ocfDrvProcessDataSetup(drvOpData, drvOpData->crp->crp_desc)) {
911 crp->crp_etype = EINVAL;
912 goto err;
913 }
914
915 if (drvOpData->crp->crp_desc->crd_next != NULL) {
916 if (icp_ocfDrvProcessDataSetup(drvOpData, drvOpData->crp->
917 crp_desc->crd_next)) {
918 crp->crp_etype = EINVAL;
919 goto err;
920 }
921
922 }
923
924 /* Allocate srcBuffer's private meta data */
925 if (ICP_OCF_DRV_STATUS_SUCCESS !=
926 icp_ocfDrvAllocMetaData(&(drvOpData->srcBuffer), drvOpData)) {
927 EPRINTK("%s() icp_ocfDrvAllocMetaData failed\n", __FUNCTION__);
928 memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData));
929 crp->crp_etype = EINVAL;
930 goto err;
931 }
932
933 /* Perform "in-place" crypto operation */
934 lacStatus = cpaCySymPerformOp(CPA_INSTANCE_HANDLE_SINGLE,
935 (void *)drvOpData,
936 &(drvOpData->lacOpData),
937 &(drvOpData->srcBuffer),
938 &(drvOpData->srcBuffer),
939 &(drvOpData->verifyResult));
940 if (CPA_STATUS_RETRY == lacStatus) {
941 DPRINTK("%s(): cpaCySymPerformOp retry, lacStatus = %d\n",
942 __FUNCTION__, lacStatus);
943 memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData));
944 crp->crp_etype = EINVAL;
945 goto err;
946 }
947 if (CPA_STATUS_SUCCESS != lacStatus) {
948 EPRINTK("%s(): cpaCySymPerformOp failed, lacStatus = %d\n",
949 __FUNCTION__, lacStatus);
950 memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData));
951 crp->crp_etype = EINVAL;
952 goto err;
953 }
954
955 return 0; //OCF success status value
956
957 err:
958 if (drvOpData->numBufferListArray > ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) {
959 kfree(drvOpData->srcBuffer.pBuffers);
960 }
961 icp_ocfDrvFreeMetaData(&(drvOpData->srcBuffer));
962 kmem_cache_free(drvOpData_zone, drvOpData);
963
964 return crp->crp_etype;
965 }
966
967 /* Name : icp_ocfDrvProcessDataSetup
968 *
969 * Description : This function will setup all the cryptographic operation data
970 * that is required by LAC to execute the operation.
971 */
972 static int icp_ocfDrvProcessDataSetup(struct icp_drvOpData *drvOpData,
973 struct cryptodesc *crp_desc)
974 {
975 CpaCyRandGenOpData randGenOpData;
976 CpaFlatBuffer randData;
977
978 drvOpData->lacOpData.packetType = CPA_CY_SYM_PACKET_TYPE_FULL;
979
980 /* Convert from the cryptop to the ICP LAC crypto parameters */
981 switch (crp_desc->crd_alg) {
982 case CRYPTO_NULL_CBC:
983 drvOpData->lacOpData.
984 cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
985 drvOpData->lacOpData.
986 messageLenToCipherInBytes = crp_desc->crd_len;
987 drvOpData->verifyResult = CPA_FALSE;
988 drvOpData->lacOpData.ivLenInBytes = NULL_BLOCK_LEN;
989 break;
990 case CRYPTO_DES_CBC:
991 drvOpData->lacOpData.
992 cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
993 drvOpData->lacOpData.
994 messageLenToCipherInBytes = crp_desc->crd_len;
995 drvOpData->verifyResult = CPA_FALSE;
996 drvOpData->lacOpData.ivLenInBytes = DES_BLOCK_LEN;
997 break;
998 case CRYPTO_3DES_CBC:
999 drvOpData->lacOpData.
1000 cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
1001 drvOpData->lacOpData.
1002 messageLenToCipherInBytes = crp_desc->crd_len;
1003 drvOpData->verifyResult = CPA_FALSE;
1004 drvOpData->lacOpData.ivLenInBytes = DES3_BLOCK_LEN;
1005 break;
1006 case CRYPTO_ARC4:
1007 drvOpData->lacOpData.
1008 cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
1009 drvOpData->lacOpData.
1010 messageLenToCipherInBytes = crp_desc->crd_len;
1011 drvOpData->verifyResult = CPA_FALSE;
1012 drvOpData->lacOpData.ivLenInBytes = ARC4_COUNTER_LEN;
1013 break;
1014 case CRYPTO_AES_CBC:
1015 drvOpData->lacOpData.
1016 cryptoStartSrcOffsetInBytes = crp_desc->crd_skip;
1017 drvOpData->lacOpData.
1018 messageLenToCipherInBytes = crp_desc->crd_len;
1019 drvOpData->verifyResult = CPA_FALSE;
1020 drvOpData->lacOpData.ivLenInBytes = RIJNDAEL128_BLOCK_LEN;
1021 break;
1022 case CRYPTO_SHA1:
1023 case CRYPTO_SHA1_HMAC:
1024 case CRYPTO_SHA2_256:
1025 case CRYPTO_SHA2_256_HMAC:
1026 case CRYPTO_SHA2_384:
1027 case CRYPTO_SHA2_384_HMAC:
1028 case CRYPTO_SHA2_512:
1029 case CRYPTO_SHA2_512_HMAC:
1030 case CRYPTO_MD5:
1031 case CRYPTO_MD5_HMAC:
1032 drvOpData->lacOpData.
1033 hashStartSrcOffsetInBytes = crp_desc->crd_skip;
1034 drvOpData->lacOpData.
1035 messageLenToHashInBytes = crp_desc->crd_len;
1036 drvOpData->lacOpData.
1037 pDigestResult =
1038 icp_ocfDrvDigestPointerFind(drvOpData, crp_desc);
1039
1040 if (NULL == drvOpData->lacOpData.pDigestResult) {
1041 DPRINTK("%s(): ERROR - could not calculate "
1042 "Digest Result memory address\n", __FUNCTION__);
1043 return ICP_OCF_DRV_STATUS_FAIL;
1044 }
1045
1046 drvOpData->lacOpData.digestVerify = CPA_FALSE;
1047 break;
1048 default:
1049 DPRINTK("%s(): Crypto process error - algorithm not "
1050 "found \n", __FUNCTION__);
1051 return ICP_OCF_DRV_STATUS_FAIL;
1052 }
1053
1054 /* Figure out what the IV is supposed to be */
1055 if ((crp_desc->crd_alg == CRYPTO_DES_CBC) ||
1056 (crp_desc->crd_alg == CRYPTO_3DES_CBC) ||
1057 (crp_desc->crd_alg == CRYPTO_AES_CBC)) {
1058 /*ARC4 doesn't use an IV */
1059 if (crp_desc->crd_flags & CRD_F_IV_EXPLICIT) {
1060 /* Explicit IV provided to OCF */
1061 drvOpData->lacOpData.pIv = crp_desc->crd_iv;
1062 } else {
1063 /* IV is not explicitly provided to OCF */
1064
1065 /* Point the LAC OP Data IV pointer to our allocated
1066 storage location for this session. */
1067 drvOpData->lacOpData.pIv = drvOpData->ivData;
1068
1069 if ((crp_desc->crd_flags & CRD_F_ENCRYPT) &&
1070 ((crp_desc->crd_flags & CRD_F_IV_PRESENT) == 0)) {
1071
1072 /* Encrypting - need to create IV */
1073 randGenOpData.generateBits = CPA_TRUE;
1074 randGenOpData.lenInBytes = MAX_IV_LEN_IN_BYTES;
1075
1076 icp_ocfDrvPtrAndLenToFlatBuffer((Cpa8U *)
1077 drvOpData->
1078 ivData,
1079 MAX_IV_LEN_IN_BYTES,
1080 &randData);
1081
1082 if (CPA_STATUS_SUCCESS !=
1083 cpaCyRandGen(CPA_INSTANCE_HANDLE_SINGLE,
1084 NULL, NULL,
1085 &randGenOpData, &randData)) {
1086 DPRINTK("%s(): ERROR - Failed to"
1087 " generate"
1088 " Initialisation Vector\n",
1089 __FUNCTION__);
1090 return ICP_OCF_DRV_STATUS_FAIL;
1091 }
1092
1093 crypto_copyback(drvOpData->crp->
1094 crp_flags,
1095 drvOpData->crp->crp_buf,
1096 crp_desc->crd_inject,
1097 drvOpData->lacOpData.
1098 ivLenInBytes,
1099 (caddr_t) (drvOpData->lacOpData.
1100 pIv));
1101 } else {
1102 /* Reading IV from buffer */
1103 crypto_copydata(drvOpData->crp->
1104 crp_flags,
1105 drvOpData->crp->crp_buf,
1106 crp_desc->crd_inject,
1107 drvOpData->lacOpData.
1108 ivLenInBytes,
1109 (caddr_t) (drvOpData->lacOpData.
1110 pIv));
1111 }
1112
1113 }
1114
1115 }
1116
1117 return ICP_OCF_DRV_STATUS_SUCCESS;
1118 }
1119
1120 /* Name : icp_ocfDrvDigestPointerFind
1121 *
1122 * Description : This function is used to find the memory address of where the
1123 * digest information shall be stored in. Input buffer types are an skbuff, iov
1124 * or flat buffer. The address is found using the buffer data start address and
1125 * an offset.
1126 *
1127 * Note: In the case of a linux skbuff, the digest address may exist within
1128 * a memory space linked to from the start buffer. These linked memory spaces
1129 * must be traversed by the data length offset in order to find the digest start
1130 * address. Whether there is enough space for the digest must also be checked.
1131 */
1132
1133 static uint8_t *icp_ocfDrvDigestPointerFind(struct icp_drvOpData *drvOpData,
1134 struct cryptodesc *crp_desc)
1135 {
1136
1137 int offsetInBytes = crp_desc->crd_inject;
1138 uint32_t digestSizeInBytes = drvOpData->digestSizeInBytes;
1139 uint8_t *flat_buffer_base = NULL;
1140 int flat_buffer_length = 0;
1141 struct sk_buff *skb;
1142
1143 if (drvOpData->crp->crp_flags & CRYPTO_F_SKBUF) {
1144 /*check if enough overall space to store hash */
1145 skb = (struct sk_buff *)(drvOpData->crp->crp_buf);
1146
1147 if (skb->len < (offsetInBytes + digestSizeInBytes)) {
1148 DPRINTK("%s() Not enough space for Digest"
1149 " payload after the offset (%d), "
1150 "digest size (%d) \n", __FUNCTION__,
1151 offsetInBytes, digestSizeInBytes);
1152 return NULL;
1153 }
1154
1155 return icp_ocfDrvSkbuffDigestPointerFind(drvOpData,
1156 offsetInBytes,
1157 digestSizeInBytes);
1158
1159 } else {
1160 /* IOV or flat buffer */
1161 if (drvOpData->crp->crp_flags & CRYPTO_F_IOV) {
1162 /*single IOV check has already been done */
1163 flat_buffer_base = ((struct uio *)
1164 (drvOpData->crp->crp_buf))->
1165 uio_iov[0].iov_base;
1166 flat_buffer_length = ((struct uio *)
1167 (drvOpData->crp->crp_buf))->
1168 uio_iov[0].iov_len;
1169 } else {
1170 flat_buffer_base = (uint8_t *) drvOpData->crp->crp_buf;
1171 flat_buffer_length = drvOpData->crp->crp_ilen;
1172 }
1173
1174 if (flat_buffer_length < (offsetInBytes + digestSizeInBytes)) {
1175 DPRINTK("%s() Not enough space for Digest "
1176 "(IOV/Flat Buffer) \n", __FUNCTION__);
1177 return NULL;
1178 } else {
1179 return (uint8_t *) (flat_buffer_base + offsetInBytes);
1180 }
1181 }
1182 DPRINTK("%s() Should not reach this point\n", __FUNCTION__);
1183 return NULL;
1184 }
1185
1186 /* Name : icp_ocfDrvSkbuffDigestPointerFind
1187 *
1188 * Description : This function is used by icp_ocfDrvDigestPointerFind to process
1189 * the non-linear portion of the skbuff if the fragmentation type is a linked
1190 * list (frag_list is not NULL in the skb_shared_info structure)
1191 */
1192 static inline uint8_t *icp_ocfDrvSkbuffDigestPointerFind(struct icp_drvOpData
1193 *drvOpData,
1194 int offsetInBytes,
1195 uint32_t
1196 digestSizeInBytes)
1197 {
1198
1199 struct sk_buff *skb = NULL;
1200 struct skb_shared_info *skb_shared = NULL;
1201
1202 uint32_t skbuffisnonlinear = 0;
1203
1204 uint32_t skbheadlen = 0;
1205
1206 skb = (struct sk_buff *)(drvOpData->crp->crp_buf);
1207 skbuffisnonlinear = skb_is_nonlinear(skb);
1208
1209 skbheadlen = skb_headlen(skb);
1210
1211 /*Linear skb checks */
1212 if (skbheadlen > offsetInBytes) {
1213
1214 if (skbheadlen >= (offsetInBytes + digestSizeInBytes)) {
1215 return (uint8_t *) (skb->data + offsetInBytes);
1216 } else {
1217 DPRINTK("%s() Auth payload stretches "
1218 "accross contiguous memory\n", __FUNCTION__);
1219 return NULL;
1220 }
1221 } else {
1222 if (skbuffisnonlinear) {
1223 offsetInBytes -= skbheadlen;
1224 } else {
1225 DPRINTK("%s() Offset outside of buffer boundaries\n",
1226 __FUNCTION__);
1227 return NULL;
1228 }
1229 }
1230
1231 /*Non Linear checks */
1232 skb_shared = (struct skb_shared_info *)(skb->end);
1233 if (unlikely(NULL == skb_shared)) {
1234 DPRINTK("%s() skbuff shared info stucture is NULL! \n",
1235 __FUNCTION__);
1236 return NULL;
1237 } else if ((0 != skb_shared->nr_frags) &&
1238 (skb_shared->frag_list != NULL)) {
1239 DPRINTK("%s() skbuff nr_frags AND "
1240 "frag_list not supported \n", __FUNCTION__);
1241 return NULL;
1242 }
1243
1244 /*TCP segmentation more likely than IP fragmentation */
1245 if (likely(0 != skb_shared->nr_frags)) {
1246 return icp_ocfDrvDigestSkbNRFragsCheck(skb, skb_shared,
1247 offsetInBytes,
1248 digestSizeInBytes);
1249 } else if (skb_shared->frag_list != NULL) {
1250 return icp_ocfDrvDigestSkbFragListCheck(skb, skb_shared,
1251 offsetInBytes,
1252 digestSizeInBytes);
1253 } else {
1254 DPRINTK("%s() skbuff is non-linear but does not show any "
1255 "linked data\n", __FUNCTION__);
1256 return NULL;
1257 }
1258
1259 }
1260
1261 /* Name : icp_ocfDrvDigestSkbNRFragsCheck
1262 *
1263 * Description : This function is used by icp_ocfDrvSkbuffDigestPointerFind to
1264 * process the non-linear portion of the skbuff, if the fragmentation type is
1265 * page fragments
1266 */
1267 static inline uint8_t *icp_ocfDrvDigestSkbNRFragsCheck(struct sk_buff *skb,
1268 struct skb_shared_info
1269 *skb_shared,
1270 int offsetInBytes,
1271 uint32_t
1272 digestSizeInBytes)
1273 {
1274 int i = 0;
1275 /*nr_frags starts from 1 */
1276 if (MAX_SKB_FRAGS < skb_shared->nr_frags) {
1277 DPRINTK("%s error processing skbuff "
1278 "page frame -- MAX FRAGS exceeded \n", __FUNCTION__);
1279 return NULL;
1280 }
1281
1282 for (i = 0; i < skb_shared->nr_frags; i++) {
1283
1284 if (offsetInBytes >= skb_shared->frags[i].size) {
1285 /*offset still greater than data position */
1286 offsetInBytes -= skb_shared->frags[i].size;
1287 } else {
1288 /* found the page containing start of hash */
1289
1290 if (NULL == skb_shared->frags[i].page) {
1291 DPRINTK("%s() Linked page is NULL!\n",
1292 __FUNCTION__);
1293 return NULL;
1294 }
1295
1296 if (offsetInBytes + digestSizeInBytes >
1297 skb_shared->frags[i].size) {
1298 DPRINTK("%s() Auth payload stretches accross "
1299 "contiguous memory\n", __FUNCTION__);
1300 return NULL;
1301 } else {
1302 return (uint8_t *) (skb_shared->frags[i].page +
1303 skb_shared->frags[i].
1304 page_offset +
1305 offsetInBytes);
1306 }
1307 }
1308 /*only possible if internal page sizes are set wrong */
1309 if (offsetInBytes < 0) {
1310 DPRINTK("%s error processing skbuff page frame "
1311 "-- offset calculation \n", __FUNCTION__);
1312 return NULL;
1313 }
1314 }
1315 /*only possible if internal page sizes are set wrong */
1316 DPRINTK("%s error processing skbuff page frame "
1317 "-- ran out of page fragments, remaining offset = %d \n",
1318 __FUNCTION__, offsetInBytes);
1319 return NULL;
1320
1321 }
1322
1323 /* Name : icp_ocfDrvDigestSkbFragListCheck
1324 *
1325 * Description : This function is used by icp_ocfDrvSkbuffDigestPointerFind to
1326 * process the non-linear portion of the skbuff, if the fragmentation type is
1327 * a linked list
1328 *
1329 */
1330 static inline uint8_t *icp_ocfDrvDigestSkbFragListCheck(struct sk_buff *skb,
1331 struct skb_shared_info
1332 *skb_shared,
1333 int offsetInBytes,
1334 uint32_t
1335 digestSizeInBytes)
1336 {
1337
1338 struct sk_buff *skb_list = skb_shared->frag_list;
1339 /*check added for readability */
1340 if (NULL == skb_list) {
1341 DPRINTK("%s error processing skbuff "
1342 "-- no more list! \n", __FUNCTION__);
1343 return NULL;
1344 }
1345
1346 for (; skb_list; skb_list = skb_list->next) {
1347 if (NULL == skb_list) {
1348 DPRINTK("%s error processing skbuff "
1349 "-- no more list! \n", __FUNCTION__);
1350 return NULL;
1351 }
1352
1353 if (offsetInBytes >= skb_list->len) {
1354 offsetInBytes -= skb_list->len;
1355
1356 } else {
1357 if (offsetInBytes + digestSizeInBytes > skb_list->len) {
1358 DPRINTK("%s() Auth payload stretches accross "
1359 "contiguous memory\n", __FUNCTION__);
1360 return NULL;
1361 } else {
1362 return (uint8_t *)
1363 (skb_list->data + offsetInBytes);
1364 }
1365
1366 }
1367
1368 /*This check is only needed if internal skb_list length values
1369 are set wrong. */
1370 if (0 > offsetInBytes) {
1371 DPRINTK("%s() error processing skbuff object -- offset "
1372 "calculation \n", __FUNCTION__);
1373 return NULL;
1374 }
1375
1376 }
1377
1378 /*catch all for unusual for-loop exit.
1379 This code should never be reached */
1380 DPRINTK("%s() Catch-All hit! Process error.\n", __FUNCTION__);
1381 return NULL;
1382 }
This page took 0.107315 seconds and 5 git commands to generate.