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