Project

General

Profile

Download (4.29 KB) Statistics
| Branch: | Revision:
1
/* Copyright 2020 sysmocom s.f.m.c. GmbH
2
 * SPDX-License-Identifier: Apache-2.0 */
3
package org.osmocom.IMSIPseudo;
4

    
5
public class MobileIdentity {
6
	public static final byte MI_IMSI = 1;
7

    
8
	/* Convert BCD-encoded digit into printable character
9
	 *  \param[in] bcd A single BCD-encoded digit
10
	 *  \returns single printable character
11
	 */
12
	public static byte bcd2char(byte bcd)
13
	{
14
		if (bcd < 0xa)
15
			return (byte)('0' + bcd);
16
		else
17
			return (byte)('A' + (bcd - 0xa));
18
	}
19

    
20
	/* Convert BCD to string.
21
	 * The given nibble offsets are interpreted in BCD order, i.e. nibble 0 is bcd[0] & 0xf, nibble 1 is bcd[0] >> 4, nibble
22
	 * 3 is bcd[1] & 0xf, etc..
23
	 *  \param[out] dst  Output byte array.
24
	 *  \param[in] dst_ofs  Where to start writing in dst.
25
	 *  \param[in] dst_len  How many bytes are available at dst_ofs.
26
	 *  \param[in] bcd  Binary coded data buffer.
27
	 *  \param[in] start_nibble  Offset to start from, in nibbles.
28
	 *  \param[in] end_nibble  Offset to stop before, in nibbles.
29
	 *  \param[in] allow_hex  If false, return false if there are digits other than 0-9.
30
	 *  \returns true on success, false otherwise
31
	 */
32
	public static boolean bcd2str(byte dst[], byte dst_ofs, byte dst_len,
33
				      byte bcd[], byte start_nibble, byte end_nibble, boolean allow_hex)
34
	{
35
		byte nibble_i;
36
		byte dst_i = dst_ofs;
37
		byte dst_end = (byte)(dst_ofs + dst_len);
38
		boolean rc = true;
39

    
40
		for (nibble_i = start_nibble; nibble_i < end_nibble && dst_i < dst_end; nibble_i++, dst_i++) {
41
			byte nibble = bcd[(byte)nibble_i >> 1];
42
			if ((nibble_i & 1) != 0)
43
				nibble >>= 4;
44
			nibble &= 0xf;
45

    
46
			if (!allow_hex && nibble > 9)
47
				rc = false;
48

    
49
			dst[dst_i] = bcd2char(nibble);
50
		}
51

    
52
		return rc;
53
	}
54

    
55
	public static byte[] mi2str(byte mi[])
56
	{
57
		/* The IMSI byte array by example:
58
		 * 08 99 10 07 00 00 10 74 90
59
		 *
60
		 * This is encoded according to 3GPP TS 24.008 10.5.1.4 Mobile
61
		 * Identity, short the Mobile Identity IEI:
62
		 *
63
		 * 08 length for the following MI, in bytes.
64
		 *  9 = 0b1001
65
		 *	1 = odd nr of digits
66
		 *	 001 = MI type = IMSI
67
		 * 9  first IMSI digit (BCD)
68
		 *  0 second digit
69
		 * 1  third
70
		 * ...
71
		 *  0 14th digit
72
		 * 9  15th and last digit
73
		 *
74
		 * If the IMSI had an even number of digits:
75
		 *
76
		 * 08 98 10 07 00 00 10 74 f0
77
		 *
78
		 * 08 length for the following MI, in bytes.
79
		 *  8 = 0b0001
80
		 *	0 = even nr of digits
81
		 *	 001 = MI type = IMSI
82
		 * 9  first IMSI digit
83
		 *  0 second digit
84
		 * 1  third
85
		 * ...
86
		 *  0 14th and last digit
87
		 * f  filler
88
		 */
89
		byte bytelen = mi[0];
90
		byte mi_type = (byte)(mi[1] & 0xf);
91
		boolean odd_nr_of_digits = ((mi_type & 0x08) != 0);
92
		byte start_nibble = 2 + 1; // 2 to skip the bytelen, 1 to skip the mi_type
93
		byte end_nibble = (byte)(2 + bytelen * 2 - (odd_nr_of_digits ? 0 : 1));
94
		byte str[] = new byte[end_nibble - start_nibble];
95
		bcd2str(str, (byte)0, (byte)str.length, mi, start_nibble, end_nibble, true);
96
		return str;
97
	}
98

    
99
	public static byte char2bcd(byte c)
100
	{
101
		if (c >= '0' && c <= '9')
102
			return (byte)(c - '0');
103
		else if (c >= 'A' && c <= 'F')
104
			return (byte)(0xa + (c - 'A'));
105
		else if (c >= 'a' && c <= 'f')
106
			return (byte)(0xa + (c - 'a'));
107
		else
108
			return 0;
109
	}
110

    
111
	public static byte[] str2mi(byte str[], byte mi_type, byte min_buflen)
112
	{
113
		boolean odd_digits = ((str.length & 1) != 0);
114
		/* 1 nibble of mi_type.
115
		 * str.length nibbles of MI BCD.
116
		 */
117
		byte mi_nibbles = (byte)(1 + str.length);
118
		byte mi_bytes = (byte)(mi_nibbles / 2 + ((mi_nibbles & 1) != 0? 1 : 0));
119
		/* 1 byte of total MI length in bytes, plus the MI nibbles */
120
		byte buflen = (byte)(1 + mi_bytes);
121
		/* Fill up with 0xff to the requested buffer size */
122
		if (buflen < min_buflen)
123
			buflen = min_buflen;
124
		byte buf[] = new byte[buflen];
125

    
126
		for (byte i = 0; i < buf.length; i++)
127
			buf[i] = (byte)0xff;
128

    
129
		/* 1 byte of following MI length in bytes */
130
		buf[0] = mi_bytes;
131

    
132
		/* first MI byte: low nibble has the MI type and odd/even indicator bit,
133
		 * high nibble has the first BCD digit.
134
		 */
135
		mi_type = (byte)(mi_type & 0x07);
136
		if (odd_digits)
137
			mi_type |= 0x08;
138
		buf[1] = (byte)((char2bcd(str[0]) << 4) + mi_type);
139

    
140
		/* fill in the remaining MI nibbles */
141
		byte str_i = 1;
142
		for (byte mi_i = 1; mi_i < mi_bytes; mi_i++) {
143
			byte data = char2bcd(str[str_i++]);
144
			if (str_i < str.length)
145
				data |= char2bcd(str[str_i++]) << 4;
146
			else
147
				data |= 0xf0;
148
			buf[1 + mi_i] = data;
149
		}
150
		return buf;
151
	}
152
}
(3-3/4)
Add picture from clipboard (Maximum size: 48.8 MB)