From 162eb847394cb4192058429792470da8546ee93b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Thu, 18 Dec 2014 16:41:33 +0100 Subject: [PATCH] add: Implement record parsing --- src/record.cpp | 112 +++++++++++++++++++++++++++++++++++++++++++++++++ src/record.h | 93 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 src/record.cpp create mode 100644 src/record.h diff --git a/src/record.cpp b/src/record.cpp new file mode 100644 index 0000000..5993b60 --- /dev/null +++ b/src/record.cpp @@ -0,0 +1,112 @@ +#include "record.h" + +#include +#include +#include +#include + +#include "bios.h" +#include "opensslBIO.h" + +std::string toHexAndChecksum( const std::string& src ) { + char checksum = 0; + std::stringstream ss; + ss << ':' << std::hex << std::setfill( '0' ) << std::uppercase; + + for( auto c : src ) { + ss << std::setw( 2 ) << ( ( ( uint32_t ) c ) & 0xFF ); + checksum += c; + } + + ss << std::setw( 2 ) << ( ( ( uint32_t )( ~checksum ) ) & 0xFF ); + ss << '\n'; + return ss.str(); +} + +void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr bio ) { + head.payloadLength = data.size(); + std::string s; + s += head.packToString(); + s += data; + + std::string res = toHexAndChecksum( s ); + bio->write( res.data(), res.size() ); +} + +int32_t fromHexDigit( char c ) { + int32_t res = -1; + + if( c >= '0' && c <= '9' ) { + res = c - '0'; + } + + if( c >= 'A' && c <= 'F' ) { + res = c - 'A' + 10; + } + + return res; +} + +std::string parseCommand( RecordHeader& head, const std::string& input ) { + int32_t dlen = ( input.size() - 2 ) / 2; + char checksum = 0; + bool error = false; + + std::string str( std::max( dlen, RECORD_HEADER_SIZE ), 0 ); + str.append( 0, dlen ); + + for( int i = 0; i < dlen; i++ ) { + int32_t digit; + int32_t accum; + digit = fromHexDigit( input[i * 2 + 1] ); + error |= digit == -1; + accum = digit; + accum <<= 4; + digit = fromHexDigit( input[i * 2 + 2] ); + error |= digit == -1; + accum += digit; + str[i] = accum; + checksum += str[i]; + } + + head.unpackFromString( str.substr( 0, RECORD_HEADER_SIZE ) ); + uint32_t len = head.payloadLength; + uint32_t expectedTotalLength = ( RECORD_HEADER_SIZE + len + 1 /*checksum*/ ) * 2 + 2; + std::string data = str.substr( RECORD_HEADER_SIZE, str.size() - RECORD_HEADER_SIZE ); + + if( checksum != -1 || expectedTotalLength != input.size() || error || dlen < RECORD_HEADER_SIZE ) { + throw "Error, invalid checksum"; + } + + data.pop_back(); + + return data; +} + +/* +int main( int argc, char* argv[] ) { + OpensslBIOWrapper *bio = new OpensslBIOWrapper(BIO_new_fd(0, 0)); + std::string data = "halloPayload"; + RecordHeader head; + head.command = 0x7; + head.flags = 1; + head.sessid = 13; + head.command_count = 0xA0B; + head.totalLength = 9; + sendCommand( head, data, std::shared_ptr(bio) ); + head.command = 0x8; + + try { + std::string c = parseCommand( head, ":0700010D0000000B0A0900000000000C0068616C6C6F5061796C6F6164E6\n" ); + + std::cout << "res: " << std::endl; + std::cout << head.payloadLength << std::endl; + std::cout << c << std::endl; + } catch( char const* c ) { + std::cout << "err: " << c << std::endl; + } + + + return 0; +} +*/ diff --git a/src/record.h b/src/record.h new file mode 100644 index 0000000..7b8f887 --- /dev/null +++ b/src/record.h @@ -0,0 +1,93 @@ +#pragma once + +#include + +#include +#include + +#include "bios.h" + +#define RECORD_HEADER_SIZE 17 + +class RecordHeader { +public: + enum class SignerCommand : uint16_t { + SET_CSR = 0x01, + SET_SPKAC = 0x02, + SET_SIGNATURE_TYPE = 0x10, + SET_PROFILE = 0x11, + ADD_SAN = 0x18, + ADD_AVA = 0x19, + ADD_PROOF_LINE = 0x40, + SIGN = 0x80, + LOG_SAVED = 0x81, + GET_TIMESTAMP = 0xC0, + GET_STATUS_REPORT = 0xD0 + }; + + enum class SignerResult : uint16_t { + SAVE_LOG = 0x80, + CERTIFICATE = 0x81 + }; + +public: + uint16_t command; + char flags; + uint32_t sessid; + uint16_t command_count; + uint32_t totalLength; + uint16_t offset; + uint16_t payloadLength; + + RecordHeader() : + command( 0 ), flags( 0 ), sessid( 0 ), command_count( 0 ), totalLength( 0 ), offset( 0 ), payloadLength( 0 ) { + } + + template + void append( std::string& str, T val ) { + str.append( ( char* ) &val, sizeof( T ) ); + } + + template + void read( std::string::iterator& it, T& val ) { + char* data = ( char* ) &val; + + for( int i = 0; i < sizeof( T ); i++ ) { + data[i] = *it; + it++; + } + } + + std::string packToString() { + std::string res; + res.reserve( RECORD_HEADER_SIZE ); + append( res, command ); + append( res, flags ); + append( res, sessid ); + append( res, command_count ); + append( res, totalLength ); + append( res, offset ); + append( res, payloadLength ); + return res; + } + + void unpackFromString( std::string str ) { + if( str.size() != RECORD_HEADER_SIZE ) { + throw "Invalid string length"; + } + + auto it = str.begin(); + read( it, command ); + read( it, flags ); + read( it, sessid ); + read( it, command_count ); + read( it, totalLength ); + read( it, offset ); + read( it, payloadLength ); + } + +}; + +std::string parseCommand( RecordHeader& head, const std::string& input ); + +void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr bio ); -- 2.39.5