Moved C-Netz "Speicherkarte" to "extra" directory and improved it.

This commit is contained in:
Andreas Eversberg 2020-05-10 19:33:27 +02:00
parent e18f7dbc1f
commit 0b6a5d19cb
11 changed files with 456 additions and 172 deletions

2
.gitignore vendored
View File

@ -69,7 +69,7 @@ src/tv/osmotv
src/radio/osmoradio
src/datenklo/datenklo
src/zeitansage/zeitansage
sim/cnetz_sim
extra/cnetz_memory_card_generator
src/test/test_filter
src/test/test_sendevolumenregler
src/test/test_compandor

View File

@ -1,4 +1,4 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src sim
SUBDIRS = src extra

View File

@ -102,7 +102,7 @@ AC_OUTPUT(
src/zeitansage/Makefile
src/test/Makefile
src/Makefile
sim/Makefile
extra/Makefile
Makefile)

12
extra/Makefile.am Normal file
View File

@ -0,0 +1,12 @@
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
bin_PROGRAMS = \
cnetz_memory_card_generator
cnetz_memory_card_generator_SOURCES = \
main.c
cnetz_memory_card_generator_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/liboptions/liboptions.a

58
extra/README Normal file
View File

@ -0,0 +1,58 @@
This is a generator for the C-Netz Sim Card
"Berechtigungskarte als Speicherkarte". (memory card)
In the sub directory "simulator" you find an Arduino Sketch to simulate a memory card.
In the sub directory "programmer" you find an Arduino Sketch to program an SLE4428 card.
NOTE:
This will only work with old phones that were released before the CPU SIM was released.
The Smart Card "Berechtigungskarte als Prozessorkarte" is implemented at src/sim.
Run cnetz_memory_card_generator:
# ./extra/cnetz_memory_card_generator
Usage: ./cnetz_memory_card_generator <futln_nat> <futln_fuvst> <futln_rest> <sicherungscode> <sonderheitsschluessel>
# ./extra/cnetz_memory_card_generator 2222002
Magic Data 011..015 = 30 (0x1e)
Magic Data 018..020 = 7
Magic Data 021..023 = 2
FUTLN NAT = 2
FUTLN FUVST = 2
FUTLN REST = 22002
Sicherungscode=12345
Sonderheitenschluessel=0 (0x0000)
Wartungsschluessel=65535 (0xffff)
Binary data: (LSB first)
0xff, 0xf7, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4b, 0x90,
0x5f, 0x25, 0x07, 0x0c, 0x00, 0x00, 0xfe, 0xfd,
0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
After generation, the hex data can be copied to the data array of programmer/programmer.ino or simulator/simulator.ino
If you use the programmer, connect an SLE4428 or compatible as inicated at the pin definition of programmer.ino.
Note: The SLE card must not have protected serial number area. (ATR area)
Also the card must show all 416 written bits via ATR, not only 32 bits.
If you use the Arduino as emulator, connect the card reader as indicated at the pin definition of simulator.ino
Tested:
Works with BSA 51
Does not work with all other phones I have.
Test cards and monitor cards for BSA 51:
# ./extra/cnetz_memory_card_generator --special-key 898 2222002
# ./extra/cnetz_memory_card_generator --special-key 899 2222002
# ./extra/cnetz_memory_card_generator --magic1 0x1d --special-key 0x900 --maintenance-key 0xa139 2222002
# ./extra/cnetz_memory_card_generator --magic1 0x1d --special-key 0x901 --maintenance-key 0xa139 2222002

257
extra/main.c Normal file
View File

