comparison smswrap/ota-smswrap-sjs1.c @ 2:d5e9af482548

ota-smswrap-sjs1 program written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 21 Feb 2021 22:21:29 +0000
parents
children 8dfa3bfaa9c1
comparison
equal deleted inserted replaced
1:b149db92cb0e 2:d5e9af482548
1 /*
2 * This utility will read a string of RFM APDU commands from stdin
3 * and wrap this OTA command block into an SMS-PP User Data element
4 * as appropriate for sysmoUSIM-SJS1 version of SIM RFM, including
5 * the necessary cryptographic checksum and ciphering.
6 *
7 * The two command line arguments are KIC2 and KID2 secret keys
8 * for the target SIM, the payload to be wrapped is supplied on stdin.
9 */
10
11 #include <sys/types.h>
12 #include <openssl/des.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <strings.h>
17
18 #define MAX_PAYLOAD_LEN 106
19
20 #define MAX_SIGBUF (MAX_PAYLOAD_LEN + 16 + 6)
21 #define MAX_CIPHERTEXT (MAX_PAYLOAD_LEN + 14)
22
23 u_char payload_data[MAX_PAYLOAD_LEN];
24 unsigned payload_len, padding_len;
25 int padding_mode;
26
27 DES_key_schedule keysched_kic[2], keysched_kid[2];
28
29 u_char part_head[8] = {0x15, 0x06, 0x01, 0x25, 0x25, 0xB0, 0x00, 0x10};
30
31 u_char part_cnt[6], signature[8];
32 u_char ciphertext[MAX_CIPHERTEXT];
33 unsigned ciphertext_len;
34
35 process_key_arg(arg, sched, name)
36 char *arg, *name;
37 DES_key_schedule *sched;
38 {
39 DES_cblock keybin[2];
40 int rc;
41 unsigned n;
42
43 rc = decode_hex_data_from_string(arg, keybin, 16, 16);
44 if (rc < 0)
45 exit(1); /* error msg already printed */
46 for (n = 0; n < 2; n++) {
47 rc = DES_set_key_checked(keybin + n, sched + n);
48 if (rc < 0) {
49 fprintf(stderr,
50 "bad %s argument: DES_set_key_checked() returned %d on part %u\n",
51 name, rc, n);
52 exit(1);
53 }
54 }
55 }
56
57 read_payload()
58 {
59 int rc;
60 unsigned maxlen;
61
62 maxlen = MAX_PAYLOAD_LEN;
63 if (padding_mode)
64 maxlen -= 8;
65 rc = read_hex_from_stdin(payload_data, maxlen);
66 if (rc < 0)
67 exit(1); /* error msg already printed */
68 payload_len = rc;
69 }
70
71 compute_pad_length()
72 {
73 unsigned ciph_len, rem;
74
75 ciph_len = payload_len + 14;
76 rem = ciph_len & 7;
77 if (!rem && !padding_mode)
78 padding_len = 0;
79 else
80 padding_len = 8 - rem;
81 }
82
83 compute_signature()
84 {
85 u_char plainbuf[MAX_SIGBUF], cipher_out[MAX_SIGBUF];
86 unsigned ciphlen;
87 DES_cblock ivec;
88
89 plainbuf[0] = 0;
90 plainbuf[1] = payload_len + padding_len + 8 + 8 + 6;
91 bcopy(part_head, plainbuf + 2, 8);
92 bcopy(part_cnt, plainbuf + 10, 6);
93 bcopy(payload_data, plainbuf + 16, payload_len + padding_len);
94 bzero(plainbuf + 16 + payload_len + padding_len, 6);
95 ciphlen = payload_len + padding_len + 16 + 6;
96 bzero(&ivec, sizeof ivec);
97 DES_ede2_cbc_encrypt(plainbuf, cipher_out, ciphlen, &keysched_kid[0],
98 &keysched_kid[1], &ivec, DES_ENCRYPT);
99 bcopy(cipher_out + ciphlen - 8, signature, 8);
100 }
101
102 encrypt_message()
103 {
104 u_char plainbuf[MAX_CIPHERTEXT];
105 DES_cblock ivec;
106
107 bcopy(part_cnt, plainbuf, 6);
108 bcopy(signature, plainbuf + 6, 8);
109 bcopy(payload_data, plainbuf + 14, payload_len + padding_len);
110 ciphertext_len = payload_len + padding_len + 14;
111 bzero(&ivec, sizeof ivec);
112 DES_ede2_cbc_encrypt(plainbuf, ciphertext, ciphertext_len,
113 &keysched_kic[0], &keysched_kic[1], &ivec,
114 DES_ENCRYPT);
115 }
116
117 emit_hex_bytes(bytes, len)
118 u_char *bytes;
119 unsigned len;
120 {
121 u_char *dp;
122 unsigned n;
123
124 dp = bytes;
125 for (n = 0; n < len; n++)
126 printf("%02X", *dp++);
127 }
128
129 main(argc, argv)
130 char **argv;
131 {
132 if (argc < 3 || argc > 4) {
133 fprintf(stderr, "usage: %s KIC2-hex KID2-hex\n", argv[0]);
134 exit(1);
135 }
136 process_key_arg(argv[1], keysched_kic, "KIC2");
137 process_key_arg(argv[2], keysched_kid, "KID2");
138 if (argc > 3)
139 padding_mode = atoi(argv[3]);
140 else
141 padding_mode = 0;
142 read_payload();
143 compute_pad_length();
144 part_cnt[5] = padding_len;
145 compute_signature();
146 encrypt_message();
147 /* emit output! */
148 printf("027000%04X", ciphertext_len + 8);
149 emit_hex_bytes(part_head, 8);
150 emit_hex_bytes(ciphertext, ciphertext_len);
151 putchar('\n');
152 exit(0);
153 }