Coverage Report

Created: 2025-07-04 06:19

/src/nss/lib/ssl/tls13hashstate.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is PRIVATE to SSL.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8
9
#include "pk11func.h"
10
#include "ssl.h"
11
#include "sslt.h"
12
#include "sslimpl.h"
13
#include "selfencrypt.h"
14
#include "tls13con.h"
15
#include "tls13ech.h"
16
#include "tls13err.h"
17
#include "tls13hashstate.h"
18
19
/*
20
 * The cookie is structured as a self-encrypted structure with the
21
 * inner value being.
22
 *
23
 * struct {
24
 *     uint8 indicator = 0xff;            // To disambiguate from tickets.
25
 *     uint16 cipherSuite;                // Selected cipher suite.
26
 *     uint16 keyShare;                   // Requested key share group (0=none)
27
 *     PRUint8 echConfigId;               // ECH config_id
28
 *     HpkeKdfId kdfId;                   // ECH KDF (uint16)
29
 *     HpkeAeadId aeadId;                 // ECH AEAD (uint16)
30
 *     opaque echHpkeCtx<0..65535>;       // ECH serialized HPKE context
31
 *     opaque applicationToken<0..65535>; // Application token
32
 *     opaque ch_hash[rest_of_buffer];    // H(ClientHello)
33
 * } CookieInner;
34
 *
35
 * An empty echConfigId means that ECH was not offered in the first ClientHello.
36
 * An empty echHrrPsk means that ECH was not accepted in CH1.
37
 */
38
SECStatus
39
tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
40
                    const PRUint8 *appToken, unsigned int appTokenLen,
41
                    PRUint8 *buf, unsigned int *len, unsigned int maxlen)
42
580
{
43
580
    SECStatus rv;
44
580
    SSL3Hashes hashes;
45
580
    PRUint8 cookie[1024];
46
580
    sslBuffer cookieBuf = SSL_BUFFER(cookie);
47
580
    static const PRUint8 indicator = 0xff;
48
580
    SECItem *echHpkeCtx = NULL;
49
50
    /* Encode header. */
51
580
    rv = sslBuffer_Append(&cookieBuf, &indicator, 1);
52
580
    if (rv != SECSuccess) {
53
0
        return SECFailure;
54
0
    }
55
580
    rv = sslBuffer_AppendNumber(&cookieBuf, ss->ssl3.hs.cipher_suite, 2);
56
580
    if (rv != SECSuccess) {
57
0
        return SECFailure;
58
0
    }
59
580
    rv = sslBuffer_AppendNumber(&cookieBuf,
60
580
                                selectedGroup ? selectedGroup->name : 0, 2);
61
580
    if (rv != SECSuccess) {
62
0
        return SECFailure;
63
0
    }
64
65
580
    if (ss->xtnData.ech) {
66
        /* Record that we received ECH. See sslEchCookieData */
67
31
        rv = sslBuffer_AppendNumber(&cookieBuf, PR_TRUE, 1);
68
31
        if (rv != SECSuccess) {
69
0
            return SECFailure;
70
0
        }
71
72
31
        rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->configId,
73
31
                                    1);
74
31
        if (rv != SECSuccess) {
75
0
            return SECFailure;
76
0
        }
77
78
31
        rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->kdfId, 2);
79
31
        if (rv != SECSuccess) {
80
0
            return SECFailure;
81
0
        }
82
31
        rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->aeadId, 2);
83
31
        if (rv != SECSuccess) {
84
0
            return SECFailure;
85
0
        }
86
        /* We need to send a ECH HRR Extension containing a signal for the client,
87
         * we must store the signal in the cookie so we can reconstruct the transcript
88
         * later. To avoid leaking whether ECH was accepted in the length of the cookie
89
         * we include the empty signal in the cookie regardless.
90
         */
91
31
        PR_ASSERT(SSL_BUFFER_LEN(&ss->ssl3.hs.greaseEchBuf) == TLS13_ECH_SIGNAL_LEN);
92
31
        rv = sslBuffer_AppendBuffer(&cookieBuf, &ss->ssl3.hs.greaseEchBuf);
93
31
        if (rv != SECSuccess) {
94
0
            return SECFailure;
95
0
        }
96
97
        /* There might be no HPKE Context, e.g. when we lack a matching ECHConfig. */
98
31
        if (ss->ssl3.hs.echHpkeCtx) {
99
0
            rv = PK11_HPKE_ExportContext(ss->ssl3.hs.echHpkeCtx, NULL, &echHpkeCtx);
100
0
            if (rv != SECSuccess) {
101
0
                return SECFailure;
102
0
            }
103
0
            rv = sslBuffer_AppendVariable(&cookieBuf, echHpkeCtx->data, echHpkeCtx->len, 2);
104
0
            SECITEM_ZfreeItem(echHpkeCtx, PR_TRUE);
105
31
        } else {
106
            /* Zero length HPKE context. */
107
31
            rv = sslBuffer_AppendNumber(&cookieBuf, 0, 2);
108
31
        }
