├── .gitignore ├── .travis.yml ├── test.sh ├── bruteforce-crc.hpp ├── testmessage_1.bits ├── LICENSE_1_0.txt ├── ThreadPool.h ├── CMakeLists.txt ├── rewrite-as.pl ├── crc.hpp ├── generate-test-data.cc ├── bruteforce-crc.1 ├── README.md ├── crc.cc ├── tests ├── test_bruteforce.cc └── test_crc.cc ├── bruteforce-crc.cc ├── bf_crc.cc └── bf_crc.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles 3 | Makefile 4 | cmake_install.cmake 5 | bruteforce-crc 6 | generate-test-data 7 | *.swp 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - sudo apt-get update -qq 3 | - sudo apt-get install libboost-all-dev 4 | language: cpp 5 | compiler: 6 | - clang 7 | - gcc 8 | script: 9 | - cmake . && make 10 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./bruteforce-crc --verbose true --width 10 --start 0 --end 49 --offs-crc 49 --file testmessage_1.bits --probe-reflected-input true --probe-reflected-output true --probe-initial true --output testresult.csv --poly-start 100 --poly-end 200 4 | -------------------------------------------------------------------------------- /bruteforce-crc.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Brute-force a CRC. 3 | * 4 | * Original Author: Martin Schobert 5 | * Modified by MarytnP 6 | * 7 | * Copyright Martin Schobert and MartynP 2012 - 2016. 8 | * Distributed under the Boost Software License, Version 1.0. 9 | * (See accompanying file LICENSE_1_0.txt or copy at 10 | * http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | */ 13 | 14 | #ifndef _BRUTEFORCE_CRC_HPP_ 15 | #define _BRUTEFORCE_CRC_HPP_ 16 | 17 | #define VERSION_STR "0.3" 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /testmessage_1.bits: -------------------------------------------------------------------------------- 1 | 01101100100000111010000110001101011110000000001001111111010 2 | 00010000000011001011001001100110111111000001101000101000101 3 | 11010111001110001101101100101110111101101010010010011100111 4 | 01000000111000111100001001110100011011000100100110110100011 5 | 01101100000101110101100110010100111001011100001011100000001 6 | 01101010000001110101111011010010001100101001111101011001001 7 | 10001010111101100101000011100011111011100000110001000010010 8 | 01101110101110000111001001111101011101011110110101001111001 9 | 10011010011110000101100010000111011100001110010010101110000 10 | 11011101101010011010011100100111010100011100001100000110111 11 | -------------------------------------------------------------------------------- /LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /ThreadPool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * A thread pool implementation. 3 | * 4 | * Author: Martin Schobert 5 | * 6 | */ 7 | #ifndef __THREADPOOL_H__ 8 | #define __THREADPOOL_H__ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | template 18 | class ThreadPool { 19 | 20 | typedef std::tr1::shared_ptr thread_shptr; 21 | 22 | private: 23 | unsigned int max_n; 24 | 25 | std::list task_queue; 26 | std::list running; 27 | 28 | void spawn() { 29 | while(running.size() < max_n && task_queue.size() > 0 ) { 30 | FunctionType f(task_queue.front()); 31 | task_queue.pop_front(); 32 | 33 | boost::thread * p = new boost::thread(f); 34 | thread_shptr t = thread_shptr(p); 35 | running.push_back(t); 36 | } 37 | } 38 | 39 | public: 40 | 41 | ThreadPool(unsigned int n = 4) : max_n(n) { 42 | } 43 | 44 | ~ThreadPool() { 45 | wait(); 46 | } 47 | 48 | 49 | void add(FunctionType f) { 50 | task_queue.push_back(f); 51 | } 52 | 53 | void wait() { 54 | 55 | while(task_queue.size() > 0 || running.size() > 0) { 56 | 57 | spawn(); 58 | 59 | for(std::list::iterator iter = running.begin(); 60 | iter != running.end(); ++iter) { 61 | 62 | //std::cout << "timed wait\n"; 63 | if((*iter)->timed_join(boost::posix_time::millisec( 1000 ) )) { 64 | std::list::iterator i(iter); 65 | ++iter; 66 | running.erase(i); 67 | } 68 | 69 | } 70 | 71 | 72 | } 73 | 74 | } 75 | 76 | 77 | }; 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(BRUTEFORCE_CRC) 2 | cmake_minimum_required(VERSION 2.6) 3 | 4 | add_definitions(-Wall -O3 -ggdb) 5 | 6 | # enable compiler output: 7 | set(CMAKE_VERBOSE_MAKEFILE true) 8 | 9 | #Setup CMake to run tests 10 | enable_testing() 11 | 12 | # Boost 13 | find_package(PkgConfig) 14 | 15 | #set(Boost_USE_STATIC_LIBS ON) 16 | set(Boost_USE_MULTITHREADED ON) 17 | 18 | find_package(Boost REQUIRED COMPONENTS program_options system regex thread unit_test_framework filesystem) 19 | if(Boost_FOUND) 20 | include_directories(${Boost_INCLUDE_DIRS}) 21 | set(LIBS ${LIBS} ${Boost_LIBRARIES}) 22 | endif() 23 | 24 | include_directories(.) 25 | 26 | add_library(crc STATIC crc.cc) 27 | add_library(bf_crc STATIC bf_crc.cc) 28 | target_link_libraries(bf_crc ${LIBS} crc) 29 | set(LIBS ${LIBS} bf_crc) 30 | 31 | set(BRUTEFORCE_CRC_CMD bruteforce-crc.cc) 32 | add_executable(bruteforce-crc ${BRUTEFORCE_CRC_CMD}) 33 | target_link_libraries(bruteforce-crc ${LIBS}) 34 | 35 | set(GENERATE_TEST_DATA_CMD generate-test-data.cc) 36 | add_executable(generate-test-data ${GENERATE_TEST_DATA_CMD}) 37 | target_link_libraries(generate-test-data ${LIBS}) 38 | 39 | # To process brute forcer stolen from http://neyasystems.com/an-engineers-guide-to-unit-testing-cmake-and-boost-unit-tests/ 40 | file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} tests/*.cc) 41 | 42 | #Run through each source 43 | foreach(testSrc ${TEST_SRCS}) 44 | 45 | #Extract the filename without an extension (NAME_WE) 46 | get_filename_component(testName ${testSrc} NAME_WE) 47 | 48 | #Add compile target 49 | add_executable(${testName} ${testSrc}) 50 | 51 | #link to Boost libraries AND your targets and dependencies 52 | target_link_libraries(${testName} ${Boost_LIBRARIES} ${LIBS}) 53 | 54 | #I like to move testing binaries into a testBin directory 55 | set_target_properties(${testName} PROPERTIES 56 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin) 57 | 58 | #Finally add it to test execution - 59 | #Notice the WORKING_DIRECTORY and COMMAND 60 | add_test(NAME ${testName} 61 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin 62 | COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bin/${testName} ) 63 | 64 | endforeach(testSrc) 65 | 66 | 67 | INSTALL(FILES bruteforce-crc.1 DESTINATION man/man1) 68 | INSTALL(PROGRAMS bruteforce-crc DESTINATION bin) 69 | INSTALL(PROGRAMS rewrite-as.pl DESTINATION bin) 70 | -------------------------------------------------------------------------------- /rewrite-as.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Parse number-containing strings and rewrite them as either 4 | # hex or binary strings. 5 | # 6 | # Input format: 7 | # - bits, e.g.: 100100101 8 | # - hex, e.g.: 0xcafecafecafecafe or deadbeefdeadbeef 9 | # - hex, e.g.: 0x23, 0x5, 0x17 10 | # 11 | # Input data might contain spaces and comments (indicated by a hash mark '#') 12 | # 13 | # Output format: 14 | # - bits, e.g., 1010010101010 15 | # - hex, e.g.: ac1d 16 | # 17 | # 18 | # Author: Martin Schobert 19 | # 20 | 21 | use strict; 22 | use Data::Dumper; 23 | use POSIX; 24 | 25 | my $mode = shift; 26 | my $file = shift; 27 | my $verbose = 0; 28 | 29 | if(not defined($file) or not( -f $file)) { 30 | print "$0 [bits|hexbytes] \n"; 31 | exit(1); 32 | } 33 | 34 | # parse messages 35 | my $msg_list = rewrite_messages($file); 36 | 37 | 38 | foreach my $msg (@$msg_list) { 39 | 40 | if($mode eq 'bits') { 41 | print $msg, "\n"; 42 | } 43 | elsif($mode eq 'hexbytes') { 44 | print unpack("H*", pack("B*", $msg)), "\n"; 45 | } 46 | } 47 | 48 | sub line_to_bits { 49 | my $line = shift; 50 | 51 | # We cannot use the perl module Bit::Vector directly, 52 | # because we have to know the vector's length. Thus, 53 | # we have to preparse it by our own. 54 | 55 | $line =~ s!\s*!!g; 56 | 57 | # process comma seperated values, e.g.: 0x5, 0x23, 0x42 58 | if($line =~ m!\,!) { 59 | my $l = "0x"; 60 | foreach my $i (split(/\,/, $line)) { 61 | if($i =~ m!0x(.*)!) { 62 | $l .= sprintf("%02x", hex($1)); 63 | } 64 | else { 65 | die "Error: number [$i] in a value list [$line] is not in hex.\n"; 66 | } 67 | } 68 | $line = $l; 69 | print "parsing pre-transformed message: [$line]\n" if($verbose); 70 | } 71 | 72 | my $bits; 73 | 74 | # process binary string 75 | if($line =~ m!^[01]+$!) { 76 | $bits = $line; 77 | 78 | } 79 | # process hex strings possibly prefixed with 0x 80 | elsif($line =~ m!^(0x)?([\da-f]+)$!i) { 81 | my $h = $2; 82 | my $hlen = length($h); 83 | my $blen = $hlen * 4; 84 | $bits = unpack("B$blen", pack("H$hlen", $h)); #XXX 85 | } 86 | else { 87 | die "Error: Can't parse line [$line]\n"; 88 | } 89 | 90 | return $bits; 91 | 92 | } 93 | 94 | sub rewrite_messages { 95 | my $file = shift; 96 | my @messages; 97 | 98 | open(FILE, "< $file") or die "can't open file: $!\n"; 99 | 100 | while(defined(my $line = )) { 101 | chomp $line; 102 | print "parsing line in message file: [$line]\n" if($verbose); 103 | 104 | if($line =~ m!\s*\#!) { 105 | # ignore comments 106 | } 107 | elsif($line =~ m![^\s]!) { 108 | push @messages, line_to_bits($line); 109 | } 110 | } 111 | return \@messages; 112 | } 113 | -------------------------------------------------------------------------------- /crc.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified by MartynP 3 | * 4 | * The original header: 5 | * 6 | * This is a stripped-down and partially modified version of Boost's CRC library. 7 | * I extracted the crc_basic class and removed the template parameter, because I 8 | * want to specify the original template parameter at run-time. 9 | * 10 | * Martin Schobert 11 | * 12 | * The original header: 13 | * 14 | * Boost CRC library crc.hpp header file -----------------------------------// 15 | * 16 | * Copyright 2001, 2004 Daryle Walker. Use, modification, and distribution are 17 | * subject to the Boost Software License, Version 1.0. (See accompanying file 18 | * LICENSE_1_0.txt or a copy at .) 19 | * 20 | * See for the library's home page. 21 | * 22 | */ 23 | 24 | #ifndef CRC_HPP 25 | #define CRC_HPP 26 | 27 | #include 28 | 29 | #define MAX_VALUE(width) ((1 << width) - 1) 30 | 31 | 32 | // Simple cyclic redundancy code (CRC) class declaration -------------------// 33 | 34 | 35 | class my_crc_basic { 36 | 37 | 38 | public: 39 | 40 | // The FEED_TYPE deines how bits are fed into the CRC 41 | enum FEED_TYPE { 42 | AUTO = 0, 43 | LINEAR_FORWARD = 1, 44 | LINEAR_REVERSED = 2, 45 | BYTEWISE_REVERSED = 3 46 | 47 | }; 48 | 49 | typedef uint32_t value_type; 50 | 51 | // Constructor 52 | explicit my_crc_basic(unsigned int width, 53 | value_type truncated_polynominal = 0, 54 | value_type initial_remainder = 0, 55 | value_type final_xor_value = 0, 56 | bool reflect_input = false, 57 | bool reflect_remainder = false ); 58 | 59 | void set( value_type truncated_polynominal, 60 | value_type initial_remainder = 0, 61 | value_type final_xor_value = 0, 62 | bool reflect_input = false, 63 | bool reflect_remainder = false); 64 | 65 | void reset( value_type new_rem ); 66 | void process_bit( bool bit ); 67 | value_type checksum() const; 68 | 69 | bool calc_crc(value_type const use_initial, 70 | boost::dynamic_bitset<> const& msg, 71 | value_type const expected_crc, FEED_TYPE feed_type = AUTO); 72 | 73 | void calc_crc(value_type const use_initia, 74 | boost::dynamic_bitset<> const& msg); 75 | 76 | bool calc_crc(value_type const use_initial, 77 | uint8_t msg[], size_t msg_length, 78 | value_type const expected_crc); 79 | 80 | value_type reflect(value_type x ) const; 81 | 82 | private: 83 | // Member data 84 | unsigned int width_; 85 | value_type rem_; 86 | value_type poly_, init_, final_; // non-const to allow assignability 87 | bool rft_in_, rft_out_; // non-const to allow assignability 88 | 89 | uint32_t high_bit_mask;; 90 | uint32_t sig_bits; 91 | 92 | }; 93 | 94 | 95 | 96 | 97 | #endif 98 | 99 | 100 | -------------------------------------------------------------------------------- /generate-test-data.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Generate artifical telegrams and append a CRC. 3 | * 4 | * Author: Martin Schobert 5 | * 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "crc.hpp" 12 | 13 | namespace po = boost::program_options; 14 | 15 | typedef my_crc_basic crc_t; 16 | 17 | bool int_to_bool(int v) { 18 | return v == 0 ? false : true; 19 | } 20 | 21 | std::string bool_to_str(bool v) { 22 | return v ? "true" : "false"; 23 | } 24 | 25 | 26 | uint32_t random_value(uint32_t max_val, uint32_t min_val = 0) { 27 | return (rand() % ((max_val-min_val)+1)) + min_val; 28 | } 29 | 30 | bool random_bool() { 31 | return int_to_bool(random_value(1)); 32 | } 33 | 34 | int main(int argc, char *argv[]) { 35 | 36 | srand((unsigned)time(0)); 37 | 38 | size_t num_messages = 5; 39 | size_t width = random_value(16, 5); 40 | size_t start = random_value(0); 41 | size_t offs_crc = start + random_value(80, 30); 42 | size_t end = offs_crc; 43 | uint32_t poly = random_value(MAX_VALUE(width)); 44 | uint32_t init = random_value(MAX_VALUE(width)); 45 | uint32_t final_xor = width < 12 ? random_value(MAX_VALUE(width)) : 0; 46 | bool 47 | ref_in = random_bool(), 48 | ref_out = random_bool(); 49 | 50 | // definition of program options 51 | po::options_description desc("Allowed options"); 52 | desc.add_options() 53 | ("help", "produce help message") 54 | ("width", po::value(), "CRC width") 55 | ("messages", po::value(), "number of messages") 56 | ("final-xor", po::value(), "use value for the final XOR") 57 | ; 58 | 59 | // parse programm options 60 | po::variables_map vm; 61 | po::store(po::parse_command_line(argc, argv, desc), vm); 62 | po::notify(vm); 63 | 64 | 65 | if(vm.count("help")) { 66 | std::cout << desc << "\n"; 67 | return 1; 68 | } 69 | 70 | if(vm.count("width")) width = vm["width"].as(); 71 | if(vm.count("messages")) num_messages = vm["messages"].as(); 72 | if(vm.count("final-xor")) final_xor = vm["final-xor"].as(); 73 | 74 | // check parameters 75 | if(width > 16) { std::cout << "maximum value for width is: 16\n"; exit(1); } 76 | 77 | 78 | // print parameters 79 | std::cout << "# width : " << width << " bits\n" 80 | << "# CRC's offset : " << offs_crc << "\n" 81 | << "# calc CRC for bit offsets : " << start << " .. " << end << " (not included)\n" 82 | << "# final XOR : " << final_xor << "\n" 83 | << "# reflect in : " << bool_to_str(ref_in) << "\n" 84 | << "# reflect out : " << bool_to_str(ref_out) << "\n" 85 | << "# \n" 86 | << "# truncated polynom : " << poly << " (MSB not shown)\n" 87 | << "# initial value : " << init << "\n" 88 | << "\n"; 89 | 90 | crc_t crc(width, poly, init, final_xor, ref_in, ref_out); 91 | 92 | for(size_t num_msg = 0; num_msg < num_messages; num_msg++) { 93 | size_t i = 0; 94 | 95 | crc.reset(init); 96 | 97 | // the data bits 98 | for(i = start; i < end; i++) { 99 | int v = random_value(1); 100 | std::cout << v; 101 | crc.process_bit(int_to_bool(v)); 102 | } 103 | std::cout << " "; 104 | 105 | // write crc 106 | uint32_t cs = crc.checksum(); 107 | 108 | for(i = 0; i < width; i++) { 109 | uint32_t mask = 1 << (width-1 -i); 110 | int bit = (cs & mask) ? 1 : 0; 111 | std::cout << bit; 112 | } 113 | std::cout << "\n"; 114 | 115 | } 116 | 117 | return 0; 118 | } 119 | 120 | 121 | -------------------------------------------------------------------------------- /bruteforce-crc.1: -------------------------------------------------------------------------------- 1 | .TH bruteforce-crc 1 "April 7, 2017" "Version 0.3" 2 | .SH NAME 3 | bruteforce-crc \- Brute-forcing parameters of a Cycling Redundancy Check (CRC) 4 | .SH SYNOPSIS 5 | .B bruteforce-crc [options] 6 | .SH DESCRIPTION 7 | There are situations when you obtained a set of messages or commands, you can clearly identify the part that is likely a checksum and you want to derive the CRC algorithm, because you want to generate own messages with valid checksums or you want to ensure that received messages are valid. You can use bruteforce-crc to calculate the parameters of a CRC. 8 | .SH OPTIONS 9 | 10 | .IP "--help | -h" 11 | Show a summary of command line options. 12 | 13 | .IP "--version | -v" 14 | Show a version information. 15 | 16 | .IP "--file FILENAME" 17 | The input file that contains messages. The file is a text file with messages specified as sequences of zeros and ones. Each line represents a single message including the CRC. The sequence of zeros and ones must start at the beginning of a line and spaces are not allowed. Each message must have the same length. 18 | 19 | To transform input data to a proper format, you may use the helper script rewrite-as.pl. 20 | 21 | .IP "--output FILENAME" 22 | Log models to an output file. 23 | 24 | .IP "--verbose BOOL" 25 | Enable or disbale debug output. 26 | 27 | .IP --threads NUM 28 | Set the number of threads to bruteforce CRC parameters. Per default four threads are used. 29 | 30 | .IP "--width NUM" 31 | Specify the CRC width in bits, for example 16. The CRC width is the length of the truncated polynom. 32 | 33 | .IP "--offs-crc OFFSET" 34 | Specify the offset where the CRC starts. Since the input file contains bits instead of bytes, the offset should be given as a bit index. 35 | 36 | .IP "--start OFFSET" 37 | Specify the offset where the message starts. Usually the message will start at the beginning of each input file line. But you may want to alter this value, for example when your input file containts a sync sequence or message header bytes that are not part of the CRC calucaltion. 38 | 39 | .IP "--end OFFSET" 40 | Specify the offset where the message ends. 41 | 42 | .IP "--initial VALUE" 43 | A CRC register may be initialized with a certain value. 44 | 45 | .IP "--probe-initial BOOL" 46 | Bruteforce the intial value (default true). This option overrides --initial. 47 | 48 | .IP "--final-xor VALUE" 49 | Use a certain value als final XOR value. The default value is 0. 50 | 51 | .IP "--probe-final-xor BOOL" 52 | Bruteforce the final XOR value. It overrides a fixed final XOR value (--final-xor). Per default this option is false. 53 | 54 | .IP "--poly VALUE" 55 | Set a fixed (truncated) polymominal for the tests. If not specified, the polynomial is brute-forced. 56 | 57 | .IP "--probe-reflected-input BOOL" 58 | Probe for reflect input (default: false) 59 | 60 | .IP "--probe-reflected-output BOOL" 61 | Probe for reflect remainder output (default: false) 62 | 63 | .IP "--feed-type arg" 64 | Specify how message bits are feeded into the CRC. Possible value are: 65 | 66 | auto: This is the default. Bits are usually feed bit-wise from left to right into the CRC, except if input reflection is enabled. Then, the bits are feed byte-wise reversed and if messages are not byte-aligned, then the entire message is feed from right to left into the CRC. 67 | 68 | linear-forward: The entire message is feed bit-wise from left to right into the CRC. 69 | 70 | linear-reversed: The entire message is feed bit-wise from right to left into the CRC. 71 | 72 | bytewise-reversed: The bits from each byte were feed from LSB to MSB into the CRC register. That means the least significant bit is treated first and at the end, the most significant bit is processed. 73 | 74 | 75 | .SH AUTHOR 76 | Martin Schobert 77 | .SH SEE ALSO 78 | Project website: https://github.com/sitsec/bruteforce-crc 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | These files are part of a CRC parameter brute-forcing tool. Please have a look at 2 | http://sitsec.net/blog/2012/02/10/brute-forcing-crc-parameters/ 3 | 4 | Author: Martin Schobert 5 | 6 | Licence 7 | -------- 8 | 9 | This code is published under the Boost Software Licence. 10 | http://www.boost.org/users/license.html 11 | 12 | Dependencies 13 | ------------- 14 | 15 | - Cmake 16 | - Boost 17 | - boost\_program\_options 18 | - boost\_system 19 | - boost\_regex 20 | - boost\_thread 21 | 22 | $ sudo apt-get install cmake libboost-program-options-dev libboost-system-dev libboost-regex-dev \ 23 | libboost-thread-dev libboost-test-dev libboost-filesystem-dev 24 | 25 | Compile 26 | -------- 27 | 28 | \> cmake . 29 | 30 | Check for errors and install missing dependencies. 31 | 32 | \> make 33 | 34 | Build bruteforce-crc and ./bin/test* 35 | 36 | \> make test 37 | 38 | Run tests (can take a long time) 39 | 40 | 41 | Install 42 | ------- 43 | 44 | in general, you may use the bruteforcer from the directory where you compiled the code. If you like to install the bruteforcer into your system, you may run the 'install' target: 45 | 46 | \> sudo make install 47 | 48 | 49 | Run 50 | ---- 51 | 52 | Minimum input: 53 | 54 |
 55 | ./bruteforce-crc --file [filename] --width [crc-width] --offs-crc [offset to start of crc] --start [start of data] --end [end of data]
 56 | 
57 | 58 | Input file is an ASCII representation of a binary string, for example: 59 | 60 |
 61 | 01101100100000111010000110001101011110000000001001111111010
 62 | 00010000000011001011001001100110111111000001101000101000101
 63 | 11010111001110001101101100101110111101101010010010011100111
 64 | 
65 | 66 | If your input is hex-bytes, just use the Perl script "rewrite-as.pl" to convert your input into a format the bruteforcer expects, for example: 67 | 68 |
 69 | perl rewrite-as.pl bits test_hexbytes.txt > test_bitmsg.txt
 70 | 
71 | 72 | The brute-forcer expects simple newlines as line endings. If you have Windows text files ending in \r\n, you need to convert them. 73 | 74 | Back to the example, in this example the CRC is 10 bits long and starts at bit 49: 75 | 76 |
 77 | [--------------------data-----------------------][---CRC--]
 78 | 01101100100000111010000110001101011110000000001001111111010
 79 | 
80 | 81 | The command line for this example would be: 82 | 83 |
 84 | ./bruteforce-crc --verbose 1 --file data.txt --start 0 --end 49 --width 10 --offs-crc 49 --probe-initial true
 85 | 
 86 | Options List [* Required]:
 87 | 
 88 |   --file arg                   * File containing messages
 89 |   --width arg                  * CRC width
 90 |   --offs-crc arg               * CRC's offset
 91 |   --start arg                  * Calculate CRC from this offset
 92 |   --end arg                    * Calculate CRC up to this offset (not included)
 93 |   --output arg                 Output file for matched crc settings
 94 |   --verbose arg                Enable verbose output
 95 |   --poly arg                   Truncated polynomial (default: bruteforced)
 96 |   --poly-start arg             Start of polynomial search space (default: 0)
 97 |   --poly-end arg               End of polynomial search space (default (2^width - 1))
 98 |   --threads arg                Number of threads (default: 4)
 99 |   --initial arg                Set intial value (default: 0)
100 |   --probe-initial arg          Bruteforce the intial, overrides initial (default: true)
101 |   --final-xor arg              Final xor (default: 0)
102 |   --probe-final-xor arg        Bruteforce the final-xor, overrides final-xor (default: false)
103 |   --probe-reflected-input arg  Probe for reflect input (default: false)
104 |   --probe-reflected-output arg Probe for reflect remainder output (default: false)
105 | 
106 | 107 | 108 | Credits 109 | -------- 110 | 111 | * Martyn Pittuck (https://github.com/martynp) made a major rework of the code base and contributed a lot of code 112 | * Solomon Tan (https://github.com/solomonbstoner) fixed issues with reflection and improved example code generation -------------------------------------------------------------------------------- /crc.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include "crc.hpp" 6 | 7 | // Simple CRC class function definitions -----------------------------------// 8 | 9 | my_crc_basic::my_crc_basic( unsigned int width, 10 | my_crc_basic::value_type truncated_polynominal, 11 | my_crc_basic::value_type initial_remainder, // = 0 12 | my_crc_basic::value_type final_xor_value, // = 0 13 | bool reflect_input, // = false 14 | bool reflect_remainder // = false 15 | ) 16 | : width_(width), rem_( initial_remainder ), poly_( truncated_polynominal ) 17 | , init_( initial_remainder ), final_( final_xor_value ) 18 | , rft_in_( reflect_input ), rft_out_( reflect_remainder ) 19 | { 20 | high_bit_mask = 1ul << ( width - 1u ); 21 | sig_bits = (~( ~( 0ul ) << width )) ; 22 | 23 | } 24 | 25 | void my_crc_basic::set(my_crc_basic::value_type truncated_polynominal, 26 | my_crc_basic::value_type initial_remainder, // = 0 27 | my_crc_basic::value_type final_xor_value, // = 0 28 | bool reflect_input, // = false 29 | bool reflect_remainder // = false 30 | ) { 31 | rem_ = initial_remainder; 32 | poly_ = truncated_polynominal; 33 | init_ = initial_remainder; 34 | final_ = final_xor_value; 35 | rft_in_ = reflect_input; 36 | rft_out_ = reflect_remainder; 37 | } 38 | 39 | 40 | 41 | void my_crc_basic::reset(my_crc_basic::value_type new_rem) { 42 | rem_ = new_rem; 43 | } 44 | 45 | 46 | void my_crc_basic::process_bit (bool bit) { 47 | 48 | // compare the new bit with the remainder's highest 49 | rem_ ^= ( bit ? high_bit_mask : 0u ); 50 | 51 | // a full polynominal division step is done when the highest bit is one 52 | bool const do_poly_div = static_cast( rem_ & high_bit_mask ); 53 | 54 | // shift out the highest bit 55 | rem_ <<= 1; 56 | 57 | // carry out the division, if needed 58 | if ( do_poly_div ) rem_ ^= poly_; 59 | 60 | } 61 | 62 | 63 | my_crc_basic::value_type my_crc_basic::checksum() const { 64 | return ( (rft_out_ ? reflect( rem_ ) : rem_) 65 | ^ final_ ) & sig_bits; 66 | } 67 | 68 | 69 | void my_crc_basic::calc_crc(value_type const use_initial, 70 | boost::dynamic_bitset<> const & msg) { 71 | this->calc_crc(use_initial, msg, 0, AUTO); 72 | } 73 | 74 | bool my_crc_basic::calc_crc(value_type const use_initial, 75 | boost::dynamic_bitset<> const& msg, 76 | value_type const expected_crc, 77 | FEED_TYPE feed_type) { 78 | 79 | reset(use_initial); 80 | 81 | 82 | if(feed_type == AUTO) { 83 | if(rft_in_) { 84 | if (msg.size() % 8 != 0) feed_type = LINEAR_REVERSED; 85 | else feed_type = BYTEWISE_REVERSED; 86 | } 87 | else { 88 | feed_type = LINEAR_FORWARD; 89 | } 90 | } 91 | 92 | 93 | 94 | if(feed_type == LINEAR_FORWARD) { 95 | for (size_t i = 0; i < msg.size(); i++) { 96 | process_bit(msg[i]); 97 | } 98 | } 99 | else if(feed_type == LINEAR_REVERSED) { 100 | for (int i = msg.size()-1; i >= 0; i--) { 101 | process_bit(msg[i]); 102 | } 103 | } 104 | else if(feed_type == BYTEWISE_REVERSED) { 105 | 106 | for(size_t i = 0; i < msg.size(); i+=8) { 107 | // inverse feeding 108 | for(int j = 1; j <= 8; j++) 109 | process_bit(msg[i + 8 - j]); 110 | } 111 | } 112 | 113 | return checksum() == expected_crc; 114 | } 115 | 116 | 117 | bool my_crc_basic::calc_crc(value_type const use_initial, 118 | uint8_t msg[], size_t msg_length, 119 | value_type const expected_crc) { 120 | 121 | reset(use_initial); 122 | 123 | //process_bytes(msg, msg_length); 124 | 125 | return checksum() == expected_crc; 126 | 127 | } 128 | 129 | 130 | 131 | // Function that reflects its argument 132 | my_crc_basic::value_type my_crc_basic::reflect(value_type x ) const { 133 | 134 | value_type reflection = 0; 135 | value_type const one = 1; 136 | 137 | for( std::size_t i = 0 ; i < width_ ; ++i, x >>= 1 ) { 138 | if ( x & one ) { 139 | reflection |= ( one << (width_ - 1u - i) ); 140 | } 141 | } 142 | 143 | return reflection; 144 | } 145 | 146 | -------------------------------------------------------------------------------- /tests/test_bruteforce.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Test vectors generated from the crc-catalogue: 3 | * http://reveng.sourceforge.net/crc-catalogue/ 4 | * 5 | * Copyright MartynP 2016. 6 | * Distributed under the Boost Software License, Version 1.0. 7 | * (See accompanying file LICENSE_1_0.txt or copy at 8 | * http://www.boost.org/LICENSE_1_0.txt) 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define BOOST_TEST_DYN_LINK 17 | #define BOOST_TEST_MODULE "Test the bruteforce functionality" 18 | #include 19 | 20 | #include "../crc.hpp" 21 | #include "../bf_crc.hpp" 22 | 23 | #define CRCFOURTEEN 24 | #define CRCSIZTEEN 25 | #define CRCTHIRTYTWO 26 | 27 | char getRandomChar(){ 28 | static char c = 'A' + rand()%24; 29 | return c; 30 | } 31 | 32 | uint32_t calculate_crc(uint32_t crc_width, uint8_t data[], size_t length, bf_crc::crc_model_t model) 33 | { 34 | bf_crc::crc_t crc(crc_width); 35 | boost::dynamic_bitset<> msg = bf_crc::convert_uint8_to_bitset(data, length); 36 | 37 | crc.set(model.polynomial, model.initial, model.final_xor, model.reflected_input, model.reflected_output); 38 | crc.calc_crc(model.initial, msg); 39 | 40 | return crc.checksum(); 41 | } 42 | 43 | uint32_t calculate_crc(uint32_t crc_width, uint8_t data[], size_t length, bf_crc::crc_model_t model, boost::dynamic_bitset<> *msg) 44 | { 45 | bf_crc::crc_t crc(crc_width); 46 | 47 | *msg = bf_crc::convert_uint8_to_bitset(data, length); 48 | 49 | crc.set(model.polynomial, model.initial, model.final_xor, model.reflected_input, model.reflected_output); 50 | crc.calc_crc(model.initial, *msg); 51 | 52 | return crc.checksum(); 53 | } 54 | 55 | #ifdef CRCFOURTEEN 56 | BOOST_AUTO_TEST_CASE(crcFourteen) 57 | { 58 | // 14 bit CRC's 59 | bf_crc *crc_bruteforce; 60 | uint16_t crc_width = 14; 61 | bf_crc::crc_t crc(crc_width); 62 | boost::dynamic_bitset<> msg; 63 | 64 | // Lets make sure things are random 65 | srand((unsigned)time(0)); 66 | 67 | std::vector test_vectors; 68 | bf_crc::test_vector_t test_vector; 69 | 70 | /* 71 | * CRC-14/DARC 72 | * width=14 poly=0x0805 init=0x0000 refin=true refout=true xorout=0x0000 check=0x082d name="CRC-14/DARC" 73 | */ 74 | 75 | bf_crc::crc_model_t model(0x0805, 0x0000, 0x0000, true, true, my_crc_basic::AUTO); 76 | 77 | // REVENG Check 78 | uint8_t data_0[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 79 | test_vector.crc = calculate_crc(crc_width, data_0, sizeof(data_0), model, (boost::dynamic_bitset<>*)&msg); 80 | test_vector.message = msg; 81 | test_vectors.push_back(test_vector); 82 | 83 | // Check the CRC engine is still working... 84 | BOOST_CHECK(test_vector.crc == 0x082D); 85 | 86 | for (int i = 0; i < 10; i++) { 87 | 88 | uint8_t data[9]; 89 | for (int b = 0; b < 9; b++) 90 | data[b] = getRandomChar(); 91 | 92 | test_vector.crc = calculate_crc(crc_width, data, sizeof(data_0), model, (boost::dynamic_bitset<>*)&msg); 93 | test_vector.message = msg; 94 | test_vectors.push_back(test_vector); 95 | 96 | } 97 | 98 | crc_bruteforce = new bf_crc(crc_width, // CRC Width 99 | 0, // Polynomial 100 | false, // Probe Final XOR? 101 | 0, // Final XOR 102 | true, // Probe Initial? 103 | 0, // Initial 104 | true, // Probe Reflected Input? 105 | true, // Probe Reflected Output? 106 | my_crc_basic::AUTO); 107 | 108 | crc_bruteforce->set_verbose(true); 109 | crc_bruteforce->do_brute_force(4, test_vectors); 110 | 111 | // Get results 112 | std::vector results = crc_bruteforce->crc_model_match(); 113 | bool match = false; 114 | for (size_t i = 0; i < results.size(); i++) { 115 | if (results[i].polynomial == model.polynomial && 116 | results[i].initial == model.initial && 117 | results[i].final_xor == model.final_xor && 118 | results[i].reflected_output == model.reflected_output && 119 | results[i].reflected_input == model.reflected_input) 120 | match = true; 121 | } 122 | 123 | // Check the correct model was one of those identified 124 | BOOST_CHECK(match == true); 125 | 126 | } 127 | #endif 128 | 129 | #ifdef CRCSIXTEEN 130 | BOOST_AUTO_TEST_CASE(crcSixteen) 131 | { 132 | // 16 bit CRC's 133 | bf_crc *crc_bruteforce; 134 | uint16_t crc_width = 16; 135 | bf_crc::crc_t crc(crc_width); 136 | boost::dynamic_bitset<> msg; 137 | 138 | // Lets make sure things are random 139 | srand((unsigned)time(0)); 140 | 141 | std::vector test_vectors; 142 | bf_crc::test_vector_t test_vector; 143 | 144 | /* 145 | * CRC-16/CCITT-FALSE 146 | * width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE" 147 | */ 148 | 149 | // Model of the CRC to brute force 150 | bf_crc::crc_model_t model(0x1021, 0xFFFF, 0x0000, false, false); 151 | 152 | // REVENG Check 153 | uint8_t data_0[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 154 | test_vector.crc = calculate_crc(crc_width, data_0, sizeof(data_0), model, (boost::dynamic_bitset<>*)&msg); 155 | test_vector.message = msg; 156 | test_vectors.push_back(test_vector); 157 | 158 | // Check the CRC engine is still working... 159 | BOOST_CHECK(test_vector.crc == 0x29B1); 160 | 161 | for (int i = 0; i < 10; i++) { 162 | 163 | uint8_t data[9]; 164 | for (int b = 0; b < 9; b++) 165 | data[b] = getRandomChar(); 166 | 167 | test_vector.crc = calculate_crc(crc_width, data, sizeof(data_0), model, (boost::dynamic_bitset<>*)&msg); 168 | test_vector.message = msg; 169 | test_vectors.push_back(test_vector); 170 | 171 | } 172 | 173 | crc_bruteforce = new bf_crc(crc_width, // CRC Width 174 | 0, // Polynomial 175 | false, // Probe Final XOR? 176 | 0, // Final XOR 177 | true, // Probe Initial? 178 | 0, // Initial 179 | false, // Probe Reflected Input? 180 | false, // Probe Reflected Output? 181 | my_crc_basic::AUTO); 182 | 183 | crc_bruteforce->set_verbose(true); 184 | crc_bruteforce->do_brute_force(4, test_vectors); 185 | 186 | // Get results 187 | std::vector results = crc_bruteforce->crc_model_match(); 188 | bool match = false; 189 | for (size_t i = 0; i < results.size(); i++) { 190 | if (results[i].polynomial == model.polynomial && 191 | results[i].initial == model.initial && 192 | results[i].final_xor == model.final_xor && 193 | results[i].reflected_output == model.reflected_output && 194 | results[i].reflected_input == model.reflected_input) 195 | match = true; 196 | } 197 | 198 | // Check the correct model was one of those identified 199 | BOOST_CHECK(match == true); 200 | 201 | } 202 | #endif 203 | 204 | 205 | #ifdef CRCTHIRTYTWO 206 | BOOST_AUTO_TEST_CASE(crcThirtyTwo) 207 | { 208 | // 32 bit CRC's 209 | bf_crc *crc_bruteforce; 210 | uint16_t crc_width = 32; 211 | bf_crc::crc_t crc(crc_width); 212 | boost::dynamic_bitset<> msg; 213 | 214 | // Lets make sure things are random 215 | srand((unsigned)time(0)); 216 | 217 | std::vector test_vectors; 218 | bf_crc::test_vector_t test_vector; 219 | 220 | /* 221 | * CRC-32/BZIP2 222 | * width=32 poly=0x04c11db7 init=0xffffffff refin=false refout=false xorout=0xffffffff check=0xfc891918 name="CRC-32/BZIP2" 223 | */ 224 | 225 | // Model of the CRC to be brute forced 226 | bf_crc::crc_model_t model(0x04c11db7, 0xffffffff, 0xffffffff, false, false, my_crc_basic::AUTO); 227 | 228 | 229 | // REVENG Check 230 | uint8_t data_0[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 231 | test_vector.crc = calculate_crc(crc_width, data_0, sizeof(data_0), model, (boost::dynamic_bitset<>*)&msg); 232 | test_vector.message = msg; 233 | test_vectors.push_back(test_vector); 234 | 235 | // Check the CRC engine worked 236 | BOOST_CHECK(test_vector.crc == 0xFC891918); 237 | 238 | // Make another 10 test vectors 239 | for (int i = 0; i < 10; i++) { 240 | 241 | // Create some random data 242 | uint8_t data[9]; 243 | for (int b = 0; b < 9; b++) 244 | data[b] = getRandomChar(); 245 | 246 | test_vector.crc = calculate_crc(crc_width, data, sizeof(data), model, (boost::dynamic_bitset<>*)&msg); 247 | test_vector.message = msg; 248 | test_vectors.push_back(test_vector); 249 | 250 | } 251 | 252 | crc_bruteforce = new bf_crc(crc_width, // CRC Width 253 | 0, // Polynomial 254 | false, // Probe Final XOR? 255 | 0xFFFFFFFF, // Final XOR 256 | false, // Probe Initial? 257 | 0xFFFFFFFF, // Initial 258 | false, // Probe Reflected Input? 259 | false, // Probe Reflected Output? 260 | my_crc_basic::AUTO); 261 | 262 | 263 | crc_bruteforce->set_verbose(true); 264 | crc_bruteforce->set_polynomial_start(0x00000000); 265 | crc_bruteforce->set_polynomial_end(0x10000000); 266 | crc_bruteforce->do_brute_force(4, test_vectors); 267 | 268 | // Get results 269 | std::vector results = crc_bruteforce->crc_model_match(); 270 | bool match = false; 271 | for (size_t i = 0; i < results.size(); i++) { 272 | if (results[i].polynomial == model.polynomial && 273 | results[i].initial == model.initial && 274 | results[i].final_xor == model.final_xor && 275 | results[i].reflected_output == model.reflected_output && 276 | results[i].reflected_input == model.reflected_input) 277 | match = true; 278 | } 279 | 280 | // Test to make sure the model was identified 281 | BOOST_CHECK(match == true); 282 | 283 | } 284 | #endif 285 | -------------------------------------------------------------------------------- /bruteforce-crc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Front end application for brute-forcing CRC's of known good 3 | * test vectors. 4 | * 5 | * Original Author: Martin Schobert 6 | * Modified by MarytnP 7 | * 8 | * Copyright Martin Schobert and MartynP 2012 - 2016. 9 | * Distributed under the Boost Software License, Version 1.0. 10 | * (See accompanying file LICENSE_1_0.txt or copy at 11 | * http://www.boost.org/LICENSE_1_0.txt) 12 | * 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "bruteforce-crc.hpp" 32 | 33 | #include "bf_crc.hpp" 34 | 35 | namespace po = boost::program_options; 36 | 37 | 38 | std::istream& operator>>(std::istream& in, my_crc_basic::FEED_TYPE & feed_type) { 39 | std::string token; 40 | in >> token; 41 | if (token == "auto") 42 | feed_type = my_crc_basic::AUTO; 43 | else if (token == "linear-forward") 44 | feed_type = my_crc_basic::LINEAR_FORWARD; 45 | else if (token == "linear-reversed") 46 | feed_type = my_crc_basic::LINEAR_REVERSED; 47 | else if (token == "bytewise-reversed") 48 | feed_type = my_crc_basic::BYTEWISE_REVERSED; 49 | 50 | else throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value, "Invalid feed type"); 51 | 52 | return in; 53 | } 54 | 55 | /* 56 | * Parse a line from a text file for binary sequence 57 | */ 58 | boost::dynamic_bitset<> parse_line(std::string const& line) { 59 | 60 | boost::dynamic_bitset<> bits; 61 | static boost::regex exp1("^\\s*[10]+", boost::regex::perl|boost::regex::icase); 62 | 63 | if(regex_match(line, exp1)) { 64 | bits.resize(line.length()); 65 | for(size_t i = 0; i < line.length(); i++) { 66 | char c = line.at(i); 67 | if(c == '1') bits[i] = true; 68 | else if(c == '0') bits[i] = false; 69 | else break; // ignore garbage 70 | } 71 | } 72 | 73 | return bits; 74 | } 75 | 76 | /* 77 | * Read a file of test vectors 78 | * Each line is a binary sequence with a message of length (message_length) starting at zero indexed offset (offset_message) 79 | * The CRC is of length (crc_length) located at zero indexed offset (offset_crc) 80 | */ 81 | std::vector read_file(std::string const& file, size_t offset_message, size_t message_length, size_t offset_crc, size_t crc_length, bool verbose) { 82 | 83 | std::vector test_vectors; 84 | std::ifstream ifs(file.c_str()); 85 | std::string current_line; 86 | 87 | while(getline(ifs, current_line)) { 88 | bf_crc::test_vector_t tv; 89 | boost::dynamic_bitset<> msg = parse_line(current_line); 90 | boost::dynamic_bitset<> resized_msg; 91 | 92 | if(msg.size() < message_length) { 93 | std::cout << "Warning: ignoring line from input file\n"; 94 | continue; 95 | } 96 | 97 | resized_msg.resize(message_length); 98 | size_t bit = 0; 99 | 100 | for(size_t i = offset_message; i < offset_message + message_length; i++) { 101 | assert(i < msg.size()); 102 | assert(bit < message_length); 103 | resized_msg[bit++] = msg[i]; 104 | } 105 | 106 | tv.message = resized_msg; 107 | 108 | uint32_t crc = 0; 109 | for(size_t i = 0; i < crc_length; i++) { 110 | assert(offset_crc + 1 < msg.size()); 111 | crc <<= 1; 112 | crc |= (msg[offset_crc + i] == true ? 1 : 0); 113 | } 114 | 115 | if (verbose) { 116 | printf("Extracted message with crc %04x\n", crc); 117 | } 118 | 119 | tv.crc = crc; 120 | test_vectors.push_back(tv); 121 | } 122 | if (verbose) { 123 | printf("Extracted %ld messages and CRC values\n", test_vectors.size()); 124 | } 125 | 126 | return test_vectors; 127 | } 128 | 129 | int main(int argc, char *argv[]) { 130 | 131 | bf_crc *crc_bruteforce; 132 | 133 | size_t crc_width = 16; 134 | size_t offs_crc = 80; 135 | size_t start = 0; 136 | size_t end = offs_crc; 137 | 138 | std::string output = ""; 139 | bool verbose = false; 140 | 141 | int num_threads = 4; 142 | 143 | uint32_t polynomial = 0; 144 | 145 | bool reflected_input = false; 146 | bool reflected_output = false; 147 | 148 | uint32_t initial = 0; 149 | bool probe_initial = false; 150 | 151 | uint32_t final_xor = 0; 152 | bool probe_final_xor = false; 153 | 154 | my_crc_basic::FEED_TYPE feed_type = my_crc_basic::AUTO; 155 | 156 | 157 | // Definition of program options 158 | // Boost program options to allow settings with call 159 | po::options_description desc("Allowed options [required *]"); 160 | desc.add_options() 161 | ("help,h", "Produce help message") 162 | ("version,v", "Show version information") 163 | ("file", po::value(), "* File containing messages") 164 | ("width", po::value(), "* CRC width") 165 | ("offs-crc", po::value(), "* CRC's offset") 166 | ("start", po::value(), "* Calculate CRC from this offset") 167 | ("end", po::value(), "* Calculate CRC up to this offset (not included)") 168 | 169 | ("output", po::value(), "Output file for matched crc settings") 170 | ("verbose", po::value(), "Enable verbose output") 171 | 172 | ("poly", po::value(), "Truncated polynomial (default: bruteforced)") 173 | ("poly-start", po::value(), "Start of polynomial search space (default: 0)") 174 | ("poly-end", po::value(), "End of polynomial search space (default (2^width - 1))") 175 | 176 | ("threads", po::value(), "Number of threads (default: 4)") 177 | ("initial", po::value(), "Set intial value (default: 0)") 178 | 179 | ("probe-initial", po::value(), "Bruteforce the intial, overrides initial (default: true)") 180 | ("final-xor", po::value(), "Final xor (default: 0)") 181 | ("probe-final-xor", po::value(), "Bruteforce the final-xor, overrides final-xor (default: false)") 182 | ("probe-reflected-input", po::value(), "Probe for reflect input (default: false)") 183 | ("probe-reflected-output", po::value(), "Probe for reflect remainder output (default: false)") 184 | ("feed-type", po::value(), "How message bits are feed into CRC ('auto' (default), 'linear-forward', 'linear-reversed', 'bytewise-reversed')") 185 | ; 186 | 187 | // Parse programm options 188 | po::variables_map vm; 189 | po::store(po::parse_command_line(argc, argv, desc), vm); 190 | po::notify(vm); 191 | 192 | if(vm.count("version")) { 193 | std::cout << argv[0] << " version " << VERSION_STR << std::endl; 194 | return 1; 195 | } 196 | 197 | // Handle call for help and non-valid call 198 | if(vm.count("help") || !vm.count("file")) { 199 | std::cout << desc << std::endl; 200 | return 1; 201 | } 202 | 203 | // Load inputs to local variables 204 | if(vm.count("output")) output = vm["output"].as(); 205 | if(vm.count("verbose")) verbose = vm["verbose"].as(); 206 | if(vm.count("threads")) num_threads = vm["threads"].as(); 207 | if(vm.count("width")) crc_width = vm["width"].as(); 208 | if(vm.count("offs-crc")) offs_crc = vm["offs-crc"].as(); 209 | if(vm.count("start")) start = vm["start"].as(); 210 | if(vm.count("end")) end = vm["end"].as(); 211 | if(vm.count("initial")) initial = vm["initial"].as(); 212 | if(vm.count("probe-initial")) probe_initial = vm["probe-initial"].as(); 213 | if(vm.count("final-xor")) final_xor = vm["final-xor"].as(); 214 | if(vm.count("probe-final-xor")) probe_final_xor = vm["probe-final-xor"].as(); 215 | if(vm.count("poly")) polynomial = vm["poly"].as(); 216 | if(vm.count("probe-reflected-input")) reflected_input = vm["probe-reflected-input"].as(); 217 | if(vm.count("probe-reflected-output")) reflected_output = vm["probe-reflected-output"].as(); 218 | if(vm.count("feed-type")) feed_type = vm["feed-type"].as(); 219 | 220 | 221 | // Check parameters: A lot more checking 222 | if(crc_width > 32) { std::cout << "Error: maximum value for width is 32" << std::endl; exit(1); } 223 | 224 | // Warn user when things are about to go wrong TODO: Needs to be make more cleaner... 225 | if(((end-start) % 8 != 0) || (end - start == 0)) { 226 | std::cout << std::endl << "Warning: input reflection only works if range start ... end is N * 8 bit with N > 0" << std::endl << std::endl; 227 | std::cout << std::flush; 228 | } 229 | 230 | // Read messages from intput file 231 | std::vector test_vectors; 232 | if(vm.count("file")) { 233 | std::string const & fname = vm["file"].as(); 234 | if(!boost::filesystem::exists(fname)) { 235 | std::cout << "Can't find file '" << fname << "'." << std::endl; 236 | exit(1); 237 | } 238 | else 239 | test_vectors = read_file(fname, start, end-start, offs_crc, crc_width, verbose); 240 | } 241 | 242 | // Override non-conformal input 243 | if (probe_initial) initial = 0; 244 | 245 | crc_bruteforce = new bf_crc(crc_width, // CRC Width 246 | polynomial, // Polynomial 247 | probe_final_xor, // Probe Final XOR? 248 | final_xor, // Final XOR 249 | probe_initial, // Probe Initial? 250 | initial, // Initial 251 | reflected_input, // Probe Reflected Input? 252 | reflected_output, // Probe Reflected Output? 253 | feed_type); 254 | 255 | // The command line input can limit the search range 256 | if (vm.count("poly-start")) { 257 | uint32_t poly_start = vm["poly-start"].as(); 258 | crc_bruteforce->set_polynomial_start(poly_start); 259 | } 260 | 261 | if (vm.count("poly-end")) { 262 | uint32_t poly_end = vm["poly-end"].as(); 263 | crc_bruteforce->set_polynomial_end(poly_end); 264 | } 265 | 266 | crc_bruteforce->set_verbose(verbose); 267 | 268 | int found = crc_bruteforce->do_brute_force(num_threads, test_vectors); 269 | 270 | if (found > 0) 271 | std::cout << "Found " << found << " matches." << std::endl << std::endl; 272 | else 273 | std::cout << "No model found." << std::endl << std::endl; 274 | 275 | // Set output file 276 | if(vm.count("output")) { 277 | std::vector models = crc_bruteforce->crc_model_match(); 278 | try { 279 | std::ofstream ofile; 280 | std::string file = vm["output"].as(); 281 | ofile.open(file.c_str()); 282 | ofile << "Polynomial, Initial, Final XOR, Reflected Input, Reflected Output" << std::endl; 283 | for (size_t i = 0; i < models.size(); i++) { 284 | ofile << std::hex << "0x" << models[i].polynomial << "," << std::dec; 285 | ofile << std::hex << "0x" << models[i].initial << "," << std::dec; 286 | ofile << std::hex << "0x" << models[i].final_xor << "," << std::dec; 287 | ofile << (models[i].reflected_input ? "true" : "false") << ","; 288 | ofile << (models[i].reflected_output ? "true" : "false") << std::endl; 289 | } 290 | ofile.close(); 291 | } catch (...) { } 292 | 293 | } 294 | 295 | return 0; 296 | } 297 | 298 | 299 | -------------------------------------------------------------------------------- /bf_crc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Brute-force CRC based on known good vectors 3 | * 4 | * Original Author: Martin Schobert 5 | * Modified by MarytnP 6 | * 7 | * Copyright Martin Schobert and MartynP 2012 - 2016. 8 | * Distributed under the Boost Software License, Version 1.0. 9 | * (See accompanying file LICENSE_1_0.txt or copy at 10 | * http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "bf_crc.hpp" 29 | 30 | #include "ThreadPool.h" 31 | 32 | namespace po = boost::program_options; 33 | 34 | uint64_t crc_counter = 0; 35 | 36 | int bf_crc::bool_to_int(bool v) { 37 | return v ? 1 : 0; 38 | } 39 | 40 | bool bf_crc::int_to_bool(int v) { 41 | return v == 0 ? false : true; 42 | } 43 | 44 | std::string bf_crc::bool_to_str(bool v) { 45 | return v ? "true" : "false"; 46 | } 47 | 48 | std::string bf_crc::feed_type_to_str(my_crc_basic::FEED_TYPE feed_type) { 49 | switch(feed_type) { 50 | case my_crc_basic::AUTO: return "auto"; 51 | case my_crc_basic::LINEAR_FORWARD: return "linear-forward"; 52 | case my_crc_basic::LINEAR_REVERSED: return "linear-reversed"; 53 | case my_crc_basic::BYTEWISE_REVERSED: return "bytewise-reversed"; 54 | default: return "undefined"; 55 | } 56 | } 57 | 58 | std::string bf_crc::number_to_str(uint64_t v) { 59 | if(v < 1000) { 60 | boost::format f("%1%"); 61 | f % v; 62 | return f.str(); 63 | } 64 | else if(v < 1000*1000) { 65 | boost::format f("%1%k"); 66 | f % (v/1000); 67 | return f.str(); 68 | } 69 | else if(v < 1000*1000*1000) { 70 | boost::format f("%1%M"); 71 | f % (v/1000000); 72 | return f.str(); 73 | } 74 | else if(v < 1000*1000*1000*1000L) { 75 | boost::format f("%1%B"); 76 | f % (v/1000000000L); 77 | return f.str(); 78 | } 79 | else { 80 | boost::format f("%1%T"); 81 | f % (v/1000000000000); 82 | return f.str(); 83 | } 84 | 85 | } 86 | 87 | boost::dynamic_bitset<> bf_crc::convert_uint8_to_bitset(const uint8_t array[], size_t size) { 88 | 89 | boost::dynamic_bitset<> retVal(size*8); 90 | 91 | for (unsigned int i = 0; i < size; i++) 92 | for (int j = 0; j < 8; j++) 93 | retVal[i*8+j] = (array[i] >> (7-j)) & 0x1 ? true : false; 94 | 95 | return retVal; 96 | } 97 | 98 | boost::dynamic_bitset<> bf_crc::convert_string_to_bitset(std::string str) 99 | { 100 | boost::dynamic_bitset<> retVal(str.length()); 101 | 102 | for (size_t i = 0; i < str.length(); i++) 103 | retVal[i] = str[i] == '1' ? true : false; 104 | 105 | return retVal; 106 | } 107 | 108 | std::string bitset_to_byte_array(boost::dynamic_bitset<> const & message) { 109 | 110 | std::string ret; 111 | 112 | uint8_t byte = 0; 113 | 114 | // for the first byte 115 | for(size_t j = 0; j < 8; j++) { 116 | byte <<= 1; 117 | byte |= (message[j] == true ? 1 : 0); 118 | } 119 | 120 | boost::format f("0x%02x"); 121 | f % static_cast(byte); 122 | ret.append(f.str()); 123 | 124 | // for all subsequent bytes 125 | for(size_t i = 8; i < message.size(); i+=8) { 126 | 127 | byte = 0; 128 | 129 | for(size_t j = 0; j < 8; j++) { 130 | byte <<= 1; 131 | byte |= (message[i + j] == true ? 1 : 0); 132 | } 133 | 134 | boost::format f(", 0x%02x"); 135 | f % static_cast(byte); 136 | ret.append(f.str()); 137 | 138 | } 139 | 140 | return ret; 141 | } 142 | 143 | 144 | uint64_t bf_crc::get_delta_time_in_ms(struct timeval const& start) { 145 | struct timeval end; 146 | gettimeofday(&end, NULL); 147 | return (end.tv_sec*1000 + end.tv_usec/1000.0) - (start.tv_sec*1000 + start.tv_usec/1000.0); 148 | } 149 | 150 | std::string bf_crc::show_reflect_output (void) { 151 | return "uint32_t reflect_output(uint32_t x ) {\n" 152 | " uint32_t reflection = 0;\n" 153 | " uint32_t const one = 1;\n" 154 | " uint32_t width_ = 16;\n" 155 | " for( uint32_t i = 0 ; i < width_ ; ++i, x >>= 1 ) {\n" 156 | " if ( x & one )\n" 157 | " reflection |= ( one << (width_ - 1u - i) );\n" 158 | " }\n" 159 | " return reflection;\n" 160 | "}\n"; 161 | } 162 | 163 | void bf_crc::show_hit(crc_model_t model, std::vector test_vectors) { 164 | 165 | if (quiet_) return; 166 | 167 | 168 | std::cout 169 | << "----------------------------[ MATCH ]--------------------------------\n" 170 | << "Found a model for the CRC calculation:\n" 171 | << "Truncated polynom : 0x" << std::hex << model.polynomial << " (" << std::dec << model.polynomial << ")\n" 172 | << "Initial value : 0x" << std::hex << model.initial << " (" << std::dec << model.initial << ")\n" 173 | << "Final XOR : 0x" << std::hex << model.final_xor << " (" << std::dec << model.final_xor << ")\n" 174 | << "Reflected input : " << bool_to_str(model.reflected_input) << "\n" 175 | << "Reflected output : " << bool_to_str(model.reflected_output) << "\n" 176 | << "Feed type : " << feed_type_to_str(model.feed_type) << std::endl 177 | << std::endl << std::flush; 178 | 179 | 180 | // print an implementation 181 | 182 | if((model.feed_type == my_crc_basic::BYTEWISE_REVERSED || model.feed_type == my_crc_basic::AUTO) && 183 | (test_vectors.size() > 0) && 184 | (test_vectors[0].message.size() % 8 == 0)) { 185 | 186 | std::cout 187 | << "----------------------------[ Example implementation ]--------------------------------" << std::endl 188 | << "#include " << std::endl 189 | << "#include " << std::endl 190 | << std::endl 191 | << "#define STANDARD_FEEDING (7-i)" << std::endl 192 | << "#define BYTEWISE_REVERSE_FEEDING (i)" << std::endl 193 | << "#define FEEDING " << (model.reflected_input == true ? "BYTEWISE_REVERSE_FEEDING" : "STANDARD_FEEDING") << std::endl 194 | << std::endl 195 | << (model.reflected_output == true ? show_reflect_output() : std::string("")) << std::endl 196 | << "uint16_t calc_crc(uint16_t poly, uint16_t initial, uint16_t final_xor, uint8_t * buf, unsigned int len) {" << std::endl 197 | << " uint16_t crc = initial;" << std::endl 198 | << " unsigned int i, k;" << std::endl 199 | << "" << std::endl 200 | << " for(k = 0; k < len; k++ ) {" << std::endl 201 | << " for(i = 0; i < 8; i++ ) {" << std::endl 202 | << " int bit = ((buf[k] >> FEEDING & 1) == 1);" << std::endl 203 | << " int c15 = ((crc >> 15 & 1) == 1);" << std::endl 204 | << " crc <<= 1;" << std::endl 205 | << " if(c15 ^ bit) crc ^= poly;" << std::endl 206 | << " }" << std::endl 207 | << " }" << std::endl 208 | << (model.reflected_output == true ? " crc = reflect_output(crc);" : "") << std::endl 209 | << " crc ^= final_xor;" << std::endl 210 | << " return crc;" << std::endl 211 | << "}" << std::endl 212 | << std::endl 213 | << "int main(int argc, char * argv) {" << std::endl 214 | << "" << std::endl 215 | << " uint8_t buf[] = { " << bitset_to_byte_array(test_vectors[0].message) << "};" << std::endl 216 | << " uint16_t crc = " << (boost::format("0x%04x") % static_cast(test_vectors[0].crc)) << ";" << std::endl 217 | << " " << std::endl 218 | << " if(calc_crc( "<< (boost::format("0x%04x") % static_cast(model.polynomial)) << ", " 219 | << (boost::format("0x%04x") % static_cast(model.initial)) << ", " 220 | << (boost::format("0x%04x") % static_cast(model.final_xor)) << ", buf, sizeof(buf)) == crc) puts(\"CRC matches\");" << std::endl 221 | << " else puts(\"CRC does not match\");" << std::endl 222 | << " " << std::endl 223 | << "}" << std::endl; 224 | 225 | } 226 | } 227 | 228 | void bf_crc::print_stats(void) { 229 | 230 | if (quiet_) return; 231 | 232 | if(get_delta_time_in_ms(current_time) > 1000) { 233 | 234 | gettimeofday(¤t_time, NULL); 235 | uint64_t elapsed_ms = get_delta_time_in_ms(start_time); 236 | 237 | if(elapsed_ms > 0) { 238 | uint64_t crcs_per_sec = (1000*crc_counter/elapsed_ms); 239 | 240 | std::cout << "\rtime=" << (elapsed_ms/1000) << "s " 241 | << "CRCs/s=" << crcs_per_sec; 242 | 243 | if (crcs_per_sec > 0) 244 | { 245 | std::cout << " done=" << (crc_counter*100.0/test_vector_count()) << "%" 246 | << " (" << number_to_str(crc_counter) << " of " << number_to_str(test_vector_count()) << ")" 247 | << " time_to_go=" << (test_vector_count() - crc_counter)/crcs_per_sec/3600 << " h"; 248 | } 249 | 250 | std::cout << " \r" << std::flush; 251 | } 252 | } 253 | 254 | } 255 | 256 | 257 | void bf_crc::print_settings(void) 258 | { 259 | 260 | // Output Brute Force Settings 261 | std::cout << "Brute Force CRC Settings" << std::endl; 262 | std::cout << "------------------------" << std::endl; 263 | 264 | std::cout << "CRC Width : " << crc_width_ << std::endl; 265 | 266 | std::cout << "Truncated Polynomial "; 267 | if (polynomial_ > 0) 268 | std::cout << ": 0x" << std::hex << polynomial_ << std::endl; 269 | else 270 | std::cout << ": 0x0 to 0x" << std::hex << MAX_VALUE(crc_width_) << std::endl; 271 | 272 | 273 | std::cout << "Truncated Polynomial "; 274 | if (polynomial_ > 0) 275 | std::cout << ": 0x" << std::hex << polynomial_ << std::dec << std::endl; 276 | else 277 | std::cout << ": 0x" << std::hex << polynomial_start_ << " to 0x" << std::hex << polynomial_end_ << std::dec << std::endl; 278 | 279 | if (probe_initial_) 280 | std::cout << "Initial value : 0x0 to 0x" << std::hex << max_value(crc_width_) << std::dec << std::endl; 281 | else 282 | std::cout << "Initial value : 0x" << std::hex << initial_ << std::dec << std::endl; 283 | 284 | if (probe_final_xor_) 285 | std::cout << "Final xor : 0x0 to 0x" << std::hex << max_value(crc_width_) << std::dec << std::endl; 286 | else 287 | std::cout << "final xor : 0x" < test_vectors) { 298 | 299 | int stats_count = 0; 300 | 301 | // Otherwise the returned list is going to take up a LOT of RAM 302 | assert(test_vectors.size() > 0); 303 | 304 | // Get a CRC checker 305 | crc_t crc(crc_width_); 306 | 307 | // Initial value defaults to 0 308 | uint32_t init = 0; 309 | 310 | // Probe reflected input 311 | int probe_rin_start = probe_reflected_input_ ? 0 : bool_to_int(reflected_input_); 312 | int probe_rin_end = probe_reflected_input_ ? 1 : bool_to_int(reflected_input_); 313 | for(int probe_reflected_input = probe_rin_start; 314 | probe_reflected_input <= probe_rin_end; 315 | probe_reflected_input++) { 316 | 317 | // Probe reflected output 318 | int probe_rout_start = probe_reflected_output_ ? 0 : bool_to_int(reflected_output_); 319 | int probe_rout_end = probe_reflected_output_ ? 1 : bool_to_int(reflected_output_); 320 | for(int probe_reflected_output = probe_rout_start; 321 | probe_reflected_output <= probe_rout_end; 322 | probe_reflected_output++) { 323 | 324 | // Check all possible polynomials 325 | for(uint32_t poly = search_poly_start; 326 | poly <= search_poly_end; 327 | poly++) { 328 | 329 | // Probe all final xors 330 | for(uint32_t final_xor = (probe_final_xor_ ? 0 : final_xor_); 331 | final_xor <= (probe_final_xor_ ? max_value(crc_width_) : final_xor_); 332 | final_xor++) { 333 | 334 | // Set the CRC engine settings (initial set to zero, igored) 335 | crc.set(poly, 0, final_xor, int_to_bool(probe_reflected_input), int_to_bool(probe_reflected_output)); 336 | 337 | // For all possible initials 338 | for(init = (probe_initial_ ? 0 : initial_); 339 | init <= (probe_initial_ ? max_value(crc_width_) : initial_); 340 | init++) { 341 | 342 | // Start with true 343 | bool match = true; 344 | size_t m_i; 345 | 346 | // Over all test vectors, test to see if CRC settings work 347 | for(m_i = 0; match && (m_i < test_vectors.size()); m_i++) 348 | match = crc.calc_crc(init, test_vectors[m_i].message, test_vectors[m_i].crc, feed_type_); 349 | 350 | // If match is true there were no errors 351 | if(match == true && m_i == test_vectors.size()) { 352 | 353 | mymutex.lock(); 354 | 355 | crc_model_t match(poly, init, final_xor, int_to_bool(probe_reflected_input), int_to_bool(probe_reflected_output), feed_type_ ); 356 | crc_model_match_.push_back(match); 357 | 358 | if (verbose_) 359 | show_hit(match, test_vectors); 360 | 361 | print_stats(); 362 | 363 | mymutex.unlock(); 364 | } 365 | 366 | stats_count++; 367 | if (stats_count % 0x80 == 0) print_stats(); 368 | 369 | if (init == max_value(sizeof(init) * 8)) break; 370 | 371 | } // end for loop, initials 372 | 373 | mymutex.lock(); 374 | 375 | crc_counter += probe_initial_ ? max_value(crc_width_) : 1; 376 | 377 | // TODO: is this a good way to do this? 378 | if(probe_final_xor_ || (crc_counter % 0x80 == 0)) 379 | { 380 | print_stats(); 381 | } 382 | 383 | mymutex.unlock(); 384 | 385 | // Handle overflow of for loop 386 | if (final_xor == max_value(sizeof(final_xor) * 8)) break; 387 | 388 | } // end for loop, final_xor 389 | 390 | if (poly == max_value(sizeof(poly) * 8)) break; 391 | 392 | } // end for loop, polynomial 393 | 394 | } // end for loop, reflected output 395 | 396 | } // end for loop, reflected input 397 | 398 | return false; 399 | } 400 | 401 | int bf_crc::do_brute_force(int num_threads, std::vector test_vectors){ 402 | 403 | 404 | // Record start time for statistics 405 | gettimeofday(&start_time, NULL); 406 | gettimeofday(¤t_time, NULL); 407 | 408 | // Start a thread pool 409 | ThreadPool > pool; 410 | 411 | if (verbose_) { 412 | // Show the current settings 413 | print_settings(); 414 | 415 | // And this specific run's settings 416 | std::cout << std::endl; 417 | std::cout << "Multithreaded CRC Brute Force Initiated" << std::endl; 418 | std::cout << "---------------------------------------" << std::endl; 419 | std::cout << "Number of threads : " << std::dec << num_threads << std::endl; 420 | std::cout << "Number of test vectors : " << std::dec << test_vectors.size() << std::endl; 421 | std::cout << std::endl << std::flush; 422 | } 423 | 424 | // TODO: If you know the poly... 425 | if (polynomial_ > 0) { 426 | num_threads = 1; 427 | } 428 | 429 | // Clear the result store 430 | crc_model_match_.clear(); 431 | 432 | // TODO: Search all known CRC combinations first 433 | if (verbose_) { 434 | std::cout << std::endl; 435 | std::cout << "Testing Known CRC's for Length " << crc_width_ << std::endl; 436 | std::cout << "---------------------------------" << std::endl; 437 | std::cout << std::endl << std::flush; 438 | } 439 | 440 | assert((int)known_models.size() >= crc_width_ - 1); // Check there are enough known models... 441 | for (size_t model = 0; model < known_models[crc_width_].size(); model++) 442 | { 443 | 444 | bf_crc *known_bf = new bf_crc( crc_width_, 445 | known_models[crc_width_][model].polynomial, 446 | false, 447 | known_models[crc_width_][model].final_xor, 448 | false, 449 | known_models[crc_width_][model].initial, 450 | false, 451 | false, my_crc_basic::AUTO); 452 | known_bf->set_reflected_input(known_models[crc_width_][model].reflected_input); 453 | known_bf->set_reflected_output(known_models[crc_width_][model].reflected_output); 454 | 455 | known_bf->set_quiet(true); // Turn off all output 456 | known_bf->brute_force(known_models[crc_width_][model].polynomial,known_models[crc_width_][model].polynomial, test_vectors); 457 | 458 | for (size_t found = 0; found < known_bf->crc_model_match().size(); found++) { 459 | crc_model_t result = known_bf->crc_model_match()[found]; 460 | 461 | if (std::find(crc_model_match_.begin(), crc_model_match_.end(), result) != crc_model_match_.end()) { 462 | // Nothing to do if model exists already 463 | show_hit(known_bf->crc_model_match()[found], test_vectors); 464 | } else { 465 | crc_model_match_.push_back(known_bf->crc_model_match()[found]); 466 | if (verbose_) 467 | show_hit(known_bf->crc_model_match()[found], test_vectors); 468 | } 469 | } 470 | 471 | delete known_bf; 472 | 473 | } 474 | 475 | 476 | // Polystep is how the search polynomials are spread betweeen threads 477 | uint32_t poly_count = polynomial_end_ - polynomial_start_; 478 | uint32_t poly_step = polynomial_ > 0 ? 1 : poly_count/num_threads; 479 | 480 | // Handle low polynomial count 481 | if (poly_step == 0) poly_step = 1; 482 | 483 | if (verbose_) { 484 | std::cout << std::endl; 485 | std::cout << "Starting brute forcer over selected threads" << std::endl; 486 | std::cout << "-------------------------------------------" << std::endl; 487 | std::cout << std::endl << std::flush; 488 | } 489 | 490 | 491 | for(int thread_number = 0; thread_number < num_threads; thread_number++) { 492 | 493 | uint32_t search_end = 0; 494 | if (polynomial_ > 0) 495 | search_end = polynomial_; 496 | else 497 | search_end = polynomial_start_ + (thread_number + 1) * poly_step - 1; 498 | 499 | // Due to math the last caluclate will wrap to zero? 500 | if (thread_number == num_threads-1 && polynomial_ == 0) 501 | search_end = polynomial_end_; 502 | 503 | uint32_t search_start = 0; 504 | if (polynomial_ > 0) 505 | search_start = polynomial_; 506 | else 507 | search_start = polynomial_start_ + thread_number * poly_step; 508 | 509 | if (verbose_) { 510 | std::cout << "Starting Thread " << thread_number << ", searching from "; 511 | std::cout << std::hex << search_start << " to " << search_end << std::endl << std::dec << std::flush; 512 | } 513 | 514 | pool.add(boost::bind(&bf_crc::brute_force, this, search_start, search_end, test_vectors)); 515 | 516 | } 517 | 518 | if (verbose_) 519 | std::cout << std::endl << std::flush; 520 | 521 | // Wait for all threads to complete 522 | pool.wait(); 523 | 524 | return crc_model_match_.size(); 525 | } 526 | 527 | -------------------------------------------------------------------------------- /bf_crc.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Brute-force CRC based on known good vectors 3 | * 4 | * Original Author: Martin Schobert 5 | * Modified by MarytnP 6 | * 7 | * Copyright Martin Schobert and MartynP 2012 - 2016. 8 | * Distributed under the Boost Software License, Version 1.0. 9 | * (See accompanying file LICENSE_1_0.txt or copy at 10 | * http://www.boost.org/LICENSE_1_0.txt) 11 | * 12 | */ 13 | 14 | #ifndef _BRUTEFORCE_CRC_LIB_HPP_ 15 | #define _BRUTEFORCE_CRC_LIB_HPP_ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "crc.hpp" 22 | 23 | class bf_crc { 24 | 25 | public: 26 | 27 | typedef struct vector_ { 28 | boost::dynamic_bitset<> message; 29 | uint32_t crc; 30 | } test_vector_t; 31 | 32 | typedef class crc_model_ { 33 | public: 34 | uint32_t polynomial; 35 | uint32_t initial; 36 | uint32_t final_xor; 37 | bool reflected_input; 38 | bool reflected_output; 39 | my_crc_basic::FEED_TYPE feed_type; 40 | 41 | crc_model_(); 42 | crc_model_(uint32_t polynomial, uint32_t initial, uint32_t final_xor, bool reflected_input, bool reflected_output, my_crc_basic::FEED_TYPE feed_type) : 43 | polynomial(polynomial), 44 | initial(initial), 45 | final_xor(final_xor), 46 | reflected_input(reflected_input), 47 | reflected_output(reflected_output), 48 | feed_type(feed_type) 49 | 50 | {} 51 | bool compare(const crc_model_& crc_model) const { 52 | if (crc_model.polynomial != polynomial || 53 | crc_model.initial != initial || 54 | crc_model.final_xor != final_xor || 55 | crc_model.reflected_input != reflected_input || 56 | crc_model.reflected_output != reflected_output) 57 | // skip feed type in comparison 58 | 59 | return 0; 60 | else 61 | return 1; 62 | } 63 | bool operator == (const crc_model_& d) const { 64 | return compare(d); 65 | } 66 | 67 | } crc_model_t; 68 | 69 | typedef my_crc_basic crc_t; 70 | 71 | bf_crc( uint16_t crc_width, 72 | uint32_t polynomial, 73 | bool probe_final_xor, 74 | uint32_t final_xor, 75 | bool probe_initial, 76 | uint32_t initial, 77 | bool probe_reflected_input, 78 | bool probe_reflected_output, 79 | my_crc_basic::FEED_TYPE feed_type) { 80 | set_parameters( crc_width, 81 | polynomial, 82 | probe_final_xor, 83 | final_xor, 84 | probe_initial, 85 | initial, 86 | probe_reflected_input, 87 | probe_reflected_output, feed_type); 88 | crc_model_match_.clear(); 89 | verbose_ = false; 90 | quiet_ = false; 91 | reflected_input_ = false; 92 | reflected_output_ = false; 93 | 94 | 95 | // Polulate known models from http://reveng.sourceforge.net 96 | std::vector crc_0; 97 | known_models.push_back(crc_0); 98 | 99 | std::vector crc_1; 100 | known_models.push_back(crc_1); 101 | 102 | std::vector crc_2; 103 | known_models.push_back(crc_2); 104 | 105 | std::vector crc_3; 106 | { 107 | // width=3 poly=0x3 init=0x7 refin=true refout=true xorout=0x0 check=0x6 name="CRC-3/ROHC" 108 | crc_3.push_back(crc_model_t(0x3, 0x7, 0x0, false, false, my_crc_basic::AUTO)); 109 | } 110 | known_models.push_back(crc_3); 111 | 112 | std::vector crc_4; 113 | { 114 | // width=4 poly=0x3 init=0xf refin=false refout=false xorout=0xf check=0xb name="CRC-4/INTERLAKEN" 115 | crc_4.push_back(crc_model_t(0x3, 0xf, 0xf, false, false, my_crc_basic::AUTO)); 116 | // width=4 poly=0x3 init=0x0 refin=true refout=true xorout=0x0 check=0x7 name="CRC-4/ITU" 117 | crc_4.push_back(crc_model_t(0x3, 0x0, 0x0, true, true, my_crc_basic::AUTO)); 118 | } 119 | known_models.push_back(crc_4); 120 | 121 | std::vector crc_5; 122 | { 123 | // width=5 poly=0x09 init=0x09 refin=false refout=false xorout=0x00 check=0x00 name="CRC-5/EPC" 124 | crc_5.push_back(crc_model_t(0x09, 0x9, 0x0, false, false, my_crc_basic::AUTO)); 125 | // width=5 poly=0x15 init=0x00 refin=true refout=true xorout=0x00 check=0x07 name="CRC-5/ITU" 126 | crc_5.push_back(crc_model_t(0x15, 0x1f, 0x1f, true, true, my_crc_basic::AUTO)); 127 | // width=5 poly=0x05 init=0x1f refin=true refout=true xorout=0x1f check=0x19 name="CRC-5/USB" 128 | crc_5.push_back(crc_model_t(0x05, 0x1f, 0x1f, true, true, my_crc_basic::AUTO)); 129 | } 130 | known_models.push_back(crc_5); 131 | 132 | std::vector crc_6; 133 | { 134 | // width=6 poly=0x27 init=0x3f refin=false refout=false xorout=0x00 check=0x0d name="CRC-6/CDMA2000-A" 135 | crc_6.push_back(crc_model_t(0x27, 0x3f, 0x00, false, false, my_crc_basic::AUTO)); 136 | // width=6 poly=0x07 init=0x3f refin=false refout=false xorout=0x00 check=0x3b name="CRC-6/CDMA2000-B" 137 | crc_6.push_back(crc_model_t(0x02, 0x3f, 0x00, false, false, my_crc_basic::AUTO)); 138 | // width=6 poly=0x19 init=0x00 refin=true refout=true xorout=0x00 check=0x26 name="CRC-6/DARC" 139 | crc_6.push_back(crc_model_t(0x19, 0x00, 0x00, true, true, my_crc_basic::AUTO)); 140 | // width=6 poly=0x03 init=0x00 refin=true refout=true xorout=0x00 check=0x06 name="CRC-6/ITU" 141 | crc_6.push_back(crc_model_t(0x03, 0x00, 0x00, true, true, my_crc_basic::AUTO)); 142 | } 143 | known_models.push_back(crc_6); 144 | 145 | std::vector crc_7; 146 | { 147 | // width=7 poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75 name="CRC-7" 148 | crc_7.push_back(crc_model_t(0x09, 0x00, 0x00, false, false, my_crc_basic::AUTO)); 149 | // width=7 poly=0x4f init=0x7f refin=true refout=true xorout=0x00 check=0x53 name="CRC-7/ROHC" 150 | crc_7.push_back(crc_model_t(0x4f, 0x7f, 0x00, true, true, my_crc_basic::AUTO)); 151 | // width=7 poly=0x45 init=0x00 refin=false refout=false xorout=0x00 check=0x61 name="CRC-7/UMTS" 152 | crc_7.push_back(crc_model_t(0x45, 0x00, 0x00, false, false, my_crc_basic::AUTO)); 153 | } 154 | known_models.push_back(crc_7); 155 | 156 | std::vector crc_8; 157 | { 158 | // width=8 poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4 name="CRC-8" 159 | crc_8.push_back(crc_model_t(0x07, 0x00, 0x00, false, false, my_crc_basic::AUTO)); 160 | // width=8 poly=0x2f init=0xff refin=false refout=false xorout=0xff check=0xdf name="CRC-8/AUTOSAR" 161 | crc_8.push_back(crc_model_t(0x2f, 0xff, 0xff, false, false, my_crc_basic::AUTO)); 162 | // width=8 poly=0x9b init=0xff refin=false refout=false xorout=0x00 check=0xda name="CRC-8/CDMA2000" 163 | crc_8.push_back(crc_model_t(0x9b, 0xff, 0x00, false, false, my_crc_basic::AUTO)); 164 | // width=8 poly=0x39 init=0x00 refin=true refout=true xorout=0x00 check=0x15 name="CRC-8/DARC" 165 | crc_8.push_back(crc_model_t(0x39, 0x00, 0x00, true, true, my_crc_basic::AUTO)); 166 | // width=8 poly=0xd5 init=0x00 refin=false refout=false xorout=0x00 check=0xbc name="CRC-8/DVB-S2" 167 | crc_8.push_back(crc_model_t(0xd5, 0x00, 0x00, false, false, my_crc_basic::AUTO)); 168 | // width=8 poly=0x1d init=0xff refin=true refout=true xorout=0x00 check=0x97 name="CRC-8/EBU" 169 | crc_8.push_back(crc_model_t(0x1d, 0xff, 0x00, true, true, my_crc_basic::AUTO)); 170 | // width=8 poly=0x1d init=0xfd refin=false refout=false xorout=0x00 check=0x7e name="CRC-8/I-CODE" 171 | crc_8.push_back(crc_model_t(0x1d, 0xfd, 0x00, false, false, my_crc_basic::AUTO)); 172 | // width=8 poly=0x07 init=0x00 refin=false refout=false xorout=0x55 check=0xa1 name="CRC-8/ITU" 173 | crc_8.push_back(crc_model_t(0x07, 0x00, 0xff, false, false, my_crc_basic::AUTO)); 174 | // width=8 poly=0x9b init=0x00 refin=false refout=false xorout=0x00 check=0xea name="CRC-8/LTE" 175 | crc_8.push_back(crc_model_t(0x9b, 0x00, 0x00, false, false, my_crc_basic::AUTO)); 176 | // width=8 poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1 name="CRC-8/MAXIM" 177 | crc_8.push_back(crc_model_t(0x31, 0x00, 0x00, true, true, my_crc_basic::AUTO)); 178 | // width=8 poly=0x2f init=0x00 refin=false refout=false xorout=0x00 check=0x3e name="CRC-8/OPENSAFETY" 179 | crc_8.push_back(crc_model_t(0x2f, 0x00, 0x00, false, false, my_crc_basic::AUTO)); 180 | // width=8 poly=0x07 init=0xff refin=true refout=true xorout=0x00 check=0xd0 name="CRC-8/ROHC" 181 | crc_8.push_back(crc_model_t(0x07, 0xff, 0x00, true, true, my_crc_basic::AUTO)); 182 | // width=8 poly=0x1d init=0xff refin=false refout=false xorout=0xff check=0x4b name="CRC-8/SAE-J1850" 183 | crc_8.push_back(crc_model_t(0x1d, 0xff, 0xff, false, false, my_crc_basic::AUTO)); 184 | // width=8 poly=0x9b init=0x00 refin=true refout=true xorout=0x00 check=0x25 name="CRC-8/WCDMA" 185 | crc_8.push_back(crc_model_t(0x9b, 0x00, 0x00, true, true, my_crc_basic::AUTO)); 186 | } 187 | known_models.push_back(crc_8); 188 | 189 | std::vector crc_9; 190 | known_models.push_back(crc_9); 191 | 192 | std::vector crc_10; 193 | { 194 | // width=10 poly=0x233 init=0x000 refin=false refout=false xorout=0x000 check=0x199 name="CRC-10" 195 | crc_10.push_back(crc_model_t(0x233, 0x000, 0x000, false, false, my_crc_basic::AUTO)); 196 | // width=10 poly=0x3d9 init=0x3ff refin=false refout=false xorout=0x000 check=0x233 name="CRC-10/CDMA2000" 197 | crc_10.push_back(crc_model_t(0x3d9, 0x3ff, 0x000, false, false, my_crc_basic::AUTO)); 198 | crc_10.push_back(crc_model_t(0x0bd, 0x00, 0x00, false, false, my_crc_basic::AUTO)); 199 | } 200 | known_models.push_back(crc_10); 201 | 202 | std::vector crc_11; 203 | { 204 | // width=11 poly=0x385 init=0x01a refin=false refout=false xorout=0x000 check=0x5a3 name="CRC-11" 205 | crc_11.push_back(crc_model_t(0x385, 0x01a, 0x000, false, false, my_crc_basic::AUTO)); 206 | // width=11 poly=0x307 init=0x000 refin=false refout=false xorout=0x000 check=0x061 name="CRC-11/UMTS" 207 | crc_11.push_back(crc_model_t(0x307, 0x000, 0x000, false, false, my_crc_basic::AUTO)); 208 | } 209 | known_models.push_back(crc_11); 210 | 211 | std::vector crc_12; 212 | { 213 | // width=12 poly=0xf13 init=0xfff refin=false refout=false xorout=0x000 check=0xd4d name="CRC-12/CDMA2000" 214 | crc_12.push_back(crc_model_t(0xf13, 0xfff, 0x000, false, false, my_crc_basic::AUTO)); 215 | // width=12 poly=0x80f init=0x000 refin=false refout=false xorout=0x000 check=0xf5b name="CRC-12/DECT" 216 | crc_12.push_back(crc_model_t(0x80f, 0x000, 0x000, false ,false, my_crc_basic::AUTO)); 217 | // width=12 poly=0x80f init=0x000 refin=false refout=true xorout=0x000 check=0xdaf name="CRC-12/UMTS" 218 | crc_12.push_back(crc_model_t(0x80f, 0x000, 0x000, false, true, my_crc_basic::AUTO)); 219 | } 220 | known_models.push_back(crc_12); 221 | 222 | std::vector crc_13; 223 | { 224 | // width=13 poly=0x1cf5 init=0x0000 refin=false refout=false xorout=0x0000 check=0x04fa name="CRC-13/BBC" 225 | crc_13.push_back(crc_model_t(0x1cf5, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 226 | } 227 | known_models.push_back(crc_13); 228 | 229 | std::vector crc_14; 230 | { 231 | // width=14 poly=0x0805 init=0x0000 refin=true refout=true xorout=0x0000 check=0x082d name="CRC-14/DARC" 232 | crc_14.push_back(crc_model_t(0x0805, 0x0000, 0x0000, true, true, my_crc_basic::AUTO)); 233 | } 234 | known_models.push_back(crc_14); 235 | 236 | std::vector crc_15; 237 | { 238 | // width=15 poly=0x4599 init=0x0000 refin=false refout=false xorout=0x0000 check=0x059e name="CRC-15" 239 | crc_15.push_back(crc_model_t(0x4599, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 240 | // width=15 poly=0x6815 init=0x0000 refin=false refout=false xorout=0x0001 check=0x2566 name="CRC-15/MPT1327" 241 | crc_15.push_back(crc_model_t(0x6815, 0x0000, 0x0001, false, false, my_crc_basic::AUTO)); 242 | } 243 | known_models.push_back(crc_15); 244 | 245 | std::vector crc_16; 246 | { 247 | //width=16 poly=0x8005 init=0x0000 refin=true refout=true xorout=0x0000 check=0xbb3d name="ARC" 248 | crc_16.push_back(crc_model_t(0x8005, 0x0000, 0x0000, true, true, my_crc_basic::AUTO)); 249 | //width=16 poly=0x1021 init=0x1d0f refin=false refout=false xorout=0x0000 check=0xe5cc name="CRC-16/AUG-CCITT" 250 | crc_16.push_back(crc_model_t(0x1021, 0x1d0f, 0x0000, false, false, my_crc_basic::AUTO)); 251 | //width=16 poly=0x8005 init=0x0000 refin=false refout=false xorout=0x0000 check=0xfee8 name="CRC-16/BUYPASS" 252 | crc_16.push_back(crc_model_t(0x8005, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 253 | //width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE" 254 | crc_16.push_back(crc_model_t(0x1021, 0xffff, 0x0000, false, false, my_crc_basic::AUTO)); 255 | //width=16 poly=0xc867 init=0xffff refin=false refout=false xorout=0x0000 check=0x4c06 name="CRC-16/CDMA2000" 256 | crc_16.push_back(crc_model_t(0xc867, 0xffff, 0x0000, false, false, my_crc_basic::AUTO)); 257 | //width=16 poly=0x8005 init=0xffff refin=false refout=false xorout=0x0000 check=0xaee7 name="CRC-16/CMS" 258 | crc_16.push_back(crc_model_t(0x8005, 0xffff, 0x0000, false, false, my_crc_basic::AUTO)); 259 | //width=16 poly=0x8005 init=0x800d refin=false refout=false xorout=0x0000 check=0x9ecf name="CRC-16/DDS-110" 260 | crc_16.push_back(crc_model_t(0x8005, 0x800d, 0x0000, false, false, my_crc_basic::AUTO)); 261 | //width=16 poly=0x0589 init=0x0000 refin=false refout=false xorout=0x0001 check=0x007e name="CRC-16/DECT-R" 262 | crc_16.push_back(crc_model_t(0x0589, 0x0000, 0x0001, false, false, my_crc_basic::AUTO)); 263 | //width=16 poly=0x0589 init=0x0000 refin=false refout=false xorout=0x0000 check=0x007f name="CRC-16/DECT-X" 264 | crc_16.push_back(crc_model_t(0x0589, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 265 | //width=16 poly=0x3d65 init=0x0000 refin=true refout=true xorout=0xffff check=0xea82 name="CRC-16/DNP" 266 | crc_16.push_back(crc_model_t(0x3d65, 0x0000, 0xffff, true, true, my_crc_basic::AUTO)); 267 | //width=16 poly=0x3d65 init=0x0000 refin=false refout=false xorout=0xffff check=0xc2b7 name="CRC-16/EN-13757" 268 | crc_16.push_back(crc_model_t(0x3d65, 0x0000, 0xffff, false, false, my_crc_basic::AUTO)); 269 | //width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0xffff check=0xd64e name="CRC-16/GENIBUS" 270 | crc_16.push_back(crc_model_t(0x1021, 0xffff, 0xffff, false, false, my_crc_basic::AUTO)); 271 | //width=16 poly=0x6f63 init=0x0000 refin=false refout=false xorout=0x0000 check=0xbdf4 name="CRC-16/LJ1200" 272 | crc_16.push_back(crc_model_t(0x6f63, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 273 | //width=16 poly=0x8005 init=0x0000 refin=true refout=true xorout=0xffff check=0x44c2 name="CRC-16/MAXIM" 274 | crc_16.push_back(crc_model_t(0x8005, 0x0000, 0xffff, true, true, my_crc_basic::AUTO)); 275 | //width=16 poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91 name="CRC-16/MCRF4XX" 276 | crc_16.push_back(crc_model_t(0x1021, 0xffff, 0x0000, true, true, my_crc_basic::AUTO)); 277 | //width=16 poly=0x5935 init=0x0000 refin=false refout=false xorout=0x0000 check=0x5d38 name="CRC-16/OPENSAFETY-A" 278 | crc_16.push_back(crc_model_t(0x5935, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 279 | //width=16 poly=0x755b init=0x0000 refin=false refout=false xorout=0x0000 check=0x20fe name="CRC-16/OPENSAFETY-B" 280 | crc_16.push_back(crc_model_t(0x755b, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 281 | //width=16 poly=0x1dcf init=0xffff refin=false refout=false xorout=0xffff check=0xa819 name="CRC-16/PROFIBUS" 282 | crc_16.push_back(crc_model_t(0x1dcf, 0xffff, 0xffff, false, false, my_crc_basic::AUTO)); 283 | //width=16 poly=0x1021 init=0xb2aa refin=true refout=true xorout=0x0000 check=0x63d0 name="CRC-16/RIELLO" 284 | crc_16.push_back(crc_model_t(0x1021, 0xb2aa, 0x0000, true, true, my_crc_basic::AUTO)); 285 | ///width=16 poly=0x8bb7 init=0x0000 refin=false refout=false xorout=0x0000 check=0xd0db name="CRC-16/T10-DIF" 286 | crc_16.push_back(crc_model_t(0x8bb7, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 287 | //width=16 poly=0xa097 init=0x0000 refin=false refout=false xorout=0x0000 check=0x0fb3 name="CRC-16/TELEDISK" 288 | crc_16.push_back(crc_model_t(0xa097, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 289 | //width=16 poly=0x1021 init=0x89ec refin=true refout=true xorout=0x0000 check=0x26b1 name="CRC-16/TMS37157" 290 | crc_16.push_back(crc_model_t(0x1021, 0x89ec, 0x0000, true, true, my_crc_basic::AUTO)); 291 | //width=16 poly=0x8005 init=0xffff refin=true refout=true xorout=0xffff check=0xb4c8 name="CRC-16/USB" 292 | crc_16.push_back(crc_model_t(0x8005, 0xffff, 0xffff, true, true, my_crc_basic::AUTO)); 293 | //width=16 poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 check=0xbf05 name="CRC-A" 294 | crc_16.push_back(crc_model_t(0x1021, 0xc6c6, 0x0000, true, true, my_crc_basic::AUTO)); 295 | //width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 name="KERMIT" 296 | crc_16.push_back(crc_model_t(0x1021, 0x0000, 0x0000, true, true, my_crc_basic::AUTO)); 297 | //width=16 poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37 name="MODBUS" 298 | crc_16.push_back(crc_model_t(0x8005, 0xffff, 0x0000, true, true, my_crc_basic::AUTO)); 299 | //width=16 poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e name="X-25" 300 | crc_16.push_back(crc_model_t(0x1021, 0xffff, 0xffff, true, true, my_crc_basic::AUTO)); 301 | //width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 name="XMODEM" 302 | crc_16.push_back(crc_model_t(0x1021, 0x0000, 0x0000, false, false, my_crc_basic::AUTO)); 303 | } 304 | known_models.push_back(crc_16); 305 | 306 | std::vector crc_17; 307 | known_models.push_back(crc_17); 308 | 309 | std::vector crc_18; 310 | known_models.push_back(crc_18); 311 | 312 | std::vector crc_19; 313 | known_models.push_back(crc_19); 314 | 315 | std::vector crc_20; 316 | known_models.push_back(crc_20); 317 | 318 | std::vector crc_21; 319 | known_models.push_back(crc_21); 320 | 321 | std::vector crc_22; 322 | known_models.push_back(crc_22); 323 | 324 | std::vector crc_23; 325 | known_models.push_back(crc_23); 326 | 327 | std::vector crc_24; 328 | { 329 | // width=24 poly=0x864cfb init=0xb704ce refin=false refout=false xorout=0x000000 check=0x21cf02 name="CRC-24" 330 | crc_24.push_back(crc_model_t(0x864cfb, 0xb704ce, 0x000000, false, false, my_crc_basic::AUTO)); 331 | // width=24 poly=0x00065b init=0x555555 refin=true refout=true xorout=0x000000 check=0xc25a56 name="CRC-24/BLE" 332 | crc_24.push_back(crc_model_t(0x00065b, 0xffffff, 0x000000, true, true, my_crc_basic::AUTO)); 333 | // width=24 poly=0x5d6dcb init=0xfedcba refin=false refout=false xorout=0x000000 check=0x7979bd name="CRC-24/FLEXRAY-A" 334 | crc_24.push_back(crc_model_t(0x5d6dcb, 0xfedcba, 0x000000, false, false, my_crc_basic::AUTO)); 335 | // width=24 poly=0x5d6dcb init=0xabcdef refin=false refout=false xorout=0x000000 check=0x1f23b8 name="CRC-24/FLEXRAY-B" 336 | crc_24.push_back(crc_model_t(0x5d6dcb, 0xabcdef, 0x000000, false, false, my_crc_basic::AUTO)); 337 | // width=24 poly=0x328b63 init=0xffffff refin=false refout=false xorout=0xffffff check=0xb4f3e6 name="CRC-24/INTERLAKEN" 338 | crc_24.push_back(crc_model_t(0x328b63, 0xffffff, 0xffffff, false, false, my_crc_basic::AUTO)); 339 | // width=24 poly=0x864cfb init=0x000000 refin=false refout=false xorout=0x000000 check=0xcde703 name="CRC-24/LTE-A" 340 | crc_24.push_back(crc_model_t(0x864cfb, 0x000000, 0x000000, false, false, my_crc_basic::AUTO)); 341 | // width=24 poly=0x800063 init=0x000000 refin=false refout=false xorout=0x000000 check=0x23ef52 name="CRC-24/LTE-B" 342 | crc_24.push_back(crc_model_t(0x800064, 0x000000, 0x000000, false, false, my_crc_basic::AUTO)); 343 | } 344 | known_models.push_back(crc_24); 345 | 346 | std::vector crc_25; 347 | known_models.push_back(crc_25); 348 | 349 | std::vector crc_26; 350 | known_models.push_back(crc_26); 351 | 352 | std::vector crc_27; 353 | known_models.push_back(crc_27); 354 | 355 | std::vector crc_28; 356 | known_models.push_back(crc_28); 357 | 358 | std::vector crc_29; 359 | known_models.push_back(crc_29); 360 | 361 | 362 | std::vector crc_30; 363 | { 364 | // width=30 poly=0x2030b9c7 init=0x3fffffff refin=false refout=false xorout=0x3fffffff check=0x04c34abf name="CRC-30/CDMA" 365 | crc_30.push_back(crc_model_t(0x2030b8c7, 0x3fffffff, 0x3fffffff, false, false, my_crc_basic::AUTO)); 366 | } 367 | known_models.push_back(crc_30); 368 | 369 | std::vector crc_31; 370 | { 371 | // width=31 poly=0x04c11db7 init=0x7fffffff refin=false refout=false xorout=0x7fffffff check=0x0ce9e46c name="CRC-31/PHILIPS" 372 | crc_31.push_back(crc_model_t(0x04c11db7, 0x7fffffff, 0x7fffffff, false, false, my_crc_basic::AUTO)); 373 | } 374 | known_models.push_back(crc_31); 375 | 376 | std::vector crc_32; 377 | { 378 | // width=32 poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926 name="CRC-32" 379 | crc_32.push_back(crc_model_t(0x04c11db7, 0xffffffff, 0xffffffff, true, true, my_crc_basic::AUTO)); 380 | // width=32 poly=0xf4acfb13 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0x1697d06a name="CRC-32/AUTOSAR" 381 | crc_32.push_back(crc_model_t(0xf4acfb13, 0xffffffff, 0xffffffff, true, true, my_crc_basic::AUTO)); 382 | // width=32 poly=0x04c11db7 init=0xffffffff refin=false refout=false xorout=0xffffffff check=0xfc891918 name="CRC-32/BZIP2" 383 | crc_32.push_back(crc_model_t(0x04c11db7, 0xffffffff, 0xffffffff, false, false, my_crc_basic::AUTO)); 384 | // width=32 poly=0x1edc6f41 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xe3069283 name="CRC-32C" 385 | crc_32.push_back(crc_model_t(0x1edc6f31, 0xffffffff, 0xffffffff, true, true, my_crc_basic::AUTO)); 386 | // width=32 poly=0xa833982b init=0xffffffff refin=true refout=true xorout=0xffffffff check=0x87315576 name="CRC-32D" 387 | crc_32.push_back(crc_model_t(0xa833982b, 0xffffffff, 0xffffffff, true, true, my_crc_basic::AUTO)); 388 | // width=32 poly=0x04c11db7 init=0xffffffff refin=false refout=false xorout=0x00000000 check=0x0376e6e7 name="CRC-32/MPEG-2" 389 | crc_32.push_back(crc_model_t(0x04c11db7, 0xffffffff, 0x00000000, false, false, my_crc_basic::AUTO)); 390 | // width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680 name="CRC-32/POSIX" 391 | crc_32.push_back(crc_model_t(0x04c11db7, 0x00000000, 0xffffffff, false, false, my_crc_basic::AUTO)); 392 | // width=32 poly=0x814141ab init=0x00000000 refin=false refout=false xorout=0x00000000 check=0x3010bf7f name="CRC-32Q" 393 | crc_32.push_back(crc_model_t(0x814141ab, 0x00000000, 0x00000000, false, false, my_crc_basic::AUTO)); 394 | // width=32 poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0x00000000 check=0x340bc6d9 name="JAMCRC" 395 | crc_32.push_back(crc_model_t(0x04c11db7, 0xffffffff, 0x00000000, true, true, my_crc_basic::AUTO)); 396 | // width=32 poly=0x000000af init=0x00000000 refin=false refout=false xorout=0x00000000 check=0xbd0be338 name="XFER" 397 | crc_32.push_back(crc_model_t(0x000000af, 0x00000000, 0x00000000, false, false, my_crc_basic::AUTO)); 398 | } 399 | known_models.push_back(crc_32); 400 | 401 | } 402 | 403 | void print_settings(void); 404 | 405 | private: 406 | uint16_t crc_width_; 407 | uint32_t polynomial_; 408 | bool polynomial_range_; 409 | uint32_t polynomial_start_; 410 | uint32_t polynomial_end_; 411 | bool probe_final_xor_; 412 | uint32_t final_xor_; 413 | bool probe_initial_; 414 | uint32_t initial_; 415 | bool probe_reflected_input_; 416 | bool reflected_input_; 417 | bool probe_reflected_output_; 418 | bool reflected_output_; 419 | my_crc_basic::FEED_TYPE feed_type_; 420 | 421 | 422 | uint64_t test_vector_count_; 423 | bool verbose_; 424 | bool quiet_; 425 | 426 | std::vector crc_model_match_; 427 | 428 | public: 429 | void set_crc_width(uint16_t var) { 430 | crc_width_ = var; 431 | update_test_vector_count(); 432 | polynomial_range_ = false; 433 | polynomial_start_ = 0; 434 | polynomial_end_ = max_value(crc_width_); 435 | update_test_vector_count(); 436 | } 437 | uint16_t crc_width() const { return crc_width_; } 438 | void set_polynomial(uint32_t var) { polynomial_ = var; update_test_vector_count(); } 439 | uint32_t polynomial() const { return polynomial_; } 440 | void set_polynomial_range(bool var) { polynomial_range_ = var; set_crc_width(crc_width_); } 441 | bool polynomial_range() const { return polynomial_range_; } 442 | void set_polynomial_start(uint32_t var) { 443 | polynomial_start_ = var; 444 | polynomial_range_ = true; 445 | update_test_vector_count(); 446 | } 447 | uint32_t polynomial_start() const { return polynomial_start_; } 448 | void set_polynomial_end(uint32_t var) { 449 | polynomial_end_ = var; 450 | polynomial_range_ = true; 451 | update_test_vector_count(); 452 | } 453 | uint32_t polynomial_end() const { return polynomial_end_; } 454 | void set_probe_final_xor(bool var) { probe_final_xor_ = var; update_test_vector_count(); } 455 | bool probe_final_xor() const { return probe_final_xor_; } 456 | void set_final_xor(uint32_t var) { final_xor_ = var; } 457 | uint32_t final_xor() const { return final_xor_; } 458 | void set_probe_initial(bool var) { probe_initial_ = var; update_test_vector_count(); } 459 | bool probe_initial() const { return probe_initial_; } 460 | void set_initial(uint32_t var) { initial_ = var; } 461 | uint32_t initial() const { return initial_; } 462 | void set_probe_reflected_input(bool var) { probe_reflected_input_ = var; update_test_vector_count(); } 463 | bool probe_reflected_input() const { return probe_reflected_input_; } 464 | void set_reflected_input(bool var) { reflected_input_ = var; } 465 | bool relfected_input() const { return reflected_input_; } 466 | void set_probe_reflected_output(bool var) { probe_reflected_output_ = var; update_test_vector_count(); } 467 | bool probe_reflected_output() const { return probe_reflected_output_; } 468 | void set_reflected_output(bool var) { reflected_output_ = var; } 469 | bool reflected_output() const { return reflected_output_; } 470 | 471 | my_crc_basic::FEED_TYPE feed_type() const { return feed_type_; } 472 | void set_feed_type(my_crc_basic::FEED_TYPE var) { feed_type_ = var; } 473 | 474 | uint64_t test_vector_count() const { return test_vector_count_; } 475 | void set_verbose(bool var) { verbose_ = var; } 476 | bool verbose() const { return verbose_; } 477 | void set_quiet(bool var) { quiet_ = var; } 478 | bool quiet() const { return quiet_; } 479 | 480 | std::vector crc_model_match() const { return crc_model_match_; } 481 | 482 | private: 483 | 484 | struct timeval start_time; 485 | struct timeval current_time; 486 | 487 | boost::mutex mymutex; 488 | 489 | uint64_t get_delta_time_in_ms(struct timeval const& start); 490 | void show_hit(crc_model_t model, std::vector test_vectors); 491 | std::string show_reflect_output (void); 492 | void print_stats(void); 493 | std::string feed_type_to_str(my_crc_basic::FEED_TYPE feed_type); 494 | 495 | void update_test_vector_count() 496 | { 497 | test_vector_count_ = 0; 498 | 499 | // TODO: Check polynomial range and throw exception if too large 500 | if (polynomial_ > 0) { 501 | test_vector_count_ = 1; 502 | } else if (polynomial_range_) { 503 | test_vector_count_ = (uint64_t)polynomial_end_ - (uint64_t)polynomial_start_; 504 | } else { 505 | test_vector_count_ = (uint64_t)max_value(crc_width_); 506 | } 507 | 508 | if (probe_final_xor_) 509 | test_vector_count_ *= (uint64_t)max_value(crc_width_); 510 | 511 | if (probe_initial_) 512 | test_vector_count_ *= (uint64_t)max_value(crc_width_); 513 | 514 | if (probe_reflected_input_) 515 | test_vector_count_ *= 2; 516 | 517 | if (probe_reflected_output_) 518 | test_vector_count_ *= 2; 519 | 520 | } 521 | 522 | public: 523 | 524 | uint64_t crc_steps; 525 | static int bool_to_int(bool v); 526 | static bool int_to_bool(int v); 527 | static std::string bool_to_str(bool v); 528 | static std::string number_to_str(uint64_t v); 529 | 530 | static boost::dynamic_bitset<> convert_uint8_to_bitset(const uint8_t array[], size_t size); 531 | static boost::dynamic_bitset<> convert_string_to_bitset(std::string str); 532 | 533 | static uint32_t max_value(uint8_t width) { return (uint32_t)(((uint64_t)1 << width) - 1); } 534 | 535 | void set_parameters( uint16_t crc_width, 536 | uint32_t polynomial, 537 | bool probe_final_xor, 538 | uint32_t final_xor, 539 | bool probe_initial, 540 | uint32_t initial, 541 | bool probe_reflected_input, 542 | bool probe_reflected_output, 543 | my_crc_basic::FEED_TYPE feed_type) 544 | { 545 | set_crc_width(crc_width); 546 | set_polynomial(polynomial); 547 | set_probe_final_xor(probe_final_xor); 548 | set_final_xor(final_xor); 549 | set_probe_initial(probe_initial); 550 | set_initial(initial); 551 | set_probe_reflected_input(probe_reflected_input); 552 | set_probe_reflected_output(probe_reflected_output); 553 | set_feed_type(feed_type); 554 | } 555 | 556 | // TODO: This does not need to return anything 557 | bool brute_force( uint32_t search_poly_start, 558 | uint32_t search_poly_end, 559 | std::vector test_vectors); 560 | int do_brute_force(int num_threads, std::vector test_vectors); 561 | 562 | private: 563 | 564 | std::vector< std::vector > known_models; 565 | 566 | }; 567 | 568 | #endif 569 | -------------------------------------------------------------------------------- /tests/test_crc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Test vectors generated from the crc-catalogue: 3 | * http://reveng.sourceforge.net/crc-catalogue/ 4 | * 5 | * Copyright MartynP 2016. 6 | * Distributed under the Boost Software License, Version 1.0. 7 | * (See accompanying file LICENSE_1_0.txt or copy at 8 | * http://www.boost.org/LICENSE_1_0.txt) 9 | */ 10 | 11 | #include 12 | #include 13 | //#include 14 | 15 | #define BOOST_TEST_DYN_LINK 16 | #define BOOST_TEST_MODULE "Test the CRC engine" 17 | #include 18 | 19 | //#define BOOST_CRC 20 | //#define TIMER 21 | 22 | #ifdef TIMER 23 | boost::timer::auto_cpu_timer t; 24 | #endif 25 | 26 | #include "../crc.hpp" 27 | 28 | // For dynamic bitset conversions only 29 | #include "../bf_crc.hpp" 30 | 31 | typedef my_crc_basic crc_t; 32 | uint8_t default_data[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 33 | 34 | uint32_t calculate_crc(uint32_t width, const uint8_t* data, size_t length, uint32_t polynomial, uint32_t initial, uint32_t final_xor, bool reflected_input, bool reflected_output) 35 | { 36 | 37 | #ifdef BOOST_CRC 38 | if (width == 3) { 39 | boost::crc_basic<3> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 40 | crc.process_bytes(data, length); 41 | return crc.checksum(); 42 | } else if (width == 4) { 43 | boost::crc_basic<4> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 44 | crc.process_bytes(data, length); 45 | return crc.checksum(); 46 | } else if (width == 5) { 47 | boost::crc_basic<5> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 48 | crc.process_bytes(data, length); 49 | return crc.checksum(); 50 | } else if (width == 6) { 51 | boost::crc_basic<6> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 52 | crc.process_bytes(data, length); 53 | return crc.checksum(); 54 | } else if (width == 7) { 55 | boost::crc_basic<7> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 56 | crc.process_bytes(data, length); 57 | return crc.checksum(); 58 | } else if (width == 8) { 59 | boost::crc_basic<8> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 60 | crc.process_bytes(data, length); 61 | return crc.checksum(); 62 | } else if (width == 9) { 63 | boost::crc_basic<9> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 64 | crc.process_bytes(data, length); 65 | return crc.checksum(); 66 | } else if (width == 10) { 67 | boost::crc_basic<10> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 68 | crc.process_bytes(data, length); 69 | return crc.checksum(); 70 | } else if (width == 11) { 71 | boost::crc_basic<11> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 72 | crc.process_bytes(data, length); 73 | return crc.checksum(); 74 | } else if (width == 12) { 75 | boost::crc_basic<12> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 76 | crc.process_bytes(data, length); 77 | return crc.checksum(); 78 | } else if (width == 13) { 79 | boost::crc_basic<13> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 80 | crc.process_bytes(data, length); 81 | return crc.checksum(); 82 | } else if (width == 14) { 83 | boost::crc_basic<14> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 84 | crc.process_bytes(data, length); 85 | return crc.checksum(); 86 | } else if (width == 15) { 87 | boost::crc_basic<15> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 88 | crc.process_bytes(data, length); 89 | return crc.checksum(); 90 | } else if (width == 16) { 91 | boost::crc_basic<16> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 92 | crc.process_bytes(data, length); 93 | return crc.checksum(); 94 | } else if (width == 17) { 95 | boost::crc_basic<17> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 96 | crc.process_bytes(data, length); 97 | return crc.checksum(); 98 | } else if (width == 32) { 99 | boost::crc_basic<32> crc(polynomial, initial, final_xor, reflected_input, reflected_output); 100 | crc.process_bytes(data, length); 101 | return crc.checksum(); 102 | } else { 103 | assert(false); 104 | return -1; 105 | } 106 | #else 107 | crc_t crc(width); 108 | boost::dynamic_bitset<> msg = bf_crc::convert_uint8_to_bitset(data, length); 109 | 110 | crc.set(polynomial, initial, final_xor, reflected_input, reflected_output); 111 | crc.calc_crc(initial, msg); 112 | return crc.checksum(); 113 | #endif 114 | 115 | } 116 | 117 | uint32_t calculate_crc(uint32_t crc_width, std::string data, uint32_t polynomial, uint32_t initial, uint32_t final_xor, bool reflected_input, bool reflected_output) 118 | { 119 | crc_t crc(crc_width); 120 | boost::dynamic_bitset<> msg = bf_crc::convert_string_to_bitset(data); 121 | 122 | crc.set(polynomial, initial, final_xor, reflected_input, reflected_output); 123 | crc.calc_crc(initial, msg); 124 | return crc.checksum(); 125 | } 126 | 127 | /* 128 | * Test 3-bit CRC's from reveng.sourceforge.net 129 | * 1 Example 130 | * 14/09/2016 131 | */ 132 | BOOST_AUTO_TEST_CASE(crcThree) { 133 | 134 | #ifdef TIMER 135 | boost::timer::auto_cpu_timer t; 136 | #endif 137 | 138 | // 3 bit CRC's 139 | uint8_t crc_width = 3; 140 | crc_t crc(crc_width); 141 | uint32_t calculated_crc; 142 | 143 | /* 144 | * CRC-3/ROHC 145 | * width=3 poly=0x3 init=0x7 refin=true refout=true xorout=0x0 check=0x6 name="CRC-3/ROHC" 146 | */ 147 | calculated_crc = calculate_crc(crc_width, default_data, sizeof(default_data), 0x3, 0x7, 0x0, true, true); 148 | BOOST_CHECK(calculated_crc == 0x6); 149 | } 150 | 151 | /* 152 | * Test 4-bit CRC's from reveng.sourceforge.net 153 | * 2 Examples 154 | * 14/09/2016 155 | */ 156 | BOOST_AUTO_TEST_CASE(crcFour) { 157 | 158 | #ifdef TIMER 159 | boost::timer::auto_cpu_timer t; 160 | #endif 161 | 162 | // 4 bit CRC's 163 | uint8_t crc_width = 4; 164 | crc_t crc(crc_width); 165 | uint32_t calculated_crc; 166 | 167 | /* 168 | * CRC-4/INTERLAKEN 169 | * width=4 poly=0x3 init=0xf refin=false refout=false xorout=0xf check=0xb name="CRC-4/INTERLAKEN" 170 | */ 171 | calculated_crc = calculate_crc(crc_width, default_data, sizeof(default_data), 0x3, 0xF, 0xF, false, false); 172 | BOOST_CHECK(calculated_crc == 0xB); 173 | 174 | /* 175 | * CRC-4/ITU 176 | * width=4 poly=0x3 init=0x0 refin=true refout=true xorout=0x0 check=0x7 name="CRC-4/ITU" 177 | */ 178 | calculated_crc = calculate_crc(crc_width, default_data, sizeof(default_data), 0x3, 0x0, 0x0, true, true); 179 | BOOST_CHECK(calculated_crc == 0x7); 180 | 181 | } 182 | 183 | /* 184 | * Test 5-bit CRC's from reveng.sourceforge.net 185 | * 3 Examples 186 | * 14/09/2016 187 | */ 188 | BOOST_AUTO_TEST_CASE(crcFive) { 189 | 190 | #ifdef TIMER 191 | boost::timer::auto_cpu_timer t; 192 | #endif 193 | 194 | // 5 bit CRC's 195 | uint8_t crc_width = 5; 196 | crc_t crc(crc_width); 197 | uint32_t calculated_crc; 198 | 199 | /* 200 | * CRC-5/EPC 201 | * width=5 poly=0x09 init=0x09 refin=false refout=false xorout=0x00 check=0x00 name="CRC-5/EPC" 202 | */ 203 | 204 | // REVENG Test Check 205 | calculated_crc = calculate_crc(crc_width, default_data, sizeof(default_data), 0x9, 0x9, 0x0, false, false); 206 | BOOST_CHECK(calculated_crc == 0x00); 207 | 208 | // High Security FeRAM-Based EPC C2G2 UHF (https://etrij.etri.re.kr/etrij/journal/getPublishedPaperFile.do?fileId=SPF-1228283393442) 209 | calculated_crc = calculate_crc(crc_width, "10001001000000100", 0x9, 0x9, 0x0, false, false); 210 | BOOST_CHECK(calculated_crc == 0x06); 211 | 212 | // Computer Interfacing Forum (topic 1330, non authoritiative) 213 | calculated_crc = calculate_crc(crc_width, "10000001000000000", 0x9, 0x9, 0x0, false, false); 214 | BOOST_CHECK(calculated_crc == 0x13); 215 | 216 | /* 217 | * CRC-5/ITU 218 | * width=5 poly=0x15 init=0x00 refin=true refout=true xorout=0x00 check=0x07 name="CRC-5/ITU" 219 | */ 220 | 221 | // REVENG Test Check 222 | uint8_t data_2_0[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 223 | calculated_crc = calculate_crc(crc_width, data_2_0, 9, 0x15, 0x0, 0x0, true, true); 224 | BOOST_CHECK(calculated_crc == 0x07); 225 | 226 | /* 227 | * CRC-5/USB 228 | * width=5 poly=0x05 init=0x1f refin=true refout=true xorout=0x1f check=0x19 name="CRC-5/USB" 229 | */ 230 | 231 | // REVENG Test Check 232 | uint8_t data_3_0[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 233 | calculated_crc = calculate_crc(crc_width, data_3_0, 9, 0x05, 0x1F, 0x1F, true, true); 234 | BOOST_CHECK(calculated_crc == 0x019); 235 | 236 | // Darft Implementation 1 TODO: These test cases do not match the exemplar / description 237 | calculated_crc = calculate_crc(crc_width, "10101000111", 0x05, 0x1F, 0x1F, false, false); 238 | BOOST_CHECK(calculated_crc == 0x017); 239 | 240 | // Darft Implementation 2 241 | calculated_crc = calculate_crc(crc_width, "01011100101", 0x05, 0x1F, 0x1F, false, false); 242 | BOOST_CHECK(calculated_crc == 0x01C); 243 | 244 | // Darft Implementation 3 245 | calculated_crc = calculate_crc(crc_width, "00001110010", 0x05, 0x1F, 0x1F, false, false); 246 | BOOST_CHECK(calculated_crc == 0x00E); 247 | 248 | // Darft Implementation 4 249 | calculated_crc = calculate_crc(crc_width, "10000000000", 0x05, 0x1F, 0x1F, false, false); 250 | BOOST_CHECK(calculated_crc == 0x017); 251 | 252 | } 253 | 254 | /* 255 | * Test 6-bit CRC's from reveng.sourceforge.net 256 | * 4 Examples 257 | * 14/06/2016 258 | */ 259 | BOOST_AUTO_TEST_CASE(crcSix) { 260 | 261 | #ifdef TIMER 262 | boost::timer::auto_cpu_timer t; 263 | #endif 264 | 265 | // 6 bit CRC's 266 | uint8_t crc_width = 6; 267 | crc_t crc(crc_width); 268 | uint32_t calculated_crc; 269 | 270 | /* 271 | * CRC-6/CDMA2000-A 272 | * width=6 poly=0x27 init=0x3f refin=false refout=false xorout=0x00 check=0x0d name="CRC-6/CDMA2000-A" 273 | */ 274 | 275 | // REVENG Test Check 276 | calculated_crc = calculate_crc(crc_width, default_data, sizeof(default_data), 0x27, 0x3F, 0x00, false, false); 277 | BOOST_CHECK(calculated_crc == 0x0D); 278 | 279 | // Test 1 - https://www.lammertbies.nl/forum/viewtopic.php?t=1702 280 | // 0xC101002E - 26 bits data, 6 bits CRC 281 | calculated_crc = calculate_crc(crc_width, "11000001000000010000000000", 0x27, 0x3F, 0x00, false, false); 282 | BOOST_CHECK(calculated_crc == 0x2E); 283 | 284 | // Test 2 - https://www.lammertbies.nl/forum/viewtopic.php?t=1702 285 | // 0x0110000F - 26 bits data, 6 bits CRC 286 | calculated_crc = calculate_crc(crc_width, "00000001000100000000000000", 0x27, 0x3F, 0x00, false, false); 287 | BOOST_CHECK(calculated_crc == 0x0F); 288 | 289 | // Test 3 - https://www.lammertbies.nl/forum/viewtopic.php?t=1702 290 | // 0x05100009 - 26 bits data, 6 bits CRC 291 | calculated_crc = calculate_crc(crc_width, "00000101000100000000000000", 0x27, 0x3F, 0x00, false, false); 292 | BOOST_CHECK(calculated_crc == 0x09); 293 | 294 | /* 295 | * CRC-6/CDMA2000-B 296 | * width=6 poly=0x07 init=0x3f refin=false refout=false xorout=0x00 check=0x3b name="CRC-6/CDMA2000-B" 297 | */ 298 | 299 | // REVENG Test Check 300 | calculated_crc = calculate_crc(crc_width, default_data, sizeof(default_data), 0x7, 0x3F, 0x0, false, false); 301 | BOOST_CHECK(calculated_crc == 0x3B); 302 | 303 | /* 304 | * CRC-6/DARC 305 | * width=6 poly=0x19 init=0x00 refin=true refout=true xorout=0x00 check=0x26 name="CRC-6/DARC" 306 | */ 307 | 308 | // REVENG Test Check 309 | calculated_crc = calculate_crc(crc_width, default_data, sizeof(default_data), 0x19, 0x00, 0x00, true, true); 310 | BOOST_CHECK(calculated_crc == 0x26); 311 | 312 | // ETSI EN 300 751 313 | // Test Vector 1 => 1001010011000100, bits are transmitted LSB first (lsb is leftmost in this example) 314 | // Data: LSB 100100011 MSB 315 | // CRC: LSB 000100 MSB 316 | // Data and CRC are fed in lsb first, however the definitition stated reflected input and output 317 | // Data and CRC should be reversed for the check in order to work 318 | /* 319 | = CAB8 320 | 00001100010000000010000000101101 = 300204B4*/ 321 | 322 | calculated_crc = calculate_crc(crc_width, "1100101001", 0x19, 0x00, 0x00, true, true); 323 | BOOST_CHECK(calculated_crc == 0x08); 324 | 325 | // ETSI EN 300 751 326 | // Test Vector 2 => 0101001100 011101 327 | // Reversed: 0011001010 101110 328 | calculated_crc = calculate_crc(crc_width, "0011001010", 0x19, 0x00, 0x00, true, true); 329 | BOOST_CHECK(calculated_crc == 0x2E); 330 | 331 | // ETSI EN 300 751 332 | // Test Vector 3 => 00001100010000000010000000 101101 333 | // Reversed: 00000001000000001000110000 101101 334 | // TODO: This one does not work... 335 | /* 336 | calculated_crc = calculate_crc(crc_width, "00001100010000000010000000", 0x19, 0x00, 0x00, false, false); 337 | std::cout << std::hex << calculated_crc <