int wrapfs_write_lower_page_segment(struct inode *wrapfs_inode,
                                      struct page *page_for_lower,
                                      size_t offset_in_page, size_t size, 
                                      struct file *file)
{
        char *virt;
        loff_t offset;
        int rc = -1;

#ifdef WRAPFS_CRYPTO
        unsigned char *encrypted_page_buffer;
        struct crypto_cipher *tfm;
#endif

        offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
                  + offset_in_page);
        virt = kmap(page_for_lower);

#ifdef WRAPFS_CRYPTO
        encrypted_page_buffer = kmalloc(size, GFP_KERNEL); //free this
		if (encrypted_page_buffer == NULL)
			goto out;		
        memset(encrypted_page_buffer, 0, size);

        tfm = crypto_alloc_cipher("aes", 0, 16);
        if (!IS_ERR(tfm))
                crypto_cipher_setkey(tfm, WRAPFS_SB(file->f_dentry->d_sb)->key, 16);
		else
				goto fail;

        crypto_cipher_encrypt_one(tfm, encrypted_page_buffer, virt);
        /*printk(KERN_ALERT "Encrypted buffer = %s\n", encrypted_page_buffer);*/
	    /*memcpy(virt, encrypted_page_buffer, size);*/

        rc = wrapfs_write_lower(wrapfs_inode, encrypted_page_buffer, offset, size, file);
#else
		rc = wrapfs_write_lower(wrapfs_inode, virt, offset, size, file);
#endif

        if (rc > 0)
                rc = 0;
        kunmap(page_for_lower);
#ifdef WRAPFS_CRYPTO
	crypto_free_cipher(tfm);
fail:
		kfree(encrypted_page_buffer);
out:
#endif
        return rc;
}
Beispiel #2
0
static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key,
			     unsigned int keylen)
{
	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(parent);
	struct crypto_cipher *child = ctx->child;
	int err;

	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
				       CRYPTO_TFM_REQ_MASK);
	err = crypto_cipher_setkey(child, key, keylen);
	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
				     CRYPTO_TFM_RES_MASK);
	return err;
}
Beispiel #3
0
/* Wipe salt and reset key derived from volume key */
static int crypt_iv_essiv_wipe(struct crypt_config *cc)
{
    struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
    unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
    struct crypto_cipher *essiv_tfm;
    int r, err = 0;

    memset(essiv->salt, 0, salt_size);

    essiv_tfm = cc->iv_private;
    r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size);
    if (r)
        err = r;

    return err;
}
/*
 * Handle an I/O request.
 */
static void sbd_transfer(struct sbd_device *dev, sector_t sector,
		unsigned long nsect, char *buffer, int write) {
	unsigned long offset = sector * logical_block_size;
	unsigned long nbytes = nsect * logical_block_size;

	int k;
  printk("Before decryption "); //added
  printk("\n");
  printing(buffer,nbytes); //added
  printk("\n");
  key_size = strlen(key); //added
	if(key_size == 0){
		printk(KERN_INFO "no key set\n");
	}else{
		crypto_cipher_clear_flags(tfm, ~0);
		crypto_cipher_setkey(tfm, crypto_key, key_size);
	}

	if ((offset + nbytes) > dev->size) {
		printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes);
		return;
	}
	if (write){
    printing(buffer, nbytes);
    printk("\n");
		if(key_size != 0){
			for (k = 0; k < nbytes; k+= crypto_cipher_blocksize(tfm)) {
				crypto_cipher_encrypt_one(tfm, dev->data+offset+k, buffer+k);
			}
		}else{
			memcpy(dev->data + offset, buffer, nbytes);
		}
	}else{
		if(key_size != 0){
			for (k = 0; k < nbytes; k+= crypto_cipher_blocksize(tfm)) {
				crypto_cipher_decrypt_one(tfm, buffer+k, dev->data+offset+k);
			}
		}else{
			memcpy(buffer, dev->data + offset, nbytes);
		}
	}
  printk("Decrypted ");
  printk("\n");
  printing(buffer,nbytes);
  printk("\n");
}
Beispiel #5
0
/* Initialise ESSIV - compute salt but no local memory allocations */
static int crypt_iv_essiv_init(struct crypt_config *cc)
{
	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
	struct hash_desc desc;
	struct scatterlist sg;
	int err;

	sg_init_one(&sg, cc->key, cc->key_size);
	desc.tfm = essiv->hash_tfm;
	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;

	err = crypto_hash_digest(&desc, &sg, cc->key_size, essiv->salt);
	if (err)
		return err;

	return crypto_cipher_setkey(essiv->tfm, essiv->salt,
				    crypto_hash_digestsize(essiv->hash_tfm));
}
Beispiel #6
0
static int setkey_fallback_cip(struct crypto_tfm *tfm, const u8 *in_key,
		unsigned int key_len)
{
	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
	int ret;

	sctx->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
	sctx->fallback.cip->base.crt_flags |= (tfm->crt_flags &
			CRYPTO_TFM_REQ_MASK);

	ret = crypto_cipher_setkey(sctx->fallback.cip, in_key, key_len);
	if (ret) {
		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
		tfm->crt_flags |= (sctx->fallback.cip->base.crt_flags &
				CRYPTO_TFM_RES_MASK);
	}
	return ret;
}
Beispiel #7
0
static int param_set_cipher_key(const char *val, struct kernel_param *kp)
{
	struct crypto_cipher *new_cipher;
	int key_len;
	u8 key[128];
	int err = 0;

	/* Try to convert the user's key to raw bytes. */
	key_len = parse_hex_string(val, key, ARRAY_SIZE(key));
	if (key_len < 0) {
		printk(KERN_INFO "stubl: Can't parse key.\n");
		return key_len;
	}

	/* If the key is empty, then clear it. */
	if (key_len == 0) {
		printk(KERN_INFO "stubl: Clearing tunnel key.\n");
		update_cipher(kp->arg, NULL);
		return 0;
	} 

	printk(KERN_INFO "stubl: Setting tunnel key.\n");

	/* Init a new cipher */
	new_cipher = crypto_alloc_cipher("blowfish", 0, 0);
	if (IS_ERR(new_cipher)) {
		printk(KERN_INFO "stubl: Can't init cipher: %ld\n",
				PTR_ERR(new_cipher));
		return PTR_ERR(new_cipher);
	}

	/* Set key */
	err = crypto_cipher_setkey(new_cipher, key, key_len);
	if (err < 0) {
		printk(KERN_INFO "stubl: Can't set key: %d\n", err);
		crypto_free_cipher(new_cipher);
		return err;
	}

	/* Perform RCU update */
	update_cipher(kp->arg, new_cipher);

	return 0;
}
Beispiel #8
0
static inline const void *
get_key(const void *p, const void *end, struct crypto_tfm **res)
{
	struct xdr_netobj	key;
	int			alg, alg_mode;
	char			*alg_name;

	p = simple_get_bytes(p, end, &alg, sizeof(alg));
	if (IS_ERR(p))
		goto out_err;
	p = simple_get_netobj(p, end, &key);
	if (IS_ERR(p))
		goto out_err;

	switch (alg) {
		case ENCTYPE_DES_CBC_RAW:
			alg_name = "des";
			alg_mode = CRYPTO_TFM_MODE_CBC;
			break;
		default:
			printk("gss_kerberos_mech: unsupported algorithm %d\n", alg);
			goto out_err_free_key;
	}
	if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) {
		printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name);
		goto out_err_free_key;
	}
	if (crypto_cipher_setkey(*res, key.data, key.len)) {
		printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name);
		goto out_err_free_tfm;
	}

	kfree(key.data);
	return p;

out_err_free_tfm:
	crypto_free_tfm(*res);
out_err_free_key:
	kfree(key.data);
	p = ERR_PTR(-EINVAL);
