Handle error and retry for Crypto.rand

pull/97/head
Andy Wang 4 years ago
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…
Cancel
Save