Skip to content

Commit 5e1479c

Browse files
Roy-HuRoy-Huroy19991013
authored
Prevent Invalid Curve Attack on 5G SUCI Feature (#20)
* Prevent Invalid Curve Attack on 5G SUCI Feature * add test case of detecting invalid cure attack * fix comment * change test case err type --------- Co-authored-by: Roy-Hu <[email protected]> Co-authored-by: roy19991013 <[email protected]>
1 parent a63c83d commit 5e1479c

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

pkg/suci/suci.go

+18
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,20 @@ func profileA(input, supiType, privateKey string) (string, error) {
218218
return calcSchemeResult(decryptPlainText, supiType), nil
219219
}
220220

221+
func checkOnCurve(curve elliptic.Curve, x, y *big.Int) error {
222+
// (0, 0) is the point at infinity by convention. It's ok to operate on it,
223+
// although IsOnCurve is documented to return false for it. See Issue 37294.
224+
if x.Sign() == 0 && y.Sign() == 0 {
225+
return nil
226+
}
227+
228+
if !curve.IsOnCurve(x, y) {
229+
return fmt.Errorf("crypto/elliptic: attempted operation on invalid point")
230+
}
231+
232+
return nil
233+
}
234+
221235
func profileB(input, supiType, privateKey string) (string, error) {
222236
logger.SuciLog.Infoln("SuciToSupi Profile B")
223237
s, hexDecodeErr := hex.DecodeString(input)
@@ -271,6 +285,10 @@ func profileB(input, supiType, privateKey string) (string, error) {
271285
}
272286
// fmt.Printf("xUncom: %x\nyUncom: %x\n", xUncompressed, yUncompressed)
273287

288+
if err := checkOnCurve(elliptic.P256(), xUncompressed, yUncompressed); err != nil {
289+
return "", err
290+
}
291+
274292
// x-coordinate is the shared key
275293
decryptSharedKey, _ := elliptic.P256().ScalarMult(xUncompressed, yUncompressed, bHNPriv)
276294
// fmt.Printf("deShared: %x\n", decryptSharedKey.Bytes())

pkg/suci/suci_test.go

+25-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package suci
22

3-
import "testing"
3+
import (
4+
"fmt"
5+
"testing"
6+
)
47

58
func TestToSupi(t *testing.T) {
69
suciProfiles := []SuciProfile{
@@ -17,30 +20,42 @@ func TestToSupi(t *testing.T) {
1720
},
1821
}
1922
testCases := []struct {
20-
suci string
21-
expected string
23+
suci string
24+
expectedSupi string
25+
expectedErr error
2226
}{
2327
{
24-
suci: "suci-0-208-93-0-0-0-00007487",
25-
expected: "imsi-2089300007487",
28+
suci: "suci-0-208-93-0-0-0-00007487",
29+
expectedSupi: "imsi-2089300007487",
30+
expectedErr: nil,
2631
},
2732
{
2833
suci: "suci-0-208-93-0-1-1-b2e92f836055a255837debf850b528997ce0201cb82a" +
2934
"dfe4be1f587d07d8457dcb02352410cddd9e730ef3fa87",
30-
expected: "imsi-20893001002086",
35+
expectedSupi: "imsi-20893001002086",
36+
expectedErr: nil,
3137
},
3238
{
3339
suci: "suci-0-208-93-0-2-2-039aab8376597021e855679a9778ea0b67396e68c66d" +
3440
"f32c0f41e9acca2da9b9d146a33fc2716ac7dae96aa30a4d",
35-
expected: "imsi-20893001002086",
41+
expectedSupi: "imsi-20893001002086",
42+
expectedErr: nil,
43+
},
44+
{
45+
suci: "suci-0-208-93-0-2-2-0434a66778799d52fedd9326db4b690d092e05c9ba0ace5b413da" +
46+
"fc0a40aa28ee00a79f790fa4da6a2ece892423adb130dc1b30e270b7d0088bdd716b93894891d5221a74c810d6b9350cc067c76",
47+
expectedSupi: "",
48+
expectedErr: fmt.Errorf("crypto/elliptic: attempted operation on invalid point"),
3649
},
3750
}
3851
for i, tc := range testCases {
3952
supi, err := ToSupi(tc.suci, suciProfiles)
4053
if err != nil {
41-
t.Errorf("TC%d err: %+v\n", i, err)
42-
} else if supi != tc.expected {
43-
t.Errorf("TC%d fail: supi[%s], expected[%s]\n", i, supi, tc.expected)
54+
if err.Error() != tc.expectedErr.Error() {
55+
t.Errorf("TC%d fail: err[%s], expected[%s]\n", i, err, tc.expectedErr)
56+
}
57+
} else if supi != tc.expectedSupi {
58+
t.Errorf("TC%d fail: supi[%s], expected[%s]\n", i, supi, tc.expectedSupi)
4459
}
4560
}
4661
}

0 commit comments

Comments
 (0)