out_err:
	return p;
}
static int setkey(struct crypto_tfm *parent, const u8 *key,
		  unsigned int keylen)
{
	struct priv *ctx = crypto_tfm_ctx(parent);
	struct crypto_cipher *child = ctx->child;
	int err, bsize = LRW_BLOCK_SIZE;
	const u8 *tweak = key + keylen - bsize;

	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
				       CRYPTO_TFM_REQ_MASK);
	err = crypto_cipher_setkey(child, key, keylen - bsize);
	if (err)
		return err;
	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
				     CRYPTO_TFM_RES_MASK);

	return lrw_init_table(&ctx->table, tweak);
}
Beispiel #10
0
static int reset_prng_context(struct prng_context *ctx,
			      unsigned char *key, size_t klen,
			      unsigned char *V, unsigned char *DT)
{
	int ret;
	unsigned char *prng_key;

	spin_lock_bh(&ctx->prng_lock);
	ctx->flags |= PRNG_NEED_RESET;

	prng_key = (key != NULL) ? key : (unsigned char *)DEFAULT_PRNG_KEY;

	if (!key)
		klen = DEFAULT_PRNG_KSZ;

	if (V)
		memcpy(ctx->V, V, DEFAULT_BLK_SZ);
	else
		memcpy(ctx->V, DEFAULT_V_SEED, DEFAULT_BLK_SZ);

	if (DT)
		memcpy(ctx->DT, DT, DEFAULT_BLK_SZ);
	else
		memset(ctx->DT, 0, DEFAULT_BLK_SZ);

	memset(ctx->rand_data, 0, DEFAULT_BLK_SZ);
	memset(ctx->last_rand_data, 0, DEFAULT_BLK_SZ);

	ctx->rand_data_valid = DEFAULT_BLK_SZ;

	ret = crypto_cipher_setkey(ctx->tfm, prng_key, klen);
	if (ret) {
		dbgprint(KERN_CRIT "PRNG: setkey() failed flags=%x\n",
			crypto_cipher_get_flags(ctx->tfm));
		goto out;
	}

	ret = 0;
	ctx->flags &= ~PRNG_NEED_RESET;
out:
	spin_unlock_bh(&ctx->prng_lock);
	return ret;
}
Beispiel #11
0
static int crypto_ecb_setkey(struct crypto_tfm *parent, const u8 *key,
                             unsigned int keylen)
{
    struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(parent);
    struct crypto_cipher *child = ctx->child;
    int err;

    crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
    crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
                            CRYPTO_TFM_REQ_MASK);
    err = crypto_cipher_setkey(child, key, keylen);
    crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
                         CRYPTO_TFM_RES_MASK);
#ifdef CONFIG_CRYPTO_DEV_REALTEK
    if (err == 0)
        err = rtl_cipher_setkey(child, &ctx->rtl_ctx, key, keylen);
#endif
    return err;
}
Beispiel #12
0
/* Perform WEP decryption using given key. data buffer includes encrypted
 * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
 * Return 0 on success and -1 on ICV mismatch.
 */
int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
			       size_t klen, u8 *data, size_t data_len)
{
	__le32 crc;
	int i;

	if (IS_ERR(tfm))
		return -1;

	crypto_cipher_setkey(tfm, rc4key, klen);
	for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
		crypto_cipher_decrypt_one(tfm, data + i, data + i);

	crc = cpu_to_le32(~crc32_le(~0, data, data_len));
	if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
		/* ICV mismatch */
		return -1;

	return 0;
}
Beispiel #13
0
/*
 * Basic transfer function called by other functions for transfering
 * data from the RAM disk block. Calls the appropriate encrypt and
 * decrypt functions from crytpo. Also calls hexdump in order to
 * dump the entirety of the data to the kernel.
 */
static void osurd_transfer(struct osurd_dev *dev, unsigned long sector,
                           unsigned long nsect, char *buffer, int write)
{
    unsigned long offset = sector *KERNEL_SECTOR_SIZE;
    unsigned long nbytes = nsect *KERNEL_SECTOR_SIZE;
    int i;

    if((offset + nbytes) > dev->size) {
        printk(KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
        return;
    }

    crypto_cipher_clear_flags(tfm, ~0);
    crypto_cipher_setkey(tfm, key, strlen(key));

    if(write) {
        printk("Writing to RAM disk\n");
        printk("Pre-encrypted data: ");
        hexdump(buffer, nbytes);

        for(i = 0; i < nbytes; i += crypto_cipher_blocksize(tfm)) {
            memset(dev->data + offset +i, 0, crypto_cipher_blocksize(tfm));
            crypto_cipher_encrypt_one(tfm, dev->data + offset + i, buffer + i);
        }

        printk("Encrypted data: ");
        hexdump(dev->data + offset, nbytes);
    }
    else {
        printk("Reading from RAM disk\n");
        printk("Encrypted data: ");
        hexdump(dev->data + offset, nbytes);

        for(i = 0; i < nbytes; i += crypto_cipher_blocksize(tfm)) {
            crypto_ckpher_decrypt_one(tfm, buffer + i, dev->data + offset + i);
        }

        printk("Decrypted data: ");
        hexdump(buffer, nbytes);
    }
}
Beispiel #14
0
int tcp_fastopen_reset_cipher(void *key, unsigned int len)
{
    int err;
    struct tcp_fastopen_context *ctx, *octx;

    ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
    if (!ctx)
        return -ENOMEM;
    ctx->tfm = crypto_alloc_cipher("aes", 0, 0);

    if (IS_ERR(ctx->tfm)) {
        err = PTR_ERR(ctx->tfm);
error:
        kfree(ctx);
        pr_err("TCP: TFO aes cipher alloc error: %d\n", err);
        return err;
    }
    err = crypto_cipher_setkey(ctx->tfm, key, len);
    if (err) {
        pr_err("TCP: TFO cipher key error: %d\n", err);
        crypto_free_cipher(ctx->tfm);
        goto error;
    }
    memcpy(ctx->key, key, len);

    spin_lock(&tcp_fastopen_ctx_lock);

    octx = rcu_dereference_protected(tcp_fastopen_ctx,
                                     lockdep_is_held(&tcp_fastopen_ctx_lock));
    rcu_assign_pointer(tcp_fastopen_ctx, ctx);
    spin_unlock(&tcp_fastopen_ctx_lock);

    if (octx)
        call_rcu(&octx->rcu, tcp_fastopen_ctx_free);
    return err;
}
Beispiel #15
0
static int
rfc4106_set_hash_subkey(u8 *hash_subkey, const u8 *key, unsigned int key_len)
{
	struct crypto_cipher *tfm;
	int ret;

	tfm = crypto_alloc_cipher("aes", 0, 0);
	if (IS_ERR(tfm))
		return PTR_ERR(tfm);

	ret = crypto_cipher_setkey(tfm, key, key_len);
	if (ret)
		goto out_free_cipher;

	/* Clear the data in the hash sub key container to zero.*/
	/* We want to cipher all zeros to create the hash sub key. */
	memset(hash_subkey, 0, RFC4106_HASH_SUBKEY_SIZE);

	crypto_cipher_encrypt_one(tfm, hash_subkey, hash_subkey);

out_free_cipher:
	crypto_free_cipher(tfm);
	return ret;
}
v_BOOL_t vos_is_mmie_valid(v_U8_t *igtk, v_U8_t *ipn,
                           v_U8_t* frm, v_U8_t* efrm)
{
    struct ieee80211_mmie  *mmie;
    struct ieee80211_frame *wh;
    v_U8_t *rx_ipn, aad[AAD_LEN], mic[CMAC_TLEN], *input;
    v_U16_t nBytes = 0;
    int ret = 0;
    struct crypto_cipher *tfm;

    /* Check if frame is invalid length */
    if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                "Invalid frame length");
        return VOS_FALSE;
    }

    mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie));

    /* Check Element ID */
    if ((mmie->element_id != IEEE80211_ELEMID_MMIE) ||
        (mmie->length != (sizeof(*mmie)-2))) {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                "IE is not Mgmt MIC IE or Invalid length");
        /* IE is not Mgmt MIC IE or invalid length */
        return VOS_FALSE;
    }

    /* Validate IPN */
    rx_ipn = mmie->sequence_number;
    if (OS_MEMCMP(rx_ipn, ipn, CMAC_IPN_LEN) <= 0)
    {
        /* Replay error */
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
            "Replay error mmie ipn %02X %02X %02X %02X %02X %02X"
            " drvr ipn %02X %02X %02X %02X %02X %02X",
            rx_ipn[0], rx_ipn[1], rx_ipn[2], rx_ipn[3], rx_ipn[4], rx_ipn[5],
            ipn[0], ipn[1], ipn[2], ipn[3], ipn[4], ipn[5]);
        return VOS_FALSE;
    }

