Coverage Report

Created: 2026-09-14 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/vtls/vtls_spack.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_SSL) && defined(USE_SSLS_EXPORT)
27
28
#include "urldata.h"
29
#include "curl_trc.h"
30
#include "vtls/vtls_scache.h"
31
#include "vtls/vtls_spack.h"
32
#include "curlx/strdup.h"
33
34
0
#define CURL_SPACK_VERSION       0x01
35
0
#define CURL_SPACK_IETF_ID       0x02
36
0
#define CURL_SPACK_VALID_UNTIL   0x03
37
0
#define CURL_SPACK_TICKET        0x04
38
0
#define CURL_SPACK_ALPN          0x05
39
0
#define CURL_SPACK_EARLYDATA     0x06
40
0
#define CURL_SPACK_QUICTP        0x07
41
0
#define CURL_SPACK_SECTRUST      0x08
42
43
static CURLcode spack_enc8(struct dynbuf *buf, uint8_t b)
44
0
{
45
0
  return curlx_dyn_addn(buf, &b, 1);
46
0
}
47
48
static CURLcode spack_dec8(uint8_t *val, const uint8_t **src,
49
                           const uint8_t *end)
50
0
{
51
0
  if(end - *src < 1)
52
0
    return CURLE_READ_ERROR;
53
0
  *val = **src;
54
0
  *src += 1;
55
0
  return CURLE_OK;
56
0
}
57
58
static CURLcode spack_enc16(struct dynbuf *buf, uint16_t val)
59
0
{
60
0
  uint8_t nval[2];
61
0
  nval[0] = (uint8_t)(val >> 8);
62
0
  nval[1] = (uint8_t)val;
63
0
  return curlx_dyn_addn(buf, nval, sizeof(nval));
64
0
}
65
66
static CURLcode spack_dec16(uint16_t *val, const uint8_t **src,
67
                            const uint8_t *end)
68
0
{
69
0
  if(end - *src < 2)
70
0
    return CURLE_READ_ERROR;
71
0
  *val = (uint16_t)((*src)[0] << 8 | (*src)[1]);
72
0
  *src += 2;
73
0
  return CURLE_OK;
74
0
}
75
76
static CURLcode spack_enc32(struct dynbuf *buf, uint32_t val)
77
0
{
78
0
  uint8_t nval[4];
79
0
  nval[0] = (uint8_t)(val >> 24);
80
0
  nval[1] = (uint8_t)(val >> 16);
81
0
  nval[2] = (uint8_t)(val >> 8);
82
0
  nval[3] = (uint8_t)val;
83
0
  return curlx_dyn_addn(buf, nval, sizeof(nval));
84
0
}
85
86
static CURLcode spack_dec32(uint32_t *val, const uint8_t **src,
87
                            const uint8_t *end)
88
0
{
89
0
  if(end - *src < 4)
90
0
    return CURLE_READ_ERROR;
91
0
  *val = (uint32_t)(*src)[0] << 24 | (uint32_t)(*src)[1] << 16 |
92
0
         (uint32_t)(*src)[2] << 8 | (*src)[3];
93
0
  *src += 4;
94
0
  return CURLE_OK;
95
0
}
96
97
static CURLcode spack_enc64(struct dynbuf *buf, uint64_t val)
98
0
{
99
0
  uint8_t nval[8];
100
0
  nval[0] = (uint8_t)(val >> 56);
101
0
  nval[1] = (uint8_t)(val >> 48);
102
0
  nval[2] = (uint8_t)(val >> 40);
103
0
  nval[3] = (uint8_t)(val >> 32);
104
0
  nval[4] = (uint8_t)(val >> 24);
105
0
  nval[5] = (uint8_t)(val >> 16);
106
0
  nval[6] = (uint8_t)(val >> 8);
107
0
  nval[7] = (uint8_t)val;
108
0
  return curlx_dyn_addn(buf, nval, sizeof(nval));
109
0
}
110
111
static CURLcode spack_dec64(uint64_t *val, const uint8_t **src,
112
                            const uint8_t *end)
