github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/libs/niaucchi4/tunnel.go (about)

     1  package niaucchi4
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/cipher"
     6  	"crypto/hmac"
     7  	"crypto/rand"
     8  	"crypto/sha256"
     9  	"encoding/binary"
    10  	"errors"
    11  	"fmt"
    12  	mrand "math/rand"
    13  	"time"
    14  
    15  	"github.com/ethereum/go-ethereum/rlp"
    16  	"github.com/geph-official/geph2/libs/c25519"
    17  	"golang.org/x/crypto/chacha20poly1305"
    18  	"golang.org/x/crypto/curve25519"
    19  )
    20  
    21  var masterSec = make([]byte, 32)
    22  
    23  func genSK(seed []byte) [32]byte {
    24  	return c25519.GenSKWithSeed(append(seed, masterSec...))
    25  }
    26  
    27  func init() {
    28  	rand.Read(masterSec)
    29  }
    30  
    31  func hm(m, k []byte) []byte {
    32  	h := hmac.New(sha256.New, k)
    33  	h.Write(m)
    34  	return h.Sum(nil)
    35  }
    36  
    37  type tunstate struct {
    38  	enc              cipher.AEAD
    39  	dec              cipher.AEAD
    40  	ss               []byte
    41  	isserv           bool
    42  	replayProtection bool
    43  	rw               replayWindow
    44  }
    45  
    46  func (ts *tunstate) deriveKeys(ss []byte) {
    47  	//log.Printf("deriving keys from shared state %x", ss[:5])
    48  	ts.ss = ss
    49  	upcrypt := aead(hm(ss, []byte("up")))
    50  	dncrypt := aead(hm(ss, []byte("dn")))
    51  	if ts.isserv {
    52  		ts.enc = dncrypt
    53  		ts.dec = upcrypt
    54  	} else {
    55  		ts.enc = upcrypt
    56  		ts.dec = dncrypt
    57  	}
    58  }
    59  
    60  func (ts *tunstate) Decrypt(pkt []byte) (bts []byte, err error) {
    61  	ns := ts.dec.NonceSize()
    62  	if len(pkt) < ns {
    63  		err = errors.New("WAT")
    64  		return
    65  	}
    66  	bts, err = ts.dec.Open(nil, pkt[:ns], pkt[ns:], nil)
    67  	if err != nil {
    68  		return
    69  	}
    70  	if ts.replayProtection {
    71  		var e2epkt e2ePacket
    72  		err = rlp.DecodeBytes(bts, &e2epkt)
    73  		if err != nil {
    74  			return
    75  		}
    76  		if !ts.rw.check(e2epkt.Sn) {
    77  			err = errors.New("blocking replay")
    78  			return
    79  		}
    80  	}
    81  	return
    82  }
    83  
    84  func (ts *tunstate) Encrypt(pkt []byte) (ctext []byte) {
    85  	nonceb := make([]byte, ts.enc.NonceSize())
    86  	rand.Read(nonceb)
    87  	ctext = ts.enc.Seal(nonceb, nonceb, pkt, nil)
    88  	return
    89  }
    90  
    91  type prototun struct {
    92  	mySK   [32]byte
    93  	cookie []byte
    94  }
    95  
    96  func (pt *prototun) realize(response []byte, isserv bool, replayProtection bool) (ts *tunstate, err error) {
    97  	// decode their hello
    98  	var theirHello helloPkt
    99  	err = binary.Read(bytes.NewReader(response), binary.BigEndian, &theirHello)
   100  	if err != nil {
   101  		return
   102  	}
   103  	// create possible nowcookies
   104  	for i := -30; i < 30; i++ {
   105  		// derive nowcookie
   106  		nowcookie := hm(pt.cookie, []byte(fmt.Sprintf("%v", time.Now().Unix()/30+int64(i))))
   107  		//log.Printf("trying nowcookie %x", nowcookie[:5])
   108  		boo := aead(hm(nowcookie, theirHello.Nonce[:]))
   109  		theirPK, e := boo.
   110  			Open(nil, make([]byte, boo.NonceSize()), theirHello.EncPK[:], nil)
   111  		if e != nil {
   112  			continue
   113  		}
   114  		var sharedsec [32]byte
   115  		var theirPKf [32]byte
   116  		copy(theirPKf[:], theirPK)
   117  		if isserv {
   118  			pt.mySK = genSK(theirPKf[:])
   119  		}
   120  		curve25519.ScalarMult(&sharedsec, &pt.mySK, &theirPKf)
   121  		// make ts
   122  		ts = &tunstate{
   123  			isserv:           isserv,
   124  			replayProtection: replayProtection,
   125  		}
   126  		ts.deriveKeys(sharedsec[:])
   127  		return
   128  	}
   129  	err = errors.New("none of the cookies work")
   130  	return
   131  }
   132  
   133  func newproto(cookie []byte) (pt *prototun) {
   134  	//log.Printf("newproto with cookie = %x and nowcookie = %x", cookie[:5], nowcookie[:5])
   135  	// generate keys
   136  	sk := c25519.GenSK()
   137  	pt = &prototun{
   138  		mySK:   sk,
   139  		cookie: cookie,
   140  	}
   141  	return
   142  }
   143  
   144  func (pt *prototun) genHello() []byte {
   145  	var pk [32]byte
   146  	curve25519.ScalarBaseMult(&pk, &pt.mySK)
   147  	// derive nowcookie
   148  	nowcookie := hm(pt.cookie, []byte(fmt.Sprintf("%v", time.Now().Unix()/30)))
   149  	// create hello
   150  	nonce := make([]byte, 32)
   151  	rand.Read(nonce)
   152  	crypter := aead(hm(nowcookie, nonce))
   153  	encpk := crypter.
   154  		Seal(nil, make([]byte, crypter.NonceSize()), pk[:], nil)
   155  	if len(encpk) != 32+crypter.Overhead() {
   156  		panic("encpk not right bytes long")
   157  	}
   158  	// form the pkt
   159  	var tosend helloPkt
   160  	copy(tosend.Nonce[:], nonce)
   161  	copy(tosend.EncPK[:], encpk)
   162  	buf := new(bytes.Buffer)
   163  	binary.Write(buf, binary.BigEndian, tosend)
   164  	padd := make([]byte, mrand.Int()%1000)
   165  	mrand.Read(padd)
   166  	buf.Write(padd)
   167  	return buf.Bytes()
   168  }
   169  
   170  func aead(key []byte) cipher.AEAD {
   171  	a, e := chacha20poly1305.NewX(key)
   172  	if e != nil {
   173  		panic(e)
   174  	}
   175  	return a
   176  }
   177  
   178  type helloPkt struct {
   179  	Nonce [32]byte
   180  	EncPK [48]byte
   181  }