#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
    tfm = crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
#else
    tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
#endif
    if (IS_ERR(tfm)) {
        ret = PTR_ERR(tfm);
        tfm = NULL;
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,
             "crypto_alloc_cipher failed (%d)", ret);
        goto err_tfm;
    }

    ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128);
    if (ret) {
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,
             "crypto_cipher_setkey failed (%d)", ret);
        goto err_tfm;
    }

    /* Construct AAD */
    wh = (struct ieee80211_frame *)frm;

    /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */

    /* FC type/subtype */
    aad[0] = wh->i_fc[0];
    /* Mask FC Retry, PwrMgt, MoreData flags to zero */
    aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
                             IEEE80211_FC1_MORE_DATA);
    /* A1 || A2 || A3 */
    vos_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN);

    /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */
    nBytes = AAD_LEN + (efrm - (v_U8_t*)(wh+1));
    input = (v_U8_t *)vos_mem_malloc(nBytes);
    if (NULL == input)
    {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
             "Memory allocation failed");
        ret = VOS_STATUS_E_NOMEM;
        goto err_tfm;
    }

    /* Copy the AAD, MMIE with 8 bit MIC zeroed out */
    vos_mem_zero(input, nBytes);
    vos_mem_copy(input, aad, AAD_LEN);
    vos_mem_copy(input+AAD_LEN, (v_U8_t*)(wh+1), nBytes - AAD_LEN - CMAC_TLEN);

#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
    cmac_calc_mic(tfm, input, nBytes, mic);
#else
    wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic);
#endif
    vos_mem_free(input);

    VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
            "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X",
            mic[0], mic[1], mic[2], mic[3],
            mic[4], mic[5], mic[6], mic[7]);

    if (OS_MEMCMP(mic, mmie->mic, CMAC_TLEN) != 0) {
        /* MMIE MIC mismatch */
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                "BC/MC MGMT frame MMIE MIC check Failed"
                " rmic %02X %02X %02X %02X %02X %02X %02X %02X"
                " cmic %02X %02X %02X %02X %02X %02X %02X %02X",
                mmie->mic[0], mmie->mic[1], mmie->mic[2], mmie->mic[3],
                mmie->mic[4], mmie->mic[5], mmie->mic[6], mmie->mic[7],
                mic[0], mic[1], mic[2], mic[3],
                mic[4], mic[5], mic[6], mic[7]);
        return VOS_FALSE;
    }

    /* Update IPN */
    vos_mem_copy(ipn, rx_ipn, CMAC_IPN_LEN);

err_tfm:
    if (tfm)
#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
        crypto_free_cipher(tfm);
#else
        wcnss_wlan_crypto_free_cipher(tfm);
#endif

    return !ret?VOS_TRUE:VOS_FALSE;
}
v_BOOL_t
vos_attach_mmie(v_U8_t *igtk, v_U8_t *ipn, u_int16_t key_id,
                v_U8_t* frm, v_U8_t* efrm, u_int16_t frmLen)
{
    struct ieee80211_mmie  *mmie;
    struct ieee80211_frame *wh;
    v_U8_t aad[AAD_LEN], mic[CMAC_TLEN], *input = NULL;
    v_U8_t previous_ipn[IEEE80211_MMIE_IPNLEN] = {0};
    v_U16_t nBytes = 0;
    int ret = 0;
    struct crypto_cipher *tfm;

    /*  This is how received frame look like
     *
     *        <------------frmLen---------------------------->
     *
     *        +---------------+----------------------+-------+
     *        | 802.11 HEADER | Management framebody | MMIE  |
     *        +---------------+----------------------+-------+
     *                                                       ^
     *                                                       |
     *                                                      efrm
     *   This is how MMIE from above frame look like
     *
     *
     *        <------------ 18 Bytes----------------------------->
     *        +--------+---------+---------+-----------+---------+
     *        |Element | Length  | Key id  |   IPN     |  MIC    |
     *        |  id    |         |         |           |         |
     *        +--------+---------+---------+-----------+---------+
     * Octet     1         1         2         6            8
     *
     */

    /* Check if frame is invalid length */
    if (((efrm - frm) != frmLen) || (frmLen < sizeof(*wh)))
    {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                  "%s: Invalid frame length", __func__);
        return VOS_FALSE;
    }
    mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie));

    /* Copy Element id */
    mmie->element_id = IEEE80211_ELEMID_MMIE;

    /* Copy Length */
    mmie->length = sizeof(*mmie)-2;

    /* Copy Key id */
    mmie->key_id = key_id;

    /*
     * In case of error, revert back to original IPN
     * to do that copy the original IPN into previous_ipn
     */
    vos_mem_copy(&previous_ipn[0], ipn, IEEE80211_MMIE_IPNLEN);
    vos_increase_seq(ipn);
    vos_mem_copy(mmie->sequence_number, ipn, IEEE80211_MMIE_IPNLEN);

    /*
     * Calculate MIC and then copy
     */
#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
    tfm = crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
#else
    tfm = wcnss_wlan_crypto_alloc_cipher( "aes", 0, CRYPTO_ALG_ASYNC);
#endif
    if (IS_ERR(tfm))
    {
        ret = PTR_ERR(tfm);
        tfm = NULL;
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,
             "%s: crypto_alloc_cipher failed (%d)", __func__, ret);
        goto err_tfm;
    }

    ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128);
    if (ret) {
        VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,
             "%s: crypto_cipher_setkey failed (%d)", __func__, ret);
        goto err_tfm;
    }

    /* Construct AAD */
    wh = (struct ieee80211_frame *)frm;

    /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */

    /* FC type/subtype */
    aad[0] = wh->i_fc[0];
    /* Mask FC Retry, PwrMgt, MoreData flags to zero */
    aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
                             IEEE80211_FC1_MORE_DATA);
    /* A1 || A2 || A3 */
    vos_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN);

    /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */
    nBytes = AAD_LEN + (frmLen - sizeof(struct ieee80211_frame));
    input = (v_U8_t *)vos_mem_malloc(nBytes);
    if (NULL == input)
    {
        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
                  "%s: Memory allocation failed", __func__);
        ret = VOS_STATUS_E_NOMEM;
        goto err_tfm;
    }

    /*
     * Copy the AAD, Management frame body, and
     * MMIE with 8 bit MIC zeroed out
     */
    vos_mem_zero(input, nBytes);
    vos_mem_copy(input, aad, AAD_LEN);
    /* Copy Management Frame Body and MMIE without MIC*/
    vos_mem_copy(input+AAD_LEN,
                (v_U8_t*)(efrm-(frmLen-sizeof(struct ieee80211_frame))),
                nBytes - AAD_LEN - CMAC_TLEN);

