RE: cra_priority usage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Herbert,

Thank you for your answer. I forgot to mention that the version of the kernel I am using is 2.6.28.10; I can't use the latest one because of the hardware I am using.

The code is below; it registers the 3 algorithms needed for IPSec. The actual implementations of the algorithms are in other files. They basically call a dedicated hardware and for that reason need to be asynchronous. I can send them if you wish.

----------------------------
/*
 * icp_netkey.c
 *
 * This is an implementation of Linux Kernel Crypto API shim that uses
 * the Intel's Quick Assist API. The focus here is IPsec, (Netkey stack).
 * 
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/rwsem.h>

#include <crypto/aead.h>
#include <crypto/algapi.h> 

#include "icp_sym_chaining.h"
#include "icp_aes_gcm.h"
#include "icp_netkey.h" 
#include "cpa.h"
#include "cpa_cy_sym.h"
#include "cpa_cy_im.h"

static icp_aead_tfm_desc_t *g_pTfm_desc_list = NULL;
static icp_aead_tfm_desc_t *g_pTfm_desc_list_head = NULL;

static struct kmem_cache *pOpDataCache = NULL;
static struct kmem_cache *pMetaCache = NULL;

static struct rw_semaphore tfm_desc_semaphore;


/* delete the tfm descriptor associated with this aead */
static void del_tfm_desc(const struct crypto_aead* const pAead)
{
    icp_aead_tfm_desc_t *pCurr = NULL;
    CpaStatus status = CPA_STATUS_SUCCESS;
    for (pCurr = g_pTfm_desc_list_head; pCurr != NULL; pCurr = pCurr->pNext)
	{
		if (pCurr->pAead == pAead)
		{
			down_write(&tfm_desc_semaphore);
            ICP_REMOVE_ELEMENT_FROM_LIST(pCurr, g_pTfm_desc_list, g_pTfm_desc_list_head);
			up_write(&tfm_desc_semaphore);
			
			if (pCurr->pEncrypt_session_ctx != NULL)
			{
				status = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE, pCurr->pEncrypt_session_ctx);
			
				if (CPA_STATUS_SUCCESS != status)
				{
					printk("cpaCySymRemoveSession failed. (status = %d)\n", status);
					/* the session could not be removed, its memory can't be freed */
				}
				else
				{
					icp_kfree(pCurr->pEncrypt_session_ctx);
					dprintk("cpaCySymRemoveSession for Encryption was successful. (status = %d)\n", status);
				}
			}
			
			if (pCurr->pDecrypt_session_ctx != NULL)
			{
				status = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE, pCurr->pDecrypt_session_ctx);
			
				if (CPA_STATUS_SUCCESS != status)
				{
				/* the session could not be removed, its memory can't be freed */					
					printk("cpaCySymRemoveSession failed. (status = %d)\n", status);
				}
				else
				{
					icp_kfree(pCurr->pDecrypt_session_ctx);
					dprintk("cpaCySymRemoveSession for Decryption was successful. (status = %d)\n", status);					
				}
			}

            icp_kfree(pCurr);
            dprintk("%s: tfm_desc deleted\n", __FUNCTION__);
            break;
        }
     }
}


static void  aead_auth_exit(struct crypto_tfm *pTfm)
{
	del_tfm_desc((struct crypto_aead *)(pTfm));
}


inline icp_aead_tfm_desc_t *find_tfm_desc(const struct crypto_aead* const pAead)
{
    icp_aead_tfm_desc_t *pCurr = NULL;
	down_read(&tfm_desc_semaphore);
		
    for (pCurr = g_pTfm_desc_list_head; pCurr != NULL; pCurr = pCurr->pNext)
	{
        if (pCurr->pAead == pAead)
		{
            dprintk("%s: found tfm_desc = %p\n", __FUNCTION__, pCurr);
			up_read(&tfm_desc_semaphore);
            return pCurr;
         }
    }
	up_read(&tfm_desc_semaphore);
    return NULL;
}


