1120945Snectar/* 2233294Sstas * Copyright (c) 1999 - 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5120945Snectar * 6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7120945Snectar * 8233294Sstas * Redistribution and use in source and binary forms, with or without 9233294Sstas * modification, are permitted provided that the following conditions 10233294Sstas * are met: 11120945Snectar * 12233294Sstas * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 14120945Snectar * 15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 16233294Sstas * notice, this list of conditions and the following disclaimer in the 17233294Sstas * documentation and/or other materials provided with the distribution. 18120945Snectar * 19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 20233294Sstas * may be used to endorse or promote products derived from this software 21233294Sstas * without specific prior written permission. 22233294Sstas * 23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33233294Sstas * SUCH DAMAGE. 34120945Snectar */ 35120945Snectar 36120945Snectar#ifdef HAVE_CONFIG_H 37120945Snectar#include <config.h> 38120945Snectar#endif 39178825Sdfr#ifdef HAVE_SYS_MMAN_H 40178825Sdfr#include <sys/mman.h> 41178825Sdfr#endif 42120945Snectar#include <stdio.h> 43120945Snectar#include <string.h> 44120945Snectar#include <err.h> 45120945Snectar#include <roken.h> 46120945Snectar 47233294Sstas#include "asn1-common.h" 48120945Snectar#include "check-common.h" 49120945Snectar 50233294SstasRCSID("$Id$"); 51120945Snectar 52178825Sdfrstruct map_page { 53178825Sdfr void *start; 54178825Sdfr size_t size; 55178825Sdfr void *data_start; 56178825Sdfr size_t data_size; 57178825Sdfr enum map_type type; 58178825Sdfr}; 59178825Sdfr 60178825Sdfr/* #undef HAVE_MMAP */ 61178825Sdfr 62178825Sdfrvoid * 63233294Sstasmap_alloc(enum map_type type, const void *buf, 64178825Sdfr size_t size, struct map_page **map) 65178825Sdfr{ 66178825Sdfr#ifndef HAVE_MMAP 67178825Sdfr unsigned char *p; 68178825Sdfr size_t len = size + sizeof(long) * 2; 69178825Sdfr int i; 70233294Sstas 71178825Sdfr *map = ecalloc(1, sizeof(**map)); 72178825Sdfr 73178825Sdfr p = emalloc(len); 74178825Sdfr (*map)->type = type; 75178825Sdfr (*map)->start = p; 76178825Sdfr (*map)->size = len; 77178825Sdfr (*map)->data_start = p + sizeof(long); 78178825Sdfr for (i = sizeof(long); i > 0; i--) 79178825Sdfr p[sizeof(long) - i] = 0xff - i; 80178825Sdfr for (i = sizeof(long); i > 0; i--) 81178825Sdfr p[len - i] = 0xff - i; 82178825Sdfr#else 83178825Sdfr unsigned char *p; 84178825Sdfr int flags, ret, fd; 85178825Sdfr size_t pagesize = getpagesize(); 86178825Sdfr 87178825Sdfr *map = ecalloc(1, sizeof(**map)); 88178825Sdfr 89178825Sdfr (*map)->type = type; 90178825Sdfr 91178825Sdfr#ifdef MAP_ANON 92178825Sdfr flags = MAP_ANON; 93178825Sdfr fd = -1; 94178825Sdfr#else 95178825Sdfr flags = 0; 96178825Sdfr fd = open ("/dev/zero", O_RDONLY); 97178825Sdfr if(fd < 0) 98178825Sdfr err (1, "open /dev/zero"); 99178825Sdfr#endif 100178825Sdfr flags |= MAP_PRIVATE; 101178825Sdfr 102178825Sdfr (*map)->size = size + pagesize - (size % pagesize) + pagesize * 2; 103178825Sdfr 104178825Sdfr p = (unsigned char *)mmap(0, (*map)->size, PROT_READ | PROT_WRITE, 105178825Sdfr flags, fd, 0); 106178825Sdfr if (p == (unsigned char *)MAP_FAILED) 107178825Sdfr err (1, "mmap"); 108178825Sdfr 109178825Sdfr (*map)->start = p; 110178825Sdfr 111178825Sdfr ret = mprotect (p, pagesize, 0); 112178825Sdfr if (ret < 0) 113178825Sdfr err (1, "mprotect"); 114178825Sdfr 115178825Sdfr ret = mprotect (p + (*map)->size - pagesize, pagesize, 0); 116178825Sdfr if (ret < 0) 117178825Sdfr err (1, "mprotect"); 118178825Sdfr 119178825Sdfr switch (type) { 120178825Sdfr case OVERRUN: 121178825Sdfr (*map)->data_start = p + (*map)->size - pagesize - size; 122178825Sdfr break; 123178825Sdfr case UNDERRUN: 124178825Sdfr (*map)->data_start = p + pagesize; 125178825Sdfr break; 126178825Sdfr default: 127178825Sdfr abort(); 128178825Sdfr } 129178825Sdfr#endif 130178825Sdfr (*map)->data_size = size; 131178825Sdfr if (buf) 132178825Sdfr memcpy((*map)->data_start, buf, size); 133178825Sdfr return (*map)->data_start; 134178825Sdfr} 135178825Sdfr 136178825Sdfrvoid 137178825Sdfrmap_free(struct map_page *map, const char *test_name, const char *map_name) 138178825Sdfr{ 139178825Sdfr#ifndef HAVE_MMAP 140178825Sdfr unsigned char *p = map->start; 141178825Sdfr int i; 142233294Sstas 143178825Sdfr for (i = sizeof(long); i > 0; i--) 144178825Sdfr if (p[sizeof(long) - i] != 0xff - i) 145178825Sdfr errx(1, "%s: %s underrun %d\n", test_name, map_name, i); 146178825Sdfr for (i = sizeof(long); i > 0; i--) 147178825Sdfr if (p[map->size - i] != 0xff - i) 148233294Sstas errx(1, "%s: %s overrun %lu\n", test_name, map_name, 149178825Sdfr (unsigned long)map->size - i); 150178825Sdfr free(map->start); 151178825Sdfr#else 152178825Sdfr int ret; 153233294Sstas 154178825Sdfr ret = munmap (map->start, map->size); 155178825Sdfr if (ret < 0) 156178825Sdfr err (1, "munmap"); 157178825Sdfr#endif 158178825Sdfr free(map); 159178825Sdfr} 160178825Sdfr 161120945Snectarstatic void 162120945Snectarprint_bytes (unsigned const char *buf, size_t len) 163120945Snectar{ 164120945Snectar int i; 165120945Snectar 166120945Snectar for (i = 0; i < len; ++i) 167120945Snectar printf ("%02x ", buf[i]); 168120945Snectar} 169120945Snectar 170178825Sdfr#ifndef MAP_FAILED 171178825Sdfr#define MAP_FAILED (-1) 172178825Sdfr#endif 173178825Sdfr 174178825Sdfrstatic char *current_test = "<uninit>"; 175178825Sdfrstatic char *current_state = "<uninit>"; 176178825Sdfr 177178825Sdfrstatic RETSIGTYPE 178178825Sdfrsegv_handler(int sig) 179178825Sdfr{ 180178825Sdfr int fd; 181178825Sdfr char msg[] = "SIGSEGV i current test: "; 182233294Sstas 183178825Sdfr fd = open("/dev/stdout", O_WRONLY, 0600); 184178825Sdfr if (fd >= 0) { 185178825Sdfr write(fd, msg, sizeof(msg)); 186178825Sdfr write(fd, current_test, strlen(current_test)); 187178825Sdfr write(fd, " ", 1); 188178825Sdfr write(fd, current_state, strlen(current_state)); 189178825Sdfr write(fd, "\n", 1); 190178825Sdfr close(fd); 191178825Sdfr } 192178825Sdfr _exit(1); 193178825Sdfr} 194178825Sdfr 195120945Snectarint 196120945Snectargeneric_test (const struct test_case *tests, 197120945Snectar unsigned ntests, 198120945Snectar size_t data_size, 199233294Sstas int (ASN1CALL *encode)(unsigned char *, size_t, void *, size_t *), 200233294Sstas int (ASN1CALL *length)(void *), 201233294Sstas int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *), 202233294Sstas int (ASN1CALL *free_data)(void *), 203233294Sstas int (*cmp)(void *a, void *b), 204233294Sstas int (ASN1CALL *copy)(const void *from, void *to)) 205120945Snectar{ 206178825Sdfr unsigned char *buf, *buf2; 207120945Snectar int i; 208120945Snectar int failures = 0; 209178825Sdfr void *data; 210178825Sdfr struct map_page *data_map, *buf_map, *buf2_map; 211120945Snectar 212233294Sstas#ifdef HAVE_SIGACTION 213178825Sdfr struct sigaction sa, osa; 214233294Sstas#endif 215120945Snectar 216120945Snectar for (i = 0; i < ntests; ++i) { 217120945Snectar int ret; 218178825Sdfr size_t sz, consumed_sz, length_sz, buf_sz; 219233294Sstas void *to = NULL; 220120945Snectar 221178825Sdfr current_test = tests[i].name; 222178825Sdfr 223178825Sdfr current_state = "init"; 224178825Sdfr 225233294Sstas#ifdef HAVE_SIGACTION 226178825Sdfr sigemptyset (&sa.sa_mask); 227178825Sdfr sa.sa_flags = 0; 228178825Sdfr#ifdef SA_RESETHAND 229178825Sdfr sa.sa_flags |= SA_RESETHAND; 230178825Sdfr#endif 231178825Sdfr sa.sa_handler = segv_handler; 232178825Sdfr sigaction (SIGSEGV, &sa, &osa); 233233294Sstas#endif 234178825Sdfr 235178825Sdfr data = map_alloc(OVERRUN, NULL, data_size, &data_map); 236178825Sdfr 237178825Sdfr buf_sz = tests[i].byte_len; 238178825Sdfr buf = map_alloc(UNDERRUN, NULL, buf_sz, &buf_map); 239178825Sdfr 240178825Sdfr current_state = "encode"; 241178825Sdfr ret = (*encode) (buf + buf_sz - 1, buf_sz, 242120945Snectar tests[i].val, &sz); 243120945Snectar if (ret != 0) { 244178825Sdfr printf ("encoding of %s failed %d\n", tests[i].name, ret); 245120945Snectar ++failures; 246178825Sdfr continue; 247120945Snectar } 248120945Snectar if (sz != tests[i].byte_len) { 249233294Sstas printf ("encoding of %s has wrong len (%lu != %lu)\n", 250233294Sstas tests[i].name, 251120945Snectar (unsigned long)sz, (unsigned long)tests[i].byte_len); 252120945Snectar ++failures; 253178825Sdfr continue; 254120945Snectar } 255120945Snectar 256178825Sdfr current_state = "length"; 257120945Snectar length_sz = (*length) (tests[i].val); 258120945Snectar if (sz != length_sz) { 259120945Snectar printf ("length for %s is bad (%lu != %lu)\n", 260120945Snectar tests[i].name, (unsigned long)length_sz, (unsigned long)sz); 261120945Snectar ++failures; 262178825Sdfr continue; 263120945Snectar } 264120945Snectar 265178825Sdfr current_state = "memcmp"; 266178825Sdfr if (memcmp (buf, tests[i].bytes, tests[i].byte_len) != 0) { 267120945Snectar printf ("encoding of %s has bad bytes:\n" 268120945Snectar "correct: ", tests[i].name); 269178825Sdfr print_bytes ((unsigned char *)tests[i].bytes, tests[i].byte_len); 270120945Snectar printf ("\nactual: "); 271178825Sdfr print_bytes (buf, sz); 272120945Snectar printf ("\n"); 273233294Sstas#if 0 274233294Sstas rk_dumpdata("correct", tests[i].bytes, tests[i].byte_len); 275233294Sstas rk_dumpdata("actual", buf, sz); 276233294Sstas exit (1); 277233294Sstas#endif 278120945Snectar ++failures; 279178825Sdfr continue; 280120945Snectar } 281178825Sdfr 282178825Sdfr buf2 = map_alloc(OVERRUN, buf, sz, &buf2_map); 283178825Sdfr 284178825Sdfr current_state = "decode"; 285178825Sdfr ret = (*decode) (buf2, sz, data, &consumed_sz); 286120945Snectar if (ret != 0) { 287178825Sdfr printf ("decoding of %s failed %d\n", tests[i].name, ret); 288120945Snectar ++failures; 289178825Sdfr continue; 290120945Snectar } 291120945Snectar if (sz != consumed_sz) { 292120945Snectar printf ("different length decoding %s (%ld != %ld)\n", 293233294Sstas tests[i].name, 294120945Snectar (unsigned long)sz, (unsigned long)consumed_sz); 295120945Snectar ++failures; 296178825Sdfr continue; 297120945Snectar } 298178825Sdfr current_state = "cmp"; 299178825Sdfr if ((*cmp)(data, tests[i].val) != 0) { 300120945Snectar printf ("%s: comparison failed\n", tests[i].name); 301120945Snectar ++failures; 302178825Sdfr continue; 303120945Snectar } 304233294Sstas 305233294Sstas current_state = "copy"; 306233294Sstas if (copy) { 307233294Sstas to = emalloc(data_size); 308233294Sstas ret = (*copy)(data, to); 309233294Sstas if (ret != 0) { 310233294Sstas printf ("copy of %s failed %d\n", tests[i].name, ret); 311233294Sstas ++failures; 312233294Sstas continue; 313233294Sstas } 314233294Sstas 315233294Sstas current_state = "cmp-copy"; 316233294Sstas if ((*cmp)(data, to) != 0) { 317233294Sstas printf ("%s: copy comparison failed\n", tests[i].name); 318233294Sstas ++failures; 319233294Sstas continue; 320233294Sstas } 321233294Sstas } 322233294Sstas 323178825Sdfr current_state = "free"; 324233294Sstas if (free_data) { 325178825Sdfr (*free_data)(data); 326233294Sstas if (to) { 327233294Sstas (*free_data)(to); 328233294Sstas free(to); 329233294Sstas } 330233294Sstas } 331178825Sdfr 332178825Sdfr current_state = "free"; 333178825Sdfr map_free(buf_map, tests[i].name, "encode"); 334178825Sdfr map_free(buf2_map, tests[i].name, "decode"); 335178825Sdfr map_free(data_map, tests[i].name, "data"); 336178825Sdfr 337233294Sstas#ifdef HAVE_SIGACTION 338178825Sdfr sigaction (SIGSEGV, &osa, NULL); 339233294Sstas#endif 340120945Snectar } 341178825Sdfr current_state = "done"; 342120945Snectar return failures; 343120945Snectar} 344178825Sdfr 345178825Sdfr/* 346178825Sdfr * check for failures 347233294Sstas * 348178825Sdfr * a test size (byte_len) of -1 means that the test tries to trigger a 349178825Sdfr * integer overflow (and later a malloc of to little memory), just 350178825Sdfr * allocate some memory and hope that is enough for that test. 351178825Sdfr */ 352178825Sdfr 353178825Sdfrint 354178825Sdfrgeneric_decode_fail (const struct test_case *tests, 355178825Sdfr unsigned ntests, 356178825Sdfr size_t data_size, 357233294Sstas int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *)) 358178825Sdfr{ 359178825Sdfr unsigned char *buf; 360178825Sdfr int i; 361178825Sdfr int failures = 0; 362178825Sdfr void *data; 363178825Sdfr struct map_page *data_map, *buf_map; 364178825Sdfr 365233294Sstas#ifdef HAVE_SIGACTION 366178825Sdfr struct sigaction sa, osa; 367233294Sstas#endif 368178825Sdfr 369178825Sdfr for (i = 0; i < ntests; ++i) { 370178825Sdfr int ret; 371178825Sdfr size_t sz; 372178825Sdfr const void *bytes; 373233294Sstas 374178825Sdfr current_test = tests[i].name; 375178825Sdfr 376178825Sdfr current_state = "init"; 377178825Sdfr 378233294Sstas#ifdef HAVE_SIGACTION 379178825Sdfr sigemptyset (&sa.sa_mask); 380178825Sdfr sa.sa_flags = 0; 381178825Sdfr#ifdef SA_RESETHAND 382178825Sdfr sa.sa_flags |= SA_RESETHAND; 383178825Sdfr#endif 384178825Sdfr sa.sa_handler = segv_handler; 385178825Sdfr sigaction (SIGSEGV, &sa, &osa); 386233294Sstas#endif 387178825Sdfr 388178825Sdfr data = map_alloc(OVERRUN, NULL, data_size, &data_map); 389178825Sdfr 390178825Sdfr if (tests[i].byte_len < 0xffffff && tests[i].byte_len >= 0) { 391178825Sdfr sz = tests[i].byte_len; 392178825Sdfr bytes = tests[i].bytes; 393178825Sdfr } else { 394178825Sdfr sz = 4096; 395178825Sdfr bytes = NULL; 396178825Sdfr } 397233294Sstas 398178825Sdfr buf = map_alloc(OVERRUN, bytes, sz, &buf_map); 399178825Sdfr 400178825Sdfr if (tests[i].byte_len == -1) 401178825Sdfr memset(buf, 0, sz); 402178825Sdfr 403178825Sdfr current_state = "decode"; 404178825Sdfr ret = (*decode) (buf, tests[i].byte_len, data, &sz); 405178825Sdfr if (ret == 0) { 406178825Sdfr printf ("sucessfully decoded %s\n", tests[i].name); 407178825Sdfr ++failures; 408178825Sdfr continue; 409178825Sdfr } 410178825Sdfr 411178825Sdfr current_state = "free"; 412178825Sdfr if (buf) 413178825Sdfr map_free(buf_map, tests[i].name, "encode"); 414178825Sdfr map_free(data_map, tests[i].name, "data"); 415178825Sdfr 416233294Sstas#ifdef HAVE_SIGACTION 417178825Sdfr sigaction (SIGSEGV, &osa, NULL); 418233294Sstas#endif 419178825Sdfr } 420178825Sdfr current_state = "done"; 421178825Sdfr return failures; 422178825Sdfr} 423