#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
    cmac_calc_mic(tfm, input, nBytes, mic);
#else
    wcnss_wlan_cmac_calc_mic(tfm, input, nBytes, mic);
#endif
    vos_mem_free(input);

    VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
            "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X",
            mic[0], mic[1], mic[2], mic[3],
            mic[4], mic[5], mic[6], mic[7]);
    vos_mem_copy(mmie->mic, mic, IEEE80211_MMIE_MICLEN);


err_tfm:
    if (ret)
    {
       vos_mem_copy(ipn, previous_ipn, IEEE80211_MMIE_IPNLEN);
    }

    if (tfm)
#if  !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO))
       crypto_free_cipher(tfm);
#else
       wcnss_wlan_crypto_free_cipher(tfm);
#endif
    return !ret?VOS_TRUE:VOS_FALSE;
}
Beispiel #18
0
static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
	struct prism2_wep_data *wep = priv;
	u32 klen, len;
	u8 key[WEP_KEY_LEN + 3];
	u8 *pos;
	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
	#if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED))
	struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
	#endif
	u32 crc;
	u8 *icv;
	struct scatterlist sg;
	if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
	    skb->len < hdr_len)
		return -1;

	len = skb->len - hdr_len;
	pos = skb_push(skb, 4);
	memmove(pos, pos + 4, hdr_len);
	pos += hdr_len;

	klen = 3 + wep->key_len;

	wep->iv++;

	
	if ((wep->iv & 0xff00) == 0xff00) {
		u8 B = (wep->iv >> 16) & 0xff;
		if (B >= 3 && B < klen)
			wep->iv += 0x0100;
	}

	
	*pos++ = key[0] = (wep->iv >> 16) & 0xff;
	*pos++ = key[1] = (wep->iv >> 8) & 0xff;
	*pos++ = key[2] = wep->iv & 0xff;
	*pos++ = wep->key_idx << 6;

	
	memcpy(key + 3, wep->key, wep->key_len);

	if (!tcb_desc->bHwSec)
	{

		
	#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
		crc = ~crc32_le(~0, pos, len);
	#else
		crc = ~ether_crc_le(len, pos);
	#endif
		icv = skb_put(skb, 4);
		icv[0] = crc;
		icv[1] = crc >> 8;
		icv[2] = crc >> 16;
		icv[3] = crc >> 24;

#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
		crypto_cipher_setkey(wep->tfm, key, klen);
		sg.page = virt_to_page(pos);
		sg.offset = offset_in_page(pos);
		sg.length = len + 4;
		crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
		return 0;
	#else
		crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
	#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
		sg.page = virt_to_page(pos);
		sg.offset = offset_in_page(pos);
		sg.length = len + 4;
	#else
		sg_init_one(&sg, pos, len+4);
	#endif
		return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
	#endif
	}
Beispiel #19
0
static int esp6_init_state(struct xfrm_state *x)
{
	struct esp_data *esp = NULL;

	/* null auth and encryption can have zero length keys */
	if (x->aalg) {
		if (x->aalg->alg_key_len > 512)
			goto error;
	}
	if (x->ealg == NULL || (x->ealg->alg_key_len == 0 && x->props.ealgo != SADB_EALG_NULL))
		goto error;

	if (x->encap)
		goto error;

	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
	if (esp == NULL)
		return -ENOMEM;

	memset(esp, 0, sizeof(*esp));

	if (x->aalg) {
		struct xfrm_algo_desc *aalg_desc;
		unsigned int digestsize;
		u32 mode = 0;

		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
		BUG_ON(!aalg_desc);

#ifdef CONFIG_CRYPTO_XCBC
		mode = aalg_desc->desc.sadb_alg_id == SADB_X_AALG_AES_XCBC_MAC ?
			CRYPTO_TFM_MODE_CBC : 0;
#endif

		esp->auth.key = x->aalg->alg_key;
		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
		esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, mode);
		if (esp->auth.tfm == NULL)
			goto error;
#ifdef CONFIG_CRYPTO_XCBC
		esp->auth.icv = !mode ? esp_hmac_digest : esp_xcbc_digest;
#else
		esp->auth.icv = esp_hmac_digest;
#endif

		digestsize = !mode ? crypto_tfm_alg_digestsize(esp->auth.tfm) :
			crypto_tfm_alg_blocksize(esp->auth.tfm);

		if (aalg_desc->uinfo.auth.icv_fullbits/8 != digestsize) {
				printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
					x->aalg->alg_name,
				       digestsize,
					aalg_desc->uinfo.auth.icv_fullbits/8);
				goto error;
		}
 
		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
 
		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
		if (!esp->auth.work_icv)
			goto error;
	}
	esp->conf.key = x->ealg->alg_key;
	if (x->props.ealgo == SADB_EALG_NULL) {
		esp->conf.key_len = 0;
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB);
	} else {
		esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
	}
	if (esp->conf.tfm == NULL)
		goto error;
	esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
	esp->conf.padlen = 0;
	if (esp->conf.ivlen) {
		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
		if (unlikely(esp->conf.ivec == NULL))
			goto error;
		get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
	}
	if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len))
		goto error;
	x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
	if (x->props.mode)
		x->props.header_len += sizeof(struct ipv6hdr);
	x->data = esp;
	return 0;

error:
	x->data = esp;
	esp6_destroy(x);
	x->data = NULL;
	return -EINVAL;
}
/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
 * so the payload length increases with 8 bytes.
 *
 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
 */
static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
	struct prism2_wep_data *wep = priv;
	u32 klen, len;
	u8 key[WEP_KEY_LEN + 3];
	u8 *pos;
	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
	#if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) )
	struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
	#endif
	u32 crc;
	u8 *icv;
#ifdef _RTL8192_EXT_PATCH_	
	u8 broadcastaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
	struct rtllib_hdr_3addr* tmp_header = (struct rtllib_hdr_3addr*)(skb->data);
	u8 is_broadcast_data = 0;
	u8 is_multicast_data = 0;
#endif
	struct scatterlist sg;
	if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
	    skb->len < hdr_len){
		printk("Error!!!headroom=%d tailroom=%d skblen=%d hdr_len=%d\n",skb_headroom(skb),skb_tailroom(skb),skb->len,hdr_len);
		return -1;
	}
#ifdef _RTL8192_EXT_PATCH_	
	if(tcb_desc->badhoc==0){
		if(memcmp(tmp_header->addr1,broadcastaddr,6) == 0){
			is_broadcast_data = 1;
			tcb_desc->bHwSec = 0;
		}
		if(is_multicast_ether_addr(tmp_header->addr1)){
			is_multicast_data = 1;
			tcb_desc->bHwSec = 0;
		}
	}
#endif
	len = skb->len - hdr_len;
	pos = skb_push(skb, 4);
	memmove(pos, pos + 4, hdr_len);
	pos += hdr_len;

	klen = 3 + wep->key_len;

	wep->iv++;

	/* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
	 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
	 * can be used to speedup attacks, so avoid using them. */
	if ((wep->iv & 0xff00) == 0xff00) {
		u8 B = (wep->iv >> 16) & 0xff;
		if (B >= 3 && B < klen)
			wep->iv += 0x0100;
	}

	/* Prepend 24-bit IV to RC4 key and TX frame */
	*pos++ = key[0] = (wep->iv >> 16) & 0xff;
	*pos++ = key[1] = (wep->iv >> 8) & 0xff;
	*pos++ = key[2] = wep->iv & 0xff;
	*pos++ = wep->key_idx << 6;

	/* Copy rest of the WEP key (the secret part) */
	memcpy(key + 3, wep->key, wep->key_len);

	if (!tcb_desc->bHwSec)
	{
	
		/* Append little-endian CRC32 and encrypt it to produce ICV */
	#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
		crc = ~crc32_le(~0, pos, len);
	#else
		crc = ~ether_crc_le(len, pos);
	#endif
		icv = skb_put(skb, 4);
		icv[0] = crc;
		icv[1] = crc >> 8;
		icv[2] = crc >> 16;
		icv[3] = crc >> 24;
		
	#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
		sg.page = virt_to_page(pos);
		sg.offset = offset_in_page(pos);
		sg.length = len + 4;
	#else
		sg_init_one(&sg, pos, len+4);
	#endif
	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
		crypto_cipher_setkey(wep->tfm, key, klen);
		crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
		return 0;
	#else
		crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
		return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
	#endif
	}
