While maintaining and developing the Go cryptography standard library, we often spend significantly more time on testing than on implementation. That’s good and an important part of how we achieve our excellent security track record.
Ideally, this would be especially true for the least safe parts of the library. However, testing assembly cores presents unique challenges, due to their constant-time nature. This has been a long-standing issue.
For Go 1.26, I am working on introducing a mutation testing framework for assembly, which will effectively act as enhanced code coverage. This will not improve tests by itself, but it will let us see what assembly code and data paths are not covered by our test suite, so we can improve it.
Cryptographic assembly is sort of my “origin story” as a Go maintainer. Back in 2017, a colleague at Cloudflare found a certificate that failed to validate with Go’s crypto/x509. The bug was a mishandled carry in the amd64 assembly implementation of P-256 modular subtraction. It had escaped all testing because that carry flag had a 1 in 2³² chance of being set when operating on random inputs.
Adam Langley commented that exploiting it was unlikely and “would be a cool paper”. Then Sean Devlin and I hid in a Starbucks in Paris for a whole day while the yellow jackets set fire to cop cars outside, and figured out how to turn it into a Hollywood-looking key recovery attack. That was fun, but it’s a different story.