Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: IMEI/IMEISV validation and test cases #30

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions nasConvert/MobileIdentity5GS.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math/bits"
"strconv"
"strings"
"unicode"

"github.com/free5gc/nas/logger"
"github.com/free5gc/nas/nasMessage"
Expand Down Expand Up @@ -282,5 +283,52 @@ func PeiToStringWithError(buf []byte) (string, error) {
digitStr = digitStr[:len(digitStr)-1] // remove the last digit
}

if prefix == "imei-" {
// Validate IMEI before returning
if len(digitStr) != 15 {
return "", fmt.Errorf("invalid IMEI length: expected 15 digits, got %d", len(digitStr))
}
valid, err := validateIMEI(digitStr)
if err != nil {
return "", fmt.Errorf("IMEI validation error: %w", err)
}
if !valid {
return "", fmt.Errorf("invalid IMEI checksum")
}
} else {
if len(digitStr) != 16 {
return "", fmt.Errorf("invalid IMEISV length: expected 16 digits, got %d", len(digitStr))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not validate IMEISV here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMEISV contains the first 14 digits of IMEI (TAC+SNR) and 2 digits of Software Version Number (SVN).

There is no Checksum or algorithm applied to IMEISV, so I think he only checks the length of the digits for now.

TS23.003

image

}

return prefix + digitStr, nil
}

func validateIMEI(imei string) (bool, error) {
// Remove any non-digit characters
cleanIMEI := strings.ReplaceAll(imei, "-", "")
cleanIMEI = strings.ReplaceAll(cleanIMEI, " ", "")

// Check if all characters are digits
for _, char := range cleanIMEI {
if !unicode.IsDigit(char) {
return false, fmt.Errorf("IMEI contains non-digit character: %c", char)
}
}

// Luhn algorithm validation
sum := 0
for i := len(cleanIMEI) - 1; i >= 0; i-- {
digit := int(cleanIMEI[i] - '0')

if (len(cleanIMEI)-i)%2 == 0 {
digit *= 2
if digit > 9 {
digit = digit/10 + digit%10
}
}
sum += digit
}

return sum%10 == 0, nil
}
47 changes: 30 additions & 17 deletions nasConvert/MobileIdentity5GS_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,40 +311,53 @@ func TestPeiToStringWithError(t *testing.T) {
wantErr bool
}{
{
name: "PEI-IMEI-even",
name: "Complete-Valid-IMEI",
args: args{
buf: []byte{0x3, 0xf1},
// Example encoding for a valid 15-digit IMEI
buf: []byte{
0x4b, 0x09, 0x51, 0x24, 0x30, 0x32, 0x57, 0x81,
},
},
want: "imei-01",
want: "imei-490154203237518",
wantErr: false,
},
{
name: "PEI-IMEISV-odd",
name: "Complete-Ivalid-IMEI",
args: args{
buf: []byte{0xd, 0x21},
// Not valid 15-digit IMEI: CD(Check Digit) not valid
buf: []byte{
0x4b, 0x09, 0x51, 0x24, 0x30, 0x32, 0x57, 0x82,
},
},
want: "imeisv-012",
wantErr: false,
},
{
name: "PEI-nil",
wantErr: true,
},
{
name: "PEI-IMEI-len1",
name: "Complete-Valid-IMEISV",
args: args{
buf: []byte{0xb},
buf: []byte{
0x90, 0x87, 0x65, 0x43, 0x21, 0x01, 0x23, 0x45, 0x60,
},
},
want: "imei-0",
want: "imeisv-9785634121032540",
wantErr: false,
},
{
name: "PEI-IMEI-len0",
name: "IMEI-TooLong",
args: args{
buf: []byte{0x3},
buf: []byte{
0x4b, 0x09, 0x51, 0x24, 0x30, 0x32, 0x57, 0x81, 0x20,
},
},
want: "imei-",
wantErr: false,
wantErr: true,
},
{
name: "IMEI-TooShort",
args: args{
buf: []byte{
0x4b, 0x09, 0x51, 0x24, 0x30, 0x32,
},
},
wantErr: true,
},
}
for _, tt := range tests {
Expand Down
Loading