mirror of
https://github.com/vacp2p/nim-libp2p.git
synced 2026-01-10 00:28:10 -05:00
chore(formatting): format the whole codebase using nph 0.5.1 (#1118)
This commit is contained in:
@@ -22,8 +22,7 @@ import ../../protobuf/minprotobuf
|
||||
import ../../utility
|
||||
import ../../errors
|
||||
|
||||
import secure,
|
||||
../../crypto/[crypto, chacha20poly1305, curve25519, hkdf]
|
||||
import secure, ../../crypto/[crypto, chacha20poly1305, curve25519, hkdf]
|
||||
|
||||
when defined(libp2p_dump):
|
||||
import ../../debugutils
|
||||
@@ -99,12 +98,15 @@ type
|
||||
|
||||
func shortLog*(conn: NoiseConnection): auto =
|
||||
try:
|
||||
if conn == nil: "NoiseConnection(nil)"
|
||||
else: &"{shortLog(conn.peerId)}:{conn.oid}"
|
||||
if conn == nil:
|
||||
"NoiseConnection(nil)"
|
||||
else:
|
||||
&"{shortLog(conn.peerId)}:{conn.oid}"
|
||||
except ValueError as exc:
|
||||
raiseAssert(exc.msg)
|
||||
|
||||
chronicles.formatIt(NoiseConnection): shortLog(it)
|
||||
chronicles.formatIt(NoiseConnection):
|
||||
shortLog(it)
|
||||
|
||||
proc genKeyPair(rng: var HmacDrbgContext): KeyPair =
|
||||
result.privateKey = Curve25519Key.random(rng)
|
||||
@@ -116,7 +118,7 @@ proc hashProtocol(name: string): MDigest[256] =
|
||||
# Otherwise sets h = HASH(protocol_name).
|
||||
|
||||
if name.len <= 32:
|
||||
result.data[0..name.high] = name.toBytes
|
||||
result.data[0 .. name.high] = name.toBytes
|
||||
else:
|
||||
result = sha256.digest(name)
|
||||
|
||||
@@ -130,13 +132,10 @@ proc hasKey(cs: CipherState): bool =
|
||||
cs.k != EmptyKey
|
||||
|
||||
proc encrypt(
|
||||
state: var CipherState,
|
||||
data: var openArray[byte],
|
||||
ad: openArray[byte]): ChaChaPolyTag
|
||||
{.noinit, raises: [NoiseNonceMaxError].} =
|
||||
|
||||
state: var CipherState, data: var openArray[byte], ad: openArray[byte]
|
||||
): ChaChaPolyTag {.noinit, raises: [NoiseNonceMaxError].} =
|
||||
var nonce: ChaChaPolyNonce
|
||||
nonce[4..<12] = toBytesLE(state.n)
|
||||
nonce[4 ..< 12] = toBytesLE(state.n)
|
||||
|
||||
ChaChaPoly.encrypt(state.k, nonce, result, data, ad)
|
||||
|
||||
@@ -144,8 +143,9 @@ proc encrypt(
|
||||
if state.n > NonceMax:
|
||||
raise (ref NoiseNonceMaxError)(msg: "Noise max nonce value reached")
|
||||
|
||||
proc encryptWithAd(state: var CipherState, ad, data: openArray[byte]): seq[byte]
|
||||
{.raises: [NoiseNonceMaxError].} =
|
||||
proc encryptWithAd(
|
||||
state: var CipherState, ad, data: openArray[byte]
|
||||
): seq[byte] {.raises: [NoiseNonceMaxError].} =
|
||||
result = newSeqOfCap[byte](data.len + sizeof(ChaChaPolyTag))
|
||||
result.add(data)
|
||||
|
||||
@@ -156,20 +156,21 @@ proc encryptWithAd(state: var CipherState, ad, data: openArray[byte]): seq[byte]
|
||||
trace "encryptWithAd",
|
||||
tag = byteutils.toHex(tag), data = result.shortLog, nonce = state.n - 1
|
||||
|
||||
proc decryptWithAd(state: var CipherState, ad, data: openArray[byte]): seq[byte]
|
||||
{.raises: [NoiseDecryptTagError, NoiseNonceMaxError].} =
|
||||
proc decryptWithAd(
|
||||
state: var CipherState, ad, data: openArray[byte]
|
||||
): seq[byte] {.raises: [NoiseDecryptTagError, NoiseNonceMaxError].} =
|
||||
var
|
||||
tagIn = data.toOpenArray(data.len - ChaChaPolyTag.len, data.high).intoChaChaPolyTag
|
||||
tagOut: ChaChaPolyTag
|
||||
nonce: ChaChaPolyNonce
|
||||
nonce[4..<12] = toBytesLE(state.n)
|
||||
result = data[0..(data.high - ChaChaPolyTag.len)]
|
||||
nonce[4 ..< 12] = toBytesLE(state.n)
|
||||
result = data[0 .. (data.high - ChaChaPolyTag.len)]
|
||||
ChaChaPoly.decrypt(state.k, nonce, tagOut, result, ad)
|
||||
trace "decryptWithAd", tagIn = tagIn.shortLog, tagOut = tagOut.shortLog, nonce = state.n
|
||||
trace "decryptWithAd",
|
||||
tagIn = tagIn.shortLog, tagOut = tagOut.shortLog, nonce = state.n
|
||||
if tagIn != tagOut:
|
||||
debug "decryptWithAd failed", data = shortLog(data)
|
||||
raise (ref NoiseDecryptTagError)(msg:
|
||||
"decryptWithAd failed tag authentication.")
|
||||
raise (ref NoiseDecryptTagError)(msg: "decryptWithAd failed tag authentication.")
|
||||
inc state.n
|
||||
if state.n > NonceMax:
|
||||
raise (ref NoiseNonceMaxError)(msg: "Noise max nonce value reached")
|
||||
@@ -204,8 +205,9 @@ proc mixKeyAndHash(ss: var SymmetricState, ikm: openArray[byte]) {.used.} =
|
||||
ss.mixHash(temp_keys[1])
|
||||
ss.cs = CipherState(k: temp_keys[2])
|
||||
|
||||
proc encryptAndHash(ss: var SymmetricState, data: openArray[byte]): seq[byte]
|
||||
{.raises: [NoiseNonceMaxError].} =
|
||||
proc encryptAndHash(
|
||||
ss: var SymmetricState, data: openArray[byte]
|
||||
): seq[byte] {.raises: [NoiseNonceMaxError].} =
|
||||
# according to spec if key is empty leave plaintext
|
||||
if ss.cs.hasKey:
|
||||
result = ss.cs.encryptWithAd(ss.h.data, data)
|
||||
@@ -213,8 +215,9 @@ proc encryptAndHash(ss: var SymmetricState, data: openArray[byte]): seq[byte]
|
||||
result = @data
|
||||
ss.mixHash(result)
|
||||
|
||||
proc decryptAndHash(ss: var SymmetricState, data: openArray[byte]): seq[byte]
|
||||
{.raises: [NoiseDecryptTagError, NoiseNonceMaxError].} =
|
||||
proc decryptAndHash(
|
||||
ss: var SymmetricState, data: openArray[byte]
|
||||
): seq[byte] {.raises: [NoiseDecryptTagError, NoiseNonceMaxError].} =
|
||||
# according to spec if key is empty leave plaintext
|
||||
if ss.cs.hasKey and data.len > ChaChaPolyTag.len:
|
||||
result = ss.cs.decryptWithAd(ss.h.data, data)
|
||||
@@ -223,15 +226,14 @@ proc decryptAndHash(ss: var SymmetricState, data: openArray[byte]): seq[byte]
|
||||
ss.mixHash(data)
|
||||
|
||||
proc split(ss: var SymmetricState): tuple[cs1, cs2: CipherState] =
|
||||
var
|
||||
temp_keys: array[2, ChaChaPolyKey]
|
||||
var temp_keys: array[2, ChaChaPolyKey]
|
||||
sha256.hkdf(ss.ck, [], [], temp_keys)
|
||||
return (CipherState(k: temp_keys[0]), CipherState(k: temp_keys[1]))
|
||||
|
||||
proc init(_: type[HandshakeState]): HandshakeState =
|
||||
result.ss = SymmetricState.init()
|
||||
|
||||
template write_e: untyped =
|
||||
template write_e(): untyped =
|
||||
trace "noise write e"
|
||||
# Sets e (which must be empty) to GENERATE_KEYPAIR().
|
||||
# Appends e.public_key to the buffer. Calls MixHash(e.public_key).
|
||||
@@ -239,17 +241,17 @@ template write_e: untyped =
|
||||
msg.add hs.e.publicKey
|
||||
hs.ss.mixHash(hs.e.publicKey)
|
||||
|
||||
template write_s: untyped =
|
||||
template write_s(): untyped =
|
||||
trace "noise write s"
|
||||
# Appends EncryptAndHash(s.public_key) to the buffer.
|
||||
msg.add hs.ss.encryptAndHash(hs.s.publicKey)
|
||||
|
||||
template dh_ee: untyped =
|
||||
template dh_ee(): untyped =
|
||||
trace "noise dh ee"
|
||||
# Calls MixKey(DH(e, re)).
|
||||
hs.ss.mixKey(dh(hs.e.privateKey, hs.re))
|
||||
|
||||
template dh_es: untyped =
|
||||
template dh_es(): untyped =
|
||||
trace "noise dh es"
|
||||
# Calls MixKey(DH(e, rs)) if initiator, MixKey(DH(s, re)) if responder.
|
||||
when initiator:
|
||||
@@ -257,7 +259,7 @@ template dh_es: untyped =
|
||||
else:
|
||||
hs.ss.mixKey(dh(hs.s.privateKey, hs.re))
|
||||
|
||||
template dh_se: untyped =
|
||||
template dh_se(): untyped =
|
||||
trace "noise dh se"
|
||||
# Calls MixKey(DH(s, re)) if initiator, MixKey(DH(e, rs)) if responder.
|
||||
when initiator:
|
||||
@@ -266,12 +268,12 @@ template dh_se: untyped =
|
||||
hs.ss.mixKey(dh(hs.e.privateKey, hs.rs))
|
||||
|
||||
# might be used for other token/handshakes
|
||||
template dh_ss: untyped {.used.} =
|
||||
template dh_ss(): untyped {.used.} =
|
||||
trace "noise dh ss"
|
||||
# Calls MixKey(DH(s, rs)).
|
||||
hs.ss.mixKey(dh(hs.s.privateKey, hs.rs))
|
||||
|
||||
template read_e: untyped =
|
||||
template read_e(): untyped =
|
||||
trace "noise read e", size = msg.len
|
||||
|
||||
if msg.len < Curve25519Key.len:
|
||||
@@ -279,27 +281,25 @@ template read_e: untyped =
|
||||
|
||||
# Sets re (which must be empty) to the next DHLEN bytes from the message.
|
||||
# Calls MixHash(re.public_key).
|
||||
hs.re[0..Curve25519Key.high] = msg.toOpenArray(0, Curve25519Key.high)
|
||||
hs.re[0 .. Curve25519Key.high] = msg.toOpenArray(0, Curve25519Key.high)
|
||||
msg.consume(Curve25519Key.len)
|
||||
hs.ss.mixHash(hs.re)
|
||||
|
||||
template read_s: untyped =
|
||||
template read_s(): untyped =
|
||||
trace "noise read s", size = msg.len
|
||||
# Sets temp to the next DHLEN + 16 bytes of the message if HasKey() == True,
|
||||
# or to the next DHLEN bytes otherwise.
|
||||
# Sets rs (which must be empty) to DecryptAndHash(temp).
|
||||
let
|
||||
rsLen =
|
||||
if hs.ss.cs.hasKey:
|
||||
if msg.len < Curve25519Key.len + ChaChaPolyTag.len:
|
||||
raise (ref NoiseHandshakeError)(msg: "Noise S, expected more data")
|
||||
Curve25519Key.len + ChaChaPolyTag.len
|
||||
else:
|
||||
if msg.len < Curve25519Key.len:
|
||||
raise (ref NoiseHandshakeError)(msg: "Noise S, expected more data")
|
||||
Curve25519Key.len
|
||||
hs.rs[0..Curve25519Key.high] =
|
||||
hs.ss.decryptAndHash(msg.toOpenArray(0, rsLen - 1))
|
||||
let rsLen =
|
||||
if hs.ss.cs.hasKey:
|
||||
if msg.len < Curve25519Key.len + ChaChaPolyTag.len:
|
||||
raise (ref NoiseHandshakeError)(msg: "Noise S, expected more data")
|
||||
Curve25519Key.len + ChaChaPolyTag.len
|
||||
else:
|
||||
if msg.len < Curve25519Key.len:
|
||||
raise (ref NoiseHandshakeError)(msg: "Noise S, expected more data")
|
||||
Curve25519Key.len
|
||||
hs.rs[0 .. Curve25519Key.high] = hs.ss.decryptAndHash(msg.toOpenArray(0, rsLen - 1))
|
||||
|
||||
msg.consume(rsLen)
|
||||
|
||||
@@ -318,10 +318,8 @@ proc readFrame(
|
||||
return buffer
|
||||
|
||||
proc writeFrame(
|
||||
sconn: Connection,
|
||||
buf: openArray[byte]
|
||||
): Future[void] {.async: (raises: [
|
||||
CancelledError, LPStreamError], raw: true).} =
|
||||
sconn: Connection, buf: openArray[byte]
|
||||
): Future[void] {.async: (raises: [CancelledError, LPStreamError], raw: true).} =
|
||||
doAssert buf.len <= uint16.high.int
|
||||
var
|
||||
lesize = buf.len.uint16
|
||||
@@ -334,25 +332,19 @@ proc writeFrame(
|
||||
|
||||
proc receiveHSMessage(
|
||||
sconn: Connection
|
||||
): Future[seq[byte]] {.async: (raises: [
|
||||
CancelledError, LPStreamError], raw: true).} =
|
||||
): Future[seq[byte]] {.async: (raises: [CancelledError, LPStreamError], raw: true).} =
|
||||
readFrame(sconn)
|
||||
|
||||
proc sendHSMessage(
|
||||
sconn: Connection,
|
||||
buf: openArray[byte]
|
||||
): Future[void] {.async: (raises: [
|
||||
CancelledError, LPStreamError], raw: true).} =
|
||||
sconn: Connection, buf: openArray[byte]
|
||||
): Future[void] {.async: (raises: [CancelledError, LPStreamError], raw: true).} =
|
||||
writeFrame(sconn, buf)
|
||||
|
||||
proc handshakeXXOutbound(
|
||||
p: Noise, conn: Connection,
|
||||
p2pSecret: seq[byte]
|
||||
): Future[HandshakeResult] {.async: (raises: [
|
||||
CancelledError, LPStreamError]).} =
|
||||
p: Noise, conn: Connection, p2pSecret: seq[byte]
|
||||
): Future[HandshakeResult] {.async: (raises: [CancelledError, LPStreamError]).} =
|
||||
const initiator = true
|
||||
var
|
||||
hs = HandshakeState.init()
|
||||
var hs = HandshakeState.init()
|
||||
|
||||
try:
|
||||
hs.ss.mixHash(p.commonPrologue)
|
||||
@@ -391,20 +383,17 @@ proc handshakeXXOutbound(
|
||||
await conn.sendHSMessage(msg.data)
|
||||
|
||||
let (cs1, cs2) = hs.ss.split()
|
||||
return HandshakeResult(
|
||||
cs1: cs1, cs2: cs2, remoteP2psecret: remoteP2psecret, rs: hs.rs)
|
||||
return
|
||||
HandshakeResult(cs1: cs1, cs2: cs2, remoteP2psecret: remoteP2psecret, rs: hs.rs)
|
||||
finally:
|
||||
burnMem(hs)
|
||||
|
||||
proc handshakeXXInbound(
|
||||
p: Noise, conn: Connection,
|
||||
p2pSecret: seq[byte]
|
||||
): Future[HandshakeResult] {.async: (raises: [
|
||||
CancelledError, LPStreamError]).} =
|
||||
p: Noise, conn: Connection, p2pSecret: seq[byte]
|
||||
): Future[HandshakeResult] {.async: (raises: [CancelledError, LPStreamError]).} =
|
||||
const initiator = false
|
||||
|
||||
var
|
||||
hs = HandshakeState.init()
|
||||
var hs = HandshakeState.init()
|
||||
|
||||
try:
|
||||
hs.ss.mixHash(p.commonPrologue)
|
||||
@@ -444,8 +433,8 @@ proc handshakeXXInbound(
|
||||
let
|
||||
remoteP2psecret = hs.ss.decryptAndHash(msg.data)
|
||||
(cs1, cs2) = hs.ss.split()
|
||||
return HandshakeResult(
|
||||
cs1: cs1, cs2: cs2, remoteP2psecret: remoteP2psecret, rs: hs.rs)
|
||||
return
|
||||
HandshakeResult(cs1: cs1, cs2: cs2, remoteP2psecret: remoteP2psecret, rs: hs.rs)
|
||||
finally:
|
||||
burnMem(hs)
|
||||
|
||||
@@ -467,32 +456,26 @@ method readMessage*(
|
||||
trace "Received 0-length message", sconn
|
||||
|
||||
proc encryptFrame(
|
||||
sconn: NoiseConnection,
|
||||
cipherFrame: var openArray[byte],
|
||||
src: openArray[byte])
|
||||
{.raises: [NoiseNonceMaxError].} =
|
||||
sconn: NoiseConnection, cipherFrame: var openArray[byte], src: openArray[byte]
|
||||
) {.raises: [NoiseNonceMaxError].} =
|
||||
# Frame consists of length + cipher data + tag
|
||||
doAssert src.len <= MaxPlainSize
|
||||
doAssert cipherFrame.len == 2 + src.len + sizeof(ChaChaPolyTag)
|
||||
|
||||
cipherFrame[0..<2] = toBytesBE(uint16(src.len + sizeof(ChaChaPolyTag)))
|
||||
cipherFrame[2..<2 + src.len()] = src
|
||||
cipherFrame[0 ..< 2] = toBytesBE(uint16(src.len + sizeof(ChaChaPolyTag)))
|
||||
cipherFrame[2 ..< 2 + src.len()] = src
|
||||
|
||||
let tag = encrypt(
|
||||
sconn.writeCs, cipherFrame.toOpenArray(2, 2 + src.len() - 1), [])
|
||||
let tag = encrypt(sconn.writeCs, cipherFrame.toOpenArray(2, 2 + src.len() - 1), [])
|
||||
|
||||
cipherFrame[2 + src.len()..<cipherFrame.len] = tag
|
||||
cipherFrame[2 + src.len() ..< cipherFrame.len] = tag
|
||||
|
||||
method write*(
|
||||
sconn: NoiseConnection,
|
||||
message: seq[byte]
|
||||
): Future[void] {.async: (raises: [
|
||||
CancelledError, LPStreamError], raw: true).} =
|
||||
sconn: NoiseConnection, message: seq[byte]
|
||||
): Future[void] {.async: (raises: [CancelledError, LPStreamError], raw: true).} =
|
||||
# Fast path: `{.async.}` would introduce a copy of `message`
|
||||
const FramingSize = 2 + sizeof(ChaChaPolyTag)
|
||||
|
||||
let
|
||||
frames = (message.len + MaxPlainSize - 1) div MaxPlainSize
|
||||
let frames = (message.len + MaxPlainSize - 1) div MaxPlainSize
|
||||
|
||||
var
|
||||
cipherFrames = newSeqUninitialized[byte](message.len + frames * FramingSize)
|
||||
@@ -501,15 +484,14 @@ method write*(
|
||||
woffset = 0
|
||||
|
||||
while left > 0:
|
||||
let
|
||||
chunkSize = min(MaxPlainSize, left)
|
||||
let chunkSize = min(MaxPlainSize, left)
|
||||
|
||||
try:
|
||||
encryptFrame(
|
||||
sconn,
|
||||
cipherFrames.toOpenArray(
|
||||
woffset, woffset + chunkSize + FramingSize - 1),
|
||||
message.toOpenArray(offset, offset + chunkSize - 1))
|
||||
cipherFrames.toOpenArray(woffset, woffset + chunkSize + FramingSize - 1),
|
||||
message.toOpenArray(offset, offset + chunkSize - 1),
|
||||
)
|
||||
except NoiseNonceMaxError as exc:
|
||||
debug "Noise nonce exceeded"
|
||||
let fut = newFuture[void]("noise.write.nonce")
|
||||
@@ -518,8 +500,10 @@ method write*(
|
||||
|
||||
when defined(libp2p_dump):
|
||||
dumpMessage(
|
||||
sconn, FlowDirection.Outgoing,
|
||||
message.toOpenArray(offset, offset + chunkSize - 1))
|
||||
sconn,
|
||||
FlowDirection.Outgoing,
|
||||
message.toOpenArray(offset, offset + chunkSize - 1),
|
||||
)
|
||||
|
||||
left = left - chunkSize
|
||||
offset += chunkSize
|
||||
@@ -532,10 +516,7 @@ method write*(
|
||||
sconn.stream.write(cipherFrames)
|
||||
|
||||
method handshake*(
|
||||
p: Noise,
|
||||
conn: Connection,
|
||||
initiator: bool,
|
||||
peerId: Opt[PeerId]
|
||||
p: Noise, conn: Connection, initiator: bool, peerId: Opt[PeerId]
|
||||
): Future[SecureConn] {.async: (raises: [CancelledError, LPStreamError]).} =
|
||||
trace "Starting Noise handshake", conn, initiator
|
||||
|
||||
@@ -543,14 +524,14 @@ method handshake*(
|
||||
conn.timeout = HandshakeTimeout
|
||||
|
||||
# https://github.com/libp2p/specs/tree/master/noise#libp2p-data-in-handshake-messages
|
||||
let signedPayload = p.localPrivateKey.sign(
|
||||
PayloadString & p.noiseKeys.publicKey.getBytes)
|
||||
let signedPayload =
|
||||
p.localPrivateKey.sign(PayloadString & p.noiseKeys.publicKey.getBytes)
|
||||
if signedPayload.isErr():
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Failed to sign public key: " & $signedPayload.error())
|
||||
raise (ref NoiseHandshakeError)(
|
||||
msg: "Failed to sign public key: " & $signedPayload.error()
|
||||
)
|
||||
|
||||
var
|
||||
libp2pProof = initProtoBuffer()
|
||||
var libp2pProof = initProtoBuffer()
|
||||
libp2pProof.write(1, p.localPublicKey)
|
||||
libp2pProof.write(2, signedPayload.get().getBytes())
|
||||
# data field also there but not used!
|
||||
@@ -562,70 +543,76 @@ method handshake*(
|
||||
else:
|
||||
await handshakeXXInbound(p, conn, libp2pProof.buffer)
|
||||
|
||||
var secure = try:
|
||||
var
|
||||
remoteProof = initProtoBuffer(handshakeRes.remoteP2psecret)
|
||||
remotePubKey: PublicKey
|
||||
remotePubKeyBytes: seq[byte]
|
||||
remoteSig: Signature
|
||||
remoteSigBytes: seq[byte]
|
||||
var secure =
|
||||
try:
|
||||
var
|
||||
remoteProof = initProtoBuffer(handshakeRes.remoteP2psecret)
|
||||
remotePubKey: PublicKey
|
||||
remotePubKeyBytes: seq[byte]
|
||||
remoteSig: Signature
|
||||
remoteSigBytes: seq[byte]
|
||||
|
||||
if not remoteProof.getField(1, remotePubKeyBytes).valueOr(false):
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Failed to deserialize remote public key bytes. (initiator: " &
|
||||
$initiator & ")")
|
||||
if not remoteProof.getField(2, remoteSigBytes).valueOr(false):
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Failed to deserialize remote signature bytes. (initiator: " &
|
||||
$initiator & ")")
|
||||
if not remoteProof.getField(1, remotePubKeyBytes).valueOr(false):
|
||||
raise (ref NoiseHandshakeError)(
|
||||
msg:
|
||||
"Failed to deserialize remote public key bytes. (initiator: " & $initiator &
|
||||
")"
|
||||
)
|
||||
if not remoteProof.getField(2, remoteSigBytes).valueOr(false):
|
||||
raise (ref NoiseHandshakeError)(
|
||||
msg:
|
||||
"Failed to deserialize remote signature bytes. (initiator: " & $initiator &
|
||||
")"
|
||||
)
|
||||
|
||||
if not remotePubKey.init(remotePubKeyBytes):
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Failed to decode remote public key. (initiator: " & $initiator & ")")
|
||||
if not remoteSig.init(remoteSigBytes):
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Failed to decode remote signature. (initiator: " & $initiator & ")")
|
||||
if not remotePubKey.init(remotePubKeyBytes):
|
||||
raise (ref NoiseHandshakeError)(
|
||||
msg: "Failed to decode remote public key. (initiator: " & $initiator & ")"
|
||||
)
|
||||
if not remoteSig.init(remoteSigBytes):
|
||||
raise (ref NoiseHandshakeError)(
|
||||
msg: "Failed to decode remote signature. (initiator: " & $initiator & ")"
|
||||
)
|
||||
|
||||
let verifyPayload = PayloadString & handshakeRes.rs.getBytes
|
||||
if not remoteSig.verify(verifyPayload, remotePubKey):
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Noise handshake signature verify failed.")
|
||||
else:
|
||||
trace "Remote signature verified", conn
|
||||
let verifyPayload = PayloadString & handshakeRes.rs.getBytes
|
||||
if not remoteSig.verify(verifyPayload, remotePubKey):
|
||||
raise (ref NoiseHandshakeError)(msg: "Noise handshake signature verify failed.")
|
||||
else:
|
||||
trace "Remote signature verified", conn
|
||||
|
||||
let pid = PeerId.init(remotePubKey).valueOr:
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Invalid remote peer id: " & $error)
|
||||
let pid = PeerId.init(remotePubKey).valueOr:
|
||||
raise (ref NoiseHandshakeError)(msg: "Invalid remote peer id: " & $error)
|
||||
|
||||
trace "Remote peer id", pid = $pid
|
||||
trace "Remote peer id", pid = $pid
|
||||
|
||||
peerId.withValue(targetPid):
|
||||
if not targetPid.validate():
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Failed to validate expected peerId.")
|
||||
peerId.withValue(targetPid):
|
||||
if not targetPid.validate():
|
||||
raise (ref NoiseHandshakeError)(msg: "Failed to validate expected peerId.")
|
||||
|
||||
if pid != targetPid:
|
||||
var
|
||||
failedKey: PublicKey
|
||||
discard extractPublicKey(targetPid, failedKey)
|
||||
debug "Noise handshake, peer id doesn't match!",
|
||||
initiator, dealt_peer = conn,
|
||||
dealt_key = $failedKey, received_peer = $pid,
|
||||
received_key = $remotePubKey
|
||||
raise (ref NoiseHandshakeError)(msg:
|
||||
"Noise handshake, peer id don't match! " & $pid & " != " & $targetPid)
|
||||
conn.peerId = pid
|
||||
if pid != targetPid:
|
||||
var failedKey: PublicKey
|
||||
discard extractPublicKey(targetPid, failedKey)
|
||||
debug "Noise handshake, peer id doesn't match!",
|
||||
initiator,
|
||||
dealt_peer = conn,
|
||||
dealt_key = $failedKey,
|
||||
received_peer = $pid,
|
||||
received_key = $remotePubKey
|
||||
raise (ref NoiseHandshakeError)(
|
||||
msg: "Noise handshake, peer id don't match! " & $pid & " != " & $targetPid
|
||||
)
|
||||
conn.peerId = pid
|
||||
|
||||
var tmp = NoiseConnection.new(conn, conn.peerId, conn.observedAddr)
|
||||
if initiator:
|
||||
tmp.readCs = handshakeRes.cs2
|
||||
tmp.writeCs = handshakeRes.cs1
|
||||
else:
|
||||
tmp.readCs = handshakeRes.cs1
|
||||
tmp.writeCs = handshakeRes.cs2
|
||||
tmp
|
||||
finally:
|
||||
burnMem(handshakeRes)
|
||||
var tmp = NoiseConnection.new(conn, conn.peerId, conn.observedAddr)
|
||||
if initiator:
|
||||
tmp.readCs = handshakeRes.cs2
|
||||
tmp.writeCs = handshakeRes.cs1
|
||||
else:
|
||||
tmp.readCs = handshakeRes.cs1
|
||||
tmp.writeCs = handshakeRes.cs2
|
||||
tmp
|
||||
finally:
|
||||
burnMem(handshakeRes)
|
||||
|
||||
trace "Noise handshake completed!", initiator, peer = shortLog(secure.peerId)
|
||||
|
||||
@@ -648,10 +635,13 @@ proc new*(
|
||||
rng: ref HmacDrbgContext,
|
||||
privateKey: PrivateKey,
|
||||
outgoing: bool = true,
|
||||
commonPrologue: seq[byte] = @[]): T =
|
||||
let pkBytes = privateKey.getPublicKey()
|
||||
commonPrologue: seq[byte] = @[],
|
||||
): T =
|
||||
let pkBytes = privateKey
|
||||
.getPublicKey()
|
||||
.expect("Expected valid Private Key")
|
||||
.getBytes().expect("Couldn't get public Key bytes")
|
||||
.getBytes()
|
||||
.expect("Couldn't get public Key bytes")
|
||||
|
||||
var noise = Noise(
|
||||
rng: rng,
|
||||
|
||||
@@ -14,13 +14,12 @@ import secure, ../../stream/connection
|
||||
|
||||
const PlainTextCodec* = "/plaintext/1.0.0"
|
||||
|
||||
type
|
||||
PlainText* = ref object of Secure
|
||||
type PlainText* = ref object of Secure
|
||||
|
||||
method init(p: PlainText) {.gcsafe.} =
|
||||
proc handle(conn: Connection, proto: string)
|
||||
{.async.} = discard
|
||||
proc handle(conn: Connection, proto: string) {.async.} =
|
||||
## plain text doesn't do anything
|
||||
discard
|
||||
|
||||
p.codec = PlainTextCodec
|
||||
p.handler = handle
|
||||
|
||||
@@ -13,20 +13,20 @@
|
||||
import std/[strformat]
|
||||
import stew/results
|
||||
import chronos, chronicles
|
||||
import ../protocol,
|
||||
../../stream/streamseq,
|
||||
../../stream/connection,
|
||||
../../multiaddress,
|
||||
../../peerinfo,
|
||||
../../errors
|
||||
import
|
||||
../protocol,
|
||||
../../stream/streamseq,
|
||||
../../stream/connection,
|
||||
../../multiaddress,
|
||||
../../peerinfo,
|
||||
../../errors
|
||||
|
||||
export protocol, results
|
||||
|
||||
logScope:
|
||||
topics = "libp2p secure"
|
||||
|
||||
const
|
||||
SecureConnTrackerName* = "SecureConn"
|
||||
const SecureConnTrackerName* = "SecureConn"
|
||||
|
||||
type
|
||||
Secure* = ref object of LPProtocol # base type for secure managers
|
||||
@@ -37,25 +37,31 @@ type
|
||||
|
||||
func shortLog*(conn: SecureConn): auto =
|
||||
try:
|
||||
if conn == nil: "SecureConn(nil)"
|
||||
else: &"{shortLog(conn.peerId)}:{conn.oid}"
|
||||
if conn == nil:
|
||||
"SecureConn(nil)"
|
||||
else:
|
||||
&"{shortLog(conn.peerId)}:{conn.oid}"
|
||||
except ValueError as exc:
|
||||
raiseAssert(exc.msg)
|
||||
|
||||
chronicles.formatIt(SecureConn): shortLog(it)
|
||||
chronicles.formatIt(SecureConn):
|
||||
shortLog(it)
|
||||
|
||||
proc new*(
|
||||
T: type SecureConn,
|
||||
conn: Connection,
|
||||
peerId: PeerId,
|
||||
observedAddr: Opt[MultiAddress],
|
||||
timeout: Duration = DefaultConnectionTimeout): T =
|
||||
result = T(stream: conn,
|
||||
peerId: peerId,
|
||||
observedAddr: observedAddr,
|
||||
closeEvent: conn.closeEvent,
|
||||
timeout: timeout,
|
||||
dir: conn.dir)
|
||||
timeout: Duration = DefaultConnectionTimeout,
|
||||
): T =
|
||||
result = T(
|
||||
stream: conn,
|
||||
peerId: peerId,
|
||||
observedAddr: observedAddr,
|
||||
closeEvent: conn.closeEvent,
|
||||
timeout: timeout,
|
||||
dir: conn.dir,
|
||||
)
|
||||
result.initStream()
|
||||
|
||||
method initStream*(s: SecureConn) =
|
||||
@@ -73,26 +79,23 @@ method closeImpl*(s: SecureConn) {.async: (raises: []).} =
|
||||
|
||||
method readMessage*(
|
||||
c: SecureConn
|
||||
): Future[seq[byte]] {.async: (raises: [
|
||||
CancelledError, LPStreamError], raw: true), base.} =
|
||||
): Future[seq[byte]] {.
|
||||
async: (raises: [CancelledError, LPStreamError], raw: true), base
|
||||
.} =
|
||||
raiseAssert("Not implemented!")
|
||||
|
||||
method getWrapped*(s: SecureConn): Connection = s.stream
|
||||
method getWrapped*(s: SecureConn): Connection =
|
||||
s.stream
|
||||
|
||||
method handshake*(
|
||||
s: Secure,
|
||||
conn: Connection,
|
||||
initiator: bool,
|
||||
peerId: Opt[PeerId]
|
||||
): Future[SecureConn] {.async: (raises: [
|
||||
CancelledError, LPStreamError], raw: true), base.} =
|
||||
s: Secure, conn: Connection, initiator: bool, peerId: Opt[PeerId]
|
||||
): Future[SecureConn] {.
|
||||
async: (raises: [CancelledError, LPStreamError], raw: true), base
|
||||
.} =
|
||||
raiseAssert("Not implemented!")
|
||||
|
||||
proc handleConn(
|
||||
s: Secure,
|
||||
conn: Connection,
|
||||
initiator: bool,
|
||||
peerId: Opt[PeerId]
|
||||
s: Secure, conn: Connection, initiator: bool, peerId: Opt[PeerId]
|
||||
): Future[Connection] {.async: (raises: [CancelledError, LPStreamError]).} =
|
||||
var sconn = await s.handshake(conn, initiator, peerId)
|
||||
# mark connection bottom level transport direction
|
||||
@@ -106,20 +109,26 @@ proc handleConn(
|
||||
let
|
||||
fut1 = conn.join()
|
||||
fut2 = sconn.join()
|
||||
try: # https://github.com/status-im/nim-chronos/issues/516
|
||||
try: # https://github.com/status-im/nim-chronos/issues/516
|
||||
discard await race(fut1, fut2)
|
||||
except ValueError: raiseAssert("Futures list is not empty")
|
||||
except ValueError:
|
||||
raiseAssert("Futures list is not empty")
|
||||
# at least one join() completed, cancel pending one, if any
|
||||
if not fut1.finished: await fut1.cancelAndWait()
|
||||
if not fut2.finished: await fut2.cancelAndWait()
|
||||
if not fut1.finished:
|
||||
await fut1.cancelAndWait()
|
||||
if not fut2.finished:
|
||||
await fut2.cancelAndWait()
|
||||
block:
|
||||
let
|
||||
fut1 = sconn.close()
|
||||
fut2 = conn.close()
|
||||
await allFutures(fut1, fut2)
|
||||
static: doAssert typeof(fut1).E is void # Cannot fail
|
||||
static: doAssert typeof(fut2).E is void # Cannot fail
|
||||
|
||||
static:
|
||||
doAssert typeof(fut1).E is void
|
||||
# Cannot fail
|
||||
static:
|
||||
doAssert typeof(fut2).E is void
|
||||
# Cannot fail
|
||||
except CancelledError:
|
||||
# This is top-level procedure which will work as separate task, so it
|
||||
# do not need to propagate CancelledError.
|
||||
@@ -152,17 +161,14 @@ method init*(s: Secure) =
|
||||
s.handler = handle
|
||||
|
||||
method secure*(
|
||||
s: Secure,
|
||||
conn: Connection,
|
||||
peerId: Opt[PeerId]
|
||||
): Future[Connection] {.async: (raises: [
|
||||
CancelledError, LPStreamError], raw: true), base.} =
|
||||
s: Secure, conn: Connection, peerId: Opt[PeerId]
|
||||
): Future[Connection] {.
|
||||
async: (raises: [CancelledError, LPStreamError], raw: true), base
|
||||
.} =
|
||||
s.handleConn(conn, conn.dir == Direction.Out, peerId)
|
||||
|
||||
method readOnce*(
|
||||
s: SecureConn,
|
||||
pbytes: pointer,
|
||||
nbytes: int
|
||||
s: SecureConn, pbytes: pointer, nbytes: int
|
||||
): Future[int] {.async: (raises: [CancelledError, LPStreamError]).} =
|
||||
doAssert(nbytes > 0, "nbytes must be positive integer")
|
||||
|
||||
@@ -182,9 +188,7 @@ method readOnce*(
|
||||
raise exc
|
||||
except LPStreamError as err:
|
||||
debug "Error while reading message from secure connection, closing.",
|
||||
error = err.name,
|
||||
message = err.msg,
|
||||
connection = s
|
||||
error = err.name, message = err.msg, connection = s
|
||||
await s.close()
|
||||
raise err
|
||||
|
||||
|
||||
Reference in New Issue
Block a user