mirror of https://github.com/cbeuw/Cloak
Handle error and retry for Crypto.rand
This commit is contained in:
parent
e714dc61a8
commit
517a6d6e57
|
|
@ -3,7 +3,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"flag"
|
||||
|
|
@ -29,7 +28,7 @@ func makeSession(sta *client.State, isAdmin bool) *mux.Session {
|
|||
// sessionID is usergenerated. There shouldn't be a security concern because the scope of
|
||||
// sessionID is limited to its UID.
|
||||
quad := make([]byte, 4)
|
||||
rand.Read(quad)
|
||||
util.CryptoRandRead(quad)
|
||||
atomic.StoreUint32(&sta.SessionID, binary.BigEndian.Uint32(quad))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
|
@ -71,7 +70,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
|||
}
|
||||
|
||||
sessionKey := make([]byte, 32)
|
||||
rand.Read(sessionKey)
|
||||
util.CryptoRandRead(sessionKey)
|
||||
obfuscator, err := mux.GenerateObfs(ci.EncryptionMethod, sessionKey, ci.Transport.HasRecordLayer())
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ package main
|
|||
import (
|
||||
"crypto/rand"
|
||||
"github.com/cbeuw/Cloak/internal/ecdh"
|
||||
"github.com/cbeuw/Cloak/internal/util"
|
||||
)
|
||||
|
||||
func generateUID() string {
|
||||
UID := make([]byte, 16)
|
||||
rand.Read(UID)
|
||||
util.CryptoRandRead(UID)
|
||||
return b64(UID)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"github.com/cbeuw/Cloak/internal/util"
|
||||
)
|
||||
|
||||
type Chrome struct{}
|
||||
|
|
@ -14,7 +14,7 @@ func makeGREASE() []byte {
|
|||
// see https://tools.ietf.org/html/draft-davidben-tls-grease-01
|
||||
// This is exclusive to Chrome.
|
||||
var one [1]byte
|
||||
rand.Read(one[:])
|
||||
util.CryptoRandRead(one[:])
|
||||
sixteenth := one[0] % 16
|
||||
monoGREASE := byte(sixteenth*16 + 0xA)
|
||||
doubleGREASE := []byte{monoGREASE, monoGREASE}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"github.com/cbeuw/Cloak/internal/util"
|
||||
)
|
||||
|
||||
type Firefox struct{}
|
||||
|
|
@ -19,7 +19,7 @@ func (f *Firefox) composeExtensions(SNI []byte, keyShare []byte) []byte {
|
|||
copy(ret[6:38], hidden)
|
||||
ret[38], ret[39] = 0x00, 0x17 // group secp256r1
|
||||
ret[40], ret[41] = 0x00, 0x41 // length 65
|
||||
rand.Read(ret[42:107])
|
||||
util.CryptoRandRead(ret[42:107])
|
||||
return ret
|
||||
}
|
||||
// extension length is always 399, and server name length is variable
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ package multiplex
|
|||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/cbeuw/Cloak/internal/util"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/salsa20"
|
||||
)
|
||||
|
|
@ -64,7 +64,7 @@ func MakeObfs(salsaKey [32]byte, payloadCipher cipher.AEAD, hasRecordLayer bool)
|
|||
if payloadCipher == nil {
|
||||
copy(encryptedPayloadWithExtra, f.Payload)
|
||||
if extraLen != 0 {
|
||||
rand.Read(encryptedPayloadWithExtra[len(encryptedPayloadWithExtra)-int(extraLen):])
|
||||
util.CryptoRandRead(encryptedPayloadWithExtra[len(encryptedPayloadWithExtra)-int(extraLen):])
|
||||
}
|
||||
} else {
|
||||
ciphertext := payloadCipher.Seal(nil, header[:12], f.Payload, nil)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package multiplex
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/cbeuw/Cloak/internal/util"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
|
@ -251,9 +251,9 @@ func (sesh *Session) passiveClose() error {
|
|||
|
||||
func genRandomPadding() []byte {
|
||||
lenB := make([]byte, 1)
|
||||
rand.Read(lenB)
|
||||
util.CryptoRandRead(lenB)
|
||||
pad := make([]byte, lenB[0])
|
||||
rand.Read(pad)
|
||||
util.CryptoRandRead(pad)
|
||||
return pad
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package server
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
|
|
@ -164,7 +163,7 @@ func parseClientHello(data []byte) (ret *ClientHello, err error) {
|
|||
|
||||
func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte) ([]byte, error) {
|
||||
nonce := make([]byte, 12)
|
||||
rand.Read(nonce)
|
||||
util.CryptoRandRead(nonce)
|
||||
|
||||
encryptedKey, err := util.AESGCMEncrypt(nonce, sharedSecret, sessionKey) // 32 + 16 = 48 bytes
|
||||
if err != nil {
|
||||
|
|
@ -185,7 +184,7 @@ func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte
|
|||
keyShare, _ := hex.DecodeString("00330024001d0020")
|
||||
keyExchange := make([]byte, 32)
|
||||
copy(keyExchange, encryptedKey[20:48])
|
||||
rand.Read(keyExchange[28:32])
|
||||
util.CryptoRandRead(keyExchange[28:32])
|
||||
serverHello[9] = append(keyShare, keyExchange...)
|
||||
|
||||
serverHello[10], _ = hex.DecodeString("002b00020304")
|
||||
|
|
@ -207,7 +206,7 @@ func composeReply(ch *ClientHello, sharedSecret []byte, sessionKey []byte) ([]by
|
|||
shBytes := addRecordLayer(sh, []byte{0x16}, TLS12)
|
||||
ccsBytes := addRecordLayer([]byte{0x01}, []byte{0x14}, TLS12)
|
||||
cert := make([]byte, 68) // TODO: add some different lengths maybe?
|
||||
rand.Read(cert)
|
||||
util.CryptoRandRead(cert)
|
||||
encryptedCertBytes := addRecordLayer(cert, []byte{0x17}, TLS12)
|
||||
ret := append(shBytes, ccsBytes...)
|
||||
ret = append(ret, encryptedCertBytes...)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -45,7 +44,7 @@ func (WebSocket) handshake(reqPacket []byte, privateKey crypto.PrivateKey, origi
|
|||
<-handler.finished
|
||||
preparedConn = handler.conn
|
||||
nonce := make([]byte, 12)
|
||||
rand.Read(nonce)
|
||||
util.CryptoRandRead(nonce)
|
||||
|
||||
// reply: [12 bytes nonce][32 bytes encrypted session key][16 bytes authentication tag]
|
||||
encryptedKey, err := util.AESGCMEncrypt(nonce, ai.sharedSecret[:], sessionKey) // 32 + 16 = 48 bytes
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@ package util
|
|||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func AESGCMEncrypt(nonce []byte, key []byte, plaintext []byte) ([]byte, error) {
|
||||
|
|
@ -39,6 +42,25 @@ func AESGCMDecrypt(nonce []byte, key []byte, ciphertext []byte) ([]byte, error)
|
|||
return plain, nil
|
||||
}
|
||||
|
||||
func CryptoRandRead(buf []byte) {
|
||||
_, err := rand.Read(buf)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
waitDur := [10]time.Duration{5 * time.Millisecond, 10 * time.Millisecond, 30 * time.Millisecond, 50 * time.Millisecond,
|
||||
100 * time.Millisecond, 300 * time.Millisecond, 500 * time.Millisecond, 1 * time.Second,
|
||||
3 * time.Second, 5 * time.Second}
|
||||
for i := 0; i < 10; i++ {
|
||||
log.Errorf("Failed to get cryptographic random bytes: %v. Retrying...", err)
|
||||
_, err = rand.Read(buf)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * waitDur[i])
|
||||
}
|
||||
log.Fatal("Cannot get cryptographic random bytes after 10 retries")
|
||||
}
|
||||
|
||||
// ReadTLS reads TLS data according to its record layer
|
||||
func ReadTLS(conn net.Conn, buffer []byte) (n int, err error) {
|
||||
// TCP is a stream. Multiple TLS messages can arrive at the same time,
|
||||
|
|
|
|||
Loading…
Reference in New Issue