Hacker Newsnew | past | comments | ask | show | jobs | submit | pizlonator's commentslogin

This article references the fact that security issues in crypto libs are memory safety issues, and I think this is meant to be a motivator for writing the crypto using SIMD intrinsics.

This misses two key issues.

1. If you want to really trust that your crypto code has no timing side channels, then you've gotta write it in assembly. Otherwise, you're at the compiler's whims to turn code that seems like it really should be constant-time into code that isn't. There's no thorough mechanism in compilers like LLVM to prevent this from happening.

2. If you look at the CVEs in OpenSSL, they are generally in the C code, not the assembly code. If you look at OpenSSL CVEs going back to the beginning of 2023, there is not a single vulnerability in Linux/X86_64 assembly. There are some in the Windows port of the X86_64 assembly (because Windows has a different calling conv and the perlasm mishandled it). There are some on other arches. But almost all of the CVEs are in C, not asm.

If you want to know a lot more about how I think about this, see https://fil-c.org/constant_time_crypto

I do think it's a good idea to have crypto libraries implemented in memory safe languages, and that may mean writing them in Rust. But the actual kernels that do the cryptographic computations that involve secrets should be written in asm for maximum security so that you can be sure that sidechannels are avoided and because empirically, the memory safety bugs are not in that asm code.


So there are more bugs in a more readable and understandable programming language (C) as opposed to asm? What gives? I am asking because intuition would say the opposite since asm is much more lower-level than C.

The core primitives written in assembly operate on fixed sized blocks of data; no allocations, no indexing arrays based on raw user controlled inputs, etc. Moreover, the nature of the algorithms--at least the parts written in assembly, e.g. block transforms--means any bugs tend to result in complete garbage and are caught early during development.

In OpenSSL, the C code is doing stuff that is hard to validate exhaustively like dealing with wire protocols, different sized buffers that have to be handled in special ways, dynamic memory allocation, etc

The assembly code is for the kernels themselves. Usually it’s a loop with easy to understand bounds, usually zero pointer chasing. Mostly math. Definitely no calls to malloc/free

So it’s not that assembly has an advantage over C. It’s that the kinds of things that get written in assembly also happen to:

- Be the sort of code where accidentally overflowing a buffer is unlikely because the indexing is the easy part. And there’s no interesting downcasting or allocation happening

- Be the sort of code where timing side channels are disastrous and the only way to know for sure you don’t have one is to look at the assembly


compiler optimization is a blackbox. shortcuts to crypto routines will allow side channel attacks

Crypto primitives tend to have very simple control flow (those that don’t are usually insecure) and even simpler data structures. You won’t find many branches beyond “is there another block?” in a typical block cipher or hash, for example.

Is it actually more readable and understandable (not to be confused with more familiar), though? It is hard to beat the understandability of the lowest level. Abstractions add unknowns. C's claim to fame was being a "portable assembler"; freeing developers from having to write the same program over and over and over for different systems.

Eh, I don't think you need to get that extreme.

A combination of careful use of a given high-level-language with expert awareness of compiler behavior, and the presence of tests that detect some of the nasty timing behaviors that get compiled in via static analysis of compiler IR or assembly on selected platforms will get you pretty far--not guaranteed perfect like handwritten asm would, but far enough that the advantages of not needing maintainers to be fluent in assembly past the point of maintaining those tests might outweigh the drawbacks.


Validating that your compiler didn’t introduce a timing side channel into a crypto algo is harder than validating that the crypto algo has no memory safety bugs.

I think this is true for crypto algos because they have low cyclomatic complexity and you’re going to think deeply about its behavior anyway as part of cryptanalysis, benchmarking, and other testing


I can't review assembly, agreed on better language part but we'd need tooling to help prove it's correctness of you want the asm path.

Well, is it that you can't or that you won't? All you need to do is learn it, you know? The full x86 ISA for one is quite nasty, but there's a useful subset, and other architectures are much nicer in general. Asm is as basic as it gets.

> Assembly programmers became C programmers became Python programmers.

Except that there are still a lot of assembly programmers.

And even more C/C++ programmers.

It's also likely that C/C++ programmers didn't become Python programmers but that people who wouldn't have otherwise been programmers became Python programmers.

> At the well-specified end, you have tasks where the inputs are clean, the desired output is clear, and success criteria are obvious: processing a standard form, writing code to a precise spec, translating a document, summarising a report. LLMs are excellent at this

Yeah

> At the ambiguous end, you have tasks where the context is messy, the right approach isn’t obvious, and success depends on knowledge that isn’t written down anywhere

Sounds like most programming

Almost all of the programming I've ever done.

> I’m arguing that the most likely outcome is something like “computers” or “the internet” rather than “the end of employment as we know it.”

Yeah


This is such an awesome project.

I had a lot of fun doing LFS plus a bit of BLFS and then I adapted it to my memory safe linux project https://fil-c.org/pizlix


nice work

That's not as bad as what a lot of nations have dealt with

Consider the turbulence that China experienced over the same 250 years, for example


Not symmetric at all.

There are countless bugs to fund.

If the offender runs these tools, then any bug they find becomes a cyberweapon.

If the defender runs these tools, they will not thwart the offender unless they find and fix all of the bugs.

Any vs all is not symmetric


LLMs effectively move us from A to B:

A) 1 cyber security employee, 1 determined attacker