static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
		       struct scatterlist *src, unsigned int nbytes)
{
	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
	be128 buf[8];
	struct xts_crypt_req req = {
		.tbuf = buf,
		.tbuflen = sizeof(buf),

		.tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
		.tweak_fn = aesni_xts_tweak,
		.crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
		.crypt_fn = lrw_xts_encrypt_callback,
	};
	int ret;

	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;

	kernel_fpu_begin();
	ret = xts_crypt(desc, dst, src, nbytes, &req);
	kernel_fpu_end();

	return ret;
}

static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
		       struct scatterlist *src, unsigned int nbytes)
{
	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
	be128 buf[8];
	struct xts_crypt_req req = {
		.tbuf = buf,
		.tbuflen = sizeof(buf),

		.tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
		.tweak_fn = aesni_xts_tweak,
		.crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
		.crypt_fn = lrw_xts_decrypt_callback,
	};
	int ret;

	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;

	kernel_fpu_begin();
	ret = xts_crypt(desc, dst, src, nbytes, &req);
	kernel_fpu_end();

	return ret;
}

#endif

#ifdef CONFIG_X86_64
static int rfc4106_init(struct crypto_aead *aead)
{
	struct cryptd_aead *cryptd_tfm;
	struct cryptd_aead **ctx = crypto_aead_ctx(aead);

	cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni",
				       CRYPTO_ALG_INTERNAL,
				       CRYPTO_ALG_INTERNAL);
	if (IS_ERR(cryptd_tfm))
		return PTR_ERR(cryptd_tfm);

	*ctx = cryptd_tfm;
	crypto_aead_set_reqsize(aead, crypto_aead_reqsize(&cryptd_tfm->base));
	return 0;
}

static void rfc4106_exit(struct crypto_aead *aead)
{
	struct cryptd_aead **ctx = crypto_aead_ctx(aead);

	cryptd_free_aead(*ctx);
}

static int
rfc4106_set_hash_subkey(u8 *hash_subkey, const u8 *key, unsigned int key_len)
{
	struct crypto_cipher *tfm;
	int ret;

	tfm = crypto_alloc_cipher("aes", 0, 0);
	if (IS_ERR(tfm))
		return PTR_ERR(tfm);

	ret = crypto_cipher_setkey(tfm, key, key_len);
	if (ret)
		goto out_free_cipher;

	/* Clear the data in the hash sub key container to zero.*/
	/* We want to cipher all zeros to create the hash sub key. */
	memset(hash_subkey, 0, RFC4106_HASH_SUBKEY_SIZE);

	crypto_cipher_encrypt_one(tfm, hash_subkey, hash_subkey);

out_free_cipher:
	crypto_free_cipher(tfm);
	return ret;
}

static int common_rfc4106_set_key(struct crypto_aead *aead, const u8 *key,
				  unsigned int key_len)
{
	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(aead);

	if (key_len < 4) {
		crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
		return -EINVAL;
	}
	/*Account for 4 byte nonce at the end.*/
	key_len -= 4;

	memcpy(ctx->nonce, key + key_len, sizeof(ctx->nonce));

	return aes_set_key_common(crypto_aead_tfm(aead),
				  &ctx->aes_key_expanded, key, key_len) ?:
	       rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len);
}

static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
			   unsigned int key_len)
{
	struct cryptd_aead **ctx = crypto_aead_ctx(parent);
	struct cryptd_aead *cryptd_tfm = *ctx;

	return crypto_aead_setkey(&cryptd_tfm->base, key, key_len);
}

