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, MERCHANTABILITY 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 * $FreeBSD: src/tools/tools/ath/athkey/athkey.c,v 1.1 2008/12/07 19:17:33 sam Exp $ 30 */ 31 32 #include "diag.h" 33 34 #include "ah.h" 35 #include "ah_internal.h" 36 37 #include <string.h> 38 #include <stdlib.h> 39 #include <err.h> 40 #include <ctype.h> 41 #include <getopt.h> 42 43 const char *progname; 44 45 static int 46 toint(int c) 47 { 48 return isdigit(c) ? c - '0' : isupper(c) ? c - 'A' + 10 : c - 'a' + 10; 49 } 50 51 static int 52 getdata(const char *arg, u_int8_t *data, size_t maxlen) 53 { 54 const char *cp = arg; 55 int len; 56 57 if (cp[0] == '0' && (cp[1] == 'x' || cp[1] == 'X')) 58 cp += 2; 59 len = 0; 60 while (*cp) { 61 int b0, b1; 62 if (cp[0] == ':' || cp[0] == '-' || cp[0] == '.') { 63 cp++; 64 continue; 65 } 66 if (!isxdigit(cp[0])) { 67 fprintf(stderr, "%s: invalid data value %c (not hex)\n", 68 progname, cp[0]); 69 exit(-1); 70 } 71 b0 = toint(cp[0]); 72 if (cp[1] != '\0') { 73 if (!isxdigit(cp[1])) { 74 fprintf(stderr, "%s: invalid data value %c " 75 "(not hex)\n", progname, cp[1]); 76 exit(-1); 77 } 78 b1 = toint(cp[1]); 79 cp += 2; 80 } else { /* fake up 0<n> */ 81 b1 = b0, b0 = 0; 82 cp += 1; 83 } 84 if (len > maxlen) { 85 fprintf(stderr, 86 "%s: too much data in %s, max %u bytes\n", 87 progname, arg, maxlen); 88 } 89 data[len++] = (b0<<4) | b1; 90 } 91 return len; 92 } 93 94 /* XXX this assumes 5212 key types are common to 5211 and 5210 */ 95 96 static int 97 getcipher(const char *name) 98 { 99 #define streq(a,b) (strcasecmp(a,b) == 0) 100 101 if (streq(name, "wep")) 102 return HAL_CIPHER_WEP; 103 if (streq(name, "tkip")) 104 return HAL_CIPHER_TKIP; 105 if (streq(name, "aes-ocb") || streq(name, "ocb")) 106 return HAL_CIPHER_AES_OCB; 107 if (streq(name, "aes-ccm") || streq(name, "ccm") || 108 streq(name, "aes")) 109 return HAL_CIPHER_AES_CCM; 110 if (streq(name, "ckip")) 111 return HAL_CIPHER_CKIP; 112 if (streq(name, "none") || streq(name, "clr")) 113 return HAL_CIPHER_CLR; 114 115 fprintf(stderr, "%s: unknown cipher %s\n", progname, name); 116 exit(-1); 117 #undef streq 118 } 119 120 static void 121 usage(void) 122 { 123 fprintf(stderr, "usage: %s [-i device] keyix cipher keyval [mac]\n", 124 progname); 125 exit(-1); 126 } 127 128 int 129 main(int argc, char *argv[]) 130 { 131 const char *ifname; 132 struct ath_diag atd; 133 HAL_DIAG_KEYVAL setkey; 134 const char *cp; 135 int s, c; 136 u_int16_t keyix; 137 int op = HAL_DIAG_SETKEY; 138 int xor = 0; 139 140 s = socket(AF_INET, SOCK_DGRAM, 0); 141 if (s < 0) 142 err(1, "socket"); 143 ifname = getenv("ATH"); 144 if (!ifname) 145 ifname = ATH_DEFAULT; 146 147 progname = argv[0]; 148 while ((c = getopt(argc, argv, "di:x")) != -1) 149 switch (c) { 150 case 'd': 151 op = HAL_DIAG_RESETKEY; 152 break; 153 case 'i': 154 ifname = optarg; 155 break; 156 case 'x': 157 xor = 1; 158 break; 159 default: 160 usage(); 161 /*NOTREACHED*/ 162 } 163 argc -= optind; 164 argv += optind; 165 if (argc < 1) 166 usage(); 167 168 keyix = (u_int16_t) atoi(argv[0]); 169 if (keyix > 127) 170 errx(-1, "%s: invalid key index %s, must be [0..127]", 171 progname, argv[0]); 172 strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); 173 atd.ad_id = op | ATH_DIAG_IN | ATH_DIAG_DYN; 174 atd.ad_out_data = NULL; 175 atd.ad_out_size = 0; 176 switch (op) { 177 case HAL_DIAG_RESETKEY: 178 atd.ad_in_data = (caddr_t) &keyix; 179 atd.ad_in_size = sizeof(u_int16_t); 180 if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 181 err(1, atd.ad_name); 182 return 0; 183 case HAL_DIAG_SETKEY: 184 if (argc != 3 && argc != 4) 185 usage(); 186 memset(&setkey, 0, sizeof(setkey)); 187 setkey.dk_keyix = keyix; 188 setkey.dk_xor = xor; 189 setkey.dk_keyval.kv_type = getcipher(argv[1]); 190 setkey.dk_keyval.kv_len = getdata(argv[2], 191 setkey.dk_keyval.kv_val, sizeof(setkey.dk_keyval.kv_val)); 192 /* XXX MIC */ 193 if (argc == 4) 194 (void) getdata(argv[3], setkey.dk_mac, 195 IEEE80211_ADDR_LEN); 196 atd.ad_in_data = (caddr_t) &setkey; 197 atd.ad_in_size = sizeof(setkey); 198 if (ioctl(s, SIOCGATHDIAG, &atd) < 0) 199 err(1, atd.ad_name); 200 return 0; 201 } 202 return -1; 203 } 204