aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--sim/Makefile.am10
-rw-r--r--sim/README15
-rw-r--r--sim/sim.c144
-rw-r--r--sim/simcard.ino231
7 files changed, 404 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 217d78e..c0b4528 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ libcolorize.pc
libtool
ltmain.sh
missing
+compile
*.o
*.lo
*.la
@@ -25,6 +26,7 @@ src/bnetz/bnetz
src/cnetz/cnetz
src/nmt/nmt
src/amps/amps
+sim/cnetz_sim
src/test/test_compandor
src/test/test_emphasis
src/test/test_dms
diff --git a/Makefile.am b/Makefile.am
index 4c3e7c3..1073c14 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = src
+SUBDIRS = src sim
diff --git a/configure.ac b/configure.ac
index c7eb648..591c548 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,6 +35,7 @@ AC_OUTPUT(
src/amps/Makefile
src/test/Makefile
src/Makefile
+ sim/Makefile
Makefile)
diff --git a/sim/Makefile.am b/sim/Makefile.am
new file mode 100644
index 0000000..35808e7
--- /dev/null
+++ b/sim/Makefile.am
@@ -0,0 +1,10 @@
+AM_CPPFLAGS = -Wall -g $(all_includes)
+
+bin_PROGRAMS = \
+ cnetz_sim
+
+cnetz_sim_SOURCES = \
+ sim.c
+cnetz_sim_LDADD = \
+ $(COMMON_LA)
+
diff --git a/sim/README b/sim/README
new file mode 100644
index 0000000..adbae3b
--- /dev/null
+++ b/sim/README
@@ -0,0 +1,15 @@
+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.
+
diff --git a/sim/sim.c b/sim/sim.c
new file mode 100644
index 0000000..02e9bc6
--- /dev/null
+++ b/sim/sim.c
@@ -0,0 +1,144 @@
+/* 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;
+}
+
diff --git a/sim/simcard.ino b/sim/simcard.ino
new file mode 100644
index 0000000..0bb01d6
--- /dev/null
+++ b/sim/simcard.ino
@@ -0,0 +1,231 @@
+
+#define RST 8
+#define CLK 9
+#define DATA 10
+
+#define PSC1 0xff
+#define PSC2 0xff
+
+uint8_t card_data[] = {
+
+0xff, 0xf7, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x38,
+0x78, 0x28, 0x07, 0x8c, 0xc1, 0x03, 0xfe, 0xff,
+0xff, 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,
+
+};
+
+void setup()
+{
+ digitalWrite(RST, LOW);
+ pinMode(RST, OUTPUT);
+ digitalWrite(CLK, LOW);
+ pinMode(CLK, OUTPUT);
+ pinMode(DATA, INPUT_PULLUP);
+ digitalWrite(DATA, HIGH);
+
+ Serial.begin(9600);
+ while (!Serial) {
+ ; // wait for serial port to connect. Needed for Leonardo only
+ }
+ Serial.readStringUntil('\m');
+}
+
+void loop()
+{
+again:
+ Serial.println("Press 'a' for ATR, 'r' to read card, 'w' to program card, 'u' to unlock card");
+ Serial.println("-> You must read card ('r') before you are able to write to card.");
+ while (42) {
+ if (Serial.available() == 0)
+ continue;
+ char inChar = Serial.read();
+ if (inChar == 'a') {
+ Serial.println("ATR...");
+ card_atr(52);
+ goto again;
+ } else if (inChar == 'r') {
+ Serial.println("reading...");
+ card_read(52, 0);
+ goto again;
+ } else if (inChar == 'w') {
+ Serial.println("writing...");
+ card_write(card_data, sizeof(card_data), 0);
+ goto again;
+ } else if (inChar == 'u') {
+ Serial.println("unlocking...");
+ card_unlock(PSC1, PSC2);
+ goto again;
+ } else {
+ goto again;
+ }
+ }
+}
+
+void card_atr(int num)
+{
+ uint8_t data[num];
+
+ digitalWrite(RST, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+ digitalWrite(RST, LOW);
+ delayMicroseconds(100);
+ card_read_bytes(data, num);
+}
+
+void card_read(int num, int address)
+{
+ uint8_t data[num];
+
+ card_command(((address >> 2) & 0xc0) | 0x0e, address & 0xff, 0);
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+ card_read_bytes(data, num);
+}
+
+void card_write(uint8_t *data, int num, int address)
+{
+ int i, cnt;
+
+ for (i = 0; i < num; i++) {
+ card_command(((address >> 2) & 0xc0) | 0x33, address & 0xff, *data);
+ cnt = card_erase_and_write();
+ if (cnt <= 2) {
+ Serial.println("write failed!");
+// break;
+ }
+ address++;
+ data++;
+ }
+}
+
+void card_unlock(uint8_t psc1, uint8_t psc2)
+{
+ int i;
+ uint8_t data[3];
+
+ // read error counter
+ card_command(0xce, 253, 0);
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+ Serial.println("3 bytes: error counter mask, first PSC code, second psc code");
+ card_read_bytes(data, 3);
+ // check bit to erase
+ for (i = 0; i < 8; i++) {
+ if ((data[0] & (1 << i)))
+ break;
+ }
+ if (i == 8) {
+ Serial.println("SORRY NO MORE BITS TO ERASE TO UNLOCK, YOUR CARD IS BRICKED!");
+ return;
+ }
+ data[0] = data[0] - (1 << i);
+ // ease bit to unlock
+ card_command(0xf2, 253, data[0]);
+ card_erase_and_write();
+ // unlock
+ Serial.println("unlock bit has been erased, sending PSC code");
+ card_command(0xcd, 254, psc1);
+ card_erase_and_write();
+ card_command(0xcd, 255, psc2);
+ card_erase_and_write();
+ // read error counter mask
+ card_command(0xce, 253, 0);
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+ Serial.println("checking error counter mask, one bit shall be erased...");
+ card_read_bytes(data, 1);
+ // reset unlock mask
+ Serial.println("PSC code has been sent, resetting error counter mask");
+ card_command(0xf3, 253, 0xff);
+ card_erase_and_write();
+ // read error counter mask
+ card_command(0xce, 253, 0);
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+ Serial.println("reading: error counter mask, all bits should be reset");
+ card_read_bytes(data, 1);
+}
+
+void card_command(uint8_t c1, uint8_t c2, uint8_t c3)
+{
+ int i, j;
+ uint8_t c[3];
+
+ c[0] = c1;
+ c[1] = c2;
+ c[2] = c3;
+ Serial.println("card command:");
+ Serial.println(c1);
+ Serial.println(c2);
+ Serial.println(c3);
+
+ digitalWrite(RST, HIGH);
+ delayMicroseconds(100);
+ pinMode(DATA, OUTPUT);
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 8; j++) {
+ digitalWrite(DATA, ((c[i] >> j) & 1) ? HIGH : LOW);
+ delayMicroseconds(100);
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+ }
+ }
+ pinMode(DATA, INPUT_PULLUP);
+ digitalWrite(DATA, HIGH);
+ digitalWrite(RST, LOW);
+ delayMicroseconds(100);
+}
+
+void card_read_bytes(uint8_t *data, int num) {
+ int i, j;
+
+ for (i = 0; i < num; i++) {
+ for (j = 0; j < 8; j++) {
+ data[i] = (data[i] >> 1) | ((digitalRead(DATA) != LOW) ? 128 : 0);
+ Serial.print((digitalRead(DATA) != LOW) ? '1' : '0');
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+ }
+ Serial.print(" 0x");
+ Serial.println(data[i], HEX);
+ }
+}
+
+int card_erase_and_write(void)
+{
+ int i;
+
+ for (i = 0; i < 203; i++) {
+ digitalWrite(CLK, HIGH);
+ delayMicroseconds(100);
+ digitalWrite(CLK, LOW);
+ delayMicroseconds(100);
+if (0) if (digitalRead(DATA) == LOW) {
+ Serial.print(" -> write pulses:");
+ Serial.println(i);
+ break;
+ }
+ }
+ return i;
+}
+