Coverage Report

Created: 2026-04-28 07:09

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
22.7k
{
69
22.7k
  return keylog_file_fp != NULL;
70
22.7k
}
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(const char *label,
106
                         const unsigned char client_random[CLIENT_RANDOM_SIZE],
107
                         const unsigned char *secret, size_t secretlen)
108
0
{
109
0
  size_t pos, i;
110
0
  unsigned char line[KEYLOG_LABEL_MAXLEN + 1 +
111
0
                     (2 * CLIENT_RANDOM_SIZE) + 1 +
112
0
                     (2 * SECRET_MAXLEN) + 1 + 1];
113
114
0
  if(!keylog_file_fp) {
115
0
    return FALSE;
116
0
  }
117
118
0
  pos = strlen(label);
119
0
  if(pos > KEYLOG_LABEL_MAXLEN || !secretlen || secretlen > SECRET_MAXLEN) {
120
    /* Should never happen - sanity check anyway. */
121
0
    return FALSE;
122
0
  }
123
124
0
  memcpy(line, label, pos);
125
0
  line[pos++] = ' ';
126
127
  /* Client Random */
128
0
  for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
129
0
    Curl_hexbyte(&line[pos], client_random[i]);
130
0
    pos += 2;
131
0
  }
132
0
  line[pos++] = ' ';
133
134
  /* Secret */
135
0
  for(i = 0; i < secretlen; i++) {
136
0
    Curl_hexbyte(&line[pos], secret[i]);
137
0
    pos += 2;
138
0
  }
139
0
  line[pos++] = '\n';
140
0
  line[pos] = '\0';
141
142
  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
143
     may not be thread-safe. */
144
0
  fputs((char *)line, keylog_file_fp);
145
  return TRUE;
146
0
}
147
148
#else /* TLS backend */
149
150
bool Curl_tls_keylog_enabled(void)
151
{
152
  return FALSE;
153
}
154
155
const char *Curl_tls_keylog_file_name(void)
156
{
157
  return NULL;
158
}
159
160
#endif  /* TLS backend */