109
31
        if (rv != SECSuccess) {
110
0
            return SECFailure;
111
0
        }
112
549
    } else {
113
549
        rv = sslBuffer_AppendNumber(&cookieBuf, PR_FALSE, 1);
114
549
        if (rv != SECSuccess) {
115
0
            return SECFailure;
116
0
        }
117
549
    }
118
119
    /* Application token. */
120
580
    rv = sslBuffer_AppendVariable(&cookieBuf, appToken, appTokenLen, 2);
121
580
    if (rv != SECSuccess) {
122
0
        return SECFailure;
123
0
    }
124
125
    /* Compute and encode hashes. */
126
580
    rv = tls13_ComputeHandshakeHashes(ss, &hashes);
127
580
    if (rv != SECSuccess) {
128
0
        return SECFailure;
129
0
    }
130
580
    rv = sslBuffer_Append(&cookieBuf, hashes.u.raw, hashes.len);
131
580
    if (rv != SECSuccess) {
132
0
        return SECFailure;
133
0
    }
134
135
    /* Encrypt right into the buffer. */
136
580
    rv = ssl_SelfEncryptProtect(ss, cookieBuf.buf, cookieBuf.len,
137
580
                                buf, len, maxlen);
138
580
    if (rv != SECSuccess) {
139
0
        return SECFailure;
140
0
    }
141
142
580
    return SECSuccess;
143
580
}
144
145
/* Given a cookie and cookieLen, decrypt and parse, returning
146
 * any values that were requested via the "previous_" params. If
147
 * recoverState is true, the transcript state and application
148
 * token are restored. Note that previousEchKdfId, previousEchAeadId,
149
 * previousEchConfigId, and previousEchHpkeCtx are not modified if ECH was not
150
 * previously negotiated (i.e., previousEchOffered is PR_FALSE). */
151
SECStatus
152
tls13_HandleHrrCookie(sslSocket *ss,
153
                      unsigned char *cookie, unsigned int cookieLen,
154
                      ssl3CipherSuite *previousCipherSuite,
155
                      const sslNamedGroupDef **previousGroup,
156
                      PRBool *previousOfferedEch,
157
                      sslEchCookieData *echData,
158
                      PRBool recoverState)
