// Decrypt the Hello using the node's private comms key, and decode its
// contents.
func ServerDecryptHello(ciphertext []byte, ckPriv *rsa.PrivateKey, rng *xr.PRNG) (
	sOneShot *AesSession, version1s uint32, err error) {
	if rng == nil {
		rng = xr.MakeSystemRNG()
	}
	sha := sha1.New()
	data, err := rsa.DecryptOAEP(sha, nil, ckPriv, ciphertext, nil)
	// DEBUG
	if err == nil {
		expectedLen := 2*aes.BlockSize + 12
		if len(data) != expectedLen {
			fmt.Printf("expected OAEP packet len %d, actual %d bytes\n",
				expectedLen, len(data))
			err = WrongOAEPSize // XXX BAD NAME
		}
	}
	// END
	if err == nil {
		key1s := data[:2*aes.BlockSize]
		// salt1s = data[2*aes.BlockSize : 2*aes.BlockSize+8]
		vBytes := data[2*aes.BlockSize+8:]
		version1s = uint32(vBytes[0]) |
			uint32(vBytes[1])<<8 |
			uint32(vBytes[2])<<16 |
			uint32(vBytes[3])<<24
		sOneShot, err = NewAesSession(key1s, rng)
	}
	return
}
// Create an AES IV and key and an 8-byte salt, then encrypt these and
// the proposed protocol version using the server's comms public key.
func ClientEncryptHello(version1 uint32, ck *rsa.PublicKey, rng *xr.PRNG) (
	cOneShot *AesSession, ciphertext []byte, err error) {

	if rng == nil {
		rng = xr.MakeSystemRNG()
	}
	vBytes := make([]byte, 4)
	vBytes[0] = byte(version1)
	vBytes[1] = byte(version1 >> 8)
	vBytes[2] = byte(version1 >> 16)
	vBytes[3] = byte(version1 >> 24)

	// Generate 32-byte AES key, and 8-byte salt for the Hello
	salty := make([]byte, 2*aes.BlockSize+8+20)
	rng.NextBytes(salty)

	key1 := salty[:2*aes.BlockSize]
	// salt1 := salty[2*aes.BlockSize : 2*aes.BlockSize+8]
	oaep1 := salty[2*aes.BlockSize+8:]
	oaepSalt := bytes.NewBuffer(oaep1)

	sha := sha1.New()
	data := salty[:2*aes.BlockSize+8] // contains key1,salt1
	data = append(data, vBytes...)    // ... plus preferred protocol version

	ciphertext, err = rsa.EncryptOAEP(sha, oaepSalt, ck, data, nil)
	if err == nil {
		cOneShot, err = NewAesSession(key1, rng)
	}
	return
}
Exemple #3
0
func MakeHelloMsg(n *xn.Node) (m *XLatticeMsg, err error) {
	var ck, sk, salt, sig []byte
	cmd := XLatticeMsg_Hello
	id := n.GetNodeID().Value()
	ck, err = xc.RSAPubKeyToWire(n.GetCommsPublicKey())
	if err == nil {
		sk, err = xc.RSAPubKeyToWire(n.GetSigPublicKey())
	}
	if err == nil {
		sysRNG := xr.MakeSystemRNG()
		salt = make([]byte, 8)
		sysRNG.NextBytes(salt)
		chunks := [][]byte{id, ck, sk, salt}
		sig, err = n.Sign(chunks)
	}
	if err == nil {
		m = &XLatticeMsg{
			Op:       &cmd,
			MsgN:     &ONE,
			ID:       id,
			CommsKey: ck,
			SigKey:   sk,
			Salt:     salt,
			Sig:      sig,
		}
	}
	return
}
Exemple #4
0
func (mm *MemberMaker) SessionSetup(proposedVersion uint32) (
	cnx *xt.TcpConnection, decidedVersion uint32, err error) {
	var (
		ciphertext1 []byte
		ciphertext2 []byte
	)
	// Set up connection to server. ---------------------------------
	ctor := mm.RegPeer.GetConnector(0)
	// DEBUG
	fmt.Printf("        SessionSetup: ctor is %s\n", ctor.String())
	// END
	var conn xt.ConnectionI
	//conn, err = ctor.Connect(xt.ANY_TCP_END_POINT) // 2016-11-14
	conn, err = ctor.Connect(nil)
	if err == nil {
		cnx = conn.(*xt.TcpConnection)
		// DEBUG
		fmt.Printf("        SessionSetup: cnx is %s\n", cnx.String())
		// END
		var cnxHandler *CnxHandler
		if err == nil {
			cnxHandler, err = NewCnxHandler(cnx, nil, nil)
			if err == nil {
				cnxHandler.State = MEMBER_START
				mm.CnxHandler = *cnxHandler
			}
		}
	}
	if err == nil {
		var cOneShot, cSession *xa.AesSession
		// Send HELLO -----------------------------------------------
		mm.Cnx = cnx
		ck := mm.RegPeer.GetCommsPublicKey()
		rng := xr.MakeSystemRNG()
		cOneShot, ciphertext1, err = xa.ClientEncryptHello(
			proposedVersion, ck, rng)
		if err == nil {
			err = mm.WriteData(ciphertext1)
			// Process HELLO REPLY ----------------------------------
			if err == nil {
				ciphertext2, err = mm.ReadData()

				if len(ciphertext2) == 0 {
					if err == nil {
						err = io.EOF
					}
				}
				if err == nil {
					cSession, decidedVersion,
						err = xa.ClientDecryptHelloReply(cOneShot, ciphertext2)
					if err == nil {
						mm.AesSession = *cSession
					}
				}
			}
		}
	}
	return
}
Exemple #5
0
// An AesSession establishes one side of a two-sided relationship.  Encryption
// and decryption share the same key (although per-direction keys could be
// supported in a slightly different implementation).  If a random number
// generator (RNG) is not supplied, it uses a secure (and expensive) system
// RNG.  If no key is supplied it creates a random 256-bit AES key.
//
func NewAesSession(key []byte, rng *xr.PRNG) (session *AesSession, err error) {
	if rng == nil {
		rng = xr.MakeSystemRNG()
	}
	if key == nil || len(key) == 0 {
		key = make([]byte, 2*aes.BlockSize)
	}
	engine, err := aes.NewCipher(key)
	if err == nil {
		session = &AesSession{
			Engine: engine,
			Key:    key,
			RNG:    rng,
		}
	}
	return session, err
}
Exemple #6
0
func New(id []byte) (q *NodeID, err error) {
	q = new(NodeID)
	if id == nil {
		id = make([]byte, xu.SHA1_BIN_LEN)
		rng := xr.MakeSystemRNG()
		rng.NextBytes(id)
		q._nodeID = id
	} else {
		// deep copy the slice
		size := len(id)
		myID := make([]byte, size)
		for i := 0; i < size; i++ {
			myID[i] = id[i]
		}
		q._nodeID = myID
	}
	if !IsValidID(id) {
		err = BadNodeIDLen
	}
	return
}
Exemple #7
0
func (upc *UpaxClient) SessionSetup(proposedVersion uint32) (
	upcx *xt.TcpConnection, decidedVersion uint32, err error) {
	var (
		ciphertext1, ciphertext2 []byte
		cOneShot, cSession       *xa.AesSession
	)
	rng := xr.MakeSystemRNG()
	// Set up connection to server. -----------------------------
	ctor, err := xt.NewTcpConnector(upc.serverEnd)
	if err == nil {
		var conn xt.ConnectionI
		conn, err = ctor.Connect(nil)
		if err == nil {
			upcx = conn.(*xt.TcpConnection)
		}
	}
	// Send HELLO -----------------------------------------------
	if err == nil {
		upc.Cnx = upcx
		cOneShot, ciphertext1, err = xa.ClientEncryptHello(
			proposedVersion, upc.serverCK, rng)
	}
	if err == nil {
		err = upc.WriteData(ciphertext1)
	}
	// Process HELLO REPLY --------------------------------------
	if err == nil {
		ciphertext2, err = upc.ReadData()
	}
	if err == nil {
		cSession, decidedVersion, err = xa.ClientDecryptHelloReply(
			cOneShot, ciphertext2)
	}
	// Set up AES engines ---------------------------------------
	if err == nil {
		upc.AesSession = *cSession
		upc.Version = xu.DecimalVersion(decidedVersion)
	}
	return
}
Exemple #8
0
// The client has sent the server a one-time AES key+iv encrypted with
// the server's RSA comms public key.  The server creates the real
// session iv+key and returns them to the client encrypted with the
// one-time key+iv.
//
// XXX This is simply a copy of the function in s_in_handler.go, with
// "Out" inserted: we definitely need to refactor!
//
func handleOutPeerHello(h *ClusterOutHandler) (err error) {
	var (
		ciphertext, ciphertextOut []byte
		version1                  uint32
		sOneShot, sSession        *xa.AesSession
		rng                       *xr.PRNG
	)
	ciphertext, err = h.ReadData()
	if err == nil {
		rng = xr.MakeSystemRNG()
		sOneShot, version1, err = xa.ServerDecryptHello(
			ciphertext, h.us.ckPriv, rng)
	}
	if err == nil {
		_ = version1 // just ignored for now
		version2 := uint32(serverVersion)
		sSession, ciphertextOut, err = xa.ServerEncryptHelloReply(
			sOneShot, version2)
		if err == nil {
			h.AesSession = *sSession
			err = h.WriteData(ciphertextOut)
		}
		if err == nil {
			h.version = uint32(version2)
			h.State = S_HELLO_RCVD
		}
	}
	// On any error silently close the connection and delete the handler,
	// an exciting thing to do.
	if err != nil {
		// DEBUG
		fmt.Printf("handleOutPeerHello closing cnx, error was %v\n", err)
		// END
		h.Cnx.Close()
		h = nil
	}
	return
}
Exemple #9
0
// The client has sent the server a one-time AES key+iv encrypted with
// the server's RSA comms public key.  The server creates the real
// session iv+key and returns them to the client encrypted with the
// one-time key+iv.
func handleClientHello(h *ClientInHandler) (err error) {
	var (
		ciphertext, ciphertextOut []byte
		version1, version2        uint32
		sOneShot, sSession        *xa.AesSession
	)
	rng := xr.MakeSystemRNG()
	ciphertext, err = h.ReadData()
	if err == nil {
		sOneShot, version1, err = xa.ServerDecryptHello(
			ciphertext, h.us.ckPriv, rng)
		_ = version1 // we don't actually use this
	}
	if err == nil {
		version2 = uint32(serverVersion) // a global !
		sSession, ciphertextOut, err = xa.ServerEncryptHelloReply(
			sOneShot, version2)
		if err == nil {
			h.AesSession = *sSession
			err = h.WriteData(ciphertextOut)
		}
		if err == nil {
			h.version = version2
			h.State = C_HELLO_RCVD
		}
	}
	// On any error silently close the connection.
	if err != nil {
		// DEBUG
		fmt.Printf("handleClientHello closing cnx, error was %s\n",
			err.Error())
		// END
		h.Cnx.Close()
	}
	return
}