B) 100 cyber security employees, 100 determined attackers

Which is better for defender?


Neither

How do bug bounties change the calculus? Assuming rational white hats who will report every bug which costs fewer LLM tokens than the bounty, on expectation.

They don’t.

For the calculus to change, anyone running an LLM to find bugs would have to be able to find all of the bugs that anyone else running an LLM could ever find.

That’s not going to happen.


Correct me if I'm wrong, but I think a better mental model would be something like: Take the union of all bugs found by all white hats, fix all of those, then check if any black hat has found sufficient unfixed bugs to construct an exploit chain?

The black hat has to find a handful of bugs. Sometimes one bug is enough.

How do you check this?

I meant in the sense that this algorithm will tell you if your software is vulnerable in the abstract. It's not a procedure you could actually follow.

Yeah Fil-C to the rescue

(I’m not trying to be facetious or troll or whatever. Stuff like this is what motivated me to do it.)


Fil-C is as compatible with C as different variants of C are with one another.

The porting effort is usually a less than if you were going from 32-bit to 64-bit for the first time. For some programs, you need zero changes.

In Qt I think the changes were stuff like:

- Use an intrinsic instead of inline assembly for cpuid.

- Change how a tagged pointer works (I.e. a 64-bit value used to store some integer bits and a pointer)

(Source: I’m the Fil-C guy and I watched the Qt porting happen from the sidelines.)


Let's say that somehow we end up in a world where capital is the only thing separating one set of humans from the other, and that separation is large, and the overwhelming majority of humans are in the underclass.

Such situations usually correct themselves violently.


> Such situations usually correct themselves violently.

Historically, they did because everyone's capacity for violence was equal.

What about now that the best the average person can do is a firearm against coordinated, organized military with armoured vehicles, advanced weaponry, drones, and sooner than later, full access to mass surveillance?

Also, how will a revolution happen once somebody trains a ML model end-to-end to identify desire for revolution from your search and chat history and communication with like-minded others?

Assuming the intent isn't prevented altogether through algorithmic feeds showing only content that makes it seem less attractive.


> Historically, they did because everyone's capacity for violence was equal.

This is so wildly ahistorical I'm immediately suspicious of your intentions.

The US alone offers plenty of counterexamples from the last ~50 years.


Yes, the ability to command a kingdom was relative to the number of people with force you could convince AND pay to be on your side vs the others. With automation, drones and AI, you no longer need any convincing just capital.

Do they in a world with humanoid robots that are harder better faster stronger?

Do you live in France? Because this is not universally true.

Brazil would like to have a word with you.

I find it surprising if Brazil meets this criteria:

> capital is the only thing separating one set of humans from the other, and that separation is large, and the overwhelming majority of humans are in the underclass.

Obviously, it's a matter of degree. You could reasonably argue that any capitalist society meets the criteria depending on your definition of "large", and depending on how you interpret the "capital is the only [sic] thing" part


You could also argue in the other direction: capital is never going to be the only thing separating one set of individuals from another, because we sure like to keep finding ways to label ourselves different: ethinicity, religion, political ideology, sex preferences, eye color...

Then again, maybe this is why Brazil finds itself in this steady state of economic inequality and endemic violence but without critical mass for a civil war: the same diversity that makes Brazilians apt at navigating conflicts is what makes us incapable at finding a common enemy and building an united front?


> Can people keep a good mental model of the repo without writing code?

Probably not.

In my experience working on large SW, you can't do interesting stuff without talking to the people who wrote the code that your interesting stuff will touch. And the reason you talk to those people is to get their visceral feel for how their code will be affected.


Ig that’s the case you really need to get some documentation in place. Otherwise after a few older people leave your code can never be changed properly anymore!

It's not binary. If you try hard enough, I bet you can make an argument that C is faster and you can make an argument that Rust is faster.

There is a set of programs that you can write in C and that are correct, that you cannot write in Rust without leaning into unsafe code. So if by "Rust" we mean "the safe subset of Rust", then this implies that there must be optimal algorithms that can be written in C but not in Rust.

On the other hand, Rust's ownership semantics are like rocket fuel for the compiler's understanding of aliasing. The inability of compilers to track aliasing precisely is a top inhibitor of load elimination in C compilers (so much so that C compiler writers lean into shady nonsense like strict aliasing, and even that doesn't buy very much precision). But a Rust compiler doesn't need to rely on shady imprecise nonsense. Therefore, there are surely algorithms that, if written in a straightforward way in both Rust and C, will be faster in Rust. I could even imagine there are algorithms for which it would be very unnatural to write the C code in a way that matches Rust's performance.

I'm purely speaking theoretically, I have no examples of either case. Just trying to provide my PL/compiler perspective


> There is a set of programs that you can write in C and that are correct, that you cannot write in Rust without leaning into unsafe code. So if by "Rust" we mean "the safe subset of Rust"

Well, unsafe rust is part of rust. So no, we don’t mean that.


If programs were primarily unsafe rust, no one would use the language. Unsafe rust is strictly more difficult to write than C in certain constructs because the complex invariants the rust language requires remain in unsafe, there’s just no compiler proof checking them being upheld.

Is argue that he’s right that generally it’s referring to safe subset and in practice people relax the conversation with a little unsafe being more ok. But as Steve points out it really depends on the definitions you choose.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: