1 /***************************************************************************
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.
8 * Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
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.
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.
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.
25 * Contact Information:
30 * Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
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
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.
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.
60 * version: Security.L.1.0.130
62 ***************************************************************************/
64 * An OCF module that uses the API for IntelĀ® QuickAssist Technology to do the
67 * This driver requires the ICP Access Library that is available from Intel in
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
77 icp_ocfDrvSymCallBack(void *callbackTag
,
79 const CpaCySymOp operationType
,
81 CpaBufferList
* pDstBuffer
, CpaBoolean verifyResult
);
83 /*This function is used to extract crypto processing information from the OCF
84 inputs, so as that it may be passed onto LAC*/
86 icp_ocfDrvProcessDataSetup(struct icp_drvOpData
*drvOpData
,
87 struct cryptodesc
*crp_desc
);
89 /*This function checks whether the crp_desc argument pertains to a digest or a
91 static int icp_ocfDrvAlgCheck(struct cryptodesc
*crp_desc
);
93 /*This function copies all the passed in session context information and stores
94 it in a LAC context structure*/
96 icp_ocfDrvAlgorithmSetup(struct cryptoini
*cri
,
97 CpaCySymSessionSetupData
* lacSessCtx
);
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
);
104 /*This function is called when a digest pointer has to be found within a
106 static inline uint8_t *icp_ocfDrvSkbuffDigestPointerFind(struct icp_drvOpData
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
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
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
131 /*This function is used to free an OCF->OCF_DRV session object*/
132 static void icp_ocfDrvFreeOCFSession(struct icp_drvSessionData
*sessionData
);
134 /*max IOV buffs supported in a UIO structure*/
135 #define NUM_IOV_SUPPORTED (1)
137 /* Name : icp_ocfDrvSymCallBack
139 * Description : When this function returns it signifies that the LAC
140 * component has completed the relevant symmetric operation.
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.
148 icp_ocfDrvSymCallBack(void *callbackTag
,
150 const CpaCySymOp operationType
,
152 CpaBufferList
* pDstBuffer
, CpaBoolean verifyResult
)
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;
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__
);
168 crp
= temp_drvOpData
->crp
;
169 crp
->crp_etype
= ICP_OCF_DRV_NO_CRYPTO_PROCESS_ERROR
;
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
;
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
;
189 if (CPA_STATUS_SUCCESS
== status
) {
191 if (temp_drvOpData
->bufferType
== CRYPTO_F_SKBUF
) {
192 if (ICP_OCF_DRV_STATUS_SUCCESS
!=
193 icp_ocfDrvBufferListToSkBuff(pDstBuffer
,
196 EPRINTK("%s(): BufferList to SkBuff "
197 "conversion error.\n", __FUNCTION__
);
198 crp
->crp_etype
= EPERM
;
201 icp_ocfDrvBufferListToPtrAndLen(pDstBuffer
,
202 (void **)&tempBasePtr
,
204 crp
->crp_olen
= (int)tempLen
;
208 DPRINTK("%s(): The callback from the LAC component has failed"
209 "(status == %d).\n", __FUNCTION__
, status
);
211 crp
->crp_etype
= ECANCELED
;
214 if (temp_drvOpData
->numBufferListArray
>
215 ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS
) {
216 kfree(pDstBuffer
->pBuffers
);
218 icp_ocfDrvFreeMetaData(pDstBuffer
);
219 kmem_cache_free(drvOpData_zone
, temp_drvOpData
);
221 /* Invoke the OCF callback function */
227 /* Name : icp_ocfDrvNewSession
229 * Description : This function will create a new Driver<->OCF session
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.
234 int icp_ocfDrvNewSession(device_t dev
, uint32_t * sid
, struct cryptoini
*cri
)
236 struct icp_drvSessionData
*sessionData
= NULL
;
237 uint32_t delete_session
= 0;
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 */
243 EPRINTK("%s(): Invalid input parameters - NULL sid.\n",
249 EPRINTK("%s(): Invalid input parameters - NULL cryptoini.\n",
254 if (icp_ocfDrvDriverId
!= *sid
) {
255 EPRINTK("%s(): Invalid input parameters - bad driver ID\n",
257 EPRINTK("\t sid = 0x08%p \n \t cri = 0x08%p \n", sid
, cri
);
261 sessionData
= kmem_cache_zalloc(drvSessionData_zone
, GFP_ATOMIC
);
262 if (NULL
== sessionData
) {
263 DPRINTK("%s():No memory for Session Data\n", __FUNCTION__
);
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
)) {
274 } else if (NO_OCF_TO_DRV_MAX_SESSIONS
!= max_sessions
) {
275 if (atomic_read(&num_ocf_to_drv_registered_sessions
) >=
277 atomic_read(&lac_session_failed_dereg_count
))) {
280 atomic_inc(&num_ocf_to_drv_registered_sessions
);
281 /* Add to session data linked list */
282 list_add(&(sessionData
->listNode
),
283 &icp_ocfDrvGlobalSymListHead
);
286 } else if (NO_OCF_TO_DRV_MAX_SESSIONS
== max_sessions
) {
287 list_add(&(sessionData
->listNode
),
288 &icp_ocfDrvGlobalSymListHead
);
291 sessionData
->inUse
= ICP_SESSION_INITIALISED
;
293 /*EXIT CRITICAL SECTION */
294 spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock
);
296 if (delete_session
) {
297 DPRINTK("%s():No Session handles available\n", __FUNCTION__
);
298 kmem_cache_free(drvSessionData_zone
, sessionData
);
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
);
310 if (cri
->cri_next
->cri_next
!= NULL
) {
311 DPRINTK("%s():only two chained algorithms supported\n",
313 icp_ocfDrvFreeOCFSession(sessionData
);
317 if (ICP_OCF_DRV_STATUS_SUCCESS
!=
318 icp_ocfDrvAlgorithmSetup(cri
->cri_next
,
319 &(sessionData
->lacSessCtx
))) {
320 DPRINTK("%s():second algorithm not supported\n",
322 icp_ocfDrvFreeOCFSession(sessionData
);
326 sessionData
->lacSessCtx
.symOperation
=
327 CPA_CY_SYM_OP_ALGORITHM_CHAINING
;
330 *sid
= (uint32_t) sessionData
;
332 return ICP_OCF_DRV_STATUS_SUCCESS
;
335 /* Name : icp_ocfDrvAlgorithmSetup
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.
343 icp_ocfDrvAlgorithmSetup(struct cryptoini
*cri
,
344 CpaCySymSessionSetupData
* lacSessCtx
)
347 lacSessCtx
->sessionPriority
= CPA_CY_PRIORITY_NORMAL
;
349 switch (cri
->cri_alg
) {
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
;
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
;
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
;
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
;
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
;
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
=
408 cri
->cri_mlen
: ICP_SHA1_DIGEST_SIZE_IN_BYTES
);
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
=
419 cri
->cri_mlen
: ICP_SHA1_DIGEST_SIZE_IN_BYTES
);
420 lacSessCtx
->hashSetupData
.authModeSetupData
.authKey
=
422 lacSessCtx
->hashSetupData
.authModeSetupData
.authKeyLenInBytes
=
423 cri
->cri_klen
/ NUM_BITS_IN_BYTE
;
424 lacSessCtx
->hashSetupData
.authModeSetupData
.aadLenInBytes
= 0;
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
=
436 cri
->cri_mlen
: ICP_SHA256_DIGEST_SIZE_IN_BYTES
);
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
=
448 cri
->cri_mlen
: ICP_SHA256_DIGEST_SIZE_IN_BYTES
);
449 lacSessCtx
->hashSetupData
.authModeSetupData
.authKey
=
451 lacSessCtx
->hashSetupData
.authModeSetupData
.authKeyLenInBytes
=
452 cri
->cri_klen
/ NUM_BITS_IN_BYTE
;
453 lacSessCtx
->hashSetupData
.authModeSetupData
.aadLenInBytes
= 0;
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
=
465 cri
->cri_mlen
: ICP_SHA384_DIGEST_SIZE_IN_BYTES
);
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
=
477 cri
->cri_mlen
: ICP_SHA384_DIGEST_SIZE_IN_BYTES
);
478 lacSessCtx
->hashSetupData
.authModeSetupData
.authKey
=
480 lacSessCtx
->hashSetupData
.authModeSetupData
.authKeyLenInBytes
=
481 cri
->cri_klen
/ NUM_BITS_IN_BYTE
;
482 lacSessCtx
->hashSetupData
.authModeSetupData
.aadLenInBytes
= 0;
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
=
494 cri
->cri_mlen
: ICP_SHA512_DIGEST_SIZE_IN_BYTES
);
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
=
506 cri
->cri_mlen
: ICP_SHA512_DIGEST_SIZE_IN_BYTES
);
507 lacSessCtx
->hashSetupData
.authModeSetupData
.authKey
=
509 lacSessCtx
->hashSetupData
.authModeSetupData
.authKeyLenInBytes
=
510 cri
->cri_klen
/ NUM_BITS_IN_BYTE
;
511 lacSessCtx
->hashSetupData
.authModeSetupData
.aadLenInBytes
= 0;
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
=
522 cri
->cri_mlen
: ICP_MD5_DIGEST_SIZE_IN_BYTES
);
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
=
533 cri
->cri_mlen
: ICP_MD5_DIGEST_SIZE_IN_BYTES
);
534 lacSessCtx
->hashSetupData
.authModeSetupData
.authKey
=
536 lacSessCtx
->hashSetupData
.authModeSetupData
.authKeyLenInBytes
=
537 cri
->cri_klen
/ NUM_BITS_IN_BYTE
;
538 lacSessCtx
->hashSetupData
.authModeSetupData
.aadLenInBytes
= 0;
543 DPRINTK("%s(): ALG Setup FAIL\n", __FUNCTION__
);
544 return ICP_OCF_DRV_STATUS_FAIL
;
547 return ICP_OCF_DRV_STATUS_SUCCESS
;
550 /* Name : icp_ocfDrvFreeOCFSession
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.
557 static void icp_ocfDrvFreeOCFSession(struct icp_drvSessionData
*sessionData
)
560 sessionData
->inUse
= ICP_SESSION_DEREGISTERED
;
562 /*ENTER CRITICAL SECTION */
563 spin_lock_bh(&icp_ocfDrvSymSessInfoListSpinlock
);
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
);
573 atomic_dec(&num_ocf_to_drv_registered_sessions
);
575 list_del(&(sessionData
->listNode
));
577 /*EXIT CRITICAL SECTION */
578 spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock
);
580 if (NULL
!= sessionData
->sessHandle
) {
581 kfree(sessionData
->sessHandle
);
583 kmem_cache_free(drvSessionData_zone
, sessionData
);
586 /* Name : icp_ocfDrvFreeLACSession
588 * Description : This attempts to deregister a LAC session. If it fails, the
589 * deregistation retry function is called.
591 int icp_ocfDrvFreeLACSession(device_t dev
, uint64_t sid
)
593 CpaCySymSessionCtx sessionToDeregister
= NULL
;
594 struct icp_drvSessionData
*sessionData
= NULL
;
595 CpaStatus lacStatus
= CPA_STATUS_SUCCESS
;
598 sessionData
= (struct icp_drvSessionData
*)CRYPTO_SESID2LID(sid
);
599 if (NULL
== sessionData
) {
600 EPRINTK("%s(): OCF Free session called with Null Session ID.\n",
605 sessionToDeregister
= sessionData
->sessHandle
;
607 if (ICP_SESSION_INITIALISED
== sessionData
->inUse
) {
608 DPRINTK("%s() Session not registered with LAC\n", __FUNCTION__
);
609 } else if (NULL
== sessionData
->sessHandle
) {
611 ("%s(): OCF Free session called with Null Session Handle.\n",
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
);
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
);
637 icp_ocfDrvFreeOCFSession(sessionData
);
642 /* Name : icp_ocfDrvAlgCheck
644 * Description : This function checks whether the cryptodesc argument pertains
645 * to a sym or hash function
647 static int icp_ocfDrvAlgCheck(struct cryptodesc
*crp_desc
)
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
;
658 return ICP_OCF_DRV_ALG_HASH
;
661 /* Name : icp_ocfDrvSymProcess
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.
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
671 int icp_ocfDrvSymProcess(device_t dev
, struct cryptop
*crp
, int hint
)
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;
680 DPRINTK("%s(): Invalid input parameters, cryptop is NULL\n",
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
;
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
;
699 if (CPA_TRUE
== atomic_read(&icp_ocfDrvIsExiting
)) {
700 crp
->crp_etype
= EFAULT
;
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",
709 crp
->crp_etype
= EINVAL
;
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
;
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
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
;
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__
);
739 if (NULL
!= crp
->crp_desc
->crd_next
) {
740 if (ICP_OCF_DRV_ALG_CIPHER
==
741 icp_ocfDrvAlgCheck(crp
->crp_desc
)) {
743 sessionData
->lacSessCtx
.algChainOrder
=
744 CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH
;
746 if (crp
->crp_desc
->crd_flags
& CRD_F_ENCRYPT
) {
747 sessionData
->lacSessCtx
.cipherSetupData
.
749 CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT
;
751 sessionData
->lacSessCtx
.cipherSetupData
.
753 CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT
;
756 sessionData
->lacSessCtx
.algChainOrder
=
757 CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER
;
759 if (crp
->crp_desc
->crd_next
->crd_flags
&
761 sessionData
->lacSessCtx
.cipherSetupData
.
763 CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT
;
765 sessionData
->lacSessCtx
.cipherSetupData
.
767 CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT
;
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
.
777 CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT
;
779 sessionData
->lacSessCtx
.cipherSetupData
.
781 CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT
;
786 /*No action required for standalone Auth here */
788 /* Allocate memory for SymSessionCtx before the Session Registration */
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
);
798 sessionData
->sessHandle
=
799 kmalloc(sessionCtxSizeInBytes
, GFP_ATOMIC
);
800 if (NULL
== sessionData
->sessHandle
) {
802 ("%s(): Failed to get memory for SymSessionCtx\n",
807 lacStatus
= cpaCySymInitSession(CPA_INSTANCE_HANDLE_SINGLE
,
808 icp_ocfDrvSymCallBack
,
809 &(sessionData
->lacSessCtx
),
810 sessionData
->sessHandle
);
812 if (CPA_STATUS_SUCCESS
!= lacStatus
) {
813 EPRINTK("%s(): cpaCySymInitSession failed -%d \n",
814 __FUNCTION__
, lacStatus
);
818 sessionData
->inUse
= ICP_SESSION_RUNNING
;
821 drvOpData
= kmem_cache_zalloc(drvOpData_zone
, GFP_ATOMIC
);
822 if (NULL
== drvOpData
) {
823 EPRINTK("%s():Failed to get memory for drvOpData\n",
825 crp
->crp_etype
= ENOMEM
;
829 drvOpData
->lacOpData
.pSessionCtx
= sessionData
->sessHandle
;
830 drvOpData
->digestSizeInBytes
= sessionData
->lacSessCtx
.hashSetupData
.
831 digestResultLenInBytes
;
832 drvOpData
->crp
= crp
;
834 /* Set the default buffer list array memory allocation */
835 drvOpData
->srcBuffer
.pBuffers
= drvOpData
->bufferListArray
;
836 drvOpData
->numBufferListArray
= ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS
;
839 * Allocate buffer list array memory allocation if the
840 * data fragment is more than the default allocation
842 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
843 numBufferListArray
= icp_ocfDrvGetSkBuffFrags((struct sk_buff
*)
845 if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS
< numBufferListArray
) {
846 DPRINTK("%s() numBufferListArray more than default\n",
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
;
859 drvOpData
->numBufferListArray
= numBufferListArray
;
864 * Check the type of buffer structure we got and convert it into
865 * CpaBufferList format.
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
;
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
) {
883 icp_ocfDrvPtrAndLenToBufferList(((struct uio
*)(crp
->
886 ((struct uio
*)(crp
->
892 drvOpData
->bufferType
= CRYPTO_F_IOV
;
895 DPRINTK("%s():Unable to handle IOVs with lengths of "
896 "greater than one!\n", __FUNCTION__
);
897 crp
->crp_etype
= EINVAL
;
902 icp_ocfDrvPtrAndLenToBufferList(crp
->crp_buf
,
904 &(drvOpData
->srcBuffer
));
906 drvOpData
->bufferType
= CRYPTO_BUF_CONTIG
;
909 if (ICP_OCF_DRV_STATUS_SUCCESS
!=
910 icp_ocfDrvProcessDataSetup(drvOpData
, drvOpData
->crp
->crp_desc
)) {
911 crp
->crp_etype
= EINVAL
;
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
;
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
;
933 /* Perform "in-place" crypto operation */
934 lacStatus
= cpaCySymPerformOp(CPA_INSTANCE_HANDLE_SINGLE
,
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
;
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
;
955 return 0; //OCF success status value
958 if (drvOpData
->numBufferListArray
> ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS
) {
959 kfree(drvOpData
->srcBuffer
.pBuffers
);
961 icp_ocfDrvFreeMetaData(&(drvOpData
->srcBuffer
));
962 kmem_cache_free(drvOpData_zone
, drvOpData
);
964 return crp
->crp_etype
;
967 /* Name : icp_ocfDrvProcessDataSetup
969 * Description : This function will setup all the cryptographic operation data
970 * that is required by LAC to execute the operation.
972 static int icp_ocfDrvProcessDataSetup(struct icp_drvOpData
*drvOpData
,
973 struct cryptodesc
*crp_desc
)
975 CpaCyRandGenOpData randGenOpData
;
976 CpaFlatBuffer randData
;
978 drvOpData
->lacOpData
.packetType
= CPA_CY_SYM_PACKET_TYPE_FULL
;
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
;
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
;
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
;
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
;
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
;
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
:
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
.
1038 icp_ocfDrvDigestPointerFind(drvOpData
, crp_desc
);
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
;
1046 drvOpData
->lacOpData
.digestVerify
= CPA_FALSE
;
1049 DPRINTK("%s(): Crypto process error - algorithm not "
1050 "found \n", __FUNCTION__
);
1051 return ICP_OCF_DRV_STATUS_FAIL
;
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
;
1063 /* IV is not explicitly provided to OCF */
1065 /* Point the LAC OP Data IV pointer to our allocated
1066 storage location for this session. */
1067 drvOpData
->lacOpData
.pIv
= drvOpData
->ivData
;
1069 if ((crp_desc
->crd_flags
& CRD_F_ENCRYPT
) &&
1070 ((crp_desc
->crd_flags
& CRD_F_IV_PRESENT
) == 0)) {
1072 /* Encrypting - need to create IV */
1073 randGenOpData
.generateBits
= CPA_TRUE
;
1074 randGenOpData
.lenInBytes
= MAX_IV_LEN_IN_BYTES
;
1076 icp_ocfDrvPtrAndLenToFlatBuffer((Cpa8U
*)
1079 MAX_IV_LEN_IN_BYTES
,
1082 if (CPA_STATUS_SUCCESS
!=
1083 cpaCyRandGen(CPA_INSTANCE_HANDLE_SINGLE
,
1085 &randGenOpData
, &randData
)) {
1086 DPRINTK("%s(): ERROR - Failed to"
1088 " Initialisation Vector\n",
1090 return ICP_OCF_DRV_STATUS_FAIL
;
1093 crypto_copyback(drvOpData
->crp
->
1095 drvOpData
->crp
->crp_buf
,
1096 crp_desc
->crd_inject
,
1097 drvOpData
->lacOpData
.
1099 (caddr_t
) (drvOpData
->lacOpData
.
1102 /* Reading IV from buffer */
1103 crypto_copydata(drvOpData
->crp
->
1105 drvOpData
->crp
->crp_buf
,
1106 crp_desc
->crd_inject
,
1107 drvOpData
->lacOpData
.
1109 (caddr_t
) (drvOpData
->lacOpData
.
1117 return ICP_OCF_DRV_STATUS_SUCCESS
;
1120 /* Name : icp_ocfDrvDigestPointerFind
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
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.
1133 static uint8_t *icp_ocfDrvDigestPointerFind(struct icp_drvOpData
*drvOpData
,
1134 struct cryptodesc
*crp_desc
)
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
;
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
);
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
);
1155 return icp_ocfDrvSkbuffDigestPointerFind(drvOpData
,
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
))->
1170 flat_buffer_base
= (uint8_t *) drvOpData
->crp
->crp_buf
;
1171 flat_buffer_length
= drvOpData
->crp
->crp_ilen
;
1174 if (flat_buffer_length
< (offsetInBytes
+ digestSizeInBytes
)) {
1175 DPRINTK("%s() Not enough space for Digest "
1176 "(IOV/Flat Buffer) \n", __FUNCTION__
);
1179 return (uint8_t *) (flat_buffer_base
+ offsetInBytes
);
1182 DPRINTK("%s() Should not reach this point\n", __FUNCTION__
);
1186 /* Name : icp_ocfDrvSkbuffDigestPointerFind
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)
1192 static inline uint8_t *icp_ocfDrvSkbuffDigestPointerFind(struct icp_drvOpData
1199 struct sk_buff
*skb
= NULL
;
1200 struct skb_shared_info
*skb_shared
= NULL
;
1202 uint32_t skbuffisnonlinear
= 0;
1204 uint32_t skbheadlen
= 0;
1206 skb
= (struct sk_buff
*)(drvOpData
->crp
->crp_buf
);
1207 skbuffisnonlinear
= skb_is_nonlinear(skb
);
1209 skbheadlen
= skb_headlen(skb
);
1211 /*Linear skb checks */
1212 if (skbheadlen
> offsetInBytes
) {
1214 if (skbheadlen
>= (offsetInBytes
+ digestSizeInBytes
)) {
1215 return (uint8_t *) (skb
->data
+ offsetInBytes
);
1217 DPRINTK("%s() Auth payload stretches "
1218 "accross contiguous memory\n", __FUNCTION__
);
1222 if (skbuffisnonlinear
) {
1223 offsetInBytes
-= skbheadlen
;
1225 DPRINTK("%s() Offset outside of buffer boundaries\n",
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",
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__
);
1244 /*TCP segmentation more likely than IP fragmentation */
1245 if (likely(0 != skb_shared
->nr_frags
)) {
1246 return icp_ocfDrvDigestSkbNRFragsCheck(skb
, skb_shared
,
1249 } else if (skb_shared
->frag_list
!= NULL
) {
1250 return icp_ocfDrvDigestSkbFragListCheck(skb
, skb_shared
,
1254 DPRINTK("%s() skbuff is non-linear but does not show any "
1255 "linked data\n", __FUNCTION__
);
1261 /* Name : icp_ocfDrvDigestSkbNRFragsCheck
1263 * Description : This function is used by icp_ocfDrvSkbuffDigestPointerFind to
1264 * process the non-linear portion of the skbuff, if the fragmentation type is
1267 static inline uint8_t *icp_ocfDrvDigestSkbNRFragsCheck(struct sk_buff
*skb
,
1268 struct skb_shared_info
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__
);
1282 for (i
= 0; i
< skb_shared
->nr_frags
; i
++) {
1284 if (offsetInBytes
>= skb_shared
->frags
[i
].size
) {
1285 /*offset still greater than data position */
1286 offsetInBytes
-= skb_shared
->frags
[i
].size
;
1288 /* found the page containing start of hash */
1290 if (NULL
== skb_shared
->frags
[i
].page
) {
1291 DPRINTK("%s() Linked page is NULL!\n",
1296 if (offsetInBytes
+ digestSizeInBytes
>
1297 skb_shared
->frags
[i
].size
) {
1298 DPRINTK("%s() Auth payload stretches accross "
1299 "contiguous memory\n", __FUNCTION__
);
1302 return (uint8_t *) (skb_shared
->frags
[i
].page
+
1303 skb_shared
->frags
[i
].
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__
);
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
);
1323 /* Name : icp_ocfDrvDigestSkbFragListCheck
1325 * Description : This function is used by icp_ocfDrvSkbuffDigestPointerFind to
1326 * process the non-linear portion of the skbuff, if the fragmentation type is
1330 static inline uint8_t *icp_ocfDrvDigestSkbFragListCheck(struct sk_buff
*skb
,
1331 struct skb_shared_info
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__
);
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__
);
1353 if (offsetInBytes
>= skb_list
->len
) {
1354 offsetInBytes
-= skb_list
->len
;
1357 if (offsetInBytes
+ digestSizeInBytes
> skb_list
->len
) {
1358 DPRINTK("%s() Auth payload stretches accross "
1359 "contiguous memory\n", __FUNCTION__
);
1363 (skb_list
->data
+ offsetInBytes
);
1368 /*This check is only needed if internal skb_list length values
1370 if (0 > offsetInBytes
) {
1371 DPRINTK("%s() error processing skbuff object -- offset "
1372 "calculation \n", __FUNCTION__
);
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__
);