@ -0,0 +1,257 @@
/* SIM Card for C-Netz "Berechtigungskarte als Speicherkarte"
*
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <../src/libdebug/debug.h>
#include <../src/liboptions/options.h>
int num_kanal = 1;
static uint8_t magic1 = 0x1e;
static uint8_t magic2 = 0x7;
static uint8_t magic3 = 0x2;
static const char *futln;
static uint8_t futln_nat;
static uint8_t futln_fuvst;
static uint16_t futln_rest;
static uint16_t sicherungscode = 12345;
static uint16_t sonderheitenschluessel = 0;
static uint16_t wartungsschluessel = 0xffff;
/* return 1, if 1-bits are odd, so parity becomes even */
static int gen_parity(uint8_t *bits)
{
int i;
uint8_t parity = 0;
for (i = 0; i < 8; i++)
parity ^= (bits[i] & 1);
return parity;
}
static uint8_t *gen_memory(uint8_t magic1, uint8_t magic2, uint8_t magic3, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, uint16_t sicherungscode, uint16_t sonderheitenschluessel, uint16_t wartungsschluessel)
{
static uint8_t memory[416];
int i;
/* meaningless data */
for (i = 0; i <= 10; i++)
memory[i] = 1;
/* magic data */
for (i = 11; i <= 15; i++)
memory[i] = (magic1 >> (i - 11)) & 1;
/* meaningless data */
for (i = 16; i <= 17; i++)
memory[i] = 0;
/* magic data */
for (i = 18; i <= 20; i++)
memory[i] = (magic2 >> (i - 18)) & 1;
/* magic data */
for (i = 21; i <= 23; i++)
memory[i] = (magic3 >> (i - 21)) & 1;
/* meaningless data */
for (i = 24; i <= 113; i++)
memory[i] = 1;
/* number */
for (i = 114; i <= 116; i++)
memory[i] = (futln_nat >> (i - 114)) & 1;
for (i = 117; i <= 121; i++)
memory[i] = (futln_fuvst >> (i - 117)) & 1;
memory[122] = gen_parity(memory + 114);
for (i = 123; i <= 130; i++)
memory[i] = (futln_rest >> (i - 123)) & 1;
memory[131] = gen_parity(memory + 123);
for (i = 132; i <= 139; i++)
memory[i] = (futln_rest >> (i - 132 + 8)) & 1;
memory[140] = gen_parity(memory + 132);
/* sicherungscode */
for (i = 141; i <= 148; i++)
memory[i] = (sicherungscode >> (i - 141)) & 1;
memory[149] = gen_parity(memory + 141);
for (i = 150; i <= 157; i++)
memory[i] = (sicherungscode >> (i - 150 + 8)) & 1;
memory[158] = gen_parity(memory + 150);
/* sonderheitenschluessel */
for (i = 159; i <= 166; i++)
memory[i] = (sonderheitenschluessel >> (i - 159)) & 1;
memory[167] = gen_parity(memory + 159);
for (i = 168; i <= 175; i++)
memory[i] = (sonderheitenschluessel >> (i - 168 + 8)) & 1;
memory[176] = gen_parity(memory + 168);
/* wartungschluessel */
for (i = 177; i <= 184; i++)
memory[i] = (wartungsschluessel >> (i - 177)) & 1;
memory[185] = gen_parity(memory + 177);
for (i = 186; i <= 193; i++)
memory[i] = (wartungsschluessel >> (i - 186 + 8)) & 1;
memory[194] = gen_parity(memory + 186);
/* meaningless data */
for (i = 195; i <= 351; i++)
memory[i] = 1;
/* all zero */
for (i = 352; i <= 415; i++)
memory[i] = 0;
return memory;
}
void print_help(const char *arg0)
{
printf("Usage: %s [options] <subscriber number>\n", arg0);
/* - - */
printf("General options:\n");
printf(" -h --help\n");
printf(" This help\n");
printf(" -1 --magic1 <value>\n");
printf(" Magic value for bits 011-015 (default = 0x%02x)\n", magic1);
printf(" -2 --magic2 <value>\n");
printf(" Magic value for bits 018-021 (default = 0x%x)\n", magic2);
printf(" -3 --magic3 <value>\n");
printf(" Magic value for bits 022-024 (default = 0x%x)\n", magic3);
printf(" -C --security-code \n");
printf(" Security code (\"Sicherungscode\") (default = %d)\n", sicherungscode);
printf(" -S --special-key \n");
printf(" Special key (\"Sonderheitenschluessel\") (default = %d)\n", sonderheitenschluessel);
printf(" -W --maintenance-key \n");
printf(" Maintenance key (\"Wartungsschluessel\") (default = %d)\n", wartungsschluessel);
printf("\nSubscriber number:\n");
printf(" Give 7 (8) digits of C-Netz subscriber number (FUTLN) without prefix.\n");
}
void add_options(void)
{
option_add('h', "help", 0);
option_add('1', "magic1", 1);
option_add('2', "magic2", 2);
option_add('3', "magic3", 3);
option_add('C', "security-code", 1);
option_add('S', "special-key", 1);
option_add('W', "maintenance-key", 1);
};
int handle_options(int short_option, int argi, char **argv)
{
switch (short_option) {
case 'h':
print_help(argv[0]);
return 0;
case '1':
magic1 = strtoul(argv[argi], NULL, 0);
break;
case '2':
magic2 = strtoul(argv[argi], NULL, 0);
break;
case '3':
magic3 = strtoul(argv[argi], NULL, 0);
break;
case 'C':
sicherungscode = strtoul(argv[argi], NULL, 0);
break;
case 'S':
sonderheitenschluessel = strtoul(argv[argi], NULL, 0);
break;
case 'W':
wartungsschluessel = strtoul(argv[argi], NULL, 0);
break;
default:
return -EINVAL;
}
return 1;
}
int main(int argc, char *argv[])
{
int argi;
int i;
debuglevel = DEBUG_INFO;
add_options();
/* parse command line */
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
/* get subscriber number */
if (argi >= argc) {
fprintf(stderr, "Expecting subscriber number, use '-h' for help!\n");
return 0;
}
futln = argv[argi];
if (strlen(futln) == 7) {
futln_nat = *futln++ - '0';
futln_fuvst = *futln++ - '0';
} else if (strlen(futln) == 8) {
futln_nat = *futln++ - '0';
futln_fuvst = (*futln++ - '0') * 10;
futln_fuvst += *futln++ - '0';
} else {
inval_sub:
fprintf(stderr, "Invalid subscriber number, use '-h' for help!\n");
return 0;
}
futln_rest = (*futln++ - '0') * 10000;
futln_rest += (*futln++ - '0') * 1000;
futln_rest += (*futln++ - '0') * 100;
futln_rest += (*futln++ - '0') * 10;
futln_rest += *futln++ - '0';
if (futln_nat > 7 || futln_fuvst > 31)
goto inval_sub;
printf("\n");
printf("Magic Data 011..015 = %d (0x%02x)\n", magic1, magic1);
printf("Magic Data 018..020 = %d\n", magic2);
printf("Magic Data 021..023 = %d\n", magic3);
printf("FUTLN NAT = %d\n", futln_nat);
printf("FUTLN FUVST = %d\n", futln_fuvst);
printf("FUTLN REST = %d\n", futln_rest);
printf("Sicherungscode=%d\n", sicherungscode);
printf("Sonderheitenschluessel=%d (0x%04x)\n", sonderheitenschluessel, sonderheitenschluessel);
printf("Wartungsschluessel=%d (0x%04x)\n", wartungsschluessel, wartungsschluessel);
printf("\nBinary data: (LSB first)\n");
uint8_t *bits = gen_memory(magic1, magic2, magic3, futln_nat, futln_fuvst, futln_rest, sicherungscode, sonderheitenschluessel, wartungsschluessel);
for (i = 0; i < 52; i++) {
printf("0x%02x, ", bits[0] + (bits[1] << 1) + (bits[2] << 2) + (bits[3] << 3) + (bits[4] << 4) + (bits[5] << 5) + (bits[6] << 6) + (bits[7] << 7));
bits += 8;
if ((i & 7) == 7)
printf("\n");
}
printf("\n");
return 0;
}

