Coverage Report

Created: 2025-11-02 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/fuzz/fuzz_gcrypt_cipher.cpp
Line
Count
Source
1
#include <stdlib.h>
2
#include <stdint.h>
3
#include <assert.h>
4
#include "fuzzer/FuzzedDataProvider.h"
5
6
#define MBEDTLS_CHECK_RETURN_TYPICAL
7
1.12k
#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret )  do { } while( 0 )
8
#include "gcrypt/cipher.h"
9
#include "gcrypt/error.h"
10
#include "gcrypt/aes.h"
11
12
extern int force_no_aesni;
13
14
203
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
15
203
  FuzzedDataProvider fuzzed_data(data, size);
16
203
  int key_lens[] = { 128, 192, 256 };
17
203
  int key_len, iv_len, rc_e, rc_d, input_length;
18
203
  unsigned char *output, *decrypted;
19
203
  size_t output_size, output_size2, decrypted_size;
20
203
  mbedtls_cipher_type_t cipher_type;
21
  /* TODO: GCM. This code/fuzzer doesn't work with GCM ciphers. Not sure why.. :( */
22
203
  const char *cipher_names[] = { NULL, "", "AES-128-ECB", "AES-192-ECB", "AES-256-ECB",
23
203
                                 /* "AES-128-GCM", "AES-192-GCM", "AES-256-GCM" */ };
24
203
  const char *cipher_name;
25
203
  mbedtls_cipher_context_t *ctx_e, *ctx_d;
26
27
  /* No real memory allocations involved */
28
29
203
  if(fuzzed_data.remaining_bytes() < 512) /* Some data */
30
16
    return -1;
31
32
187
  posix_memalign((void **)&ctx_e, 8, sizeof(mbedtls_cipher_context_t));
33
187
  posix_memalign((void **)&ctx_d, 8, sizeof(mbedtls_cipher_context_t));
34
35
187
  key_len = fuzzed_data.PickValueInArray(key_lens);
36
187
  std::vector<unsigned char>key = fuzzed_data.ConsumeBytes<u_int8_t>(key_len / 8);
37
187
  iv_len = fuzzed_data.ConsumeIntegralInRange(0, MBEDTLS_MAX_IV_LENGTH + 1);
38
187
  std::vector<u_int8_t>iv = fuzzed_data.ConsumeBytes<uint8_t>(iv_len);
39
187
  input_length = fuzzed_data.ConsumeIntegralInRange(16, 17);
40
187
  std::vector<unsigned char>input = fuzzed_data.ConsumeBytes<u_int8_t>(input_length);
41
187
  output = (unsigned char *)malloc(input_length);
42
187
  decrypted = (unsigned char *)malloc(input_length);
43
44
187
  mbedtls_cipher_list();
45
  /* Random iteration */
46
187
  cipher_type = static_cast<mbedtls_cipher_type_t>(fuzzed_data.ConsumeIntegralInRange(0, (int)MBEDTLS_CIPHER_AES_256_KWP) + 1);
47
187
  mbedtls_cipher_info_from_type(cipher_type);
48
49
  /* Real cipher used */
50
187
  cipher_name = cipher_names[fuzzed_data.ConsumeIntegralInRange(0, (int)(sizeof(cipher_names) / sizeof(char *) - 1))];
51
187
  mbedtls_cipher_init(ctx_e);
52
187
  mbedtls_cipher_init(ctx_d);
53
187
  ctx_e->cipher_info = mbedtls_cipher_info_from_string(cipher_name);
54
187
  ctx_d->cipher_info = ctx_e->cipher_info;
55
56
187
  mbedtls_cipher_info_get_mode(ctx_e->cipher_info);
57
187
  mbedtls_cipher_info_get_type(ctx_e->cipher_info);
58
187
  mbedtls_cipher_info_get_name(ctx_e->cipher_info);
59
187
  mbedtls_cipher_info_has_variable_key_bitlen(ctx_e->cipher_info);
60
187
  mbedtls_cipher_info_has_variable_iv_size(ctx_e->cipher_info);
61
187
  mbedtls_cipher_info_get_iv_size(ctx_e->cipher_info);
62
187
  mbedtls_cipher_info_get_block_size(ctx_e->cipher_info);
63
187
  mbedtls_cipher_get_cipher_mode(ctx_e);
64
187
  mbedtls_cipher_get_iv_size(ctx_e);
65
187
  mbedtls_cipher_get_type(ctx_e);
66
187
  mbedtls_cipher_get_name(ctx_e);
67
187
  mbedtls_cipher_get_key_bitlen(ctx_e);
68
187
  mbedtls_cipher_get_operation(ctx_e);
69
187
  mbedtls_cipher_info_get_key_bitlen(ctx_e->cipher_info);
70
187
  mbedtls_error_add(0, 0, NULL, 0);
71
72
187
  posix_memalign((void **)&ctx_e->cipher_ctx, 8, sizeof(mbedtls_aes_context));
73
187
  posix_memalign((void **)&ctx_d->cipher_ctx, 8, sizeof(mbedtls_aes_context));
74
75
187
  rc_e = mbedtls_cipher_setkey(ctx_e, key.data(), key.size() * 8, MBEDTLS_ENCRYPT);
76
187
  rc_d = mbedtls_cipher_setkey(ctx_d, key.data(), key.size() * 8, MBEDTLS_DECRYPT);
77
187
  if(rc_e == 0 && rc_d == 0) {
78
79
96
    if(fuzzed_data.ConsumeBool()) {
80
50
      rc_e = mbedtls_cipher_crypt(ctx_e, iv.data(), iv.size(),
81
50
                                  input.data(), input.size(), output, &output_size);
82
50
    } else {
83
46
      rc_e = mbedtls_cipher_set_iv(ctx_e, iv.data(), iv.size());
84
46
      rc_d = mbedtls_cipher_set_iv(ctx_d, iv.data(), iv.size());
85
46
      if(rc_e == 0 && rc_d == 0) {
86
42
        mbedtls_cipher_reset(ctx_e);
87
42
        mbedtls_cipher_reset(ctx_d);
88
89
42
        rc_e = mbedtls_cipher_update(ctx_e, input.data(), input.size(), output, &output_size);
90
42
        if(rc_e == 0) {
91
36
    rc_e = mbedtls_cipher_finish(ctx_e, NULL, &output_size2);
92
36
          if(rc_e == 0) {
93
94
36
            rc_d = mbedtls_cipher_update(ctx_d, output, output_size, decrypted, &decrypted_size);
95
36
            if(rc_d == 0) {
96
36
              rc_d = mbedtls_cipher_finish(ctx_d, NULL, &output_size2);
97
              /* TODO: decryption doesn't work with no-aesni data path!
98
           Note that with MASAN, aesni is always disabled */
99
#if 0
100
        if(rc_d == 0) {
101
                assert(input.size() == decrypted_size);
102
                assert(memcmp(input.data(), decrypted, decrypted_size) == 0);
103
              }
104
#endif
105
36
      }
106
36
          }
107
36
        }
108
42
      }
109
46
    }
110
96
  }
111
112
187
  free(output);
113
187
  free(decrypted);
114
187
  free(ctx_e->cipher_ctx);
115
187
  free(ctx_e);
116
187
  free(ctx_d->cipher_ctx);
117
187
  free(ctx_d);
118
187
  return 0;
119
203
}