113
0
{
114
0
  if(end - *src < 8)
115
0
    return CURLE_READ_ERROR;
116
0
  *val = (uint64_t)(*src)[0] << 56 | (uint64_t)(*src)[1] << 48 |
117
0
         (uint64_t)(*src)[2] << 40 | (uint64_t)(*src)[3] << 32 |
118
0
         (uint64_t)(*src)[4] << 24 | (uint64_t)(*src)[5] << 16 |
119
0
         (uint64_t)(*src)[6] << 8 | (*src)[7];
120
0
  *src += 8;
121
0
  return CURLE_OK;
122
0
}
123
124
static CURLcode spack_encstr16(struct dynbuf *buf, const char *s)
125
0
{
126
0
  size_t slen = strlen(s);
127
0
  CURLcode result;
128
0
  if(slen > UINT16_MAX)
129
0
    return CURLE_BAD_FUNCTION_ARGUMENT;
130
0
  result = spack_enc16(buf, (uint16_t)slen);
131
0
  if(!result) {
132
0
    result = curlx_dyn_addn(buf, s, slen);
133
0
  }
134
0
  return result;
135
0
}
136
137
static CURLcode spack_decstr16(char **val, const uint8_t **src,
138
                               const uint8_t *end)
139
0
{
140
0
  uint16_t slen;
141
0
  CURLcode result;
142
143
0
  *val = NULL;
144
0
  result = spack_dec16(&slen, src, end);
145
0
  if(result)
146
0
    return result;
147
0
  if(end - *src < slen)
148
0
    return CURLE_READ_ERROR;
149
0
  *val = curlx_memdup0((const char *)(*src), slen);
150
0
  *src += slen;
151
0
  return *val ? CURLE_OK : CURLE_OUT_OF_MEMORY;
152
0
}
153
154
static CURLcode spack_encdata16(struct dynbuf *buf, const uint8_t *data,
155
                                size_t data_len)
156
0
{
157
0
  CURLcode result;
158
0
  if(data_len > UINT16_MAX)
159
0
    return CURLE_BAD_FUNCTION_ARGUMENT;
160
0
  result = spack_enc16(buf, (uint16_t)data_len);
161
0
  if(!result) {
162
0
    result = curlx_dyn_addn(buf, data, data_len);
163
0
  }
164
0
  return result;
165
0
}
166
167
static CURLcode spack_decdata16(uint8_t **val, size_t *val_len,
168
                                const uint8_t **src, const uint8_t *end)
169
0
{
170
0
  uint16_t data_len;
171
0
  CURLcode result;
172
173
0
  *val = NULL;
174
0
  result = spack_dec16(&data_len, src, end);
175
0
  if(result)
176
0
    return result;
177
0
  if(end - *src < data_len)
178
0
    return CURLE_READ_ERROR;
179
0
  *val = curlx_memdup0((const char *)(*src), data_len);
180
0
  *val_len = data_len;
181
0
  *src += data_len;
182
0
  return *val ? CURLE_OK : CURLE_OUT_OF_MEMORY;
183
0
}
184
185
CURLcode Curl_ssl_session_pack(struct Curl_easy *data,
186
                               struct Curl_ssl_session *s,
187
                               struct dynbuf *buf)
188
0
{
189
0
  CURLcode result;
190
0
  DEBUGASSERT(s->sdata);
191
0
  DEBUGASSERT(s->sdata_len);
192
193
0
  if(s->valid_until < 0)
194
0
    return CURLE_BAD_FUNCTION_ARGUMENT;
195
196
0
  result = spack_enc8(buf, CURL_SPACK_VERSION);
197
0
  if(!result)
198
0
    result = spack_enc8(buf, CURL_SPACK_TICKET);
199
0
  if(!result)
200
0
    result = spack_encdata16(buf, s->sdata, s->sdata_len);
201
0
  if(!result)
202
0
    result = spack_enc8(buf, CURL_SPACK_IETF_ID);
203
0
  if(!result)
204
0
    result = spack_enc16(buf, (uint16_t)s->ietf_tls_id);
205
0
  if(!result)
206
0
    result = spack_enc8(buf, CURL_SPACK_VALID_UNTIL);
207
0
  if(!result)
208
0
    result = spack_enc64(buf, (uint64_t)s->valid_until);
209
0
  if(!result && s->alpn) {
210
0
    result = spack_enc8(buf, CURL_SPACK_ALPN);
211
0
    if(!result)
212
0
      result = spack_encstr16(buf, s->alpn);
213
0
  }
214
0
  if(!result && s->earlydata_max) {
215
0
    if(s->earlydata_max > UINT32_MAX)
216
0
      result = CURLE_BAD_FUNCTION_ARGUMENT;
217
0
    if(!result)
218
0
      result = spack_enc8(buf, CURL_SPACK_EARLYDATA);
219
0
    if(!result)
220
0
      result = spack_enc32(buf, (uint32_t)s->earlydata_max);
221
0
  }
222
0
  if(!result && s->sectrust_verified) {
223
0
    result = spack_enc8(buf, CURL_SPACK_SECTRUST);
224
0
  }
225
0
  if(!result && s->quic_tp && s->quic_tp_len) {
226
0
    result = spack_enc8(buf, CURL_SPACK_QUICTP);
227
0
    if(!result)
228
0
      result = spack_encdata16(buf, s->quic_tp, s->quic_tp_len);
229
0
  }
230
231
0
  if(result)
232
0
    CURL_TRC_SSLS(data, "error packing data: %d", (int)result);
233
0
  return result;
234
0
}
235
236
CURLcode Curl_ssl_session_unpack(struct Curl_easy *data,
237
                                 const void *bufv, size_t buflen,
238
                                 struct Curl_ssl_session **ps)
