1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2001 Atsushi Onoe 8 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * Alternatively, this software may be distributed under the terms of the 23 * GNU General Public License ("GPL") version 2 as published by the Free 24 * Software Foundation. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 /* 41 * IEEE 802.11i CCMP crypto support. 42 */ 43 #include <sys/byteorder.h> 44 #include <sys/crypto/common.h> 45 #include <sys/crypto/api.h> 46 #include <sys/crc32.h> 47 #include <sys/random.h> 48 #include "net80211_impl.h" 49 50 struct ccmp_ctx { 51 struct ieee80211com *cc_ic; /* for diagnostics */ 52 }; 53 54 static void *ccmp_attach(struct ieee80211com *, struct ieee80211_key *); 55 static void ccmp_detach(struct ieee80211_key *); 56 static int ccmp_setkey(struct ieee80211_key *); 57 static int ccmp_encap(struct ieee80211_key *k, mblk_t *, uint8_t); 58 static int ccmp_decap(struct ieee80211_key *, mblk_t *, int); 59 static int ccmp_enmic(struct ieee80211_key *, mblk_t *, int); 60 static int ccmp_demic(struct ieee80211_key *, mblk_t *, int); 61 62 const struct ieee80211_cipher ccmp = { 63 "AES-CCM", 64 IEEE80211_CIPHER_AES_CCM, 65 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 66 IEEE80211_WEP_EXTIVLEN, 67 IEEE80211_WEP_MICLEN, 68 0, 69 ccmp_attach, 70 ccmp_detach, 71 ccmp_setkey, 72 ccmp_encap, 73 ccmp_decap, 74 ccmp_enmic, 75 ccmp_demic, 76 }; 77 78 /* ARGSUSED */ 79 static void * 80 ccmp_attach(struct ieee80211com *ic, struct ieee80211_key *k) 81 { 82 struct ccmp_ctx *ctx; 83 84 ctx = kmem_zalloc(sizeof (struct ccmp_ctx), KM_SLEEP); 85 if (ctx == NULL) 86 return (NULL); 87 88 ctx->cc_ic = ic; 89 return (ctx); 90 } 91 92 static void 93 ccmp_detach(struct ieee80211_key *k) 94 { 95 struct ccmp_ctx *ctx = k->wk_private; 96 97 if (ctx != NULL) 98 kmem_free(ctx, sizeof (struct ccmp_ctx)); 99 } 100 101 static int 102 ccmp_setkey(struct ieee80211_key *k) 103 { 104 if (k->wk_keylen != (128/NBBY)) 105 return (0); 106 107 return (1); 108 } 109 110 /* 111 * Add privacy headers appropriate for the specified key. 112 */ 113 static int 114 ccmp_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid) 115 { 116 uint8_t *ivp; 117 int hdrlen; 118 119 hdrlen = ieee80211_hdrspace(mp->b_rptr); 120 /* 121 * Copy down 802.11 header and add the IV, KeyID, and ExtIV. 122 */ 123 ivp = mp->b_rptr; 124 ivp += hdrlen; 125 126 k->wk_keytsc++; /* wrap at 48 bits */ 127 ivp[0] = k->wk_keytsc >> 0; /* PN0 */ 128 ivp[1] = k->wk_keytsc >> 8; /* PN1 */ 129 ivp[2] = 0; /* Reserved */ 130 ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */ 131 ivp[4] = k->wk_keytsc >> 16; /* PN2 */ 132 ivp[5] = k->wk_keytsc >> 24; /* PN3 */ 133 ivp[6] = k->wk_keytsc >> 32; /* PN4 */ 134 ivp[7] = k->wk_keytsc >> 40; /* PN5 */ 135 136 /* 137 * NB: software CCMP is not supported. 138 */ 139 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) 140 return (0); 141 142 return (1); 143 } 144 145 /* 146 * Validate and strip privacy headers (and trailer) for a 147 * received frame. The specified key should be correct but 148 * is also verified. 149 */ 150 static int 151 ccmp_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen) 152 { 153 struct ieee80211_frame tmp; 154 uint8_t *ivp; 155 uint64_t pn; 156 157 /* 158 * Header should have extended IV and sequence number; 159 * verify the former and validate the latter. 160 */ 161 ivp = mp->b_rptr + hdrlen; 162 if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) { 163 /* 164 * No extended IV; discard frame. 165 */ 166 return (0); 167 } 168 169 pn = ieee80211_read_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); 170 if (pn <= k->wk_keyrsc) { 171 /* 172 * Replay violation. 173 */ 174 return (0); 175 } 176 177 /* 178 * NB: software CCMP is not supported. 179 */ 180 if (k->wk_flags & IEEE80211_KEY_SWCRYPT) 181 return (0); 182 183 /* 184 * Copy up 802.11 header and strip crypto bits. 185 */ 186 bcopy(mp->b_rptr, &tmp, hdrlen); 187 bcopy(&tmp, mp->b_rptr + ccmp.ic_header, hdrlen); 188 mp->b_rptr += ccmp.ic_header; 189 mp->b_wptr -= ccmp.ic_trailer; 190 191 /* 192 * Ok to update rsc now. 193 */ 194 k->wk_keyrsc = pn; 195 196 return (1); 197 } 198 199 /* 200 * Add MIC to the frame as needed. 201 */ 202 /* ARGSUSED */ 203 static int 204 ccmp_enmic(struct ieee80211_key *k, mblk_t *mp, int force) 205 { 206 return (1); 207 } 208 209 /* 210 * Verify and strip MIC from the frame. 211 */ 212 /* ARGSUSED */ 213 static int 214 ccmp_demic(struct ieee80211_key *k, mblk_t *mp, int force) 215 { 216 return (1); 217 } 218