libssl_internals.c (16668B)
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 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 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 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 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 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. */ 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 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. 152 void SSLInt_ClearSelfEncryptKey() { ssl_ResetSelfEncryptKeys(); } 153 154 sslSelfEncryptKeys *ssl_GetSelfEncryptKeysInt(); 155 156 void SSLInt_SetSelfEncryptMacKey(PK11SymKey *key) { 157 sslSelfEncryptKeys *keys = ssl_GetSelfEncryptKeysInt(); 158 159 PK11_FreeSymKey(keys->macKey); 160 keys->macKey = key; 161 } 162 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 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 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. */ 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 /* Instead of waiting the ACK timer to expire, we send the ack immediately*/ 226 SECStatus SSLInt_SendImmediateACK(PRFileDesc *fd) { 227 sslSocket *ss = ssl_FindSocket(fd); 228 if (!ss) { 229 return SECFailure; 230 } 231 PORT_Assert(IS_DTLS(ss)); 232 dtls13_SendAck(ss); 233 return SECSuccess; 234 } 235 236 #define CHECK_SECRET(secret) \ 237 if (ss->ssl3.hs.secret) { \ 238 fprintf(stderr, "%s != NULL\n", #secret); \ 239 return PR_FALSE; \ 240 } 241 242 PRBool SSLInt_CheckSecretsDestroyed(PRFileDesc *fd) { 243 sslSocket *ss = ssl_FindSocket(fd); 244 if (!ss) { 245 return PR_FALSE; 246 } 247 248 CHECK_SECRET(currentSecret); 249 CHECK_SECRET(dheSecret); 250 CHECK_SECRET(clientEarlyTrafficSecret); 251 CHECK_SECRET(clientHsTrafficSecret); 252 CHECK_SECRET(serverHsTrafficSecret); 253 254 return PR_TRUE; 255 } 256 257 PRBool sslint_DamageTrafficSecret(PRFileDesc *fd, size_t offset) { 258 unsigned char data[32] = {0}; 259 PK11SymKey **keyPtr; 260 PK11SlotInfo *slot = PK11_GetInternalSlot(); 261 SECItem key_item = {siBuffer, data, sizeof(data)}; 262 sslSocket *ss = ssl_FindSocket(fd); 263 if (!ss) { 264 return PR_FALSE; 265 } 266 if (!slot) { 267 return PR_FALSE; 268 } 269 keyPtr = (PK11SymKey **)((char *)&ss->ssl3.hs + offset); 270 if (!*keyPtr) { 271 return PR_FALSE; 272 } 273 PK11_FreeSymKey(*keyPtr); 274 *keyPtr = PK11_ImportSymKey(slot, CKM_NSS_HKDF_SHA256, PK11_OriginUnwrap, 275 CKA_DERIVE, &key_item, NULL); 276 PK11_FreeSlot(slot); 277 if (!*keyPtr) { 278 return PR_FALSE; 279 } 280 281 return PR_TRUE; 282 } 283 284 PRBool SSLInt_DamageClientHsTrafficSecret(PRFileDesc *fd) { 285 return sslint_DamageTrafficSecret( 286 fd, offsetof(SSL3HandshakeState, clientHsTrafficSecret)); 287 } 288 289 PRBool SSLInt_DamageServerHsTrafficSecret(PRFileDesc *fd) { 290 return sslint_DamageTrafficSecret( 291 fd, offsetof(SSL3HandshakeState, serverHsTrafficSecret)); 292 } 293 294 PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd) { 295 return sslint_DamageTrafficSecret( 296 fd, offsetof(SSL3HandshakeState, clientEarlyTrafficSecret)); 297 } 298 299 SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len) { 300 sslSocket *ss = ssl_FindSocket(fd); 301 if (!ss) { 302 return SECFailure; 303 } 304 305 ss->xtnData.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE; 306 if (ss->xtnData.nextProto.data) { 307 SECITEM_FreeItem(&ss->xtnData.nextProto, PR_FALSE); 308 } 309 if (!SECITEM_AllocItem(NULL, &ss->xtnData.nextProto, len)) { 310 return SECFailure; 311 } 312 PORT_Memcpy(ss->xtnData.nextProto.data, data, len); 313 314 return SECSuccess; 315 } 316 317 PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType) { 318 sslSocket *ss = ssl_FindSocket(fd); 319 if (!ss) { 320 return PR_FALSE; 321 } 322 323 return (PRBool)(!!ssl_FindServerCert(ss, authType, NULL)); 324 } 325 326 PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type) { 327 sslSocket *ss = ssl_FindSocket(fd); 328 if (!ss) { 329 return PR_FALSE; 330 } 331 332 SECStatus rv = SSL3_SendAlert(ss, level, type); 333 if (rv != SECSuccess) return PR_FALSE; 334 335 return PR_TRUE; 336 } 337 338 SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to) { 339 sslSocket *ss; 340 ssl3CipherSpec *spec; 341 342 ss = ssl_FindSocket(fd); 343 if (!ss) { 344 return SECFailure; 345 } 346 if (to > RECORD_SEQ_MAX) { 347 PORT_SetError(SEC_ERROR_INVALID_ARGS); 348 return SECFailure; 349 } 350 ssl_GetSpecWriteLock(ss); 351 spec = ss->ssl3.crSpec; 352 spec->nextSeqNum = to; 353 354 /* For DTLS, we need to fix the record sequence number. For this, we can just 355 * scrub the entire structure on the assumption that the new sequence number 356 * is far enough past the last received sequence number. */ 357 if (spec->nextSeqNum <= 358 spec->recvdRecords.right + DTLS_RECVD_RECORDS_WINDOW) { 359 PORT_SetError(SEC_ERROR_INVALID_ARGS); 360 return SECFailure; 361 } 362 dtls_RecordSetRecvd(&spec->recvdRecords, spec->nextSeqNum - 1); 363 364 ssl_ReleaseSpecWriteLock(ss); 365 return SECSuccess; 366 } 367 368 SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to) { 369 sslSocket *ss; 370 ssl3CipherSpec *spec; 371 PK11Context *pk11ctxt; 372 const ssl3BulkCipherDef *cipher_def; 373 374 ss = ssl_FindSocket(fd); 375 if (!ss) { 376 return SECFailure; 377 } 378 if (to >= RECORD_SEQ_MAX) { 379 PORT_SetError(SEC_ERROR_INVALID_ARGS); 380 return SECFailure; 381 } 382 ssl_GetSpecWriteLock(ss); 383 spec = ss->ssl3.cwSpec; 384 cipher_def = spec->cipherDef; 385 spec->nextSeqNum = to; 386 if (cipher_def->type != type_aead) { 387 ssl_ReleaseSpecWriteLock(ss); 388 return SECSuccess; 389 } 390 /* If we are using aead, we need to advance the counter in the 391 * internal IV generator as well. 392 * This could be in the token or software. */ 393 pk11ctxt = spec->cipherContext; 394 /* If counter is in the token, we need to switch it to software, 395 * since we don't have access to the internal state of the token. We do 396 * that by turning on the simulated message interface, then setting up the 397 * software IV generator */ 398 if (pk11ctxt->ivCounter == 0) { 399 _PK11_ContextSetAEADSimulation(pk11ctxt); 400 pk11ctxt->ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size; 401 pk11ctxt->ivMaxCount = PR_UINT64(0xffffffffffffffff); 402 if ((cipher_def->explicit_nonce_size == 0) || 403 (spec->version >= SSL_LIBRARY_VERSION_TLS_1_3)) { 404 pk11ctxt->ivFixedBits = 405 (pk11ctxt->ivLen - sizeof(sslSequenceNumber)) * BPB; 406 pk11ctxt->ivGen = CKG_GENERATE_COUNTER_XOR; 407 } else { 408 pk11ctxt->ivFixedBits = cipher_def->iv_size * BPB; 409 pk11ctxt->ivGen = CKG_GENERATE_COUNTER; 410 } 411 /* DTLS1.2 and below included the epoch in the fixed portion of the IV */ 412 if (IS_DTLS_1_OR_12(ss)) { 413 pk11ctxt->ivFixedBits += 2 * BPB; 414 } 415 } 416 /* now we can update the internal counter (either we are already using 417 * the software IV generator, or we just switched to it above */ 418 pk11ctxt->ivCounter = to; 419 420 ssl_ReleaseSpecWriteLock(ss); 421 return SECSuccess; 422 } 423 424 /* The next two functions are responsible for replacing the epoch count with the 425 one given as the parameter. Important: It does not modify any other data, i.e. 426 keys. Used in ssl_keyupdate_unittests.cc, 427 DTLSKeyUpdateClient_KeyUpdateMaxEpoch TV. 428 */ 429 SECStatus SSLInt_AdvanceWriteEpochNum(PRFileDesc *fd, PRUint64 to) { 430 sslSocket *ss; 431 ss = ssl_FindSocket(fd); 432 if (!ss) { 433 return SECFailure; 434 } 435 // As currently the epoch is presented as a uint16, the max_epoch is the 436 // maximum value of the type 437 PRUint64 max_epoch = UINT16_MAX; 438 if (to > max_epoch) { 439 PORT_SetError(SEC_ERROR_INVALID_ARGS); 440 return SECFailure; 441 } 442 443 ssl_GetSpecWriteLock(ss); 444 ss->ssl3.cwSpec->epoch = to; 445 ssl_ReleaseSpecWriteLock(ss); 446 return SECSuccess; 447 } 448 449 SECStatus SSLInt_AdvanceReadEpochNum(PRFileDesc *fd, PRUint64 to) { 450 sslSocket *ss; 451 ss = ssl_FindSocket(fd); 452 if (!ss) { 453 return SECFailure; 454 } 455 456 PRUint64 max_epoch = UINT16_MAX; 457 if (to > max_epoch) { 458 PORT_SetError(SEC_ERROR_INVALID_ARGS); 459 return SECFailure; 460 } 461 462 ssl_GetSpecReadLock(ss); 463 ss->ssl3.crSpec->epoch = to; 464 ssl_ReleaseSpecReadLock(ss); 465 return SECSuccess; 466 } 467 468 SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra) { 469 sslSocket *ss; 470 sslSequenceNumber to; 471 472 ss = ssl_FindSocket(fd); 473 if (!ss) { 474 return SECFailure; 475 } 476 ssl_GetSpecReadLock(ss); 477 to = ss->ssl3.cwSpec->nextSeqNum + DTLS_RECVD_RECORDS_WINDOW + extra; 478 ssl_ReleaseSpecReadLock(ss); 479 return SSLInt_AdvanceWriteSeqNum(fd, to); 480 } 481 482 SECStatus SSLInt_AdvanceDtls13DecryptFailures(PRFileDesc *fd, PRUint64 to) { 483 sslSocket *ss = ssl_FindSocket(fd); 484 if (!ss) { 485 return SECFailure; 486 } 487 488 ssl_GetSpecWriteLock(ss); 489 ssl3CipherSpec *spec = ss->ssl3.crSpec; 490 if (spec->cipherDef->type != type_aead) { 491 ssl_ReleaseSpecWriteLock(ss); 492 return SECFailure; 493 } 494 495 spec->deprotectionFailures = to; 496 ssl_ReleaseSpecWriteLock(ss); 497 return SECSuccess; 498 } 499 500 SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group) { 501 const sslNamedGroupDef *groupDef = ssl_LookupNamedGroup(group); 502 if (!groupDef) return ssl_kea_null; 503 504 return groupDef->keaType; 505 } 506 507 SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size) { 508 sslSocket *ss; 509 510 ss = ssl_FindSocket(fd); 511 if (!ss) { 512 return SECFailure; 513 } 514 515 /* This only works when resuming. */ 516 if (!ss->statelessResume) { 517 PORT_SetError(SEC_INTERNAL_ONLY); 518 return SECFailure; 519 } 520 521 /* Modifying both specs allows this to be used on either peer. */ 522 ssl_GetSpecWriteLock(ss); 523 ss->ssl3.crSpec->earlyDataRemaining = size; 524 ss->ssl3.cwSpec->earlyDataRemaining = size; 525 ssl_ReleaseSpecWriteLock(ss); 526 527 return SECSuccess; 528 } 529 530 SECStatus SSLInt_HasPendingHandshakeData(PRFileDesc *fd, PRBool *pending) { 531 sslSocket *ss = ssl_FindSocket(fd); 532 if (!ss) { 533 return SECFailure; 534 } 535 536 ssl_GetSSL3HandshakeLock(ss); 537 *pending = ss->ssl3.hs.msg_body.len > 0; 538 ssl_ReleaseSSL3HandshakeLock(ss); 539 return SECSuccess; 540 } 541 542 SECStatus SSLInt_SetRawEchConfigForRetry(PRFileDesc *fd, const uint8_t *buf, 543 size_t len) { 544 sslSocket *ss = ssl_FindSocket(fd); 545 if (!ss) { 546 return SECFailure; 547 } 548 549 sslEchConfig *cfg = (sslEchConfig *)PR_LIST_HEAD(&ss->echConfigs); 550 SECITEM_FreeItem(&cfg->raw, PR_FALSE); 551 SECITEM_AllocItem(NULL, &cfg->raw, len); 552 PORT_Memcpy(cfg->raw.data, buf, len); 553 return SECSuccess; 554 } 555 556 PRBool SSLInt_IsIp(PRUint8 *s, unsigned int len) { return tls13_IsIp(s, len); } 557 558 SECStatus SSLInt_GetCertificateCompressionAlgorithm( 559 PRFileDesc *fd, SSLCertificateCompressionAlgorithm *alg) { 560 sslSocket *ss = ssl_FindSocket(fd); 561 if (!ss) { 562 return SECFailure; /* Code already set. */ 563 } 564 565 PRBool algFound = PR_FALSE; 566 567 if (!ssl_HaveXmitBufLock(ss)) { 568 ssl_GetSSL3HandshakeLock(ss); 569 } 570 571 if (!ss->xtnData.compressionAlg) { 572 if (!ssl_HaveXmitBufLock(ss)) { 573 ssl_ReleaseSSL3HandshakeLock(ss); 574 } 575 576 PORT_SetError(SEC_ERROR_INVALID_ARGS); 577 return SECFailure; 578 } 579 for (int i = 0; i < ss->ssl3.supportedCertCompressionAlgorithmsCount; i++) { 580 if (ss->ssl3.supportedCertCompressionAlgorithms[i].id == 581 ss->xtnData.compressionAlg) { 582 *alg = ss->ssl3.supportedCertCompressionAlgorithms[i]; 583 algFound = PR_TRUE; 584 break; 585 } 586 } 587 588 if (!ssl_HaveXmitBufLock(ss)) { 589 ssl_ReleaseSSL3HandshakeLock(ss); 590 } 591 592 if (algFound) { 593 return SECSuccess; 594 } 595 return SECFailure; 596 }