]> Cypherpunks.ru repositories - nncp.git/blobdiff - src/pkt.go
Counter increment optimization
[nncp.git] / src / pkt.go
index 2fab844422486793be179dd571ef5f77386a3e1c..2049b6354fb8bf0210eb3e61558afe9a76ee9236 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2021 Sergey Matveev <stargrave@stargrave.org>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ import (
        "errors"
        "io"
 
-       "github.com/davecgh/go-xdr/xdr2"
+       xdr "github.com/davecgh/go-xdr/xdr2"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/chacha20poly1305"
        "golang.org/x/crypto/curve25519"
@@ -40,14 +40,17 @@ const (
        EncBlkSize = 128 * (1 << 10)
        KDFXOFSize = chacha20poly1305.KeySize * 2
 
-       PktTypeFile PktType = iota
-       PktTypeFreq PktType = iota
-       PktTypeExec PktType = iota
-       PktTypeTrns PktType = iota
+       PktTypeFile    PktType = iota
+       PktTypeFreq    PktType = iota
+       PktTypeExec    PktType = iota
+       PktTypeTrns    PktType = iota
+       PktTypeExecFat PktType = iota
 
        MaxPathSize = 1<<8 - 1
 
        NNCPBundlePrefix = "NNCP"
+
+       PktSizeOverhead = 8 + poly1305.TagSize
 )
 
 var (
@@ -56,9 +59,8 @@ var (
        BadMagic     error   = errors.New("Unknown magic number")
        BadPktType   error   = errors.New("Unknown packet type")
 
-       PktOverhead     int64
-       PktEncOverhead  int64
-       PktSizeOverhead int64 = 8 + poly1305.TagSize
+       PktOverhead    int64
+       PktEncOverhead int64
 )
 
 type Pkt struct {
@@ -66,7 +68,7 @@ type Pkt struct {
        Type    PktType
        Nice    uint8
        PathLen uint8
-       Path    *[MaxPathSize]byte
+       Path    [MaxPathSize]byte
 }
 
 type PktTbs struct {
@@ -74,7 +76,7 @@ type PktTbs struct {
        Nice      uint8
        Sender    *NodeId
        Recipient *NodeId
-       ExchPub   *[32]byte
+       ExchPub   [32]byte
 }
 
 type PktEnc struct {
@@ -82,15 +84,12 @@ type PktEnc struct {
        Nice      uint8
        Sender    *NodeId
        Recipient *NodeId
-       ExchPub   *[32]byte
-       Sign      *[ed25519.SignatureSize]byte
+       ExchPub   [32]byte
+       Sign      [ed25519.SignatureSize]byte
 }
 
 func init() {
-       pkt := Pkt{
-               Type: PktTypeFile,
-               Path: new([MaxPathSize]byte),
-       }
+       pkt := Pkt{Type: PktTypeFile}
        var buf bytes.Buffer
        n, err := xdr.Marshal(&buf, pkt)
        if err != nil {
@@ -105,11 +104,8 @@ func init() {
        }
        pktEnc := PktEnc{
                Magic:     MagicNNCPEv4,
-               Nice:      123,
                Sender:    dummyId,
                Recipient: dummyId,
-               ExchPub:   new([32]byte),
-               Sign:      new([ed25519.SignatureSize]byte),
        }
        n, err = xdr.Marshal(&buf, pktEnc)
        if err != nil {
@@ -127,12 +123,21 @@ func NewPkt(typ PktType, nice uint8, path []byte) (*Pkt, error) {
                Type:    typ,
                Nice:    nice,
                PathLen: uint8(len(path)),
-               Path:    new([MaxPathSize]byte),
        }
        copy(pkt.Path[:], path)
        return &pkt, nil
 }
 
+func ctrIncr(b []byte) {
+       for i := len(b) - 1; i >= 0; i-- {
+               b[i]++
+               if b[i] != 0 {
+                       return
+               }
+       }
+       panic("counter overflow")
+}
+
 func aeadProcess(
        aead cipher.AEAD,
        nonce []byte,
@@ -140,7 +145,6 @@ func aeadProcess(
        r io.Reader,
        w io.Writer,
 ) (int, error) {
-       var blkCtr uint64
        ciphCtr := nonce[len(nonce)-8:]
        buf := make([]byte, EncBlkSize+aead.Overhead())
        var toRead []byte
@@ -164,8 +168,7 @@ func aeadProcess(
                        }
                }
                readBytes += n
-               blkCtr++
-               binary.BigEndian.PutUint64(ciphCtr, blkCtr)
+               ctrIncr(ciphCtr)
                if doEncrypt {
                        toWrite = aead.Seal(buf[:0], nonce, buf[:n], nil)
                } else {
@@ -197,25 +200,25 @@ func PktEncWrite(
        size, padSize int64,
        data io.Reader,
        out io.Writer,
-) error {
+) ([]byte, error) {
        pubEph, prvEph, err := box.GenerateKey(rand.Reader)
        if err != nil {
-               return err
+               return nil, err
        }
        var pktBuf bytes.Buffer
        if _, err := xdr.Marshal(&pktBuf, pkt); err != nil {
-               return err
+               return nil, err
        }
        tbs := PktTbs{
                Magic:     MagicNNCPEv4,
                Nice:      nice,
                Sender:    our.Id,
                Recipient: their.Id,
-               ExchPub:   pubEph,
+               ExchPub:   *pubEph,
        }
        var tbsBuf bytes.Buffer
        if _, err = xdr.Marshal(&tbsBuf, &tbs); err != nil {
-               return err
+               return nil, err
        }
        signature := new([ed25519.SignatureSize]byte)
        copy(signature[:], ed25519.Sign(our.SignPrv, tbsBuf.Bytes()))
@@ -224,29 +227,34 @@ func PktEncWrite(
                Nice:      nice,
                Sender:    our.Id,
                Recipient: their.Id,
-               ExchPub:   pubEph,
-               Sign:      signature,
+               ExchPub:   *pubEph,
+               Sign:      *signature,
+       }
+       tbsBuf.Reset()
+       if _, err = xdr.Marshal(&tbsBuf, &pktEnc); err != nil {
+               return nil, err
        }
-       if _, err = xdr.Marshal(out, &pktEnc); err != nil {
-               return err
+       pktEncRaw := tbsBuf.Bytes()
+       if _, err = out.Write(pktEncRaw); err != nil {
+               return nil, err
        }
        sharedKey := new([32]byte)
        curve25519.ScalarMult(sharedKey, prvEph, their.ExchPub)
        kdf, err := blake2b.NewXOF(KDFXOFSize, sharedKey[:])
        if err != nil {
-               return err
+               return nil, err
        }
        if _, err = kdf.Write(MagicNNCPEv4[:]); err != nil {
-               return err
+               return nil, err
        }
 
        key := make([]byte, chacha20poly1305.KeySize)
        if _, err = io.ReadFull(kdf, key); err != nil {
-               return err
+               return nil, err
        }
        aead, err := chacha20poly1305.New(key)
        if err != nil {
-               return err
+               return nil, err
        }
        nonce := make([]byte, aead.NonceSize())
 
@@ -254,31 +262,31 @@ func PktEncWrite(
        sizeBuf := make([]byte, 8+aead.Overhead())
        binary.BigEndian.PutUint64(sizeBuf, uint64(sizeWithTags(int64(fullSize))))
        if _, err = out.Write(aead.Seal(sizeBuf[:0], nonce, sizeBuf[:8], nil)); err != nil {
-               return err
+               return nil, err
        }
 
        lr := io.LimitedReader{R: data, N: size}
        mr := io.MultiReader(&pktBuf, &lr)
        written, err := aeadProcess(aead, nonce, true, mr, out)
        if err != nil {
-               return err
+               return nil, err
        }
        if written != fullSize {
-               return io.ErrUnexpectedEOF
+               return nil, io.ErrUnexpectedEOF
        }
        if padSize > 0 {
                if _, err = io.ReadFull(kdf, key); err != nil {
-                       return err
+                       return nil, err
                }
                kdf, err = blake2b.NewXOF(blake2b.OutputLengthUnknown, key)
                if err != nil {
-                       return err
+                       return nil, err
                }
                if _, err = io.CopyN(out, kdf, padSize); err != nil {
-                       return err
+                       return nil, err
                }
        }
-       return nil
+       return pktEncRaw, nil
 }
 
 func TbsVerify(our *NodeOur, their *Node, pktEnc *PktEnc) (bool, error) {
@@ -325,7 +333,7 @@ func PktEncRead(
                return their, 0, errors.New("Invalid signature")
        }
        sharedKey := new([32]byte)
-       curve25519.ScalarMult(sharedKey, our.ExchPrv, pktEnc.ExchPub)
+       curve25519.ScalarMult(sharedKey, our.ExchPrv, &pktEnc.ExchPub)
        kdf, err := blake2b.NewXOF(KDFXOFSize, sharedKey[:])
        if err != nil {
                return their, 0, err