1 /* $OpenBSD: aesctr.c,v 1.1 2005/05/25 05:47:53 markus Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Markus Friedl <markus@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/param.h> 21 #include <sys/ioctl.h> 22 #include <sys/sysctl.h> 23 #include <crypto/cryptodev.h> 24 #include <err.h> 25 #include <fcntl.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include <limits.h> 31 #include <errno.h> 32 33 int debug = 0; 34 35 enum { TST_KEY, TST_IV, TST_PLAIN, TST_CIPHER, TST_NUM }; 36 37 /* Test vectors from RFC 3686 */ 38 struct { 39 char *data[TST_NUM]; 40 } tests[] = { 41 /* 128 bit key */ 42 { 43 "AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E " 44 "00 00 00 30", 45 "00 00 00 00 00 00 00 00", 46 "53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", 47 "E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8" 48 }, 49 { 50 "7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63 " 51 "00 6C B6 DB", 52 "C0 54 3B 59 DA 48 D9 0B", 53 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F " 54 "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", 55 "51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88 " 56 "EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28" 57 }, 58 { 59 "76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC " 60 "00 E0 01 7B", 61 "27 77 7F 3F 4A 17 86 F0", 62 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F " 63 "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" 64 /*"20 21 22 23"*/, 65 "C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7 " 66 "45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53" 67 /*"25 B2 07 2F"*/ 68 }, 69 /* 192 bit key */ 70 { 71 "16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED " 72 "86 3D 06 CC FD B7 85 15 " 73 "00 00 00 48", 74 "36 73 3C 14 7D 6D 93 CB", 75 "53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", 76 "4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28", 77 }, 78 { 79 "7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C " 80 "67 8C 3D B8 E6 F6 A9 1A " 81 "00 96 B0 3B", 82 "02 0C 6E AD C2 CB 50 0D", 83 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F " 84 "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", 85 "45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F " 86 "84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00", 87 }, 88 { 89 "02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B " 90 "F5 9B 60 A7 86 D3 E0 FE " 91 "00 07 BD FD", 92 "5C BD 60 27 8D CC 09 12", 93 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F " 94 "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" 95 /*"20 21 22 23"*/, 96 "96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58 " 97 "D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88" 98 /*"AB EE 09 35"*/, 99 }, 100 /* 256 bit key */ 101 { 102 "77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C " 103 "6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04 " 104 "00 00 00 60", 105 "DB 56 72 C9 7A A8 F0 B2", 106 "53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", 107 "14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0" 108 }, 109 { 110 "F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86 " 111 "C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84 " 112 "00 FA AC 24", 113 "C1 58 5E F1 5A 43 D8 75", 114 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F " 115 "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", 116 "F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9 " 117 "B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C", 118 }, 119 { 120 "FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2 " 121 "AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D " 122 "00 1C C5 B7", 123 "51 A5 1D 70 A1 C1 11 48", 124 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F " 125 "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" 126 /*"20 21 22 23"*/, 127 "EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA " 128 "B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F" 129 /*"1E C0 E6 B8"*/, 130 }, 131 }; 132 133 static int 134 syscrypt(const unsigned char *key, size_t klen, const unsigned char *iv, 135 const unsigned char *in, unsigned char *out, size_t len, int encrypt) 136 { 137 struct session_op session; 138 struct crypt_op cryp; 139 int cryptodev_fd = -1, fd = -1; 140 141 if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) { 142 warn("/dev/crypto"); 143 goto err; 144 } 145 if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) { 146 warn("CRIOGET failed"); 147 goto err; 148 } 149 memset(&session, 0, sizeof(session)); 150 session.cipher = CRYPTO_AES_CTR; 151 session.key = (caddr_t) key; 152 session.keylen = klen; 153 if (ioctl(fd, CIOCGSESSION, &session) == -1) { 154 warn("CIOCGSESSION"); 155 goto err; 156 } 157 memset(&cryp, 0, sizeof(cryp)); 158 cryp.ses = session.ses; 159 cryp.op = encrypt ? COP_ENCRYPT : COP_DECRYPT; 160 cryp.flags = 0; 161 cryp.len = len; 162 cryp.src = (caddr_t) in; 163 cryp.dst = (caddr_t) out; 164 cryp.iv = (caddr_t) iv; 165 cryp.mac = 0; 166 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 167 warn("CIOCCRYPT"); 168 goto err; 169 } 170 if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) { 171 warn("CIOCFSESSION"); 172 goto err; 173 } 174 close(fd); 175 close(cryptodev_fd); 176 return (0); 177 178 err: 179 if (fd != -1) 180 close(fd); 181 if (cryptodev_fd != -1) 182 close(cryptodev_fd); 183 return (-1); 184 } 185 186 static int 187 getallowsoft(void) 188 { 189 int mib[2], old; 190 size_t olen; 191 192 olen = sizeof(old); 193 194 mib[0] = CTL_KERN; 195 mib[1] = KERN_CRYPTODEVALLOWSOFT; 196 if (sysctl(mib, 2, &old, &olen, NULL, 0) < 0) 197 err(1, "sysctl failed"); 198 199 return old; 200 } 201 202 static void 203 setallowsoft(int new) 204 { 205 int mib[2], old; 206 size_t olen, nlen; 207 208 olen = nlen = sizeof(new); 209 210 mib[0] = CTL_KERN; 211 mib[1] = KERN_CRYPTODEVALLOWSOFT; 212 213 if (sysctl(mib, 2, &old, &olen, &new, nlen) < 0) 214 err(1, "sysctl failed"); 215 } 216 217 static int 218 match(unsigned char *a, unsigned char *b, size_t len) 219 { 220 int i; 221 222 if (memcmp(a, b, len) == 0) 223 return (1); 224 225 warnx("ciphertext mismatch"); 226 227 for (i = 0; i < len; i++) 228 printf("%2.2x", a[i]); 229 printf("\n"); 230 for (i = 0; i < len; i++) 231 printf("%2.2x", b[i]); 232 printf("\n"); 233 234 return (0); 235 } 236 237 static int 238 run(int num) 239 { 240 int i, fail = 1, len, j, length[TST_NUM]; 241 u_long val; 242 char *ep, *from; 243 u_char *p, *data[TST_NUM]; 244 245 for (i = 0; i < TST_NUM; i++) 246 data[i] = NULL; 247 for (i = 0; i < TST_NUM; i++) { 248 from = tests[num].data[i]; 249 if (debug) 250 printf("%s\n", from); 251 len = strlen(from); 252 if ((p = malloc(len)) == 0) { 253 warn("malloc"); 254 goto done; 255 } 256 errno = 0; 257 for (j = 0; j < len; j++) { 258 val = strtoul(&from[j*3], &ep, 16); 259 p[j] = (u_char)val; 260 if (*ep == '\0' || errno) 261 break; 262 } 263 length[i] = j+1; 264 data[i] = p; 265 } 266 len = length[TST_PLAIN]; 267 if ((p = malloc(len)) == 0) { 268 warn("malloc"); 269 return (1); 270 } 271 if (syscrypt(data[TST_KEY], length[TST_KEY], 272 data[TST_IV], data[TST_PLAIN], p, 273 length[TST_PLAIN], 0) < 0) { 274 warnx("crypt with /dev/crypto failed"); 275 goto done; 276 } 277 fail = !match(data[TST_CIPHER], p, len); 278 printf("%s test vector %d\n", fail ? "FAILED" : "OK", num); 279 done: 280 for (i = 0; i < TST_NUM; i++) 281 free(data[i]); 282 return (fail); 283 } 284 285 int 286 main(int argc, char **argv) 287 { 288 int allowed = 0, fail = 0, i; 289 290 if (geteuid() == 0) { 291 allowed = getallowsoft(); 292 if (allowed == 0) 293 setallowsoft(1); 294 } 295 for (i = 0; i < (sizeof(tests) / sizeof(tests[0])); i++) 296 fail += run(i); 297 if (geteuid() == 0 && allowed == 0) 298 setallowsoft(0); 299 exit((fail > 0) ? 1 : 0); 300 } 301