6. Binary Packet Protocol (Protocollo a pacchetti binari)
6. Binary Packet Protocol (Protocollo a pacchetti binari)
Ogni pacchetto ha il formato seguente:
uint32 packet_length
byte padding_length
byte[n1] payload; n1 = packet_length - padding_length - 1
byte[n2] random padding; n2 = padding_length
byte[m] mac (Message Authentication Code - MAC); m = mac_length
packet_length
The length of the packet in bytes, not including 'mac' or the
'packet_length' field itself.
padding_length
Length of 'random padding' (bytes).
payload
The useful contents of the packet. If compression has been
negotiated, this field is compressed. Initially, compression
MUST be "none".
random padding
Arbitrary-length padding, such that the total length of
(packet_length || padding_length || payload || random padding)
is a multiple of the cipher block size or 8, whichever is
larger. There MUST be at least four bytes of padding. The
padding SHOULD consist of random bytes. The maximum amount of
padding is 255 bytes.
mac
Message Authentication Code. If message authentication has
been negotiated, this field contains the MAC bytes. Initially,
the MAC algorithm MUST be "none".
Si noti che la lunghezza della concatenazione di 'packet_length', 'padding_length', 'payload' e 'random padding' DEVE essere un multiplo della dimensione del blocco del cifrario (cipher block size) o 8, a seconda di quale sia maggiore. Questo vincolo DEVE essere rispettato, anche quando si usano cifrari a flusso (stream ciphers). Si noti che il campo 'packet_length' è anch'esso crittografato, e la sua elaborazione richiede particolare attenzione quando si inviano o si ricevono pacchetti. Si noti inoltre che l'inserimento di quantità variabili di 'random padding' può aiutare a contrastare l'analisi del traffico (traffic analysis).
La dimensione minima di un pacchetto è 16 byte (o la dimensione del blocco del cifrario, a seconda di quale sia maggiore) più 'mac'. Le implementazioni DOVREBBERO decrittare la lunghezza dopo aver ricevuto i primi 8 byte (o la dimensione del blocco del cifrario, a seconda di quale sia maggiore) di un pacchetto.
6.1. Maximum Packet Length (Lunghezza massima del pacchetto)
Tutte le implementazioni DEVONO essere in grado di elaborare pacchetti con una lunghezza del payload non compresso di 32768 byte o meno e una dimensione totale del pacchetto di 35000 byte o meno (inclusi 'packet_length', 'padding_length', 'payload', 'random padding' e 'mac'). Il massimo di 35000 byte è un valore scelto arbitrariamente, maggiore della lunghezza non compressa indicata sopra. Le implementazioni DOVREBBERO supportare pacchetti più lunghi, ove necessario. Ad esempio, se un'implementazione vuole inviare un numero molto elevato di certificati, i pacchetti più lunghi POSSONO essere inviati se la stringa di identificazione indica che l'altra parte è in grado di elaborarli. Tuttavia, le implementazioni DOVREBBERO verificare che la lunghezza del pacchetto sia ragionevole affinché l'implementazione eviti attacchi di denial of service e/o buffer overflow.
6.2. Compression (Compressione)
Se la compressione è stata negoziata, il campo 'payload' (e solo esso) sarà compresso usando l'algoritmo negoziato. I campi 'packet_length' e 'mac' saranno calcolati dal payload compresso. La crittografia sarà eseguita dopo la compressione.
La compressione PUÒ essere con stato (stateful), a seconda del metodo. La compressione DEVE essere indipendente per ciascuna direzione, e le implementazioni DEVONO consentire la scelta indipendente dell'algoritmo per ciascuna direzione. In pratica tuttavia, si RACCOMANDA che il metodo di compressione sia lo stesso in entrambe le direzioni.
I seguenti metodi di compressione sono attualmente definiti:
none REQUIRED no compression
zlib OPTIONAL ZLIB (LZ77) compression
La compressione "zlib" è descritta in [RFC1950] e in [RFC1951]. Il contesto di compressione è inizializzato dopo ciascuno scambio di chiavi e viene passato da un pacchetto al successivo, con esecuzione solo di un flush parziale alla fine di ciascun pacchetto. Un flush parziale significa che il blocco compresso corrente termina e tutti i dati saranno emessi. Se il blocco corrente non è un blocco memorizzato (stored block), uno o più blocchi vuoti sono aggiunti dopo il blocco corrente per garantire che vi siano almeno 8 bit, contando dall'inizio del codice di fine blocco del blocco corrente fino alla fine del payload del pacchetto.
Metodi aggiuntivi possono essere definiti come specificato in [SSH-ARCH] e [SSH-NUMBERS].
6.3. Encryption (Crittografia)
Un algoritmo di crittografia e una chiave saranno negoziati durante lo scambio di chiavi. Quando la crittografia è attiva, la lunghezza del pacchetto, la lunghezza del padding, il payload e i campi padding di ciascun pacchetto DEVONO essere crittografati con l'algoritmo indicato.
I dati crittografati in tutti i pacchetti inviati in una direzione DOVREBBERO essere considerati un unico flusso di dati. Ad esempio, i vettori di inizializzazione (initialization vectors) DOVREBBERO essere passati dalla fine di un pacchetto all'inizio del successivo. Tutti i cifrari DOVREBBERO usare chiavi con una lunghezza effettiva di 128 bit o più.
I cifrari in ciascuna direzione DEVONO funzionare indipendentemente l'uno dall'altro. Le implementazioni DEVONO consentire che l'algoritmo per ciascuna direzione sia selezionato indipendentemente, se più algoritmi sono consentiti dalla politica locale. In pratica tuttavia, si RACCOMANDA che lo stesso algoritmo sia usato in entrambe le direzioni.
I seguenti cifrari sono attualmente definiti:
3des-cbc REQUIRED three-key 3DES in CBC mode
blowfish-cbc OPTIONAL Blowfish in CBC mode
twofish256-cbc OPTIONAL Twofish in CBC mode,
with a 256-bit key
twofish-cbc OPTIONAL alias for "twofish256-cbc"
(this is being retained
for historical reasons)
twofish192-cbc OPTIONAL Twofish with a 192-bit key
twofish128-cbc OPTIONAL Twofish with a 128-bit key
aes256-cbc OPTIONAL AES in CBC mode,
with a 256-bit key
aes192-cbc OPTIONAL AES with a 192-bit key
aes128-cbc RECOMMENDED AES with a 128-bit key
serpent256-cbc OPTIONAL Serpent in CBC mode, with
a 256-bit key
serpent192-cbc OPTIONAL Serpent with a 192-bit key
serpent128-cbc OPTIONAL Serpent with a 128-bit key
arcfour OPTIONAL the ARCFOUR stream cipher
with a 128-bit key
idea-cbc OPTIONAL IDEA in CBC mode
cast128-cbc OPTIONAL CAST-128 in CBC mode
none OPTIONAL no encryption; NOT RECOMMENDED
Il cifrario "3des-cbc" è triple-DES a tre chiavi (encrypt-decrypt-encrypt), dove i primi 8 byte della chiave sono usati per la prima crittografia, i successivi 8 byte per la decrittazione e i seguenti 8 byte per la crittografia finale. Sono richiesti 24 byte di dati di chiave (di cui 168 bit sono effettivamente usati). Per implementare la modalità CBC, DEVE essere usata la concatenazione esterna (outer chaining), cioè vi è un solo vettore di inizializzazione. È un cifrario a blocchi con blocchi di 8 byte. Questo algoritmo è definito in [FIPS-46-3]. Si noti che poiché questo algoritmo ha solo una lunghezza effettiva di chiave di 112 bit ([SCHNEIER]), non soddisfa le specifiche secondo cui gli algoritmi di crittografia SSH dovrebbero usare chiavi di 128 bit o più. Tuttavia, questo algoritmo è ancora RICHIESTO per motivi storici; essenzialmente, tutte le implementazioni note al momento della stesura supportano questo algoritmo, ed è comunemente usato perché è l'algoritmo interoperabile fondamentale. In un futuro si prevede che un altro algoritmo, con maggiore robustezza, diventi così prevalente e onnipresente che l'uso di "3des-cbc" sarà deprecato mediante un'altra STANDARDS ACTION.
Il cifrario "blowfish-cbc" è Blowfish in modalità CBC, con chiavi a 128 bit [SCHNEIER]. È un cifrario a blocchi con blocchi di 8 byte.
Il cifrario "twofish-cbc" o "twofish256-cbc" è Twofish in modalità CBC, con chiavi a 256 bit come descritto in [TWOFISH]. È un cifrario a blocchi con blocchi di 16 byte.
Il cifrario "twofish192-cbc" è come sopra, ma con chiave a 192 bit.
Il cifrario "twofish128-cbc" è come sopra, ma con chiave a 128 bit.
Il cifrario "aes256-cbc" è AES (Advanced Encryption Standard) [FIPS-197], in modalità CBC. Questa versione usa una chiave a 256 bit.
Il cifrario "aes192-cbc" è come sopra, ma con chiave a 192 bit.
Il cifrario "aes128-cbc" è come sopra, ma con chiave a 128 bit.
Il cifrario "serpent256-cbc" in modalità CBC, con chiave a 256 bit come descritto nella proposta Serpent per AES.
Il cifrario "serpent192-cbc" è come sopra, ma con chiave a 192 bit.
Il cifrario "serpent128-cbc" è come sopra, ma con chiave a 128 bit.
Il cifrario "arcfour" è il cifrario a flusso Arcfour con chiavi a 128 bit. Si ritiene che il cifrario Arcfour sia compatibile con il cifrario RC4 [SCHNEIER]. Arcfour (e RC4) presenta problemi con chiavi deboli (weak keys) e dovrebbe essere usato con cautela.
Il cifrario "idea-cbc" è il cifrario IDEA in modalità CBC [SCHNEIER].
Il cifrario "cast128-cbc" è il cifrario CAST-128 in modalità CBC con chiave a 128 bit [RFC2144].
L'algoritmo "none" specifica che non deve essere eseguita alcuna crittografia. Si noti che questo metodo non fornisce protezione della riservatezza (confidentiality), e NON È RACCOMANDATO. Alcune funzionalità (ad esempio, l'autenticazione con password) possono essere disabilitate per motivi di sicurezza se si sceglie questo cifrario.
Metodi aggiuntivi possono essere definiti come specificato in [SSH-ARCH] e in [SSH-NUMBERS].
6.4. Data Integrity (Integrità dei dati)
L'integrità dei dati è protetta includendo in ciascun pacchetto un MAC calcolato da un segreto condiviso (shared secret), dal numero di sequenza del pacchetto e dal contenuto del pacchetto.
L'algoritmo di autenticazione del messaggio e la chiave sono negoziati durante lo scambio di chiavi. Inizialmente, nessun MAC sarà attivo e la sua lunghezza DEVE essere zero. Dopo lo scambio di chiavi, il 'mac' per l'algoritmo MAC selezionato sarà calcolato prima della crittografia dalla concatenazione dei dati del pacchetto:
mac = MAC(key, sequence_number || unencrypted_packet)
dove unencrypted_packet è l'intero pacchetto senza 'mac' (i campi di lunghezza, 'payload' e 'random padding'), e sequence_number è un numero di sequenza implicito del pacchetto rappresentato come uint32. Il sequence_number è inizializzato a zero per il primo pacchetto ed è incrementato dopo ogni pacchetto (indipendentemente dall'uso di crittografia o MAC). Non viene mai azzerato, anche se chiavi/algoritmi sono rinegoziati successivamente. Torna a zero dopo ogni 2^32 pacchetti. Il sequence_number del pacchetto stesso non è incluso nel pacchetto inviato sul canale.
Gli algoritmi MAC per ciascuna direzione DEVONO funzionare indipendentemente, e le implementazioni DEVONO consentire di scegliere l'algoritmo indipendentemente per entrambe le direzioni. In pratica tuttavia, si RACCOMANDA che lo stesso algoritmo sia usato in entrambe le direzioni.
Il valore di 'mac' risultante dall'algoritmo MAC DEVE essere trasmesso senza crittografia come ultima parte del pacchetto. Il numero di byte 'mac' dipende dall'algoritmo scelto.
I seguenti algoritmi MAC sono attualmente definiti:
hmac-sha1 REQUIRED HMAC-SHA1 (digest length = key
length = 20)
hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest
length = 12, key length = 20)
hmac-md5 OPTIONAL HMAC-MD5 (digest length = key
length = 16)
hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest
length = 12, key length = 16)
none OPTIONAL no MAC; NOT RECOMMENDED
Gli algoritmi "hmac-" sono descritti in [RFC2104]. I MAC "-n" usano solo i primi n bit del valore risultante.
SHA-1 è descritto in [FIPS-180-2] e MD5 è descritto in [RFC1321].
Metodi aggiuntivi possono essere definiti, come specificato in [SSH-ARCH] e in [SSH-NUMBERS].
6.5. Key Exchange Methods (Metodi di scambio di chiavi)
Il metodo di scambio di chiavi specifica come vengono generate le chiavi di sessione monouso (one-time session keys) per la crittografia e per l'autenticazione, e come viene effettuata l'autenticazione del server.
Due metodi di scambio di chiavi RICHIESTI sono stati definiti:
diffie-hellman-group1-sha1 REQUIRED
diffie-hellman-group14-sha1 REQUIRED
Questi metodi sono descritti nella Sezione 8.
Metodi aggiuntivi possono essere definiti come specificato in [SSH-NUMBERS]. Il nome "diffie-hellman-group1-sha1" è usato per un metodo di scambio di chiavi che usa un gruppo Oakley, come definito in [RFC2409]. SSH mantiene un proprio spazio di identificatori di gruppo logicamente distinto da Oakley [RFC2412] e IKE; tuttavia, per un gruppo aggiuntivo, il Working Group ha adottato il numero assegnato da [RFC3526], usando diffie-hellman-group14-sha1 come nome del secondo gruppo definito. Le implementazioni dovrebbero trattare questi nomi come identificatori opachi e non dovrebbero assumere alcuna relazione tra i gruppi usati da SSH e i gruppi definiti per IKE.
6.6. Public Key Algorithms (Algoritmi a chiave pubblica)
Questo protocollo è stato progettato per operare con quasi qualsiasi formato, codifica e algoritmo a chiave pubblica (firma e/o crittografia).
Vi sono diversi aspetti che definiscono un tipo di chiave pubblica:
-
Formato della chiave (Key format): come è codificata la chiave e come sono rappresentati i certificati. I blob di chiave in questo protocollo POSSONO contenere certificati oltre alle chiavi.
-
Algoritmi di firma e/o crittografia. Alcuni tipi di chiave potrebbero non supportare sia la firma sia la crittografia. L'uso della chiave può anche essere limitato da dichiarazioni di policy (ad esempio, nei certificati). In questo caso, DOVREBBERO essere definiti tipi di chiave diversi per le diverse alternative di policy.
-
Codifica delle firme e/o dei dati crittografati. Ciò include ma non è limitato a padding, ordine dei byte e formati dei dati.
I seguenti formati di chiave pubblica e/o certificato sono attualmente definiti:
ssh-dss REQUIRED sign Raw DSS Key
ssh-rsa RECOMMENDED sign Raw RSA Key
pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key)
pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key)
Tipi di chiave aggiuntivi possono essere definiti, come specificato in [SSH-ARCH] e in [SSH-NUMBERS].
Il tipo di chiave DEVE essere sempre esplicitamente noto (dalla negoziazione degli algoritmi o da un'altra fonte). Non è normalmente incluso nel blob della chiave.
Certificati e chiavi pubbliche sono codificati come segue:
string certificate or public key format identifier
byte[n] key/certificate data
La parte certificato può essere una stringa di lunghezza zero, ma è richiesta una chiave pubblica. Questa è la chiave pubblica che sarà usata per l'autenticazione. La sequenza di certificati contenuta nel blob del certificato può essere usata per fornire l'autorizzazione.
I formati di chiave pubblica/certificato che non specificano esplicitamente un identificatore di formato di firma DEVONO usare l'identificatore di formato di chiave pubblica/certificato come identificatore di firma.
Le firme sono codificate come segue:
string signature format identifier (as specified by the
public key/certificate format)
byte[n] signature blob in format specific encoding.
Il formato di chiave "ssh-dss" ha la codifica specifica seguente:
string "ssh-dss"
mpint p
mpint q
mpint g
mpint y
Qui, i parametri 'p', 'q', 'g' e 'y' formano il blob della chiave di firma.
La firma e la verifica usando questo formato di chiave sono eseguite secondo lo Digital Signature Standard [FIPS-186-2] usando l'hash SHA-1 [FIPS-180-2].
La firma risultante è codificata come segue:
string "ssh-dss"
string dss_signature_blob
Il valore di 'dss_signature_blob' è codificato come stringa contenente r, seguito da s (che sono interi a 160 bit, senza lunghezze o padding, senza segno e in ordine di byte di rete).
Il formato di chiave "ssh-rsa" ha la codifica specifica seguente:
string "ssh-rsa"
mpint e
mpint n
Qui i parametri 'e' e 'n' formano il blob della chiave di firma.
La firma e la verifica usando questo formato di chiave sono eseguite secondo lo schema RSASSA-PKCS1-v1_5 in [RFC3447] usando l'hash SHA-1.
La firma risultante è codificata come segue:
string "ssh-rsa"
string rsa_signature_blob
Il valore di 'rsa_signature_blob' è codificato come stringa contenente s (che è un intero, senza lunghezze o padding, senza segno e in ordine di byte di rete).
Il metodo "pgp-sign-rsa" indica che certificati, chiave pubblica e firma sono in formato binario compatibile OpenPGP ([RFC2440]). Questo metodo indica che la chiave è una chiave RSA.
Il metodo "pgp-sign-dss" è come sopra, ma indica che la chiave è una chiave DSS.