Coverage Report

Created: 2024-02-25 06:14

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