SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) { sslSocket * ss; SSLChannelInfo inf; sslSessionID * sid; if (!info || len < sizeof inf.length) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo", SSL_GETPID(), fd)); return SECFailure; } memset(&inf, 0, sizeof inf); inf.length = PR_MIN(sizeof inf, len); if (ss->opt.useSecurity && ss->enoughFirstHsDone) { sid = ss->sec.ci.sid; inf.protocolVersion = ss->version; inf.authKeyBits = ss->sec.authKeyBits; inf.keaKeyBits = ss->sec.keaKeyBits; if (ss->version < SSL_LIBRARY_VERSION_3_0) { inf.cipherSuite = ss->sec.cipherType | 0xff00; inf.compressionMethod = ssl_compression_null; inf.compressionMethodName = "N/A"; } else if (ss->ssl3.initialized) { ssl_GetSpecReadLock(ss); inf.cipherSuite = ss->ssl3.hs.cipher_suite; inf.compressionMethod = ss->ssl3.cwSpec->compression_method; ssl_ReleaseSpecReadLock(ss); inf.compressionMethodName = ssl_GetCompressionMethodName(inf.compressionMethod); } if (sid) { inf.creationTime = sid->creationTime; inf.lastAccessTime = sid->lastAccessTime; inf.expirationTime = sid->expirationTime; if (ss->version < SSL_LIBRARY_VERSION_3_0) { inf.sessionIDLength = SSL2_SESSIONID_BYTES; memcpy(inf.sessionID, sid->u.ssl2.sessionID, SSL2_SESSIONID_BYTES); } else { unsigned int sidLen = sid->u.ssl3.sessionIDLength; sidLen = PR_MIN(sidLen, sizeof inf.sessionID); inf.sessionIDLength = sidLen; memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen); } } } memcpy(info, &inf, inf.length); return SECSuccess; }
SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra) { sslSocket *ss; sslSequenceNumber to; ss = ssl_FindSocket(fd); if (!ss) { return SECFailure; } ssl_GetSpecReadLock(ss); to = ss->ssl3.cwSpec->write_seq_num + DTLS_RECVD_RECORDS_WINDOW + extra; ssl_ReleaseSpecReadLock(ss); return SSLInt_AdvanceWriteSeqNum(fd, to & RECORD_SEQ_MAX); }
SECItem * SSL_GetNegotiatedHostInfo(PRFileDesc *fd) { SECItem *sniName = NULL; sslSocket *ss; char *name = NULL; ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo", SSL_GETPID(), fd)); return NULL; } if (ss->sec.isServer) { if (ss->version > SSL_LIBRARY_VERSION_3_0 && ss->ssl3.initialized) { /* TLS */ SECItem *crsName; ssl_GetSpecReadLock(ss); /*********************************/ crsName = &ss->ssl3.hs.srvVirtName; if (crsName->data) { sniName = SECITEM_DupItem(crsName); } ssl_ReleaseSpecReadLock(ss); /*----------------------------*/ } return sniName; } name = SSL_RevealURL(fd); if (name) { sniName = PORT_ZNew(SECItem); if (!sniName) { PORT_Free(name); return NULL; } sniName->data = (void *)name; sniName->len = PORT_Strlen(name); } return sniName; }
SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd, const char *label, unsigned int labelLen, PRBool hasContext, const unsigned char *context, unsigned int contextLen, unsigned char *out, unsigned int outLen) { sslSocket *ss; unsigned char *val = NULL; unsigned int valLen, i; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial", SSL_GETPID(), fd)); return SECFailure; } if (!label || !labelLen || !out || !outLen || (hasContext && (!context || !contextLen))) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { return tls13_Exporter(ss, ss->ssl3.hs.exporterSecret, label, labelLen, context, hasContext ? contextLen : 0, out, outLen); } if (hasContext && contextLen > MAX_CONTEXT_LEN) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } /* construct PRF arguments */ valLen = SSL3_RANDOM_LENGTH * 2; if (hasContext) { valLen += 2 /* PRUint16 length */ + contextLen; } val = PORT_Alloc(valLen); if (!val) { return SECFailure; } i = 0; PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH); i += SSL3_RANDOM_LENGTH; PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH); i += SSL3_RANDOM_LENGTH; if (hasContext) { val[i++] = contextLen >> 8; val[i++] = contextLen; PORT_Memcpy(val + i, context, contextLen); i += contextLen; } PORT_Assert(i == valLen); /* Allow TLS keying material to be exported sooner, when the master * secret is available and we have sent ChangeCipherSpec. */ ssl_GetSpecReadLock(ss); if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) { PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); rv = SECFailure; } else { rv = ssl3_TLSPRFWithMasterSecret(ss, ss->ssl3.cwSpec, label, labelLen, val, valLen, out, outLen); } ssl_ReleaseSpecReadLock(ss); PORT_ZFree(val, valLen); return rv; }
SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) { sslSocket *ss; SSLChannelInfo inf; sslSessionID *sid; /* Check if we can properly return the length of data written and that * we're not asked to return more information than we know how to provide. */ if (!info || len < sizeof inf.length || len > sizeof inf) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo", SSL_GETPID(), fd)); return SECFailure; } memset(&inf, 0, sizeof inf); inf.length = PR_MIN(sizeof inf, len); if (ss->opt.useSecurity && ss->enoughFirstHsDone) { sid = ss->sec.ci.sid; inf.protocolVersion = ss->version; inf.authKeyBits = ss->sec.authKeyBits; inf.keaKeyBits = ss->sec.keaKeyBits; if (ss->ssl3.initialized) { SSLCipherSuiteInfo cinfo; SECStatus rv; ssl_GetSpecReadLock(ss); /* XXX The cipher suite should be in the specs and this * function should get it from cwSpec rather than from the "hs". * See bug 275744 comment 69 and bug 766137. */ inf.cipherSuite = ss->ssl3.hs.cipher_suite; inf.compressionMethod = ss->ssl3.cwSpec->compression_method; ssl_ReleaseSpecReadLock(ss); inf.compressionMethodName = ssl_GetCompressionMethodName(inf.compressionMethod); /* Fill in the cipher details from the cipher suite. */ rv = SSL_GetCipherSuiteInfo(inf.cipherSuite, &cinfo, sizeof(cinfo)); if (rv != SECSuccess) { return SECFailure; /* Error code already set. */ } inf.symCipher = cinfo.symCipher; inf.macAlgorithm = cinfo.macAlgorithm; /* Get these fromm |ss->sec| because that is accurate * even with TLS 1.3 disaggregated cipher suites. */ inf.keaType = ss->sec.keaType; inf.keaGroup = ss->sec.keaGroup ? ss->sec.keaGroup->name : ssl_grp_none; inf.keaKeyBits = ss->sec.keaKeyBits; inf.authType = ss->sec.authType; inf.authKeyBits = ss->sec.authKeyBits; inf.signatureScheme = ss->sec.signatureScheme; } if (sid) { unsigned int sidLen; inf.creationTime = sid->creationTime; inf.lastAccessTime = sid->lastAccessTime; inf.expirationTime = sid->expirationTime; inf.extendedMasterSecretUsed = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 || sid->u.ssl3.keys.extendedMasterSecretUsed) ? PR_TRUE : PR_FALSE; inf.earlyDataAccepted = (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted || ss->ssl3.hs.zeroRttState == ssl_0rtt_done); sidLen = sid->u.ssl3.sessionIDLength; sidLen = PR_MIN(sidLen, sizeof inf.sessionID); inf.sessionIDLength = sidLen; memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen); } } memcpy(info, &inf, inf.length); return SECSuccess; }
SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) { sslSocket * ss; SSLChannelInfo inf; sslSessionID * sid; PRBool enoughFirstHsDone = PR_FALSE; if (!info || len < sizeof inf.length) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo", SSL_GETPID(), fd)); return SECFailure; } memset(&inf, 0, sizeof inf); inf.length = PR_MIN(sizeof inf, len); if (ss->firstHsDone) { enoughFirstHsDone = PR_TRUE; } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 && ssl3_CanFalseStart(ss)) { enoughFirstHsDone = PR_TRUE; } if (ss->opt.useSecurity && enoughFirstHsDone) { sid = ss->sec.ci.sid; inf.protocolVersion = ss->version; inf.authKeyBits = ss->sec.authKeyBits; inf.keaKeyBits = ss->sec.keaKeyBits; if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ inf.cipherSuite = ss->sec.cipherType | 0xff00; inf.compressionMethod = ssl_compression_null; inf.compressionMethodName = "N/A"; } else if (ss->ssl3.initialized) { /* SSL3 and TLS */ ssl_GetSpecReadLock(ss); /* XXX The cipher suite should be in the specs and this * function should get it from crSpec rather than from the "hs". * See bug 275744 comment 69. */ inf.cipherSuite = ss->ssl3.hs.cipher_suite; inf.compressionMethod = ss->ssl3.crSpec->compression_method; ssl_ReleaseSpecReadLock(ss); inf.compressionMethodName = ssl_GetCompressionMethodName(inf.compressionMethod); } if (sid) { inf.creationTime = sid->creationTime; inf.lastAccessTime = sid->lastAccessTime; inf.expirationTime = sid->expirationTime; if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ inf.sessionIDLength = SSL2_SESSIONID_BYTES; memcpy(inf.sessionID, sid->u.ssl2.sessionID, SSL2_SESSIONID_BYTES); } else { unsigned int sidLen = sid->u.ssl3.sessionIDLength; sidLen = PR_MIN(sidLen, sizeof inf.sessionID); inf.sessionIDLength = sidLen; memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen); } } } memcpy(info, &inf, inf.length); return SECSuccess; }
SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd, const char *label, unsigned int labelLen, PRBool hasContext, const unsigned char *context, unsigned int contextLen, unsigned char *out, unsigned int outLen) { sslSocket *ss; unsigned char *val = NULL; unsigned int valLen, i; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial", SSL_GETPID(), fd)); return SECFailure; } ssl_GetRecvBufLock(ss); ssl_GetSSL3HandshakeLock(ss); if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) { PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION); ssl_ReleaseSSL3HandshakeLock(ss); ssl_ReleaseRecvBufLock(ss); return SECFailure; } valLen = SSL3_RANDOM_LENGTH * 2; if (hasContext) { valLen += 2 + contextLen; } val = PORT_Alloc(valLen); if (!val) { ssl_ReleaseSSL3HandshakeLock(ss); ssl_ReleaseRecvBufLock(ss); return SECFailure; } i = 0; PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH); i += SSL3_RANDOM_LENGTH; PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH); i += SSL3_RANDOM_LENGTH; if (hasContext) { val[i++] = contextLen >> 8; val[i++] = contextLen; PORT_Memcpy(val + i, context, contextLen); i += contextLen; } PORT_Assert(i == valLen); ssl_GetSpecReadLock(ss); if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) { PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); rv = SECFailure; } else { rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.cwSpec, label, labelLen, val, valLen, out, outLen); } ssl_ReleaseSpecReadLock(ss); ssl_ReleaseSSL3HandshakeLock(ss); ssl_ReleaseRecvBufLock(ss); PORT_ZFree(val, valLen); return rv; }