Skip to content

Commit

Permalink
Add sha256 integrity algo
Browse files Browse the repository at this point in the history
  • Loading branch information
Allen00991 authored and tim-ywliu committed Aug 24, 2024
1 parent 01c10b4 commit bf3e299
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 81 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/urfave/cli v1.22.5
github.com/vishvananda/netlink v1.1.0
github.com/wmnsk/go-gtp v0.8.11-0.20240705144331-f53bfdd4233b
Expand All @@ -27,6 +28,7 @@ require (
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/free5gc/openapi v1.0.9-0.20240503143645-eac9f06c2f6b // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
Expand All @@ -43,6 +45,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // indirect
Expand Down
38 changes: 26 additions & 12 deletions pkg/ike/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (s *Server) HandleIKESAINIT(

if len(proposal.EncryptionAlgorithm) > 0 {
for _, transform := range proposal.EncryptionAlgorithm {
if is_supported(ike_message.TypeEncryptionAlgorithm, transform.TransformID,
if isTransformSupported(ike_message.TypeEncryptionAlgorithm, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
encryptionAlgorithmTransform = transform
break
Expand All @@ -117,7 +117,7 @@ func (s *Server) HandleIKESAINIT(
}
if len(proposal.PseudorandomFunction) > 0 {
for _, transform := range proposal.PseudorandomFunction {
if is_supported(ike_message.TypePseudorandomFunction, transform.TransformID,
if isTransformSupported(ike_message.TypePseudorandomFunction, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
pseudorandomFunctionTransform = transform
break
Expand All @@ -131,7 +131,7 @@ func (s *Server) HandleIKESAINIT(
}
if len(proposal.IntegrityAlgorithm) > 0 {
for _, transform := range proposal.IntegrityAlgorithm {
if is_supported(ike_message.TypeIntegrityAlgorithm, transform.TransformID,
if isTransformSupported(ike_message.TypeIntegrityAlgorithm, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
integrityAlgorithmTransform = transform
break
Expand All @@ -145,7 +145,7 @@ func (s *Server) HandleIKESAINIT(
}
if len(proposal.DiffieHellmanGroup) > 0 {
for _, transform := range proposal.DiffieHellmanGroup {
if is_supported(ike_message.TypeDiffieHellmanGroup, transform.TransformID,
if isTransformSupported(ike_message.TypeDiffieHellmanGroup, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
diffieHellmanGroupTransform = transform
break
Expand Down Expand Up @@ -572,7 +572,7 @@ func (s *Server) HandleIKEAUTH(

if len(proposal.EncryptionAlgorithm) > 0 {
for _, transform := range proposal.EncryptionAlgorithm {
if is_Kernel_Supported(ike_message.TypeEncryptionAlgorithm, transform.TransformID,
if isTransformKernelSupported(ike_message.TypeEncryptionAlgorithm, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
encryptionAlgorithmTransform = transform
break
Expand All @@ -589,7 +589,7 @@ func (s *Server) HandleIKEAUTH(
}
if len(proposal.IntegrityAlgorithm) > 0 {
for _, transform := range proposal.IntegrityAlgorithm {
if is_Kernel_Supported(ike_message.TypeIntegrityAlgorithm, transform.TransformID,
if isTransformKernelSupported(ike_message.TypeIntegrityAlgorithm, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
integrityAlgorithmTransform = transform
break
Expand All @@ -601,7 +601,7 @@ func (s *Server) HandleIKEAUTH(
} // Optional
if len(proposal.DiffieHellmanGroup) > 0 {
for _, transform := range proposal.DiffieHellmanGroup {
if is_Kernel_Supported(ike_message.TypeDiffieHellmanGroup, transform.TransformID,
if isTransformKernelSupported(ike_message.TypeDiffieHellmanGroup, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
diffieHellmanGroupTransform = transform
break
Expand All @@ -613,7 +613,7 @@ func (s *Server) HandleIKEAUTH(
} // Optional
if len(proposal.ExtendedSequenceNumbers) > 0 {
for _, transform := range proposal.ExtendedSequenceNumbers {
if is_Kernel_Supported(ike_message.TypeExtendedSequenceNumbers, transform.TransformID,
if isTransformKernelSupported(ike_message.TypeExtendedSequenceNumbers, transform.TransformID,
transform.AttributePresent, transform.AttributeValue) {
extendedSequenceNumbersTransform = transform
break
Expand Down Expand Up @@ -1835,7 +1835,7 @@ func (s *Server) CreatePDUSessionChildSA(
// Integrity transform
if pduSession.SecurityIntegrity {
proposal.IntegrityAlgorithm.BuildTransform(ike_message.TypeIntegrityAlgorithm,
ike_message.AUTH_HMAC_SHA1_96, nil, nil, nil)
ikeUe.N3IWFIKESecurityAssociation.IntegrityAlgorithm.TransformID, nil, nil, nil)
}

// RFC 7296
Expand Down Expand Up @@ -1952,7 +1952,12 @@ func (s *Server) StartDPD(ikeUe *n3iwf_context.N3IWFIkeUe) {
}
}

func is_supported(transformType uint8, transformID uint16, attributePresent bool, attributeValue uint16) bool {
func isTransformSupported(
transformType uint8,
transformID uint16,
attributePresent bool,
attributeValue uint16,
) bool {
switch transformType {
case ike_message.TypeEncryptionAlgorithm:
switch transformID {
Expand Down Expand Up @@ -2004,6 +2009,8 @@ func is_supported(transformType uint8, transformID uint16, attributePresent bool
return true
case ike_message.PRF_HMAC_TIGER:
return false
case ike_message.PRF_HMAC_SHA2_256:
return true
default:
return false
}
Expand All @@ -2021,6 +2028,8 @@ func is_supported(transformType uint8, transformID uint16, attributePresent bool
return false
case ike_message.AUTH_AES_XCBC_96:
return false
case ike_message.AUTH_HMAC_SHA2_256_128:
return true
default:
return false
}
Expand Down Expand Up @@ -2052,8 +2061,11 @@ func is_supported(transformType uint8, transformID uint16, attributePresent bool
}
}

func is_Kernel_Supported(
transformType uint8, transformID uint16, attributePresent bool, attributeValue uint16,
func isTransformKernelSupported(
transformType uint8,
transformID uint16,
attributePresent bool,
attributeValue uint16,
) bool {
switch transformType {
case ike_message.TypeEncryptionAlgorithm:
Expand Down Expand Up @@ -2136,6 +2148,8 @@ func is_Kernel_Supported(
return false
case ike_message.AUTH_AES_XCBC_96:
return true
case ike_message.AUTH_HMAC_SHA2_256_128:
return true
default:
return false
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/ike/message/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const (
PRF_HMAC_MD5 = iota + 1
PRF_HMAC_SHA1
PRF_HMAC_TIGER
PRF_HMAC_SHA2_256 = 5
)

const (
Expand All @@ -89,6 +90,7 @@ const (
AUTH_DES_MAC
AUTH_KPDK_MD5
AUTH_AES_XCBC_96
AUTH_HMAC_SHA2_256_128 = 12
)

const (
Expand Down
123 changes: 58 additions & 65 deletions pkg/ike/security/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ import (
"crypto/hmac"
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"crypto/sha1" // #nosec G505
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"errors"
"hash"
"io"
"math/big"
"strings"

"github.com/pkg/errors"

"github.com/free5gc/n3iwf/internal/logger"
n3iwf_context "github.com/free5gc/n3iwf/pkg/context"
"github.com/free5gc/n3iwf/pkg/ike/message"
Expand Down Expand Up @@ -141,80 +143,63 @@ func NewPseudorandomFunction(key []byte, algorithmType uint16) (hash.Hash, bool)
case message.PRF_HMAC_MD5:
return hmac.New(md5.New, key), true
case message.PRF_HMAC_SHA1:
return hmac.New(sha1.New, key), true
return hmac.New(sha1.New, key), true // #nosec G401
case message.PRF_HMAC_SHA2_256:
return hmac.New(sha256.New, key), true
default:
ikeLog.Errorf("Unsupported pseudo random function: %d", algorithmType)
return nil, false
}
}

// Integrity Algorithm
func CalculateChecksum(key []byte, originData []byte, algorithmType uint16) ([]byte, error) {
ikeLog := logger.IKELog
switch algorithmType {
func calculateIntegrity(key []byte, originData []byte, transform *message.Transform) ([]byte, error) {
expectKeyLen, ok := getKeyLength(
transform.TransformType, transform.TransformID,
transform.AttributePresent, transform.AttributeValue)
if !ok {
return nil, errors.Errorf("calculateIntegrity[%d]: unsupported algo", transform.TransformID)
}
keyLen := len(key)
if keyLen != expectKeyLen {
return nil, errors.Errorf("calculateIntegrity[%d]: Unmatched input key length[%d:%d]",
transform.TransformID, keyLen, expectKeyLen)
}
outputLen, ok := getOutputLength(
transform.TransformType, transform.TransformID,
transform.AttributePresent, transform.AttributeValue)
if !ok {
return nil, errors.Errorf("calculateIntegrity[%d]: unsupported algo", transform.TransformID)
}

var integrityFunction hash.Hash
switch transform.TransformID {
case message.AUTH_HMAC_MD5_96:
if len(key) != 16 {
return nil, errors.New("Unmatched input key length")
}
integrityFunction := hmac.New(md5.New, key)
if _, err := integrityFunction.Write(originData); err != nil {
ikeLog.Errorf("Hash function write error when calculating checksum: %+v", err)
return nil, errors.New("Hash function write error")
}
return integrityFunction.Sum(nil), nil
integrityFunction = hmac.New(md5.New, key)
case message.AUTH_HMAC_SHA1_96:
if len(key) != 20 {
return nil, errors.New("Unmatched input key length")
}
integrityFunction := hmac.New(sha1.New, key)
if _, err := integrityFunction.Write(originData); err != nil {
ikeLog.Errorf("Hash function write error when calculating checksum: %+v", err)
return nil, errors.New("Hash function write error")
}
return integrityFunction.Sum(nil)[:12], nil
integrityFunction = hmac.New(sha1.New, key) // #nosec G401
case message.AUTH_HMAC_SHA2_256_128:
integrityFunction = hmac.New(sha256.New, key)
default:
ikeLog.Errorf("Unsupported integrity function: %d", algorithmType)
return nil, errors.New("Unsupported algorithm")
return nil, errors.Errorf("calculateIntegrity[%d]: unsupported algo", transform.TransformID)
}

if _, err := integrityFunction.Write(originData); err != nil {
return nil, errors.Wrapf(err, "calculateIntegrity[%d]", transform.TransformID)
}
return integrityFunction.Sum(nil)[:outputLen], nil
}

func VerifyIKEChecksum(key []byte, originData []byte, checksum []byte, algorithmType uint16) (bool, error) {
func verifyIntegrity(key []byte, originData []byte, checksum []byte, transform *message.Transform) (bool, error) {
ikeLog := logger.IKELog
switch algorithmType {
case message.AUTH_HMAC_MD5_96:
if len(key) != 16 {
return false, errors.New("Unmatched input key length")
}
integrityFunction := hmac.New(md5.New, key)
if _, err := integrityFunction.Write(originData); err != nil {
ikeLog.Errorf("Hash function write error when verifying IKE checksum: %+v", err)
return false, errors.New("Hash function write error")
}
checksumOfMessage := integrityFunction.Sum(nil)

ikeLog.Tracef("Calculated checksum:\n%s\nReceived checksum:\n%s",
hex.Dump(checksumOfMessage), hex.Dump(checksum))

return hmac.Equal(checksumOfMessage, checksum), nil
case message.AUTH_HMAC_SHA1_96:
if len(key) != 20 {
return false, errors.New("Unmatched input key length")
}
integrityFunction := hmac.New(sha1.New, key)
if _, err := integrityFunction.Write(originData); err != nil {
ikeLog.Errorf("Hash function write error when verifying IKE checksum: %+v", err)
return false, errors.New("Hash function write error")
}
checksumOfMessage := integrityFunction.Sum(nil)[:12]

ikeLog.Tracef("Calculated checksum:\n%s\nReceived checksum:\n%s",
hex.Dump(checksumOfMessage), hex.Dump(checksum))

return hmac.Equal(checksumOfMessage, checksum), nil
default:
ikeLog.Errorf("Unsupported integrity function: %d", algorithmType)
return false, errors.New("Unsupported algorithm")
expectChecksum, err := calculateIntegrity(key, originData, transform)
if err != nil {
return false, errors.Wrapf(err, "verifyIntegrity")
}

ikeLog.Tracef("Calculated checksum:\n%s\nReceived checksum:\n%s",
hex.Dump(expectChecksum), hex.Dump(checksum))
return hmac.Equal(expectChecksum, checksum), nil
}

// Encryption Algorithm
Expand Down Expand Up @@ -605,9 +590,9 @@ func DecryptProcedure(ikeSecurityAssociation *n3iwf_context.IKESecurityAssociati
return nil, errors.New("Encoding IKE message failed")
}

ok, err = VerifyIKEChecksum(ikeSecurityAssociation.SK_ai,
ok, err = verifyIntegrity(ikeSecurityAssociation.SK_ai,
ikeMessageData[:len(ikeMessageData)-checksumLength], checksum,
transformIntegrityAlgorithm.TransformID)
transformIntegrityAlgorithm)
if err != nil {
ikeLog.Errorf("Error occur when verifying checksum: %+v", err)
return nil, errors.New("Error verify checksum")
Expand Down Expand Up @@ -701,9 +686,9 @@ func EncryptProcedure(ikeSecurityAssociation *n3iwf_context.IKESecurityAssociati
ikeLog.Error(err)
return errors.New("Encoding IKE message error")
}
checksumOfMessage, err := CalculateChecksum(ikeSecurityAssociation.SK_ar,
checksumOfMessage, err := calculateIntegrity(ikeSecurityAssociation.SK_ar,
responseIKEMessageData[:len(responseIKEMessageData)-checksumLength],
transformIntegrityAlgorithm.TransformID)
transformIntegrityAlgorithm)
if err != nil {
ikeLog.Errorf("Calculating checksum failed: %+v", err)
return errors.New("Error calculating checksum")
Expand Down Expand Up @@ -800,6 +785,8 @@ func getKeyLength(transformType uint8, transformID uint16, attributePresent bool
return 16, true
case message.PRF_HMAC_SHA1:
return 20, true
case message.PRF_HMAC_SHA2_256:
return 32, true
case message.PRF_HMAC_TIGER:
return 0, false
default:
Expand All @@ -819,6 +806,8 @@ func getKeyLength(transformType uint8, transformID uint16, attributePresent bool
return 0, false
case message.AUTH_AES_XCBC_96:
return 0, false
case message.AUTH_HMAC_SHA2_256_128:
return 32, true
default:
return 0, false
}
Expand Down Expand Up @@ -868,6 +857,8 @@ func getOutputLength(
return 20, true
case message.PRF_HMAC_TIGER:
return 0, false
case message.PRF_HMAC_SHA2_256:
return 32, true
default:
return 0, false
}
Expand All @@ -885,6 +876,8 @@ func getOutputLength(
return 0, false
case message.AUTH_AES_XCBC_96:
return 0, false
case message.AUTH_HMAC_SHA2_256_128:
return 16, true
default:
return 0, false
}
Expand Down
Loading

0 comments on commit bf3e299

Please sign in to comment.