FreeCalypso > hg > themwi-ota-tools
view smswrap/ota-smswrap-sjs1.c @ 3:8dfa3bfaa9c1
Sysmocom 2DES keys don't have correct parity
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 21 Feb 2021 22:34:03 +0000 |
parents | d5e9af482548 |
children |
line wrap: on
line source
/* * This utility will read a string of RFM APDU commands from stdin * and wrap this OTA command block into an SMS-PP User Data element * as appropriate for sysmoUSIM-SJS1 version of SIM RFM, including * the necessary cryptographic checksum and ciphering. * * The two command line arguments are KIC2 and KID2 secret keys * for the target SIM, the payload to be wrapped is supplied on stdin. */ #include <sys/types.h> #include <openssl/des.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #define MAX_PAYLOAD_LEN 106 #define MAX_SIGBUF (MAX_PAYLOAD_LEN + 16 + 6) #define MAX_CIPHERTEXT (MAX_PAYLOAD_LEN + 14) u_char payload_data[MAX_PAYLOAD_LEN]; unsigned payload_len, padding_len; int padding_mode; DES_key_schedule keysched_kic[2], keysched_kid[2]; u_char part_head[8] = {0x15, 0x06, 0x01, 0x25, 0x25, 0xB0, 0x00, 0x10}; u_char part_cnt[6], signature[8]; u_char ciphertext[MAX_CIPHERTEXT]; unsigned ciphertext_len; process_key_arg(arg, sched, name) char *arg, *name; DES_key_schedule *sched; { DES_cblock keybin[2]; int rc; unsigned n; rc = decode_hex_data_from_string(arg, keybin, 16, 16); if (rc < 0) exit(1); /* error msg already printed */ for (n = 0; n < 2; n++) DES_set_key_unchecked(keybin + n, sched + n); } read_payload() { int rc; unsigned maxlen; maxlen = MAX_PAYLOAD_LEN; if (padding_mode) maxlen -= 8; rc = read_hex_from_stdin(payload_data, maxlen); if (rc < 0) exit(1); /* error msg already printed */ payload_len = rc; } compute_pad_length() { unsigned ciph_len, rem; ciph_len = payload_len + 14; rem = ciph_len & 7; if (!rem && !padding_mode) padding_len = 0; else padding_len = 8 - rem; } compute_signature() { u_char plainbuf[MAX_SIGBUF], cipher_out[MAX_SIGBUF]; unsigned ciphlen; DES_cblock ivec; plainbuf[0] = 0; plainbuf[1] = payload_len + padding_len + 8 + 8 + 6; bcopy(part_head, plainbuf + 2, 8); bcopy(part_cnt, plainbuf + 10, 6); bcopy(payload_data, plainbuf + 16, payload_len + padding_len); bzero(plainbuf + 16 + payload_len + padding_len, 6); ciphlen = payload_len + padding_len + 16 + 6; bzero(&ivec, sizeof ivec); DES_ede2_cbc_encrypt(plainbuf, cipher_out, ciphlen, &keysched_kid[0], &keysched_kid[1], &ivec, DES_ENCRYPT); bcopy(cipher_out + ciphlen - 8, signature, 8); } encrypt_message() { u_char plainbuf[MAX_CIPHERTEXT]; DES_cblock ivec; bcopy(part_cnt, plainbuf, 6); bcopy(signature, plainbuf + 6, 8); bcopy(payload_data, plainbuf + 14, payload_len + padding_len); ciphertext_len = payload_len + padding_len + 14; bzero(&ivec, sizeof ivec); DES_ede2_cbc_encrypt(plainbuf, ciphertext, ciphertext_len, &keysched_kic[0], &keysched_kic[1], &ivec, DES_ENCRYPT); } emit_hex_bytes(bytes, len) u_char *bytes; unsigned len; { u_char *dp; unsigned n; dp = bytes; for (n = 0; n < len; n++) printf("%02X", *dp++); } main(argc, argv) char **argv; { if (argc < 3 || argc > 4) { fprintf(stderr, "usage: %s KIC2-hex KID2-hex\n", argv[0]); exit(1); } process_key_arg(argv[1], keysched_kic, "KIC2"); process_key_arg(argv[2], keysched_kid, "KID2"); if (argc > 3) padding_mode = atoi(argv[3]); else padding_mode = 0; read_payload(); compute_pad_length(); part_cnt[5] = padding_len; compute_signature(); encrypt_message(); /* emit output! */ printf("027000%04X", ciphertext_len + 8); emit_hex_bytes(part_head, 8); emit_hex_bytes(ciphertext, ciphertext_len); putchar('\n'); exit(0); }