Coverage Report

Created: 2026-01-25 06:18

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 "../escape.h"
35
#include "../curlx/fopen.h"
36
37
/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
38
static FILE *keylog_file_fp;
39
40
void Curl_tls_keylog_open(void)
41
16
{
42
16
  char *keylog_file_name;
43
44
16
  if(!keylog_file_fp) {
45
16
    keylog_file_name = curl_getenv("SSLKEYLOGFILE");
46
16
    if(keylog_file_name) {
47
0
      keylog_file_fp = curlx_fopen(keylog_file_name, FOPEN_APPENDTEXT);
48
0
      if(keylog_file_fp) {
49
#ifdef _WIN32
50
        if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
51
#else
52
0
        if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
53
0
#endif
54
0
        {
55
0
          curlx_fclose(keylog_file_fp);
56
0
          keylog_file_fp = NULL;
57
0
        }
58
0
      }
59
0
      Curl_safefree(keylog_file_name);
60
0
    }
61
16
  }
62
16
}
63
64
void Curl_tls_keylog_close(void)
65
0
{
66
0
  if(keylog_file_fp) {
67
0
    curlx_fclose(keylog_file_fp);
68
0
    keylog_file_fp = NULL;
69
0
  }
70
0
}
71
72
bool Curl_tls_keylog_enabled(void)
73
23.7k
{
74
23.7k
  return keylog_file_fp != NULL;
75
23.7k
}
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 + 2 * CLIENT_RANDOM_SIZE + 1 +
111
0
                     2 * SECRET_MAXLEN + 1 + 1];
112
113
0
  if(!keylog_file_fp) {
114
0
    return FALSE;
115
0
  }
116
117
0
  pos = strlen(label);
118
0
  if(pos > KEYLOG_LABEL_MAXLEN || !secretlen || secretlen > SECRET_MAXLEN) {
119
    /* Should never happen - sanity check anyway. */
120
0
    return FALSE;
121
0
  }
122
123
0
  memcpy(line, label, pos);
124
0
  line[pos++] = ' ';
125
126
  /* Client Random */
127
0
  for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
128
0
    Curl_hexbyte(&line[pos], client_random[i]);
129
0
    pos += 2;
130
0
  }
131
0
  line[pos++] = ' ';
132
133
  /* Secret */
134
0
  for(i = 0; i < secretlen; i++) {
135
0
    Curl_hexbyte(&line[pos], secret[i]);
136
0
    pos += 2;
137
0
  }
138
0
  line[pos++] = '\n';
139
0
  line[pos] = '\0';
140
141
  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
142
     may not be thread-safe. */
143
0
  fputs((char *)line, keylog_file_fp);
144
  return TRUE;
145
0
}
146
147
#endif /* TLS or QUIC backend */