]> WPIA git - cassiopeia.git/commitdiff
add: Implement record parsing
authorFelix Dörre <felix@dogcraft.de>
Thu, 18 Dec 2014 15:41:33 +0000 (16:41 +0100)
committerBenny Baumann <BenBE@geshi.org>
Sat, 24 Jan 2015 16:39:44 +0000 (17:39 +0100)
src/record.cpp [new file with mode: 0644]
src/record.h [new file with mode: 0644]

diff --git a/src/record.cpp b/src/record.cpp
new file mode 100644 (file)
index 0000000..5993b60
--- /dev/null
@@ -0,0 +1,112 @@
+#include "record.h"
+
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <sstream>
+
+#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<OpensslBIO> 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<OpensslBIO>(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 (file)
index 0000000..7b8f887
--- /dev/null
@@ -0,0 +1,93 @@
+#pragma once
+
+#include <inttypes.h>
+
+#include <memory>
+#include <string>
+
+#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 <class T>
+    void append( std::string& str, T val ) {
+        str.append( ( char* ) &val, sizeof( T ) );
+    }
+
+    template <class T>
+    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<OpensslBIO> bio );