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.orgosmith 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>