/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* vim: set ts=2 et sw=2 tw=80: *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. *//* This file contains functions for frobbing the internals of libssl */#include"libssl_internals.h"#include"nss.h"#include"pk11pub.h"#include"seccomon.h"SECStatusSSLInt_IncrementClientHandshakeVersion(PRFileDesc*fd){sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnSECFailure;}++ss->clientHelloVersion;returnSECSuccess;}/* Use this function to update the ClientRandom of a client's handshake state * after replacing its ClientHello message. We for example need to do this * when replacing an SSLv3 ClientHello with its SSLv2 equivalent. */SECStatusSSLInt_UpdateSSLv2ClientRandom(PRFileDesc*fd,uint8_t*rnd,size_trnd_len,uint8_t*msg,size_tmsg_len){sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnSECFailure;}SECStatusrv=ssl3_InitState(ss);if(rv!=SECSuccess){returnrv;}rv=ssl3_RestartHandshakeHashes(ss);if(rv!=SECSuccess){returnrv;}// Ensure we don't overrun hs.client_random.rnd_len=PR_MIN(SSL3_RANDOM_LENGTH,rnd_len);// Zero the client_random struct.PORT_Memset(&ss->ssl3.hs.client_random,0,SSL3_RANDOM_LENGTH);// Copy over the challenge bytes.size_toffset=SSL3_RANDOM_LENGTH-rnd_len;PORT_Memcpy(&ss->ssl3.hs.client_random.rand[offset],rnd,rnd_len);// Rehash the SSLv2 client hello message.returnssl3_UpdateHandshakeHashes(ss,msg,msg_len);}PRBoolSSLInt_ExtensionNegotiated(PRFileDesc*fd,PRUint16ext){sslSocket*ss=ssl_FindSocket(fd);return(PRBool)(ss&&ssl3_ExtensionNegotiated(ss,ext));}voidSSLInt_ClearSessionTicketKey(){ssl3_SessionTicketShutdown(NULL,NULL);NSS_UnregisterShutdown(ssl3_SessionTicketShutdown,NULL);}SECStatusSSLInt_SetMTU(PRFileDesc*fd,PRUint16mtu){sslSocket*ss=ssl_FindSocket(fd);if(ss){ss->ssl3.mtu=mtu;returnSECSuccess;}returnSECFailure;}PRInt32SSLInt_CountTls13CipherSpecs(PRFileDesc*fd){PRCList*cur_p;PRInt32ct=0;sslSocket*ss=ssl_FindSocket(fd);if(!ss){return-1;}for(cur_p=PR_NEXT_LINK(&ss->ssl3.hs.cipherSpecs);cur_p!=&ss->ssl3.hs.cipherSpecs;cur_p=PR_NEXT_LINK(cur_p)){++ct;}returnct;}voidSSLInt_PrintTls13CipherSpecs(PRFileDesc*fd){PRCList*cur_p;sslSocket*ss=ssl_FindSocket(fd);if(!ss){return;}fprintf(stderr,"Cipher specs\n");for(cur_p=PR_NEXT_LINK(&ss->ssl3.hs.cipherSpecs);cur_p!=&ss->ssl3.hs.cipherSpecs;cur_p=PR_NEXT_LINK(cur_p)){ssl3CipherSpec*spec=(ssl3CipherSpec*)cur_p;fprintf(stderr," %s\n",spec->phase);}}/* Force a timer expiry by backdating when the timer was started. * We could set the remaining time to 0 but then backoff would not * work properly if we decide to test it. */voidSSLInt_ForceTimerExpiry(PRFileDesc*fd){sslSocket*ss=ssl_FindSocket(fd);if(!ss){return;}if(!ss->ssl3.hs.rtTimerCb)return;ss->ssl3.hs.rtTimerStarted=PR_IntervalNow()-PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs+1);}#define CHECK_SECRET(secret) \ if (ss->ssl3.hs.secret) { \ fprintf(stderr, "%s != NULL\n", #secret); \ return PR_FALSE; \ }PRBoolSSLInt_CheckSecretsDestroyed(PRFileDesc*fd){sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnPR_FALSE;}CHECK_SECRET(currentSecret);CHECK_SECRET(resumptionMasterSecret);CHECK_SECRET(dheSecret);CHECK_SECRET(clientEarlyTrafficSecret);CHECK_SECRET(clientHsTrafficSecret);CHECK_SECRET(serverHsTrafficSecret);returnPR_TRUE;}PRBoolsslint_DamageTrafficSecret(PRFileDesc*fd,size_toffset){unsignedchardata[32]={0};PK11SymKey**keyPtr;PK11SlotInfo*slot=PK11_GetInternalSlot();SECItemkey_item={siBuffer,data,sizeof(data)};sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnPR_FALSE;}if(!slot){returnPR_FALSE;}keyPtr=(PK11SymKey**)((char*)&ss->ssl3.hs+offset);if(!*keyPtr){returnPR_FALSE;}PK11_FreeSymKey(*keyPtr);*keyPtr=PK11_ImportSymKey(slot,CKM_NSS_HKDF_SHA256,PK11_OriginUnwrap,CKA_DERIVE,&key_item,NULL);PK11_FreeSlot(slot);if(!*keyPtr){returnPR_FALSE;}returnPR_TRUE;}PRBoolSSLInt_DamageClientHsTrafficSecret(PRFileDesc*fd){returnsslint_DamageTrafficSecret(fd,offsetof(SSL3HandshakeState,clientHsTrafficSecret));}PRBoolSSLInt_DamageServerHsTrafficSecret(PRFileDesc*fd){returnsslint_DamageTrafficSecret(fd,offsetof(SSL3HandshakeState,serverHsTrafficSecret));}PRBoolSSLInt_DamageEarlyTrafficSecret(PRFileDesc*fd){returnsslint_DamageTrafficSecret(fd,offsetof(SSL3HandshakeState,clientEarlyTrafficSecret));}SECStatusSSLInt_Set0RttAlpn(PRFileDesc*fd,PRUint8*data,unsignedintlen){sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnSECFailure;}ss->xtnData.nextProtoState=SSL_NEXT_PROTO_EARLY_VALUE;if(ss->xtnData.nextProto.data){SECITEM_FreeItem(&ss->xtnData.nextProto,PR_FALSE);}if(!SECITEM_AllocItem(NULL,&ss->xtnData.nextProto,len))returnSECFailure;PORT_Memcpy(ss->xtnData.nextProto.data,data,len);returnSECSuccess;}PRBoolSSLInt_HasCertWithAuthType(PRFileDesc*fd,SSLAuthTypeauthType){sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnPR_FALSE;}return(PRBool)(!!ssl_FindServerCertByAuthType(ss,authType));}PRBoolSSLInt_SendAlert(PRFileDesc*fd,uint8_tlevel,uint8_ttype){sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnPR_FALSE;}SECStatusrv=SSL3_SendAlert(ss,level,type);if(rv!=SECSuccess)returnPR_FALSE;returnPR_TRUE;}PRBoolSSLInt_SendNewSessionTicket(PRFileDesc*fd){sslSocket*ss=ssl_FindSocket(fd);if(!ss){returnPR_FALSE;}ssl_GetSSL3HandshakeLock(ss);ssl_GetXmitBufLock(ss);SECStatusrv=tls13_SendNewSessionTicket(ss);if(rv==SECSuccess){rv=ssl3_FlushHandshake(ss,0);}ssl_ReleaseXmitBufLock(ss);ssl_ReleaseSSL3HandshakeLock(ss);returnrv==SECSuccess;}SECStatusSSLInt_AdvanceReadSeqNum(PRFileDesc*fd,PRUint64to){PRUint64epoch;sslSocket*ss;ssl3CipherSpec*spec;ss=ssl_FindSocket(fd);if(!ss){returnSECFailure;}if(to>=(1ULL<<48)){returnSECFailure;}ssl_GetSpecWriteLock(ss);spec=ss->ssl3.crSpec;epoch=spec->read_seq_num>>48;spec->read_seq_num=(epoch<<48)|to;/* For DTLS, we need to fix the record sequence number. For this, we can just * scrub the entire structure on the assumption that the new sequence number * is far enough past the last received sequence number. */if(to<=spec->recvdRecords.right+DTLS_RECVD_RECORDS_WINDOW){returnSECFailure;}dtls_RecordSetRecvd(&spec->recvdRecords,to);ssl_ReleaseSpecWriteLock(ss);returnSECSuccess;}SECStatusSSLInt_AdvanceWriteSeqNum(PRFileDesc*fd,PRUint64to){PRUint64epoch;sslSocket*ss;ss=ssl_FindSocket(fd);if(!ss){returnSECFailure;}if(to>=(1ULL<<48)){returnSECFailure;}ssl_GetSpecWriteLock(ss);epoch=ss->ssl3.cwSpec->write_seq_num>>48;ss->ssl3.cwSpec->write_seq_num=(epoch<<48)|to;ssl_ReleaseSpecWriteLock(ss);returnSECSuccess;}SECStatusSSLInt_AdvanceWriteSeqByAWindow(PRFileDesc*fd,PRInt32extra){sslSocket*ss;sslSequenceNumberto;ss=ssl_FindSocket(fd);if(!ss){returnSECFailure;}ssl_GetSpecReadLock(ss);to=ss->ssl3.cwSpec->write_seq_num+DTLS_RECVD_RECORDS_WINDOW+extra;ssl_ReleaseSpecReadLock(ss);returnSSLInt_AdvanceWriteSeqNum(fd,to&RECORD_SEQ_MAX);}SSLKEATypeSSLInt_GetKEAType(SSLNamedGroupgroup){constsslNamedGroupDef*groupDef=ssl_LookupNamedGroup(group);if(!groupDef)returnssl_kea_null;returngroupDef->keaType;}SECStatusSSLInt_SetCipherSpecChangeFunc(PRFileDesc*fd,sslCipherSpecChangedFuncfunc,void*arg){sslSocket*ss;ss=ssl_FindSocket(fd);if(!ss){returnSECFailure;}ss->ssl3.changedCipherSpecFunc=func;ss->ssl3.changedCipherSpecArg=arg;returnSECSuccess;}staticssl3KeyMaterial*GetKeyingMaterial(PRBoolisServer,ssl3CipherSpec*spec){returnisServer?&spec->server:&spec->client;}PK11SymKey*SSLInt_CipherSpecToKey(PRBoolisServer,ssl3CipherSpec*spec){returnGetKeyingMaterial(isServer,spec)->write_key;}SSLCipherAlgorithmSSLInt_CipherSpecToAlgorithm(PRBoolisServer,ssl3CipherSpec*spec){returnspec->cipher_def->calg;}unsignedchar*SSLInt_CipherSpecToIv(PRBoolisServer,ssl3CipherSpec*spec){returnGetKeyingMaterial(isServer,spec)->write_iv;}