1*f1c4c3daSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*f1c4c3daSCy Schubert /* tests/fuzzing/fuzz_crypto.c - fuzzing harness for general crypto */
3*f1c4c3daSCy Schubert /*
4*f1c4c3daSCy Schubert * Copyright (C) 2024 by Arjun. All rights reserved.
5*f1c4c3daSCy Schubert *
6*f1c4c3daSCy Schubert * Redistribution and use in source and binary forms, with or without
7*f1c4c3daSCy Schubert * modification, are permitted provided that the following conditions
8*f1c4c3daSCy Schubert * are met:
9*f1c4c3daSCy Schubert *
10*f1c4c3daSCy Schubert * * Redistributions of source code must retain the above copyright
11*f1c4c3daSCy Schubert * notice, this list of conditions and the following disclaimer.
12*f1c4c3daSCy Schubert *
13*f1c4c3daSCy Schubert * * Redistributions in binary form must reproduce the above copyright
14*f1c4c3daSCy Schubert * notice, this list of conditions and the following disclaimer in
15*f1c4c3daSCy Schubert * the documentation and/or other materials provided with the
16*f1c4c3daSCy Schubert * distribution.
17*f1c4c3daSCy Schubert *
18*f1c4c3daSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19*f1c4c3daSCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20*f1c4c3daSCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21*f1c4c3daSCy Schubert * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22*f1c4c3daSCy Schubert * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23*f1c4c3daSCy Schubert * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24*f1c4c3daSCy Schubert * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25*f1c4c3daSCy Schubert * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*f1c4c3daSCy Schubert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27*f1c4c3daSCy Schubert * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*f1c4c3daSCy Schubert * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29*f1c4c3daSCy Schubert * OF THE POSSIBILITY OF SUCH DAMAGE.
30*f1c4c3daSCy Schubert */
31*f1c4c3daSCy Schubert
32*f1c4c3daSCy Schubert #include "autoconf.h"
33*f1c4c3daSCy Schubert #include <k5-int.h>
34*f1c4c3daSCy Schubert #include <crypto_int.h>
35*f1c4c3daSCy Schubert
36*f1c4c3daSCy Schubert #define kMinInputLength 2
37*f1c4c3daSCy Schubert #define kMaxInputLength 512
38*f1c4c3daSCy Schubert
39*f1c4c3daSCy Schubert extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
40*f1c4c3daSCy Schubert
41*f1c4c3daSCy Schubert static void
fuzz_checksum(krb5_cksumtype sumtype,krb5_keyblock keyblock,krb5_keyusage usage,krb5_data data)42*f1c4c3daSCy Schubert fuzz_checksum(krb5_cksumtype sumtype, krb5_keyblock keyblock,
43*f1c4c3daSCy Schubert krb5_keyusage usage, krb5_data data)
44*f1c4c3daSCy Schubert {
45*f1c4c3daSCy Schubert krb5_error_code ret;
46*f1c4c3daSCy Schubert krb5_checksum cksum;
47*f1c4c3daSCy Schubert krb5_boolean valid;
48*f1c4c3daSCy Schubert
49*f1c4c3daSCy Schubert ret = krb5_c_make_checksum(NULL, sumtype, &keyblock, usage, &data, &cksum);
50*f1c4c3daSCy Schubert if (ret)
51*f1c4c3daSCy Schubert return;
52*f1c4c3daSCy Schubert
53*f1c4c3daSCy Schubert ret = krb5_c_verify_checksum(NULL, &keyblock, usage, &data, &cksum,
54*f1c4c3daSCy Schubert &valid);
55*f1c4c3daSCy Schubert if (ret || !valid)
56*f1c4c3daSCy Schubert abort();
57*f1c4c3daSCy Schubert
58*f1c4c3daSCy Schubert krb5_free_checksum_contents(NULL, &cksum);
59*f1c4c3daSCy Schubert }
60*f1c4c3daSCy Schubert
61*f1c4c3daSCy Schubert static void
fuzz_crypt(krb5_keyblock keyblock,krb5_enctype enctype,krb5_keyusage usage,krb5_data data)62*f1c4c3daSCy Schubert fuzz_crypt(krb5_keyblock keyblock, krb5_enctype enctype,
63*f1c4c3daSCy Schubert krb5_keyusage usage, krb5_data data)
64*f1c4c3daSCy Schubert {
65*f1c4c3daSCy Schubert krb5_error_code ret;
66*f1c4c3daSCy Schubert krb5_enc_data encoded = { 0 };
67*f1c4c3daSCy Schubert krb5_data decoded = empty_data();
68*f1c4c3daSCy Schubert size_t enclen;
69*f1c4c3daSCy Schubert
70*f1c4c3daSCy Schubert ret = krb5_c_encrypt_length(NULL, enctype, data.length, &enclen);
71*f1c4c3daSCy Schubert if (ret)
72*f1c4c3daSCy Schubert return;
73*f1c4c3daSCy Schubert
74*f1c4c3daSCy Schubert encoded.magic = KV5M_ENC_DATA;
75*f1c4c3daSCy Schubert encoded.enctype = enctype;
76*f1c4c3daSCy Schubert
77*f1c4c3daSCy Schubert ret = alloc_data(&encoded.ciphertext, enclen);
78*f1c4c3daSCy Schubert if (ret)
79*f1c4c3daSCy Schubert return;
80*f1c4c3daSCy Schubert
81*f1c4c3daSCy Schubert ret = alloc_data(&decoded, data.length);
82*f1c4c3daSCy Schubert if (ret) {
83*f1c4c3daSCy Schubert krb5_free_data_contents(NULL, &encoded.ciphertext);
84*f1c4c3daSCy Schubert return;
85*f1c4c3daSCy Schubert }
86*f1c4c3daSCy Schubert
87*f1c4c3daSCy Schubert ret = krb5_c_encrypt(NULL, &keyblock, usage, NULL, &data, &encoded);
88*f1c4c3daSCy Schubert if (ret)
89*f1c4c3daSCy Schubert goto cleanup;
90*f1c4c3daSCy Schubert
91*f1c4c3daSCy Schubert ret = krb5_c_decrypt(NULL, &keyblock, usage, NULL, &encoded, &decoded);
92*f1c4c3daSCy Schubert if (ret)
93*f1c4c3daSCy Schubert goto cleanup;
94*f1c4c3daSCy Schubert
95*f1c4c3daSCy Schubert if (memcmp(data.data, decoded.data, data.length) != 0)
96*f1c4c3daSCy Schubert abort();
97*f1c4c3daSCy Schubert
98*f1c4c3daSCy Schubert cleanup:
99*f1c4c3daSCy Schubert krb5_free_data_contents(NULL, &encoded.ciphertext);
100*f1c4c3daSCy Schubert krb5_free_data_contents(NULL, &decoded);
101*f1c4c3daSCy Schubert }
102*f1c4c3daSCy Schubert
103*f1c4c3daSCy Schubert static void
fuzz_prf(krb5_keyblock keyblock,krb5_enctype enctype,krb5_data data)104*f1c4c3daSCy Schubert fuzz_prf(krb5_keyblock keyblock, krb5_enctype enctype, krb5_data data)
105*f1c4c3daSCy Schubert {
106*f1c4c3daSCy Schubert krb5_error_code ret;
107*f1c4c3daSCy Schubert krb5_data output;
108*f1c4c3daSCy Schubert size_t prfsz;
109*f1c4c3daSCy Schubert
110*f1c4c3daSCy Schubert ret = krb5_c_prf_length(NULL, enctype, &prfsz);
111*f1c4c3daSCy Schubert if (ret)
112*f1c4c3daSCy Schubert return;
113*f1c4c3daSCy Schubert
114*f1c4c3daSCy Schubert ret = alloc_data(&output, prfsz);
115*f1c4c3daSCy Schubert if (ret)
116*f1c4c3daSCy Schubert return;
117*f1c4c3daSCy Schubert
118*f1c4c3daSCy Schubert krb5_c_prf(NULL, &keyblock, &data, &output);
119*f1c4c3daSCy Schubert
120*f1c4c3daSCy Schubert krb5_free_data_contents(NULL, &output);
121*f1c4c3daSCy Schubert }
122*f1c4c3daSCy Schubert
123*f1c4c3daSCy Schubert static void
fuzz_setup(krb5_enctype enctype,krb5_cksumtype sumtype,krb5_keyusage usage,krb5_data data)124*f1c4c3daSCy Schubert fuzz_setup(krb5_enctype enctype, krb5_cksumtype sumtype,
125*f1c4c3daSCy Schubert krb5_keyusage usage, krb5_data data)
126*f1c4c3daSCy Schubert {
127*f1c4c3daSCy Schubert krb5_error_code ret;
128*f1c4c3daSCy Schubert krb5_keyblock keyblock;
129*f1c4c3daSCy Schubert
130*f1c4c3daSCy Schubert ret = krb5_c_make_random_key(NULL, enctype, &keyblock);
131*f1c4c3daSCy Schubert if (ret)
132*f1c4c3daSCy Schubert return;
133*f1c4c3daSCy Schubert
134*f1c4c3daSCy Schubert fuzz_checksum(sumtype, keyblock, usage, data);
135*f1c4c3daSCy Schubert fuzz_crypt(keyblock, enctype, usage, data);
136*f1c4c3daSCy Schubert fuzz_prf(keyblock, enctype, data);
137*f1c4c3daSCy Schubert
138*f1c4c3daSCy Schubert krb5_free_keyblock_contents(NULL, &keyblock);
139*f1c4c3daSCy Schubert }
140*f1c4c3daSCy Schubert
141*f1c4c3daSCy Schubert int
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)142*f1c4c3daSCy Schubert LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
143*f1c4c3daSCy Schubert {
144*f1c4c3daSCy Schubert krb5_data data_in;
145*f1c4c3daSCy Schubert
146*f1c4c3daSCy Schubert if (size < kMinInputLength || size > kMaxInputLength)
147*f1c4c3daSCy Schubert return 0;
148*f1c4c3daSCy Schubert
149*f1c4c3daSCy Schubert data_in = make_data((void *)data, size);
150*f1c4c3daSCy Schubert
151*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_DES3_CBC_SHA1, CKSUMTYPE_HMAC_SHA1_DES3, 0, data_in);
152*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_ARCFOUR_HMAC, CKSUMTYPE_MD5_HMAC_ARCFOUR, 1, data_in);
153*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_ARCFOUR_HMAC, CKSUMTYPE_HMAC_MD5_ARCFOUR, 2, data_in);
154*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_ARCFOUR_HMAC_EXP, CKSUMTYPE_RSA_MD4, 3, data_in);
155*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_ARCFOUR_HMAC_EXP, CKSUMTYPE_RSA_MD5, 4, data_in);
156*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_ARCFOUR_HMAC_EXP, CKSUMTYPE_SHA1, 5, data_in);
157*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_AES128_CTS_HMAC_SHA1_96, CKSUMTYPE_HMAC_SHA1_96_AES128,
158*f1c4c3daSCy Schubert 6, data_in);
159*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_AES256_CTS_HMAC_SHA1_96, CKSUMTYPE_HMAC_SHA1_96_AES256,
160*f1c4c3daSCy Schubert 7, data_in);
161*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_CAMELLIA128_CTS_CMAC, CKSUMTYPE_CMAC_CAMELLIA128,
162*f1c4c3daSCy Schubert 8, data_in);
163*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_CAMELLIA256_CTS_CMAC, CKSUMTYPE_CMAC_CAMELLIA256,
164*f1c4c3daSCy Schubert 9, data_in);
165*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_AES128_CTS_HMAC_SHA256_128,
166*f1c4c3daSCy Schubert CKSUMTYPE_HMAC_SHA256_128_AES128, 10, data_in);
167*f1c4c3daSCy Schubert fuzz_setup(ENCTYPE_AES256_CTS_HMAC_SHA384_192,
168*f1c4c3daSCy Schubert CKSUMTYPE_HMAC_SHA384_192_AES256, 11, data_in);
169*f1c4c3daSCy Schubert
170*f1c4c3daSCy Schubert return 0;
171*f1c4c3daSCy Schubert }
172