Coverage Report

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