View File

@ -0,0 +1,126 @@
/* SIM card for ATMEL
*
* (C) 2020 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(__AVR_ATtiny85__)
#define RST_PIN 2
#define CLK_PIN 3
#define DATA_PIN 4
#error UNTESTED!
#else
#define CLK_PIN 5
#define RST_PIN 6
#define DATA_PIN 7
#endif
uint8_t card_data[] = {
0xff, 0xf7, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4b, 0x90,
0x5f, 0x25, 0x07, 0x0c, 0x00, 0x00, 0xfe, 0xfd,
0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
volatile uint8_t *rst_in, *clk_in, *data_in, *data_out, *data_mode;
uint8_t rst_bit, clk_bit, data_bit;
void setup()
{
volatile uint8_t *out, *mode;
uint8_t port;
rst_bit = digitalPinToBitMask(RST_PIN);
port = digitalPinToPort(RST_PIN);
mode = portModeRegister(port);
out = portOutputRegister(port);
rst_in = portInputRegister(port);
*mode &= ~rst_bit; /* input */
*out |= rst_bit; /* pullup */
clk_bit = digitalPinToBitMask(CLK_PIN);
port = digitalPinToPort(CLK_PIN);
mode = portModeRegister(port);
out = portOutputRegister(port);
clk_in = portInputRegister(port);
*mode &= ~clk_bit; /* input */
*out |= clk_bit; /* pullup */
data_bit = digitalPinToBitMask(DATA_PIN);
port = digitalPinToPort(DATA_PIN);
data_mode = portModeRegister(port);
data_out = portOutputRegister(port);
data_in = portInputRegister(port);
*data_mode |= data_bit; /* output */
}
uint8_t byte_count;
uint8_t bit_count;
void loop()
{
reset:
byte_count = 0;
bit_count = 0;
/* wait for reset pulse */
while (!(*rst_in & rst_bit));
/* now we have reset, so we wait for clock pulse */
while (!(*clk_in & clk_bit)) {
/* if we lost reset, go to start */
if (!(*rst_in & rst_bit))
goto reset;
}
while ((*clk_in & clk_bit)) {
/* if we lost reset, go to start */
if (!(*rst_in & rst_bit))
goto reset;
}
while ((*rst_in & rst_bit));
next_bit:
/* present bit */
if ((card_data[byte_count] >> bit_count) & 1)
*data_out |= data_bit; /* high */
else
*data_out &= ~data_bit; /* low */
if (++bit_count == 8) {
bit_count = 0;
if (++byte_count == sizeof(card_data)) {
goto reset;
}
}
/* wait for clock pulse */
while (!(*clk_in & clk_bit)) {
/* reset counter if reset was detected */
if ((*rst_in & rst_bit)) {
goto reset;
}
}
while ((*clk_in & clk_bit)) {
/* reset counter if reset was detected */
if ((*rst_in & rst_bit)) {
goto reset;
}
}
goto next_bit;
}

