Added new decryption block (be careful - untested component). Changed CMakeFiles to reflect more modular design (not finished for the lib directory)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8e1a75d..c6abc58 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -151,8 +151,7 @@
 ########################################################################
 # 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/include/plotting/CMakeLists.txt b/grc/decoding/CMakeLists.txt
similarity index 78%
copy from include/plotting/CMakeLists.txt
copy to grc/decoding/CMakeLists.txt
index 569c462..36820f3 100644
--- a/include/plotting/CMakeLists.txt
+++ b/grc/decoding/CMakeLists.txt
@@ -17,9 +17,6 @@
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
 
-########################################################################
-# Install public header files
-########################################################################
 install(FILES
-    plotting.hpp DESTINATION include/plotting
+    gsm_control_channels_decoder.xml DESTINATION share/gnuradio/grc/blocks
 )
diff --git a/include/plotting/CMakeLists.txt b/grc/decryption/CMakeLists.txt
similarity index 72%
copy from include/plotting/CMakeLists.txt
copy to grc/decryption/CMakeLists.txt
index 569c462..29d86f4 100644
--- a/include/plotting/CMakeLists.txt
+++ b/grc/decryption/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2011,2012 Free Software Foundation, Inc.
+# Copyright 2011 Free Software Foundation, Inc.
 #
 # This file is part of GNU Radio
 #
@@ -17,9 +17,6 @@
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
 
-########################################################################
-# Install public header files
-########################################################################
 install(FILES
-    plotting.hpp DESTINATION include/plotting
+    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/include/plotting/CMakeLists.txt b/grc/demapping/CMakeLists.txt
similarity index 78%
copy from include/plotting/CMakeLists.txt
copy to grc/demapping/CMakeLists.txt
index 569c462..a057d19 100644
--- a/include/plotting/CMakeLists.txt
+++ b/grc/demapping/CMakeLists.txt
@@ -17,9 +17,7 @@
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
 
-########################################################################
-# Install public header files
-########################################################################
 install(FILES
-    plotting.hpp DESTINATION include/plotting
+    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/include/plotting/CMakeLists.txt b/grc/misc_utils/CMakeLists.txt
similarity index 77%
copy from include/plotting/CMakeLists.txt
copy to grc/misc_utils/CMakeLists.txt
index 569c462..48e8cae 100644
--- a/include/plotting/CMakeLists.txt
+++ b/grc/misc_utils/CMakeLists.txt
@@ -17,9 +17,10 @@
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
 
-########################################################################
-# Install public header files
-########################################################################
 install(FILES
-    plotting.hpp DESTINATION include/plotting
+    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/include/plotting/CMakeLists.txt b/grc/receiver/CMakeLists.txt
similarity index 77%
copy from include/plotting/CMakeLists.txt
copy to grc/receiver/CMakeLists.txt
index 569c462..25f08cc 100644
--- a/include/plotting/CMakeLists.txt
+++ b/grc/receiver/CMakeLists.txt
@@ -17,9 +17,11 @@
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
 
-########################################################################
-# Install public header files
-########################################################################
 install(FILES
-    plotting.hpp DESTINATION include/plotting
+    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/plotting/CMakeLists.txt b/include/CMakeLists.txt
similarity index 76%
copy from include/plotting/CMakeLists.txt
copy to include/CMakeLists.txt
index 569c462..a7c18dd 100644
--- a/include/plotting/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -17,9 +17,4 @@
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
 
-########################################################################
-# Install public header files
-########################################################################
-install(FILES
-    plotting.hpp DESTINATION include/plotting
-)
+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
similarity index 94%
rename from include/plotting/CMakeLists.txt
rename to 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
similarity index 100%
rename from include/plotting/plotting.hpp
rename to 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 @@
     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 @@
 #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 @@
 %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"