Skip to content

Commit

Permalink
Merge pull request #87 from Jigsaw-Code/bemasc-unpack
Browse files Browse the repository at this point in the history
Use our own implementation of Pack for UDP
  • Loading branch information
Benjamin M. Schwartz authored Oct 5, 2020
2 parents f625a9f + 2b2558d commit f57f555
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
2 changes: 1 addition & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (c *packetConn) WriteTo(b []byte, addr net.Addr) (int, error) {
// partially overlapping the plaintext and cipher slices since `Pack` skips the salt when calling
// `AEAD.Seal` (see https://golang.org/pkg/crypto/cipher/#AEAD).
plaintextBuf := append(append(cipherBuf[saltSize:saltSize], socksTargetAddr...), b...)
buf, err := shadowaead.Pack(cipherBuf, plaintextBuf, c.cipher)
buf, err := ss.Pack(cipherBuf, plaintextBuf, c.cipher)
if err != nil {
return 0, err
}
Expand Down
2 changes: 1 addition & 1 deletion service/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ func timedCopy(clientAddr net.Addr, clientConn net.PacketConn, targetConn *natco
// [ packBuf ]
// [ buf ]
packBuf := pkt[saltStart:]
buf, err := shadowaead.Pack(packBuf, plaintextBuf, targetConn.cipher) // Encrypt in-place
buf, err := ss.Pack(packBuf, plaintextBuf, targetConn.cipher) // Encrypt in-place
if err != nil {
return onet.NewConnectionError("ERR_PACK", "Failed to pack data to client", err)
}
Expand Down
25 changes: 25 additions & 0 deletions shadowsocks/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,31 @@ var ErrShortPacket = errors.New("short packet")
// This array must be at least service.maxNonceSize bytes.
var zeroNonce [12]byte

// Pack encrypts a Shadowsocks-UDP packet and returns a slice containing the encrypted packet.
// dst must be big enough to hold the encrypted packet.
// If plaintext and dst overlap but are not aligned for in-place encryption, this
// function will panic.
func Pack(dst, plaintext []byte, cipher shadowaead.Cipher) ([]byte, error) {
saltSize := cipher.SaltSize()
if len(dst) < saltSize {
return nil, io.ErrShortBuffer
}
salt := dst[:saltSize]
if err := RandomSaltGenerator.GetSalt(salt); err != nil {
return nil, err
}

aead, err := cipher.Encrypter(salt)
if err != nil {
return nil, err
}

if len(dst) < saltSize+len(plaintext)+aead.Overhead() {
return nil, io.ErrShortBuffer
}
return aead.Seal(salt, zeroNonce[:aead.NonceSize()], plaintext, nil), nil
}

// Unpack decrypts a Shadowsocks-UDP packet and returns a slice containing the decrypted payload or an error.
// If dst is present, it is used to store the plaintext, and must have enough capacity.
// If dst is nil, decryption proceeds in-place.
Expand Down

0 comments on commit f57f555

Please sign in to comment.