TinySSH is a small SSH server using NaCl, TweetNaCl
tinyssh.org
tinyssh.org
$ 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.
[0] Daniel J Bernstein - author of qmail, daemontools and long-time promoter of full disclosure. https://en.wikipedia.org/wiki/Daniel_J._Bernstein
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.
keydir = *++argv; if (!keydir) die_usage();
or if (*x == 'v') { if (flagverbose >= 2) flagverbose = 3; else flagverbose = 2; continue; }
why put multiple statements on the same line if you have nothing to hide?[1](Not that I would have written either line that way, mind you. But there's no real challenge understanding them.)
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.
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.
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.
Because it's more readable.
Do
you
truly
find having
only a few
words per line
more
readable?
Does
it aid
with
comprehension?
I find having a high word density to be the most "readable", and it doesn't seem to matter whether it's C or English.
The TinySSH source code is small enough that I was able to read it in about 25 minutes and I learned about the SSH protocol along the way.
that being said,
breaking a sentence across multiple lines
does help with comprehension
when you break on clause boundaries.
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.
----
https://matt.ucc.asn.au/dropbear/dropbear.html
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.
CHALLENGE ACCEPTED!
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!
djb's cryptography is great, but djb's implementations leave something to be desired.
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.
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 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 ... no older cryptographic primitives - rsa, dsa, classic diffie-hellman, md5, sha1, 3des, arcfour, ...
It is actually used in the code though. I didn't look into for what it was used though.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?
typedef unsigned long u32;
but on 64-bit LP64 systems (like Linux), long is 64-bits.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.
IMHO, of course.
* no variable-length arrays
* 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...
ulong is as you know the smallest type that's always guaranteed to be at least 32 bits.
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.
[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
[2] http://nepsweb.co.uk/langstand/isoC/gordon/ansi-c89w.txt
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.
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.
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).
tar c path/to/files | ssh host tar x
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."
-- ISO/IEC 9899:1999, Section 7.1.3 Reserved Identifiers