Coverage Report

Created: 2026-07-30 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/vtls/keylog.c
Line
Count
Source
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
#include "curl_setup.h"
25
#include "vtls/keylog.h"
26
27
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
28
  defined(USE_RUSTLS)
29
30
#include "escape.h"
31
#include "curlx/fopen.h"
32
33
/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
34
static FILE *keylog_file_fp;
35
/* Used for verbose logging */
36
static char *keylog_file_name;
37
38
void Curl_tls_keylog_open(void)
39
18
{
40
18
  if(!keylog_file_fp) {
41
18
    keylog_file_name = getenv("SSLKEYLOGFILE");
42
18
    if(keylog_file_name) {
43
0
      keylog_file_fp = curlx_fopen(keylog_file_name, FOPEN_APPENDTEXT);
44
0
      if(keylog_file_fp) {
45
#ifdef _WIN32
46
        if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
47
#else
48
0
        if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
49
0
#endif
50
0
        {
51
0
          curlx_fclose(keylog_file_fp);
52
0
          keylog_file_fp = NULL;
53
0
        }
54
0
      }
55
0
    }
56
18
  }
57
18
}
58
59
void Curl_tls_keylog_close(void)
60
0
{
61
0
  if(keylog_file_fp) {
62
0
    curlx_fclose(keylog_file_fp);
63
0
    keylog_file_fp = NULL;
64
0
  }
65
0
}
66
67
bool Curl_tls_keylog_enabled(void)
68
24.6k
{
69
24.6k
  return !!keylog_file_fp;
70
24.6k
}
71
72
const char *Curl_tls_keylog_file_name(void)
73
0
{
74
0
  return keylog_file_name;
75
0
}
76
77
bool Curl_tls_keylog_write_line(const char *line)
78
0
{
79
  /* The current maximum valid keylog line length LF and NUL is 195. */
80
0
  size_t linelen;
81
0
  char buf[256];
82
83
0
  if(!keylog_file_fp || !line) {
84
0
    return FALSE;
85
0
  }
86
87
0
  linelen = strlen(line);
88
0
  if(linelen == 0 || linelen > sizeof(buf) - 2) {
89
    /* Empty line or too big to fit in an LF and NUL. */
90
0
    return FALSE;
91
0
  }
92
93
0
  memcpy(buf, line, linelen);
94
0
  if(line[linelen - 1] != '\n') {
95
0
    buf[linelen++] = '\n';
96
0
  }
97
0
  buf[linelen] = '\0';
98
99
  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
100
     may not be thread-safe. */
101
0
  fputs(buf, keylog_file_fp);
102
0
  return TRUE;
103
0
}
104
105
bool Curl_tls_keylog_write(
106
  const char *label,
107
  const unsigned char client_random[CLIENT_RANDOM_SIZE],
108
  const unsigned char *secret, size_t secretlen)
109
0
{
110
0
  size_t pos, i;
111
0
  unsigned char line[KEYLOG_LABEL_MAXLEN + 1 +
112
0
                     (2 * CLIENT_RANDOM_SIZE) + 1 +
113
0
                     (2 * SECRET_MAXLEN) + 1 + 1];
114
115
0
  if(!keylog_file_fp) {
116
0
    return FALSE;
117
0
  }
118
119
0
  pos = strlen(label);
120
0
  if(pos > KEYLOG_LABEL_MAXLEN || !secretlen || secretlen > SECRET_MAXLEN) {
121
    /* Should never happen - sanity check anyway. */
122
0
    return FALSE;
123
0
  }
124
125
0
  memcpy(line, label, pos);
126
0
  line[pos++] = ' ';
127
128
  /* Client Random */
129
0
  for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
130
0
    Curl_hexbyte(&line[pos], client_random[i]);
131
0
    pos += 2;
132
0
  }
133
0
  line[pos++] = ' ';
134
135
  /* Secret */
136
0
  for(i = 0; i < secretlen; i++) {
137
0
    Curl_hexbyte(&line[pos], secret[i]);
138
0
    pos += 2;
139
0
  }
140
0
  line[pos++] = '\n';
141
0
  line[pos] = '\0';
142
143
  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
144
     may not be thread-safe. */
145
0
  fputs((char *)line, keylog_file_fp);
146
  return TRUE;
147
0
}
148
149
#else /* TLS backend */
150
151
bool Curl_tls_keylog_enabled(void)
152
{
153
  return FALSE;
154
}
155
156
const char *Curl_tls_keylog_file_name(void)
157
{
158
  return NULL;
159
}
160
161
#endif  /* TLS backend */