yoncho`s blog

AUTOSAR IDS 본문

기술, 나의 공부를 공유합니다./[Vehicle] AUTOSAR

AUTOSAR IDS

욘초 2023. 6. 24. 13:53

공식 문서 : https://www.autosar.org/fileadmin/standards/R20-11/FO/AUTOSAR_PRS_IntrusionDetectionSystem.pdf

 

 

 

 

 

코드

AUTOSAR IDS Message Format 에 맞는 랜덤 IDS Message 생성 코드 autosar_random_messge.js

더보기
const crypto = require('crypto');

const QSEV_MAX_BYTE_SIZE = 2147549199; // 8(EVENT) + 8(TIMESTAMP) + 2,147,483,648(CONTEXT) + 65,535(SIGNATURE)
const RESERVED_BYTE = '00000000'; //reserved 1byte (8bit)
const RESERVED_BIT = '0';
const CONTEXT_SHORT_TYPE = 0;
const CONTEXT_LONG_TYPE = 1;

//EVENT FRAME (total : 8byte)
class event_frame{
    constructor(protocolVer, includeContextData, includeTimeStamp, includeSignature,idsAndSensorInstanceID, evenetDefinitionID, count, reserved)
    {
        this.protocolVer = protocolVer;                         //4bit
        //protocl header = 4bit (reserved:1bit, include context, timestamp, signature 1bit)
        this.protocolHeaderReserved = RESERVED_BIT;
        this.includeContextData = includeContextData;           //1bit
        this.includeTimeStamp = includeTimeStamp;               //1bit
        this.includeSignature = includeSignature;               //1bit
        
        this.idsAndSensorInstanceID = idsAndSensorInstanceID;   //16bit  
        
        this.evenetDefinitionID = evenetDefinitionID;           //16bit
        this.count = count;                                     //16bit
        this.reserved = reserved;                               //8bit
    }

    createBitData() {
        return `${this.protocolVer
                +this.protocolHeaderReserved
                +this.includeSignature
                +this.includeTimeStamp
                +this.includeContextData
                +this.idsAndSensorInstanceID
                +this.evenetDefinitionID
                +this.count
                +this.reserved}`;
    }
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------------

//TIME STAMP (total : 8byte) 
class time_stamp{
    constructor(source, nanoSeconds, seconds, oemTimeStamp)
    {
        this.source = source;             // [0 : AUTOSAR Standard CP - StbM - AP:ara::tsync | 1 : Auxiliary/OEM Specific timestamp]
        this.reserved = RESERVED_BIT;
        this.nanoSeconds = nanoSeconds;   //30bit
        this.seconds = seconds;           //32bit
        this.oemTimeStamp = oemTimeStamp; //63bit
    }

    createBitDataByAUTOSARTimeStamp() {
        return `${this.source
                +this.reserved
                +this.nanoSeconds
                +this.seconds}`;
    }

    createBitDataByOEMTimeStamp() {
        return `${this.source
                +this.oemTimeStamp}`;
    }
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------------

//CONTEXT DATA LONG (total : n byte [n = 5.. 2^31])
class context_data_long{
    constructor(context_length_format, context_data_length, context_data_3byte_length, context_data)
    {
        this.context_length_format = context_length_format;         //1bit
        this.context_data_length = context_data_length;             //7bit
        this.context_data_3byte_length = context_data_3byte_length; //3byte   
        this.context_data = context_data;                           //1byte ~ 2^31 - 4byte
    }

    createFrame() {
        return `${bitsToBytes(`${this.context_length_format
                    +this.context_data_length}`)
                    +this.context_data_3byte_length
                    +this.context_data}`;
    }
}

//CONTEXT DATA SHORT (total : n byte [n = 2.. 127])
class context_data_short{
    constructor(context_length_format, context_data_length, context_data)
    {
        this.context_length_format = context_length_format; //1bit
        this.context_data_length = context_data_length;     //7bit 
        this.context_data = context_data;                   //1byte ~ 126byte -> bit
    }

    createBitData() {
        return `${this.context_length_format
                +this.context_data_length
                +this.context_data}`;
    }
}

//CONTEXT DATA - BYTE INDEX '0' OF CONTEXT DATA LENGTH (total : 1 byte)
class context_data_length_encoding{
    constructor(length_format, context_data_length){
        this.length_format = length_format;                 //bit number 7   [ 0 : 7bit length info include data length code | 1 : 31bit length info include data length code ]
        this.context_data_length = context_data_length;     //bit number 6...0 
    }
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------------

//SIGNATURE (total : n byte [ n : 3.. 65535])
class signature{
    constructor(signature_length, signature_data){
        this.signature_length = signature_length;       //16bit
        this.signature_data = signature_data;           //1byte ~ 65,533byte -> bit
    }
    createBitData() {
        return `${this.signature_length
                +this.signature_data}`;
    }

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------------

function createEventFrame()
{
    //eventFrame
    const eventFrameData = new event_frame();
    eventFrameData.protocolVer = generateRandomBitString(4);
    eventFrameData.includeContextData = generateRandomBitString(1);
    eventFrameData.includeTimeStamp = generateRandomBitString(1);
    eventFrameData.includeSignature = generateRandomBitString(1); 
    eventFrameData.idsAndSensorInstanceID = generateRandomBitString(16);
    eventFrameData.evenetDefinitionID = generateRandomBitString(16);
    eventFrameData.count = generateRandomBitString(16);
    eventFrameData.reserved = RESERVED_BYTE; //reserved 8bit

    return eventFrameData;
}

function createTimeStamp()
{
    const timeStampData = new time_stamp();
    timeStampData.source = generateRandomBitString(1);
    if (timeStampData.source == '0') //AUTOSAR Standard
    {
        timeStampData.nanoSeconds = generateRandomBitString(30);
        timeStampData.seconds = generateRandomBitString(32);
        return timeStampData.createBitDataByAUTOSARTimeStamp();
    }else{                     //OEM
        timeStampData.oemTimeStamp = generateRandomBitString(63);
        return timeStampData.createBitDataByOEMTimeStamp();
    }
}

function createContextData(contextDataType)
{   
    const contextDataLength = new context_data_length_encoding();

    //only short
    if(contextDataType == CONTEXT_SHORT_TYPE)
    {
        contextDataLength.length_format = CONTEXT_SHORT_TYPE;
    }
    else
    {
        contextDataLength.length_format = generateRandomBitString(1);
    }
    

    if(contextDataLength.length_format == CONTEXT_SHORT_TYPE) // 0 : 7bit length info include data length code
    {
        const shortContextData = new context_data_short();
        shortContextData.context_length_format = contextDataLength.length_format; 
        shortContextData.context_data_length = generateRandomBitString(7);
        let byteLength = parseInt(bitsToBytes(`${'0'+shortContextData.context_data_length}`.toString()), 16) - 1;
        if (byteLength < 1) //최소 조건
        {
            byteLength = 1;
        }
        shortContextData.context_data = generateRandomBitString(byteLength * 8); 
        // crypto.randomBytes(byteLength).toString('hex'); //byte
        
        return shortContextData.createBitData();
    }else{ // 1 : 31bit length info include data length code ]
        const longContextData = new context_data_long();
        longContextData.context_length_format = contextDataLength.length_format;
        longContextData.context_data_length = generateRandomBitString(7);
        longContextData.context_data_3byte_length = crypto.randomBytes(3).toString('hex');
        let byteLengthString = `${bitsToBytes(`${'0'+longContextData.context_data_length}`)+longContextData.context_data_3byte_length}`;
        let byteLength = parseInt(byteLengthString, 16) - 4;
        
        if (byteLength < 1)
        {
            byteLength = 1;
        }
        console.log(byteLength);
        if (byteLength > 7)
        {
            longContextData.context_data = createLongContextData(byteLength);
        }
        else
        {
            longContextData.context_data = crypto.randomBytes(byteLength).toString('hex');
        }
        return longContextData.createFrame();
    }
}

function createSignature()
{
    const signatureData = new signature();
    signatureData.signature_length = generateRandomBitString(16);
    let byteLength = parseInt(bitsToBytes(signatureData.signature_length), 16) - 2; 
    signatureData.signature_data = generateRandomBitString(byteLength * 8); 
    return signatureData.createBitData();
}

function createAutosarIDSMessage(contextDataType)
{
    let IDSMessage;
    let eventFrame;
    let timeStamp;
    let contextData;
    let signature;

    //eventFrame
    eventFrame = createEventFrame();
    const eventFrameData = eventFrame.createBitData();
    console.log(`EVENT FRAME :  ${eventFrameData}  [length : ${eventFrameData.length / 8} byte]`);
    IDSMessage = eventFrameData;
    
    //timeStamp
    if(eventFrame.includeTimeStamp == '1')
    {
        timeStamp = createTimeStamp();
        console.log(`TIME STAMP :  ${timeStamp}  [length : ${timeStamp.length / 8} byte]`);
        IDSMessage += timeStamp;
    }

    //contextData
    if(eventFrame.includeContextData == '1')
    {
        contextData = createContextData(contextDataType); 
        console.log(`CONTEXT DATA :  ${contextData}  [length : ${contextData.length / 8} byte]`);
        IDSMessage += contextData;
    }

    //signature
    if(eventFrame.includeSignature == '1')
    {
        signature = createSignature();
        console.log('SIGNATURE : ', signature);
        IDSMessage += signature;
    }

    const contextType = contextDataType == '0'? 'SHORT ONLY':'SHORT OR LONG';
    // console.log("\nTOTAL :" ,IDSMessage);
    console.log(`TOTAL LENGTH : ${(IDSMessage.length / 8)} byte`);
    console.log(` - EVENT  FRAME LENGTH : ${(eventFrameData.length / 8)} byte`);
    if(eventFrame.includeTimeStamp == '1')
    {
        console.log(` - TIME   STAMP LENGTH : ${(timeStamp.length / 8)} byte`);
    }
    if(eventFrame.includeContextData == '1')
    {
        console.log(` - CONTEXT DATA LENGTH : ${(contextData.length) / 8} byte  | Data Type : ${contextType}`);
    }
    if(eventFrame.includeSignature == '1')
    {
        console.log(` - SIGNATURE    LENGTH : ${(signature.length / 8)} byte`);
    }
    
    return IDSMessage;
}

createAutosarIDSMessage(0);

//+ export module
module.exports = {
    createAutosarIDSMessage: createAutosarIDSMessage
}

//+ method
function generateRandomBitString(length)
{
    let createBitString = '';
    for(let i = 0; i < length; i++)
    {
        const randomDigit = Math.floor(Math.random() * 2); // 0 또는 1 중 랜덤한 값 생성
        createBitString += randomDigit;
    }
    return createBitString;
}

function bitsToBytes(bitString) {
    let length = bitString.length;
    const bytes = [];
  
    for (let i = 0; i < bitString.length; i += 8) {
      const byte = bitString.slice(i, i + 8);
      bytes.push(parseInt(byte, 2));
    }
  
    return Buffer.from(bytes).toString('hex');
}

function createLongContextData(byteLength)
{
    let longContextData = '';
    while(byteLength > 0)
    {
        let splitCount;
        if (byteLength > 7)
        {
            splitCount = 7;
            byteLength -= 7;
        }
        else
        {
            splitCount = byteLength;
            byteLength -= splitCount;
        }
         
        longContextData += generateHex(splitCount);
    }

    return longContextData;
}

function generateHex(length) {
    const characters = '0123456789abcdef';
    let hexString = '';
  
    for (let i = 0; i < length; i++) {
      const randomIndex = Math.floor(Math.random() * characters.length);
      hexString += characters[randomIndex];
    }
  
    return hexString;
}

단, Context long data의 경우 createFrame() 함수에서 return값이 byte type이다.
나머지 Event frame, Time stamp, Signature, Context_short는 bit string을 return한다.

Comments