static int common_rfc4106_set_authsize(struct crypto_aead *aead,
				       unsigned int authsize)
{
	switch (authsize) {
	case 8:
	case 12:
	case 16:
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

/* This is the Integrity Check Value (aka the authentication tag length and can
 * be 8, 12 or 16 bytes long. */
static int rfc4106_set_authsize(struct crypto_aead *parent,
				unsigned int authsize)
{
	struct cryptd_aead **ctx = crypto_aead_ctx(parent);
	struct cryptd_aead *cryptd_tfm = *ctx;

	return crypto_aead_setauthsize(&cryptd_tfm->base, authsize);
}

static int helper_rfc4106_encrypt(struct aead_request *req)
{
	u8 one_entry_in_sg = 0;
	u8 *src, *dst, *assoc;
	__be32 counter = cpu_to_be32(1);
	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
	void *aes_ctx = &(ctx->aes_key_expanded);
	unsigned long auth_tag_len = crypto_aead_authsize(tfm);
	u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
	struct scatter_walk src_sg_walk;
	struct scatter_walk dst_sg_walk = {};
	unsigned int i;

	/* Assuming we are supporting rfc4106 64-bit extended */
	/* sequence numbers We need to have the AAD length equal */
	/* to 16 or 20 bytes */
	if (unlikely(req->assoclen != 16 && req->assoclen != 20))
		return -EINVAL;

	/* IV below built */
	for (i = 0; i < 4; i++)
		*(iv+i) = ctx->nonce[i];
	for (i = 0; i < 8; i++)
		*(iv+4+i) = req->iv[i];
	*((__be32 *)(iv+12)) = counter;

	if (sg_is_last(req->src) &&
	    req->src->offset + req->src->length <= PAGE_SIZE &&
	    sg_is_last(req->dst) &&
	    req->dst->offset + req->dst->length <= PAGE_SIZE) {
		one_entry_in_sg = 1;
		scatterwalk_start(&src_sg_walk, req->src);
		assoc = scatterwalk_map(&src_sg_walk);
		src = assoc + req->assoclen;
		dst = src;
		if (unlikely(req->src != req->dst)) {
			scatterwalk_start(&dst_sg_walk, req->dst);
			dst = scatterwalk_map(&dst_sg_walk) + req->assoclen;
		}
	} else {
		/* Allocate memory for src, dst, assoc */
		assoc = kmalloc(req->cryptlen + auth_tag_len + req->assoclen,
			GFP_ATOMIC);
		if (unlikely(!assoc))
			return -ENOMEM;
		scatterwalk_map_and_copy(assoc, req->src, 0,
					 req->assoclen + req->cryptlen, 0);
		src = assoc + req->assoclen;
		dst = src;
	}

	kernel_fpu_begin();
	aesni_gcm_enc_tfm(aes_ctx, dst, src, req->cryptlen, iv,
			  ctx->hash_subkey, assoc, req->assoclen - 8,
			  dst + req->cryptlen, auth_tag_len);
	kernel_fpu_end();

	/* The authTag (aka the Integrity Check Value) needs to be written
	 * back to the packet. */
	if (one_entry_in_sg) {
		if (unlikely(req->src != req->dst)) {
			scatterwalk_unmap(dst - req->assoclen);
			scatterwalk_advance(&dst_sg_walk, req->dst->length);
			scatterwalk_done(&dst_sg_walk, 1, 0);
		}
		scatterwalk_unmap(assoc);
		scatterwalk_advance(&src_sg_walk, req->src->length);
		scatterwalk_done(&src_sg_walk, req->src == req->dst, 0);
	} else {
		scatterwalk_map_and_copy(dst, req->dst, req->assoclen,
					 req->cryptlen + auth_tag_len, 1);
		kfree(assoc);
	}
	return 0;
}

static int helper_rfc4106_decrypt(struct aead_request *req)
{
	u8 one_entry_in_sg = 0;
	u8 *src, *dst, *assoc;
	unsigned long tempCipherLen = 0;
	__be32 counter = cpu_to_be32(1);
	int retval = 0;
	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
	void *aes_ctx = &(ctx->aes_key_expanded);
	unsigned long auth_tag_len = crypto_aead_authsize(tfm);
	u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
	u8 authTag[16];
	struct scatter_walk src_sg_walk;
	struct scatter_walk dst_sg_walk = {};
	unsigned int i;

	if (unlikely(req->assoclen != 16 && req->assoclen != 20))
		return -EINVAL;

	/* Assuming we are supporting rfc4106 64-bit extended */
	/* sequence numbers We need to have the AAD length */
	/* equal to 16 or 20 bytes */

	tempCipherLen = (unsigned long)(req->cryptlen - auth_tag_len);
	/* IV below built */
	for (i = 0; i < 4; i++)
		*(iv+i) = ctx->nonce[i];
	for (i = 0; i < 8; i++)
		*(iv+4+i) = req->iv[i];
	*((__be32 *)(iv+12)) = counter;

	if (sg_is_last(req->src) &&
	    req->src->offset + req->src->length <= PAGE_SIZE &&
	    sg_is_last(req->dst) &&
	    req->dst->offset + req->dst->length <= PAGE_SIZE) {
		one_entry_in_sg = 1;
		scatterwalk_start(&src_sg_walk, req->src);
		assoc = scatterwalk_map(&src_sg_walk);
		src = assoc + req->assoclen;
		dst = src;
		if (unlikely(req->src != req->dst)) {
			scatterwalk_start(&dst_sg_walk, req->dst);
			dst = scatterwalk_map(&dst_sg_walk) + req->assoclen;
		}

	} else {
		/* Allocate memory for src, dst, assoc */
		assoc = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC);
		if (!assoc)
			return -ENOMEM;
		scatterwalk_map_and_copy(assoc, req->src, 0,
					 req->assoclen + req->cryptlen, 0);
		src = assoc + req->assoclen;
		dst = src;
	}

	kernel_fpu_begin();
	aesni_gcm_dec_tfm(aes_ctx, dst, src, tempCipherLen, iv,
			  ctx->hash_subkey, assoc, req->assoclen - 8,
			  authTag, auth_tag_len);
	kernel_fpu_end();

	/* Compare generated tag with passed in tag. */
	retval = crypto_memneq(src + tempCipherLen, authTag, auth_tag_len) ?
		-EBADMSG : 0;

	if (one_entry_in_sg) {
		if (unlikely(req->src != req->dst)) {
			scatterwalk_unmap(dst - req->assoclen);
			scatterwalk_advance(&dst_sg_walk, req->dst->length);
			scatterwalk_done(&dst_sg_walk, 1, 0);
		}
		scatterwalk_unmap(assoc);
		scatterwalk_advance(&src_sg_walk, req->src->length);
		scatterwalk_done(&src_sg_walk, req->src == req->dst, 0);
	} else {
		scatterwalk_map_and_copy(dst, req->dst, req->assoclen,
					 tempCipherLen, 1);
		kfree(assoc);
	}
	return retval;
}
/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
 * ICV (4 bytes). len includes both IV and ICV.
 *
 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
 * failure. If frame is OK, IV and ICV will be removed.
 */
static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
	struct prism2_wep_data *wep = priv;
        #if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21))
        struct blkcipher_desc desc = {.tfm = wep->rx_tfm};
        #endif
	u32 klen, plen;
	u8 key[WEP_KEY_LEN + 3];
	u8 keyidx, *pos;
#ifndef JOHN_HWSEC
	u32 crc;
	u8 icv[4];	
	struct scatterlist sg;
#endif	
	if (skb->len < hdr_len + 8)
		return -1;

	pos = skb->data + hdr_len;
	key[0] = *pos++;
	key[1] = *pos++;
	key[2] = *pos++;
	keyidx = *pos++ >> 6;
	if (keyidx != wep->key_idx)
		return -1;

	klen = 3 + wep->key_len;

	/* Copy rest of the WEP key (the secret part) */
	memcpy(key + 3, wep->key, wep->key_len);

	/* Apply RC4 to data and compute CRC32 over decrypted data */
	plen = skb->len - hdr_len - 8;
#ifndef JOHN_HWSEC
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))
	crypto_cipher_setkey(wep->tfm, key, klen);
	sg.page = virt_to_page(pos);
	sg.offset = offset_in_page(pos);
	sg.length = plen + 4;
	crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4);
#else
	crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
	#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
	sg.page = virt_to_page(pos);
	sg.offset = offset_in_page(pos);
	sg.length = plen + 4;	
	#else
	sg_init_one(&sg, pos, plen + 4);
	#endif	
	if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
		return -7;
#endif 

#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
	crc = ~crc32_le(~0, pos, plen);
#else
	crc = ~ether_crc_le(plen, pos);
#endif
	icv[0] = crc;
	icv[1] = crc >> 8;
	icv[2] = crc >> 16;
	icv[3] = crc >> 24;

	if (memcmp(icv, pos + plen, 4) != 0) {
		/* ICV mismatch - drop frame */
		return -2;
	}
#endif 	/* JOHN_HWSEC */

	/* Remove IV and ICV */
	memmove(skb->data + 4, skb->data, hdr_len);
	skb_pull(skb, 4);
	skb_trim(skb, skb->len - 4);
        return 0;
}


static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
{
	struct prism2_wep_data *wep = priv;

	if (len < 0 || len > WEP_KEY_LEN)
		return -1;

	memcpy(wep->key, key, len);
	wep->key_len = len;

	return 0;
}


static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
{
	struct prism2_wep_data *wep = priv;

	if (len < wep->key_len)
		return -1;

	memcpy(key, wep->key, wep->key_len);

	return wep->key_len;
}


static char * prism2_wep_print_stats(char *p, void *priv)
{
	struct prism2_wep_data *wep = priv;
	p += sprintf(p, "key[%d] alg=WEP len=%d\n",
		     wep->key_idx, wep->key_len);
	return p;
}


static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
	.name			= "WEP",
	.init			= prism2_wep_init,
	.deinit			= prism2_wep_deinit,
	.encrypt_mpdu		= prism2_wep_encrypt,
	.decrypt_mpdu		= prism2_wep_decrypt,
	.encrypt_msdu		= NULL,
	.decrypt_msdu		= NULL,
	.set_key		= prism2_wep_set_key,
	.get_key		= prism2_wep_get_key,
	.print_stats		= prism2_wep_print_stats,
	.extra_prefix_len	= 4, /* IV */
	.extra_postfix_len	= 4, /* ICV */
	.owner			= THIS_MODULE,
};


int __init ieee80211_crypto_wep_init(void)
{
	return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
}


void __exit ieee80211_crypto_wep_exit(void)
{
	ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
}


void ieee80211_wep_null(void)
{
//	printk("============>%s()\n", __FUNCTION__);
        return;
}
#if 0
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
EXPORT_SYMBOL(ieee80211_wep_null);
#else
EXPORT_SYMBOL_NOVERS(ieee80211_wep_null);
#endif

