Line data Source code
1 : /**
2 : * @file crypto.c
3 : * @brief Mock implementation of crypto.h for unit testing.
4 : *
5 : * Provides deterministic outputs and call counters so tests can verify
6 : * crypto usage without depending on OpenSSL.
7 : */
8 :
9 : #include "crypto.h"
10 :
11 : #include <stdlib.h>
12 : #include <string.h>
13 :
14 : /* ---- Internal mock state ---- */
15 :
16 : static struct {
17 : int sha256_count;
18 : unsigned char sha256_output[32];
19 :
20 : int sha1_count;
21 : unsigned char sha1_output[20];
22 :
23 : int sha512_count;
24 : unsigned char sha512_output[64];
25 :
26 : int pbkdf2_count;
27 : unsigned char pbkdf2_output[128];
28 : size_t pbkdf2_output_len;
29 :
30 : int encrypt_block_count;
31 : int decrypt_block_count;
32 :
33 : int rand_bytes_count;
34 : unsigned char rand_bytes_buf[256];
35 : size_t rand_bytes_len;
36 :
37 : int set_encrypt_key_count;
38 : int set_decrypt_key_count;
39 :
40 : int rsa_encrypt_count;
41 : int rsa_encrypt_result_len;
42 : unsigned char rsa_encrypt_result[512];
43 :
44 : int bn_mod_exp_count;
45 : unsigned char bn_mod_exp_result[512];
46 : size_t bn_mod_exp_result_len;
47 : } g_mock;
48 :
49 : /* ---- Test accessor functions ---- */
50 :
51 149 : void mock_crypto_reset(void) {
52 149 : memset(&g_mock, 0, sizeof(g_mock));
53 149 : }
54 :
55 1 : void mock_crypto_set_sha256_output(const unsigned char hash[32]) {
56 1 : memcpy(g_mock.sha256_output, hash, 32);
57 1 : }
58 :
59 5 : int mock_crypto_sha256_call_count(void) {
60 5 : return g_mock.sha256_count;
61 : }
62 :
63 0 : int mock_crypto_sha1_call_count(void) {
64 0 : return g_mock.sha1_count;
65 : }
66 :
67 0 : int mock_crypto_sha512_call_count(void) {
68 0 : return g_mock.sha512_count;
69 : }
70 :
71 0 : void mock_crypto_set_sha512_output(const unsigned char hash[64]) {
72 0 : memcpy(g_mock.sha512_output, hash, 64);
73 0 : }
74 :
75 1 : int mock_crypto_pbkdf2_call_count(void) {
76 1 : return g_mock.pbkdf2_count;
77 : }
78 :
79 0 : void mock_crypto_set_pbkdf2_output(const unsigned char *buf, size_t len) {
80 0 : if (len > sizeof(g_mock.pbkdf2_output)) len = sizeof(g_mock.pbkdf2_output);
81 0 : memcpy(g_mock.pbkdf2_output, buf, len);
82 0 : g_mock.pbkdf2_output_len = len;
83 0 : }
84 :
85 3 : int mock_crypto_encrypt_block_call_count(void) {
86 3 : return g_mock.encrypt_block_count;
87 : }
88 :
89 2 : int mock_crypto_decrypt_block_call_count(void) {
90 2 : return g_mock.decrypt_block_count;
91 : }
92 :
93 3 : int mock_crypto_rand_bytes_call_count(void) {
94 3 : return g_mock.rand_bytes_count;
95 : }
96 :
97 0 : void mock_crypto_set_rand_bytes(const unsigned char *buf, size_t len) {
98 0 : if (len > sizeof(g_mock.rand_bytes_buf)) len = sizeof(g_mock.rand_bytes_buf);
99 0 : memcpy(g_mock.rand_bytes_buf, buf, len);
100 0 : g_mock.rand_bytes_len = len;
101 0 : }
102 :
103 1 : int mock_crypto_set_encrypt_key_call_count(void) {
104 1 : return g_mock.set_encrypt_key_count;
105 : }
106 :
107 2 : int mock_crypto_rsa_encrypt_call_count(void) {
108 2 : return g_mock.rsa_encrypt_count;
109 : }
110 :
111 0 : void mock_crypto_set_rsa_encrypt_result(const unsigned char *data, size_t len) {
112 0 : if (len > sizeof(g_mock.rsa_encrypt_result)) len = sizeof(g_mock.rsa_encrypt_result);
113 0 : memcpy(g_mock.rsa_encrypt_result, data, len);
114 0 : g_mock.rsa_encrypt_result_len = (int)len;
115 0 : }
116 :
117 3 : int mock_crypto_bn_mod_exp_call_count(void) {
118 3 : return g_mock.bn_mod_exp_count;
119 : }
120 :
121 0 : void mock_crypto_set_bn_mod_exp_result(const unsigned char *data, size_t len) {
122 0 : if (len > sizeof(g_mock.bn_mod_exp_result)) len = sizeof(g_mock.bn_mod_exp_result);
123 0 : memcpy(g_mock.bn_mod_exp_result, data, len);
124 0 : g_mock.bn_mod_exp_result_len = len;
125 0 : }
126 :
127 : /* ---- crypto.h interface implementation ---- */
128 :
129 1070 : void crypto_sha256(const unsigned char *data, size_t len, unsigned char *out) {
130 : (void)data;
131 : (void)len;
132 1070 : g_mock.sha256_count++;
133 1070 : memcpy(out, g_mock.sha256_output, 32);
134 1070 : }
135 :
136 53 : void crypto_sha1(const unsigned char *data, size_t len, unsigned char *out) {
137 : (void)data;
138 : (void)len;
139 53 : g_mock.sha1_count++;
140 53 : memcpy(out, g_mock.sha1_output, 20);
141 53 : }
142 :
143 0 : void crypto_sha512(const unsigned char *data, size_t len, unsigned char *out) {
144 : (void)data; (void)len;
145 0 : g_mock.sha512_count++;
146 0 : memcpy(out, g_mock.sha512_output, 64);
147 0 : }
148 :
149 1 : int crypto_pbkdf2_hmac_sha512(const unsigned char *password, size_t password_len,
150 : const unsigned char *salt, size_t salt_len,
151 : int iters,
152 : unsigned char *out, size_t out_len) {
153 : (void)password; (void)password_len;
154 : (void)salt; (void)salt_len; (void)iters;
155 1 : g_mock.pbkdf2_count++;
156 1 : if (g_mock.pbkdf2_output_len > 0) {
157 0 : size_t copy = g_mock.pbkdf2_output_len < out_len
158 : ? g_mock.pbkdf2_output_len : out_len;
159 0 : memcpy(out, g_mock.pbkdf2_output, copy);
160 0 : if (copy < out_len) memset(out + copy, 0, out_len - copy);
161 : } else {
162 1 : memset(out, 0xDD, out_len);
163 : }
164 1 : return 0;
165 : }
166 :
167 152 : int crypto_aes_set_encrypt_key(const unsigned char *key, int bits,
168 : CryptoAesKey *schedule) {
169 : (void)key;
170 : (void)bits;
171 : (void)schedule;
172 152 : g_mock.set_encrypt_key_count++;
173 152 : return 0;
174 : }
175 :
176 140 : int crypto_aes_set_decrypt_key(const unsigned char *key, int bits,
177 : CryptoAesKey *schedule) {
178 : (void)key;
179 : (void)bits;
180 : (void)schedule;
181 140 : g_mock.set_decrypt_key_count++;
182 140 : return 0;
183 : }
184 :
185 787740 : void crypto_aes_encrypt_block(const unsigned char *in, unsigned char *out,
186 : const CryptoAesKey *schedule) {
187 : (void)schedule;
188 787740 : g_mock.encrypt_block_count++;
189 787740 : memcpy(out, in, 16);
190 787740 : }
191 :
192 789 : void crypto_aes_decrypt_block(const unsigned char *in, unsigned char *out,
193 : const CryptoAesKey *schedule) {
194 : (void)schedule;
195 789 : g_mock.decrypt_block_count++;
196 789 : memcpy(out, in, 16);
197 789 : }
198 :
199 516 : int crypto_rand_bytes(unsigned char *buf, size_t len) {
200 516 : g_mock.rand_bytes_count++;
201 516 : if (g_mock.rand_bytes_len > 0) {
202 0 : size_t copy = g_mock.rand_bytes_len < len ? g_mock.rand_bytes_len : len;
203 0 : memcpy(buf, g_mock.rand_bytes_buf, copy);
204 0 : if (copy < len) memset(buf + copy, 0, len - copy);
205 : } else {
206 516 : memset(buf, 0xAA, len);
207 : }
208 516 : return 0;
209 : }
210 :
211 : /* ---- RSA mock ---- */
212 :
213 : struct CryptoRsaKey { int dummy; };
214 :
215 3 : CryptoRsaKey *crypto_rsa_load_public(const char *pem) {
216 : (void)pem;
217 3 : CryptoRsaKey *key = (CryptoRsaKey *)calloc(1, sizeof(CryptoRsaKey));
218 3 : return key;
219 : }
220 :
221 3 : void crypto_rsa_free(CryptoRsaKey *key) {
222 3 : free(key);
223 3 : }
224 :
225 3 : int crypto_rsa_public_encrypt(CryptoRsaKey *key, const unsigned char *data,
226 : size_t data_len, unsigned char *out, size_t *out_len) {
227 : (void)key;
228 : (void)data;
229 : (void)data_len;
230 3 : g_mock.rsa_encrypt_count++;
231 3 : if (g_mock.rsa_encrypt_result_len > 0) {
232 0 : memcpy(out, g_mock.rsa_encrypt_result, (size_t)g_mock.rsa_encrypt_result_len);
233 0 : *out_len = (size_t)g_mock.rsa_encrypt_result_len;
234 : } else {
235 3 : memset(out, 0xBB, 256);
236 3 : *out_len = 256;
237 : }
238 3 : return 0;
239 : }
240 :
241 : /* ---- BN mock ---- */
242 :
243 : struct CryptoBnCtx { int dummy; };
244 :
245 8 : CryptoBnCtx *crypto_bn_ctx_new(void) {
246 8 : return (CryptoBnCtx *)calloc(1, sizeof(CryptoBnCtx));
247 : }
248 :
249 8 : void crypto_bn_ctx_free(CryptoBnCtx *ctx) {
250 8 : free(ctx);
251 8 : }
252 :
253 17 : int crypto_bn_mod_exp(unsigned char *result, size_t *res_len,
254 : const unsigned char *base, size_t base_len,
255 : const unsigned char *exp, size_t exp_len,
256 : const unsigned char *mod, size_t mod_len,
257 : CryptoBnCtx *ctx) {
258 : (void)base;
259 : (void)exp;
260 : (void)mod;
261 : (void)ctx;
262 17 : g_mock.bn_mod_exp_count++;
263 :
264 : /* Mock: use configured result or fill with 0xCC */
265 17 : size_t out_len = mod_len;
266 17 : if (out_len > *res_len) return -1;
267 17 : if (g_mock.bn_mod_exp_result_len > 0) {
268 0 : size_t copy = g_mock.bn_mod_exp_result_len < out_len
269 : ? g_mock.bn_mod_exp_result_len : out_len;
270 0 : memset(result, 0, out_len);
271 0 : memcpy(result + out_len - copy, g_mock.bn_mod_exp_result, copy);
272 : } else {
273 17 : memset(result, 0xCC, out_len);
274 : }
275 17 : *res_len = out_len;
276 :
277 : (void)base_len;
278 : (void)exp_len;
279 17 : return 0;
280 : }
281 :
282 3 : static int mock_bn_op(unsigned char *result, size_t *res_len,
283 : const unsigned char *a, size_t a_len,
284 : const unsigned char *b, size_t b_len,
285 : const unsigned char *m, size_t m_len,
286 : unsigned char fill) {
287 : (void)a; (void)a_len; (void)b; (void)b_len; (void)m;
288 3 : if (m_len > *res_len) return -1;
289 3 : memset(result, fill, m_len);
290 3 : *res_len = m_len;
291 3 : return 0;
292 : }
293 :
294 2 : int crypto_bn_mod_mul(unsigned char *result, size_t *res_len,
295 : const unsigned char *a, size_t a_len,
296 : const unsigned char *b, size_t b_len,
297 : const unsigned char *m, size_t m_len,
298 : CryptoBnCtx *ctx) {
299 : (void)ctx;
300 2 : return mock_bn_op(result, res_len, a, a_len, b, b_len, m, m_len, 0xC1);
301 : }
302 :
303 0 : int crypto_bn_mod_add(unsigned char *result, size_t *res_len,
304 : const unsigned char *a, size_t a_len,
305 : const unsigned char *b, size_t b_len,
306 : const unsigned char *m, size_t m_len,
307 : CryptoBnCtx *ctx) {
308 : (void)ctx;
309 0 : return mock_bn_op(result, res_len, a, a_len, b, b_len, m, m_len, 0xC2);
310 : }
311 :
312 1 : int crypto_bn_mod_sub(unsigned char *result, size_t *res_len,
313 : const unsigned char *a, size_t a_len,
314 : const unsigned char *b, size_t b_len,
315 : const unsigned char *m, size_t m_len,
316 : CryptoBnCtx *ctx) {
317 : (void)ctx;
318 1 : return mock_bn_op(result, res_len, a, a_len, b, b_len, m, m_len, 0xC3);
319 : }
320 :
321 0 : int crypto_bn_ucmp(const unsigned char *a, size_t a_len,
322 : const unsigned char *b, size_t b_len) {
323 : /* Mock: lexicographic comparison of the provided bytes — not a real
324 : * big-number comparison but deterministic enough for the few test
325 : * callers that care about "same input → same result". */
326 0 : size_t n = a_len < b_len ? a_len : b_len;
327 0 : int r = memcmp(a, b, n);
328 0 : if (r == 0 && a_len != b_len) r = a_len < b_len ? -1 : 1;
329 0 : return r < 0 ? -1 : (r > 0 ? 1 : 0);
330 : }
|