159
157
{
160
157
    SECStatus rv;
161
157
    unsigned char plaintext[1024];
162
157
    unsigned int plaintextLen = 0;
163
157
    sslBuffer messageBuf = SSL_BUFFER_EMPTY;
164
157
    sslReadBuffer echHpkeBuf = { 0 };
165
157
    PRBool receivedEch;
166
157
    PRUint64 sentinel;
167
157
    PRUint64 cipherSuite;
168
157
    sslEchCookieData parsedEchData = { 0 };
169
157
    sslReadBuffer greaseReadBuf = { 0 };
170
157
    PRUint64 group;
171
157
    PRUint64 tmp64;
172
157
    const sslNamedGroupDef *selectedGroup;
173
157
    PRUint64 appTokenLen;
174
175
157
    rv = ssl_SelfEncryptUnprotect(ss, cookie, cookieLen,
176
157
                                  plaintext, &plaintextLen, sizeof(plaintext));
177
157
    if (rv != SECSuccess) {
178
80
        SSL_TRC(100, ("Error decrypting cookie."));
179
80
        return SECFailure;
180
80
    }
181
182
77
    sslReader reader = SSL_READER(plaintext, plaintextLen);
183
184
    /* Should start with the sentinel value. */
185
77
    rv = sslRead_ReadNumber(&reader, 1, &sentinel);
186
77
    if ((rv != SECSuccess) || (sentinel != TLS13_COOKIE_SENTINEL)) {
187
17
        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
188
17
        return SECFailure;
189
17
    }
190
    /* The cipher suite should be the same or there are some shenanigans. */
191
60
    rv = sslRead_ReadNumber(&reader, 2, &cipherSuite);
192
60
    if (rv != SECSuccess) {
193
1
        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
194
1
        return SECFailure;
195
1
    }
196
197
    /* The named group, if any. */
198
59
    rv = sslRead_ReadNumber(&reader, 2, &group);
199
59
    if (rv != SECSuccess) {
200
1
        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
201
1
        return SECFailure;
202
1
    }
203
58
    selectedGroup = ssl_LookupNamedGroup(group);
204
205
    /* Was ECH received. */
206
58
    rv = sslRead_ReadNumber(&reader, 1, &tmp64);
207
58
    if (rv != SECSuccess) {
208
1
        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
209
1
        return SECFailure;
210
1
    }
211
57
    receivedEch = tmp64 == PR_TRUE;
212
57
    *previousOfferedEch = receivedEch;
213
57
    if (receivedEch) {
214
        /* ECH config ID */
215
16
        rv = sslRead_ReadNumber(&reader, 1, &tmp64);
216
16
        if (rv != SECSuccess) {
217
1
            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
218
1
            return SECFailure;
219
1
        }
220
15
        parsedEchData.configId = (PRUint8)tmp64;
221
222
        /* ECH Ciphersuite */
223
15
        rv = sslRead_ReadNumber(&reader, 2, &tmp64);
224
15
        if (rv != SECSuccess) {
225
1
            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
226
1
            return SECFailure;
227
1
        }
228
14
        parsedEchData.kdfId = (HpkeKdfId)tmp64;
229
230
14
        rv = sslRead_ReadNumber(&reader, 2, &tmp64);
231
14
        if (rv != SECSuccess) {
232
1
            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
233
1
            return SECFailure;
234
1
        }
235
13
        parsedEchData.aeadId = (HpkeAeadId)tmp64;
236
237
        /* ECH accept_confirmation signal. */
238
13
        rv = sslRead_Read(&reader, TLS13_ECH_SIGNAL_LEN, &greaseReadBuf);
239
13
        if (rv != SECSuccess) {
240
3
            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
241
3
            return SECFailure;
242
3
        }
243
10
        PORT_Memcpy(parsedEchData.signal, greaseReadBuf.buf, TLS13_ECH_SIGNAL_LEN);
244
245
        /* ECH HPKE context may be empty. */
246
10
        rv = sslRead_ReadVariable(&reader, 2, &echHpkeBuf);
247
10
        if (rv != SECSuccess) {
248
3
            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
249
3
            return SECFailure;
250
3
        }
251
7
        if (echData && echHpkeBuf.len) {
252
2
            const SECItem hpkeItem = { siBuffer, CONST_CAST(unsigned char, echHpkeBuf.buf),
253
2
                                       echHpkeBuf.len };
254
2
            parsedEchData.hpkeCtx = PK11_HPKE_ImportContext(&hpkeItem, NULL);
255
2
            if (!parsedEchData.hpkeCtx) {
256
2
                FATAL_ERROR(ss, PORT_GetError(), illegal_parameter);
257
2
                return SECFailure;
258
2
            }
259
2
        }
260
7
    }
261
262
    /* Application token. */
263
46
    rv = sslRead_ReadNumber(&reader, 2, &appTokenLen);
264
46
    if (rv != SECSuccess) {
265
1
        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
266
1
        return SECFailure;
267
1
    }
268
45
    sslReadBuffer appTokenReader = { 0 };
269
45
    rv = sslRead_Read(&reader, appTokenLen, &appTokenReader);
270
45
    if (rv != SECSuccess) {
271
17
        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
272
17
        return SECFailure;
273
17
    }
274
28
    PORT_Assert(appTokenReader.len == appTokenLen);
275
276
28
    if (recoverState) {
277
6
        PORT_Assert(ss->xtnData.applicationToken.len == 0);
278
6
        if (SECITEM_AllocItem(NULL, &ss->xtnData.applicationToken,
279
6
                              appTokenLen) == NULL) {
280
0
            FATAL_ERROR(ss, PORT_GetError(), internal_error);
281
0
            return SECFailure;
282
0
        }
283
6
        PORT_Memcpy(ss->xtnData.applicationToken.data, appTokenReader.buf, appTokenLen);
284
6
        ss->xtnData.applicationToken.len = appTokenLen;
285
286
        /* The remainder is the hash. */
287
6
        unsigned int hashLen = SSL_READER_REMAINING(&reader);
288
6
        if (hashLen != tls13_GetHashSize(ss)) {
289
6
            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
290
6
            return SECFailure;
291
6
        }
292
293
        /* Now reinject the message. */
294
0
        SSL_ASSERT_HASHES_EMPTY(ss);
295
0
        rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0,
296
0
                                         SSL_READER_CURRENT(&reader), hashLen,
297
0
                                         ssl3_UpdateHandshakeHashes);
298
0
        if (rv != SECSuccess) {
299
0
            return SECFailure;
300
0
        }
301
302
        /* And finally reinject the HRR. */
303
0
        rv = tls13_ConstructHelloRetryRequest(ss, cipherSuite,
304
0
                                              selectedGroup,
305
0
                                              cookie, cookieLen,
306
0
                                              parsedEchData.signal,
307
0
                                              &messageBuf);
308
0
        if (rv != SECSuccess) {
309
0
            return SECFailure;
310
0
        }
311
312
0
        rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_server_hello, 0,
313
0
                                         SSL_BUFFER_BASE(&messageBuf),
314
0
                                         SSL_BUFFER_LEN(&messageBuf),
315
0
                                         ssl3_UpdateHandshakeHashes);
316
0
        sslBuffer_Clear(&messageBuf);
317
0
        if (rv != SECSuccess) {
318
0
            return SECFailure;
319
0
        }
320
0
    }
321
322
22
    if (previousCipherSuite) {
323
0
        *previousCipherSuite = cipherSuite;
324
0
    }
325
22
    if (previousGroup) {
326
0
        *previousGroup = selectedGroup;
327
0
    }
328
22
    if (echData) {
329
22
        PORT_Memcpy(echData, &parsedEchData, sizeof(parsedEchData));
330
22
    }
331
22
    return SECSuccess;
332
28
}