4 * Copyright (c) 2002 Markus Friedl. All rights reserved.
5 * Copyright (c) 2008 Damien Miller. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Test crypto(4) Serpent with test vectors provided by Dr Brian Gladman
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
35 #include <sys/sysctl.h>
36 #include <crypto/cryptodev.h>
46 syscrypt(const unsigned char *key, size_t klen, const unsigned char *in,
47 unsigned char *out, size_t len, int do_encrypt)
49 struct session_op session;
51 int cryptodev_fd = -1, fd = -1;
55 * Kludge; the kernel doesn't support ECB encryption so we
56 * use a all-zero IV and encrypt a single block only, so the
57 * result should be the same.
59 bzero(iv, sizeof(iv));
61 if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
65 if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) {
66 warn("CRIOGET failed");
69 memset(&session, 0, sizeof(session));
70 session.cipher = CRYPTO_SERPENT_CBC;
71 session.key = (caddr_t) key;
72 session.keylen = klen;
73 if (ioctl(fd, CIOCGSESSION, &session) == -1) {
77 memset(&cryp, 0, sizeof(cryp));
78 cryp.ses = session.ses;
79 cryp.op = do_encrypt ? COP_ENCRYPT : COP_DECRYPT;
82 cryp.src = (caddr_t) in;
83 cryp.dst = (caddr_t) out;
84 cryp.iv = (caddr_t) iv;
86 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) {
90 if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) {
101 if (cryptodev_fd != -1)
114 if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, NULL, 0) < 0)
115 err(1, "sysctl failed");
121 setallowsoft(int new)
126 olen = nlen = sizeof(new);
128 if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, &new, nlen) < 0)
129 err(1, "sysctl failed");
133 match(unsigned char *a, unsigned char *b, size_t len)
137 if (memcmp(a, b, len) == 0)
140 fprintf(stderr, "decrypt/plaintext mismatch\n");
142 for (i = 0; i < len; i++)
143 fprintf(stderr, "%2.2x", a[i]);
144 fprintf(stderr, "\n");
145 for (i = 0; i < len; i++)
146 fprintf(stderr, "%2.2x", b[i]);
147 fprintf(stderr, "\n");
153 print_hex(unsigned char *a, size_t len)
156 fprintf(stderr, "%02x,", *a++);
157 fprintf(stderr, "\n");
161 * Match expected substring at start of line. If sequence is match, return
162 * a pointer to the first character in the string past the sequence and and
163 * following whitespace.
164 * returns NULL is the start of the line does not match.
167 startswith(const char *line, const char *startswith)
169 size_t len = strlen(startswith);
171 if (strncmp(line, startswith, len) != 0)
174 while (isspace(*line))
179 /* Read a hex string and convert to bytes */
181 parsehex(const char *hex, u_char **s, u_int *lenp)
190 while ((c = *(hex++)) != '\0') {
191 if (strchr(" \t\r\n", c) != NULL)
193 if (c >= '0' && c <= '9')
195 else if (c >= 'a' && c <= 'f')
197 else if (c >= 'A' && c <= 'F')
200 errx(1, "%s: invalid character \"%c\" in hex string",
207 if ((ret = realloc(ret, ++len)) == NULL)
208 errx(1, "realloc(%u)", len);
215 errx(1, "%s: odd number of characters in hex string", __func__);
221 do_tests(const char *filename, int test_num, u_char *key, u_int keylen,
222 u_char *plaintext, u_char *ciphertext, u_int textlen)
228 fprintf(stderr, "Encrypting: \n");
229 print_hex(key, keylen);
230 print_hex(plaintext, textlen);
231 print_hex(ciphertext, textlen);
234 if (syscrypt(key, keylen, plaintext, result, textlen, 1) < 0) {
235 warnx("encrypt with /dev/crypto failed");
237 } else if (!match(result, ciphertext, textlen)) {
238 fprintf(stderr, "on encrypt (result, ciphertext)\n");
241 printf("OK encrypt test vector %s %u\n", filename, test_num);
244 if (syscrypt(key, keylen, ciphertext, result, textlen, 0) < 0) {
245 warnx("decrypt with /dev/crypto failed");
247 } else if (!match(result, plaintext, textlen)) {
248 fprintf(stderr, "on decrypt (result, plaintext)\n");
251 printf("OK decrypt test vector %s %u\n", filename, test_num);
257 run_file(const char *filename)
260 char buf[1024], *eol;
261 const char *cp, *errstr;
262 int lnum = 0, fail = 0;
263 u_char *key, *plaintext, *ciphertext;
264 u_int keylen, textlen, tmp;
265 int blocksize, keysize, test;
267 if ((tv = fopen(filename, "r")) == NULL)
268 err(1, "fopen(\"%s\")", filename);
270 keylen = textlen = tmp = 0;
271 key = ciphertext = plaintext = NULL;
274 while ((fgets(buf, sizeof(buf), tv)) != NULL) {
276 eol = buf + strlen(buf) - 1;
278 errx(1, "line %d: too long", lnum);
279 if (eol > buf && *(eol - 1) == '\r')
282 if ((cp = startswith(buf, "BLOCKSIZE=")) != NULL) {
284 errx(1, "line %d: blocksize already set", lnum);
285 blocksize = (int)strtonum(cp, 128, 128, &errstr);
287 errx(1, "line %d: blocksize is %s: \"%s\"",
289 } else if ((cp = startswith(buf, "KEYSIZE=")) != NULL) {
291 * On a keysize change, run scheduled test before
292 * doing anything else; at least if there is a test
295 if (plaintext != NULL && ciphertext != NULL &&
296 key != NULL && blocksize > 0 && keysize > 0) {
297 fail += do_tests(filename, test, key, keylen,
298 plaintext, ciphertext, textlen);
300 /* And reset the test number */
303 keysize = (int)strtonum(cp, 128, 256, &errstr);
305 errx(1, "line %d: keysize is %s: \"%s\"",
307 if (keysize != 128 && keysize != 192 && keysize != 256)
308 errx(1, "line %d: XXX only 128,192 or 256 "
309 "bit keys (keysize = %d)",
311 } else if ((cp = startswith(buf, "PT=")) != NULL) {
312 if (plaintext != NULL)
314 parsehex(cp, &plaintext, &tmp);
315 if (tmp * 8 != (u_int)blocksize)
316 errx(1, "line %d: plaintext len %u != "
317 "blocklen %d", lnum, tmp, blocksize);
320 errx(1, "line %d: plaintext len %u != "
321 "ciphertext len %d", lnum, tmp,
325 } else if ((cp = startswith(buf, "CT=")) != NULL) {
326 if (ciphertext != NULL)
328 parsehex(cp, &ciphertext, &tmp);
329 if (tmp * 8 != (u_int)blocksize)
330 errx(1, "line %d: ciphertext len %u != "
331 "blocklen %d", lnum, tmp, blocksize);
334 errx(1, "line %d: ciphertext len %u != "
335 "plaintext len %d", lnum, tmp,
339 } else if ((cp = startswith(buf, "KEY=")) != NULL) {
342 parsehex(cp, &key, &keylen);
343 if (keylen * 8 != (u_int)keysize)
344 errx(1, "line %d: ciphertext len %u != "
345 "blocklen %d", lnum, tmp, textlen);
346 } else if ((cp = startswith(buf, "I=")) != NULL) {
350 if (plaintext == NULL || ciphertext == NULL ||
351 key == NULL || blocksize == -1 || keysize == -1) {
352 errx(1, "line %d: new test before "
356 fail += do_tests(filename, test, key, keylen,
357 plaintext, ciphertext, textlen);
359 test = (int)strtonum(cp, 0, 65536, &errstr);
361 errx(1, "line %d: test is %s: \"%s\"",
374 main(int argc, char **argv)
376 int allowed = 0, fail = 0, i;
379 errx(1, "usage: aestest [test-vector-file]");
381 if (geteuid() == 0) {
382 allowed = getallowsoft();
387 for (i = 1; i < argc; i++)
388 fail += run_file(argv[1]);
390 if (geteuid() == 0 && allowed == 0)
393 return fail > 0 ? 1 : 0;