icp_aead_tfm_desc_t *add_tfm_desc(struct crypto_aead* const pAead)
{
    icp_aead_tfm_desc_t *pCurr = NULL;

    pCurr = find_tfm_desc(pAead);
    if (NULL != pCurr)
	{
        dprintk("%s: tfm_desc already exist for this aead\n", __FUNCTION__);
        return pCurr;
    }

    pCurr = kzalloc(sizeof(icp_aead_tfm_desc_t), GFP_ATOMIC);
    if (NULL == pCurr)
	{
        printk("%s: unable to allocate memory\n", __FUNCTION__);
        return NULL;
    }

    pCurr->pAead = pAead;
	
	down_write(&tfm_desc_semaphore);
    ICP_ADD_ELEMENT_TO_END_OF_LIST(pCurr, g_pTfm_desc_list, g_pTfm_desc_list_head);
	up_write(&tfm_desc_semaphore);

    dprintk("%s: new tfm_desc added %p\n", __FUNCTION__, pCurr);
    return pCurr;
}


static struct crypto_alg aead_authenc_3des_hmac_sha1 = {
        .cra_name               =       "authenc(hmac(sha1),cbc(des3_ede))",
        .cra_driver_name        =       "icp_aead",
        .cra_priority           =       ICP_AES_ASYNC_PRIORITY,
        .cra_flags              =       CRYPTO_ALG_TYPE_AEAD|CRYPTO_ALG_GENIV|CRYPTO_ALG_ASYNC,
        .cra_blocksize          =       DES3_BLOCK_SIZE /*8*/,
        .cra_ctxsize            =       0,
        .cra_type               =       &crypto_aead_type,
        .cra_module             =       THIS_MODULE,
        .cra_list               =       LIST_HEAD_INIT(aead_authenc_3des_hmac_sha1.cra_list),
		.cra_exit               =       aead_auth_exit,
        .cra_u                  =       {
                .aead = {
			.ivsize       = DES3_BLOCK_SIZE /*8*/,
        	.maxauthsize  = SHA1_DIGEST_SIZE /*20*/,
			.setkey       = setkey_3des_hmac_sha1,
			.setauthsize  = qat_setauthsize,
			.encrypt      = encrypt_3des_hmac_sha1,
			.decrypt      = decrypt_3des_hmac_sha1,
			.givencrypt   = geniv_encrypt_3des_hmac_sha1,
			.givdecrypt   = geniv_decrypt_3des_hmac_sha1,
                }
        }
};


static struct crypto_alg aead_authenc_aes_cbc_hmac_sha1 = {
        .cra_name               =       "authenc(hmac(sha1),cbc(aes))",
        .cra_driver_name        =       "icp_aead",
        .cra_priority           =       ICP_AES_ASYNC_PRIORITY,
        .cra_flags              =       CRYPTO_ALG_TYPE_AEAD|CRYPTO_ALG_GENIV|CRYPTO_ALG_ASYNC,
        .cra_blocksize          =       AES_BLOCK_SIZE /*16*/,
        .cra_ctxsize            =       0,
        .cra_type               =       &crypto_aead_type,
        .cra_module             =       THIS_MODULE,
        .cra_list               =       LIST_HEAD_INIT(aead_authenc_aes_cbc_hmac_sha1.cra_list),
		.cra_exit               =       aead_auth_exit,
        .cra_u                  =       {
                .aead = {
			.ivsize       = AES_BLOCK_SIZE /*16*/,
        	.maxauthsize  = SHA1_DIGEST_SIZE /*20*/,
			.setkey       = setkey_aes_cbc_hmac_sha1,
			.setauthsize  = qat_setauthsize,
			.encrypt      = encrypt_aes_cbc_hmac_sha1,
			.decrypt      = decrypt_aes_cbc_hmac_sha1,
			.givencrypt   = geniv_encrypt_aes_cbc_hmac_sha1,
			.givdecrypt   = geniv_decrypt_aes_cbc_hmac_sha1,
                }
        }
};


