Coverage Report

Created: 2025-12-03 07:13

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 fp for the open SSLKEYLOGFILE, or NULL if not open */
39
static FILE *keylog_file_fp;
40
41
void Curl_tls_keylog_open(void)
42
16
{
43
16
  char *keylog_file_name;
44
45
16
  if(!keylog_file_fp) {
46
16
    keylog_file_name = curl_getenv("SSLKEYLOGFILE");
47
16
    if(keylog_file_name) {
48
0
      keylog_file_fp = curlx_fopen(keylog_file_name, FOPEN_APPENDTEXT);
49
0
      if(keylog_file_fp) {
50
#ifdef _WIN32
51
        if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
52
#else
53
0
        if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
54
0
#endif
55
0
        {
56
0
          curlx_fclose(keylog_file_fp);
57
0
          keylog_file_fp = NULL;
58
0
        }
59
0
      }
60
0
      Curl_safefree(keylog_file_name);
61
0
    }
62
16
  }
63
16
}
64
65
void Curl_tls_keylog_close(void)
66
0
{
67
0
  if(keylog_file_fp) {
68
0
    curlx_fclose(keylog_file_fp);
69
0
    keylog_file_fp = NULL;
70
0
  }
71
0
}
72
73
bool Curl_tls_keylog_enabled(void)
74
20.4k
{
75
20.4k
  return keylog_file_fp != NULL;
76
20.4k
}
77
78
bool Curl_tls_keylog_write_line(const char *line)
79
0
{
80
  /* The current maximum valid keylog line length LF and NUL is 195. */
81
0
  size_t linelen;
82
0
  char buf[256];
83
84
0
  if(!keylog_file_fp || !line) {
85
0
    return FALSE;
86
0
  }
87
88
0
  linelen = strlen(line);
89
0
  if(linelen == 0 || linelen > sizeof(buf) - 2) {
90
    /* Empty line or too big to fit in an LF and NUL. */
91
0
    return FALSE;
92
0
  }
93
94
0
  memcpy(buf, line, linelen);
95
0
  if(line[linelen - 1] != '\n') {
96
0
    buf[linelen++] = '\n';
97
0
  }
98
0
  buf[linelen] = '\0';
99
100
  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
101
     may not be thread-safe. */
102
0
  fputs(buf, keylog_file_fp);
103
0
  return TRUE;
104
0
}
105
106
bool Curl_tls_keylog_write(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 + 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
#endif  /* TLS or QUIC backend */