source: openpam/trunk/t/t_rfc4648.c @ 783

Last change on this file since 783 was 783, checked in by Dag-Erling Smørgrav, 7 years ago

Fix buffer overflow in the b64complete test case by increasing the size
of the buffer used in tests.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1/*-
2 * Copyright (c) 2013-2014 Universitetet i Oslo
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 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 *    products derived from this software without specific prior written
15 *    permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: t_rfc4648.c 783 2014-03-10 11:13:05Z des $
30 */
31
32#ifdef HAVE_CONFIG_H
33# include "config.h"
34#endif
35
36#include <errno.h>
37#include <stdint.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#include <security/oath.h>
44
45#include "t.h"
46
47struct t_case {
48        const char *desc;
49        int (*func)(const char *, size_t, char *, size_t *);
50        const char *in;         /* input string  */
51        size_t ilen;            /* input length */
52        const char *out;        /* expected output string or NULL */
53        size_t blen;            /* initial value for olen or 0*/
54        size_t olen;            /* expected value for olen */
55        int ret;                /* expected return value */
56        int err;                /* expected errno if ret != 0 */
57};
58
59/* basic encoding / decoding */
60#define T_ENCODE_N(N, i, o)                                             \
61        { "base"#N"_enc("#i")", base##N##_enc, i, sizeof i - 1,         \
62          o, sizeof o, sizeof o, 0, 0 }
63#define T_DECODE_N(N, i, o)                                             \
64        { "base"#N"_dec("#i")", base##N##_dec, i, sizeof i - 1,         \
65          o, sizeof o - 1, sizeof o - 1, 0, 0 }
66#define T_ENCODE(p, b32, b64)                                           \
67        T_ENCODE_N(32, p, b32), T_ENCODE_N(64, p, b64)
68#define T_DECODE(p, b32, b64)                                           \
69        T_DECODE_N(32, b32, p), T_DECODE_N(64, b64, p)
70
71/* roundtrip encoding tests */
72#define T_ENCDEC_N(N, p, e)                                             \
73        T_ENCODE_N(N, p, e), T_DECODE_N(N, e, p)
74#define T_ENCDEC(p, b32, b64)                                           \
75        T_ENCDEC_N(32, p, b32), T_ENCDEC_N(64, p, b64)
76
77/* decoding failure */
78#define T_DECODE_FAIL_N(N, e, i)                                        \
79        { "base"#N"_dec("#i")", base##N##_dec, i, sizeof i - 1,         \
80          NULL, 0, 0, -1, e }
81#define T_DECODE_FAIL(e, b32, b64)                                      \
82        T_DECODE_FAIL_N(32, e, b32), T_DECODE_FAIL_N(64, e, b64)
83
84/* input string shorter than input length */
85#define T_SHORT_INPUT_DEC(N, i)                                         \
86        { "base"#N"_dec (short input)", base##N##_dec, i, sizeof i + 2, \
87          NULL, 0, base##N##_declen(sizeof i - 1), 0, 0 }
88#define T_SHORT_INPUT()                                                 \
89        T_SHORT_INPUT_DEC(32, "AAAAAAAA"),                              \
90        T_SHORT_INPUT_DEC(64, "AAAA")
91
92/* output string longer than output length */
93#define T_LONG_OUTPUT_ENC(N, i)                                         \
94        { "base"#N"_enc (long output)", base##N##_enc, i, sizeof i - 1, \
95          NULL, 1, base##N##_enclen(sizeof i - 1) + 1, -1, ENOSPC }
96#define T_LONG_OUTPUT_DEC(N, i)                                         \
97        { "base"#N"_dec (long output)", base##N##_dec, "AAAAAAAA", 8,   \
98          NULL, 1, base##N##_declen(sizeof i - 1), -1, ENOSPC }
99#define T_LONG_OUTPUT()                                                 \
100        T_LONG_OUTPUT_ENC(32, "foo"),                                   \
101        T_LONG_OUTPUT_DEC(32, "AAAAAAAA"),                              \
102        T_LONG_OUTPUT_ENC(64, "foo"),                                   \
103        T_LONG_OUTPUT_DEC(64, "AAAA")
104
105static const char b64alphabet[] =
106    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
107    "abcdefghijklmnopqrstuvwxyz"
108    "0123456789+/";
109static const char b64complete[] = {
110        0x00, 0x10, 0x83, 0x10, 0x51, 0x87,
111        0x20, 0x92, 0x8b, 0x30, 0xd3, 0x8f,
112        0x41, 0x14, 0x93, 0x51, 0x55, 0x97,
113        0x61, 0x96, 0x9b, 0x71, 0xd7, 0x9f,
114        0x82, 0x18, 0xa3, 0x92, 0x59, 0xa7,
115        0xa2, 0x9a, 0xab, 0xb2, 0xdb, 0xaf,
116        0xc3, 0x1c, 0xb3, 0xd3, 0x5d, 0xb7,
117        0xe3, 0x9e, 0xbb, 0xf3, 0xdf, 0xbf,
118        0x00
119};
120
121static const char b32alphabet[] =
122    "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
123static const char b32complete[] = {
124        0x00, 0x44, 0x32, 0x14, 0xc7,
125        0x42, 0x54, 0xb6, 0x35, 0xcf,
126        0x84, 0x65, 0x3a, 0x56, 0xd7,
127        0xc6, 0x75, 0xbe, 0x77, 0xdf,
128        0x00
129};
130
131static struct t_case t_cases[] = {
132        /* complete alphabet */
133        T_ENCDEC_N(32, b32complete, b32alphabet),
134        T_ENCDEC_N(64, b64complete, b64alphabet),
135
136        /* test vectors from RFC 4648 */
137        /*       plain          base32                  base64 */
138        T_ENCDEC("",            "",                     ""),
139        T_ENCDEC("f",           "MY======",             "Zg=="),
140        T_ENCDEC("fo",          "MZXQ====",             "Zm8="),
141        T_ENCDEC("foo",         "MZXW6===",             "Zm9v"),
142        T_ENCDEC("foob",        "MZXW6YQ=",             "Zm9vYg=="),
143        T_ENCDEC("fooba",       "MZXW6YTB",             "Zm9vYmE="),
144        T_ENCDEC("foobar",      "MZXW6YTBOI======",     "Zm9vYmFy"),
145
146        /* zeroes */
147        T_ENCDEC("\0\0\0",      "AAAAA===",             "AAAA"),
148
149        /* sloppy padding */
150        T_DECODE("f",           "MY=",                  "Zg="),
151        T_DECODE("f",           "MY",                   "Zg"),
152
153        /* whitespace */
154        /*       plain          base32                  base64 */
155        T_DECODE("tst",         "ORZX I===",            "dH N0"),
156        T_DECODE("tst",         "ORZX\tI===",           "dH\tN0"),
157        T_DECODE("tst",         "ORZX\rI===",           "dH\rN0"),
158        T_DECODE("tst",         "ORZX\nI===",           "dH\nN0"),
159
160        /* invalid character in data */
161        T_DECODE_FAIL(EINVAL,   "AA!AAAAAA",            "AA!A"),
162
163        /* invalid character in padding */
164        T_DECODE_FAIL(EINVAL,   "AAAAA==!",             "AA=!"),
165
166        /* padding with no data */
167        T_DECODE_FAIL(EINVAL,   "AAAAAAAA=",            "AAAA="),
168
169        /* data after padding */
170        T_DECODE_FAIL(EINVAL,   "AA=A",                 "AA=A"),
171
172        /* padding in incorrect location */
173        T_DECODE_FAIL_N(32, EINVAL, "A======="),
174        T_DECODE_FAIL_N(32, EINVAL, "AAA====="),
175        T_DECODE_FAIL_N(32, EINVAL, "AAAAAA=="),
176        T_DECODE_FAIL_N(64, EINVAL, "A==="),
177
178        /* various error conditions */
179        T_SHORT_INPUT(),
180        T_LONG_OUTPUT(),
181};
182
183/*
184 * Encoding test function
185 */
186static int
187t_rfc4648(void *arg)
188{
189        struct t_case *t = arg;
190        char buf[256];
191        size_t len;
192        int ret;
193
194        len = t->blen ? t->blen : sizeof buf;
195        ret = t->func(t->in, t->ilen, buf, &len);
196        if (ret != t->ret) {
197                t_verbose("expected return code %d, got %d\n",
198                    t->ret, ret);
199                return (0);
200        }
201        if (t->out && len != t->olen) {
202                t_verbose("expected output length %zu, got %zu\n",
203                    t->olen, len);
204                return (0);
205        }
206        if (t->ret != 0 && errno != t->err) {
207                t_verbose("expected errno %d, got %d\n",
208                    t->err, errno);
209                return (0);
210        }
211        if (t->ret == 0 && t->out && strncmp(buf, t->out, len) != 0) {
212                t_verbose("expected '%.*s' got '%.*s'\n",
213                    (int)t->olen, t->out, (int)len, buf);
214                return (0);
215        }
216        return (1);
217}
218
219/*
220 * Generate the test plan
221 */
222const struct t_test **
223t_prepare(int argc, char *argv[])
224{
225        struct t_test **plan, *tests;
226        int i, n;
227
228        (void)argc;
229        (void)argv;
230        n = sizeof t_cases / sizeof t_cases[0];
231        if ((plan = calloc(n + 1, sizeof *plan)) == NULL ||
232            (tests = calloc(n, sizeof *tests)) == NULL)
233                return (NULL);
234        for (i = 0; i < n; ++i) {
235                plan[i] = &tests[i];
236                tests[i].func = t_rfc4648;
237                tests[i].desc = t_cases[i].desc;
238                tests[i].arg = &t_cases[i];
239        }
240        plan[n] = NULL;
241        return ((const struct t_test **)plan);
242}
243
244/*
245 * Cleanup
246 */
247void
248t_cleanup(void)
249{
250}
Note: See TracBrowser for help on using the repository browser.