xref: /freebsd/crypto/krb5/src/tests/fuzzing/fuzz_crypto.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* tests/fuzzing/fuzz_crypto.c - fuzzing harness for general crypto */
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 #include "autoconf.h"
33 #include <k5-int.h>
34 #include <crypto_int.h>
35 
36 #define kMinInputLength 2
37 #define kMaxInputLength 512
38 
39 extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
40 
41 static void
fuzz_checksum(krb5_cksumtype sumtype,krb5_keyblock keyblock,krb5_keyusage usage,krb5_data data)42 fuzz_checksum(krb5_cksumtype sumtype, krb5_keyblock keyblock,
43               krb5_keyusage usage, krb5_data data)
44 {
45     krb5_error_code ret;
46     krb5_checksum cksum;
47     krb5_boolean valid;
48 
49     ret = krb5_c_make_checksum(NULL, sumtype, &keyblock, usage, &data, &cksum);
50     if (ret)
51         return;
52 
53     ret = krb5_c_verify_checksum(NULL, &keyblock, usage, &data, &cksum,
54                                  &valid);
55     if (ret || !valid)
56         abort();
57 
58     krb5_free_checksum_contents(NULL, &cksum);
59 }
60 
61 static void
fuzz_crypt(krb5_keyblock keyblock,krb5_enctype enctype,krb5_keyusage usage,krb5_data data)62 fuzz_crypt(krb5_keyblock keyblock, krb5_enctype enctype,
63            krb5_keyusage usage, krb5_data data)
64 {
65     krb5_error_code ret;
66     krb5_enc_data encoded = { 0 };
67     krb5_data decoded = empty_data();
68     size_t enclen;
69 
70     ret = krb5_c_encrypt_length(NULL, enctype, data.length, &enclen);
71     if (ret)
72         return;
73 
74     encoded.magic = KV5M_ENC_DATA;
75     encoded.enctype = enctype;
76 
77     ret = alloc_data(&encoded.ciphertext, enclen);
78     if (ret)
79         return;
80 
81     ret = alloc_data(&decoded, data.length);
82     if (ret) {
83         krb5_free_data_contents(NULL, &encoded.ciphertext);
84         return;
85     }
86 
87     ret = krb5_c_encrypt(NULL, &keyblock, usage, NULL, &data, &encoded);
88     if (ret)
89         goto cleanup;
90 
91     ret = krb5_c_decrypt(NULL, &keyblock, usage, NULL, &encoded, &decoded);
92     if (ret)
93         goto cleanup;
94 
95     if (memcmp(data.data, decoded.data, data.length) != 0)
96         abort();
97 
98 cleanup:
99     krb5_free_data_contents(NULL, &encoded.ciphertext);
100     krb5_free_data_contents(NULL, &decoded);
101 }
102 
103 static void
fuzz_prf(krb5_keyblock keyblock,krb5_enctype enctype,krb5_data data)104 fuzz_prf(krb5_keyblock keyblock, krb5_enctype enctype, krb5_data data)
105 {
106     krb5_error_code ret;
107     krb5_data output;
108     size_t prfsz;
109 
110     ret = krb5_c_prf_length(NULL, enctype, &prfsz);
111     if (ret)
112         return;
113 
114     ret = alloc_data(&output, prfsz);
115     if (ret)
116         return;
117 
118     krb5_c_prf(NULL, &keyblock, &data, &output);
119 
120     krb5_free_data_contents(NULL, &output);
121 }
122 
123 static void
fuzz_setup(krb5_enctype enctype,krb5_cksumtype sumtype,krb5_keyusage usage,krb5_data data)124 fuzz_setup(krb5_enctype enctype, krb5_cksumtype sumtype,
125            krb5_keyusage usage, krb5_data data)
126 {
127     krb5_error_code ret;
128     krb5_keyblock keyblock;
129 
130     ret = krb5_c_make_random_key(NULL, enctype, &keyblock);
131     if (ret)
132         return;
133 
134     fuzz_checksum(sumtype, keyblock, usage, data);
135     fuzz_crypt(keyblock, enctype, usage, data);
136     fuzz_prf(keyblock, enctype, data);
137 
138     krb5_free_keyblock_contents(NULL, &keyblock);
139 }
140 
141 int
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)142 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
143 {
144     krb5_data data_in;
145 
146     if (size < kMinInputLength || size > kMaxInputLength)
147         return 0;
148 
149     data_in = make_data((void *)data, size);
150 
151     fuzz_setup(ENCTYPE_DES3_CBC_SHA1, CKSUMTYPE_HMAC_SHA1_DES3, 0, data_in);
152     fuzz_setup(ENCTYPE_ARCFOUR_HMAC, CKSUMTYPE_MD5_HMAC_ARCFOUR, 1, data_in);
153     fuzz_setup(ENCTYPE_ARCFOUR_HMAC, CKSUMTYPE_HMAC_MD5_ARCFOUR, 2, data_in);
154     fuzz_setup(ENCTYPE_ARCFOUR_HMAC_EXP, CKSUMTYPE_RSA_MD4, 3, data_in);
155     fuzz_setup(ENCTYPE_ARCFOUR_HMAC_EXP, CKSUMTYPE_RSA_MD5, 4, data_in);
156     fuzz_setup(ENCTYPE_ARCFOUR_HMAC_EXP, CKSUMTYPE_SHA1, 5, data_in);
157     fuzz_setup(ENCTYPE_AES128_CTS_HMAC_SHA1_96, CKSUMTYPE_HMAC_SHA1_96_AES128,
158                6, data_in);
159     fuzz_setup(ENCTYPE_AES256_CTS_HMAC_SHA1_96, CKSUMTYPE_HMAC_SHA1_96_AES256,
160                7, data_in);
161     fuzz_setup(ENCTYPE_CAMELLIA128_CTS_CMAC, CKSUMTYPE_CMAC_CAMELLIA128,
162                8, data_in);
163     fuzz_setup(ENCTYPE_CAMELLIA256_CTS_CMAC, CKSUMTYPE_CMAC_CAMELLIA256,
164                9, data_in);
165     fuzz_setup(ENCTYPE_AES128_CTS_HMAC_SHA256_128,
166                CKSUMTYPE_HMAC_SHA256_128_AES128, 10, data_in);
167     fuzz_setup(ENCTYPE_AES256_CTS_HMAC_SHA384_192,
168                CKSUMTYPE_HMAC_SHA384_192_AES256, 11, data_in);
169 
170     return 0;
171 }
172