module_init(ieee80211_crypto_wep_init);
module_exit(ieee80211_crypto_wep_exit);
static int esp6_init_state(struct xfrm_state *x)
{
	struct esp_data *esp = NULL;

	/* null auth and encryption can have zero length keys */
	if (x->aalg) {
		if (x->aalg->alg_key_len > 512)
			goto error;
	}
	if (x->ealg == NULL)
		goto error;

	if (x->encap)
		goto error;

	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
	if (esp == NULL)
		return -ENOMEM;

	memset(esp, 0, sizeof(*esp));

	if (x->aalg) {
		struct xfrm_algo_desc *aalg_desc;

		esp->auth.key = x->aalg->alg_key;
		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
		esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
		if (esp->auth.tfm == NULL)
			goto error;
		esp->auth.icv = esp_hmac_digest;
 
		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
		BUG_ON(!aalg_desc);
 
		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
			crypto_tfm_alg_digestsize(esp->auth.tfm)) {
				printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
					x->aalg->alg_name,
					crypto_tfm_alg_digestsize(esp->auth.tfm),
					aalg_desc->uinfo.auth.icv_fullbits/8);
				goto error;
		}
 
		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
 
		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
		if (!esp->auth.work_icv)
			goto error;
	}
	esp->conf.key = x->ealg->alg_key;
	esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
	if (x->props.ealgo == SADB_EALG_NULL)
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB);
	else
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
	if (esp->conf.tfm == NULL)
		goto error;
	esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
	esp->conf.padlen = 0;
	if (esp->conf.ivlen) {
		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
		if (unlikely(esp->conf.ivec == NULL))
			goto error;
		get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
	}
	if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len))
		goto error;
	x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
	if (x->props.mode)
		x->props.header_len += sizeof(struct ipv6hdr);
	x->data = esp;
#if defined (CONFIG_OCTEON_NATIVE_IPSEC)
	esp->oct_data = cavium_alloc_n_fill(x);
#endif
	return 0;

error:
	x->data = esp;
	esp6_destroy(x);
	x->data = NULL;
	return -EINVAL;
}
Beispiel #24
0
/*
 * Handle an I/O request.
 */
static void sbd_transfer(struct sbd_device *dev, sector_t sector,
		unsigned long nsect, char *buffer, int write) {
	unsigned long offset = sector * logical_block_size;
	unsigned long nbytes = nsect * logical_block_size;
	char *encrypts[2];
	u8 *dst, *src;
	unsigned long len;
	int i;

	//set up the key
	crypto_cipher_setkey(crypto, crypto_key, crypto_key_len);

	if ((offset + nbytes) > dev->size) {
		printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes);
		return;
	}

	if (write) {
		encrypts[0] = "UNECRYPTED";
		encrypts[1] = "ENCRYPTED";
		dst = dev->data + offset;
		src = buffer;

		for (i = 0; i < nbytes; i += crypto_cipher_blocksize(crypto)) {
			/*
			* crypto_cipher_encrypt_one() - encrypt one block of plaintext
			* @tfm: cipher handle
			* @dst: points to the buffer that will be filled with the ciphertext
			* @src: buffer holding the plaintext to be encrypted
			*
			* Invoke the encryption operation of one block. The caller must ensure that
			* the plaintext and ciphertext buffers are at least one block in size.

			static inline void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
														u8 *dst, const u8 *src)
			{
				crypto_cipher_crt(tfm)->cit_encrypt_one(crypto_cipher_tfm(tfm),
														dst, src);
			}
			*/
			crypto_cipher_encrypt_one(crypto, dst + i, src + i);
		}
	}
	else {
		//backwards from encrypt
		encrypts[0] = "ENCRYPTED";
		encrypts[1] = "UNENCRYPTED";
		dst = buffer;
		src = dev->data + offset;

		for (i = 0; i < nbytes; i += crypto_cipher_blocksize(crypto)) {
			/*
			* crypto_cipher_decrypt_one() - decrypt one block of ciphertext
			* @tfm: cipher handle
			* @dst: points to the buffer that will be filled with the plaintext
			* @src: buffer holding the ciphertext to be decrypted
			*
			* Invoke the decryption operation of one block. The caller must ensure that
			* the plaintext and ciphertext buffers are at least one block in size.

			static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
			                                      		u8 *dst, const u8 *src)
			{
			     crypto_cipher_crt(tfm)->cit_decrypt_one(crypto_cipher_tfm(tfm),
		                                             	dst, src);
			}
			*/
			crypto_cipher_decrypt_one(crypto, dst + i, src + i);
		}
	}

	// print out both buffers of encrypted and unencrypted
	// len = nbytes;
	// printk("%s:", encrypts[0]);
	// while (len--) {
 //    	printk("%u", (unsigned) *src++);
 //    }

	// len = nbytes;
	// printk("\n%s:", encrypts[1]);
	// while (len--) {
 //    	printk("%u", (unsigned) *dst++);
 //    }
	// printk("\n");
}
Beispiel #25
0
int esp_init_state(struct xfrm_state *x, void *args)
{
	struct esp_data *esp = NULL;

	/* null auth and encryption can have zero length keys */
	if (x->aalg) {
		if (x->aalg->alg_key_len > 512)
			goto error;
	}
	if (x->ealg == NULL)
		goto error;

	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
	if (esp == NULL)
		return -ENOMEM;

	memset(esp, 0, sizeof(*esp));

	if (x->aalg) {
		struct xfrm_algo_desc *aalg_desc;

		esp->auth.key = x->aalg->alg_key;
		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
		esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
		if (esp->auth.tfm == NULL)
			goto error;
		esp->auth.icv = esp_hmac_digest;

		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
		BUG_ON(!aalg_desc);

		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
		    crypto_tfm_alg_digestsize(esp->auth.tfm)) {
			printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
			       x->aalg->alg_name,
			       crypto_tfm_alg_digestsize(esp->auth.tfm),
			       aalg_desc->uinfo.auth.icv_fullbits/8);
			goto error;
		}

		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;

		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
		if (!esp->auth.work_icv)
			goto error;
	}
	esp->conf.key = x->ealg->alg_key;
	esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
	if (x->props.ealgo == SADB_EALG_NULL)
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB);
	else
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
	if (esp->conf.tfm == NULL)
		goto error;
	esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
	esp->conf.padlen = 0;
	if (esp->conf.ivlen) {
		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
		get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
	}
	crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len);
	x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
	if (x->props.mode)
		x->props.header_len += sizeof(struct iphdr);
	if (x->encap) {
		struct xfrm_encap_tmpl *encap = x->encap;

		if (encap->encap_type) {
			switch (encap->encap_type) {
			case UDP_ENCAP_ESPINUDP:
				x->props.header_len += sizeof(struct udphdr);
				break;
			default:
				printk (KERN_INFO
				"esp_init_state(): Unhandled encap type: %u\n",
					encap->encap_type);
				break;
			}
		}
	}
	x->data = esp;
	x->props.trailer_len = esp4_get_max_size(x, 0) - x->props.header_len;
	return 0;

error:
	if (esp) {
		if (esp->auth.tfm)
			crypto_free_tfm(esp->auth.tfm);
		if (esp->auth.work_icv)
			kfree(esp->auth.work_icv);
		if (esp->conf.tfm)
			crypto_free_tfm(esp->conf.tfm);
		kfree(esp);
	}
	return -EINVAL;
}
/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
 * so the payload length increases with 8 bytes.
 *
 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
 */
