26 #ifdef PREFER_ECC_SUITES
35 #if !defined( PREFER_ECC_SUITES )
48 #ifdef PREFER_ECC_SUITES
54 #if !defined( PREFER_ECC_SUITES )
115 assert(
isReadPtr( algoStringInfoPtrPtr, \
117 assert(
isWritePtr( noInfoEntries,
sizeof(
int ) ) );
119 *algoStringInfoPtrPtr = algoStringMapTbl;
166 GETALGO_FIRST_MATCH_WARN,
175 int noAlgoInfoEntries;
177 GETALGO_TYPE getAlgoType;
185 #define setAlgoIDInfo( algoIDInfo, algoStrInfo, algoStrInfoEntries, prefAlgo, getType ) \
187 memset( ( algoIDInfo ), 0, sizeof( ALGOID_INFO ) ); \
188 ( algoIDInfo )->algoInfo = ( algoStrInfo ); \
189 ( algoIDInfo )->noAlgoInfoEntries = ( algoStrInfoEntries ); \
190 ( algoIDInfo )->preferredAlgo = ( prefAlgo ); \
191 ( algoIDInfo )->getAlgoType = ( getType ); \
192 ( algoIDInfo )->allowECC = TRUE; \
202 int stringPos,
stringLen, substringLen, algoIndex = 999;
203 int iterationCount,
status;
207 assert(
isReadPtr( algoIDInfo->algoInfo, \
209 algoIDInfo->noAlgoInfoEntries ) );
211 ENSURES( ( algoIDInfo->getAlgoType == GETALGO_BEST_MATCH && \
213 ( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH ) ||
214 ( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH_WARN && \
216 algoIDInfo->preferredAlgo < CRYPT_ALGO_LAST_EXTERNAL ) ) );
222 status = stringLen = readUint32( stream );
226 status = sMemGetDataBlock( stream, &
string, stringLen );
228 status = sSkip( stream, stringLen );
233 "Invalid algorithm ID string" ) );
247 for( stringPos = 0, iterationCount = 0;
248 stringPos < stringLen && !foundMatch && \
250 stringPos += substringLen + 1, iterationCount++ )
255 int currentAlgoIndex;
258 for( substringLen = stringPos; \
259 substringLen < stringLen && stringPtr[ substringLen ] !=
','; \
261 substringLen -= stringPos;
273 for( currentAlgoIndex = 0;
274 currentAlgoIndex < algoIDInfo->noAlgoInfoEntries && \
275 algoIDInfo->algoInfo[ currentAlgoIndex ].name != NULL && \
279 if( substringLen == algoIDInfo->algoInfo[ currentAlgoIndex ].nameLen && \
280 !memcmp( algoIDInfo->algoInfo[ currentAlgoIndex ].name,
281 stringPtr + stringPos, substringLen ) )
283 matchedAlgoInfo = &algoIDInfo->algoInfo[ currentAlgoIndex ];
287 ENSURES( currentAlgoIndex < FAILSAFE_ITERATIONS_MED );
288 ENSURES( currentAlgoIndex < algoIDInfo->noAlgoInfoEntries );
289 if( matchedAlgoInfo == NULL )
294 if( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH_WARN )
295 algoIDInfo->prefAlgoMismatch =
TRUE;
324 !algoIDInfo->allowECC )
332 if( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH_WARN )
333 algoIDInfo->prefAlgoMismatch =
TRUE;
337 switch( algoIDInfo->getAlgoType )
339 case GETALGO_BEST_MATCH:
343 if( currentAlgoIndex < algoIndex )
345 algoIndex = currentAlgoIndex;
351 case GETALGO_FIRST_MATCH:
355 algoIDInfo->preferredAlgo == matchedAlgoInfo->
algo )
357 algoIndex = currentAlgoIndex;
362 case GETALGO_FIRST_MATCH_WARN:
365 if( algoIDInfo->preferredAlgo != matchedAlgoInfo->
algo )
369 algoIDInfo->prefAlgoMismatch =
TRUE;
371 algoIndex = currentAlgoIndex;
379 ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
382 char algoString[ 256 + 8 ];
383 const int algoStringLen =
min( stringLen, \
388 if( algoStringLen > 0 )
389 memcpy( algoString,
string, algoStringLen );
392 "No algorithm compatible with the remote system's "
393 "selection was found: '%s'",
394 sanitiseString( algoString, 256, stringLen ) ) );
398 algoIDInfo->algo = algoIDInfo->algoInfo[ algoIndex ].algo;
406 IN_RANGE( 1, 100 )
const int noAlgoStringEntries,
416 noAlgoStringEntries ) );
419 REQUIRES( noAlgoStringEntries > 0 && noAlgoStringEntries <= 100 );
424 setAlgoIDInfo( &algoIDInfo, algoInfo, noAlgoStringEntries,
426 GETALGO_BEST_MATCH );
427 status = readAlgoStringEx( stream, &algoIDInfo, errorInfo );
429 *algo = algoIDInfo.algo;
441 static
int readAlgoStringPair(
INOUT STREAM *stream,
444 IN_RANGE( 1, 100 )
const int noAlgoStringEntries,
447 const BOOLEAN allowAsymmetricAlgos,
456 noAlgoStringEntries ) );
459 REQUIRES( noAlgoStringEntries > 0 && noAlgoStringEntries <= 100 );
465 setAlgoIDInfo( &algoIDInfo, algoInfo, noAlgoStringEntries,
467 GETALGO_BEST_MATCH );
468 status = readAlgoStringEx( stream, &algoIDInfo, errorInfo );
471 pairPreferredAlgo = algoIDInfo.algo;
478 setAlgoIDInfo( &algoIDInfo, algoInfo, noAlgoStringEntries,
479 pairPreferredAlgo, GETALGO_FIRST_MATCH );
480 status = readAlgoStringEx( stream, &algoIDInfo, errorInfo );
483 if( pairPreferredAlgo != algoIDInfo.algo && !allowAsymmetricAlgos )
487 "Client algorithm %d doesn't match server algorithm %d "
488 "in algorithm pair", pairPreferredAlgo,
491 *algo = algoIDInfo.algo;
510 algoStringMapTbl[ i ].algo != algo && \
515 return( writeString32( stream, algoStringMapTbl[ i ].
name,
516 algoStringMapTbl[ i ].
nameLen ) );
541 assert(
isWritePtr( keyexLength,
sizeof(
int ) ) );
570 sMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );
578 setAlgoIDInfo( &algoIDInfo, algoStringKeyexTbl,
592 algoIDInfo.allowECC =
FALSE;
596 setAlgoIDInfo( &algoIDInfo, algoStringKeyexTbl,
604 sMemDisconnect( &stream );
607 handshakeInfo->keyexAlgo = algoIDInfo.algo;
608 if( algoIDInfo.prefAlgoMismatch )
612 preferredAlgoMismatch =
TRUE;
632 handshakeInfo->isECDH =
TRUE;
639 setAlgoIDInfo( &algoIDInfo, handshakeInfo->algoStringPubkeyTbl,
640 handshakeInfo->algoStringPubkeyTblNoEntries,
641 handshakeInfo->pubkeyAlgo, GETALGO_FIRST_MATCH_WARN );
645 setAlgoIDInfo( &algoIDInfo, handshakeInfo->algoStringPubkeyTbl,
646 handshakeInfo->algoStringPubkeyTblNoEntries,
652 sMemDisconnect( &stream );
656 handshakeInfo->pubkeyAlgo = algoIDInfo.algo;
657 if( algoIDInfo.prefAlgoMismatch )
661 preferredAlgoMismatch =
TRUE;
665 status = readAlgoStringPair( &stream, algoStringEncrTbl,
668 &sessionInfoPtr->cryptAlgo, isServer,
FALSE,
672 status = readAlgoStringPair( &stream, algoStringMACTbl,
675 &sessionInfoPtr->integrityAlgo,
680 sMemDisconnect( &stream );
687 status = readAlgoStringPair( &stream, algoStringCoprTbl,
690 &dummyAlgo, isServer,
695 sMemDisconnect( &stream );
698 status = readUniversal32( &stream );
700 status = readUniversal32( &stream );
703 if( sgetc( &stream ) )
705 status = readUint32( &stream );
707 sMemDisconnect( &stream );
712 "Invalid hello packet language string/trailer data" ) );
720 const CRYPT_CONTEXT tempContext = handshakeInfo->iExchangeHashContext;
722 handshakeInfo->iExchangeHashContext = \
723 handshakeInfo->iExchangeHashAltContext;
724 handshakeInfo->iExchangeHashAltContext = tempContext;
729 if( guessedKeyex && preferredAlgoMismatch )
749 BYTE *bufPtr = sessionInfoPtr->receiveBuffer +
\
778 if( localPayloadLength <= 0 || \
779 localPayloadLength > sessionInfoPtr->receiveBufEnd - \
780 sessionInfoPtr->receiveBufPos )
784 "Invalid session control message payload length %d for "
785 "packet type %d", localPayloadLength,
792 sessionInfoPtr->receiveBufEnd ) );
793 sMemConnect( &stream, bufPtr, localPayloadLength );
794 status = processChannelControlMessage( sessionInfoPtr, &stream );
795 sMemDisconnect( &stream );
796 sessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos;
797 sessionInfoPtr->pendingPacketLength = 0;
808 SSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;
809 BYTE *bufPtr = sessionInfoPtr->receiveBuffer +
\
822 if( sessionInfoPtr->receiveBufPos >= \
823 sessionInfoPtr->receiveBufSize - 128 )
827 REQUIRES( sessionInfoPtr->receiveBufPos == sessionInfoPtr->receiveBufEnd );
829 &length, &extraLength, sshInfo,
836 return( ( status ==
OK_SPECIAL ) ? 0 : status );
839 length <= sessionInfoPtr->receiveBufSize - \
840 sessionInfoPtr->receiveBufPos );
841 status = checkMacSSHIncremental( sessionInfoPtr->iAuthInContext,
846 sessionInfoPtr->authBlocksize );
869 status = payloadLength = readUint32( &stream );
871 removedDataLength = stell( &stream );
873 payloadLength != length - ( removedDataLength + \
876 sMemDisconnect( &stream );
879 "Invalid data packet payload length %ld, should be "
881 length - ( removedDataLength + sshInfo->
padLength ) ) );
884 status = processChannelControlMessage( sessionInfoPtr, &stream );
885 sMemDisconnect( &stream );
898 memmove( bufPtr, bufPtr + removedDataLength,
903 sessionInfoPtr->pendingPacketLength =
\
905 ( length + extraLength ) - removedDataLength;
918 SSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;
919 BYTE *dataRemainingPtr = sessionInfoPtr->receiveBuffer +
\
922 const int dataRemainingSize = sessionInfoPtr->pendingPacketLength - \
923 sshInfo->partialPacketDataLength;
924 const int dataLength = dataRemainingSize - sessionInfoPtr->authBlocksize;
930 REQUIRES( dataRemainingSize >= sessionInfoPtr->authBlocksize && \
931 dataRemainingSize <= sessionInfoPtr->receiveBufEnd - \
932 ( sessionInfoPtr->receiveBufPos + \
934 REQUIRES( dataLength >= 0 && dataLength < dataRemainingSize );
961 status = checkMacSSHIncremental( sessionInfoPtr->iAuthInContext, 0,
962 dataRemainingPtr, dataRemainingSize,
964 sessionInfoPtr->authBlocksize );
968 status = checkMacSSHIncremental( sessionInfoPtr->iAuthInContext, 0,
969 dataRemainingPtr, dataRemainingSize,
971 sessionInfoPtr->authBlocksize );
977 "Bad message MAC for packet type %d, length %d",
983 payloadLength = sessionInfoPtr->pendingPacketLength - \
984 ( sshInfo->
padLength + sessionInfoPtr->authBlocksize );
986 ENSURES( payloadLength >= 0 && \
987 payloadLength < sessionInfoPtr->pendingPacketLength + dataLength );
992 sessionInfoPtr->receiveBufPos, payloadLength );
998 status = processControlMessage( sessionInfoPtr, readInfo,
1014 return( payloadLength );
1022 SSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;
1024 const int dataLength = sessionInfoPtr->sendBufPos - \
1031 REQUIRES( dataLength > 0 && dataLength < sessionInfoPtr->sendBufPos && \
1043 status = openPacketStreamSSHEx( &stream, sessionInfoPtr,
1048 writeUint32( &stream, getCurrentChannelNo( sessionInfoPtr, \
1050 status = writeUint32( &stream, dataLength );
1051 sMemDisconnect( &stream );
1053 sMemConnect( &stream, sessionInfoPtr->sendBuffer,
1054 sessionInfoPtr->sendBufSize );
1058 status = wrapPacketSSH2( sessionInfoPtr, &stream, 0,
FALSE,
FALSE );
1060 length = stell( &stream );
1061 sMemDisconnect( &stream );
1073 length2 = appendChannelData( sessionInfoPtr, length );
1101 status = openPacketStreamSSH( &stream, sessionInfoPtr,
1106 writeString32( &stream,
"Handshake failed", 16 );
1107 status = writeUint32( &stream, 0 );
1110 status = wrapPacketSSH2( sessionInfoPtr, &stream, 0,
1114 const int length = stell( &stream );
1120 status = sMemGetDataBlockAbs( &stream, 0, &dataPtr, length );
1122 ( void ) sendCloseNotification( sessionInfoPtr, dataPtr,
1125 sMemDisconnect( &stream );
1126 sNetDisconnect( &sessionInfoPtr->stream );
1135 ( void ) closeChannel( sessionInfoPtr,
TRUE );
1163 SESSION_NEEDS_KEYORPASSWORD | \
1164 SESSION_NEEDS_PRIVKEYSIGN,
1177 DEFAULT_PACKET_SIZE,
1179 SSH2_PAYLOAD_HEADER_SIZE,
1184 assert( ( handshakeInfo == NULL ) || \
1188 sessionInfoPtr->readHeaderFunction = readHeaderFunction;
1189 sessionInfoPtr->processBodyFunction = processBodyFunction;
1190 sessionInfoPtr->preparePacketFunction = preparePacketFunction;
1191 sessionInfoPtr->shutdownFunction = shutdownFunction;
1192 if( handshakeInfo != NULL )
1195 initSSH2serverProcessing( sessionInfoPtr, handshakeInfo );
1197 initSSH2clientProcessing( sessionInfoPtr, handshakeInfo );
1199 handshakeInfo->algoStringPubkeyTbl = algoStringPubkeyTbl;
1200 handshakeInfo->algoStringPubkeyTblNoEntries = \