Change in libosmocore[master]: gsm23003: add osmo_imei_str_valid()

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

osmith gerrit-no-reply at lists.osmocom.org
Mon Jan 14 14:39:57 UTC 2019


osmith has submitted this change and it was merged. ( https://gerrit.osmocom.org/12524 )

Change subject: gsm23003: add osmo_imei_str_valid()
......................................................................

gsm23003: add osmo_imei_str_valid()

Verify 14 digit and 15 digit IMEI strings. OsmoHLR will use the 14
digit version to check IMEIs before writing them to the DB.

Place the Luhn checksum code in a dedicated osmo_luhn() function, so
it can be used elsewhere.

Related: OS#2541
Change-Id: Id2d2a3a93b033bafc74c62e15297034bf4aafe61
---
M include/osmocom/core/utils.h
M include/osmocom/gsm/gsm23003.h
M src/gsm/gsm23003.c
M src/gsm/libosmogsm.map
M src/utils.c
M tests/gsm23003/gsm23003_test.c
M tests/gsm23003/gsm23003_test.ok
7 files changed, 107 insertions(+), 0 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h
index 04f2fb4..987080e 100644
--- a/include/osmocom/core/utils.h
+++ b/include/osmocom/core/utils.h
@@ -140,4 +140,6 @@
 
 uint32_t osmo_isqrt32(uint32_t x);
 
+const char osmo_luhn(const char* in, int in_len);
+
 /*! @} */
diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h
index 2f380ae..b5c8dcd 100644
--- a/include/osmocom/gsm/gsm23003.h
+++ b/include/osmocom/gsm/gsm23003.h
@@ -93,6 +93,7 @@
 
 bool osmo_imsi_str_valid(const char *imsi);
 bool osmo_msisdn_str_valid(const char *msisdn);
+bool osmo_imei_str_valid(const char *imei, bool with_15th_digit);
 
 const char *osmo_mcc_name(uint16_t mcc);
 const char *osmo_mnc_name(uint16_t mnc, bool mnc_3_digits);
diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c
index 4fdad48..1d9cefe 100644
--- a/src/gsm/gsm23003.c
+++ b/src/gsm/gsm23003.c
@@ -31,6 +31,7 @@
 
 #include <osmocom/gsm/gsm23003.h>
 #include <osmocom/gsm/protocol/gsm_23_003.h>
+#include <osmocom/core/utils.h>
 
 static bool is_n_digits(const char *str, int min_digits, int max_digits)
 {
@@ -71,6 +72,23 @@
 	return is_n_digits(msisdn, 1, 15);
 }
 
+/*! Determine whether the given IMEI is valid according to 3GPP TS 23.003,
+ * Section 6.2.1. It consists of 14 digits, the 15th check digit is not
+ * intended for digital transmission.
+ * \param imei  IMEI digits in ASCII string representation.
+ * \param with_15th_digit  when true, expect the 15th digit to be present and
+ *        verify it.
+ * \returns true when the IMEI is valid, false for invalid characters or number
+ *          of digits.
+ */
+bool osmo_imei_str_valid(const char *imei, bool with_15th_digit)
+{
+	if (with_15th_digit)
+		return is_n_digits(imei, 15, 15) && osmo_luhn(imei, 14) == imei[14];
+	else
+		return is_n_digits(imei, 14, 14);
+}
+
 /*! Return MCC string as standardized 3-digit with leading zeros.
  * \param[in] mcc  MCC value.
  * \returns string in static buffer.
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index a903787..331c3f0 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -551,6 +551,7 @@
 
 osmo_imsi_str_valid;
 osmo_msisdn_str_valid;
+osmo_imei_str_valid;
 
 osmo_mncc_stringify;
 osmo_mncc_names;
diff --git a/src/utils.c b/src/utils.c
index 35d70ac..d1da4fa 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -765,4 +765,35 @@
 	return buf;
 }
 
+/*! Calculate the Luhn checksum (as used for IMEIs).
+ * \param[in] in  Input digits in ASCII string representation.
+ * \param[in] in_len  Count of digits to use for the input (14 for IMEI).
+ * \returns checksum char (e.g. '3'); negative on error
+ */
+const char osmo_luhn(const char* in, int in_len)
+{
+	int i, sum = 0;
+
+	/* All input must be numbers */
+	for (i = 0; i < in_len; i++) {
+		if (!isdigit(in[i]))
+			return -EINVAL;
+	}
+
+	/* Double every second digit and add it to sum */
+	for (i = in_len - 1; i >= 0; i -= 2) {
+		int dbl = (in[i] - '0') * 2;
+		if (dbl > 9)
+			dbl -= 9;
+		sum += dbl;
+	}
+
+	/* Add other digits to sum */
+	for (i = in_len - 2; i >= 0; i -= 2)
+		sum += in[i] - '0';
+
+	/* Final checksum */
+	return (sum * 9) % 10 + '0';
+}
+
 /*! @} */
diff --git a/tests/gsm23003/gsm23003_test.c b/tests/gsm23003/gsm23003_test.c
index 79965cf..eac5a11 100644
--- a/tests/gsm23003/gsm23003_test.c
+++ b/tests/gsm23003/gsm23003_test.c
@@ -118,6 +118,47 @@
 	return pass;
 }
 