239
0
{
240
0
  struct Curl_ssl_session *s = NULL;
241
0
  const unsigned char *buf = (const unsigned char *)bufv;
242
0
  const unsigned char *end = buf + buflen;
243
0
  uint8_t val8, *pval8;
244
0
  uint16_t val16;
245
0
  uint32_t val32;
246
0
  uint64_t val64;
247
0
  size_t dlen;
248
0
  CURLcode result;
249
250
0
  DEBUGASSERT(buf);
251
0
  DEBUGASSERT(buflen);
252
0
  *ps = NULL;
253
254
0
  result = spack_dec8(&val8, &buf, end);
255
0
  if(result)
256
0
    goto out;
257
0
  if(val8 != CURL_SPACK_VERSION) {
258
0
    result = CURLE_READ_ERROR;
259
0
    goto out;
260
0
  }
261
262
0
  s = curlx_calloc(1, sizeof(*s));
263
0
  if(!s) {
264
0
    result = CURLE_OUT_OF_MEMORY;
265
0
    goto out;
266
0
  }
267
268
0
  while(buf < end) {
269
0
    result = spack_dec8(&val8, &buf, end);
270
0
    if(result)
271
0
      goto out;
272
273
0
    switch(val8) {
274
0
    case CURL_SPACK_ALPN:
275
0
      curlx_free(s->alpn);
276
0
      result = spack_decstr16(&s->alpn, &buf, end);
277
0
      if(result)
278
0
        goto out;
279
0
      break;
280
0
    case CURL_SPACK_EARLYDATA:
281
0
      result = spack_dec32(&val32, &buf, end);
282
0
      if(result)
283
0
        goto out;
284
0
      s->earlydata_max = val32;
285
0
      break;
286
0
    case CURL_SPACK_IETF_ID:
287
0
      result = spack_dec16(&val16, &buf, end);
288
0
      if(result)
289
0
        goto out;
290
0
      s->ietf_tls_id = val16;
291
0
      break;
292
0
    case CURL_SPACK_QUICTP: {
293
0
      result = spack_decdata16(&pval8, &dlen, &buf, end);
294
0
      if(result)
295
0
        goto out;
296
0
      curlx_free(s->quic_tp);
297
0
      s->quic_tp = pval8;
298
0
      s->quic_tp_len = dlen;
299
0
      break;
300
0
    }
301
0
    case CURL_SPACK_TICKET: {
302
0
      result = spack_decdata16(&pval8, &dlen, &buf, end);
303
0
      if(result)
304
0
        goto out;
305
0
      curlx_free(s->sdata);
306
0
      s->sdata = pval8;
307
0
      s->sdata_len = dlen;
308
0
      break;
309
0
    }
310
0
    case CURL_SPACK_VALID_UNTIL:
311
0
      result = spack_dec64(&val64, &buf, end);
312
0
      if(result)
313
0
        goto out;
314
0
      s->valid_until = (curl_off_t)val64;
315
0
      break;
316
0
    case CURL_SPACK_SECTRUST:
317
0
      s->sectrust_verified = TRUE;
318
0
      break;
319
0
    default:  /* unknown tag */
320
0
      result = CURLE_READ_ERROR;
321
0
      goto out;
322
0
    }
323
0
  }
324
325
0
out:
326
0
  if(result) {
327
0
    CURL_TRC_SSLS(data, "error unpacking data: %d", (int)result);
328
0
    Curl_ssl_session_destroy(s);
329
0
  }
330
0
  else
331
0
    *ps = s;
332
0
  return result;
333
0
}
334
335
#endif /* USE_SSL && USE_SSLS_EXPORT */