[kernel] ocf: move all stuff into files, and fix build error on .25
[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 }