Coverage Report

Created: 2025-07-11 07:03

/src/curl/lib/vtls/keylog.c
Line
Count
Source (jump to first uncovered line)
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
26
#if defined(USE_OPENSSL) || \
27
  defined(USE_GNUTLS) || \
28
  defined(USE_WOLFSSL) || \
29
  (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
30
  defined(USE_QUICHE) || \
31
  defined(USE_RUSTLS)
32
33
#include "keylog.h"
34
#include <curl/curl.h>
35
#include "../escape.h"
36
37
/* The last #include files should be: */
38
#include "../curl_memory.h"
39
#include "../memdebug.h"
40
41
/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
42
static FILE *keylog_file_fp;
43
44
void
45
Curl_tls_keylog_open(void)
46
15
{
47
15
  char *keylog_file_name;
48
49
15
  if(!keylog_file_fp) {
50
15
    keylog_file_name = curl_getenv("SSLKEYLOGFILE");
51
15
    if(keylog_file_name) {
52
0
      keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
53
0
      if(keylog_file_fp) {
54
#ifdef _WIN32
55
        if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
56
#else
57
0
        if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
58
0
#endif
59
0
        {
60
0
          fclose(keylog_file_fp);
61
0
          keylog_file_fp = NULL;
62
0
        }
63
0
      }
64
0
      Curl_safefree(keylog_file_name);
65
0
    }
66
15
  }
67
15
}
68
69
void
70
Curl_tls_keylog_close(void)
71
0
{
72
0
  if(keylog_file_fp) {
73
0
    fclose(keylog_file_fp);
74
0
    keylog_file_fp = NULL;
75
0
  }
76
0
}
77
78
bool
79
Curl_tls_keylog_enabled(void)
80
18.0k
{
81
18.0k
  return keylog_file_fp != NULL;
82
18.0k
}
83
84
bool
85
Curl_tls_keylog_write_line(const char *line)
86
0
{
87
  /* The current maximum valid keylog line length LF and NUL is 195. */
88
0
  size_t linelen;
89
0
  char buf[256];
90
91
0
  if(!keylog_file_fp || !line) {
92
0
    return FALSE;
93
0
  }
94
95
0
  linelen = strlen(line);
96
0
  if(linelen == 0 || linelen > sizeof(buf) - 2) {
97
    /* Empty line or too big to fit in an LF and NUL. */
98
0
    return FALSE;
99
0
  }
100
101
0
  memcpy(buf, line, linelen);
102
0
  if(line[linelen - 1] != '\n') {
103
0
    buf[linelen++] = '\n';
104
0
  }
105
0
  buf[linelen] = '\0';
106
107
  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
108
     may not be thread-safe. */
109
0
  fputs(buf, keylog_file_fp);
110
0
  return TRUE;
111
0
}
112
113
bool
114
Curl_tls_keylog_write(const char *label,
115
                      const unsigned char client_random[CLIENT_RANDOM_SIZE],
116
                      const unsigned char *secret, size_t secretlen)
117
0
{
118
0
  size_t pos, i;
119
0
  unsigned char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
120
0
                     2 * SECRET_MAXLEN + 1 + 1];
121
122
0
  if(!keylog_file_fp) {
123
0
    return FALSE;
124
0
  }
125
126
0
  pos = strlen(label);
127
0
  if(pos > KEYLOG_LABEL_MAXLEN || !secretlen || secretlen > SECRET_MAXLEN) {
128
    /* Should never happen - sanity check anyway. */
129
0
    return FALSE;
130
0
  }
131
132
0
  memcpy(line, label, pos);
133
0
  line[pos++] = ' ';
134
135
  /* Client Random */
136
0
  for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
137
0
    Curl_hexbyte(&line[pos], client_random[i]);
138
0
    pos += 2;
139
0
  }
140
0
  line[pos++] = ' ';
141
142
  /* Secret */
143
0
  for(i = 0; i < secretlen; i++) {
144
0
    Curl_hexbyte(&line[pos], secret[i]);
145
0
    pos += 2;
146
0
  }
147
0
  line[pos++] = '\n';
148
0
  line[pos] = '\0';
149
150
  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
151
     may not be thread-safe. */
152
0
  fputs((char *)line, keylog_file_fp);
153
0
  return TRUE;
154
0
}
155
156
#endif  /* TLS or QUIC backend */