diff --git a/libp2p/protocols/secure/noise.nim b/libp2p/protocols/secure/noise.nim index a5a2b8c16..0a4032bce 100644 --- a/libp2p/protocols/secure/noise.nim +++ b/libp2p/protocols/secure/noise.nim @@ -142,7 +142,7 @@ proc encrypt( inc state.n if state.n > NonceMax: - raise newException(NoiseNonceMaxError, "Noise max nonce value reached") + raise (ref NoiseNonceMaxError)(msg: "Noise max nonce value reached") proc encryptWithAd(state: var CipherState, ad, data: openArray[byte]): seq[byte] {.raises: [NoiseNonceMaxError].} = @@ -168,10 +168,11 @@ proc decryptWithAd(state: var CipherState, ad, data: openArray[byte]): seq[byte] trace "decryptWithAd", tagIn = tagIn.shortLog, tagOut = tagOut.shortLog, nonce = state.n if tagIn != tagOut: debug "decryptWithAd failed", data = shortLog(data) - raise newException(NoiseDecryptTagError, "decryptWithAd failed tag authentication.") + raise (ref NoiseDecryptTagError)(msg: + "decryptWithAd failed tag authentication.") inc state.n if state.n > NonceMax: - raise newException(NoiseNonceMaxError, "Noise max nonce value reached") + raise (ref NoiseNonceMaxError)(msg: "Noise max nonce value reached") # Symmetricstate @@ -181,8 +182,7 @@ proc init(_: type[SymmetricState]): SymmetricState = result.cs = CipherState(k: EmptyKey) proc mixKey(ss: var SymmetricState, ikm: ChaChaPolyKey) = - var - temp_keys: array[2, ChaChaPolyKey] + var temp_keys: array[2, ChaChaPolyKey] sha256.hkdf(ss.ck, ikm, [], temp_keys) ss.ck = temp_keys[0] ss.cs = CipherState(k: temp_keys[1]) @@ -198,8 +198,7 @@ proc mixHash(ss: var SymmetricState, data: openArray[byte]) = # We might use this for other handshake patterns/tokens proc mixKeyAndHash(ss: var SymmetricState, ikm: openArray[byte]) {.used.} = - var - temp_keys: array[3, ChaChaPolyKey] + var temp_keys: array[3, ChaChaPolyKey] sha256.hkdf(ss.ck, ikm, [], temp_keys) ss.ck = temp_keys[0] ss.mixHash(temp_keys[1]) @@ -234,7 +233,8 @@ proc init(_: type[HandshakeState]): HandshakeState = 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). + # Sets e (which must be empty) to GENERATE_KEYPAIR(). + # Appends e.public_key to the buffer. Calls MixHash(e.public_key). hs.e = genKeyPair(p.rng[]) msg.add hs.e.publicKey hs.ss.mixHash(hs.e.publicKey) @@ -275,26 +275,28 @@ template read_e: untyped = trace "noise read e", size = msg.len if msg.len < Curve25519Key.len: - raise newException(NoiseHandshakeError, "Noise E, expected more data") + raise (ref NoiseHandshakeError)(msg: "Noise E, expected more data") - # Sets re (which must be empty) to the next DHLEN bytes from the message. Calls MixHash(re.public_key). + # 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) msg.consume(Curve25519Key.len) hs.ss.mixHash(hs.re) 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 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 newException(NoiseHandshakeError, "Noise S, expected more data") + raise (ref NoiseHandshakeError)(msg: "Noise S, expected more data") Curve25519Key.len + ChaChaPolyTag.len else: if msg.len < Curve25519Key.len: - raise newException(NoiseHandshakeError, "Noise S, expected more data") + raise (ref NoiseHandshakeError)(msg: "Noise S, expected more data") Curve25519Key.len hs.rs[0..Curve25519Key.high] = hs.ss.decryptAndHash(msg.toOpenArray(0, rsLen - 1)) @@ -315,7 +317,11 @@ proc readFrame( await sconn.readExactly(addr buffer[0], buffer.len) return buffer -proc writeFrame(sconn: Connection, buf: openArray[byte]): Future[void] = +proc writeFrame( + sconn: Connection, + buf: openArray[byte] +): Future[void] {.async: (raises: [ + CancelledError, LPStreamError], raw: true).} = doAssert buf.len <= uint16.high.int var lesize = buf.len.uint16 @@ -326,13 +332,24 @@ proc writeFrame(sconn: Connection, buf: openArray[byte]): Future[void] = outbuf &= buf sconn.write(outbuf) -proc receiveHSMessage(sconn: Connection): Future[seq[byte]] = readFrame(sconn) -proc sendHSMessage(sconn: Connection, buf: openArray[byte]): Future[void] = +proc receiveHSMessage( + sconn: Connection +): 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).} = writeFrame(sconn, buf) proc handshakeXXOutbound( p: Noise, conn: Connection, - p2pSecret: seq[byte]): Future[HandshakeResult] {.async.} = + p2pSecret: seq[byte] +): Future[HandshakeResult] {.async: (raises: [ + CancelledError, LPStreamError]).} = const initiator = true var hs = HandshakeState.init() @@ -374,13 +391,16 @@ 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.} = + p2pSecret: seq[byte] +): Future[HandshakeResult] {.async: (raises: [ + CancelledError, LPStreamError]).} = const initiator = false var @@ -424,7 +444,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) @@ -486,7 +507,8 @@ method write*( try: encryptFrame( sconn, - cipherFrames.toOpenArray(woffset, woffset + chunkSize + FramingSize - 1), + cipherFrames.toOpenArray( + woffset, woffset + chunkSize + FramingSize - 1), message.toOpenArray(offset, offset + chunkSize - 1)) except NoiseNonceMaxError as exc: debug "Noise nonce exceeded" @@ -509,21 +531,28 @@ method write*( # sequencing issues sconn.stream.write(cipherFrames) -method handshake*(p: Noise, conn: Connection, initiator: bool, peerId: Opt[PeerId]): Future[SecureConn] {.async.} = +method handshake*( + p: Noise, + conn: Connection, + initiator: bool, + peerId: Opt[PeerId] +): Future[SecureConn] {.async: (raises: [CancelledError, LPStreamError]).} = trace "Starting Noise handshake", conn, initiator let timeout = conn.timeout 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).tryGet() + let signedPayload = p.localPrivateKey.sign( + PayloadString & p.noiseKeys.publicKey.getBytes) + if signedPayload.isErr(): + raise (ref NoiseHandshakeError)(msg: + "Failed to sign public key: " & $signedPayload.error()) var libp2pProof = initProtoBuffer() libp2pProof.write(1, p.localPublicKey) - libp2pProof.write(2, signedPayload.getBytes()) + libp2pProof.write(2, signedPayload.get().getBytes()) # data field also there but not used! libp2pProof.finish() @@ -542,29 +571,38 @@ method handshake*(p: Noise, conn: Connection, initiator: bool, peerId: Opt[PeerI remoteSigBytes: seq[byte] if not remoteProof.getField(1, remotePubKeyBytes).valueOr(false): - raise newException(NoiseHandshakeError, "Failed to deserialize remote public key bytes. (initiator: " & $initiator & ")") + raise (ref NoiseHandshakeError)(msg: + "Failed to deserialize remote public key bytes. (initiator: " & + $initiator & ")") if not remoteProof.getField(2, remoteSigBytes).valueOr(false): - raise newException(NoiseHandshakeError, "Failed to deserialize remote signature bytes. (initiator: " & $initiator & ")") + raise (ref NoiseHandshakeError)(msg: + "Failed to deserialize remote signature bytes. (initiator: " & + $initiator & ")") if not remotePubKey.init(remotePubKeyBytes): - raise newException(NoiseHandshakeError, "Failed to decode remote public key. (initiator: " & $initiator & ")") + raise (ref NoiseHandshakeError)(msg: + "Failed to decode remote public key. (initiator: " & $initiator & ")") if not remoteSig.init(remoteSigBytes): - raise newException(NoiseHandshakeError, "Failed to decode remote signature. (initiator: " & $initiator & ")") + raise (ref NoiseHandshakeError)(msg: + "Failed to decode remote signature. (initiator: " & $initiator & ")") let verifyPayload = PayloadString & handshakeRes.rs.getBytes if not remoteSig.verify(verifyPayload, remotePubKey): - raise newException(NoiseHandshakeError, "Noise handshake signature verify failed.") + raise (ref NoiseHandshakeError)(msg: + "Noise handshake signature verify failed.") else: trace "Remote signature verified", conn let pid = PeerId.init(remotePubKey).valueOr: - raise newException(NoiseHandshakeError, "Invalid remote peer id: " & $error) + raise (ref NoiseHandshakeError)(msg: + "Invalid remote peer id: " & $error) trace "Remote peer id", pid = $pid peerId.withValue(targetPid): if not targetPid.validate(): - raise newException(NoiseHandshakeError, "Failed to validate expected peerId.") + raise (ref NoiseHandshakeError)(msg: + "Failed to validate expected peerId.") if pid != targetPid: var @@ -574,7 +612,8 @@ method handshake*(p: Noise, conn: Connection, initiator: bool, peerId: Opt[PeerI initiator, dealt_peer = conn, dealt_key = $failedKey, received_peer = $pid, received_key = $remotePubKey - raise newException(NoiseHandshakeError, "Noise handshake, peer id don't match! " & $pid & " != " & $targetPid) + 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) diff --git a/libp2p/protocols/secure/secio.nim b/libp2p/protocols/secure/secio.nim index 032fd0df5..4b0ea71f0 100644 --- a/libp2p/protocols/secure/secio.nim +++ b/libp2p/protocols/secure/secio.nim @@ -107,11 +107,11 @@ proc update(mac: var SecureMac, data: openArray[byte]) = proc sizeDigest(mac: SecureMac): int {.inline.} = case mac.kind of SecureMacType.Sha256: - result = int(mac.ctxsha256.sizeDigest()) + int(mac.ctxsha256.sizeDigest()) of SecureMacType.Sha512: - result = int(mac.ctxsha512.sizeDigest()) + int(mac.ctxsha512.sizeDigest()) of SecureMacType.Sha1: - result = int(mac.ctxsha1.sizeDigest()) + int(mac.ctxsha1.sizeDigest()) proc finish(mac: var SecureMac, data: var openArray[byte]) = case mac.kind @@ -188,7 +188,7 @@ proc macCheckAndDecode(sconn: SecioConn, data: var seq[byte]): bool = sconn.readerCoder.decrypt(data.toOpenArray(0, mark - 1), data.toOpenArray(0, mark - 1)) data.setLen(mark) - result = true + true proc readRawMessage( conn: Connection @@ -222,7 +222,7 @@ method readMessage*( stream_oid = $sconn.stream.oid var buf = await sconn.stream.readRawMessage() if sconn.macCheckAndDecode(buf): - result = buf + buf else: trace "Message MAC verification failed", buf = buf.shortLog raise (ref SecioError)(msg: "message failed MAC verification") @@ -239,15 +239,16 @@ method write*( offset = 0 while left > 0: let - chunkSize = if left > SecioMaxMessageSize - 64: SecioMaxMessageSize - 64 else: left + chunkSize = min(left, SecioMaxMessageSize - 64) macsize = sconn.writerMac.sizeDigest() length = chunkSize + macsize var msg = newSeq[byte](chunkSize + 4 + macsize) msg[0..<4] = uint32(length).toBytesBE() - sconn.writerCoder.encrypt(message.toOpenArray(offset, offset + chunkSize - 1), - msg.toOpenArray(4, 4 + chunkSize - 1)) + sconn.writerCoder.encrypt( + message.toOpenArray(offset, offset + chunkSize - 1), + msg.toOpenArray(4, 4 + chunkSize - 1)) left = left - chunkSize offset = offset + chunkSize let mo = 4 + chunkSize @@ -259,17 +260,16 @@ method write*( await sconn.stream.write(msg) sconn.activity = true -proc newSecioConn(conn: Connection, - hash: string, - cipher: string, - secrets: Secret, - order: int, - remotePubKey: PublicKey): SecioConn - {.raises: [LPError].} = +proc newSecioConn( + conn: Connection, + hash: string, + cipher: string, + secrets: Secret, + order: int, + remotePubKey: PublicKey): SecioConn = ## Create new secure stream/lpstream, using specified hash algorithm ``hash``, ## cipher algorithm ``cipher``, stretched keys ``secrets`` and order ## ``order``. - result = SecioConn.new(conn, conn.peerId, conn.observedAddr) let i0 = if order < 0: 1 else: 0 @@ -288,108 +288,136 @@ proc newSecioConn(conn: Connection, result.readerCoder.init(cipher, secrets.keyOpenArray(i1), secrets.ivOpenArray(i1)) -proc transactMessage(conn: Connection, - msg: seq[byte]): Future[seq[byte]] {.async.} = +proc transactMessage( + conn: Connection, + msg: seq[byte] +): Future[seq[byte]] {.async: (raises: [CancelledError, LPStreamError]).} = trace "Sending message", message = msg.shortLog, length = len(msg) await conn.write(msg) - return await conn.readRawMessage() + await conn.readRawMessage() -method handshake*(s: Secio, conn: Connection, initiator: bool, peerId: Opt[PeerId]): Future[SecureConn] {.async.} = - var - localNonce: array[SecioNonceSize, byte] - remoteNonce: seq[byte] - remoteBytesPubkey: seq[byte] - remoteEBytesPubkey: seq[byte] - remoteEBytesSig: seq[byte] - remotePubkey: PublicKey - remoteEPubkey: ecnist.EcPublicKey - remoteESignature: Signature - remoteExchanges: string - remoteCiphers: string - remoteHashes: string - remotePeerId: PeerId - localPeerId: PeerId - localBytesPubkey = s.localPublicKey.getBytes().tryGet() +method handshake*( + s: Secio, + conn: Connection, + initiator: bool, + peerId: Opt[PeerId] +): Future[SecureConn] {.async: (raises: [CancelledError, LPStreamError]).} = + let localBytesPubkey = s.localPublicKey.getBytes() + if localBytesPubkey.isErr(): + raise (ref SecioError)(msg: + "Failed to get local public key bytes: " & $localBytesPubkey.error()) + let localPeerId = PeerId.init(s.localPublicKey) + if localPeerId.isErr(): + raise (ref SecioError)(msg: + "Failed to initialize local peer ID: " & $localPeerId.error()) + + var localNonce: array[SecioNonceSize, byte] hmacDrbgGenerate(s.rng[], localNonce) - var request = createProposal(localNonce, - localBytesPubkey, - SecioExchanges, - SecioCiphers, - SecioHashes) - - localPeerId = PeerId.init(s.localPublicKey).tryGet() + let request = createProposal( + localNonce, localBytesPubkey.get(), + SecioExchanges, SecioCiphers, SecioHashes) trace "Local proposal", schemes = SecioExchanges, ciphers = SecioCiphers, hashes = SecioHashes, - pubkey = localBytesPubkey.shortLog, - peer = localPeerId - - var answer = await transactMessage(conn, request) + pubkey = localBytesPubkey.get().shortLog, + peer = localPeerId.get() + let answer = await transactMessage(conn, request) if len(answer) == 0: trace "Proposal exchange failed", conn raise (ref SecioError)(msg: "Proposal exchange failed") - if not decodeProposal(answer, remoteNonce, remoteBytesPubkey, remoteExchanges, - remoteCiphers, remoteHashes): + var + remoteNonce: seq[byte] + remoteBytesPubkey: seq[byte] + remoteExchanges: string + remoteCiphers: string + remoteHashes: string + if not decodeProposal( + answer, remoteNonce, remoteBytesPubkey, remoteExchanges, + remoteCiphers, remoteHashes): trace "Remote proposal decoding failed", conn raise (ref SecioError)(msg: "Remote proposal decoding failed") + var remotePubkey: PublicKey if not remotePubkey.init(remoteBytesPubkey): trace "Remote public key incorrect or corrupted", pubkey = remoteBytesPubkey.shortLog raise (ref SecioError)(msg: "Remote public key incorrect or corrupted") - remotePeerId = PeerId.init(remotePubkey).tryGet() + let remotePeerId = PeerId.init(remotePubkey) + if remotePeerId.isErr(): + raise (ref SecioError)(msg: + "Failed to initialize remote peer ID: " & $remotePeerId.error()) peerId.withValue(targetPid): if not targetPid.validate(): - raise newException(SecioError, "Failed to validate expected peerId.") + raise (ref SecioError)(msg: "Failed to validate expected peerId.") - if remotePeerId != targetPid: - raise newException(SecioError, "Peer ids don't match!") - conn.peerId = remotePeerId - let order = getOrder(remoteBytesPubkey, localNonce, localBytesPubkey, - remoteNonce).tryGet() + if remotePeerId.get() != targetPid: + raise (ref SecioError)(msg: "Peer ids don't match!") + conn.peerId = remotePeerId.get() + let order = getOrder( + remoteBytesPubkey, localNonce, localBytesPubkey.get(), remoteNonce) + if order.isErr(): + raise (ref SecioError)(msg: "Failed to get order: " & $order.error()) trace "Remote proposal", schemes = remoteExchanges, ciphers = remoteCiphers, hashes = remoteHashes, - pubkey = remoteBytesPubkey.shortLog, order = order, - peer = remotePeerId + pubkey = remoteBytesPubkey.shortLog, + order = order.get(), + peer = remotePeerId.get() - let scheme = selectBest(order, SecioExchanges, remoteExchanges) - let cipher = selectBest(order, SecioCiphers, remoteCiphers) - let hash = selectBest(order, SecioHashes, remoteHashes) + let + scheme = selectBest(order.get(), SecioExchanges, remoteExchanges) + cipher = selectBest(order.get(), SecioCiphers, remoteCiphers) + hash = selectBest(order.get(), SecioHashes, remoteHashes) if len(scheme) == 0 or len(cipher) == 0 or len(hash) == 0: - trace "No algorithms in common", peer = remotePeerId + trace "No algorithms in common", peer = remotePeerId.get() raise (ref SecioError)(msg: "No algorithms in common") trace "Encryption scheme selected", scheme = scheme, cipher = cipher, hash = hash - var ekeypair = ephemeral(scheme, s.rng[]).tryGet() + let ekeypair = ephemeral(scheme, s.rng[]) + if ekeypair.isErr(): + raise (ref SecioError)(msg: + "Failed to create ephemeral keypair: " & $ekeypair.error()) # We need EC public key in raw binary form - var epubkey = ekeypair.pubkey.getRawBytes().tryGet() - var localCorpus = request[4..^1] & answer & epubkey - var signature = s.localPrivateKey.sign(localCorpus).tryGet() + let epubkey = ekeypair.get().pubkey.getRawBytes() + if epubkey.isErr(): + raise (ref SecioError)(msg: + "Failed to get ephemeral key bytes: " & $epubkey.error()) + let + localCorpus = request[4..^1] & answer & epubkey.get() + signature = s.localPrivateKey.sign(localCorpus) + if signature.isErr(): + raise (ref SecioError)(msg: + "Failed to sign local corpus: " & $signature.error()) - var localExchange = createExchange(epubkey, signature.getBytes()) - var remoteExchange = await transactMessage(conn, localExchange) + let + localExchange = createExchange(epubkey.get(), signature.get().getBytes()) + remoteExchange = await transactMessage(conn, localExchange) if len(remoteExchange) == 0: trace "Corpus exchange failed", conn raise (ref SecioError)(msg: "Corpus exchange failed") + var + remoteEBytesPubkey: seq[byte] + remoteEBytesSig: seq[byte] if not decodeExchange(remoteExchange, remoteEBytesPubkey, remoteEBytesSig): trace "Remote exchange decoding failed", conn raise (ref SecioError)(msg: "Remote exchange decoding failed") + var remoteESignature: Signature if not remoteESignature.init(remoteEBytesSig): - trace "Remote signature incorrect or corrupted", signature = remoteEBytesSig.shortLog + trace "Remote signature incorrect or corrupted", + signature = remoteEBytesSig.shortLog raise (ref SecioError)(msg: "Remote signature incorrect or corrupted") - var remoteCorpus = answer & request[4..^1] & remoteEBytesPubkey + let remoteCorpus = answer & request[4..^1] & remoteEBytesPubkey if not remoteESignature.verify(remoteCorpus, remotePubkey): trace "Signature verification failed", scheme = $remotePubkey.scheme, signature = $remoteESignature, @@ -399,30 +427,34 @@ method handshake*(s: Secio, conn: Connection, initiator: bool, peerId: Opt[PeerI trace "Signature verified", scheme = remotePubkey.scheme + var remoteEPubkey: ecnist.EcPublicKey if not remoteEPubkey.initRaw(remoteEBytesPubkey): trace "Remote ephemeral public key incorrect or corrupted", pubkey = toHex(remoteEBytesPubkey) - raise (ref SecioError)(msg: "Remote ephemeral public key incorrect or corrupted") + raise (ref SecioError)(msg: + "Remote ephemeral public key incorrect or corrupted") - var secret = getSecret(remoteEPubkey, ekeypair.seckey) + let secret = getSecret(remoteEPubkey, ekeypair.get().seckey) if len(secret) == 0: trace "Shared secret could not be created" raise (ref SecioError)(msg: "Shared secret could not be created") trace "Shared secret calculated", secret = secret.shortLog - var keys = stretchKeys(cipher, hash, secret) + let keys = stretchKeys(cipher, hash, secret) trace "Authenticated encryption parameters", - iv0 = toHex(keys.ivOpenArray(0)), key0 = keys.keyOpenArray(0).shortLog, + iv0 = toHex(keys.ivOpenArray(0)), + key0 = keys.keyOpenArray(0).shortLog, mac0 = keys.macOpenArray(0).shortLog, - iv1 = keys.ivOpenArray(1).shortLog, key1 = keys.keyOpenArray(1).shortLog, + iv1 = keys.ivOpenArray(1).shortLog, + key1 = keys.keyOpenArray(1).shortLog, mac1 = keys.macOpenArray(1).shortLog # Perform Nonce exchange over encrypted channel. - var secioConn = newSecioConn(conn, hash, cipher, keys, order, remotePubkey) - result = secioConn + let secioConn = newSecioConn( + conn, hash, cipher, keys, order.get(), remotePubkey) await secioConn.write(remoteNonce) var res = await secioConn.readMessage() @@ -432,6 +464,7 @@ method handshake*(s: Secio, conn: Connection, initiator: bool, peerId: Opt[PeerI raise (ref SecioError)(msg: "Nonce verification failed") else: trace "Secure handshake succeeded" + secioConn method init(s: Secio) {.gcsafe.} = procCall Secure(s).init() diff --git a/libp2p/protocols/secure/secure.nim b/libp2p/protocols/secure/secure.nim index b1270216b..18f74aec6 100644 --- a/libp2p/protocols/secure/secure.nim +++ b/libp2p/protocols/secure/secure.nim @@ -79,16 +79,21 @@ method readMessage*( method getWrapped*(s: SecureConn): Connection = s.stream -method handshake*(s: Secure, - conn: Connection, - initiator: bool, - peerId: Opt[PeerId]): Future[SecureConn] {.async, base.} = +method handshake*( + 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]): Future[Connection] {.async.} = +proc handleConn( + 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 # this is the safest place to do this @@ -112,14 +117,8 @@ proc handleConn(s: Secure, fut1 = sconn.close() fut2 = conn.close() await allFutures(fut1, fut2) - if fut1.failed: - let err = fut1.error() - if not (err of CancelledError): - debug "error cleaning up secure connection", err = err.msg, sconn - if fut2.failed: - let err = fut2.error() - if not (err of CancelledError): - debug "error cleaning up secure connection", err = err.msg, sconn + 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 @@ -130,7 +129,7 @@ proc handleConn(s: Secure, # All the errors are handled inside `cleanup()` procedure. asyncSpawn cleanup() - return sconn + sconn method init*(s: Secure) = procCall LPProtocol(s).init() @@ -146,16 +145,18 @@ method init*(s: Secure) = warn "securing connection canceled", conn await conn.close() raise exc - except CatchableError as exc: + except LPStreamError as exc: warn "securing connection failed", err = exc.msg, conn await conn.close() s.handler = handle -method secure*(s: Secure, - conn: Connection, - peerId: Opt[PeerId]): - Future[Connection] {.base.} = +method secure*( + 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*(