AmigaSSH: SSH2 client and server for the Amiga

Intro

There was no working SSH2 client/server for the Amiga supporting modern encryption, but I wanted both.
Should I start porting OpenSSH? Or should I use AmiSSL?
-> Considering the sizes of both - both are monsters, the AmiSSL library is larger than 3MB - and then the missing support for the 68000... So I decided to start from scratch.
Since I already had Java and C++ code for some of the cryptographic methods, C++ was my choice for the Amiga. I just needed some info for the "how does it work" and was ready to start.

The resources:

Coding AmigaSSH

I started with a simple TCP client to connect to a server and started to implement the packets. Since it should work with the standard SSH2 server on my Linux servers, I used these for testing. The most importand tool was the dump function to print received and sent packages.

First packets

And here starts the fun...

-> client hello packet

The protocol states to start with a simple helle message, containing the protocol version and some vendor specific text, so I sent
0000 
53 53 48 2D 32 2E 30
 2D  
6D 69 6E 69 53 53 48 2D
 
SSH-2.0
-
miniSSH-
0010 
30 2E 31
 0D 0A                                   
0.1
  
A plaintext with a CRLF at the end.

<- server hello packet

And to no surprise I could also read the server's hello packet:
0000 53 53 48 2D 32 2E 30 2D  4F 70 65 6E 53 53 48 5F SSH-2.0-OpenSSH_
0010 39 2E 36                                         9.6
Also a plaintext with the same structure and a CRLF at the end.

-> client key exchange init

Since I wanted to support only one variant I managed to assemble the packet to announce my supported variants:
0000  
00 00 00 B4
 
0B
 
14
 
1D FC  61 19 C0 C7 C6 75 9C 13
  ........a....u..
0010  
E2 E1 98 5F 3E 13
 
00 00  00 11 63 75 72 76 65 32
  ..._>.....curve2
0020  
35 35 31 39 2D 73 68 61  32 35 36
 
00 00 00 0B 73
  5519-sha256....s
0030  
73 68 2D 65 64 32 35 35  31 39
 
00 00 00 16 61 65
  sh-ed25519....ae
0040  
73 31 32 38 2D 67 63 6D  40 6F 70 65 6E 73 73 68
  s128-gcm@openssh
0050  
2E 63 6F 6D
 
00 00 00 16  61 65 73 31 32 38 2D 67
  .com....aes128-g
0060  
63 6D 40 6F 70 65 6E 73  73 68 2E 63 6F 6D
 
00 00
  cm@openssh.com..
0070  
00 0D 68 6D 61 63 2D 73  68 61 32 2D 32 35 36
 
00
  ..hmac-sha2-256.
0080  
00 00 0D 68 6D 61 63 2D  73 68 61 32 2D 32 35 36
  ...hmac-sha2-256
0090  
00 00 00 04 6E 6F 6E 65
  
00 00 00 04 6E 6F 6E 65
  ....none....none
00a0  
00 00 00 00 00 00 00 00  00 00 00 00 00
 
FF C9 71
  ................
00b0  
ED 64 38 B8 6C 92 27 BA
                           ........
We generate the random nonce, the rest is constant. There is no need to track the nonce, it contributes to the hash, that's it.

<- server key exchange init

The server sent a packet with the same structure, but way more options, a ridiculous large amount of options... I could have checked if the server matches, but since my client offers only one option there's nothing to check. Nice!

-> client ecdh init

The client sends it's public key.
0000 
00 00 00 2C
 
06
 
1E
 
00 00  00 20 92 D7 57 3C 2C A3
  ...,..... ..W<,.
0010 
C0 70 97 5E 5B 81 0A AF  27 D4 9B B0 CF 50 C7 1B
  .p.^[...'....P..
0020 
A2 F2 82 6E C2 FB 33 EB  B1 78
 00 00 00 00 00 00  ...n..3..x...... 

<- server ecdh reply

The server packet contains the servers's public key.
0000 
00 00 00 BC
 
08
 
1F
 
00 00  00 33 00 00 00 0B 73 73
  .........3....ss
0010 
68 2D 65 64 32 35 35 31  39 
00 00 00 20 AC AF 4D
  h-ed25519... ..M
0020 
62 55 87 43 BC 72 E4 2F  C9 7C B0 3A 35 1F A5 62
  bU.C.r./.|.:5..b
0030 
FB F5 DC E8 17 81 1F 00  8D 28 6F 49 5E
 
00 00 00
  .........(oI^...
0040 
20 5C 7E 63 16 BE 68 62  34 5A 28 55 69 B3 92 B2
   \~c..hb4Z(Ui...
0050 
00 4F 6C 98 16 29 70 FD  6B 59 74 13 EE 2B D3 52
  .Ol..)p.kYt..+.R
0060 
71
 
00 00 00 53 00 00 00  0B 73 73 68 2D 65 64 32
  q...S....ssh-ed2
0070 
35 35 31 39 
00 00 00 40  4B 21 25 1A D8 60 71 2B
  5519...@K!%..`q+
0080 
B0 E9 96 61 B8 42 29 29  B4 45 6C 05 60 DA 4A 20
  ...a.B)).El.`.J 
0090 
E9 16 65 6F 09 60 A2 59  25 9C 44 3F 0C B6 89 ED
  ..eo.`.Y%.D?....
00A0 
16 B8 59 97 F5 3D 6B 21  E2 0C B9 90 5F 39 99 2F
  ..Y..=k!...._9./
00B0 
4A 56 46 3A B0 BD 71 0E
  00 00 00 00 00 00 00 00  JVF:..q.........

And here starts the fun to learn more about ED25519 and X22519: I first managed to do the X22519 multiplication correctly. Since And Both sides can compute the same value by multiplying the received public key with its own private key:
Checking the signature was more work since ED25519 is not X25519!!.
Luckily I had my Java code plus there are python reference implementations around to create test data and debug. For C implementations you my consider supercop or ed25519-donna where donna seems to be the fastest implementation. But donna needs 64 bit integers and 32 bit multiplication... So I started with a supercop variant using 16 bit integers with 8 bits used and dropped all superfluous code which should help to avoid timing attacks. Well, on the Amiga anyone can read anything -> drop it! I also removed some optimizations which resulted in big big code.
Eventually it worked out.
After putting the correct data into a SHA512 hash I also managed to create the correct keymaterial.

-> client newkeys

<- server newkeys

Both are empty packets to activate the encryption.
From now on the messages are encrypted.

-> client's service request

<- servers's service response

Now the client wants to perform some authentication and the server replies the supported methods.
0000 
05
 
00 00 00 0C 73 73 68  2D 75 73 65 72 61 75 74
  .....ssh-useraut
0010 
68

-> client's user auth request

The first attempt is without any authentication
0000 
32
 
00 00 00 06 73 74 65  66 61 6E
 
00 00 00 0E 73
  2....stefan....s
0010 
73 68 2D 63 6F 6E 6E 65  63 74 69 6F 6E
 
00 00 00
  sh-connection...
0020 
04 6E 6F 6E 65
                                    .none

<- server's user auth response

The server replies with an authentication failure and the list of supported methods.
0000 
33
 
00 00 00 08 70 61 73  73 77 6F 72 64 00
        3....password.

O.K. I stop here with the dumps, or you could read my secret password^^

Terminal fun

After establishing a SSH connection I had to work on key translation. On the server side there are many terminal emulations available, even some for the Amiga, but none seems to work properly. So I started to code terminal emulation too. Together with the key translations I finally made a login with a good look and feel:
amigassh.png
After all also the midnight commander worked properly:
amigassh-mc.png
(Note: the CLI title changed too^^ plus you can use the mouse to click)