+static struct {
+	bool with_15th_digit;
+	const char *imei;
+	bool expect_ok;
+} test_imeis[] = {
+	/* without 15th digit */
+	{false, "12345678901234", true},
+	{false, "1234567890123", false},
+	{false, "123456789012345", false},
+
+	/* with 15th digit: valid */
+	{true, "357613004448485", true},
+	{true, "357805023984447", true},
+	{true, "352936001349777", true},
+	{true, "357663017768551", true},
+
+	/* with 15th digit: invalid */
+	{true, "357613004448480", false},
+	{true, "357613004448405", false},
+	{true, "357613004448085", false},
+
+	{ NULL, false, false },
+};
+
+bool test_valid_imei()
+{
+	int i;
+	bool pass = true;
+	bool ok = true;
+	printf("----- %s\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(test_imeis); i++) {
+		ok = osmo_imei_str_valid(test_imeis[i].imei, test_imeis[i].with_15th_digit);
+		pass = pass && (ok == test_imeis[i].expect_ok);
+		printf("%2d: expect=%s result=%s imei='%s' with_15th_digit=%s\n",
+		       i, BOOL_STR(test_imeis[i].expect_ok), BOOL_STR(ok),
+		       test_imeis[i].imei, test_imeis[i].with_15th_digit ? "true" : "false");
+	}
+	return pass;
+}
+
 struct test_mnc_from_str_result {
 	int rc;
 	uint16_t mnc;
@@ -248,6 +289,7 @@
 
 	pass = pass && test_valid_imsi();
 	pass = pass && test_valid_msisdn();
+	pass = pass && test_valid_imei();
 	pass = pass && test_mnc_from_str();
 	pass = pass && test_gummei_name();
 	pass = pass && test_domain_gen();
diff --git a/tests/gsm23003/gsm23003_test.ok b/tests/gsm23003/gsm23003_test.ok
index c64f515..2f7c37f 100644
--- a/tests/gsm23003/gsm23003_test.ok
+++ b/tests/gsm23003/gsm23003_test.ok
@@ -42,6 +42,18 @@
 17: expect=false result=false msisdn='123456	123456'
 18: expect=false result=false msisdn='123456
123456'
 19: expect=false result=false msisdn='(null)'
+----- test_valid_imei
+ 0: expect=true result=true imei='12345678901234' with_15th_digit=false
+ 1: expect=false result=false imei='1234567890123' with_15th_digit=false
+ 2: expect=false result=false imei='123456789012345' with_15th_digit=false
+ 3: expect=true result=true imei='357613004448485' with_15th_digit=true
+ 4: expect=true result=true imei='357805023984447' with_15th_digit=true
+ 5: expect=true result=true imei='352936001349777' with_15th_digit=true
+ 6: expect=true result=true imei='357663017768551' with_15th_digit=true
+ 7: expect=false result=false imei='357613004448480' with_15th_digit=true
+ 8: expect=false result=false imei='357613004448405' with_15th_digit=true
+ 9: expect=false result=false imei='357613004448085' with_15th_digit=true
+10: expect=false result=false imei='(null)' with_15th_digit=false
 ----- test_mnc_from_str
  0: "0" rc=0 mnc=0 mnc_3_digits=0 pass
  1: "00" rc=0 mnc=0 mnc_3_digits=0 pass

-- 
To view, visit https://gerrit.osmocom.org/12524
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: Id2d2a3a93b033bafc74c62e15297034bf4aafe61
Gerrit-Change-Number: 12524
Gerrit-PatchSet: 5
Gerrit-Owner: osmith <osmith at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>
Gerrit-Reviewer: osmith <osmith at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190114/4c30b39e/attachment.htm>


More information about the gerrit-log mailing list