From 894be2d9da60a8e0f7ffc0224e3f294ce49b70be Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Fri, 11 Jan 2019 13:13:37 +0100 Subject: 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 --- src/utils.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/utils.c') diff --git a/src/utils.c b/src/utils.c index 35d70ace..d1da4fa8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -765,4 +765,35 @@ const char *osmo_str_toupper(const char *src) 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'; +} + /*! @} */ -- cgit v1.2.3