1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 /* This file contains functions for frobbing the internals of libssl */
8 #include "libssl_internals.h"
9
10 #include "nss.h"
11 #include "pk11hpke.h"
12 #include "pk11pub.h"
13 #include "pk11priv.h"
14 #include "tls13ech.h"
15 #include "seccomon.h"
16 #include "selfencrypt.h"
17 #include "secmodti.h"
18 #include "sslproto.h"
19
SSLInt_RemoveServerCertificates(PRFileDesc * fd)20 SECStatus SSLInt_RemoveServerCertificates(PRFileDesc *fd) {
21 if (!fd) {
22 return SECFailure;
23 }
24 sslSocket *ss = ssl_FindSocket(fd);
25 if (!ss) {
26 return SECFailure;
27 }
28
29 PRCList *cursor;
30 while (!PR_CLIST_IS_EMPTY(&ss->serverCerts)) {
31 cursor = PR_LIST_TAIL(&ss->serverCerts);
32 PR_REMOVE_LINK(cursor);
33 ssl_FreeServerCert((sslServerCert *)cursor);
34 }
35 return SECSuccess;
36 }
37
SSLInt_SetDCAdvertisedSigSchemes(PRFileDesc * fd,const SSLSignatureScheme * schemes,uint32_t num_sig_schemes)38 SECStatus SSLInt_SetDCAdvertisedSigSchemes(PRFileDesc *fd,
39 const SSLSignatureScheme *schemes,
40 uint32_t num_sig_schemes) {
41 if (!fd) {
42 return SECFailure;
43 }
44 sslSocket *ss = ssl_FindSocket(fd);
45 if (!ss) {
46 return SECFailure;
47 }
48
49 // Alloc and copy, libssl will free.
50 SSLSignatureScheme *dc_schemes =
51 PORT_ZNewArray(SSLSignatureScheme, num_sig_schemes);
52 if (!dc_schemes) {
53 return SECFailure;
54 }
55 memcpy(dc_schemes, schemes, sizeof(SSLSignatureScheme) * num_sig_schemes);
56
57 if (ss->xtnData.delegCredSigSchemesAdvertised) {
58 PORT_Free(ss->xtnData.delegCredSigSchemesAdvertised);
59 }
60 ss->xtnData.delegCredSigSchemesAdvertised = dc_schemes;
61 ss->xtnData.numDelegCredSigSchemesAdvertised = num_sig_schemes;
62 return SECSuccess;
63 }
64
SSLInt_TweakChannelInfoForDC(PRFileDesc * fd,PRBool changeAuthKeyBits,PRBool changeScheme)65 SECStatus SSLInt_TweakChannelInfoForDC(PRFileDesc *fd, PRBool changeAuthKeyBits,
66 PRBool changeScheme) {
67 if (!fd) {
68 return SECFailure;
69 }
70 sslSocket *ss = ssl_FindSocket(fd);
71 if (!ss) {
72 return SECFailure;
73 }
74
75 // Just toggle so we'll always have a valid value.
76 if (changeScheme) {
77 ss->sec.signatureScheme = (ss->sec.signatureScheme == ssl_sig_ed25519)
78 ? ssl_sig_ecdsa_secp256r1_sha256
79 : ssl_sig_ed25519;
80 }
81 if (changeAuthKeyBits) {
82 ss->sec.authKeyBits = ss->sec.authKeyBits ? ss->sec.authKeyBits * 2 : 384;
83 }
84
85 return SECSuccess;
86 }
87
SSLInt_GetHandshakeRandoms(PRFileDesc * fd,SSL3Random client_random,SSL3Random server_random)88 SECStatus SSLInt_GetHandshakeRandoms(PRFileDesc *fd, SSL3Random client_random,
89 SSL3Random server_random) {
90 if (!fd) {
91 return SECFailure;
92 }
93 sslSocket *ss = ssl_FindSocket(fd);
94 if (!ss) {
95 return SECFailure;
96 }
97
98 if (client_random) {
99 memcpy(client_random, ss->ssl3.hs.client_random, sizeof(SSL3Random));
100 }
101 if (server_random) {
102 memcpy(server_random, ss->ssl3.hs.server_random, sizeof(SSL3Random));
103 }
104 return SECSuccess;
105 }
106
SSLInt_IncrementClientHandshakeVersion(PRFileDesc * fd)107 SECStatus SSLInt_IncrementClientHandshakeVersion(PRFileDesc *fd) {
108 sslSocket *ss = ssl_FindSocket(fd);
109 if (!ss) {
110 return SECFailure;
111 }
112
113 ++ss->clientHelloVersion;
114
115 return SECSuccess;
116 }
117
118 /* Use this function to update the ClientRandom of a client's handshake state
119 * after replacing its ClientHello message. We for example need to do this
120 * when replacing an SSLv3 ClientHello with its SSLv2 equivalent. */
SSLInt_UpdateSSLv2ClientRandom(PRFileDesc * fd,uint8_t * rnd,size_t rnd_len,uint8_t * msg,size_t msg_len)121 SECStatus SSLInt_UpdateSSLv2ClientRandom(PRFileDesc *fd, uint8_t *rnd,
122 size_t rnd_len, uint8_t *msg,
123 size_t msg_len) {
124 sslSocket *ss = ssl_FindSocket(fd);
125 if (!ss) {
126 return SECFailure;
127 }
128
129 ssl3_RestartHandshakeHashes(ss);
130
131 // Ensure we don't overrun hs.client_random.
132 rnd_len = PR_MIN(SSL3_RANDOM_LENGTH, rnd_len);
133
134 // Zero the client_random.
135 PORT_Memset(ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
136
137 // Copy over the challenge bytes.
138 size_t offset = SSL3_RANDOM_LENGTH - rnd_len;
139 PORT_Memcpy(ss->ssl3.hs.client_random + offset, rnd, rnd_len);
140
141 // Rehash the SSLv2 client hello message.
142 return ssl3_UpdateHandshakeHashes(ss, msg, msg_len);
143 }
144
SSLInt_ExtensionNegotiated(PRFileDesc * fd,PRUint16 ext)145 PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext) {
146 sslSocket *ss = ssl_FindSocket(fd);
147 return (PRBool)(ss && ssl3_ExtensionNegotiated(ss, ext));
148 }
149
150 // Tests should not use this function directly, because the keys may
151 // still be in cache. Instead, use TlsConnectTestBase::ClearServerCache.
SSLInt_ClearSelfEncryptKey()152 void SSLInt_ClearSelfEncryptKey() { ssl_ResetSelfEncryptKeys(); }
153
154 sslSelfEncryptKeys *ssl_GetSelfEncryptKeysInt();
155
SSLInt_SetSelfEncryptMacKey(PK11SymKey * key)156 void SSLInt_SetSelfEncryptMacKey(PK11SymKey *key) {
157 sslSelfEncryptKeys *keys = ssl_GetSelfEncryptKeysInt();
158
159 PK11_FreeSymKey(keys->macKey);
160 keys->macKey = key;
161 }
162
SSLInt_SetMTU(PRFileDesc * fd,PRUint16 mtu)163 SECStatus SSLInt_SetMTU(PRFileDesc *fd, PRUint16 mtu) {
164 sslSocket *ss = ssl_FindSocket(fd);
165 if (!ss) {
166 return SECFailure;
167 }
168 ss->ssl3.mtu = mtu;
169 ss->ssl3.hs.rtRetries = 0; /* Avoid DTLS shrinking the MTU any more. */
170 return SECSuccess;
171 }
172
SSLInt_CountCipherSpecs(PRFileDesc * fd)173 PRInt32 SSLInt_CountCipherSpecs(PRFileDesc *fd) {
174 PRCList *cur_p;
175 PRInt32 ct = 0;
176
177 sslSocket *ss = ssl_FindSocket(fd);
178 if (!ss) {
179 return -1;
180 }
181
182 for (cur_p = PR_NEXT_LINK(&ss->ssl3.hs.cipherSpecs);
183 cur_p != &ss->ssl3.hs.cipherSpecs; cur_p = PR_NEXT_LINK(cur_p)) {
184 ++ct;
185 }
186 return ct;
187 }
188
SSLInt_PrintCipherSpecs(const char * label,PRFileDesc * fd)189 void SSLInt_PrintCipherSpecs(const char *label, PRFileDesc *fd) {
190 PRCList *cur_p;
191
192 sslSocket *ss = ssl_FindSocket(fd);
193 if (!ss) {
194 return;
195 }
196
197 fprintf(stderr, "Cipher specs for %s\n", label);
198 for (cur_p = PR_NEXT_LINK(&ss->ssl3.hs.cipherSpecs);
199 cur_p != &ss->ssl3.hs.cipherSpecs; cur_p = PR_NEXT_LINK(cur_p)) {
200 ssl3CipherSpec *spec = (ssl3CipherSpec *)cur_p;
201 fprintf(stderr, " %s spec epoch=%d (%s) refct=%d\n", SPEC_DIR(spec),
202 spec->epoch, spec->phase, spec->refCt);
203 }
204 }
205
206 /* DTLS timers are separate from the time that the rest of the stack uses.
207 * Force a timer expiry by backdating when all active timers were started.
208 * We could set the remaining time to 0 but then backoff would not work properly
209 * if we decide to test it. */
SSLInt_ShiftDtlsTimers(PRFileDesc * fd,PRIntervalTime shift)210 SECStatus SSLInt_ShiftDtlsTimers(PRFileDesc *fd, PRIntervalTime shift) {
211 size_t i;
212 sslSocket *ss = ssl_FindSocket(fd);
213 if (!ss) {
214 return SECFailure;
215 }
216
217 for (i = 0; i < PR_ARRAY_SIZE(ss->ssl3.hs.timers); ++i) {
218 if (ss->ssl3.hs.timers[i].cb) {
219 ss->ssl3.hs.timers[i].started -= shift;
220 }
221 }
222 return SECSuccess;
223 }
224
225 #define CHECK_SECRET(secret) \
226 if (ss->ssl3.hs.secret) { \
227 fprintf(stderr, "%s != NULL\n", #secret); \
228 return PR_FALSE; \
229 }
230
SSLInt_CheckSecretsDestroyed(PRFileDesc * fd)231 PRBool SSLInt_CheckSecretsDestroyed(PRFileDesc *fd) {
232 sslSocket *ss = ssl_FindSocket(fd);
233 if (!ss) {
234 return PR_FALSE;
235 }
236
237 CHECK_SECRET(currentSecret);
238 CHECK_SECRET(dheSecret);
239 CHECK_SECRET(clientEarlyTrafficSecret);
240 CHECK_SECRET(clientHsTrafficSecret);
241 CHECK_SECRET(serverHsTrafficSecret);
242
243 return PR_TRUE;
244 }
245
sslint_DamageTrafficSecret(PRFileDesc * fd,size_t offset)246 PRBool sslint_DamageTrafficSecret(PRFileDesc *fd, size_t offset) {
247 unsigned char data[32] = {0};
248 PK11SymKey **keyPtr;
249 PK11SlotInfo *slot = PK11_GetInternalSlot();
250 SECItem key_item = {siBuffer, data, sizeof(data)};
251 sslSocket *ss = ssl_FindSocket(fd);
252 if (!ss) {
253 return PR_FALSE;
254 }
255 if (!slot) {
256 return PR_FALSE;
257 }
258 keyPtr = (PK11SymKey **)((char *)&ss->ssl3.hs + offset);
259 if (!*keyPtr) {
260 return PR_FALSE;
261 }
262 PK11_FreeSymKey(*keyPtr);
263 *keyPtr = PK11_ImportSymKey(slot, CKM_NSS_HKDF_SHA256, PK11_OriginUnwrap,
264 CKA_DERIVE, &key_item, NULL);
265 PK11_FreeSlot(slot);
266 if (!*keyPtr) {
267 return PR_FALSE;
268 }
269
270 return PR_TRUE;
271 }
272
SSLInt_DamageClientHsTrafficSecret(PRFileDesc * fd)273 PRBool SSLInt_DamageClientHsTrafficSecret(PRFileDesc *fd) {
274 return sslint_DamageTrafficSecret(
275 fd, offsetof(SSL3HandshakeState, clientHsTrafficSecret));
276 }
277
SSLInt_DamageServerHsTrafficSecret(PRFileDesc * fd)278 PRBool SSLInt_DamageServerHsTrafficSecret(PRFileDesc *fd) {
279 return sslint_DamageTrafficSecret(
280 fd, offsetof(SSL3HandshakeState, serverHsTrafficSecret));
281 }
282
SSLInt_DamageEarlyTrafficSecret(PRFileDesc * fd)283 PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd) {
284 return sslint_DamageTrafficSecret(
285 fd, offsetof(SSL3HandshakeState, clientEarlyTrafficSecret));
286 }
287
SSLInt_Set0RttAlpn(PRFileDesc * fd,PRUint8 * data,unsigned int len)288 SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len) {
289 sslSocket *ss = ssl_FindSocket(fd);
290 if (!ss) {
291 return SECFailure;
292 }
293
294 ss->xtnData.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE;
295 if (ss->xtnData.nextProto.data) {
296 SECITEM_FreeItem(&ss->xtnData.nextProto, PR_FALSE);
297 }
298 if (!SECITEM_AllocItem(NULL, &ss->xtnData.nextProto, len)) {
299 return SECFailure;
300 }
301 PORT_Memcpy(ss->xtnData.nextProto.data, data, len);
302
303 return SECSuccess;
304 }
305
SSLInt_HasCertWithAuthType(PRFileDesc * fd,SSLAuthType authType)306 PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType) {
307 sslSocket *ss = ssl_FindSocket(fd);
308 if (!ss) {
309 return PR_FALSE;
310 }
311
312 return (PRBool)(!!ssl_FindServerCert(ss, authType, NULL));
313 }
314
SSLInt_SendAlert(PRFileDesc * fd,uint8_t level,uint8_t type)315 PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type) {
316 sslSocket *ss = ssl_FindSocket(fd);
317 if (!ss) {
318 return PR_FALSE;
319 }
320
321 SECStatus rv = SSL3_SendAlert(ss, level, type);
322 if (rv != SECSuccess) return PR_FALSE;
323
324 return PR_TRUE;
325 }
326
SSLInt_AdvanceReadSeqNum(PRFileDesc * fd,PRUint64 to)327 SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to) {
328 sslSocket *ss;
329 ssl3CipherSpec *spec;
330
331 ss = ssl_FindSocket(fd);
332 if (!ss) {
333 return SECFailure;
334 }
335 if (to > RECORD_SEQ_MAX) {
336 PORT_SetError(SEC_ERROR_INVALID_ARGS);
337 return SECFailure;
338 }
339 ssl_GetSpecWriteLock(ss);
340 spec = ss->ssl3.crSpec;
341 spec->nextSeqNum = to;
342
343 /* For DTLS, we need to fix the record sequence number. For this, we can just
344 * scrub the entire structure on the assumption that the new sequence number
345 * is far enough past the last received sequence number. */
346 if (spec->nextSeqNum <=
347 spec->recvdRecords.right + DTLS_RECVD_RECORDS_WINDOW) {
348 PORT_SetError(SEC_ERROR_INVALID_ARGS);
349 return SECFailure;
350 }
351 dtls_RecordSetRecvd(&spec->recvdRecords, spec->nextSeqNum - 1);
352
353 ssl_ReleaseSpecWriteLock(ss);
354 return SECSuccess;
355 }
356
SSLInt_AdvanceWriteSeqNum(PRFileDesc * fd,PRUint64 to)357 SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to) {
358 sslSocket *ss;
359 ssl3CipherSpec *spec;
360 PK11Context *pk11ctxt;
361 const ssl3BulkCipherDef *cipher_def;
362
363 ss = ssl_FindSocket(fd);
364 if (!ss) {
365 return SECFailure;
366 }
367 if (to >= RECORD_SEQ_MAX) {
368 PORT_SetError(SEC_ERROR_INVALID_ARGS);
369 return SECFailure;
370 }
371 ssl_GetSpecWriteLock(ss);
372 spec = ss->ssl3.cwSpec;
373 cipher_def = spec->cipherDef;
374 spec->nextSeqNum = to;
375 if (cipher_def->type != type_aead) {
376 ssl_ReleaseSpecWriteLock(ss);
377 return SECSuccess;
378 }
379 /* If we are using aead, we need to advance the counter in the
380 * internal IV generator as well.
381 * This could be in the token or software. */
382 pk11ctxt = spec->cipherContext;
383 /* If counter is in the token, we need to switch it to software,
384 * since we don't have access to the internal state of the token. We do
385 * that by turning on the simulated message interface, then setting up the
386 * software IV generator */
387 if (pk11ctxt->ivCounter == 0) {
388 _PK11_ContextSetAEADSimulation(pk11ctxt);
389 pk11ctxt->ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size;
390 pk11ctxt->ivMaxCount = PR_UINT64(0xffffffffffffffff);
391 if ((cipher_def->explicit_nonce_size == 0) ||
392 (spec->version >= SSL_LIBRARY_VERSION_TLS_1_3)) {
393 pk11ctxt->ivFixedBits =
394 (pk11ctxt->ivLen - sizeof(sslSequenceNumber)) * BPB;
395 pk11ctxt->ivGen = CKG_GENERATE_COUNTER_XOR;
396 } else {
397 pk11ctxt->ivFixedBits = cipher_def->iv_size * BPB;
398 pk11ctxt->ivGen = CKG_GENERATE_COUNTER;
399 }
400 /* DTLS included the epoch in the fixed portion of the IV */
401 if (IS_DTLS(ss)) {
402 pk11ctxt->ivFixedBits += 2 * BPB;
403 }
404 }
405 /* now we can update the internal counter (either we are already using
406 * the software IV generator, or we just switched to it above */
407 pk11ctxt->ivCounter = to;
408
409 ssl_ReleaseSpecWriteLock(ss);
410 return SECSuccess;
411 }
412
SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc * fd,PRInt32 extra)413 SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra) {
414 sslSocket *ss;
415 sslSequenceNumber to;
416
417 ss = ssl_FindSocket(fd);
418 if (!ss) {
419 return SECFailure;
420 }
421 ssl_GetSpecReadLock(ss);
422 to = ss->ssl3.cwSpec->nextSeqNum + DTLS_RECVD_RECORDS_WINDOW + extra;
423 ssl_ReleaseSpecReadLock(ss);
424 return SSLInt_AdvanceWriteSeqNum(fd, to);
425 }
426
SSLInt_AdvanceDtls13DecryptFailures(PRFileDesc * fd,PRUint64 to)427 SECStatus SSLInt_AdvanceDtls13DecryptFailures(PRFileDesc *fd, PRUint64 to) {
428 sslSocket *ss = ssl_FindSocket(fd);
429 if (!ss) {
430 return SECFailure;
431 }
432
433 ssl_GetSpecWriteLock(ss);
434 ssl3CipherSpec *spec = ss->ssl3.crSpec;
435 if (spec->cipherDef->type != type_aead) {
436 ssl_ReleaseSpecWriteLock(ss);
437 return SECFailure;
438 }
439
440 spec->deprotectionFailures = to;
441 ssl_ReleaseSpecWriteLock(ss);
442 return SECSuccess;
443 }
444
SSLInt_GetKEAType(SSLNamedGroup group)445 SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group) {
446 const sslNamedGroupDef *groupDef = ssl_LookupNamedGroup(group);
447 if (!groupDef) return ssl_kea_null;
448
449 return groupDef->keaType;
450 }
451
SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc * fd,uint32_t size)452 SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size) {
453 sslSocket *ss;
454
455 ss = ssl_FindSocket(fd);
456 if (!ss) {
457 return SECFailure;
458 }
459
460 /* This only works when resuming. */
461 if (!ss->statelessResume) {
462 PORT_SetError(SEC_INTERNAL_ONLY);
463 return SECFailure;
464 }
465
466 /* Modifying both specs allows this to be used on either peer. */
467 ssl_GetSpecWriteLock(ss);
468 ss->ssl3.crSpec->earlyDataRemaining = size;
469 ss->ssl3.cwSpec->earlyDataRemaining = size;
470 ssl_ReleaseSpecWriteLock(ss);
471
472 return SECSuccess;
473 }
474
SSLInt_HasPendingHandshakeData(PRFileDesc * fd,PRBool * pending)475 SECStatus SSLInt_HasPendingHandshakeData(PRFileDesc *fd, PRBool *pending) {
476 sslSocket *ss = ssl_FindSocket(fd);
477 if (!ss) {
478 return SECFailure;
479 }
480
481 ssl_GetSSL3HandshakeLock(ss);
482 *pending = ss->ssl3.hs.msg_body.len > 0;
483 ssl_ReleaseSSL3HandshakeLock(ss);
484 return SECSuccess;
485 }
486
SSLInt_SetRawEchConfigForRetry(PRFileDesc * fd,const uint8_t * buf,size_t len)487 SECStatus SSLInt_SetRawEchConfigForRetry(PRFileDesc *fd, const uint8_t *buf,
488 size_t len) {
489 sslSocket *ss = ssl_FindSocket(fd);
490 if (!ss) {
491 return SECFailure;
492 }
493
494 sslEchConfig *cfg = (sslEchConfig *)PR_LIST_HEAD(&ss->echConfigs);
495 SECITEM_FreeItem(&cfg->raw, PR_FALSE);
496 SECITEM_AllocItem(NULL, &cfg->raw, len);
497 PORT_Memcpy(cfg->raw.data, buf, len);
498 return SECSuccess;
499 }
500
SSLInt_IsIp(PRUint8 * s,unsigned int len)501 PRBool SSLInt_IsIp(PRUint8 *s, unsigned int len) { return tls13_IsIp(s, len); }
502