1 /*- 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30 #include "diag.h" 31 32 #include "ah.h" 33 #include "ah_internal.h" 34 35 #include <string.h> 36 #include <stdlib.h> 37 #include <err.h> 38 #include <ctype.h> 39 #include <getopt.h> 40 41 const char *progname; 42 43 static int 44 toint(int c) 45 { 46 return isdigit(c) ? c - '0' : isupper(c) ? c - 'A' + 10 : c - 'a' + 10; 47 } 48 49 static int 50 getdata(const char *arg, u_int8_t *data, size_t maxlen) 51 { 52 const char *cp = arg; 53 int len; 54 55 if (cp[0] == '0' && (cp[1] == 'x' || cp[1] == 'X')) 56 cp += 2; 57 len = 0; 58 while (*cp) { 59 int b0, b1; 60 if (cp[0] == ':' || cp[0] == '-' || cp[0] == '.') { 61 cp++; 62 continue; 63 } 64 if (!isxdigit(cp[0])) { 65 fprintf(stderr, "%s: invalid data value %c (not hex)\n", 66 progname, cp[0]); 67 exit(-1); 68 } 69 b0 = toint(cp[0]); 70 if (cp[1] != '\0') { 71 if (!isxdigit(cp[1])) { 72 fprintf(stderr, "%s: invalid data value %c " 73 "(not hex)\n", progname, cp[1]); 74 exit(-1); 75 } 76 b1 = toint(cp[1]); 77 cp += 2; 78 } else { /* fake up 0<n> */ 79 b1 = b0, b0 = 0; 80 cp += 1; 81 } 82 if (len > maxlen) { 83 fprintf(stderr, 84 "%s: too much data in %s, max %llu bytes\n", 85 progname, arg, (unsigned long long) maxlen); 86 } 87 data[len++] = (b0<<4) | b1; 88 } 89 return len; 90 } 91 92 /* XXX this assumes 5212 key types are common to 5211 and 5210 */ 93 94 static int 95 getcipher(const char *name) 96 { 97 #define streq(a,b) (strcasecmp(a,b) == 0) 98 99 if (streq(name, "wep")) 100 return HAL_CIPHER_WEP; 101 if (streq(name, "tkip")) 102 return HAL_CIPHER_TKIP; 103 if (streq(name, "aes-ocb") || streq(name, "ocb")) 104 return HAL_CIPHER_AES_OCB; 105 if (streq(name, "aes-ccm") || streq(name, "ccm") || 106 streq(name, "aes")) 107 return HAL_CIPHER_AES_CCM; 108 if (streq(name, "ckip")) 109 return HAL_CIPHER_CKIP; 110 if (streq(name, "none") || streq(name, "clr")) 111 return HAL_CIPHER_CLR; 112 113 fprintf(stderr, "%s: unknown cipher %s\n", progname, name); 114 exit(-1); 115 #undef streq 116 } 117 118 static void 119 usage(void) 120 { 121 fprintf(stderr, "usage: %s [-i device] keyix cipher keyval [mac]\n", 122 progname); 123 exit(-1); 124 } 125 126 int 127 main(int argc, char *argv[]) 128 { 129 const char *ifname; 130 struct ath_diag atd; 131 HAL_DIAG_KEYVAL setkey; 132 const char *cp; 133 int s, c; 134 u_int16_t keyix; 135 int op = HAL_DIAG_SETKEY; 136 int xor = 0; 137 138 s = socket(AF_INET, SOCK_DGRAM, 0); 139 if (s < 0) 140 err(1, "socket"); 141 ifname = getenv("ATH"); 142 if (!ifname) 143 ifname = ATH_DEFAULT; 144 145 progname = argv[0]; 146 while ((c = getopt(argc, argv, "di:x")) != -1) 147 switch (c) { 148 case 'd': 149 op = HAL_DIAG_RESETKEY; 150 break; 151 case 'i': 152 ifname = optarg; 153 break; 154 case 'x': 155 xor = 1; 156 break; 157 default: 158 usage(); 159 /*NOTREACHED*/ 160 } 161 argc -= optind; 162 argv += optind; 163 if (argc < 1) 164 usage(); 165 166 keyix = (u_int16_t) atoi(argv[0]); 167 if (keyix > 127) 168 errx(-1, "%s: invalid key index %s, must be [0..127]", 169 progname, argv[0]); 170 strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); 171 atd.ad_id = op | ATH_DIAG_IN | ATH_DIAG_DYN; 172 atd.ad_out_data = NULL; 173 atd.ad_out_size = 0; 174 switch (op) { 175 case HAL_DIAG_RESETKEY: 176 atd.ad_in_data = (caddr_t) &keyix; 177 atd.ad_in_size = sizeof(u_int16_t); 178 if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 179 err(1, "ioctl: %s", atd.ad_name); 180 return 0; 181 case HAL_DIAG_SETKEY: 182 if (argc != 3 && argc != 4) 183 usage(); 184 memset(&setkey, 0, sizeof(setkey)); 185 setkey.dk_keyix = keyix; 186 setkey.dk_xor = xor; 187 setkey.dk_keyval.kv_type = getcipher(argv[1]); 188 setkey.dk_keyval.kv_len = getdata(argv[2], 189 setkey.dk_keyval.kv_val, sizeof(setkey.dk_keyval.kv_val)); 190 /* XXX MIC */ 191 if (argc == 4) 192 (void) getdata(argv[3], setkey.dk_mac, 193 IEEE80211_ADDR_LEN); 194 atd.ad_in_data = (caddr_t) &setkey; 195 atd.ad_in_size = sizeof(setkey); 196 if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 197 err(1, "ioctl: %s", atd.ad_name); 198 return 0; 199 } 200 return -1; 201 } 202