xref: /freebsd/crypto/krb5/src/tests/fuzzing/fuzz_util.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* tests/fuzzing/fuzz_util.c */
3 /*
4  * Copyright (C) 2024 by Arjun. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Fuzzing harness implementation for k5_base64_decode, k5_hex_decode
34  * krb5_parse_name and k5_parse_host_string.
35  */
36 
37 #include "autoconf.h"
38 #include <k5-int.h>
39 #include <k5-base64.h>
40 #include <k5-hex.h>
41 #include <string.h>
42 #include <k5-utf8.h>
43 
44 #include <hashtab.c>
45 
46 #define kMinInputLength 2
47 #define kMaxInputLength 256
48 
49 extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
50 
51 static void
fuzz_base64(const char * data_in,size_t size)52 fuzz_base64(const char *data_in, size_t size)
53 {
54     size_t len;
55 
56     free(k5_base64_encode(data_in, size));
57     free(k5_base64_decode(data_in, &len));
58 }
59 
60 static void
fuzz_hashtab(const char * data_in,size_t size)61 fuzz_hashtab(const char *data_in, size_t size)
62 {
63     int st;
64     struct k5_hashtab *ht;
65 
66     k5_hashtab_create(NULL, 4, &ht);
67     if (ht == NULL)
68         return;
69 
70     k5_hashtab_add(ht, data_in, size, &st);
71 
72     k5_hashtab_free(ht);
73 }
74 
75 static void
fuzz_hex(const char * data_in,size_t size)76 fuzz_hex(const char *data_in, size_t size)
77 {
78     char *hex;
79     uint8_t *bytes;
80     size_t len;
81 
82     if (k5_hex_encode(data_in, size, 0, &hex) == 0)
83         free(hex);
84 
85     if (k5_hex_encode(data_in, size, 1, &hex) == 0)
86         free(hex);
87 
88     if (k5_hex_decode(data_in, &bytes, &len) == 0)
89         free(bytes);
90 }
91 
92 static void
fuzz_name(const char * data_in,size_t size)93 fuzz_name(const char *data_in, size_t size)
94 {
95     krb5_context context;
96     krb5_principal fuzzing;
97 
98     if (krb5_init_context(&context) != 0)
99         return;
100 
101     krb5_parse_name(context, data_in, &fuzzing);
102 
103     krb5_free_principal(context, fuzzing);
104     krb5_free_context(context);
105 }
106 
107 static void
fuzz_parse_host(const char * data_in,size_t size)108 fuzz_parse_host(const char *data_in, size_t size)
109 {
110     char *host_out = NULL;
111     int port_out = -1;
112 
113     if (k5_parse_host_string(data_in, 1, &host_out, &port_out) == 0)
114         free(host_out);
115 }
116 
117 static void
fuzz_utf8(const char * data_in,size_t size)118 fuzz_utf8(const char *data_in, size_t size)
119 {
120     krb5_ucs4 u = 0;
121     char *utf8;
122     uint8_t *utf16;
123     size_t utf16len;
124 
125     krb5int_utf8_to_ucs4(data_in, &u);
126 
127     k5_utf8_to_utf16le(data_in, &utf16, &utf16len);
128     if (utf16 != NULL)
129         free(utf16);
130 
131     k5_utf16le_to_utf8((const uint8_t *)data_in, size, &utf8);
132     if (utf8 != NULL)
133         free(utf8);
134 }
135 
136 extern int
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)137 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
138 {
139     krb5_error_code ret;
140     char *data_in;
141 
142     if (size < kMinInputLength || size > kMaxInputLength)
143         return 0;
144 
145     data_in = k5memdup0(data, size, &ret);
146     if (data_in == NULL)
147         return 0;
148 
149     fuzz_base64(data_in, size);
150     fuzz_hashtab(data_in, size);
151     fuzz_hex(data_in, size);
152     fuzz_name(data_in, size);
153     fuzz_parse_host(data_in, size);
154     fuzz_utf8(data_in, size);
155 
156     free(data_in);
157 
158     return 0;
159 }
160