static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
	struct prism2_wep_data *wep = priv;
	u32 klen, len;
	u8 key[WEP_KEY_LEN + 3];
	u8 *pos;
	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
	#if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED))
	struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
	#endif
	u32 crc;
	u8 *icv;
	struct scatterlist sg;
	if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
	    skb->len < hdr_len)
		return -1;

	len = skb->len - hdr_len;
	pos = skb_push(skb, 4);
	memmove(pos, pos + 4, hdr_len);
	pos += hdr_len;

	klen = 3 + wep->key_len;

	wep->iv++;

	/* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
	 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
	 * can be used to speedup attacks, so avoid using them. */
	if ((wep->iv & 0xff00) == 0xff00) {
		u8 B = (wep->iv >> 16) & 0xff;
		if (B >= 3 && B < klen)
			wep->iv += 0x0100;
	}

	/* Prepend 24-bit IV to RC4 key and TX frame */
	*pos++ = key[0] = (wep->iv >> 16) & 0xff;
	*pos++ = key[1] = (wep->iv >> 8) & 0xff;
	*pos++ = key[2] = wep->iv & 0xff;
	*pos++ = wep->key_idx << 6;

	/* Copy rest of the WEP key (the secret part) */
	memcpy(key + 3, wep->key, wep->key_len);

	if (!tcb_desc->bHwSec)
	{

		/* Append little-endian CRC32 and encrypt it to produce ICV */
	#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
		crc = ~crc32_le(~0, pos, len);
	#else
		crc = ~ether_crc_le(len, pos);
	#endif
		icv = skb_put(skb, 4);
		icv[0] = crc;
		icv[1] = crc >> 8;
		icv[2] = crc >> 16;
		icv[3] = crc >> 24;

#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
		crypto_cipher_setkey(wep->tfm, key, klen);
		sg.page = virt_to_page(pos);
		sg.offset = offset_in_page(pos);
		sg.length = len + 4;
		crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
		return 0;
	#else
		crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
	#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
		sg.page = virt_to_page(pos);
		sg.offset = offset_in_page(pos);
		sg.length = len + 4;
	#else
		sg_init_one(&sg, pos, len+4);
	#endif
		return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
	#endif
	}
Beispiel #27
0
/******************************************************************************
 * Handle an I/O request.
 *
 ******************************************************************************/
static void sbd_transfer(struct sbd_device *dev, sector_t sector,
						 unsigned long nsect, char *buffer, int write) {
	unsigned long offset = sector * logical_block_size;
	unsigned long nbytes = nsect * logical_block_size;
	
	int i;
	int encrypt_flag;
	int decrypt_flag;
	unsigned long length;
	u8 *dst;
	u8 *src;
	
	/* Setting the Key */
	crypto_cipher_setkey(crypt_cipher, key, key_len);
	
	if ((offset + nbytes) > dev->size) {
		printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes);
		return;
	}
	
	if (write){
		decrypt_flag = 0;
		encrypt_flag = 1;
		dst = dev->data + offset;
		src = buffer;
		
		for (i = 0; i < nbytes; i += crypto_cipher_blocksize(crypt_cipher)) {
			crypto_cipher_encrypt_one(crypt_cipher, dst + i, src + i);
		}
	
	} else {
		decrypt_flag = 1;
		encrypt_flag = 0;
		dst = buffer;
		src = dev->data + offset;
		
		for (i = 0; i < nbytes; i += crypto_cipher_blocksize(crypt_cipher)) {
			crypto_cipher_decrypt_one(crypt_cipher, dst + i, src + i);
		}
	}
	
	length = nbytes;
	printk("\n\n");
	if (encrypt_flag && !decrypt_flag) {
		printk("Encrypt:\n");
	} else {
		printk("Decrypt:\n");
	}
	while (length--) {
		printk("%u ", (unsigned) *src++);
	}
	
	length = nbytes;
	printk("\n\n");
	if (encrypt_flag && !decrypt_flag) {
		printk("Decrypt:\n");
	} else {
		printk("Encrypt:\n");
	}
	while (length--) {
		printk("%u ", (unsigned) *dst++);
	}
	printk("\n");
}
Beispiel #28
0
int esp6_init_state(struct xfrm_state *x, void *args)
{
	struct esp_data *esp = NULL;

	if (x->aalg) {
		if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512)
			goto error;
	}
	if (x->ealg == NULL)
		goto error;

	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
	if (esp == NULL)
		return -ENOMEM;

	memset(esp, 0, sizeof(*esp));

	if (x->aalg) {
		struct xfrm_algo_desc *aalg_desc;

		esp->auth.key = x->aalg->alg_key;
		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
		esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
		if (esp->auth.tfm == NULL)
			goto error;
		esp->auth.icv = esp_hmac_digest;
 
		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
		BUG_ON(!aalg_desc);
 
		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
			crypto_tfm_alg_digestsize(esp->auth.tfm)) {
				printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
					x->aalg->alg_name,
					crypto_tfm_alg_digestsize(esp->auth.tfm),
					aalg_desc->uinfo.auth.icv_fullbits/8);
				goto error;
		}
 
		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
 
		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
		if (!esp->auth.work_icv)
			goto error;
	}
	esp->conf.key = x->ealg->alg_key;
	esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
	if (x->props.ealgo == SADB_EALG_NULL)
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB);
	else
		esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
	if (esp->conf.tfm == NULL)
		goto error;
	esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
	esp->conf.padlen = 0;
	if (esp->conf.ivlen) {
		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
		get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
	}
	crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len);
	x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
	if (x->props.mode)
		x->props.header_len += sizeof(struct ipv6hdr);
	x->data = esp;
	return 0;

error:
	if (esp) {
		if (esp->auth.tfm)
			crypto_free_tfm(esp->auth.tfm);
		if (esp->auth.work_icv)
			kfree(esp->auth.work_icv);
		if (esp->conf.tfm)
			crypto_free_tfm(esp->conf.tfm);
		kfree(esp);
	}
	return -EINVAL;
}
Beispiel #29
0
static inline int chcr_ipsec_setkey(struct xfrm_state *x,
				    struct ipsec_sa_entry *sa_entry)
{
	struct crypto_cipher *cipher;
	int keylen = (x->aead->alg_key_len + 7) / 8;
	unsigned char *key = x->aead->alg_key;
	int ck_size, key_ctx_size = 0;
	unsigned char ghash_h[AEAD_H_SIZE];
	int ret = 0;

	if (keylen > 3) {
		keylen -= 4;  /* nonce/salt is present in the last 4 bytes */
		memcpy(sa_entry->salt, key + keylen, 4);
	}

	if (keylen == AES_KEYSIZE_128) {
		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
	} else if (keylen == AES_KEYSIZE_192) {
		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
	} else if (keylen == AES_KEYSIZE_256) {
		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
	} else {
		pr_err("GCM: Invalid key length %d\n", keylen);
		ret = -EINVAL;
		goto out;
	}

	memcpy(sa_entry->key, key, keylen);
	sa_entry->enckey_len = keylen;
	key_ctx_size = sizeof(struct _key_ctx) +
			      ((DIV_ROUND_UP(keylen, 16)) << 4) +
			      AEAD_H_SIZE;

	sa_entry->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size,
						 CHCR_KEYCTX_MAC_KEY_SIZE_128,
						 0, 0,
						 key_ctx_size >> 4);

	/* Calculate the H = CIPH(K, 0 repeated 16 times).
	 * It will go in key context
	 */
	cipher = crypto_alloc_cipher("aes-generic", 0, 0);
	if (IS_ERR(cipher)) {
		sa_entry->enckey_len = 0;
		ret = -ENOMEM;
		goto out;
	}

	ret = crypto_cipher_setkey(cipher, key, keylen);
	if (ret) {
		sa_entry->enckey_len = 0;
		goto out1;
	}
	memset(ghash_h, 0, AEAD_H_SIZE);
	crypto_cipher_encrypt_one(cipher, ghash_h, ghash_h);
	memcpy(sa_entry->key + (DIV_ROUND_UP(sa_entry->enckey_len, 16) *
	       16), ghash_h, AEAD_H_SIZE);
	sa_entry->kctx_len = ((DIV_ROUND_UP(sa_entry->enckey_len, 16)) << 4) +
			      AEAD_H_SIZE;
out1:
	crypto_free_cipher(cipher);
out:
	return ret;
}