Outstanding! Not only are the slightly mysterious authors of this project
not inventing their own crypto, they rely on djb's[0] much acclaimed
NaCL/TweetNaCl. The codebase is accordingly small:
$ wc -l source/*/*c | tail -n1
11308 total
$ wc -l source/crypto/*c | tail -n1
1293 total
The first line suggests a measure of total code ballast, whereas the
second incantation might hint at the amount of core crypto code. The latter
might be a good starting point for any auditing endeavours.
Incidentally, I am impressed by the spirit of organisation that the source
tree permeates. Both crypto/ and tinyssh/ source trees sport corresponding
-test directories and a debian/ tree has already been added.
Initially, I felt irritation by the consistent lack of documentation (no
README, no AUTHORS, almost no comments, it seems). Browsing the source,
however, I grow convinced that this from a conviction that out-dated or
redundant documentation is the greater evil.
this is pretty slick. i'm glad people are making more modular implementations of the programs that i depend upon in addition to creating fancy new programs that i might find useful.
for comparison, the openbsd version of openssh's sshd compiles just under 20k lines, and the openbsd version is supposed to be much smaller than the "portable" version of openssh.
The answer seems to me quite simple: because they have a different coding
style. Just as no one is bound to K&R or the GNU style, nothing suggests that
crypto code needs to follow Linux kernel conventions.
Value consistency above everything.
Honestly, I am not convinced that the peculiar if-style isn't actually helping
readability and refactoring. Note, that a Apple-style "goto break" bug might
be harder to construct, when your one-line if's look like this:
some_code;
if (something) die(message);
other_code;
Now the surrounding indentation does not suggest that there's an extendable
block where there in fact isn't, as with Kernel style:
some_code;
if (something)
die(message);
other_code;
To be perfectly honest, the authors' style reminds me a bit of my younger
self's style: keep logically connected pieces of code tightly together.
You (presumably) and I have beaten ourselves into submission to the Linux
style; the authors' haven't.
On a side note: your second example even seems to suggest that the authors
made some effort at additional readability by refraining from using the
ternary operator construct.
"You (presumably) and I have beaten ourselves into submission to the Linux style; the authors' haven't."
An awakening!
Is it really so terrible to have things compile quickly and without the usual ./configure nonsense? It seems there are an infinite number of ways an author can organise her project using ./configure; for every one I have to spend time figuring out what they have done.
One of my favourite aspects of djb's build approach (which is what is being used here) is that it's easier (than with the popular build systems) to change compiler and linker options and make static binaries: in most cases, simple edit the conf-* files. Thankfully, authors who use djb's approach usually do not vary much from the model. This means less time spent figuring out how things are organised.
I like (portable) open source software that compiles quickly and cleanly.
djb has continued to deliver on this point.
Nice to see someone discovering this build system for the first time.
I'm just curious, where does the parent post mention anything about the build system? The "Linux style" referred to there seems to be the Linux code style, not "configure".
Who said it did? Consider that I was commenting in a general sense.
djb's work, whether it's coding style or build system or something else, tends to differ from what is "popular".
The parent's comment is along the lines of: what is unfamiliar can appear more difficult, but after the adjustment it may actually appear easier than the prior alternative.
If you view the parent's comment in this light, then you will see that both the Linux kernel coding style and the GNU build system are very familiar for lots of folks.
If you are migrating to using tinyssh and other software that follow's djb's style for the first time, then you will no doubt have to "get used to it" and you might even perceive it as being difficult.
To be crystal clear, I'm not singling out the Linux kernel or the GNU build system. The GNU build system is but one example; the Linux kernel coding style is another.
I could make a lengthy list of "familiar", popular approaches that I could argue are inferior to djb's approach to the same task.
It's just my opinion. If you disagree, feel free to state your own opinion.
There is nothing particularly unauditable about that style.
To me, more code that you can get on a single screen/buffer, the better. My complaint is more about putting braces on a separate line all by themselves.
It's an SSH server. If dealing with simple cases of more than one statement on the same line is the worst bit of auditing it, it is indeed an easily auditable SSH server.
(Not that I would have written either line that way, mind you. But there's no real challenge understanding them.)
Curious as to whether something like this would be good for embedded work, as I'm working on a "modern" HP 200LX[0] running RetroBSD[1] possibly, all off a PIC micro controller (!) and want to work out how to get some form of SSH into it. Will be interesting to attempt to port it regardless of what happens though!
Quick check shows that both compile to about 220K without any tuning on x86_64. While I wouldn't use that figure as serious comparison, it shows that they are in the same ballpark in size.
Right now, you're suggesting it be downloaded via HTTP, which isn't exactly the best way to get my secure daemons. Any chance you could move that to HTTPS?
Semi-related: any chance you'll be making a repo available in some form? (I'm preferential to GitHub, but really anything that lets us follow source changes and open bug reports would rock)
I would love to see an audit of this by some 3rd party entity.
Glad to see folks working to build new tools from such solid building blocks!
The usual problem with DJB's implementations is not that they're incorrect or slow or insecure -- far from it! -- but that they're awkward to integrate with the rest of the world, may require weird build configurations, and are hard for anybody else to modify. Well, TweetNaCl is really easy to integrate with the rest of the world, since it's just a single portable .c file, and the speed is surprisingly good, and its functionality and API are stable enough that you probably don't need to modify it.
So, I don't see the problem here. If these guys had tried to cobble together a replacement for NaCl out of pieces like the curve25519-donna code, that would be a problem, because there's more potential to screw that up.
I see 3 alternatives: use the original NaCl, use the unofficial fork libsodium, or use TweetNaCl.
The latter shares the same authors as the original NaCl, with the advantage of being much smaller.
I don't like the fact that TinySSH modified TweetNaCl, and
added back MD5:
/*
Based on tweetnacl 20140427 (http://tweetnacl.cr.yp.to software.html)
- updated int/uint types to crypto_int/crypto_uint
- added crypto_stream_chacha20
- added crypto_hash_sha256
- added crypto_hash_md5
*/
I mean they use TweetNaCl because it has "state-of-the-art crypto", but then they add back MD5. Something is wrong here ...
It appears to be used only in tinysshd-printkey to print the key's fingerprint.
The fingerprint is 47 characters when printed, the key itself is 64. Since the key is so short does the fingerprint still server a useful purpose, or would it be enough to print only the key?
What do they leave to be desired? Style is a personal preference, of course - but merit? Every single djb implementation I've seen (a lot of them) is fast, efficient, secure, and clear, once you get his style.
Mostly his disregard for packaging conventions and unwillingness to acomodate them. The code is usually A grade, but the odd use of the filesystem, runtime configs, daemons etc. means it will never get into any mainstream distro without heavy patching.
There's a reason why libsodium's tag line is "P(ortable|ackageable) NaCl-based crypto library".
The word of distros/packagers isn't gospel, but it counts for a lot, considering that (for better or worse) most people won't even think about using something not available as a package.
I've been doing "apt-get install daemontools daemontools-run" since forever on Ubuntu; it might take a little longer to get into the repositories, but it does get into mainstream distros with almost no patching -- comparable, IIRC, to packages of similar size and complexity that do not have an upstream debian packaging.
No it isn't. The only guarantees you have about the size of long are that it is at least as large as (greater than or equal) a normal int. And a normal int is greater than or equal as big as a short.
C99 standard [1], §5.2.4.2.1 says otherwise. Int must acommodate at least 16 bits, long 32 bits, and long long 64 bits. C89 [2], §2.2.4.2 says the same thing but omits long long, so tweetnacl's u64 may not exist (this was the case with MSVC not too long ago).
Additionally, char is required to be at least 8 bits by the C standard, but tweetnacl assumes exactly 8. Some oddball architectures have larger character types, but POSIX mandates 8.
This code is attempting to be portable to C89, or why not just use C99's stdint.h? I don't believe your statement "C89 says the same thing," do you have a source to point to?
Do you have the section number in the latest freely available C99 working draft? The "Types" section (which 6.something in the draft) simply says what I said earlier about scalar rank. And 5.4.4.2.1 doesn't seem to exist in the draft.
Sorry, I mistyped the section number. Updated the parent comment with corrections and links.
I assume the intent of tweetnacl is to be C89-compatible, but due to the long long (and char, although that one's pretty pedantic) issue there's little guarantee of success.
Yes, TweetNaCl is. TweetNaCl's goal is to be auditable, not to be portable.
On the other hand, TinySSH actually includes a configuration mechanism to detect integer sizes, and modifies TweetNaCl accordingly, so TinySSH is not 32-bit/LLP64 only.
"Wait, this code is hard to understand and requires deep domain knowledge. Better nitpick the code style instead. Also, bikesheds should clearly be orange. Green is way too fishy."
I have domain knowledge and I've read a lot of code in my time. The style in use there is peculiar. That doesn't mean it is malicious or incorrect but it might make it easier to hide if it was.
stdint.h is C99 and while I'd love to believe that every C compiler is C99 capable by now, I don't know if that is actually the case.
Does stdint.h exist on Win32 these days?
Microsoft's poor support for standard C is no excuse not to use these types everywhere else and either define them yourself on windows or get stdint from boost, from one of the stdint.h replacements or <cstdint> from MSVC 2012.
* no qualifiers in parameter array declarators (`int x[static 10]`, etc.)
* no `restrict` keyword
* no compound literals
* no designated initializers
There's probably more.
On the web you'll find the same quote copy & pasted over and over saying that support for compound literals and designated initializers was supposedly added in VS2013, but it does not appear to be true. Either that, or I haven't found the hidden switch to enable it. By the way, C code still needs to be compiled as C++ to get anything beyond C89 to work, which should give you a clue as to how serious Microsoft is about C99.
What's true though is that stdbool.h was added. It's a start, I guess...
What use is an sshd that doesn't support SCP? I think to most people that is a core feature, I'd be surprised if it wasn't a requirement for git for example.
It sounds like it's small enough perhaps for a direct port to a safe language like rust, that would be interesting (to me at least).
To be fair, OpenSSH's sshd doesn't have support for scp either. scp invokes ssh to connect to the target host and launches another scp instance there to talk to. There's no reason that wouldn't work with TinySSH too.
Rsync stats a bunch of files on both sides. There are plenty of cases where reading is much more expensive than writing at the destination---imagine Glacier, maybe.
Only 6.5/6.6 versions of the OpenSSH client can connect to this server. 6.5 is the first (and as far as I know only) ssh client that introduced chacha20 and ed25519 support.
Every function name in tinyssh/buf.c starts with an underscore...
To quote the standard:
"All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
...
If the program declares or defines an identifier in a
context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined."
Incidentally, I am impressed by the spirit of organisation that the source tree permeates. Both crypto/ and tinyssh/ source trees sport corresponding -test directories and a debian/ tree has already been added.
Initially, I felt irritation by the consistent lack of documentation (no README, no AUTHORS, almost no comments, it seems). Browsing the source, however, I grow convinced that this from a conviction that out-dated or redundant documentation is the greater evil.
[0] Daniel J Bernstein - author of qmail, daemontools and long-time promoter of full disclosure. https://en.wikipedia.org/wiki/Daniel_J._Bernstein