int tcomp_udvm_createTempState(tcomp_udvm_t *udvm, uint16_t state_length, uint16_t state_address, uint16_t state_instruction, uint16_t minimum_access_length, uint16_t state_retention_priority, int end_msg) { /* * If the specified minimum_access_length does not lie between 6 and 20 inclusive, or if * the state_retention_priority is 65535 then the END-MESSAGE * instruction fails to make a state creation request of its own * (however decompression failure does not occur and the state creation * requests made by the STATE-CREATE instruction are still valid). */ int is_ok = ( (6<=minimum_access_length && minimum_access_length<=20) && state_retention_priority!=65535 ); // if not ok and not END_MESSAGE --> decompression failure MUST occurs if(!is_ok) { if(end_msg) return 1; if(state_retention_priority == 65535) { tcomp_udvm_createNackInfo2(udvm, NACK_INVALID_STATE_PRIORITY); } else { tcomp_udvm_createNackInfo2(udvm, NACK_INVALID_STATE_ID_LENGTH); } return 0; } /* * decompression failure occurs if the END-MESSAGE instruction makes a state creation request and four * instances of the STATE-CREATE instruction have already been encountered. */ if(tcomp_result_getTempStatesToCreateSize(udvm->lpResult) >= MAX_TEMP_SATES) { tcomp_udvm_createNackInfo2(udvm, NACK_TOO_MANY_STATE_REQUESTS); return 0; } /* * Is there a state to create? */ if(is_ok) { // no byte copy () tcomp_state_t *lpState = tcomp_state_create(state_length, state_address, state_instruction, minimum_access_length, state_retention_priority); tcomp_result_addTempStateToCreate(udvm->lpResult, lpState); } return 1; }
/**RFC3320-Setction_8.4. Byte copying From EXTERNAL to UDVM */ int tcomp_udvm_bytecopy_to(tcomp_udvm_t *udvm, uint32_t destination, const uint8_t* source, uint32_t tsk_size_tocopy) { uint32_t byte_copy_left, byte_copy_right; if(destination == TCOMP_UDVM_GET_SIZE()) { /* SEGFAULT */ tcomp_udvm_createNackInfo2(udvm, NACK_SEGFAULT); return 0; } /* * The string of bytes is copied in ascending order of memory address, * respecting the bounds set by byte_copy_left and byte_copy_right. */ byte_copy_left = TCOMP_UDVM_GET_2BYTES_VAL(TCOMP_UDVM_HEADER_BYTE_COPY_LEFT_INDEX); byte_copy_right = TCOMP_UDVM_GET_2BYTES_VAL(TCOMP_UDVM_HEADER_BYTE_COPY_RIGHT_INDEX); // string of bytes is copied one byte at a time while((tsk_size_tocopy--)) { *TCOMP_UDVM_GET_BUFFER_AT(destination++) = *(source++); destination = (destination == byte_copy_right)? byte_copy_left : destination; } return 1; }
/**RFC3320-Setction_8.4. Byte copying From UDVM to EXTERNAL */ int tcomp_udvm_bytecopy_from(tcomp_udvm_t *udvm, uint8_t* destination, uint32_t source, uint32_t tsk_size_tocopy) { uint32_t byte_copy_left, byte_copy_right; if(source >= TCOMP_UDVM_GET_SIZE()){ TSK_DEBUG_ERROR("SEGFAULT"); tcomp_udvm_createNackInfo2(udvm, NACK_SEGFAULT); return 0; } /* * The string of bytes is copied in ascending order of memory address, * respecting the bounds set by byte_copy_left and byte_copy_right. */ byte_copy_left = TCOMP_UDVM_GET_2BYTES_VAL(TCOMP_UDVM_HEADER_BYTE_COPY_LEFT_INDEX); byte_copy_right = TCOMP_UDVM_GET_2BYTES_VAL(TCOMP_UDVM_HEADER_BYTE_COPY_RIGHT_INDEX); // string of bytes is copied one byte at a time while((tsk_size_tocopy--)){ *(destination++) = *TCOMP_UDVM_GET_BUFFER_AT(source++); source = (source == byte_copy_right)? byte_copy_left : source; } return 1; }
/** reference ($)<br> <table> <tr><td>Bytecode</td> <td>Operand value</td> <td>Range</td></tr> <tr><td>0nnnnnnn</td> <td>memory[2 * N]</td> <td>0 - 65535</td></tr> <tr><td>10nnnnnn nnnnnnnn </td> <td>memory[2 * N]</td> <td>0 - 65535</td></tr> <tr><td>11000000 nnnnnnnn nnnnnnnn</td> <td>memory[N]</td> <td>0 - 65535</td></tr> </table> */ uint16_t tcomp_udvm_opget_reference_param(tcomp_udvm_t *udvm) { const uint8_t* memory_ptr = TCOMP_UDVM_GET_BUFFER_AT(udvm->executionPointer); uint16_t result = 0; switch( *memory_ptr & 0xc0) // 2 first bits { case 0x00: // 0nnnnnnn memory[2 * N] 0 - 65535 case 0x40: // 0nnnnnnn memory[2 * N] 0 - 65535 { uint8_t N = (*(memory_ptr) & 0x7f); // no effect first bit is already nil result = 2*N; udvm->executionPointer++; } break; case 0x80: // 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535 { uint16_t N = (TSK_BINARY_GET_2BYTES(memory_ptr) & 0x3fff); result = 2*N; udvm->executionPointer+=2; } break; case 0xc0: // 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 { uint16_t N = TSK_BINARY_GET_2BYTES(memory_ptr+1); result = N; udvm->executionPointer+=3; } break; default: { TSK_DEBUG_ERROR("Invalide opcode: %u", *memory_ptr); tcomp_udvm_createNackInfo2(udvm, NACK_INVALID_OPERAND); } break; } return result; }
/** literal (#)<br> <table> <tr> <td>Bytecode</td> <td>Operand value</td> <td>Range</td></tr> <tr> <td>0nnnnnnn</td> <td>N</td> <td>0 - 127</td></tr> <tr> <td>10nnnnnn nnnnnnnn</td> <td>N</td> <td>0 - 16383</td></tr> <tr> <td>11000000 nnnnnnnn nnnnnnnn</td> <td>N</td> <td>0 - 65535</td></tr> </table> */ uint16_t tcomp_udvm_opget_literal_param(tcomp_udvm_t *udvm) { uint16_t result = 0; const uint8_t* memory_ptr = TCOMP_UDVM_GET_BUFFER_AT(udvm->executionPointer); switch( *memory_ptr & 0xc0) // 2 first bits { case 0x00: // 0nnnnnnn N 0 - 127 case 0x40: // 0nnnnnnn N 0 - 127 { result = *(memory_ptr); udvm->executionPointer++; } break; case 0x80: // 10nnnnnn nnnnnnnn N 0 - 16383 { result = TSK_BINARY_GET_2BYTES(memory_ptr)&0x3fff; // All except 2 first bits udvm->executionPointer+=2; } break; case 0xc0: // 11000000 nnnnnnnn nnnnnnnn N 0 - 65535 { result = TSK_BINARY_GET_2BYTES((memory_ptr+1)); udvm->executionPointer+=3; } break; default: { TSK_DEBUG_ERROR("Invalide opcode: %u", *memory_ptr); tcomp_udvm_createNackInfo2(udvm, NACK_INVALID_OPERAND); } break; } return result; }
/**Executes the bytecode. */ static tsk_bool_t tcomp_udvm_runByteCode(tcomp_udvm_t *udvm) { uint16_t operand_1, operand_2, operand_3, operand_4, operand_5, operand_6, operand_7; tsk_bool_t excution_failed = tsk_false, end_message = tsk_false; if(!udvm->isOK) { TSK_DEBUG_ERROR("Cannot run()/execute() invalid bytecode"); return tsk_false; } // LOOP - EXCUTE all bytecode while( !excution_failed && !end_message ) { uint8_t udvm_instruction = * (TCOMP_UDVM_GET_BUFFER_AT(udvm->executionPointer)); udvm->last_memory_address_of_instruction = udvm->executionPointer; udvm->executionPointer++; /* Skip the 1-byte [INSTRUCTION]. */ switch(udvm_instruction) { case TCOMP_UDVM_INST__DECOMPRESSION_FAILURE: { TCOMP_UDVM_EXEC_INST__DECOMPRESSION_FAILURE(udvm); excution_failed = tsk_true; break; } case TCOMP_UDVM_INST__AND: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__AND(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__OR: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__OR(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__NOT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__NOT(udvm, operand_1); break; } case TCOMP_UDVM_INST__LSHIFT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__LSHIFT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__RSHIFT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__RSHIFT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__ADD: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__ADD(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__SUBTRACT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SUBTRACT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__MULTIPLY: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__MULTIPLY(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__DIVIDE: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__DIVIDE(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__REMAINDER: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__REMAINDER(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__SORT_ASCENDING: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SORT_ASCENDING(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__SORT_DESCENDING: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SORT_DESCENDING(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__SHA_1: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SHA_1(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__LOAD: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__LOAD(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__MULTILOAD: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_literal_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__MULTILOAD(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__PUSH: { excution_failed = !TCOMP_UDVM_EXEC_INST__PUSH2(udvm); break; } case TCOMP_UDVM_INST__POP: { excution_failed = !TCOMP_UDVM_EXEC_INST__POP2(udvm); break; } case TCOMP_UDVM_INST__COPY: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__COPY(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__COPY_LITERAL: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__COPY_LITERAL(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__COPY_OFFSET: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__COPY_OFFSET(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__MEMSET: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__MEMSET(udvm, operand_1, operand_2, operand_3, operand_4); break; } case TCOMP_UDVM_INST__JUMP: { excution_failed = !TCOMP_UDVM_EXEC_INST__JUMP2(udvm); break; } case TCOMP_UDVM_INST__COMPARE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); operand_4 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); operand_5 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__COMPARE(udvm, operand_1, operand_2, operand_3, operand_4, operand_5); break; } case TCOMP_UDVM_INST__CALL: { operand_1 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__CALL(udvm, operand_1); break; } case TCOMP_UDVM_INST__RETURN: { excution_failed = !TCOMP_UDVM_EXEC_INST__RETURN(udvm); break; } case TCOMP_UDVM_INST__SWITCH: { operand_1 = tcomp_udvm_opget_literal_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SWITCH(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__CRC: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__CRC(udvm, operand_1, operand_2, operand_3, operand_4); break; } case TCOMP_UDVM_INST__INPUT_BYTES: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__INPUT_BYTES(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__INPUT_BITS: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__INPUT_BITS(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__INPUT_HUFFMAN: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); operand_3 = tcomp_udvm_opget_literal_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__INPUT_HUFFMAN(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__STATE_ACCESS: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); operand_5 = tcomp_udvm_opget_multitype_param(udvm); operand_6 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__STATE_ACCESS(udvm, operand_1, operand_2, operand_3, operand_4, operand_5, operand_6); break; } case TCOMP_UDVM_INST__STATE_CREATE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); operand_5 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__STATE_CREATE(udvm, operand_1, operand_2, operand_3, operand_4, operand_5); break; } case TCOMP_UDVM_INST__STATE_FREE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__STATE_FREE(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__OUTPUT: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__OUTPUT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__END_MESSAGE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); operand_5 = tcomp_udvm_opget_multitype_param(udvm); operand_6 = tcomp_udvm_opget_multitype_param(udvm); operand_7 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__END_MESSAGE(udvm, operand_1, operand_2, operand_3, operand_4, operand_5, operand_6, operand_7); end_message = 1; break; } default: tcomp_udvm_createNackInfo2(udvm, NACK_INVALID_OPCODE); goto bail; } //TCOMP_UDVM_DEBUG_PRINT(200); } bail: udvm->lpResult->consumed_cycles = udvm->consumed_cycles; return (!excution_failed); }
//======================================================== // UDVM machine definition // static tsk_object_t* tcomp_udvm_ctor(tsk_object_t * self, va_list * app) { tcomp_udvm_t *udvm = self; if(udvm){ /* RFC 3320 - 7. SigComp Message Format */ udvm->sigCompMessage = va_arg(*app, tcomp_message_t *); udvm->stateHandler = va_arg(*app, tcomp_statehandler_t *); udvm->lpResult = va_arg(*app, tcomp_result_t *); udvm->isOK = tsk_true; udvm->maximum_UDVM_cycles = 0; /* RFC 3320 subclause 8.6 */ udvm->consumed_cycles = 0; udvm->memory = tcomp_buffer_create_null(); /* Alloc UDVM memory */ if(udvm->sigCompMessage->stream_based){ /* * If the transport is stream-based however, then a fixed-size input buffer is required to accommodate the stream, independently of the * size of each SigComp message. So, for simplicity, the UDVM memory size is set to (decompression_memory_size / 2). */ tcomp_buffer_allocBuff(udvm->memory, udvm->stateHandler->sigcomp_parameters->dmsValue/2); } else{ /* * If the transport is message-based then sufficient memory must be available * to buffer the entire SigComp message before it is passed to the UDVM. So if the message is n bytes long, then the UDVM memory size is set * to (decompression_memory_size - n), up to a maximum of 65536 bytes. */ tcomp_buffer_allocBuff(udvm->memory, (udvm->stateHandler->sigcomp_parameters->dmsValue-udvm->sigCompMessage->totalSize)); } /* * Has feedback with my state id? */ if(tcomp_buffer_getSize(udvm->sigCompMessage->ret_feedback_buffer)){ tsk_size_t size = tcomp_buffer_getSize(udvm->sigCompMessage->ret_feedback_buffer); tcomp_buffer_allocBuff(udvm->lpResult->ret_feedback, size); memcpy(tcomp_buffer_getBuffer(udvm->lpResult->ret_feedback), tcomp_buffer_getBuffer(udvm->sigCompMessage->ret_feedback_buffer), size); } /* * Has state? */ if(tcomp_buffer_getSize(udvm->sigCompMessage->stateId)){ /* Find the provided state */ tcomp_state_t* lpState = NULL; uint16_t match_count = tcomp_statehandler_findState(udvm->stateHandler, udvm->sigCompMessage->stateId, &lpState); if( (!match_count || match_count>1 || !lpState) || (lpState->minimum_access_length > tcomp_buffer_getSize(udvm->sigCompMessage->stateId)) || ((tsk_size_t)(lpState->address + lpState->length) > TCOMP_UDVM_GET_SIZE()) ) { tcomp_udvm_createNackInfo(udvm, NACK_STATE_NOT_FOUND, udvm->sigCompMessage->stateId, 0); udvm->isOK = tsk_false; return self; } //this->sigCompMessage->stateId.print();//FIXME /* * Copy bytecodes to UDVM memory */ if( (tsk_size_t)(lpState->address + lpState->length) >= TCOMP_UDVM_GET_SIZE() ){ tcomp_udvm_createNackInfo2(udvm, NACK_SEGFAULT); udvm->isOK = tsk_false; return self; } memcpy( TCOMP_UDVM_GET_BUFFER_AT(lpState->address), tcomp_buffer_getBuffer(lpState->value), tcomp_buffer_getSize(lpState->value) ); //RFC 3320 - 7.2. Accessing Stored State (Useful values) TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_PARTIAL_STATE_ID_LENGTH_INDEX, tcomp_buffer_getSize(udvm->sigCompMessage->stateId)); TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_STATE_LENGTH_INDEX, tcomp_buffer_getSize(lpState->value)); udvm->executionPointer = lpState->instruction; } else // DON'T HAVE STATE { /* * Copy bytecodes to UDVM memory */ tsk_size_t bytecodes_destination = udvm->sigCompMessage->bytecodes_destination; if( (bytecodes_destination + tcomp_buffer_getSize(udvm->sigCompMessage->uploaded_UDVM_buffer)) >= TCOMP_UDVM_GET_SIZE() ){ tcomp_udvm_createNackInfo2(udvm, NACK_BYTECODES_TOO_LARGE); udvm->isOK = tsk_false; return self; } memcpy( TCOMP_UDVM_GET_BUFFER_AT(bytecodes_destination), tcomp_buffer_getBuffer(udvm->sigCompMessage->uploaded_UDVM_buffer), tcomp_buffer_getSize(udvm->sigCompMessage->uploaded_UDVM_buffer)); // Set pointer indicating execution index udvm->executionPointer = bytecodes_destination; } /* RFC 3320-Section_8.6. UDVM Cycles /* * To ensure that a SigComp message cannot consume excessive processing * resources, SigComp limits the number of "UDVM cycles" allocated to * each message. The number of available UDVM cycles is initialized to * 1000 plus the number of bits in the SigComp header (as described in * Section 7); this sum is then multiplied by cycles_per_bit. */ /*maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit*///FIXME:header_size udvm->maximum_UDVM_cycles = ( (8 * udvm->sigCompMessage->header_size + 1000)* udvm->stateHandler->sigcomp_parameters->cpbValue ); // // RFC 3320 - 7.2. Useful values // TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_UDVM_MEMORY_SIZE_INDEX, TCOMP_UDVM_GET_SIZE()); TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_CYCLES_PER_BIT_INDEX, udvm->stateHandler->sigcomp_parameters->cpbValue); TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_SIGCOMP_VERSION_INDEX, udvm->stateHandler->sigcomp_parameters->SigComp_version); memset(TCOMP_UDVM_GET_BUFFER_AT(TCOMP_UDVM_HEADER_RESERVED_INDEX), 0, TCOMP_UDVM_HEADER_RESERVED_SIZE); } else{
/** multitype(%)<br> <table> <tr><td>Bytecode</td> <td>Operand value</td> <td>Range</td></tr> <tr><td>00nnnnnn</td> <td>N</td> <td>0 - 63</td></tr> <tr><td>01nnnnnn</td> <td>memory[2 * N]</td> <td>0 - 65535</td></tr> <tr><td>1000011n</td> <td>2 ^ (N + 6)</td> <td>64 , 128</td></tr> <tr><td>10001nnn</td> <td>2 ^ (N + 8)</td> <td>256 , ... , 32768</td></tr> <tr><td>111nnnnn</td> <td>N + 65504</td> <td>65504 - 65535</td></tr> <tr><td>1001nnnn nnnnnnnn</td> <td>N + 61440</td> <td>61440 - 65535</td></tr> <tr><td>101nnnnn nnnnnnnn</td> <td>N</td> <td>0 - 8191</td></tr> <tr><td>110nnnnn nnnnnnnn</td> <td>memory[N]</td> <td>0 - 65535</td></tr> <tr><td>10000000 nnnnnnnn nnnnnnnn</td> <td>N</td> <td>0 - 65535</td></tr> <tr><td>10000001 nnnnnnnn nnnnnnnn</td> <td>memory[N]</td> <td>0 - 65535</td></tr> </table> */ uint16_t tcomp_udvm_opget_multitype_param(tcomp_udvm_t *udvm) { const uint8_t* memory_ptr = TCOMP_UDVM_GET_BUFFER_AT(udvm->executionPointer); int8_t index = operand_multitype_indexes[*memory_ptr]; uint16_t result = 0; switch(index) { case 1: // 00nnnnnn N 0 - 63 { result = *(memory_ptr); udvm->executionPointer++; } break; case 2: // 01nnnnnn memory[2 * N] 0 - 65535 { uint8_t N = (*(memory_ptr) & 0x3f); result = TSK_BINARY_GET_2BYTES( TCOMP_UDVM_GET_BUFFER_AT(2*N) ); udvm->executionPointer++; } break; case 3: // 1000011n 2 ^ (N + 6) 64 , 128 { uint8_t N = (*(memory_ptr) & 0x01); result = (uint16_t)pow( (double)2, (N + 6) ); udvm->executionPointer++; } break; case 4: // 10001nnn 2 ^ (N + 8) 256 , ... , 32768 { uint8_t N = (*(memory_ptr) & 0x07); result = (uint16_t)pow( (double)2, (N + 8) ); udvm->executionPointer++; } break; case 5: // 111nnnnn N + 65504 65504 - 65535 { result = ((*(memory_ptr) & 0x1f) + 65504 ); udvm->executionPointer++; } break; case 6: // 1001nnnn nnnnnnnn N + 61440 61440 - 65535 { result = (TSK_BINARY_GET_2BYTES(memory_ptr) & 0x0fff) + 61440; udvm->executionPointer+=2; } break; case 7: // 101nnnnn nnnnnnnn N 0 - 8191 { result = (TSK_BINARY_GET_2BYTES(memory_ptr) & 0x1fff); udvm->executionPointer+=2; } break; case 8: // 110nnnnn nnnnnnnn memory[N] 0 - 65535 { uint16_t N = TSK_BINARY_GET_2BYTES(memory_ptr) & 0x1fff; result = TSK_BINARY_GET_2BYTES( TCOMP_UDVM_GET_BUFFER_AT(N) ); udvm->executionPointer+=2; } break; case 9: // 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 { result = TSK_BINARY_GET_2BYTES(memory_ptr+1); udvm->executionPointer+=3; } break; case 10: // 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 { uint16_t N = TSK_BINARY_GET_2BYTES(memory_ptr+1); result = TSK_BINARY_GET_2BYTES( TCOMP_UDVM_GET_BUFFER_AT(N) ); udvm->executionPointer+=3; } break; default: // -1 { TSK_DEBUG_ERROR("Invalide opcode: %u", *memory_ptr); tcomp_udvm_createNackInfo2(udvm, NACK_INVALID_OPERAND); } break; } return result; }