示例#1
0
//=============================================================================
//  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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
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;
}