//============================================================================= // Helpers //============================================================================= static RPU8 findAndCapEncodedDataInBeacon ( RPU8 beaconData, RU32 maxSize ) { RPU8 pData = NULL; RPU8 end = NULL; OBFUSCATIONLIB_DECLARE( header, RP_HCP_CONFIG_DATA_HEADER ); OBFUSCATIONLIB_DECLARE( footer, RP_HCP_CONFIG_DATA_FOOTER ); if( NULL != beaconData ) { OBFUSCATIONLIB_TOGGLE( header ); OBFUSCATIONLIB_TOGGLE( footer ); if( ( sizeof( header ) + sizeof( footer ) + 1 ) < maxSize ) { pData = rpal_memory_memmem( beaconData, maxSize, (RPCHAR)header, sizeof(header) - sizeof(RCHAR) ); if( NULL != pData ) { pData += sizeof( header ) - sizeof( RCHAR ); end = rpal_memory_memmem( pData, maxSize - (RU32)( pData - beaconData - sizeof( header ) - sizeof( RCHAR ) ), footer, sizeof(footer) - sizeof(RCHAR) ); if( NULL != end ) { if( maxSize > (RU32)( end - beaconData ) ) { *end = 0; } else { pData = NULL; } } else { pData = NULL; } } } OBFUSCATIONLIB_TOGGLE( header ); OBFUSCATIONLIB_TOGGLE( footer ); } return pData; }
static RBOOL getStoreConf ( ) { RBOOL isSuccess = FALSE; RPU8 storeFile = NULL; RU32 storeFileSize = 0; rpHCPIdentStore* storeV2 = NULL; OBFUSCATIONLIB_DECLARE( store, RP_HCP_CONFIG_IDENT_STORE ); OBFUSCATIONLIB_TOGGLE( store ); if( rpal_file_read( (RPNCHAR)store, (RPVOID)&storeFile, &storeFileSize, FALSE ) ) { if( sizeof( rpHCPIdentStore ) <= storeFileSize ) { storeV2 = (rpHCPIdentStore*)storeFile; if( storeV2->enrollmentTokenSize == storeFileSize - sizeof( rpHCPIdentStore ) ) { isSuccess = TRUE; rpal_debug_info( "ident store found" ); if( NULL != ( g_hcpContext.enrollmentToken = rpal_memory_alloc( storeV2->enrollmentTokenSize ) ) ) { rpal_memory_memcpy( g_hcpContext.enrollmentToken, storeV2->enrollmentToken, storeV2->enrollmentTokenSize ); g_hcpContext.enrollmentTokenSize = storeV2->enrollmentTokenSize; } g_hcpContext.currentId = storeV2->agentId; } else { rpal_debug_warning( "inconsistent ident store, reseting" ); rpal_file_delete( (RPNCHAR)store, FALSE ); } } rpal_memory_free( storeFile ); } OBFUSCATIONLIB_TOGGLE( store ); // Set some always-correct defaults g_hcpContext.currentId.id.platformId = RP_HCP_ID_MAKE_PLATFORM( RP_HCP_PLATFORM_CURRENT_CPU, RP_HCP_PLATFORM_CURRENT_MAJOR, RP_HCP_PLATFORM_CURRENT_MINOR ); return isSuccess; }
static BOOL ctrlHandler ( DWORD type ) { OBFUSCATIONLIB_DECLARE( store, RP_HCP_CONFIG_CRASH_STORE ); UNREFERENCED_PARAMETER( type ); if( CTRL_SHUTDOWN_EVENT == type ) { // This is an emergency shutdown. // Trying to do this cleanly is pointless since Windows // will kill us very shortly, so let's just clean up // the CC so we don't report a pointless "crash". OBFUSCATIONLIB_TOGGLE( store ); rpal_file_delete( (RPWCHAR)store, FALSE ); OBFUSCATIONLIB_TOGGLE( store ); } // Pass the signal along return FALSE; }
RBOOL processMessage ( rSequence seq ) { RBOOL isSuccess = FALSE; RU8 command = 0; rSequence idSeq = NULL; rpHCPId tmpId = { 0 }; rpHCPId emptyId = { 0 }; RU64 tmpTime = 0; rThread hQuitThread = 0; rpHCPIdentStore identStore = {0}; RPU8 token = NULL; RU32 tokenSize = 0; OBFUSCATIONLIB_DECLARE( store, RP_HCP_CONFIG_IDENT_STORE ); if( NULL != seq ) { if( rSequence_getRU8( seq, RP_TAGS_OPERATION, &command ) ) { rpal_debug_info( "Received command 0x%0X.", command ); switch( command ) { case RP_HCP_COMMAND_LOAD_MODULE: isSuccess = loadModule( &g_hcpContext, seq ); break; case RP_HCP_COMMAND_UNLOAD_MODULE: isSuccess = unloadModule( &g_hcpContext, seq ); break; case RP_HCP_COMMAND_SET_HCP_ID: if( rSequence_getSEQUENCE( seq, RP_TAGS_HCP_IDENT, &idSeq ) ) { tmpId = seqToHcpId( idSeq ); if( 0 != rpal_memory_memcmp( &emptyId, &tmpId, sizeof( emptyId ) ) ) { g_hcpContext.currentId = tmpId; OBFUSCATIONLIB_TOGGLE( store ); if( rSequence_getBUFFER( seq, RP_TAGS_HCP_ENROLLMENT_TOKEN, &token, &tokenSize ) ) { identStore.agentId = tmpId; if( saveHcpId( (RPNCHAR)store, &identStore, token, tokenSize ) ) { isSuccess = TRUE; } if( NULL != g_hcpContext.enrollmentToken ) { rpal_memory_free( g_hcpContext.enrollmentToken ); g_hcpContext.enrollmentToken = NULL; } if( NULL != ( g_hcpContext.enrollmentToken = rpal_memory_alloc( tokenSize ) ) ) { rpal_memory_memcpy( g_hcpContext.enrollmentToken, token, tokenSize ); g_hcpContext.enrollmentTokenSize = tokenSize; isSuccess = TRUE; } } else { rpal_debug_warning( "hcp id is missing token" ); } OBFUSCATIONLIB_TOGGLE( store ); } } break; case RP_HCP_COMMAND_SET_GLOBAL_TIME: if( rSequence_getTIMESTAMP( seq, RP_TAGS_TIMESTAMP, &tmpTime ) ) { rpal_time_setGlobalOffset( tmpTime - rpal_time_getLocal() ); isSuccess = TRUE; } break; case RP_HCP_COMMAND_QUIT: if( 0 != ( hQuitThread = rpal_thread_new( thread_quitAndCleanup, NULL ) ) ) { rpal_thread_free( hQuitThread ); isSuccess = TRUE; } break; case RP_HCP_COMMAND_UPGRADE: isSuccess = upgradeHcp( seq ); break; default: break; } if( isSuccess ) { rpal_debug_info( "Command was successful." ); } else { rpal_debug_warning( "Command was not successful." ); } } } return isSuccess; }
RPRIVATE_TESTABLE RBOOL loadModule ( rpHCPContext* hcpContext, rSequence seq ) { RBOOL isSuccess = FALSE; RU32 moduleIndex = (RU32)(-1); RPU8 tmpBuff = NULL; RU32 tmpSize = 0; RPU8 tmpSig = NULL; RU32 tmpSigSize = 0; rpal_thread_func pEntry = NULL; rpHCPModuleContext* modContext = NULL; OBFUSCATIONLIB_DECLARE( entryName, RP_HCP_CONFIG_MODULE_ENTRY ); OBFUSCATIONLIB_DECLARE( recvMessage, RP_HCP_CONFIG_MODULE_RECV_MESSAGE ); if( NULL != seq && NULL != hcpContext ) { for( moduleIndex = 0; moduleIndex < RP_HCP_CONTEXT_MAX_MODULES; moduleIndex++ ) { if( 0 == hcpContext->modules[ moduleIndex ].hThread ) { // Found an empty spot break; } } } if( RP_HCP_CONTEXT_MAX_MODULES != moduleIndex && (RU32)(-1) != moduleIndex ) { // We got an empty spot for our module if( rSequence_getRU8( seq, RP_TAGS_HCP_MODULE_ID, &(hcpContext->modules[ moduleIndex ].id ) ) && rSequence_getBUFFER( seq, RP_TAGS_BINARY, &tmpBuff, &tmpSize ) && rSequence_getBUFFER( seq, RP_TAGS_SIGNATURE, &tmpSig, &tmpSigSize ) && CRYPTOLIB_SIGNATURE_SIZE == tmpSigSize ) { // We got the data, now verify the buffer signature if( CryptoLib_verify( tmpBuff, tmpSize, getRootPublicKey(), tmpSig ) ) { // Ready to load the module rpal_debug_info( "loading module in memory" ); hcpContext->modules[ moduleIndex ].hModule = MemoryLoadLibrary( tmpBuff, tmpSize ); if( NULL != hcpContext->modules[ moduleIndex ].hModule ) { OBFUSCATIONLIB_TOGGLE( entryName ); pEntry = (rpal_thread_func)MemoryGetProcAddress( hcpContext->modules[ moduleIndex ].hModule, (RPCHAR)entryName ); OBFUSCATIONLIB_TOGGLE( entryName ); if( NULL != pEntry ) { modContext = &(hcpContext->modules[ moduleIndex ].context); modContext->pCurrentId = &( hcpContext->currentId ); modContext->func_sendHome = doSend; modContext->isTimeToStop = rEvent_create( TRUE ); modContext->rpalContext = rpal_Context_get(); modContext->isOnlineEvent = hcpContext->isCloudOnline; if( NULL != modContext->isTimeToStop ) { hcpContext->modules[ moduleIndex ].isTimeToStop = modContext->isTimeToStop; OBFUSCATIONLIB_TOGGLE( recvMessage ); hcpContext->modules[ moduleIndex ].func_recvMessage = (rpHCPModuleMsgEntry)MemoryGetProcAddress( hcpContext->modules[ moduleIndex ].hModule, (RPCHAR)recvMessage ); OBFUSCATIONLIB_TOGGLE( recvMessage ); hcpContext->modules[ moduleIndex ].hThread = rpal_thread_new( pEntry, modContext ); if( 0 != hcpContext->modules[ moduleIndex ].hThread ) { CryptoLib_hash( tmpBuff, tmpSize, &(hcpContext->modules[ moduleIndex ].hash ) ); hcpContext->modules[ moduleIndex ].isOsLoaded = FALSE; isSuccess = TRUE; } else { rpal_debug_warning( "Error creating handler thread for new module." ); } } } else { rpal_debug_warning( "Could not find new module's entry point." ); } } else { rpal_debug_warning( "Error loading module in memory." ); } } else { rpal_debug_warning( "New module signature invalid." ); } } else { rpal_debug_warning( "Could not find core module components to load." ); } // Main cleanup if( !isSuccess ) { if( NULL != modContext ) { IF_VALID_DO( modContext->isTimeToStop, rEvent_free ); } if( NULL != hcpContext->modules[ moduleIndex ].hModule ) { MemoryFreeLibrary( hcpContext->modules[ moduleIndex ].hModule ); } rpal_memory_zero( &(hcpContext->modules[ moduleIndex ] ), sizeof( hcpContext->modules[ moduleIndex ] ) ); } } else { rpal_debug_error( "Could not find a spot for new module, or invalid module id!" ); } return isSuccess; }
RBOOL rpHostCommonPlatformLib_load ( RPNCHAR modulePath, RU32 moduleId ) { RBOOL isSuccess = FALSE; RU32 moduleIndex = 0; rpal_thread_func pEntry = NULL; rpHCPModuleContext* modContext = NULL; RPCHAR errorStr = NULL; OBFUSCATIONLIB_DECLARE( entrypoint, RP_HCP_CONFIG_MODULE_ENTRY ); OBFUSCATIONLIB_DECLARE( recvMessage, RP_HCP_CONFIG_MODULE_RECV_MESSAGE ); if( NULL != modulePath ) { for( moduleIndex = 0; moduleIndex < RP_HCP_CONTEXT_MAX_MODULES; moduleIndex++ ) { if( 0 == g_hcpContext.modules[ moduleIndex ].hThread ) { // Found an empty spot #ifdef RPAL_PLATFORM_WINDOWS g_hcpContext.modules[ moduleIndex ].hModule = LoadLibraryW( modulePath ); #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) g_hcpContext.modules[ moduleIndex ].hModule = dlopen( modulePath, RTLD_NOW | RTLD_LOCAL ); #endif if( NULL != g_hcpContext.modules[ moduleIndex ].hModule ) { OBFUSCATIONLIB_TOGGLE( entrypoint ); #ifdef RPAL_PLATFORM_WINDOWS pEntry = (rpal_thread_func)GetProcAddress( (HMODULE)g_hcpContext.modules[ moduleIndex ].hModule, (RPCHAR)entrypoint ); #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) pEntry = (rpal_thread_func)dlsym( g_hcpContext.modules[ moduleIndex ].hModule, (RPCHAR)entrypoint ); #endif OBFUSCATIONLIB_TOGGLE( entrypoint ); if( NULL != pEntry ) { modContext = &(g_hcpContext.modules[ moduleIndex ].context); modContext->pCurrentId = &(g_hcpContext.currentId); modContext->func_sendHome = doSend; modContext->isTimeToStop = rEvent_create( TRUE ); modContext->rpalContext = rpal_Context_get(); modContext->isOnlineEvent = g_hcpContext.isCloudOnline; if( NULL != modContext->isTimeToStop ) { g_hcpContext.modules[ moduleIndex ].id = (RpHcp_ModuleId)moduleId; g_hcpContext.modules[ moduleIndex ].isTimeToStop = modContext->isTimeToStop; OBFUSCATIONLIB_TOGGLE( recvMessage ); #ifdef RPAL_PLATFORM_WINDOWS g_hcpContext.modules[ moduleIndex ].func_recvMessage = (rpHCPModuleMsgEntry)GetProcAddress( (HMODULE)g_hcpContext.modules[ moduleIndex ].hModule, (RPCHAR)recvMessage ); #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) g_hcpContext.modules[ moduleIndex ].func_recvMessage = (rpHCPModuleMsgEntry)dlsym( g_hcpContext.modules[ moduleIndex ].hModule, (RPCHAR)recvMessage ); #endif OBFUSCATIONLIB_TOGGLE( recvMessage ); g_hcpContext.modules[ moduleIndex ].hThread = rpal_thread_new( pEntry, modContext ); if( 0 != g_hcpContext.modules[ moduleIndex ].hThread ) { g_hcpContext.modules[ moduleIndex ].isOsLoaded = TRUE; isSuccess = TRUE; rpal_debug_info( "module %S successfully loaded manually.", modulePath ); } } } else { #ifdef RPAL_PLATFORM_WINDOWS FreeLibrary( (HMODULE)g_hcpContext.modules[ moduleIndex ].hModule ); #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) dlclose( g_hcpContext.modules[ moduleIndex ].hModule ); #endif g_hcpContext.modules[ moduleIndex ].hModule = NULL; rpal_debug_error( "Could not manually finding the entry point to a module!" ); } } else { #if defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) errorStr = dlerror(); #endif rpal_debug_error( "Could not manually load module %S: %X %s", modulePath, rpal_error_getLast(), errorStr ); } break; } } } //forceCrash(); return isSuccess; }
RBOOL doBeacon ( RpHcp_ModuleId sourceModuleId, rList toSend, rList* pReceived ) { RBOOL isSuccess = FALSE; RPU8 receivedData = NULL; RU32 receivedSize = 0; RPU8 encodedData = NULL; RPU8 rawPayloadBuff = NULL; RU32 rawPayloadSize = 0; RU32 zError = 0; RPU8 signature = NULL; RPU8 payloadBuff = NULL; RU32 payloadSize = 0; RU8 sessionKey[ CRYPTOLIB_SYM_KEY_SIZE ] = {0}; RU8 sessionIv[ CRYPTOLIB_SYM_IV_SIZE ] = {0}; rString payloadToSend = NULL; RU32 decryptedSize = 0; RPU8 tmpBuff = NULL; RU64 tmpSize = 0; OBFUSCATIONLIB_DECLARE( url1, RP_HCP_CONFIG_HOME_URL_PRIMARY ); OBFUSCATIONLIB_DECLARE( url2, RP_HCP_CONFIG_HOME_URL_SECONDARY ); RPCHAR effectivePrimary = (RPCHAR)url1; RPCHAR effectiveSecondary = (RPCHAR)url2; rpal_debug_info( "called by module %d.", sourceModuleId ); // Pre-generate the session key and iv we want for the session CryptoLib_genRandomBytes( sessionKey, sizeof( sessionKey ) ); CryptoLib_genRandomBytes( sessionIv, sizeof( sessionIv ) ); // Assemble the stream to send payloadToSend = assembleOutboundStream( sourceModuleId, toSend, sessionKey, sessionIv ); if( NULL != payloadToSend ) { // Send the beacon if( NULL == g_hcpContext.primaryUrl ) { OBFUSCATIONLIB_TOGGLE( url1 ); OBFUSCATIONLIB_TOGGLE( url2 ); } else { effectivePrimary = g_hcpContext.primaryUrl; effectiveSecondary = g_hcpContext.secondaryUrl; } if( postHttp( effectivePrimary, rpal_stringbuffer_getString( payloadToSend ), FALSE, (RPVOID*)&receivedData, &receivedSize ) ) { isSuccess = TRUE; } else if( postHttp( effectiveSecondary, rpal_stringbuffer_getString( payloadToSend ), FALSE, (RPVOID*)&receivedData, &receivedSize ) ) { isSuccess = TRUE; rpal_debug_info( "beacon using secondary home." ); } else { rpal_debug_warning( "could not contact server." ); } if( NULL == g_hcpContext.primaryUrl ) { OBFUSCATIONLIB_TOGGLE( url1 ); OBFUSCATIONLIB_TOGGLE( url2 ); } if( isSuccess ) { isSuccess = FALSE; if( NULL != receivedData && 0 != receivedSize ) { if( NULL != pReceived ) { *pReceived = NULL; // Process the data received encodedData = findAndCapEncodedDataInBeacon( receivedData, receivedSize ); if( NULL != encodedData ) { if( stripBeaconEncoding( (RPCHAR)encodedData, &rawPayloadBuff, &rawPayloadSize ) ) { if( rawPayloadSize >= CRYPTOLIB_SIGNATURE_SIZE ) { // Verify signature signature = rawPayloadBuff; payloadBuff = signature + CRYPTOLIB_SIGNATURE_SIZE; payloadSize = rawPayloadSize - CRYPTOLIB_SIGNATURE_SIZE; if( verifyC2Signature( payloadBuff, payloadSize, signature ) ) { // Remove the symetric crypto using the session key if( CryptoLib_symDecrypt( payloadBuff, payloadSize, sessionKey, sessionIv, &decryptedSize ) ) { // Remove the compression tmpSize = rpal_ntoh32( *(RU32*)payloadBuff ); if( 0 != tmpSize && (-1) != tmpSize ) { tmpBuff = rpal_memory_alloc( (RSIZET)tmpSize ); if( rpal_memory_isValid( tmpBuff ) ) { if( Z_OK == ( zError = uncompress( tmpBuff, (uLongf*)&tmpSize, payloadBuff + sizeof( RU32 ), payloadSize - sizeof( RU32 ) ) ) ) { // Payload is valid, turn it into a sequence to return if( rList_deserialise( pReceived, tmpBuff, (RU32)tmpSize, NULL ) ) { rpal_debug_info( "success." ); isSuccess = TRUE; } else { rpal_debug_error( "could not deserialise list." ); } } else { rpal_debug_error( "could not decompress received data: %d (%d bytes).", zError, payloadSize ); } rpal_memory_free( tmpBuff ); } else { rpal_debug_error( "could not allocate memory for data received, asking for: %d.", tmpSize ); } } else { rpal_debug_error( "invalid size field in decrypted data." ); } } else { rpal_debug_error( "failed to decrypt received data." ); } } else { rpal_debug_error( "signature verification failed." ); } } else { rpal_debug_error( "stripped payload failed sanity check." ); } rpal_memory_free( rawPayloadBuff ); } else { rpal_debug_error( "could not strip BASE64 encoding." ); } } else { rpal_debug_error( "could not find the encoded data." ); } } else { rpal_debug_info( "not interested in the returned data." ); isSuccess = TRUE; } FREE_AND_NULL( receivedData ); receivedSize = 0; } else { rpal_debug_warning( "no data received from the server." ); isSuccess = FALSE; } } rpal_stringbuffer_free( payloadToSend ); } else { rpal_debug_error( "failed to generate payload for beacon." ); } return isSuccess; }
static rString assembleOutboundStream ( RpHcp_ModuleId moduleId, rList payload, RU8 sessionKey[ CRYPTOLIB_SYM_KEY_SIZE ], RU8 sessionIv[ CRYPTOLIB_SYM_IV_SIZE ] ) { rString str = NULL; rSequence hdrSeq = NULL; rSequence hcpid = NULL; rBlob blob = NULL; RPCHAR encoded = NULL; RPU8 encBuffer = NULL; RU64 encSize = 0; RPU8 finalBuffer = NULL; RU32 finalSize = 0; RPCHAR hostName = NULL; RBOOL isSuccess = FALSE; OBFUSCATIONLIB_DECLARE( payHdr, RP_HCP_CONFIG_PAYLOAD_HDR ); str = rpal_stringbuffer_new( 0, 0, FALSE ); if( NULL != str ) { if( NULL != ( hdrSeq = rSequence_new() ) ) { if( NULL != ( hcpid = hcpIdToSeq( g_hcpContext.currentId ) ) ) { // System basic information // Host Name if( NULL != ( hostName = libOs_getHostName() ) ) { rSequence_addSTRINGA( hdrSeq, RP_TAGS_HOST_NAME, hostName ); rpal_memory_free( hostName ); } else { rpal_debug_warning( "could not determine hostname" ); } // Internal IP rSequence_addIPV4( hdrSeq, RP_TAGS_IP_ADDRESS, libOs_getMainIp() ); if( rSequence_addSEQUENCE( hdrSeq, RP_TAGS_HCP_ID, hcpid ) && rSequence_addRU8( hdrSeq, RP_TAGS_HCP_MODULE_ID, moduleId ) && rSequence_addBUFFER( hdrSeq, RP_TAGS_SYM_KEY, sessionKey, CRYPTOLIB_SYM_KEY_SIZE ) && rSequence_addBUFFER( hdrSeq, RP_TAGS_SYM_IV, sessionIv, CRYPTOLIB_SYM_IV_SIZE ) ) { if( NULL != g_hcpContext.enrollmentToken && 0 != g_hcpContext.enrollmentTokenSize ) { rSequence_addBUFFER( hdrSeq, RP_TAGS_HCP_ENROLLMENT_TOKEN, g_hcpContext.enrollmentToken, g_hcpContext.enrollmentTokenSize ); } if( NULL != payload ) { blob = rpal_blob_create( 0, 0 ); } if( NULL == payload || NULL != blob ) { if( rSequence_serialise( hdrSeq, blob ) && ( NULL == payload || rList_serialise( payload, blob ) ) ) { encSize = compressBound( rpal_blob_getSize( blob ) ); encBuffer = rpal_memory_alloc( (RU32)encSize ); if( NULL == payload || NULL != encBuffer ) { if( NULL == payload || Z_OK == compress( encBuffer, (uLongf*)&encSize, (RPU8)rpal_blob_getBuffer( blob ), rpal_blob_getSize( blob ) ) ) { FREE_N_NULL( blob, rpal_blob_free ); if( NULL == payload || CryptoLib_fastAsymEncrypt( encBuffer, (RU32)encSize, getC2PublicKey(), &finalBuffer, &finalSize ) ) { FREE_N_NULL( encBuffer, rpal_memory_free ); if( NULL == payload || base64_encode( finalBuffer, finalSize, &encoded, TRUE ) ) { isSuccess = TRUE; if( NULL != payload ) { FREE_N_NULL( finalBuffer, rpal_memory_free ); DO_IFF( rpal_stringbuffer_add( str, "&" ), isSuccess ); OBFUSCATIONLIB_TOGGLE( payHdr ); DO_IFF( rpal_stringbuffer_add( str, (RPCHAR)payHdr ), isSuccess ); DO_IFF( rpal_stringbuffer_add( str, encoded ), isSuccess ); OBFUSCATIONLIB_TOGGLE( payHdr ); } IF_VALID_DO( encoded, rpal_memory_free ); } IF_VALID_DO( finalBuffer, rpal_memory_free ); } } IF_VALID_DO( encBuffer, rpal_memory_free ); } } IF_VALID_DO( blob, rpal_blob_free ); } } } rSequence_free( hdrSeq ); } if( !isSuccess ) { rpal_stringbuffer_free( str ); str = NULL; } } return str; }