# HG changeset patch # User Mychaela Falconia # Date 1614370798 0 # Node ID f064dbcc5f41a0938fb530a3ac2998e5467f305a # Parent 5f1f3f6fd865083a69763bb02ce46f4bff62828c libutil split from libcommon diff -r 5f1f3f6fd865 -r f064dbcc5f41 Makefile --- a/Makefile Thu Feb 25 20:55:10 2021 +0000 +++ b/Makefile Fri Feb 26 20:19:58 2021 +0000 @@ -1,12 +1,12 @@ PROGDIR=misc simtool uicc -LIBDIR= libcommon +LIBDIR= libcommon libutil SUBDIR= ${PROGDIR} ${LIBDIR} all: ${SUBDIR} -misc: libcommon -simtool: libcommon -uicc: libcommon +misc: libcommon libutil +simtool: libcommon libutil +uicc: libcommon libutil ${SUBDIR}: FRC cd $@; ${MAKE} ${MFLAGS} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/Makefile --- a/libcommon/Makefile Thu Feb 25 20:55:10 2021 +0000 +++ b/libcommon/Makefile Fri Feb 26 20:19:58 2021 +0000 @@ -1,11 +1,7 @@ CC= gcc CFLAGS= -O2 -I/usr/include/PCSC -OBJS= alpha_decode.o alpha_fromfile.o alpha_valid.o apdu.o apducmd.o atr.o \ - cardconnect.o chkblank.o decimal_str.o dumpdirfunc.o exit.o \ - filesearch.o globalopts.o gsm7_decode.o gsm7_encode.o \ - gsm7_encode_table.o gsm7_unpack.o hexdump.o hexread.o hexstr.o \ - localcd.o names.o number_decode.o number_encode.o pinentry.o \ - plmncodes.o revnibbles.o +OBJS= apdu.o apducmd.o atr.o cardconnect.o chkblank.o dumpdirfunc.o exit.o \ + globalopts.o hexdump.o localcd.o names.o LIB= libcommon.a all: ${LIB} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/alpha_decode.c --- a/libcommon/alpha_decode.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * This module contains functions for decoding and displaying alpha fields - * that exist in various SIM files. - */ - -#include -#include - -static void -print_alpha_field_hex(data, nbytes, outf) - u_char *data; - unsigned nbytes; - FILE *outf; -{ - u_char *dp, *endp; - - fputs("HEX ", outf); - dp = data; - endp = data + nbytes; - while (dp < endp) - fprintf(outf, "%02X", *dp++); -} - -void -print_alpha_field(data, nbytes, outf) - u_char *data; - unsigned nbytes; - FILE *outf; -{ - if (!nbytes) { - fputs("\"\"", outf); - return; - } - if (data[0] & 0x80) - print_alpha_field_hex(data, nbytes, outf); - else - print_gsm7_string_to_file(data, nbytes, outf); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/alpha_fromfile.c --- a/libcommon/alpha_fromfile.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * This module implements functions for parsing alpha tag strings - * from input data files, to be used by commands like pb-update - * and smsp-restore. - */ - -#include -#include -#include - -extern u_char gsm7_encode_table[256]; - -char * -alpha_from_file_qstring(cp, record, maxlen, filename_for_errs, lineno_for_errs) - char *cp, *filename_for_errs; - u_char *record; - unsigned maxlen; -{ - unsigned acclen, nadd; - int c; - - for (acclen = 0; ; ) { - if (*cp == '\0') { -unterm_qstring: fprintf(stderr, - "%s line %d: unterminated quoted string\n", - filename_for_errs, lineno_for_errs); - return(0); - } - if (*cp == '"') - break; - c = *cp++; - if (c == '\\') { - if (*cp == '\0') - goto unterm_qstring; - c = *cp++; - if (c >= '0' && c <= '7' && isxdigit(*cp)) { - c = ((c - '0') << 4) | decode_hex_digit(*cp++); - goto bypass_encoding; - } - switch (c) { - case 'n': - c = '\n'; - goto bypass_encoding; - case 'r': - c = '\r'; - goto bypass_encoding; - case 'e': - c = 0x1B; - goto bypass_encoding; - case '"': - case '\\': - break; - default: - fprintf(stderr, - "%s line %d: non-understood backslash escape\n", - filename_for_errs, lineno_for_errs); - return(0); - } - } - c = gsm7_encode_table[c]; - if (c == 0xFF) { - fprintf(stderr, - "%s line %d: character in quoted string cannot be encoded in GSM7\n", - filename_for_errs, lineno_for_errs); - return(0); - } -bypass_encoding: - if (c & 0x80) - nadd = 2; - else - nadd = 1; - if (acclen + nadd > maxlen) { - fprintf(stderr, - "%s line %d: alpha tag string is longer than SIM limit\n", - filename_for_errs, lineno_for_errs); - return(0); - } - if (c & 0x80) - record[acclen++] = 0x1B; - record[acclen++] = c & 0x7F; - } - return(cp + 1); -} - -char * -alpha_from_file_hex(cp, record, maxlen, filename_for_errs, lineno_for_errs) - char *cp, *filename_for_errs; - u_char *record; - unsigned maxlen; -{ - unsigned acclen; - - for (acclen = 0; ; ) { - if (!isxdigit(cp[0]) || !isxdigit(cp[1])) - break; - if (acclen >= maxlen) { - fprintf(stderr, - "%s line %d: alpha tag string is longer than SIM limit\n", - filename_for_errs, lineno_for_errs); - return(0); - } - record[acclen++] = (decode_hex_digit(cp[0]) << 4) | - decode_hex_digit(cp[1]); - cp += 2; - } - return(cp); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/alpha_valid.c --- a/libcommon/alpha_valid.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -/* - * This module contains functions for validating alpha fields - * that exist in various SIM files. - */ - -#include -#include -#include -#include -#include - -static -validate_classic_gsm(data, nbytes, textlenp) - u_char *data; - unsigned nbytes, *textlenp; -{ - u_char *dp; - unsigned n; - - dp = data; - for (n = 0; n < nbytes; n++) { - if (*dp == 0xFF) - break; - if (*dp & 0x80) - return(-1); - dp++; - } - if (textlenp) - *textlenp = n; - for (; n < nbytes; n++) - if (*dp++ != 0xFF) - return(-1); - return(0); -} - -static -validate_ucs2_80(data, nbytes, textlenp) - u_char *data; - unsigned nbytes, *textlenp; -{ - u_char *dp, *endp; - - if (nbytes < 3) - return(-1); - dp = data + 1; - endp = data + nbytes; - while (dp < endp) { - if (dp + 1 == endp) { - if (*dp != 0xFF) - return(-1); - if (textlenp) - *textlenp = dp - data; - return(0); - } - if (dp[0] == 0xFF && dp[1] == 0xFF) - break; - dp += 2; - } - if (textlenp) - *textlenp = dp - data; - while (dp < endp) - if (*dp++ != 0xFF) - return(-1); - return(0); -} - -static -validate_ucs2_81(data, nbytes, textlenp) - u_char *data; - unsigned nbytes, *textlenp; -{ - u_char *dp, *endp; - unsigned textlen; - - if (nbytes < 4) - return(-1); - if (!data[1]) - return(-1); - textlen = data[1] + 3; - if (textlen > nbytes) - return(-1); - if (textlenp) - *textlenp = textlen; - dp = data + textlen; - endp = data + nbytes; - while (dp < endp) - if (*dp++ != 0xFF) - return(-1); - return(0); -} - -static -validate_ucs2_82(data, nbytes, textlenp) - u_char *data; - unsigned nbytes, *textlenp; -{ - u_char *dp, *endp; - unsigned textlen; - - if (nbytes < 5) - return(-1); - if (!data[1]) - return(-1); - textlen = data[1] + 4; - if (textlen > nbytes) - return(-1); - if (textlenp) - *textlenp = textlen; - dp = data + textlen; - endp = data + nbytes; - while (dp < endp) - if (*dp++ != 0xFF) - return(-1); - return(0); -} - -static -validate_empty(data, nbytes, textlenp) - u_char *data; - unsigned nbytes, *textlenp; -{ - u_char *dp; - unsigned n; - - dp = data; - for (n = 0; n < nbytes; n++) - if (*dp++ != 0xFF) - return(-1); - if (textlenp) - *textlenp = 0; - return(0); -} - -validate_alpha_field(data, nbytes, textlenp) - u_char *data; - unsigned nbytes, *textlenp; -{ - if (data[0] < 0x80) - return validate_classic_gsm(data, nbytes, textlenp); - switch (data[0]) { - case 0x80: - return validate_ucs2_80(data, nbytes, textlenp); - case 0x81: - return validate_ucs2_81(data, nbytes, textlenp); - case 0x82: - return validate_ucs2_82(data, nbytes, textlenp); - case 0xFF: - return validate_empty(data, nbytes, textlenp); - default: - return -1; - } -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/decimal_str.c --- a/libcommon/decimal_str.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * This module implements some functions for initial parsing of decimal - * string arguments, intended for implementation of commands like - * write-iccid and write-imsi. - */ - -#include -#include -#include - -parse_decimal_string_arg(arg, dest, maxdigits) - char *arg; - u_char *dest; - unsigned maxdigits; -{ - unsigned n, ndig; - - if (!*arg) { - fprintf(stderr, - "error: empty argument given for decimal string\n"); - return(-1); - } - for (n = 0; *arg; ) { - if (!isdigit(*arg)) { - fprintf(stderr, - "error: non-digit char in decimal string argument\n"); - return(-1); - } - if (n >= maxdigits) { - fprintf(stderr, - "error: decimal string exceeds limit of %u digits\n", - maxdigits); - return(-1); - } - dest[n++] = *arg++ - '0'; - } - ndig = n; - while (n < maxdigits) - dest[n++] = 0xF; - return ndig; -} - -pack_reversed_nibbles(nibbles, bytes, nbytes) - u_char *nibbles, *bytes; - unsigned nbytes; -{ - u_char *sp, *dp; - unsigned n; - - sp = nibbles; - dp = bytes; - for (n = 0; n < nbytes; n++) { - *dp++ = sp[0] | (sp[1] << 4); - sp += 2; - } -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/filesearch.c --- a/libcommon/filesearch.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/* - * This module implements the function that searches for files - * in a dedicated directory for SIM programming scripts. - */ - -#include -#include -#include - -static char script_install_dir[] = "/opt/freecalypso/sim-scripts"; - -FILE * -open_script_input_file(req_filename) - char *req_filename; -{ - char pathbuf[256]; - FILE *f; - - if (!index(req_filename, '/') && strlen(req_filename) < 128) { - sprintf(pathbuf, "%s/%s", script_install_dir, req_filename); - f = fopen(pathbuf, "r"); - if (f) - return f; - } - f = fopen(req_filename, "r"); - return f; -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/gsm7_decode.c --- a/libcommon/gsm7_decode.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * This module contains functions for decoding GSM7 strings - * that exist in various SIM files. - */ - -#include -#include - -static char gsm7_decode_table[128] = { - '@', 0, '$', 0, 0, 0, 0, 0, - 0, 0, '\n', 0, 0, '\r', 0, 0, - 0, '_', 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - ' ', '!', '"', '#', 0, '%', '&', 0x27, - '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ':', ';', '<', '=', '>', '?', - 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', 0, 0, 0, 0, 0, - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', 0, 0, 0, 0, 0 -}; - -static char gsm7ext_decode_table[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, '^', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, '{', '}', 0, 0, 0, 0, 0, '\\', - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '[', '~', ']', 0, - '|', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -void -print_gsm7_string_to_file(data, nbytes, outf) - u_char *data; - unsigned nbytes; - FILE *outf; -{ - u_char *dp, *endp; - int b, c; - - dp = data; - endp = data + nbytes; - putc('"', outf); - while (dp < endp) { - b = *dp++; - if (b == 0x1B) { - if (dp >= endp || *dp == 0x1B || *dp == '\n' || - *dp == '\r') { - putc('\\', outf); - putc('e', outf); - continue; - } - b = *dp++; - c = gsm7ext_decode_table[b]; - if (!c) { - fprintf(outf, "\\e\\%02X", b); - continue; - } - } else { - c = gsm7_decode_table[b]; - if (!c) { - fprintf(outf, "\\%02X", b); - continue; - } - } - if (c == '\n') { - putc('\\', outf); - putc('n', outf); - continue; - } - if (c == '\r') { - putc('\\', outf); - putc('r', outf); - continue; - } - if (c == '"' || c == '\\') - putc('\\', outf); - putc(c, outf); - } - putc('"', outf); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/gsm7_encode.c --- a/libcommon/gsm7_encode.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * This module implements functions for parsing quoted string - * arguments intended for GSM7 string encoding, and actually - * encoding them into GSM7 binary strings. - */ - -#include -#include -#include - -extern u_char gsm7_encode_table[256]; - -qstring_arg_to_gsm7(arg, record, maxlen) - char *arg; - u_char *record; - unsigned maxlen; -{ - unsigned acclen, nadd; - char *cp; - int c; - - cp = arg; - for (acclen = 0; *cp; ) { - c = *cp++; - if (c == '\\') { - if (*cp == '\0') { - fprintf(stderr, - "error: dangling backslash escape\n"); - return(-1); - } - c = *cp++; - if (c >= '0' && c <= '7' && isxdigit(*cp)) { - c = ((c - '0') << 4) | decode_hex_digit(*cp++); - goto bypass_encoding; - } - switch (c) { - case 'n': - c = '\n'; - goto bypass_encoding; - case 'r': - c = '\r'; - goto bypass_encoding; - case 'e': - c = 0x1B; - goto bypass_encoding; - case '"': - case '\\': - break; - default: - fprintf(stderr, - "error: non-understood backslash escape\n"); - return(-1); - } - } - c = gsm7_encode_table[c]; - if (c == 0xFF) { - fprintf(stderr, - "error: character in alpha tag string cannot be encoded in GSM7\n"); - return(-1); - } -bypass_encoding: - if (c & 0x80) - nadd = 2; - else - nadd = 1; - if (acclen + nadd > maxlen) { - fprintf(stderr, - "error: alpha tag string is longer than SIM limit\n"); - return(-1); - } - if (c & 0x80) - record[acclen++] = 0x1B; - record[acclen++] = c & 0x7F; - } - return(acclen); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/gsm7_encode_table.c --- a/libcommon/gsm7_encode_table.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * This library module contains the table for encoding from ISO 8859-1 - * into the GSM 7-bit default alphabet (03.38 or 23.038). High bit set - * in the output indicates escape encoding, used for ASCII characters - * [\]^ and {|}~. 0xFF indicates invalid chars. - */ - -#include - -u_char gsm7_encode_table[256] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x00 */ - 0xFF, 0xFF, '\n', 0xFF, 0xFF, '\r', 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x10 */ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - ' ', '!', '"', '#', 0x02, '%', '&', 0x27, /* 0x20 */ - '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', /* 0x30 */ - '8', '9', ':', ';', '<', '=', '>', '?', - 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 0x40 */ - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 0x50 */ - 'X', 'Y', 'Z', 0xBC, 0xAF, 0xBE, 0x94, 0x11, - 0xFF, 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 0x60 */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 0x70 */ - 'x', 'y', 'z', 0xA8, 0xC0, 0xA9, 0xBD, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x80 */ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x90 */ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x40, 0xFF, 0x01, 0x24, 0x03, 0xFF, 0x5F, /* 0xA0 */ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0xB0 */ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, - 0xFF, 0xFF, 0xFF, 0xFF, 0x5B, 0x0E, 0x1C, 0x09, /* 0xC0 */ - 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0xFF, /* 0xD0 */ - 0x0B, 0xFF, 0xFF, 0xFF, 0x5E, 0xFF, 0xFF, 0x1E, - 0x7F, 0xFF, 0xFF, 0xFF, 0x7B, 0x0F, 0x1D, 0xFF, /* 0xE0 */ - 0x04, 0x05, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, - 0xFF, 0x7D, 0x08, 0xFF, 0xFF, 0xFF, 0x7C, 0xFF, /* 0xF0 */ - 0x0C, 0x06, 0xFF, 0xFF, 0x7E, 0xFF, 0xFF, 0xFF -}; diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/gsm7_unpack.c --- a/libcommon/gsm7_unpack.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/* - * This library module implements unpacking of GSM 7-bit data - * from packed octets. - */ - -#include - -static u_char shift[8] = {0, 7, 6, 5, 4, 3, 2, 1}; - -gsm7_unpack(inbuf, outbuf, nseptets) - u_char *inbuf, *outbuf; - unsigned nseptets; -{ - u_char *inp = inbuf, *outp = outbuf; - unsigned n; - - for (n = 0; n < nseptets; n++) { - *outp++ = (((inp[1] << 8) | inp[0]) >> shift[n&7]) & 0x7F; - if (n & 7) - inp++; - } -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/hexread.c --- a/libcommon/hexread.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * This module contains the function for reading hex files, - * to be used in the implementation of manual write commands. - */ - -#include -#include -#include -#include - -extern FILE *open_script_input_file(); - -read_hex_data_file(filename, databuf, maxlen) - char *filename; - u_char *databuf; - unsigned maxlen; -{ - FILE *inf; - unsigned count; - int c, c2; - - inf = open_script_input_file(filename); - if (!inf) { - perror(filename); - return(-1); - } - for (count = 0; ; count++) { - do - c = getc(inf); - while (isspace(c)); - if (c < 0) - break; - if (!isxdigit(c)) { -inv_input: fprintf(stderr, "%s: invalid hex file input\n", - filename); - fclose(inf); - return(-1); - } - c2 = getc(inf); - if (!isxdigit(c2)) - goto inv_input; - if (count >= maxlen) { - fprintf(stderr, "%s: hex input data is too long\n", - filename); - fclose(inf); - return(-1); - } - databuf[count] = (decode_hex_digit(c) << 4) | - decode_hex_digit(c2); - } - fclose(inf); - if (!count) { - fprintf(stderr, "%s: no hex data input found\n", filename); - return(-1); - } - return(count); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/hexstr.c --- a/libcommon/hexstr.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * This module contains the function for decoding hex strings. - */ - -#include -#include -#include -#include -#include -#include - -decode_hex_digit(c) -{ - if (c >= '0' && c <= '9') - return(c - '0'); - if (c >= 'A' && c <= 'F') - return(c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return(c - 'a' + 10); - return(-1); -} - -decode_hex_data_from_string(arg, databuf, minlen, maxlen) - char *arg; - u_char *databuf; - unsigned minlen, maxlen; -{ - unsigned count; - - for (count = 0; ; count++) { - while (isspace(*arg)) - arg++; - if (!*arg) - break; - if (!isxdigit(arg[0]) || !isxdigit(arg[1])) { - fprintf(stderr, "error: invalid hex string input\n"); - return(-1); - } - if (count >= maxlen) { - fprintf(stderr, "error: hex string is too long\n"); - return(-1); - } - databuf[count] = (decode_hex_digit(arg[0]) << 4) | - decode_hex_digit(arg[1]); - arg += 2; - } - if (count < minlen) { - fprintf(stderr, "error: hex string is too short\n"); - return(-1); - } - return(count); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/number_decode.c --- a/libcommon/number_decode.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * This module implements functions for decoding phone numbers. - */ - -#include - -static char gsm_address_digits[16] = - {'0','1','2','3','4','5','6','7','8','9','*','#','a','b','c','?'}; - -decode_phone_number(data, nbytes, out) - u_char *data; - unsigned nbytes; - char *out; -{ - u_char *dp, *endp; - int c; - - dp = data; - endp = data + nbytes; - while (dp < endp) { - c = *dp & 0xF; - if (c == 0xF) - return(-1); - *out++ = gsm_address_digits[c]; - c = *dp >> 4; - if (c == 0xF) { - if (dp + 1 == endp) - break; - else - return(-1); - } - *out++ = gsm_address_digits[c]; - dp++; - } - *out = '\0'; - return(0); -} - -decode_address_digits(inbuf, outbuf, ndigits) - u_char *inbuf; - char *outbuf; - unsigned ndigits; -{ - u_char *inp = inbuf; - char *outp = outbuf; - unsigned n = 0, b; - - while (n < ndigits) { - b = *inp++; - *outp++ = gsm_address_digits[b & 0xF]; - n++; - if (n >= ndigits) - break; - *outp++ = gsm_address_digits[b >> 4]; - n++; - } - *outp = '\0'; -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/number_encode.c --- a/libcommon/number_encode.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * This module implements functions for encoding phone numbers. - */ - -#include -#include -#include -#include - -digit_char_to_gsm(ch) -{ - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return (ch - '0'); - case '*': - return 0xA; - case '#': - return 0xB; - case 'a': - case 'b': - case 'c': - return (ch - 'a' + 0xC); - case 'A': - case 'B': - case 'C': - return (ch - 'A' + 0xC); - } - return (-1); -} - -void -pack_digit_bytes(digits, dest, num_digit_bytes) - u_char *digits, *dest; - unsigned num_digit_bytes; -{ - u_char *sp, *dp; - unsigned n; - - sp = digits; - dp = dest; - for (n = 0; n < num_digit_bytes; n++) { - *dp++ = sp[0] | (sp[1] << 4); - sp += 2; - } -} - -encode_phone_number_arg(arg, fixp, mode) - char *arg; - u_char *fixp; -{ - u_char digits[20]; - unsigned ndigits, num_digit_bytes; - char *cp, *endp; - int c; - - cp = arg; - if (*cp == '+') { - fixp[1] = 0x91; - cp++; - } else - fixp[1] = 0x81; - if (digit_char_to_gsm(*cp) < 0) { -inv_arg: fprintf(stderr, "error: invalid phone number argument\n"); - return(-1); - } - for (ndigits = 0; ; ndigits++) { - c = digit_char_to_gsm(*cp); - if (c < 0) - break; - cp++; - if (ndigits >= 20) { - fprintf(stderr, "error: too many number digits\n"); - return(-1); - } - digits[ndigits] = c; - } - if (mode) - fixp[0] = ndigits; - if (ndigits & 1) - digits[ndigits++] = 0xF; - num_digit_bytes = ndigits >> 1; - if (!mode) - fixp[0] = num_digit_bytes + 1; - pack_digit_bytes(digits, fixp + 2, num_digit_bytes); - if (*cp == ',') { - cp++; - if (!isdigit(*cp)) - goto inv_arg; - fixp[1] = strtoul(cp, &endp, 0); - if (*endp) - goto inv_arg; - } else if (*cp) - goto inv_arg; - return(0); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/pinentry.c --- a/libcommon/pinentry.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#include -#include -#include - -encode_pin_entry(arg, dest) - char *arg; - u_char *dest; -{ - unsigned n; - - n = 0; - while (*arg) { - if (!isdigit(*arg)) { - fprintf(stderr, - "error: PIN argument contains a non-digit character\n"); - return(-1); - } - if (n >= 8) { - fprintf(stderr, "error: PIN argument is too long\n"); - return(-1); - } - *dest++ = *arg++; - n++; - } - for (; n < 8; n++) - *dest++ = 0xFF; - return(0); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/plmncodes.c --- a/libcommon/plmncodes.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * This module implements some functions for working with MCC-MNC PLMN codes. - */ - -#include -#include -#include - -decode_plmn_3bytes(bin, asc, space_pad) - u_char *bin; - char *asc; -{ - asc[0] = encode_hex_digit(bin[0] & 0xF); - asc[1] = encode_hex_digit(bin[0] >> 4); - asc[2] = encode_hex_digit(bin[1] & 0xF); - asc[3] = '-'; - asc[4] = encode_hex_digit(bin[2] & 0xF); - asc[5] = encode_hex_digit(bin[2] >> 4); - asc[6] = encode_hex_digit(bin[1] >> 4); - asc[7] = '\0'; - if (asc[6] == 'F') { - if (space_pad) - asc[6] = ' '; - else - asc[6] = '\0'; - } -} - -encode_plmn_3bytes(asc, bin) - char *asc; - u_char *bin; -{ - u_char mcc[3], mnc[3]; - - if (!isxdigit(asc[0]) || !isxdigit(asc[1]) || !isxdigit(asc[2])) { -inv: fprintf(stderr, "error: invalid MCC-MNC argument\n"); - return(-1); - } - mcc[0] = decode_hex_digit(asc[0]); - mcc[1] = decode_hex_digit(asc[1]); - mcc[2] = decode_hex_digit(asc[2]); - asc += 3; - if (*asc == '-') - asc++; - if (!isxdigit(asc[0]) || !isxdigit(asc[1])) - goto inv; - mnc[0] = decode_hex_digit(asc[0]); - mnc[1] = decode_hex_digit(asc[1]); - asc += 2; - if (*asc == '\0') - mnc[2] = 0xF; - else if (isxdigit(asc[0]) && asc[1] == '\0') - mnc[2] = decode_hex_digit(*asc); - else - goto inv; - bin[0] = (mcc[1] << 4) | mcc[0]; - bin[1] = (mnc[2] << 4) | mcc[2]; - bin[2] = (mnc[1] << 4) | mnc[0]; - return(0); -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libcommon/revnibbles.c --- a/libcommon/revnibbles.c Thu Feb 25 20:55:10 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * This module implements some reversed-nibbles parsing functions. - */ - -#include - -encode_hex_digit(d) - unsigned d; -{ - if (d <= 9) - return(d + '0'); - else - return(d - 10 + 'A'); -} - -decode_reversed_nibbles(bytes, nbytes, dest) - u_char *bytes; - unsigned nbytes; - char *dest; -{ - u_char *sp; - char *dp; - unsigned n, c; - - sp = bytes; - dp = dest; - for (n = 0; n < nbytes; n++) { - c = *sp & 0xF; - *dp++ = encode_hex_digit(c); - c = *sp >> 4; - *dp++ = encode_hex_digit(c); - sp++; - } -} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/Makefile Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,16 @@ +CC= gcc +CFLAGS= -O2 +OBJS= alpha_decode.o alpha_fromfile.o alpha_valid.o decimal_str.o \ + filesearch.o gsm7_decode.o gsm7_encode.o gsm7_encode_table.o \ + gsm7_unpack.o hexread.o hexstr.o number_decode.o number_encode.o \ + pinentry.o plmncodes.o revnibbles.o +LIB= libutil.a + +all: ${LIB} + +${LIB}: ${OBJS} + ar rcu $@ ${OBJS} + ranlib $@ + +clean: + rm -f *.[oa] errs diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/alpha_decode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/alpha_decode.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,38 @@ +/* + * This module contains functions for decoding and displaying alpha fields + * that exist in various SIM files. + */ + +#include +#include + +static void +print_alpha_field_hex(data, nbytes, outf) + u_char *data; + unsigned nbytes; + FILE *outf; +{ + u_char *dp, *endp; + + fputs("HEX ", outf); + dp = data; + endp = data + nbytes; + while (dp < endp) + fprintf(outf, "%02X", *dp++); +} + +void +print_alpha_field(data, nbytes, outf) + u_char *data; + unsigned nbytes; + FILE *outf; +{ + if (!nbytes) { + fputs("\"\"", outf); + return; + } + if (data[0] & 0x80) + print_alpha_field_hex(data, nbytes, outf); + else + print_gsm7_string_to_file(data, nbytes, outf); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/alpha_fromfile.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/alpha_fromfile.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,107 @@ +/* + * This module implements functions for parsing alpha tag strings + * from input data files, to be used by commands like pb-update + * and smsp-restore. + */ + +#include +#include +#include + +extern u_char gsm7_encode_table[256]; + +char * +alpha_from_file_qstring(cp, record, maxlen, filename_for_errs, lineno_for_errs) + char *cp, *filename_for_errs; + u_char *record; + unsigned maxlen; +{ + unsigned acclen, nadd; + int c; + + for (acclen = 0; ; ) { + if (*cp == '\0') { +unterm_qstring: fprintf(stderr, + "%s line %d: unterminated quoted string\n", + filename_for_errs, lineno_for_errs); + return(0); + } + if (*cp == '"') + break; + c = *cp++; + if (c == '\\') { + if (*cp == '\0') + goto unterm_qstring; + c = *cp++; + if (c >= '0' && c <= '7' && isxdigit(*cp)) { + c = ((c - '0') << 4) | decode_hex_digit(*cp++); + goto bypass_encoding; + } + switch (c) { + case 'n': + c = '\n'; + goto bypass_encoding; + case 'r': + c = '\r'; + goto bypass_encoding; + case 'e': + c = 0x1B; + goto bypass_encoding; + case '"': + case '\\': + break; + default: + fprintf(stderr, + "%s line %d: non-understood backslash escape\n", + filename_for_errs, lineno_for_errs); + return(0); + } + } + c = gsm7_encode_table[c]; + if (c == 0xFF) { + fprintf(stderr, + "%s line %d: character in quoted string cannot be encoded in GSM7\n", + filename_for_errs, lineno_for_errs); + return(0); + } +bypass_encoding: + if (c & 0x80) + nadd = 2; + else + nadd = 1; + if (acclen + nadd > maxlen) { + fprintf(stderr, + "%s line %d: alpha tag string is longer than SIM limit\n", + filename_for_errs, lineno_for_errs); + return(0); + } + if (c & 0x80) + record[acclen++] = 0x1B; + record[acclen++] = c & 0x7F; + } + return(cp + 1); +} + +char * +alpha_from_file_hex(cp, record, maxlen, filename_for_errs, lineno_for_errs) + char *cp, *filename_for_errs; + u_char *record; + unsigned maxlen; +{ + unsigned acclen; + + for (acclen = 0; ; ) { + if (!isxdigit(cp[0]) || !isxdigit(cp[1])) + break; + if (acclen >= maxlen) { + fprintf(stderr, + "%s line %d: alpha tag string is longer than SIM limit\n", + filename_for_errs, lineno_for_errs); + return(0); + } + record[acclen++] = (decode_hex_digit(cp[0]) << 4) | + decode_hex_digit(cp[1]); + cp += 2; + } + return(cp); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/alpha_valid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/alpha_valid.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,152 @@ +/* + * This module contains functions for validating alpha fields + * that exist in various SIM files. + */ + +#include +#include +#include +#include +#include + +static +validate_classic_gsm(data, nbytes, textlenp) + u_char *data; + unsigned nbytes, *textlenp; +{ + u_char *dp; + unsigned n; + + dp = data; + for (n = 0; n < nbytes; n++) { + if (*dp == 0xFF) + break; + if (*dp & 0x80) + return(-1); + dp++; + } + if (textlenp) + *textlenp = n; + for (; n < nbytes; n++) + if (*dp++ != 0xFF) + return(-1); + return(0); +} + +static +validate_ucs2_80(data, nbytes, textlenp) + u_char *data; + unsigned nbytes, *textlenp; +{ + u_char *dp, *endp; + + if (nbytes < 3) + return(-1); + dp = data + 1; + endp = data + nbytes; + while (dp < endp) { + if (dp + 1 == endp) { + if (*dp != 0xFF) + return(-1); + if (textlenp) + *textlenp = dp - data; + return(0); + } + if (dp[0] == 0xFF && dp[1] == 0xFF) + break; + dp += 2; + } + if (textlenp) + *textlenp = dp - data; + while (dp < endp) + if (*dp++ != 0xFF) + return(-1); + return(0); +} + +static +validate_ucs2_81(data, nbytes, textlenp) + u_char *data; + unsigned nbytes, *textlenp; +{ + u_char *dp, *endp; + unsigned textlen; + + if (nbytes < 4) + return(-1); + if (!data[1]) + return(-1); + textlen = data[1] + 3; + if (textlen > nbytes) + return(-1); + if (textlenp) + *textlenp = textlen; + dp = data + textlen; + endp = data + nbytes; + while (dp < endp) + if (*dp++ != 0xFF) + return(-1); + return(0); +} + +static +validate_ucs2_82(data, nbytes, textlenp) + u_char *data; + unsigned nbytes, *textlenp; +{ + u_char *dp, *endp; + unsigned textlen; + + if (nbytes < 5) + return(-1); + if (!data[1]) + return(-1); + textlen = data[1] + 4; + if (textlen > nbytes) + return(-1); + if (textlenp) + *textlenp = textlen; + dp = data + textlen; + endp = data + nbytes; + while (dp < endp) + if (*dp++ != 0xFF) + return(-1); + return(0); +} + +static +validate_empty(data, nbytes, textlenp) + u_char *data; + unsigned nbytes, *textlenp; +{ + u_char *dp; + unsigned n; + + dp = data; + for (n = 0; n < nbytes; n++) + if (*dp++ != 0xFF) + return(-1); + if (textlenp) + *textlenp = 0; + return(0); +} + +validate_alpha_field(data, nbytes, textlenp) + u_char *data; + unsigned nbytes, *textlenp; +{ + if (data[0] < 0x80) + return validate_classic_gsm(data, nbytes, textlenp); + switch (data[0]) { + case 0x80: + return validate_ucs2_80(data, nbytes, textlenp); + case 0x81: + return validate_ucs2_81(data, nbytes, textlenp); + case 0x82: + return validate_ucs2_82(data, nbytes, textlenp); + case 0xFF: + return validate_empty(data, nbytes, textlenp); + default: + return -1; + } +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/decimal_str.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/decimal_str.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,56 @@ +/* + * This module implements some functions for initial parsing of decimal + * string arguments, intended for implementation of commands like + * write-iccid and write-imsi. + */ + +#include +#include +#include + +parse_decimal_string_arg(arg, dest, maxdigits) + char *arg; + u_char *dest; + unsigned maxdigits; +{ + unsigned n, ndig; + + if (!*arg) { + fprintf(stderr, + "error: empty argument given for decimal string\n"); + return(-1); + } + for (n = 0; *arg; ) { + if (!isdigit(*arg)) { + fprintf(stderr, + "error: non-digit char in decimal string argument\n"); + return(-1); + } + if (n >= maxdigits) { + fprintf(stderr, + "error: decimal string exceeds limit of %u digits\n", + maxdigits); + return(-1); + } + dest[n++] = *arg++ - '0'; + } + ndig = n; + while (n < maxdigits) + dest[n++] = 0xF; + return ndig; +} + +pack_reversed_nibbles(nibbles, bytes, nbytes) + u_char *nibbles, *bytes; + unsigned nbytes; +{ + u_char *sp, *dp; + unsigned n; + + sp = nibbles; + dp = bytes; + for (n = 0; n < nbytes; n++) { + *dp++ = sp[0] | (sp[1] << 4); + sp += 2; + } +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/filesearch.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/filesearch.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,27 @@ +/* + * This module implements the function that searches for files + * in a dedicated directory for SIM programming scripts. + */ + +#include +#include +#include + +static char script_install_dir[] = "/opt/freecalypso/sim-scripts"; + +FILE * +open_script_input_file(req_filename) + char *req_filename; +{ + char pathbuf[256]; + FILE *f; + + if (!index(req_filename, '/') && strlen(req_filename) < 128) { + sprintf(pathbuf, "%s/%s", script_install_dir, req_filename); + f = fopen(pathbuf, "r"); + if (f) + return f; + } + f = fopen(req_filename, "r"); + return f; +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/gsm7_decode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/gsm7_decode.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,88 @@ +/* + * This module contains functions for decoding GSM7 strings + * that exist in various SIM files. + */ + +#include +#include + +static char gsm7_decode_table[128] = { + '@', 0, '$', 0, 0, 0, 0, 0, + 0, 0, '\n', 0, 0, '\r', 0, 0, + 0, '_', 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ' ', '!', '"', '#', 0, '%', '&', 0x27, + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 0, 0, 0, 0, 0, + 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', 0, 0, 0, 0, 0 +}; + +static char gsm7ext_decode_table[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, '^', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, '{', '}', 0, 0, 0, 0, 0, '\\', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '[', '~', ']', 0, + '|', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void +print_gsm7_string_to_file(data, nbytes, outf) + u_char *data; + unsigned nbytes; + FILE *outf; +{ + u_char *dp, *endp; + int b, c; + + dp = data; + endp = data + nbytes; + putc('"', outf); + while (dp < endp) { + b = *dp++; + if (b == 0x1B) { + if (dp >= endp || *dp == 0x1B || *dp == '\n' || + *dp == '\r') { + putc('\\', outf); + putc('e', outf); + continue; + } + b = *dp++; + c = gsm7ext_decode_table[b]; + if (!c) { + fprintf(outf, "\\e\\%02X", b); + continue; + } + } else { + c = gsm7_decode_table[b]; + if (!c) { + fprintf(outf, "\\%02X", b); + continue; + } + } + if (c == '\n') { + putc('\\', outf); + putc('n', outf); + continue; + } + if (c == '\r') { + putc('\\', outf); + putc('r', outf); + continue; + } + if (c == '"' || c == '\\') + putc('\\', outf); + putc(c, outf); + } + putc('"', outf); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/gsm7_encode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/gsm7_encode.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,76 @@ +/* + * This module implements functions for parsing quoted string + * arguments intended for GSM7 string encoding, and actually + * encoding them into GSM7 binary strings. + */ + +#include +#include +#include + +extern u_char gsm7_encode_table[256]; + +qstring_arg_to_gsm7(arg, record, maxlen) + char *arg; + u_char *record; + unsigned maxlen; +{ + unsigned acclen, nadd; + char *cp; + int c; + + cp = arg; + for (acclen = 0; *cp; ) { + c = *cp++; + if (c == '\\') { + if (*cp == '\0') { + fprintf(stderr, + "error: dangling backslash escape\n"); + return(-1); + } + c = *cp++; + if (c >= '0' && c <= '7' && isxdigit(*cp)) { + c = ((c - '0') << 4) | decode_hex_digit(*cp++); + goto bypass_encoding; + } + switch (c) { + case 'n': + c = '\n'; + goto bypass_encoding; + case 'r': + c = '\r'; + goto bypass_encoding; + case 'e': + c = 0x1B; + goto bypass_encoding; + case '"': + case '\\': + break; + default: + fprintf(stderr, + "error: non-understood backslash escape\n"); + return(-1); + } + } + c = gsm7_encode_table[c]; + if (c == 0xFF) { + fprintf(stderr, + "error: character in alpha tag string cannot be encoded in GSM7\n"); + return(-1); + } +bypass_encoding: + if (c & 0x80) + nadd = 2; + else + nadd = 1; + if (acclen + nadd > maxlen) { + fprintf(stderr, + "error: alpha tag string is longer than SIM limit\n"); + return(-1); + } + if (c & 0x80) + record[acclen++] = 0x1B; + record[acclen++] = c & 0x7F; + } + return(acclen); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/gsm7_encode_table.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/gsm7_encode_table.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,43 @@ +/* + * This library module contains the table for encoding from ISO 8859-1 + * into the GSM 7-bit default alphabet (03.38 or 23.038). High bit set + * in the output indicates escape encoding, used for ASCII characters + * [\]^ and {|}~. 0xFF indicates invalid chars. + */ + +#include + +u_char gsm7_encode_table[256] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x00 */ + 0xFF, 0xFF, '\n', 0xFF, 0xFF, '\r', 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x10 */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + ' ', '!', '"', '#', 0x02, '%', '&', 0x27, /* 0x20 */ + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', /* 0x30 */ + '8', '9', ':', ';', '<', '=', '>', '?', + 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 0x40 */ + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 0x50 */ + 'X', 'Y', 'Z', 0xBC, 0xAF, 0xBE, 0x94, 0x11, + 0xFF, 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 0x60 */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 0x70 */ + 'x', 'y', 'z', 0xA8, 0xC0, 0xA9, 0xBD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x80 */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0x90 */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x40, 0xFF, 0x01, 0x24, 0x03, 0xFF, 0x5F, /* 0xA0 */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 0xB0 */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, + 0xFF, 0xFF, 0xFF, 0xFF, 0x5B, 0x0E, 0x1C, 0x09, /* 0xC0 */ + 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0xFF, /* 0xD0 */ + 0x0B, 0xFF, 0xFF, 0xFF, 0x5E, 0xFF, 0xFF, 0x1E, + 0x7F, 0xFF, 0xFF, 0xFF, 0x7B, 0x0F, 0x1D, 0xFF, /* 0xE0 */ + 0x04, 0x05, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, + 0xFF, 0x7D, 0x08, 0xFF, 0xFF, 0xFF, 0x7C, 0xFF, /* 0xF0 */ + 0x0C, 0x06, 0xFF, 0xFF, 0x7E, 0xFF, 0xFF, 0xFF +}; diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/gsm7_unpack.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/gsm7_unpack.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,22 @@ +/* + * This library module implements unpacking of GSM 7-bit data + * from packed octets. + */ + +#include + +static u_char shift[8] = {0, 7, 6, 5, 4, 3, 2, 1}; + +gsm7_unpack(inbuf, outbuf, nseptets) + u_char *inbuf, *outbuf; + unsigned nseptets; +{ + u_char *inp = inbuf, *outp = outbuf; + unsigned n; + + for (n = 0; n < nseptets; n++) { + *outp++ = (((inp[1] << 8) | inp[0]) >> shift[n&7]) & 0x7F; + if (n & 7) + inp++; + } +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/hexread.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/hexread.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,57 @@ +/* + * This module contains the function for reading hex files, + * to be used in the implementation of manual write commands. + */ + +#include +#include +#include +#include + +extern FILE *open_script_input_file(); + +read_hex_data_file(filename, databuf, maxlen) + char *filename; + u_char *databuf; + unsigned maxlen; +{ + FILE *inf; + unsigned count; + int c, c2; + + inf = open_script_input_file(filename); + if (!inf) { + perror(filename); + return(-1); + } + for (count = 0; ; count++) { + do + c = getc(inf); + while (isspace(c)); + if (c < 0) + break; + if (!isxdigit(c)) { +inv_input: fprintf(stderr, "%s: invalid hex file input\n", + filename); + fclose(inf); + return(-1); + } + c2 = getc(inf); + if (!isxdigit(c2)) + goto inv_input; + if (count >= maxlen) { + fprintf(stderr, "%s: hex input data is too long\n", + filename); + fclose(inf); + return(-1); + } + databuf[count] = (decode_hex_digit(c) << 4) | + decode_hex_digit(c2); + } + fclose(inf); + if (!count) { + fprintf(stderr, "%s: no hex data input found\n", filename); + return(-1); + } + return(count); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/hexstr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/hexstr.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,52 @@ +/* + * This module contains the function for decoding hex strings. + */ + +#include +#include +#include +#include +#include +#include + +decode_hex_digit(c) +{ + if (c >= '0' && c <= '9') + return(c - '0'); + if (c >= 'A' && c <= 'F') + return(c - 'A' + 10); + if (c >= 'a' && c <= 'f') + return(c - 'a' + 10); + return(-1); +} + +decode_hex_data_from_string(arg, databuf, minlen, maxlen) + char *arg; + u_char *databuf; + unsigned minlen, maxlen; +{ + unsigned count; + + for (count = 0; ; count++) { + while (isspace(*arg)) + arg++; + if (!*arg) + break; + if (!isxdigit(arg[0]) || !isxdigit(arg[1])) { + fprintf(stderr, "error: invalid hex string input\n"); + return(-1); + } + if (count >= maxlen) { + fprintf(stderr, "error: hex string is too long\n"); + return(-1); + } + databuf[count] = (decode_hex_digit(arg[0]) << 4) | + decode_hex_digit(arg[1]); + arg += 2; + } + if (count < minlen) { + fprintf(stderr, "error: hex string is too short\n"); + return(-1); + } + return(count); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/number_decode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/number_decode.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,58 @@ +/* + * This module implements functions for decoding phone numbers. + */ + +#include + +static char gsm_address_digits[16] = + {'0','1','2','3','4','5','6','7','8','9','*','#','a','b','c','?'}; + +decode_phone_number(data, nbytes, out) + u_char *data; + unsigned nbytes; + char *out; +{ + u_char *dp, *endp; + int c; + + dp = data; + endp = data + nbytes; + while (dp < endp) { + c = *dp & 0xF; + if (c == 0xF) + return(-1); + *out++ = gsm_address_digits[c]; + c = *dp >> 4; + if (c == 0xF) { + if (dp + 1 == endp) + break; + else + return(-1); + } + *out++ = gsm_address_digits[c]; + dp++; + } + *out = '\0'; + return(0); +} + +decode_address_digits(inbuf, outbuf, ndigits) + u_char *inbuf; + char *outbuf; + unsigned ndigits; +{ + u_char *inp = inbuf; + char *outp = outbuf; + unsigned n = 0, b; + + while (n < ndigits) { + b = *inp++; + *outp++ = gsm_address_digits[b & 0xF]; + n++; + if (n >= ndigits) + break; + *outp++ = gsm_address_digits[b >> 4]; + n++; + } + *outp = '\0'; +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/number_encode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/number_encode.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,104 @@ +/* + * This module implements functions for encoding phone numbers. + */ + +#include +#include +#include +#include + +digit_char_to_gsm(ch) +{ + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return (ch - '0'); + case '*': + return 0xA; + case '#': + return 0xB; + case 'a': + case 'b': + case 'c': + return (ch - 'a' + 0xC); + case 'A': + case 'B': + case 'C': + return (ch - 'A' + 0xC); + } + return (-1); +} + +void +pack_digit_bytes(digits, dest, num_digit_bytes) + u_char *digits, *dest; + unsigned num_digit_bytes; +{ + u_char *sp, *dp; + unsigned n; + + sp = digits; + dp = dest; + for (n = 0; n < num_digit_bytes; n++) { + *dp++ = sp[0] | (sp[1] << 4); + sp += 2; + } +} + +encode_phone_number_arg(arg, fixp, mode) + char *arg; + u_char *fixp; +{ + u_char digits[20]; + unsigned ndigits, num_digit_bytes; + char *cp, *endp; + int c; + + cp = arg; + if (*cp == '+') { + fixp[1] = 0x91; + cp++; + } else + fixp[1] = 0x81; + if (digit_char_to_gsm(*cp) < 0) { +inv_arg: fprintf(stderr, "error: invalid phone number argument\n"); + return(-1); + } + for (ndigits = 0; ; ndigits++) { + c = digit_char_to_gsm(*cp); + if (c < 0) + break; + cp++; + if (ndigits >= 20) { + fprintf(stderr, "error: too many number digits\n"); + return(-1); + } + digits[ndigits] = c; + } + if (mode) + fixp[0] = ndigits; + if (ndigits & 1) + digits[ndigits++] = 0xF; + num_digit_bytes = ndigits >> 1; + if (!mode) + fixp[0] = num_digit_bytes + 1; + pack_digit_bytes(digits, fixp + 2, num_digit_bytes); + if (*cp == ',') { + cp++; + if (!isdigit(*cp)) + goto inv_arg; + fixp[1] = strtoul(cp, &endp, 0); + if (*endp) + goto inv_arg; + } else if (*cp) + goto inv_arg; + return(0); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/pinentry.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/pinentry.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,28 @@ +#include +#include +#include + +encode_pin_entry(arg, dest) + char *arg; + u_char *dest; +{ + unsigned n; + + n = 0; + while (*arg) { + if (!isdigit(*arg)) { + fprintf(stderr, + "error: PIN argument contains a non-digit character\n"); + return(-1); + } + if (n >= 8) { + fprintf(stderr, "error: PIN argument is too long\n"); + return(-1); + } + *dest++ = *arg++; + n++; + } + for (; n < 8; n++) + *dest++ = 0xFF; + return(0); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/plmncodes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/plmncodes.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,60 @@ +/* + * This module implements some functions for working with MCC-MNC PLMN codes. + */ + +#include +#include +#include + +decode_plmn_3bytes(bin, asc, space_pad) + u_char *bin; + char *asc; +{ + asc[0] = encode_hex_digit(bin[0] & 0xF); + asc[1] = encode_hex_digit(bin[0] >> 4); + asc[2] = encode_hex_digit(bin[1] & 0xF); + asc[3] = '-'; + asc[4] = encode_hex_digit(bin[2] & 0xF); + asc[5] = encode_hex_digit(bin[2] >> 4); + asc[6] = encode_hex_digit(bin[1] >> 4); + asc[7] = '\0'; + if (asc[6] == 'F') { + if (space_pad) + asc[6] = ' '; + else + asc[6] = '\0'; + } +} + +encode_plmn_3bytes(asc, bin) + char *asc; + u_char *bin; +{ + u_char mcc[3], mnc[3]; + + if (!isxdigit(asc[0]) || !isxdigit(asc[1]) || !isxdigit(asc[2])) { +inv: fprintf(stderr, "error: invalid MCC-MNC argument\n"); + return(-1); + } + mcc[0] = decode_hex_digit(asc[0]); + mcc[1] = decode_hex_digit(asc[1]); + mcc[2] = decode_hex_digit(asc[2]); + asc += 3; + if (*asc == '-') + asc++; + if (!isxdigit(asc[0]) || !isxdigit(asc[1])) + goto inv; + mnc[0] = decode_hex_digit(asc[0]); + mnc[1] = decode_hex_digit(asc[1]); + asc += 2; + if (*asc == '\0') + mnc[2] = 0xF; + else if (isxdigit(asc[0]) && asc[1] == '\0') + mnc[2] = decode_hex_digit(*asc); + else + goto inv; + bin[0] = (mcc[1] << 4) | mcc[0]; + bin[1] = (mnc[2] << 4) | mcc[2]; + bin[2] = (mnc[1] << 4) | mnc[0]; + return(0); +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 libutil/revnibbles.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libutil/revnibbles.c Fri Feb 26 20:19:58 2021 +0000 @@ -0,0 +1,34 @@ +/* + * This module implements some reversed-nibbles parsing functions. + */ + +#include + +encode_hex_digit(d) + unsigned d; +{ + if (d <= 9) + return(d + '0'); + else + return(d - 10 + 'A'); +} + +decode_reversed_nibbles(bytes, nbytes, dest) + u_char *bytes; + unsigned nbytes; + char *dest; +{ + u_char *sp; + char *dp; + unsigned n, c; + + sp = bytes; + dp = dest; + for (n = 0; n < nbytes; n++) { + c = *sp & 0xF; + *dp++ = encode_hex_digit(c); + c = *sp >> 4; + *dp++ = encode_hex_digit(c); + sp++; + } +} diff -r 5f1f3f6fd865 -r f064dbcc5f41 misc/Makefile --- a/misc/Makefile Thu Feb 25 20:55:10 2021 +0000 +++ b/misc/Makefile Fri Feb 26 20:19:58 2021 +0000 @@ -1,7 +1,7 @@ CC= gcc CFLAGS= -O2 -I/usr/include/PCSC -I../libcommon PROGS= fc-pcsc-atr fc-pcsc-list -LIBS= ../libcommon/libcommon.a +LIBS= ../libcommon/libcommon.a ../libutil/libutil.a INSTBIN=/opt/freecalypso/bin all: ${PROGS} diff -r 5f1f3f6fd865 -r f064dbcc5f41 simtool/Makefile --- a/simtool/Makefile Thu Feb 25 20:55:10 2021 +0000 +++ b/simtool/Makefile Fri Feb 26 20:19:58 2021 +0000 @@ -8,7 +8,7 @@ restorebin.o savebin.o script.o select.o smserase.o smsp_common.o \ smsp_dump.o smsp_erase.o smsp_restore.o smsp_set.o sstlist.o stktest.o \ sysmo.o telsum.o usersum.o writecmd.o writeops.o -LIBS= ../libcommon/libcommon.a +LIBS= ../libcommon/libcommon.a ../libutil/libutil.a INSTBIN=/opt/freecalypso/bin all: ${PROG} diff -r 5f1f3f6fd865 -r f064dbcc5f41 uicc/Makefile --- a/uicc/Makefile Thu Feb 25 20:55:10 2021 +0000 +++ b/uicc/Makefile Fri Feb 26 20:19:58 2021 +0000 @@ -3,7 +3,7 @@ PROG= fc-uicc-tool OBJS= bfsearch.o createfile.o dispatch.o dumpdir.o getresp.o hlread.o main.o \ pins.o readcmd.o readops.o script.o select.o writecmd.o writeops.o -LIBS= ../libcommon/libcommon.a +LIBS= ../libcommon/libcommon.a ../libutil/libutil.a INSTBIN=/opt/freecalypso/bin all: ${PROG}