View File

@ -1,10 +0,0 @@
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
bin_PROGRAMS = \
cnetz_sim
cnetz_sim_SOURCES = \
sim.c
cnetz_sim_LDADD = \
$(COMMON_LA)

View File

@ -1,15 +0,0 @@
This is a generator for the C-Netz Sim Card
"Berechtigungskarte als Speicherkarte".
The Smart Card "Berechtigungskarte als Prozessorkarte" is not supported.
After generation, the hex data can be copied to the data array of simcard.ino
and written to an SLE4428 or compatible.
Note: The SLE card must not have protected serial number area. (ATR area)
Also the card must show all 416 written bits via ATR, not only 32 bits.
Tested:
Works with BSA 51
Does not work with all other phones I have.

144
sim/sim.c
View File

@ -1,144 +0,0 @@
/* SIM Card for C-Netz "Berechtigungskarte als Speicherkarte"
*
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
/* return 1, if 1-bits are odd, so parity becomes even */
static int gen_parity(uint8_t *bits)
{
int i;
uint8_t parity = 0;
for (i = 0; i < 8; i++)
parity ^= (bits[i] & 1);
return parity;
}
static uint8_t *gen_memory(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, uint16_t sicherungscode, uint16_t sonderheitsschluessel)
{
static uint8_t memory[416];
int i;
/* meaningless data */
for (i = 0; i <= 10; i++)
memory[i] = 1;
/* magic data */
memory[11] = 0;
memory[12] = 1;
memory[13] = 1;
memory[14] = 1;
memory[15] = 1;
/* meaningless data */
for (i = 16; i <= 17; i++)
memory[i] = 0;
/* magic data */
memory[18] = 1;
memory[19] = 1;
memory[20] = 1;
/* magic data */
memory[21] = 0;
memory[22] = 1;
memory[23] = 0;
/* meaningless data */
for (i = 24; i <= 113; i++)
memory[i] = 1;
/* number */
for (i = 114; i <= 116; i++)
memory[i] = (futln_nat >> (i - 114)) & 1;
for (i = 117; i <= 121; i++)
memory[i] = (futln_fuvst >> (i - 117)) & 1;
memory[122] = gen_parity(memory + 114);
for (i = 123; i <= 130; i++)
memory[i] = (futln_rest >> (i - 123)) & 1;
memory[131] = gen_parity(memory + 123);
for (i = 132; i <= 139; i++)
memory[i] = (futln_rest >> (i - 132 + 8)) & 1;
memory[140] = gen_parity(memory + 132);
/* sicherungscode */
for (i = 141; i <= 148; i++)
memory[i] = (sicherungscode >> (i - 141)) & 1;
memory[149] = gen_parity(memory + 141);
for (i = 150; i <= 157; i++)
memory[i] = (sicherungscode >> (i - 150 + 8)) & 1;
memory[158] = gen_parity(memory + 150);
/* sonderheitsschluessel */
for (i = 159; i <= 166; i++)
memory[i] = (sonderheitsschluessel >> (i - 159)) & 1;
memory[167] = gen_parity(memory + 159);
for (i = 168; i <= 175; i++)
memory[i] = (sonderheitsschluessel >> (i - 168 + 8)) & 1;
memory[176] = gen_parity(memory + 168);
/* meaningless data */
for (i = 177; i <= 351; i++)
memory[i] = 1;
/* all zero */
for (i = 352; i <= 415; i++)
memory[i] = 0;
return memory;
}
int main(int argc, char *argv[])
{
if (argc <= 5) {
printf("Usage: %s <futln_nat> <futln_fuvst> <futln_rest> <sicherungscode> <sonderheitsschluessel>\n", argv[0]);
return 0;
}
int i;
uint8_t futln_nat = atoi(argv[1]);
uint8_t futln_fuvst = atoi(argv[2]);
uint16_t futln_rest = atoi(argv[3]);
uint16_t sicherungscode = atoi(argv[4]);
uint16_t sonderheitsschluessel = atoi(argv[5]);
printf("nat=%d\n", futln_nat);
printf("fufvt=%d\n", futln_fuvst);
printf("rest=%d\n", futln_rest);
printf("sicherungscode=%d\n", sicherungscode);
printf("sonderheitsschluessel=%d\n", sonderheitsschluessel);
printf("Telefonnummer: %d%d%05d\n", futln_nat, futln_fuvst, futln_rest);
uint8_t *bits = gen_memory(futln_nat, futln_fuvst, futln_rest, sicherungscode, sonderheitsschluessel);
for (i = 0; i < 52; i++) {
//printf("%d %d %d %d %d %d %d %d\n", bits[0], bits[1], bits[2] ,bits[3] ,bits[4] ,bits[5] ,bits[6] ,bits[7]);
printf("0x%02x, ", bits[0] + (bits[1] << 1) + (bits[2] << 2) + (bits[3] << 3) + (bits[4] << 4) + (bits[5] << 5) + (bits[6] << 6) + (bits[7] << 7));
//printf("\n");
bits += 8;
if ((i & 7) == 7)
printf("\n");
}
printf("\n");
return 0;
}