diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | grc/CMakeLists.txt | 24 | ||||
-rw-r--r-- | grc/decoding/CMakeLists.txt | 22 | ||||
-rw-r--r-- | grc/decryption/CMakeLists.txt | 22 | ||||
-rw-r--r-- | grc/decryption/gsm_decryption.xml | 23 | ||||
-rw-r--r-- | grc/demapping/CMakeLists.txt | 23 | ||||
-rw-r--r-- | grc/gsm_block_tree.xml | 4 | ||||
-rw-r--r-- | grc/misc_utils/CMakeLists.txt | 26 | ||||
-rw-r--r-- | grc/receiver/CMakeLists.txt | 27 | ||||
-rw-r--r-- | include/CMakeLists.txt | 20 | ||||
-rw-r--r-- | include/grgsm/CMakeLists.txt | 4 | ||||
-rw-r--r-- | include/grgsm/decryption/CMakeLists.txt (renamed from include/plotting/CMakeLists.txt) | 2 | ||||
-rw-r--r-- | include/grgsm/decryption/decryption.h | 60 | ||||
-rw-r--r-- | include/grgsm/plotting.hpp (renamed from include/plotting/plotting.hpp) | 0 | ||||
-rw-r--r-- | lib/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/decryption/a5_1_2.h | 385 | ||||
-rw-r--r-- | lib/decryption/decryption_impl.cc | 138 | ||||
-rw-r--r-- | lib/decryption/decryption_impl.h | 43 | ||||
-rw-r--r-- | python/CMakeLists.txt | 2 | ||||
-rwxr-xr-x | python/qa_decryption.py | 43 | ||||
-rw-r--r-- | swig/grgsm_swig.i | 6 |
21 files changed, 858 insertions, 22 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e1a75d..c6abc58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,8 +151,7 @@ add_custom_target(uninstall ######################################################################## # Add subdirectories ######################################################################## -add_subdirectory(include/grgsm) -add_subdirectory(include/plotting) +add_subdirectory(include) add_subdirectory(lib) add_subdirectory(swig) add_subdirectory(python) diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index d1628cc..0baaac8 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -16,21 +16,13 @@ # along with GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. + +add_subdirectory(decoding) +add_subdirectory(decryption) +add_subdirectory(demapping) +add_subdirectory(receiver) +add_subdirectory(misc_utils) + install(FILES - gsm_block_tree.xml - receiver/gsm_input.xml - receiver/gsm_receiver.xml - misc_utils/gsm_bursts_printer.xml - receiver/gsm_fcch_burst_tagger.xml - receiver/gsm_sch_detector.xml - receiver/gsm_fcch_detector.xml - demapping/gsm_get_bcch_or_ccch_bursts.xml - demapping/gsm_universal_ctrl_chans_demapper.xml - decoding/gsm_control_channels_decoder.xml - misc_utils/gsm_extract_system_info.xml - misc_utils/gsm_controlled_rotator_cc.xml - misc_utils/gsm_controlled_const_source_f.xml - receiver/gsm_clock_offset_control.xml - misc_utils/gsm_message_printer.xml - misc_utils/gsm_clock_offset_corrector.xml DESTINATION share/gnuradio/grc/blocks + gsm_block_tree.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/decoding/CMakeLists.txt b/grc/decoding/CMakeLists.txt new file mode 100644 index 0000000..36820f3 --- /dev/null +++ b/grc/decoding/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + gsm_control_channels_decoder.xml DESTINATION share/gnuradio/grc/blocks +) diff --git a/grc/decryption/CMakeLists.txt b/grc/decryption/CMakeLists.txt new file mode 100644 index 0000000..29d86f4 --- /dev/null +++ b/grc/decryption/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + gsm_decryption.xml DESTINATION share/gnuradio/grc/blocks +) diff --git a/grc/decryption/gsm_decryption.xml b/grc/decryption/gsm_decryption.xml new file mode 100644 index 0000000..28a2b93 --- /dev/null +++ b/grc/decryption/gsm_decryption.xml @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<block> + <name>Decryption</name> + <key>gsm_decryption</key> + <import>import grgsm</import> + <make>grgsm.decryption($k_c)</make> + + <param> + <name>Kc session key</name> + <key>k_c</key> + <type>int_vector</type> + </param> + + <sink> + <name>bursts</name> + <type>message</type> + </sink> + <source> + <name>bursts</name> + <type>message</type> + </source> + +</block> diff --git a/grc/demapping/CMakeLists.txt b/grc/demapping/CMakeLists.txt new file mode 100644 index 0000000..a057d19 --- /dev/null +++ b/grc/demapping/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + gsm_get_bcch_or_ccch_bursts.xml + gsm_universal_ctrl_chans_demapper.xml DESTINATION share/gnuradio/grc/blocks +) diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index df463b2..d080175 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -25,6 +25,10 @@ <block>gsm_universal_ctrl_chans_demapper</block> </cat> <cat> + <name>Decryption</name> + <block>gsm_decryption</block> + </cat> + <cat> <name>Decoding</name> <block>gsm_control_channels_decoder</block> </cat> diff --git a/grc/misc_utils/CMakeLists.txt b/grc/misc_utils/CMakeLists.txt new file mode 100644 index 0000000..48e8cae --- /dev/null +++ b/grc/misc_utils/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + gsm_extract_system_info.xml + gsm_controlled_rotator_cc.xml + gsm_controlled_const_source_f.xml + gsm_message_printer.xml + gsm_clock_offset_corrector.xml DESTINATION share/gnuradio/grc/blocks +) diff --git a/grc/receiver/CMakeLists.txt b/grc/receiver/CMakeLists.txt new file mode 100644 index 0000000..25f08cc --- /dev/null +++ b/grc/receiver/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + gsm_input.xml + gsm_receiver.xml + gsm_fcch_burst_tagger.xml + gsm_sch_detector.xml + gsm_fcch_detector.xml + gsm_clock_offset_control.xml DESTINATION share/gnuradio/grc/blocks +) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..a7c18dd --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +add_subdirectory(grgsm) diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index 292431f..6df01d7 100644 --- a/include/grgsm/CMakeLists.txt +++ b/include/grgsm/CMakeLists.txt @@ -20,12 +20,14 @@ ######################################################################## # Install public header files ######################################################################## -add_subdirectory(misc_utils) add_subdirectory(decoding) +add_subdirectory(decryption) add_subdirectory(demapping) add_subdirectory(receiver) +add_subdirectory(misc_utils) install(FILES + plotting.hpp api.h gsmtap.h DESTINATION include/grgsm ) diff --git a/include/plotting/CMakeLists.txt b/include/grgsm/decryption/CMakeLists.txt index 569c462..3a0c6b6 100644 --- a/include/plotting/CMakeLists.txt +++ b/include/grgsm/decryption/CMakeLists.txt @@ -21,5 +21,5 @@ # Install public header files ######################################################################## install(FILES - plotting.hpp DESTINATION include/plotting + decryption.h DESTINATION include/grgsm/decoding ) diff --git a/include/grgsm/decryption/decryption.h b/include/grgsm/decryption/decryption.h new file mode 100644 index 0000000..96d3eca --- /dev/null +++ b/include/grgsm/decryption/decryption.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * @file + * @author Piotr Krysik <ptrkrysik@gmail.com> + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + + +#ifndef INCLUDED_GSM_DECRYPTION_H +#define INCLUDED_GSM_DECRYPTION_H + +#include <grgsm/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace gsm { + + /*! + * \brief <+description of block+> + * \ingroup gsm + * + */ + class GSM_API decryption : virtual public gr::block + { + public: + typedef boost::shared_ptr<decryption> sptr; + + /*! + * \brief Return a shared_ptr to a new instance of gsm::decryption. + * + * To avoid accidental use of raw pointers, gsm::decryption's + * constructor is in a private implementation + * class. gsm::decryption::make is the public interface for + * creating new instances. + */ + static sptr make(const std::vector<uint8_t> & k_c); + virtual void set_k_c(const std::vector<uint8_t> & k_c) = 0; + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_DECRYPTION_H */ + diff --git a/include/plotting/plotting.hpp b/include/grgsm/plotting.hpp index ff37fec..ff37fec 100644 --- a/include/plotting/plotting.hpp +++ b/include/grgsm/plotting.hpp diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ef29d6c..d4f04d8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -22,7 +22,7 @@ ######################################################################## include(GrPlatform) #define LIB_SUFFIX -include_directories(${Boost_INCLUDE_DIR} receiver burst_printer) +include_directories(${Boost_INCLUDE_DIR} receiver) link_directories(${Boost_LIBRARY_DIRS}) list(APPEND gsm_sources receiver/receiver_impl.cc @@ -39,6 +39,7 @@ list(APPEND gsm_sources misc_utils/controlled_rotator_cc_impl.cc misc_utils/controlled_const_source_f_impl.cc misc_utils/message_printer_impl.cc + decryption/decryption_impl.cc ) add_library(gnuradio-gsm SHARED ${gsm_sources}) diff --git a/lib/decryption/a5_1_2.h b/lib/decryption/a5_1_2.h new file mode 100644 index 0000000..fb87498 --- /dev/null +++ b/lib/decryption/a5_1_2.h @@ -0,0 +1,385 @@ +/* + * A pedagogical implementation of the GSM A5/1 and A5/2 "voice privacy" + * encryption algorithms. + * + * Copyright (C) 1998-1999: Marc Briceno, Ian Goldberg, and David Wagner + * + * The source code below is optimized for instructional value and clarity. + * Performance will be terrible, but that's not the point. + * + * This software may be export-controlled by US law. + * + * This software is free for commercial and non-commercial use as long as + * the following conditions are adhered to. + * Copyright remains the authors' and as such any Copyright notices in + * the code are not to be removed. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The license and distribution terms for any publicly available version + * or derivative of this code cannot be changed. i.e. this code cannot + * simply be copied and put under another distribution license + * [including the GNU Public License]. + * + * Background: The Global System for Mobile communications is the most + * widely deployed digital cellular telephony system in the world. GSM + * makes use of four core cryptographic algorithms, none of which has + * been published by the GSM MOU. This failure to subject the + * algorithms to public review is all the more puzzling given that over + * 215 million GSM subscribers are expected to rely on the claimed + * security of the system. + * + * The four core GSM cryptographic algorithms are: + * A3 authentication algorithm + * A5/1 "stronger" over-the-air voice-privacy algorithm + * A5/2 "weaker" over-the-air voice-privacy algorithm + * A8 voice-privacy key generation algorithm + * + * In April of 1998, our group showed that COMP128, the algorithm used by the + * overwhelming majority of GSM providers for both A3 and A8 functionality + * is fatally flawed and allows for cloning of GSM mobile phones. + * + * Furthermore, we demonstrated that all A8 implementations we could locate, + * including the few that did not use COMP128 for key generation, had been + * deliberately weakened by reducing the keyspace from 64 bits to 54 bits. + * The remaining 10 bits are simply set to zero! + * + * See http://www.scard.org/gsm for additional information. + * + * [May 1999] + * One question so far unanswered is if A5/1, the "stronger" of the two + * widely deployed voice-privacy algorithm is at least as strong as the + * key. Meaning: "Does A5/1 have a work factor of at least 54 bits"? + * Absent a publicly available A5/1 reference implementation, this question + * could not be answered. We hope that our reference implementation below, + * which has been verified against official A5/1 test vectors, will provide + * the cryptographic community with the base on which to construct the + * answer to this important question. + * + * Initial indications about the strength of A5/1 are not encouraging. + * A variant of A5, while not A5/1 itself, has been estimated to have a + * work factor of well below 54 bits. See http://jya.com/crack-a5.htm for + * background information and references. + * + * With COMP128 broken and A5/1 published below, we will now turn our + * attention to A5/2. + * + * [August 1999] + * 19th Annual International Cryptology Conference - Crypto'99 + * Santa Barbara, California + * + * A5/2 has been added to the previously published A5/1 source. Our + * implementation has been verified against official test vectors. + * + * This means that our group has now reverse engineered the entire set + * of cryptographic algorithms used in the overwhelming majority of GSM + * installations, including all the over-the-air "voice privacy" algorithms. + * + * The "voice privacy" algorithm A5/2 proved especially weak. Which perhaps + * should come as no surprise, since even GSM MOU members have admitted that + * A5/2 was designed with heavy input by intelligence agencies to ensure + * breakability. Just how insecure is A5/2? It can be broken in real time + * with a work factor of a mere 16 bits. GSM might just as well use no "voice + * privacy" algorithm at all. + * + * We announced the break of A5/2 at the Crypto'99 Rump Session. + * Details will be published in a scientific paper following soon. + * + * + * -- Marc Briceno <marc@scard.org> + * Voice: +1 (925) 798-4042 + * + */ + +#ifndef A5_1_2_H +#define A5_1_2_H + +#include <stdio.h> + + +/* Masks for the shift registers */ +#define R1MASK 0x07FFFF /* 19 bits, numbered 0..18 */ +#define R2MASK 0x3FFFFF /* 22 bits, numbered 0..21 */ +#define R3MASK 0x7FFFFF /* 23 bits, numbered 0..22 */ +#ifdef A5_2 +#define R4MASK 0x01FFFF /* 17 bits, numbered 0..16 */ +#endif /* A5_2 */ + + +#ifndef A5_2 +/* Middle bit of each of the three shift registers, for clock control */ +#define R1MID 0x000100 /* bit 8 */ +#define R2MID 0x000400 /* bit 10 */ +#define R3MID 0x000400 /* bit 10 */ +#else /* A5_2 */ +/* A bit of R4 that controls each of the shift registers */ +#define R4TAP1 0x000400 /* bit 10 */ +#define R4TAP2 0x000008 /* bit 3 */ +#define R4TAP3 0x000080 /* bit 7 */ +#endif /* A5_2 */ + + +/* Feedback taps, for clocking the shift registers. + * These correspond to the primitive polynomials + * x^19 + x^5 + x^2 + x + 1, x^22 + x + 1, + * x^23 + x^15 + x^2 + x + 1, and x^17 + x^5 + 1. */ + + +#define R1TAPS 0x072000 /* bits 18,17,16,13 */ +#define R2TAPS 0x300000 /* bits 21,20 */ +#define R3TAPS 0x700080 /* bits 22,21,20,7 */ +#ifdef A5_2 +#define R4TAPS 0x010800 /* bits 16,11 */ +#endif /* A5_2 */ + + +typedef unsigned char byte; +typedef unsigned long word; +typedef word bit; + + +/* Calculate the parity of a 32-bit word, i.e. the sum of its bits modulo 2 +*/ +bit parity(word x) +{ + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + x ^= x >> 2; + x ^= x >> 1; + return x&1; +} + + +/* Clock one shift register. For A5/2, when the last bit of the frame + * is loaded in, one particular bit of each register is forced to '1'; + * that bit is passed in as the last argument. */ +#ifndef A5_2 +word clockone(word reg, word mask, word taps) +{ +#else /* A5_2 */ +word clockone(word reg, word mask, word taps, word loaded_bit) { +#endif /* A5_2 */ + word t = reg & taps; + reg = (reg << 1) & mask; + reg |= parity(t); +#ifdef A5_2 + reg |= loaded_bit; +#endif /* A5_2 */ + return reg; +} + + +/* The three shift registers. They're in global variables to make the code + * easier to understand. + * A better implementation would not use global variables. */ +word R1, R2, R3; +#ifdef A5_2 +word R4; +#endif /* A5_2 */ + + +/* Return 1 iff at least two of the parameter words are non-zero. */ +bit majority(word w1, word w2, word w3) { + int sum = (w1 != 0) + (w2 != 0) + (w3 != 0); + if (sum >= 2) + return 1; + else + return 0; +} + + +/* Clock two or three of R1,R2,R3, with clock control + * according to their middle bits. + * Specifically, we clock Ri whenever Ri's middle bit + * agrees with the majority value of the three middle bits. For A5/2, + * use particular bits of R4 instead of the middle bits. Also, for A5/2, + * always clock R4. + * If allP == 1, clock all three of R1,R2,R3, ignoring their middle bits. + * This is only used for key setup. If loaded == 1, then this is the last + * bit of the frame number, and if we're doing A5/2, we have to set a + * particular bit in each of the four registers. */ +void clock(int allP, int loaded) { +#ifndef A5_2 + bit maj = majority(R1 & R1MID, R2 & R2MID, R3 & R3MID); + if (allP || (((R1&R1MID) != 0) == maj)) + R1 = clockone(R1, R1MASK, R1TAPS); + if (allP || (((R2&R2MID) != 0) == maj)) + R2 = clockone(R2, R2MASK, R2TAPS); + if (allP || (((R3&R3MID) != 0) == maj)) + R3 = clockone(R3, R3MASK, R3TAPS); +#else /* A5_2 */ + bit maj = majority(R4 & R4TAP1, R4 & R4TAP2, R4 & R4TAP3); + if (allP || (((R4&R4TAP1) != 0) == maj)) + R1 = clockone(R1, R1MASK, R1TAPS, loaded << 15); + if (allP || (((R4&R4TAP2) != 0) == maj)) + R2 = clockone(R2, R2MASK, R2TAPS, loaded << 16); + if (allP || (((R4&R4TAP3) != 0) == maj)) + R3 = clockone(R3, R3MASK, R3TAPS, loaded << 18); + R4 = clockone(R4, R4MASK, R4TAPS, loaded << 10); +#endif /* A5_2 */ +} + + +/* Generate an output bit from the current state. + * You grab a bit from each register via the output generation taps; + * then you XOR the resulting three bits. For A5/2, in addition to + * the top bit of each of R1,R2,R3, also XOR in a majority function + * of three particular bits of the register (one of them complemented) + * to make it non-linear. Also, for A5/2, delay the output by one + * clock cycle for some reason. */ +bit getbit() { + bit topbits = (((R1 >> 18) ^ (R2 >> 21) ^ (R3 >> 22)) & 0x01); +#ifndef A5_2 + return topbits; +#else /* A5_2 */ + static bit delaybit = 0; + bit nowbit = delaybit; + delaybit = ( + topbits + ^ majority(R1 & 0x8000, (~R1) & 0x4000, R1 & 0x1000) + ^ majority((~R2) & 0x10000, R2 & 0x2000, R2 & 0x200) + ^ majority(R3 & 0x40000, R3 & 0x10000, (~R3) & 0x2000) + ); + return nowbit; +#endif /* A5_2 */ +} + + +/* Do the A5 key setup. This routine accepts a 64-bit key and + * a 22-bit frame number. */ +void keysetup(byte key_reversed[8], word frame) { + int i; + bit keybit, framebit; + + byte key[8]; + for(i=0; i<8; i++){ + key[i] = key_reversed[7-i]; + } + /* Zero out the shift registers. */ + R1 = R2 = R3 = 0; +#ifdef A5_2 + R4 = 0; +#endif /* A5_2 */ + + + /* Load the key into the shift registers, + * LSB of first byte of key array first, + * clocking each register once for every + * key bit loaded. (The usual clock + * control rule is temporarily disabled.) */ + for (i = 0; i < 64; i++) { + clock(1, 0); /* always clock */ + keybit = (key[i/8] >> (i & 7)) & 1; /* The i-th bit of the key */ + R1 ^= keybit; + R2 ^= keybit; + R3 ^= keybit; +#ifdef A5_2 + R4 ^= keybit; +#endif /* A5_2 */ + } + + + /* Load the frame number into the shift registers, LSB first, + * clocking each register once for every key bit loaded. + * (The usual clock control rule is still disabled.) + * For A5/2, signal when the last bit is being clocked in. */ + for (i = 0; i < 22; i++) { + clock(1, i == 21); /* always clock */ + framebit = (frame >> i) & 1; /* The i-th bit of the frame # */ + R1 ^= framebit; + R2 ^= framebit; + R3 ^= framebit; +#ifdef A5_2 + R4 ^= framebit; +#endif /* A5_2 */ + } + + + /* Run the shift registers for 100 clocks + * to mix the keying material and frame number + * together with output generation disabled, + * so that there is sufficient avalanche. + * We re-enable the majority-based clock control + * rule from now on. */ + for (i = 0; i < 100; i++) { + clock(0, 0); + } + /* For A5/2, we have to load the delayed output bit. This does _not_ + * change the state of the registers. For A5/1, this is a no-op. */ + getbit(); + + + /* Now the key is properly set up. */ +} + + +/* Generate output. We generate 228 bits of + * keystream output. The first 114 bits is for + * the A->B frame; the next 114 bits is for the + * B->A frame. You allocate a 15-byte buffer + * for each direction, and this function fills + * it in. */ +void run(byte AtoBkeystream[], byte BtoAkeystream[]) { + int i; + + + /* Zero out the output buffers. */ + for (i = 0; i <= 113 / 8; i++) + AtoBkeystream[i] = BtoAkeystream[i] = 0; + + + /* Generate 114 bits of keystream for the + * A->B direction. Store it, MSB first. */ + for (i = 0; i < 114; i++) { + clock(0, 0); + AtoBkeystream[i/8] |= getbit() << (7 - (i & 7)); + } + + + /* Generate 114 bits of keystream for the + * B->A direction. Store it, MSB first. */ + for (i = 0; i < 114; i++) { + clock(0, 0); + BtoAkeystream[i/8] |= getbit() << (7 - (i & 7)); + } +} + +void runA51(unsigned char AtoBkeystream[]) { + int i; + + /* Zero out the output buffers. */ + for (i = 0; i < 114; i++) + AtoBkeystream[i] = 0; + + + /* Generate 114 bits of keystream for the + * A->B direction. Store it, MSB first. */ + for (i = 0; i < 114; i++) { + clock(0, 0); + AtoBkeystream[i] = getbit(); + } +} + + + +#endif /* A5_1_2_H */ diff --git a/lib/decryption/decryption_impl.cc b/lib/decryption/decryption_impl.cc new file mode 100644 index 0000000..4347b62 --- /dev/null +++ b/lib/decryption/decryption_impl.cc @@ -0,0 +1,138 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 <+YOU OR YOUR COMPANY+>. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include <grgsm/endian.h> +#include <grgsm/gsmtap.h> +#include "decryption_impl.h" +#include "a5_1_2.h" + +const uint32_t BURST_SIZE=148; + +namespace gr { + namespace gsm { + + decryption::sptr + decryption::make(const std::vector<uint8_t> & k_c) + { + return gnuradio::get_initial_sptr + (new decryption_impl(k_c)); + } + + /* + * The private constructor + */ + decryption_impl::decryption_impl(const std::vector<uint8_t> & k_c) + : gr::block("decryption", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + set_k_c(k_c); + +// std::cout << "Be careful with decryption block - it wasn't tested yet!" << std::endl; + message_port_register_in(pmt::mp("bursts")); + set_msg_handler(pmt::mp("bursts"), boost::bind(&decryption_impl::decrypt, this, _1)); + message_port_register_out(pmt::mp("bursts")); + } + + /* + * Virtual destructor + */ + decryption_impl::~decryption_impl() + { + } + + void decryption_impl::set_k_c(const std::vector<uint8_t> & k_c) + { + d_k_c = k_c; + } + + void decryption_impl::decrypt(pmt::pmt_t msg) + { + if(d_k_c.size() != 8){ + message_port_pub(pmt::mp("bursts"), msg); + } else + if(d_k_c[0] == 0 && d_k_c[1] == 0 && d_k_c[2] == 0 && d_k_c[3] == 0 & + d_k_c[4] == 0 && d_k_c[5] == 0 && d_k_c[6] == 0 && d_k_c[7] == 0) + { + message_port_pub(pmt::mp("bursts"), msg); + } else + { + uint8_t decrypted_data[BURST_SIZE]; + uint8_t AtoBkeystream[15]; + uint8_t BtoAkeystream[15]; + uint8_t * keystream; + + pmt::pmt_t header_plus_burst = pmt::cdr(msg); + gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst); + uint8_t * burst_binary = (uint8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr); + + uint32_t frame_number = be32toh(header->frame_number) & 0x3fff; + bool uplink_burst = (be32toh(header->frame_number) & 0x4000) ? true : false; + uint32_t t1 = frame_number / (26*51); + uint32_t t2 = frame_number % 26; + uint32_t t3 = frame_number % 51; + uint32_t frame_number_mod = (t1 << 11) + (t3 << 5) + t2; + keysetup(&d_k_c[0], frame_number_mod); + run(AtoBkeystream, BtoAkeystream); + + if(uplink_burst){ + //process uplink burst + keystream = BtoAkeystream; + } else { + //process downlink burst + keystream = AtoBkeystream; + } + /* guard bits */ + for (int i = 0; i < 3; i++) { + decrypted_data[i] = burst_binary[i]; + } + for (int i = 0; i < 57; i++) { + decrypted_data[i+3] = keystream[i] ^ burst_binary[i+3]; + } + /* stealing bits and midamble */ + for (int i = 60; i < 88; i++) { + decrypted_data[i] = burst_binary[i]; + } + for (int i = 0; i < 57; i++) { + decrypted_data[i+88] = keystream[i+57] ^ burst_binary[i+88]; + } + /* guard bits */ + for (int i = 145; i < 148; i++) { + decrypted_data[i] = burst_binary[i]; + } + uint8_t new_header_plus_burst[sizeof(gsmtap_hdr)+BURST_SIZE]; + memcpy(new_header_plus_burst, header, sizeof(gsmtap_hdr)); + memcpy(new_header_plus_burst+sizeof(gsmtap_hdr), decrypted_data, BURST_SIZE); + + pmt::pmt_t msg_binary_blob = pmt::make_blob(new_header_plus_burst, sizeof(gsmtap_hdr)+BURST_SIZE); + pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob); + + message_port_pub(pmt::mp("bursts"), msg_out); + } + return; + } + } /* namespace gsm */ +} /* namespace gr */ + diff --git a/lib/decryption/decryption_impl.h b/lib/decryption/decryption_impl.h new file mode 100644 index 0000000..a39cf4f --- /dev/null +++ b/lib/decryption/decryption_impl.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 <+YOU OR YOUR COMPANY+>. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GSM_DECRYPTION_IMPL_H +#define INCLUDED_GSM_DECRYPTION_IMPL_H + +#include <grgsm/decryption/decryption.h> + +namespace gr { + namespace gsm { + + class decryption_impl : public decryption + { + private: + std::vector<uint8_t> d_k_c; + void decrypt(pmt::pmt_t msg); + public: + decryption_impl(const std::vector<uint8_t> & k_c); + ~decryption_impl(); + virtual void set_k_c(const std::vector<uint8_t> & k_c); + }; + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_DECRYPTION_IMPL_H */ + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 2b6a543..0fa695b 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -49,3 +49,5 @@ GR_PYTHON_INSTALL( #set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) #GR_ADD_TEST(qa_receiver ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_receiver.py) #GR_ADD_TEST(qa_receiver_hier ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_receiver_hier.py) +#GR_ADD_TEST(qa_decryption ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_decryption.py) +#GR_ADD_TEST(qa_decryption ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_decryption.py) diff --git a/python/qa_decryption.py b/python/qa_decryption.py new file mode 100755 index 0000000..a87d392 --- /dev/null +++ b/python/qa_decryption.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @file +# @author Piotr Krysik <ptrkrysik@gmail.com> +# @section LICENSE +# +# Gr-gsm is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Gr-gsm is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with gr-gsm; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import gsm_swig as gsm + +class qa_decryption (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + # set up fg + self.tb.run () + # check data + + +if __name__ == '__main__': + gr_unittest.run(qa_decryption, "qa_decryption.xml") diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index d86226c..529a5f8 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -9,9 +9,10 @@ %{ #include "grgsm/receiver/receiver.h" +#include "grgsm/decoding/control_channels_decoder.h" +#include "grgsm/decryption/decryption.h" #include "grgsm/demapping/get_bcch_or_ccch_bursts.h" #include "grgsm/demapping/universal_ctrl_chans_demapper.h" -#include "grgsm/decoding/control_channels_decoder.h" #include "grgsm/misc_utils/bursts_printer.h" #include "grgsm/misc_utils/controlled_const_source_f.h" #include "grgsm/misc_utils/controlled_rotator_cc.h" @@ -26,6 +27,9 @@ GR_SWIG_BLOCK_MAGIC2(gsm, receiver); %include "grgsm/decoding/control_channels_decoder.h" GR_SWIG_BLOCK_MAGIC2(gsm, control_channels_decoder); +%include "grgsm/decryption/decryption.h" +GR_SWIG_BLOCK_MAGIC2(gsm, decryption); + %include "grgsm/demapping/get_bcch_or_ccch_bursts.h" GR_SWIG_BLOCK_MAGIC2(gsm, get_bcch_or_ccch_bursts); %include "grgsm/demapping/universal_ctrl_chans_demapper.h" |