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