blob: 551afa44302b37076eb9aa27c435237f023394db [file] [log] [blame]
ptrkrysik18b631e2014-12-15 09:09:18 +01001/* -*- c++ -*- */
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +02002/*
Piotr Krysikea34c012016-10-02 18:53:43 +02003 * @file
Piotr Krysika6268a52017-08-23 16:02:19 +02004 * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
5 * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
Piotr Krysikea34c012016-10-02 18:53:43 +02006 * @section LICENSE
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +02007 *
Piotr Krysikea34c012016-10-02 18:53:43 +02008 * Gr-gsm is free software; you can redistribute it and/or modify
ptrkrysik18b631e2014-12-15 09:09:18 +01009 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3, or (at your option)
11 * any later version.
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +020012 *
Piotr Krysikea34c012016-10-02 18:53:43 +020013 * Gr-gsm is distributed in the hope that it will be useful,
ptrkrysik18b631e2014-12-15 09:09:18 +010014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +020017 *
ptrkrysik18b631e2014-12-15 09:09:18 +010018 * You should have received a copy of the GNU General Public License
Piotr Krysikea34c012016-10-02 18:53:43 +020019 * along with gr-gsm; see the file COPYING. If not, write to
ptrkrysik18b631e2014-12-15 09:09:18 +010020 * the Free Software Foundation, Inc., 51 Franklin Street,
21 * Boston, MA 02110-1301, USA.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include <gnuradio/io_signature.h>
ptrkrysik18b631e2014-12-15 09:09:18 +010029#include <grgsm/gsmtap.h>
ptrkrysik5817a792015-04-25 18:51:08 +020030#include <grgsm/endian.h>
Roman Khassraf4dec5402015-07-17 18:32:22 +020031#include <numeric>
ptrkrysik18b631e2014-12-15 09:09:18 +010032#include "decryption_impl.h"
ptrkrysik18b631e2014-12-15 09:09:18 +010033
Roman Khassrafc51f12b2015-07-17 15:18:10 +020034extern "C" {
35 #include <osmocom/gsm/a5.h>
36}
ptrkrysik5817a792015-04-25 18:51:08 +020037
ptrkrysik18b631e2014-12-15 09:09:18 +010038const uint32_t BURST_SIZE=148;
39
40namespace gr {
41 namespace gsm {
42
43 decryption::sptr
Roman Khassraf4dec5402015-07-17 18:32:22 +020044 decryption::make(const std::vector<uint8_t> & k_c, unsigned int a5_version)
ptrkrysik18b631e2014-12-15 09:09:18 +010045 {
46 return gnuradio::get_initial_sptr
Roman Khassraf4dec5402015-07-17 18:32:22 +020047 (new decryption_impl(k_c, a5_version));
ptrkrysik18b631e2014-12-15 09:09:18 +010048 }
49
50 /*
51 * The private constructor
52 */
Roman Khassraf4dec5402015-07-17 18:32:22 +020053 decryption_impl::decryption_impl(const std::vector<uint8_t> & k_c, unsigned int a5_version)
ptrkrysik18b631e2014-12-15 09:09:18 +010054 : gr::block("decryption",
55 gr::io_signature::make(0, 0, 0),
Roman Khassraf4dec5402015-07-17 18:32:22 +020056 gr::io_signature::make(0, 0, 0)),
57 d_k_c_valid(false)
ptrkrysik18b631e2014-12-15 09:09:18 +010058 {
59 set_k_c(k_c);
Roman Khassraf4dec5402015-07-17 18:32:22 +020060 set_a5_version(a5_version);
61 validate_k_c();
ptrkrysik18b631e2014-12-15 09:09:18 +010062
ptrkrysik18b631e2014-12-15 09:09:18 +010063 message_port_register_in(pmt::mp("bursts"));
64 set_msg_handler(pmt::mp("bursts"), boost::bind(&decryption_impl::decrypt, this, _1));
65 message_port_register_out(pmt::mp("bursts"));
66 }
67
68 /*
69 * Virtual destructor
70 */
71 decryption_impl::~decryption_impl()
72 {
73 }
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +020074
ptrkrysik18b631e2014-12-15 09:09:18 +010075 void decryption_impl::set_k_c(const std::vector<uint8_t> & k_c)
76 {
Roman Khassraf4dec5402015-07-17 18:32:22 +020077 d_k_c = k_c;
78 }
79
80 void decryption_impl::set_a5_version(unsigned int a5_version)
81 {
82 d_a5_version = 1;
83 if (a5_version >= 1 && a5_version <= 4)
Roman Khassrafc51f12b2015-07-17 15:18:10 +020084 {
Roman Khassraf4dec5402015-07-17 18:32:22 +020085 d_a5_version = a5_version;
86 }
87 }
88
89 void decryption_impl::validate_k_c()
90 {
91 if (d_k_c.size() == 0)
92 {
93 d_k_c_valid = false;
94 return;
95 }
96 else if ((d_a5_version < 4 && d_k_c.size() != 8) || (d_a5_version == 4 && d_k_c.size() != 16))
97 {
98 d_k_c_valid = false;
99 return;
Roman Khassrafc51f12b2015-07-17 15:18:10 +0200100 }
101 else
102 {
Roman Khassraf4dec5402015-07-17 18:32:22 +0200103 for (int i=0; i<d_k_c.size(); i++)
Roman Khassrafc51f12b2015-07-17 15:18:10 +0200104 {
Roman Khassraf4dec5402015-07-17 18:32:22 +0200105 if (d_k_c[i] != 0)
106 {
107 d_k_c_valid = true;
108 return;
109 }
Roman Khassrafc51f12b2015-07-17 15:18:10 +0200110 }
111 }
ptrkrysik18b631e2014-12-15 09:09:18 +0100112 }
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +0200113
ptrkrysik18b631e2014-12-15 09:09:18 +0100114 void decryption_impl::decrypt(pmt::pmt_t msg)
115 {
Roman Khassraf4dec5402015-07-17 18:32:22 +0200116 if (!d_k_c_valid)
ptrkrysik18b631e2014-12-15 09:09:18 +0100117 {
118 message_port_pub(pmt::mp("bursts"), msg);
Roman Khassraf4dec5402015-07-17 18:32:22 +0200119 }
120 else
ptrkrysik18b631e2014-12-15 09:09:18 +0100121 {
122 uint8_t decrypted_data[BURST_SIZE];
Roman Khassrafc51f12b2015-07-17 15:18:10 +0200123 uint8_t keystream[114];
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +0200124
ptrkrysik18b631e2014-12-15 09:09:18 +0100125 pmt::pmt_t header_plus_burst = pmt::cdr(msg);
126 gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
127 uint8_t * burst_binary = (uint8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +0200128
ptrkrysik4739c942015-02-07 19:51:03 +0100129 uint32_t frame_number = be32toh(header->frame_number);
130 bool uplink_burst = (be16toh(header->arfcn) & 0x4000) ? true : false;
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +0200131
ptrkrysik18b631e2014-12-15 09:09:18 +0100132 if(uplink_burst){
133 //process uplink burst
Roman Khassraf4dec5402015-07-17 18:32:22 +0200134 osmo_a5(d_a5_version, &d_k_c[0], frame_number, NULL, keystream);
ptrkrysik18b631e2014-12-15 09:09:18 +0100135 } else {
136 //process downlink burst
Roman Khassraf4dec5402015-07-17 18:32:22 +0200137 osmo_a5(d_a5_version, &d_k_c[0], frame_number, keystream, NULL);
ptrkrysik18b631e2014-12-15 09:09:18 +0100138 }
139 /* guard bits */
140 for (int i = 0; i < 3; i++) {
141 decrypted_data[i] = burst_binary[i];
142 }
Piotr Krysik58782252016-09-28 11:53:51 +0200143 //decrypt first part of the burst
ptrkrysik18b631e2014-12-15 09:09:18 +0100144 for (int i = 0; i < 57; i++) {
145 decrypted_data[i+3] = keystream[i] ^ burst_binary[i+3];
146 }
147 /* stealing bits and midamble */
148 for (int i = 60; i < 88; i++) {
149 decrypted_data[i] = burst_binary[i];
150 }
Piotr Krysik58782252016-09-28 11:53:51 +0200151 //decrypt second part of the burst
ptrkrysik18b631e2014-12-15 09:09:18 +0100152 for (int i = 0; i < 57; i++) {
153 decrypted_data[i+88] = keystream[i+57] ^ burst_binary[i+88];
154 }
155 /* guard bits */
156 for (int i = 145; i < 148; i++) {
157 decrypted_data[i] = burst_binary[i];
158 }
159 uint8_t new_header_plus_burst[sizeof(gsmtap_hdr)+BURST_SIZE];
160 memcpy(new_header_plus_burst, header, sizeof(gsmtap_hdr));
161 memcpy(new_header_plus_burst+sizeof(gsmtap_hdr), decrypted_data, BURST_SIZE);
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +0200162
ptrkrysik18b631e2014-12-15 09:09:18 +0100163 pmt::pmt_t msg_binary_blob = pmt::make_blob(new_header_plus_burst, sizeof(gsmtap_hdr)+BURST_SIZE);
164 pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);
Martin Jesper Low Madsenaf769642015-04-28 22:33:43 +0200165
ptrkrysik18b631e2014-12-15 09:09:18 +0100166 message_port_pub(pmt::mp("bursts"), msg_out);
167 }
168 return;
169 }
170 } /* namespace gsm */
171} /* namespace gr */