Skip to content
This repository has been archived by the owner on Dec 10, 2021. It is now read-only.

Make tls cert binary compat with the go implementation #6

Merged
merged 1 commit into from
Aug 2, 2021
Merged

Make tls cert binary compat with the go implementation #6

merged 1 commit into from
Aug 2, 2021

Conversation

kpp
Copy link
Contributor

@kpp kpp commented Jul 30, 2021

Make cert parsing and serialization compatible with the go implementation according to the specs.

I changed examples/smoke locally to test it, it worked (successfully connected).

Copy link
Member

@dvc94ch dvc94ch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, although can't really judge since the tls code was copied. @DemiMarie any objections?

Copy link

@DemiMarie DemiMarie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signing the SubjectPublicKeyInfo instead of the raw public key is fantastic, but the remaining changes should be reverted unless there is a good justification for them.

src/tls/verifier.rs Outdated Show resolved Hide resolved
src/tls/verifier.rs Outdated Show resolved Hide resolved
src/tls/verifier.rs Outdated Show resolved Hide resolved
src/tls/verifier.rs Outdated Show resolved Hide resolved
src/tls/verifier.rs Outdated Show resolved Hide resolved
};

let mut ext = rcgen::CustomExtension::from_oid_content(LIBP2P_OID, extension_content);
ext.set_criticality(true);
ext.set_criticality(false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From an X.509 perspective, the extension is critical, in that the whole certificate is useless to a peer that cannot interpret it. That said, if using false here improved interoperability, I would be okay with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to https://github.com/libp2p/specs/blob/master/tls/tls.md:

This extension MAY be marked critical.

I tried keep it, but the go implementation fails to connect:

go-libp2p-quic-transport/cmd$ go run client/main.go /ip4/127.0.0.1/udp/8383/quic 12D3KooWKnmstT37WmaiMRviHevoHZvWBrL7KsAXddcgrzqpp79i
2021/07/30 15:02:04 Dialing /ip4/127.0.0.1/udp/8383/quic
2021/07/30 15:02:04 failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.
2021/07/30 15:02:04 CRYPTO_ERROR (0x12a): certificate verification failed: x509: unhandled critical extension
exit status 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a bug in the Go implementation, and is most likely a result of them using the Go standard library to verify X.509 certificates. webpki has the same limitation, and in fact that limitation is why I wrote barebones-x509 in the first place.

Copy link
Contributor Author

@kpp kpp Jul 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right, here is the bug: https://github.com/libp2p/go-libp2p-tls/blob/master/crypto.go#L116.

However the extension MAY be marked as critical, so we don't have to.


Filed an issue: libp2p/go-libp2p-tls#87

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so unresolving this because it seems it's go-libp2p that is broken

src/tls/certificate.rs Show resolved Hide resolved
src/tls/certificate.rs Show resolved Hide resolved
@DemiMarie
Copy link

LGTM, although can't really judge since the tls code was copied. @DemiMarie any objections?

Thanks for the ping. In short: signing the SubjectPublicKeyInfo is a very good change from a security perspective, for which I am grateful. The libp2p extension really should be critical, though, and most of the ASN.1 handling changes are not necessary.

examples/server.rs Outdated Show resolved Hide resolved
src/tls/certificate.rs Show resolved Hide resolved
src/tls/certificate.rs Show resolved Hide resolved
};

let mut ext = rcgen::CustomExtension::from_oid_content(LIBP2P_OID, extension_content);
ext.set_criticality(true);
ext.set_criticality(false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a bug in the Go implementation, and is most likely a result of them using the Go standard library to verify X.509 certificates. webpki has the same limitation, and in fact that limitation is why I wrote barebones-x509 in the first place.

src/tls/verifier.rs Outdated Show resolved Hide resolved
src/tls/verifier.rs Outdated Show resolved Hide resolved
@dvc94ch
Copy link
Member

dvc94ch commented Jul 30, 2021

Isn't it lovely when pl doesn't follow it's own specs? I recall their mdns spec being incompatible with their go implementation which was incompatible with their js implementation. Not sure if it's fixed yet, this was about 5y ago. I've generally given up on trying to be compliant.

Copy link
Member

@dvc94ch dvc94ch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like merging this PR is blocked on go-libp2p getting it's act together?

};

let mut ext = rcgen::CustomExtension::from_oid_content(LIBP2P_OID, extension_content);
ext.set_criticality(true);
ext.set_criticality(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so unresolving this because it seems it's go-libp2p that is broken

src/tls/certificate.rs Show resolved Hide resolved
examples/server.rs Outdated Show resolved Hide resolved
@DemiMarie
Copy link

looks like merging this PR is blocked on go-libp2p getting it's act together?

Using SubjectPublicKeyInfo instead of the raw public key is an enormous security win, so we should certainly keep that change! The previous behavior was not exploitable as far as I can tell, but that does not mean an exploit did not exist. Signing SubjectPublicKeyInfo, on the other hand, is cryptographically sound.

Using OCTET STRING instead of BIT STRING saves 2 bytes of wire overhead without any drawbacks I can think of, and matches both the Go and JS implementations.

That leaves the certificate criticality. While the certificate should be marked as critical, this is only a MAY in the specification for a reason. Leaving it as non-critical is okay.

In short, the only change that go-libp2p really needs to make is to allow the libp2p extension to be critical, and even that should not block rust-libp2p from supporting TLS and QUIC. Allowing the libp2p extension to be critical required me to write an entire X.509 parsing library, so I understand why the go-libp2p developers made the choice they did.

@dvc94ch
Copy link
Member

dvc94ch commented Aug 2, 2021

Sounds reasonable. The example still needs to be improved or removed.

@kpp
Copy link
Contributor Author

kpp commented Aug 2, 2021

I was playing around with the QuicTransport but still could not make it work (none of the accept/dial futures actually resolve).
I will remove the example which I used to test your code.
Still there are a lot of questions left for me I would like to hear your advice to.

@dvc94ch
Copy link
Member

dvc94ch commented Aug 2, 2021

none of the accept/dial futures actually resolve

the tests pass right? so that can't be right. you're probably not polling something maybe the stream muxer?

Still there are a lot of questions left for me I would like to hear your advice to.

why don't you want to use the swarm?

@kpp
Copy link
Contributor Author

kpp commented Aug 2, 2021

I've just tested the go version running server/main.go and then client/main.go. They don't work either! I spent two weeks trying to figure out what's wrong with my code.
I am deleting the example... Done

Copy link
Member

@dvc94ch dvc94ch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@dvc94ch dvc94ch merged commit f2a8602 into ipfs-rust:master Aug 2, 2021
@kpp kpp deleted the go_compat branch August 2, 2021 13:07
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants