10ba2cbe9Sxc /*
2*e2cf88acSQuaker Fang  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
30ba2cbe9Sxc  * Use is subject to license terms.
40ba2cbe9Sxc  */
50ba2cbe9Sxc 
60ba2cbe9Sxc /*
70ba2cbe9Sxc  * Copyright (c) 2001 Atsushi Onoe
8*e2cf88acSQuaker Fang  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
90ba2cbe9Sxc  * All rights reserved.
100ba2cbe9Sxc  *
110ba2cbe9Sxc  * Redistribution and use in source and binary forms, with or without
120ba2cbe9Sxc  * modification, are permitted provided that the following conditions
130ba2cbe9Sxc  * are met:
140ba2cbe9Sxc  * 1. Redistributions of source code must retain the above copyright
150ba2cbe9Sxc  *    notice, this list of conditions and the following disclaimer.
160ba2cbe9Sxc  * 2. Redistributions in binary form must reproduce the above copyright
170ba2cbe9Sxc  *    notice, this list of conditions and the following disclaimer in the
180ba2cbe9Sxc  *    documentation and/or other materials provided with the distribution.
190ba2cbe9Sxc  * 3. The name of the author may not be used to endorse or promote products
200ba2cbe9Sxc  *    derived from this software without specific prior written permission.
210ba2cbe9Sxc  *
220ba2cbe9Sxc  * Alternatively, this software may be distributed under the terms of the
230ba2cbe9Sxc  * GNU General Public License ("GPL") version 2 as published by the Free
240ba2cbe9Sxc  * Software Foundation.
250ba2cbe9Sxc  *
260ba2cbe9Sxc  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
270ba2cbe9Sxc  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
280ba2cbe9Sxc  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
290ba2cbe9Sxc  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
300ba2cbe9Sxc  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
310ba2cbe9Sxc  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
320ba2cbe9Sxc  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
330ba2cbe9Sxc  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
340ba2cbe9Sxc  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
350ba2cbe9Sxc  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
360ba2cbe9Sxc  */
370ba2cbe9Sxc 
380ba2cbe9Sxc /*
390ba2cbe9Sxc  * IEEE 802.11 WEP crypto support.
400ba2cbe9Sxc  */
410ba2cbe9Sxc #include <sys/byteorder.h>
420ba2cbe9Sxc #include <sys/crypto/common.h>
430ba2cbe9Sxc #include <sys/crypto/api.h>
440ba2cbe9Sxc #include <sys/crc32.h>
450ba2cbe9Sxc #include <sys/random.h>
46ff3124efSff #include <sys/strsun.h>
470ba2cbe9Sxc #include "net80211_impl.h"
480ba2cbe9Sxc 
490ba2cbe9Sxc static  void *wep_attach(struct ieee80211com *, struct ieee80211_key *);
500ba2cbe9Sxc static  void wep_detach(struct ieee80211_key *);
510ba2cbe9Sxc static  int wep_setkey(struct ieee80211_key *);
520ba2cbe9Sxc static  int wep_encap(struct ieee80211_key *, mblk_t *, uint8_t keyid);
530ba2cbe9Sxc static  int wep_decap(struct ieee80211_key *, mblk_t *, int);
540ba2cbe9Sxc static  int wep_enmic(struct ieee80211_key *, mblk_t *, int);
550ba2cbe9Sxc static  int wep_demic(struct ieee80211_key *, mblk_t *, int);
560ba2cbe9Sxc 
570ba2cbe9Sxc const struct ieee80211_cipher wep = {
580ba2cbe9Sxc 	"WEP",
590ba2cbe9Sxc 	IEEE80211_CIPHER_WEP,
600ba2cbe9Sxc 	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN,
610ba2cbe9Sxc 	IEEE80211_WEP_CRCLEN,
620ba2cbe9Sxc 	0,
630ba2cbe9Sxc 	wep_attach,
640ba2cbe9Sxc 	wep_detach,
650ba2cbe9Sxc 	wep_setkey,
660ba2cbe9Sxc 	wep_encap,
670ba2cbe9Sxc 	wep_decap,
680ba2cbe9Sxc 	wep_enmic,
690ba2cbe9Sxc 	wep_demic,
700ba2cbe9Sxc };
710ba2cbe9Sxc 
720ba2cbe9Sxc int rc4_init(crypto_context_t *, const uint8_t *, int);
730ba2cbe9Sxc int rc4_crypt(crypto_context_t, const uint8_t *, uint8_t *, int);
740ba2cbe9Sxc int rc4_final(crypto_context_t, uint8_t *, int);
750ba2cbe9Sxc 
760ba2cbe9Sxc static	int wep_encrypt(struct ieee80211_key *, mblk_t *, int);
770ba2cbe9Sxc static	int wep_decrypt(struct ieee80211_key *, mblk_t *, int);
780ba2cbe9Sxc 
790ba2cbe9Sxc struct wep_ctx {
800ba2cbe9Sxc 	ieee80211com_t *wc_ic;		/* for diagnostics */
810ba2cbe9Sxc 	uint32_t	wc_iv;		/* initial vector for crypto */
820ba2cbe9Sxc };
830ba2cbe9Sxc 
840ba2cbe9Sxc /* Table of CRCs of all 8-bit messages */
850ba2cbe9Sxc static uint32_t crc_table[] = { CRC32_TABLE };
860ba2cbe9Sxc 
870ba2cbe9Sxc /* ARGSUSED */
880ba2cbe9Sxc static void *
wep_attach(struct ieee80211com * ic,struct ieee80211_key * k)890ba2cbe9Sxc wep_attach(struct ieee80211com *ic, struct ieee80211_key *k)
900ba2cbe9Sxc {
910ba2cbe9Sxc 	struct wep_ctx *ctx;
920ba2cbe9Sxc 
930ba2cbe9Sxc 	ctx = kmem_zalloc(sizeof (struct wep_ctx), KM_NOSLEEP);
940ba2cbe9Sxc 	if (ctx == NULL)
950ba2cbe9Sxc 		return (NULL);
960ba2cbe9Sxc 
970ba2cbe9Sxc 	ctx->wc_ic = ic;
980ba2cbe9Sxc 	(void) random_get_pseudo_bytes((unsigned char *)&ctx->wc_iv,
990ba2cbe9Sxc 	    sizeof (uint32_t));
1000ba2cbe9Sxc 	return (ctx);
1010ba2cbe9Sxc }
1020ba2cbe9Sxc 
1030ba2cbe9Sxc static void
wep_detach(struct ieee80211_key * k)1040ba2cbe9Sxc wep_detach(struct ieee80211_key *k)
1050ba2cbe9Sxc {
1060ba2cbe9Sxc 	struct wep_ctx *ctx = k->wk_private;
1070ba2cbe9Sxc 
1080ba2cbe9Sxc 	if (ctx != NULL)
1090ba2cbe9Sxc 		kmem_free(ctx, sizeof (struct wep_ctx));
1100ba2cbe9Sxc }
1110ba2cbe9Sxc 
1120ba2cbe9Sxc static int
wep_setkey(struct ieee80211_key * k)1130ba2cbe9Sxc wep_setkey(struct ieee80211_key *k)
1140ba2cbe9Sxc {
1150ba2cbe9Sxc 	/*
1160ba2cbe9Sxc 	 * WEP key length is standardized to 40-bit. Many
1170ba2cbe9Sxc 	 * implementations support 104-bit WEP kwys.
1180ba2cbe9Sxc 	 */
1190ba2cbe9Sxc 	return (k->wk_keylen == 40/NBBY || k->wk_keylen == 104/NBBY);
1200ba2cbe9Sxc }
1210ba2cbe9Sxc 
1220ba2cbe9Sxc /*
1230ba2cbe9Sxc  * Add privacy headers appropriate for the specified key.
1240ba2cbe9Sxc  */
1250ba2cbe9Sxc static int
wep_encap(struct ieee80211_key * k,mblk_t * mp,uint8_t keyid)1260ba2cbe9Sxc wep_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
1270ba2cbe9Sxc {
1280ba2cbe9Sxc 	struct wep_ctx *ctx = k->wk_private;
1290ba2cbe9Sxc 	struct ieee80211_frame *wh = (struct ieee80211_frame *)mp->b_rptr;
1300ba2cbe9Sxc 	uint32_t iv;
1310ba2cbe9Sxc 	uint8_t *ivp;
1320ba2cbe9Sxc 	int hdrlen;
1330ba2cbe9Sxc 
1340ba2cbe9Sxc 	if (mp == NULL)
1350ba2cbe9Sxc 		return (0);
136*e2cf88acSQuaker Fang 	hdrlen = ieee80211_hdrspace(ctx->wc_ic, wh);
1370ba2cbe9Sxc 
1380ba2cbe9Sxc 	ivp = (uint8_t *)wh;
1390ba2cbe9Sxc 	ivp += hdrlen;
1400ba2cbe9Sxc 
1410ba2cbe9Sxc 	/*
1420ba2cbe9Sxc 	 * IV must not duplicate during the lifetime of the key.
1430ba2cbe9Sxc 	 * But no mechanism to renew keys is defined in IEEE 802.11
1440ba2cbe9Sxc 	 * WEP.  And IV may be duplicated between other stations
1450ba2cbe9Sxc 	 * because of the session key itself is shared.
1460ba2cbe9Sxc 	 * So we use pseudo random IV for now, though it is not the
1470ba2cbe9Sxc 	 * right way.
1480ba2cbe9Sxc 	 */
1490ba2cbe9Sxc 	iv = ctx->wc_iv;
1500ba2cbe9Sxc 	/*
1510ba2cbe9Sxc 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
1520ba2cbe9Sxc 	 * (B, 255, N) with 3 <= B < 8
1530ba2cbe9Sxc 	 */
1540ba2cbe9Sxc 	if ((iv & 0xff00) == 0xff00) {
1550ba2cbe9Sxc 		int B = (iv & 0xff0000) >> 16;
1560ba2cbe9Sxc 		if (3 <= B && B < 16)
1570ba2cbe9Sxc 			iv = (B+1) << 16;
1580ba2cbe9Sxc 	}
1590ba2cbe9Sxc 	ctx->wc_iv = iv + 1;
1600ba2cbe9Sxc 
1610ba2cbe9Sxc 	ivp[2] = (uint8_t)(iv >> 0);
1620ba2cbe9Sxc 	ivp[1] = (uint8_t)(iv >> 8);
1630ba2cbe9Sxc 	ivp[0] = (uint8_t)(iv >> 16);
1640ba2cbe9Sxc 
1650ba2cbe9Sxc 	/* Key ID and pad */
1660ba2cbe9Sxc 	ivp[IEEE80211_WEP_IVLEN] = keyid;
1670ba2cbe9Sxc 
1680ba2cbe9Sxc 	if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
1690ba2cbe9Sxc 	    (wep_encrypt(k, mp, hdrlen) == 0))
1700ba2cbe9Sxc 		return (0);
1710ba2cbe9Sxc 
1720ba2cbe9Sxc 	return (1);
1730ba2cbe9Sxc }
1740ba2cbe9Sxc 
1750ba2cbe9Sxc /*
1760ba2cbe9Sxc  * Validate and strip privacy headers (and trailer) for a
1770ba2cbe9Sxc  * received frame.  If necessary, decrypt the frame using
1780ba2cbe9Sxc  * the specified key.
1790ba2cbe9Sxc  */
1800ba2cbe9Sxc static int
wep_decap(struct ieee80211_key * k,mblk_t * mp,int hdrlen)1810ba2cbe9Sxc wep_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
1820ba2cbe9Sxc {
1830ba2cbe9Sxc 	/*
1840ba2cbe9Sxc 	 * Check if the device handled the decrypt in hardware.
1850ba2cbe9Sxc 	 * If so we just strip the header; otherwise we need to
1860ba2cbe9Sxc 	 * handle the decrypt in software.
1870ba2cbe9Sxc 	 */
1880ba2cbe9Sxc 	if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
1890ba2cbe9Sxc 	    (wep_decrypt(k, mp, hdrlen) == 0)) {
1900ba2cbe9Sxc 		ieee80211_err("WEP ICV mismatch on decrypt\n");
1910ba2cbe9Sxc 		return (0);
1920ba2cbe9Sxc 	}
1930ba2cbe9Sxc 
1940ba2cbe9Sxc 	/*
1950ba2cbe9Sxc 	 * Copy up 802.11 header and strip crypto bits.
1960ba2cbe9Sxc 	 */
197*e2cf88acSQuaker Fang 	(void) memmove(mp->b_rptr + wep.ic_header, mp->b_rptr, hdrlen);
1980ba2cbe9Sxc 	mp->b_rptr += wep.ic_header;
1990ba2cbe9Sxc 	mp->b_wptr -= wep.ic_trailer;
2000ba2cbe9Sxc 
2010ba2cbe9Sxc 	return (1);
2020ba2cbe9Sxc }
2030ba2cbe9Sxc 
2040ba2cbe9Sxc /*
2050ba2cbe9Sxc  * Add MIC to the frame as needed.
2060ba2cbe9Sxc  */
2070ba2cbe9Sxc /* ARGSUSED */
2080ba2cbe9Sxc static int
wep_enmic(struct ieee80211_key * k,mblk_t * mp,int force)2090ba2cbe9Sxc wep_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
2100ba2cbe9Sxc {
2110ba2cbe9Sxc 	return (1);
2120ba2cbe9Sxc }
2130ba2cbe9Sxc 
2140ba2cbe9Sxc /*
2150ba2cbe9Sxc  * Verify and strip MIC from the frame.
2160ba2cbe9Sxc  */
2170ba2cbe9Sxc /* ARGSUSED */
2180ba2cbe9Sxc static int
wep_demic(struct ieee80211_key * k,mblk_t * mp,int force)2190ba2cbe9Sxc wep_demic(struct ieee80211_key *k, mblk_t *mp, int force)
2200ba2cbe9Sxc {
2210ba2cbe9Sxc 	return (1);
2220ba2cbe9Sxc }
2230ba2cbe9Sxc 
2240ba2cbe9Sxc static int
wep_encrypt(struct ieee80211_key * key,mblk_t * mp,int hdrlen)2250ba2cbe9Sxc wep_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen)
2260ba2cbe9Sxc {
2270ba2cbe9Sxc 	uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
2280ba2cbe9Sxc 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
2290ba2cbe9Sxc 	uint8_t *icv;
2300ba2cbe9Sxc 	uint32_t crc;
2310ba2cbe9Sxc 	crypto_context_t ctx;
2320ba2cbe9Sxc 	int rv;
2330ba2cbe9Sxc 
2340ba2cbe9Sxc 	ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT);
2350ba2cbe9Sxc 
2360ba2cbe9Sxc 	/* ctx->wc_ic->isc_stats.is_crypto_wep++; */
2370ba2cbe9Sxc 
2380ba2cbe9Sxc 	(void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN);
2390ba2cbe9Sxc 	(void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key,
240ff3124efSff 	    key->wk_keylen);
2410ba2cbe9Sxc 
2420ba2cbe9Sxc 	ctx = NULL;
2430ba2cbe9Sxc 	rv = rc4_init(&ctx, (const uint8_t *)rc4key,
244ff3124efSff 	    IEEE80211_WEP_IVLEN + key->wk_keylen);
2450ba2cbe9Sxc 
2460ba2cbe9Sxc 	if (rv != CRYPTO_SUCCESS)
2470ba2cbe9Sxc 		return (0);
2480ba2cbe9Sxc 
2490ba2cbe9Sxc 	/* calculate CRC over unencrypted data */
2500ba2cbe9Sxc 	CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header,
251ff3124efSff 	    MBLKL(mp) - (hdrlen + wep.ic_header),
2520ba2cbe9Sxc 	    -1U, crc_table);
2530ba2cbe9Sxc 
2540ba2cbe9Sxc 	/* encrypt data */
2550ba2cbe9Sxc 	(void) rc4_crypt(ctx,
256ff3124efSff 	    mp->b_rptr + hdrlen + wep.ic_header,
257ff3124efSff 	    mp->b_rptr + hdrlen + wep.ic_header,
258ff3124efSff 	    MBLKL(mp) - (hdrlen + wep.ic_header));
2590ba2cbe9Sxc 
2600ba2cbe9Sxc 	/* tack on ICV */
2610ba2cbe9Sxc 	*(uint32_t *)crcbuf = LE_32(~crc);
2620ba2cbe9Sxc 	icv = mp->b_wptr;
2630ba2cbe9Sxc 	mp->b_wptr += IEEE80211_WEP_CRCLEN;
2640ba2cbe9Sxc 	(void) rc4_crypt(ctx, crcbuf, icv, IEEE80211_WEP_CRCLEN);
2650ba2cbe9Sxc 
2660ba2cbe9Sxc 	(void) rc4_final(ctx, icv, IEEE80211_WEP_CRCLEN);
2670ba2cbe9Sxc 
2680ba2cbe9Sxc 	return (1);
2690ba2cbe9Sxc }
2700ba2cbe9Sxc 
2710ba2cbe9Sxc static int
wep_decrypt(struct ieee80211_key * key,mblk_t * mp,int hdrlen)2720ba2cbe9Sxc wep_decrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen)
2730ba2cbe9Sxc {
2740ba2cbe9Sxc 	uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
2750ba2cbe9Sxc 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
2760ba2cbe9Sxc 	uint8_t *icv;
2770ba2cbe9Sxc 	uint32_t crc;
2780ba2cbe9Sxc 	crypto_context_t ctx;
2790ba2cbe9Sxc 	int rv;
2800ba2cbe9Sxc 
2810ba2cbe9Sxc 	ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT);
2820ba2cbe9Sxc 
2830ba2cbe9Sxc 	/* ctx->wc_ic->isc_stats.is_crypto_wep++; */
2840ba2cbe9Sxc 
2850ba2cbe9Sxc 	(void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN);
2860ba2cbe9Sxc 	(void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key,
287ff3124efSff 	    key->wk_keylen);
2880ba2cbe9Sxc 
2890ba2cbe9Sxc 	ctx = NULL;
2900ba2cbe9Sxc 	rv = rc4_init(&ctx, (const uint8_t *)rc4key,
291ff3124efSff 	    IEEE80211_WEP_IVLEN + key->wk_keylen);
2920ba2cbe9Sxc 
2930ba2cbe9Sxc 	if (rv != CRYPTO_SUCCESS)
2940ba2cbe9Sxc 		return (0);
2950ba2cbe9Sxc 
2960ba2cbe9Sxc 	/* decrypt data */
2970ba2cbe9Sxc 	(void) rc4_crypt(ctx,
298ff3124efSff 	    mp->b_rptr + hdrlen + wep.ic_header,
299ff3124efSff 	    mp->b_rptr + hdrlen + wep.ic_header,
300ff3124efSff 	    MBLKL(mp) -
301ff3124efSff 	    (hdrlen + wep.ic_header + wep.ic_trailer));
3020ba2cbe9Sxc 
3030ba2cbe9Sxc 	/* calculate CRC over unencrypted data */
3040ba2cbe9Sxc 	CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header,
305ff3124efSff 	    MBLKL(mp) -
3060ba2cbe9Sxc 	    (hdrlen + wep.ic_header + wep.ic_trailer),
3070ba2cbe9Sxc 	    -1U, crc_table);
3080ba2cbe9Sxc 
3090ba2cbe9Sxc 	/* decrypt ICV and compare to CRC */
3100ba2cbe9Sxc 	icv = mp->b_wptr - IEEE80211_WEP_CRCLEN;
3110ba2cbe9Sxc 	(void) rc4_crypt(ctx, icv, crcbuf, IEEE80211_WEP_CRCLEN);
3120ba2cbe9Sxc 
3130ba2cbe9Sxc 	(void) rc4_final(ctx, crcbuf, IEEE80211_WEP_CRCLEN);
3140ba2cbe9Sxc 
3150ba2cbe9Sxc 	return (crc == ~LE_32(*(uint32_t *)crcbuf));
3160ba2cbe9Sxc }
3170ba2cbe9Sxc 
3180ba2cbe9Sxc /*
3190ba2cbe9Sxc  * rc_init() -  To init the key, for multiply encryption/decryption
3200ba2cbe9Sxc  * Using the Kernel encryption framework
3210ba2cbe9Sxc  */
3220ba2cbe9Sxc int
rc4_init(crypto_context_t * ctx,const uint8_t * key,int keylen)3230ba2cbe9Sxc rc4_init(crypto_context_t *ctx, const uint8_t *key, int keylen)
3240ba2cbe9Sxc {
3250ba2cbe9Sxc 	crypto_mechanism_t mech;
3260ba2cbe9Sxc 	crypto_key_t crkey;
3270ba2cbe9Sxc 	int rv;
3280ba2cbe9Sxc 
3290ba2cbe9Sxc 	bzero(&crkey, sizeof (crkey));
3300ba2cbe9Sxc 
3310ba2cbe9Sxc 	crkey.ck_format = CRYPTO_KEY_RAW;
3320ba2cbe9Sxc 	crkey.ck_data   = (char *)key;
3330ba2cbe9Sxc 	/* keys are measured in bits, not bytes, so multiply by 8 */
3340ba2cbe9Sxc 	crkey.ck_length = keylen * 8;
3350ba2cbe9Sxc 
3360ba2cbe9Sxc 	mech.cm_type	  = crypto_mech2id(SUN_CKM_RC4);
3370ba2cbe9Sxc 	mech.cm_param	  = NULL;
3380ba2cbe9Sxc 	mech.cm_param_len = 0;
3390ba2cbe9Sxc 
3400ba2cbe9Sxc 	rv = crypto_encrypt_init(&mech, &crkey, NULL, ctx, NULL);
3410ba2cbe9Sxc 	if (rv != CRYPTO_SUCCESS)
3420ba2cbe9Sxc 		cmn_err(CE_WARN, "rc4_init failed (%x)", rv);
3430ba2cbe9Sxc 
3440ba2cbe9Sxc 	return (rv);
3450ba2cbe9Sxc }
3460ba2cbe9Sxc 
3470ba2cbe9Sxc /*
3480ba2cbe9Sxc  * rc4_crypt
3490ba2cbe9Sxc  *
3500ba2cbe9Sxc  * Use the Kernel encryption framework to provide the
3510ba2cbe9Sxc  * crypto operations for the indicated data.
3520ba2cbe9Sxc  */
3530ba2cbe9Sxc int
rc4_crypt(crypto_context_t ctx,const uint8_t * inbuf,uint8_t * outbuf,int buflen)3540ba2cbe9Sxc rc4_crypt(crypto_context_t ctx, const uint8_t *inbuf,
3550ba2cbe9Sxc 	uint8_t *outbuf, int buflen)
3560ba2cbe9Sxc {
3570ba2cbe9Sxc 	int rv = CRYPTO_FAILED;
3580ba2cbe9Sxc 
3590ba2cbe9Sxc 	crypto_data_t d1, d2;
3600ba2cbe9Sxc 
3610ba2cbe9Sxc 	ASSERT(inbuf  != NULL);
3620ba2cbe9Sxc 	ASSERT(outbuf != NULL);
3630ba2cbe9Sxc 
3640ba2cbe9Sxc 	bzero(&d1, sizeof (d1));
3650ba2cbe9Sxc 	bzero(&d2, sizeof (d2));
3660ba2cbe9Sxc 
3670ba2cbe9Sxc 	d1.cd_format = CRYPTO_DATA_RAW;
3680ba2cbe9Sxc 	d1.cd_offset = 0;
3690ba2cbe9Sxc 	d1.cd_length = buflen;
3700ba2cbe9Sxc 	d1.cd_raw.iov_base = (char *)inbuf;
3710ba2cbe9Sxc 	d1.cd_raw.iov_len  = buflen;
3720ba2cbe9Sxc 
3730ba2cbe9Sxc 	d2.cd_format = CRYPTO_DATA_RAW;
3740ba2cbe9Sxc 	d2.cd_offset = 0;
3750ba2cbe9Sxc 	d2.cd_length = buflen;
3760ba2cbe9Sxc 	d2.cd_raw.iov_base = (char *)outbuf;
3770ba2cbe9Sxc 	d2.cd_raw.iov_len  = buflen;
3780ba2cbe9Sxc 
3790ba2cbe9Sxc 	rv = crypto_encrypt_update(ctx, &d1, &d2, NULL);
3800ba2cbe9Sxc 
3810ba2cbe9Sxc 	if (rv != CRYPTO_SUCCESS)
3820ba2cbe9Sxc 		cmn_err(CE_WARN, "rc4_crypt failed (%x)", rv);
3830ba2cbe9Sxc 	return (rv);
3840ba2cbe9Sxc }
3850ba2cbe9Sxc 
3860ba2cbe9Sxc /*
3870ba2cbe9Sxc  * rc4_final
3880ba2cbe9Sxc  *
3890ba2cbe9Sxc  * Use the Kernel encryption framework to provide the
3900ba2cbe9Sxc  * crypto operations for the indicated data.
3910ba2cbe9Sxc  */
3920ba2cbe9Sxc int
rc4_final(crypto_context_t ctx,uint8_t * outbuf,int buflen)3930ba2cbe9Sxc rc4_final(crypto_context_t ctx, uint8_t *outbuf, int buflen)
3940ba2cbe9Sxc {
3950ba2cbe9Sxc 	int rv = CRYPTO_FAILED;
3960ba2cbe9Sxc 
3970ba2cbe9Sxc 	crypto_data_t d2;
3980ba2cbe9Sxc 
3990ba2cbe9Sxc 	ASSERT(outbuf != NULL);
4000ba2cbe9Sxc 
4010ba2cbe9Sxc 	bzero(&d2, sizeof (d2));
4020ba2cbe9Sxc 
4030ba2cbe9Sxc 	d2.cd_format = CRYPTO_DATA_RAW;
4040ba2cbe9Sxc 	d2.cd_offset = 0;
4050ba2cbe9Sxc 	d2.cd_length = buflen;
4060ba2cbe9Sxc 	d2.cd_raw.iov_base = (char *)outbuf;
4070ba2cbe9Sxc 	d2.cd_raw.iov_len = buflen;
4080ba2cbe9Sxc 
4090ba2cbe9Sxc 	rv = crypto_encrypt_final(ctx, &d2, NULL);
4100ba2cbe9Sxc 
4110ba2cbe9Sxc 	if (rv != CRYPTO_SUCCESS)
4120ba2cbe9Sxc 		cmn_err(CE_WARN, "rc4_final failed (%x)", rv);
4130ba2cbe9Sxc 	return (rv);
4140ba2cbe9Sxc }
415