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