Root/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*/
76static void
77icp_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*/
85static int
86icp_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*/
91static 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*/
95static int
96icp_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. */
101static 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.*/
106static 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.*/
116static 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.*/
124static 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*/
132static 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 */
147static void
148icp_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 */
234int 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 */
342static int
343icp_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 */
557static 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 */
591int 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 */
647static 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 */
671int 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 */
972static 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
1133static 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 */
1192static 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 */
1267static 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 */
1330static 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}
1383

Archive Download this file



interactive