Skip to content
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,5 @@ tags

# local buildkite run
/artifacts.out

.idea/*
5 changes: 4 additions & 1 deletion env/debian/pkgs.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

bridge-utils
capnproto
cgroup-bin
Expand All @@ -12,10 +13,12 @@ jq
libcapnp-dev
make
moreutils
net-tools
netcat-openbsd
net-tools
ntp
patch
python
python3
python3-dev
python3-flake8
python3-nose
Expand Down
1 change: 1 addition & 0 deletions go/lib/layers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ go_library(
deps = [
"//go/lib/common:go_default_library",
"//go/lib/serrors:go_default_library",
"//go/lib/spse:go_default_library",
"//go/lib/util:go_default_library",
"@com_github_google_gopacket//:go_default_library",
"@com_github_google_gopacket//layers:go_default_library",
Expand Down
15 changes: 15 additions & 0 deletions go/lib/layers/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package layers

import (
"fmt"
"github.com/scionproto/scion/go/lib/spse"

"github.com/scionproto/scion/go/lib/common"
)
Expand Down Expand Up @@ -283,6 +284,20 @@ func ExtensionDataToExtensionLayer(nextHdr common.L4ProtocolType,
return &Extension{
NextHeader: nextHdr,
Type: data.Type().Type,
Class: data.Type().Class,
Data: bytes,
}, nil
}

func ExtensionDataToSPSELayer(nextHdr common.L4ProtocolType,
extn spse.Extn) (*SPSE, error) {
extnLayer, err := ExtensionDataToExtensionLayer(nextHdr, &extn)
if err != nil {
return nil, err
}
return &SPSE{
Comment thread
radwasherif marked this conversation as resolved.
Extension: *extnLayer,
AuthStartOffset: spse.SecModeLength + len(extn.Metadata),
AuthEndOffset: spse.SecModeLength + len(extn.Metadata) + len(extn.Authenticator),
}, nil
}
72 changes: 63 additions & 9 deletions go/lib/layers/extensions_layer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package layers
import (
"github.com/google/gopacket"
"github.com/google/gopacket/layers"

"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/serrors"
"github.com/scionproto/scion/go/lib/util"
Expand Down Expand Up @@ -49,10 +48,12 @@ var (

type Extension struct {
layers.BaseLayer
NextHeader common.L4ProtocolType
NumLines uint8
Type uint8
Data []byte
NextHeader common.L4ProtocolType
NumLines uint8
Type uint8
Class common.L4ProtocolType
Comment thread
radwasherif marked this conversation as resolved.
Data []byte
AuthenticatedBytes []byte
}

func (e *Extension) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
Expand Down Expand Up @@ -84,6 +85,22 @@ func (e *Extension) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) err
}

func (e *Extension) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
bytes, err := e.serialize(b, opts)
if err != nil {
return err
}

//The bytes that need to be authenticated
switch e.Class {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why don't we have different behaviors for these? Interface Extension implemented by a base class and e2e and hbh.
Or, since the caller will know if they are e2e or hbh, let them pass that information along.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

This is a bit complicated because we convert common.Extension (an interface) to layers.Extension using the function layers.ExtensionDataToExtensionLayer. The packet stores []common.Extension and what enables us to distinguish types is with the Class() function, or explicit type checks. So effectively we would just be moving that check somewhere else.

case common.HopByHopClass:
e.AuthenticatedBytes = []byte{bytes[0], bytes[2]} //HBH: only next header and type
case common.End2EndClass: //E2E: entire extension
e.AuthenticatedBytes = bytes
}

return nil
}
func (e *Extension) serialize(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) ([]byte, error) {
totalLength := common.ExtnSubHdrLen + len(e.Data)
paddingSize := 0
if opts.FixLengths {
Expand All @@ -93,12 +110,49 @@ func (e *Extension) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serial
}
bytes, err := b.PrependBytes(totalLength)
if err != nil {
return err
return nil, err
}
bytes[0] = uint8(e.NextHeader)
bytes[1] = e.NumLines
bytes[2] = e.Type
copy(bytes[3:], e.Data)
copy(bytes[3+len(e.Data):], zeroes[:paddingSize])
return nil
copy(bytes[common.ExtnSubHdrLen:], e.Data)
copy(bytes[common.ExtnSubHdrLen+len(e.Data):], zeroes[:paddingSize])

return bytes, nil
}

type SPSE struct {
Extension
//AuthenticatorBuffer is a pointer to the serialization buffer where the MAC is written
AuthenticatorBuffer []byte
//AuthStartOffset the start offset of the authenticator relative to the Data field
AuthStartOffset int
//AuthEndOffset the end offset of the authenticator relative to the Data field
AuthEndOffset int
}

func (e *SPSE) SetAuthenticator(b []byte) {
copy(e.AuthenticatorBuffer, b)
}

func (e *SPSE) Serialize() []byte {
totalLength := common.ExtnSubHdrLen + len(e.Data)
paddingSize := util.CalcPadding(totalLength, common.LineLen)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

in Extension.serialize the padding is zero unless opts.FixLengths is set. Do we need that here?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

I honestly don't understand why we need this opts.FixLengths anyways, since our spec says we should always pad to an 8-byte boundary AFAIK. I think it's just there to match the function signature of SerializeTo. In hpkt.WriteScnPkt its set to true always.

totalLength += paddingSize
e.NumLines = uint8(totalLength / common.LineLen)
bytes := make([]byte, totalLength)
bytes[0] = uint8(e.NextHeader)
bytes[1] = e.NumLines
bytes[2] = e.Type
copy(bytes[common.ExtnSubHdrLen:], e.Data)
copy(bytes[common.ExtnSubHdrLen+len(e.Data):], zeroes[:paddingSize])
//The bytes that need to be authenticated
e.AuthenticatedBytes = bytes

//Keep pointer to the buffer containing authenticator
//Initialized to zero, set later by call to SetAuthenticator after MAC computation
e.AuthenticatorBuffer = bytes[common.ExtnSubHdrLen+e.AuthStartOffset : common.ExtnSubHdrLen+e.AuthEndOffset]

return bytes

}
11 changes: 11 additions & 0 deletions go/lib/snet/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ go_library(
"path.go",
"reader.go",
"router.go",
"scion_layer.go",
"scion_layer_parser.go",
"snet.go",
"svcaddr.go",
"udpaddr.go",
Expand All @@ -24,14 +26,18 @@ go_library(
"//go/lib/ctrl/path_mgmt:go_default_library",
"//go/lib/hpkt:go_default_library",
"//go/lib/l4:go_default_library",
"//go/lib/layers:go_default_library",
"//go/lib/log:go_default_library",
"//go/lib/scmp:go_default_library",
"//go/lib/serrors:go_default_library",
"//go/lib/snet/internal/metrics:go_default_library",
"//go/lib/sock/reliable:go_default_library",
"//go/lib/spath:go_default_library",
"//go/lib/spkt:go_default_library",
"//go/lib/spse:go_default_library",
"//go/lib/topology/overlay:go_default_library",
"//go/lib/util:go_default_library",
"@com_github_google_gopacket//:go_default_library",
],
)

Expand All @@ -40,6 +46,7 @@ go_test(
srcs = [
"export_test.go",
"raw_test.go",
"scion_layer_test.go",
"svcaddr_test.go",
"udpaddr_test.go",
"writer_test.go",
Expand All @@ -48,8 +55,12 @@ go_test(
deps = [
"//go/lib/addr:go_default_library",
"//go/lib/common:go_default_library",
"//go/lib/l4:go_default_library",
"//go/lib/layers:go_default_library",
"//go/lib/spath:go_default_library",
"//go/lib/spse:go_default_library",
"//go/lib/xtest:go_default_library",
"@com_github_google_gopacket//:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
],
)
60 changes: 37 additions & 23 deletions go/lib/snet/packet_conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package snet

import (
"github.com/scionproto/scion/go/lib/spse"
"net"
"sort"
"time"
Expand Down Expand Up @@ -104,11 +105,27 @@ type SCIONPacketInfo struct {
// even when the L4Header and Payload demand one (as is the case, for
// example, for a SCMP::General::RecordPathRequest packet).
Extensions []common.Extension

//Security extensions, for now only one per packet
AuthExt *spse.Extn

// L4Header contains L4 header information.
L4Header l4.L4Header
Payload common.Payload
}

func (pkt *SCIONPacket) Serialize() error {
pkt.Prepare()
scionLayer := scionLayer{SCIONPacket:*pkt}
n, err := scionLayer.serialize()
if err != nil {
return common.NewBasicError("Unable to serialize SCION packet", err)
}
pkt.Bytes = pkt.Bytes[:n]

return nil
}

// SCIONAddress is the fully-specified address of a host.
type SCIONAddress struct {
IA addr.IA
Expand Down Expand Up @@ -145,32 +162,29 @@ func (c *SCIONPacketConn) Close() error {
}

func (c *SCIONPacketConn) WriteTo(pkt *SCIONPacket, ov *net.UDPAddr) error {
StableSortExtensions(pkt.Extensions)
hbh, e2e, err := hpkt.ValidateExtensions(pkt.Extensions)
if err != nil {
return common.NewBasicError("Bad extension list", err)
}
// TODO(scrye): scnPkt is a temporary solution. Its functionality will be
// absorbed by the easier to use SCIONPacket structure in this package.
scnPkt := &spkt.ScnPkt{
DstIA: pkt.Destination.IA,
SrcIA: pkt.Source.IA,
DstHost: pkt.Destination.Host,
SrcHost: pkt.Source.Host,
E2EExt: e2e,
HBHExt: hbh,
Path: pkt.Path,
L4: pkt.L4Header,
Pld: pkt.Payload,
}
pkt.Prepare()
n, err := hpkt.WriteScnPkt(scnPkt, common.RawBytes(pkt.Bytes))
//hbh, e2e, err := hpkt.ValidateExtensions(pkt.Extensions)
//if err != nil {
// return common.NewBasicError("Bad extension list", err)
//}
//// TODO(scrye): scnPkt is a temporary solution. Its functionality will be
//// absorbed by the easier to use SCIONPacket structure in this package.
//scnPkt := &spkt.ScnPkt{
// DstIA: pkt.Destination.IA,
// SrcIA: pkt.Source.IA,
// DstHost: pkt.Destination.Host,
// SrcHost: pkt.Source.Host,
// E2EExt: e2e,
// HBHExt: hbh,
// Path: pkt.Path,
// L4: pkt.L4Header,
// Pld: pkt.Payload,
//}
err := pkt.Serialize()
if err != nil {
return common.NewBasicError("Unable to serialize SCION packet", err)
return common.NewBasicError("Error serializing SCIONPacket", err)
}
pkt.Bytes = pkt.Bytes[:n]
// Send message
n, err = c.conn.WriteTo(pkt.Bytes, ov)
n, err := c.conn.WriteTo(pkt.Bytes, ov)
if err != nil {
return common.NewBasicError("Reliable socket write error", err)
}
Expand Down
Loading