apple / swift-crypto

Open-source implementation of a substantial portion of the API of Apple CryptoKit suitable for use on Linux platforms.
https://apple.github.io/swift-crypto
Apache License 2.0
1.48k stars 166 forks source link

Point validation #146

Closed frederikbosch closed 1 year ago

frederikbosch commented 1 year ago

Question Checklist

Question Subject

In the swift-paseto package we were discussing the initialization of P384.Signing.Publickey. While this is SwiftCrypto and not CryptoKit, I was hoping you could answer our question anyhow. I have no clue where to direct our question otherwise, and so I hope you do not mind me opening this question here.

couldn't find (and am still having trouble finding) documentation about whether or not Apple's CryptoKit does point validation when constructing the PublicKey type.

Question Description

So the question comes down to: do you know if the following line does any point validation? I think this is a valid question for this library and for CryptoKit.

let publicKey = P384.Signing.Publickey.init(pemRepresentation: publicKeyPem)
remko commented 1 year ago

I think I asked a related question yesterday specifically on CryptoKit, and filed a documentation request in response. I'm interested in the answer for Crypto too.

Lukasa commented 1 year ago

Thanks for filing this! @remko has kindly already received an answer on the developer forums, which is a better venue for this question, so I'll defer to that answer. To close the loop, swift-crypto's BoringSSL backend does point validation as well.

aidantwoods commented 1 year ago

To be clear, when does the point validation occur, and what does it include?

Mostly what I'm interested in is validating that points are actually on the curve when constructing a public key. I wrote a test to check that my library can catch this, because it seems that public key objects with points not on the curve will be created in CryptoKit.

To test if the point is on the curve I am exporting the raw representation of the key and the compressed representation of the key. I then use the compressed representation to construct a new key (which forces a point on the curve to be found). If the exported raw representation of this new key is not the same as the original, then a different point was recovered from compression (and so the original point was therefore not on the curve).

Lukasa commented 1 year ago

I can't speak to the behaviour of CryptoKit in this context I'm afraid, that's a topic for the developer forums. In the BoringSSL-backed implementation the call stack that does this validation is:

https://github.com/apple/swift-crypto/blob/a1b800581eaf9cf36f42da9ca32c152134db8f5a/Sources/Crypto/Key%20Agreement/ECDH.swift#L314-L316

using

https://github.com/apple/swift-crypto/blob/a1b800581eaf9cf36f42da9ca32c152134db8f5a/Sources/Crypto/Key%20Agreement/ECDH.swift#L21

calls

https://github.com/apple/swift-crypto/blob/a1b800581eaf9cf36f42da9ca32c152134db8f5a/Sources/Crypto/Keys/EC/BoringSSL/NISTCurvesKeys_boring.swift#L94-L96

calls

https://github.com/apple/swift-crypto/blob/a1b800581eaf9cf36f42da9ca32c152134db8f5a/Sources/Crypto/Keys/EC/BoringSSL/NISTCurvesKeys_boring.swift#L360-L376

calls

https://github.com/apple/swift-crypto/blob/a1b800581eaf9cf36f42da9ca32c152134db8f5a/Sources/Crypto/Keys/EC/BoringSSL/NISTCurvesKeys_boring.swift#L493-L503

calls

https://github.com/apple/swift-crypto/blob/a1b800581eaf9cf36f42da9ca32c152134db8f5a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/ec_key.c#L372-L395

calls

https://github.com/apple/swift-crypto/blob/a1b800581eaf9cf36f42da9ca32c152134db8f5a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/ec_key.c#L294-L330

which performs the point validation in the various functions it calls, specifically confirming that the point is not the point at infinity and that it is the point on the curve.

aidantwoods commented 1 year ago

Thanks!

It would seem that CryptoKit is behaving differently to that, which is a tad concerning 😬 Guess we'll need to chase that on the dev forums.