static struct crypto_alg aead_authenc_aes_gcm = {
        .cra_name               =       "rfc4106(gcm(aes))",
        .cra_driver_name        =       "icp_aead",
        .cra_priority           =       ICP_AES_ASYNC_PRIORITY,
        .cra_flags              =       CRYPTO_ALG_TYPE_AEAD|CRYPTO_ALG_GENIV|CRYPTO_ALG_ASYNC,
        .cra_blocksize          =       AES_BLOCK_SIZE /*16*/,
        .cra_ctxsize            =       0,
        .cra_type               =       &crypto_aead_type,
        .cra_module             =       THIS_MODULE,
        .cra_list               =       LIST_HEAD_INIT(aead_authenc_aes_gcm.cra_list),
		.cra_exit               =       aead_auth_exit,
        .cra_u                  =       {
                .aead = {
			.ivsize       = AES_GCM_IV_SIZE, /*8*/
        	.maxauthsize  = AES_GCM_AUTH_TAG_LEN, /*16*/
			.setkey       = setkey_aes_gcm,
			.setauthsize  = qat_setauthsize,
			.encrypt      = encrypt_aes_gcm,
			.decrypt      = decrypt_aes_gcm,
			.givencrypt   = geniv_encrypt_aes_gcm,
			.givdecrypt   = geniv_decrypt_aes_gcm,
                }
        }
};

static int __init netkey_init(void)
{
    CpaStatus status = CPA_STATUS_SUCCESS;
	Cpa32U bufferListMetaSize = 0;
	int registerStatus =0;

	init_rwsem(&tfm_desc_semaphore);
		
    status = cpaCyStartInstance(CPA_INSTANCE_HANDLE_SINGLE);
    if (CPA_STATUS_SUCCESS != status) {
        printk("cpaCyStartInstance failed. (status = %d)\n", status);
        return -EPERM;
   }

    /* Determine the size of bufferlist pPrivateMetaData */
    status = cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE,
                                            ICP_MAX_NUM_BUFFERS,
                                            &bufferListMetaSize);
    if (CPA_STATUS_SUCCESS != status)
	{
        printk("cpaCyBufferListGetMetaSize failed. (status = %d)\n", status);
		status = cpaCyStopInstance(CPA_INSTANCE_HANDLE_SINGLE);
		if (CPA_STATUS_SUCCESS != status)
		{
             printk("cpaCyStopInstance failed. (status = %d)\n", status);
        }
        return -EPERM;
    }
    dprintk("%s: cpaCyBufferListGetMetaSize = %u\n", __FUNCTION__, bufferListMetaSize);

	/*
	 * Allocation of the OpData includes the allocation space for meta data.
	 * The memory after the opData structure is reserved for this meta data.
	 */

	pOpDataCache = kmem_cache_create("icp_opdata",
					sizeof(icp_aead_op_data_t),
					0, SLAB_HWCACHE_ALIGN,  NULL);
					
	if (NULL == pOpDataCache) {
		printk("%s: unable to allocate OpData cache\n", __FUNCTION__);
		status = cpaCyStopInstance(CPA_INSTANCE_HANDLE_SINGLE);
		if (CPA_STATUS_SUCCESS != status)
		{
             printk("cpaCyStopInstance failed. (status = %d)\n", status);
        }
		return -ENOMEM;
	}

	pMetaCache = kmem_cache_create("icp_meta",
				 bufferListMetaSize,
               			 0, SLAB_HWCACHE_ALIGN, NULL);
	if (NULL == pMetaCache) {
		printk("%s: unable to allocate OpData cache\n", __FUNCTION__);
		kmem_cache_destroy(pOpDataCache);
        pOpDataCache = NULL;
		status = cpaCyStopInstance(CPA_INSTANCE_HANDLE_SINGLE);
		if (CPA_STATUS_SUCCESS != status)
		{
            printk("cpaCyStopInstance failed. (status = %d)\n", status);
		}
		return -ENOMEM;
	}
	
	registerStatus = crypto_register_alg(&aead_authenc_3des_hmac_sha1);
	if (registerStatus != 0)
	{
		printk("Register alg failed for 3DES-HMAC_SHA1\n");
		kmem_cache_destroy(pOpDataCache);
		kmem_cache_destroy(pMetaCache);
		pOpDataCache = NULL;
        pMetaCache = NULL;
		return registerStatus;
	}	
	printk("3DES-HMAC_SHA1 loaded\n");
	
	registerStatus = crypto_register_alg(&aead_authenc_aes_cbc_hmac_sha1);
	if (registerStatus != 0)
	{
		printk("Register alg failed for AES-CBC-HMAC_SHA1\n");
		kmem_cache_destroy(pOpDataCache);
		kmem_cache_destroy(pMetaCache);
		pOpDataCache = NULL;
        pMetaCache = NULL;
		return registerStatus;
	}
	printk("AES-CBC-HMAC_SHA1 loaded\n");
	
	registerStatus = crypto_register_alg(&aead_authenc_aes_gcm);
	if (registerStatus !=0)
	{
		printk("Register alg failed for AES_GCM\n");
		kmem_cache_destroy(pOpDataCache);
		kmem_cache_destroy(pMetaCache);
		pOpDataCache = NULL;
        pMetaCache = NULL;
		return registerStatus;
	}
	printk("AES_GCM loaded\n");
	printk("%s: Intel ICP NetKey Loaded.\n", __FUNCTION__);
	
	return 0;
}

static void __exit netkey_exit(void)
{
    CpaStatus status = CPA_STATUS_SUCCESS;

	printk("%s: crypto_unregister_alg()\n", __FUNCTION__);
	if (crypto_unregister_alg(&aead_authenc_3des_hmac_sha1) != 0)
	{
		printk("Unable to unload 3DES-HMAC_SHA1\n");
	}
	if (crypto_unregister_alg(&aead_authenc_aes_cbc_hmac_sha1) != 0)
	{
		printk("Unable to unload AES-CBC-HMAC_SHA1\n");
	}
	
	if (crypto_unregister_alg(&aead_authenc_aes_gcm) != 0)
	{
		printk("Unable to unload AES_GCM\n");
	}
	
    status = cpaCyStopInstance(CPA_INSTANCE_HANDLE_SINGLE);
    if (CPA_STATUS_SUCCESS != status)
	{
        printk("cpaCyStopInstance failed. (status = %d)\n", status);
    }

     if (NULL != pOpDataCache)
	 {
        kmem_cache_destroy(pOpDataCache);
        pOpDataCache = NULL;
    }
    if (NULL != pMetaCache) {
         kmem_cache_destroy(pMetaCache);
         pMetaCache = NULL;
     }
	
	/* delete all the tfm descriptors */
	while (NULL != g_pTfm_desc_list_head) {
        del_tfm_desc(g_pTfm_desc_list_head->pAead);
    } 
    printk("%s: Intel ICP NetKey Unloaded.\n", __FUNCTION__);
	
}

module_init(netkey_init);
module_exit(netkey_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("QAT ICP NETKEY");
MODULE_AUTHOR("Intel");
---------------------------------------
Thank you very much.
Best regards,

Mario

-----Original Message-----
From: Herbert Xu [mailto:herbert@xxxxxxxxxxxxxxxxxxx] 
Sent: 01 April 2010 09:55
To: Nicolas, Mario
Cc: linux-crypto@xxxxxxxxxxxxxxx
Subject: Re: cra_priority usage

Nicolas, Mario <mario.nicolas@xxxxxxxxx> wrote:
> So my questions are: 
> -What is this variable used for?
> -If there are multiple implementations of the same algorithm, how is one version chosen as opposed to another one?

The one with the numerically higher priority will be used.  If
there are multiple implementations with the same priority, the
one registered last will be used.

> I guess that the reason is that an asynchronous version always has a higher priority than a synchronous one. Is that correct?

Actually this is probably a bug.  I'll have a look to see why this
is the case.  Can you please post your complete source?

Thanks,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@xxxxxxxxxxxxxxxxxxx>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--------------------------------------------------------------
Intel Shannon Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263
Business address: Dromore House, East Park, Shannon, Co. Clare

This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.


--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux