What's new in NSS 3.12.\* - Transport Layer Security (TLS) Session Resumption without Server-Side State
NSS 3.12.\* has this new feature "Transport Layer Security (TLS) Session Resumption without Server-Side State". It is not enabled by default.
It is defined in RFC5077 . This RFC defines mechanisms to resume a Transport Layer Security (TLS) session
without requiring session-specific state at the TLS server. This mechanism is useful in the following situations:
servers that handle a large number of transactions from different
users
servers that desire to cache sessions for a long time
ability to load balance requests across servers
embedded servers with little memory
Lets look at these two cases described in RFC
1. Full Handshake Issuing New Session Ticket
Client |
| Server |
ClientHello (empty SessionTicket extension) | ----> | |
| <---- | ServerHello (empty SessionTicket extension)
Certificate\* ServerKeyExchange\* CertificateRequest\* ServerHelloDone |
Certificate\* ClientKeyExchange CertificateVerify\* [ChangeCipherSpec] Finished | ----> | |
| <---- | NewSessionTicket [ChangeCipherSpec] Finished |
Application Data | <---> | Application Data |
2. Abbreviated Handshake Using New Session Ticket
Client |
| Server |
ClientHello (SessionTicket extension) |
----> |
|
| <---- | ServerHello (empty SessionTicket extension) NewSessionTicket [ChangeCipherSpec]
Finished |
[ChangeCipherSpec] Finished | ----> |
|
Application Data | <---> | ApplicationData |
I have used NSS 3.12.7 in this blog.
Observing Two Connections
Create a certificate
$NSS_DIR/bin/certutil -N -d .
$NSS_DIR/bin/certutil -S -n test -s "CN=test" -x -t "CT,CT,CT" -d .
For ease of use I will use the same certificate for selfserv and strsclnt. I have used -c z (SSL_RSA_WITH_NULL_SHA) NULL cipher to see what's happening as Jyri had used in one of his blogs. For client we use a tool in NSS "strsclnt" with options "-c 2" (2
connections or more) and "-u.
Note that "-u" option means enable the session ticket extension.
In one window we run server
$NSS_DIR/bin/selfserv -p 8444 -d . -D -B -s -n test -u -c z
In another window we run the client strsclnt :
$NSS_DIR/bin/strsclnt -p 1924 -c 2 -o -d . -n test -u -2 test -C z
strsclnt: -- SSL: Server Certificate Validated.
strsclnt: 0 cache hits; 1 cache misses, 0 cache not reusable
0 stateless resumes
strsclnt: 1 cache hits; 1 cache misses, 0 cache not reusable
1 stateless resumes
Here is the ssltap output for this :
$ssltap -l -p 1924 -s test:8444 Connection #1 [Tue Nov 2 20:03:16 2010] Connected to test:8444 --> [ (75 bytes of 70) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 70 (0x46) handshake { type = 1 (client_hello) length = 66 (0x000042) ClientHelloV3 { client_version = {3, 1} random = {...} session ID = { length = 0 contents = {...} } cipher_suites[2] = { (0x00ff) ????/????????/?????????/??? (0x0002) SSL3/RSA/NULL/SHA } compression[1] = { (00) NULL } extensions[21] = { extension type server_name, length [13] = { 0: 00 0b 00 00 08 ... | .....test } extension type session_ticket, length [0] } } } } ] <-- [ (526 bytes of 521) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 521 (0x209) handshake { type = 2 (server_hello) length = 85 (0x000055) ServerHello { server_version = {3, 1} random = {...} session ID = { length = 32 contents = {...} } cipher_suite = (0x0002) SSL3/RSA/NULL/SHA compression method = (00) NULL extensions[13] = { extension type 65281, length [1] = { 0: 00 | . } extension type session_ticket, length [0] extension type server_name, length [0] } } type = 11 (certificate) length = 424 (0x0001a8) CertificateChain { chainlength = 421 (0x01a5) Certificate { size = 418 (0x01a2) data = { saved in file 'cert.001' } } } type = 14 (server_hello_done) length = 0 (0x000000) } } ] --> [ (186 bytes of 134, with 47 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 134 (0x86) handshake { type = 16 (client_key_exchange) length = 130 (0x000082) ClientKeyExchange { message = {...} } } } (186 bytes of 1, with 41 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 20 (change_cipher_spec) version = { 3,1 } length = 1 (0x1) } (186 bytes of 36) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 36 (0x24) handshake { type = 20 (finished) length = 12 (0x00000c) Finished { verify_data = {...} } } MAC = {...} } ] <-- [ (224 bytes of 172, with 47 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 172 (0xac) handshake {type = 4 (new_session_ticket) length = 168 (0x0000a8) NewSessionTicket { ticket_lifetime_hint = Sat, 03-Jan-1970 00:00:00 GMT ticket = { length = 162 contents = {...} } } } } (224 bytes of 1, with 41 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 20 (change_cipher_spec) version = { 3,1 } length = 1 (0x1) } (224 bytes of 36) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 36 (0x24) handshake { type = 20 (finished) length = 12 (0x00000c) Finished { verify_data = {...} } } MAC = {...} } ] --> [ (46 bytes of 41) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 23 (application_data) version = { 3,1 } length = 41 (0x29) 0: 47 45 54 20 2f 61 62 63 20 48 54 54 50 2f 31 2e | GET /abc HTTP/1. 10: 30 0d 0a 0d 0a | 0.... MAC = {...} } ] <-- [ (192 bytes of 160, with 27 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 23 (application_data) version = { 3,1 } length = 160 (0xa0) 0: 48 54 54 50 2f 31 2e 30 20 32 30 30 20 4f 4b 0d | HTTP/1.0 200 OK. 10: 0a 53 65 72 76 65 72 3a 20 47 65 6e 65 72 69 63 | .Server: Generic 20: 20 57 65 62 20 53 65 72 76 65 72 0d 0a 44 61 74 | Web Server..Dat 30: 65 3a 20 54 75 65 2c 20 32 36 20 41 75 67 20 31 | e: Tue, 26 Aug 1 40: 39 39 37 20 32 32 3a 31 30 3a 30 35 20 47 4d 54 | 997 22:10:05 GMT 50: 0d 0a 43 6f 6e 74 65 6e 74 2d 74 79 70 65 3a 20 | ..Content-type: 60: 74 65 78 74 2f 70 6c 61 69 6e 0d 0a 0d 0a 47 45 | text/plain....GE 70: 54 20 2f 61 62 63 20 48 54 54 50 2f 31 2e 30 0d | T /abc HTTP/1.0. 80: 0a 0d 0a 45 4f 46 0d 0a 0d 0a 0d 0a | ...EOF...... MAC = {...} } (192 bytes of 22) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 21 (alert) version = { 3,1 } length = 22 (0x16) warning: close_notify MAC = {...} } ] Read EOF on Server socket. [Tue Nov 2 20:03:16 2010] Read EOF on Client socket. [Tue Nov 2 20:03:16 2010] Connection 1 Complete [Tue Nov 2 20:03:16 2010] |
You can see that the server sends the session ticket in the first connection. Hence connection 1 is same as "Full Handshake Issuing New Session Ticket" in the table above.
Connection #2 [Tue Nov 2 20:03:16 2010] Connected to test:8444 --> [ (269 bytes of 264) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 264 (0x108) handshake { type = 1 (client_hello) length = 260 (0x000104) ClientHelloV3 { client_version = {3, 1} random = {...} session ID = { length = 32 contents = {...} } cipher_suites[2] = { (0x00ff) ????/????????/?????????/??? (0x0002) SSL3/RSA/NULL/SHA } compression[1] = { (00) NULL } extensions[183] = { extension type server_name, length [13] = { 0: 00 0b 00 00 08 ... | .....test } extension type session_ticket, length [162] = { 0: 4e 53 53 21 27 9b e0 2e 14 46 9c 67 e0 31 b6 b9 | NSS!'....F.g.1.. 10: fd 97 31 0a 73 25 0f 70 de 84 89 ac 2b d9 d0 af | ..1.s%.p....+... 20: 00 60 4d 99 7c dd fc 0b 67 10 dd 61 66 55 55 88 | .`M.|...g..afUU. 30: db 59 ce f8 46 95 6b b9 09 ad 7b 95 7c cb 6a dd | .Y..F.k...{.|.j. 40: 17 b6 31 43 df 26 13 6a 15 69 4a 3a f2 9e 6c 43 | ..1C.&.j.iJ:..lC 50: b3 5f 60 4e fc e7 d1 dd 0d 97 d6 a6 cc c7 89 f7 | ._`N............ 60: a4 e4 17 54 23 0f 14 fc e7 c7 5e 7f 5d 00 56 c4 | ...T#.....\^].V. 70: e0 c3 3c cb d1 48 3c 29 b1 26 89 d2 ac d4 2f 14 | ..<..H<).&..../. 80: 99 f5 49 a5 87 2a a5 5b ac c8 a4 df d4 c4 f9 b8 | ..I..\*.[........ 90: 93 55 bf 2f ff 9e 7d e3 0d e2 51 56 c2 30 66 92 | .U./..}...QV.0f. a0: d5 17 | .. } } } } } ] <-- [ (133 bytes of 81, with 47 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 81 (0x51) handshake { type = 2 (server_hello) length = 77 (0x00004d) ServerHello { server_version = {3, 1} random = {...} session ID = { length = 32 contents = {...} } cipher_suite = (0x0002) SSL3/RSA/NULL/SHA compression method = (00) NULLextensions[5] = { extension type 65281, length [1] = { 0: 00 | . } } } } } (133 bytes of 1, with 41 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 20 (change_cipher_spec) version = { 3,1 } length = 1 (0x1) } (133 bytes of 36) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 36 (0x24) handshake { type = 20 (finished) length = 12 (0x00000c) Finished { verify_data = {...} } } MAC = {...} } ] --> [ (93 bytes of 1, with 87 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 20 (change_cipher_spec) version = { 3,1 } length = 1 (0x1) } (93 bytes of 36, with 46 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 22 (handshake) version = { 3,1 } length = 36 (0x24) handshake { type = 20 (finished) length = 12 (0x00000c) Finished { verify_data = {...} } } MAC = {...} } (93 bytes of 41) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 23 (application_data) version = { 3,1 } length = 41 (0x29) 0: 47 45 54 20 2f 61 62 63 20 48 54 54 50 2f 31 2e | GET /abc HTTP/1. 10: 30 0d 0a 0d 0a | 0.... MAC = {...} } ] <-- [ (192 bytes of 160, with 27 left over) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 23 (application_data) version = { 3,1 } length = 160 (0xa0) 0: 48 54 54 50 2f 31 2e 30 20 32 30 30 20 4f 4b 0d | HTTP/1.0 200 OK. 10: 0a 53 65 72 76 65 72 3a 20 47 65 6e 65 72 69 63 | .Server: Generic 20: 20 57 65 62 20 53 65 72 76 65 72 0d 0a 44 61 74 | Web Server..Dat 30: 65 3a 20 54 75 65 2c 20 32 36 20 41 75 67 20 31 | e: Tue, 26 Aug 1 40: 39 39 37 20 32 32 3a 31 30 3a 30 35 20 47 4d 54 | 997 22:10:05 GMT 50: 0d 0a 43 6f 6e 74 65 6e 74 2d 74 79 70 65 3a 20 | ..Content-type: 60: 74 65 78 74 2f 70 6c 61 69 6e 0d 0a 0d 0a 47 45 | text/plain....GE 70: 54 20 2f 61 62 63 20 48 54 54 50 2f 31 2e 30 0d | T /abc HTTP/1.0. 80: 0a 0d 0a 45 4f 46 0d 0a 0d 0a 0d 0a | ...EOF...... MAC = {...} } (192 bytes of 22) SSLRecord { [Tue Nov 2 20:03:16 2010] type = 21 (alert) version = { 3,1 } length = 22 (0x16) warning: close_notify MAC = {...} } ] Read EOF on Server socket. [Tue Nov 2 20:03:16 2010] Read EOF on Client socket. [Tue Nov 2 20:03:16 2010] Connection 2 Complete [Tue Nov 2 20:03:16 2010] |
In the second connection, the client has used the same ticket and that's why it doesn't have to go through the full handshake and is not resending its certificate chain etc. Connection 2 is same as "Abbreviated Handshake Using New Session Ticket" in the table above but only with one difference that the server doesn't send a new ticket.
When session ticket extension is enabled, session information is taken
from the extension data. However, if the extension is not used, SSL
layer obtains session info from the internal session cache. If
the client comes with a valid session id, session is restarted with out
key exchange.
NSS Code
If you look at selfserv.c http://mxr.mozilla.org/security/source/security/nss/cmd/selfserv/selfserv.c#1695,
it uses the call SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
Same is true for strsclnt http://mxr.mozilla.org/security/source/security/nss/cmd/strsclnt/strsclnt.c#1237
Reference
- RFC5077 Transport Layer Security (TLS) Session Resumption without Server-Side State
What does following mean :
extension type 65281, length [1] = {
0: 00
}
I think this is not related.
look at RFC 5746 http://www.ietf.org/rfc/rfc5746.txt
section 6. IANA Considerations
IANA has added the extension code point 65281 (0xff01), which has been used for prototype implementations, for the "renegotiation_info" extension to the TLS ExtensionType values registry.