Using
Pre-Shared Keys with Transport Layer Security : Tutorial
This topic describes how to use Pre-Shared Keys (PSKs) with Transport
Layer Security (TLS). This tutorial is useful for licensees and third-party
developers.
TLS_PSK is a standard for using PSKs with Transport Layer Security
(TLS). You can use TLS_PSK instead of certificate authentication. The benefits
of using TLS_PSK are as follows:
Easy to manage - For
example, PSK can derive from a "secret key" that vendors deploy in the SIM
card of each phone.
It improves the connection
setup performance and battery life, as the key exchange algorithm takes less
time to run.
Symbian maintains the following TLS_PSK ciphersuites:
TLS_PSK_WITH_RC4_128_SHA
TLS_PSK_WITH_3DES_EDE_CBC_SHA
TLS_PSK_WITH_AES_128_CBC_SHA
TLS_PSK_WITH_AES_256_CBC_SHA
The ciphersuite is made up of a key exchange (for example PSK), a
cipher (for example RC4_128) and a hash (for example SHA).
Note: TLS_PSK
operation is specified by RFC4279.
For a client to make a secure connection
with a TLS_PSK server, it must provide a pre-shared key and an identity. To
provide a pre-shared key and an identity, do the following steps:
- Configure a PSK
key handler
Set available ciphersuites. There are two possibilities for offering
PSK ciphersuites:
- Specify an explicit
ordered list of ciphersuites for the server to select from.
To do this call SetAvailableCipherSuites(). You can
do this only after configuring the PSK key handler.
- Use the default
list, which is automatically generated.
If you do not specify an explicit list, the stack automatically includes
the PSK ciphersuites in addition to any other ciphersuites supported.
If you specify an explicit list by calling SetAvailableCipherSuites(),
and you later deconfigure the PSK key handler, you must remove the PSK ciphersuites
from the list by calling SetAvailableCipherSuites() again.
Start a connection.
The server chooses a ciphersuite from those offered by the client. If
the server chooses a PSK ciphersuite, the following sequence of events occurs:
- The server can
optionally send a “PSK identity hint” to the client.
This PSK identity hint might influence the choice of key and identity
the client makes. If the server sends one, it is passed to the key handler.
If it does not send one, NULL is passed to the key handler.
Note: The PSK identity hint is optional and its meaning is not defined
(format must be UTF8). Applications using TLS-PSK may left out it or use it
for any action (for example SUPL uses it to indicate the SUPL protocol version
and to present a list of allowed PSK generators).
- The TLS stack
on the client calls ptrToKeyHandler->getPskL()
The TLS stack on the client calls getPskL() for the instance of the
key handler (in this case ptrToKeyHandler). See MSoPskKeyHandler::
GetPskL() for the prototype. This call returns the PSK identity
and value to be used to secure the connection.
- The TLS stack
sends the PSK identity to the server.
The TLS stack sends the PSK identity (chosen in Step 2) to the server
so it can retrieve the matching PSK value to secure the connection.
After the client has chosen which PSK to use, it sends an identity to
the server and the server can use this to obtain a matching PSK. Again the
meaning of the identity field is not specified, but its format must be UTF8.
An application may choose to use it or leave it empty.
Note: In the example, the server must select a PSK ciphersuite, because
the client provides only PSK ciphersuites. The connection fails, if the server
selects a PSK ciphersuite and fails to get a key that matches with the client.
The TLS assumes that the first common ciphersuite cannot fail and does not
implement connection retry.
TLS_PSK example
The following example code shows
how to configure TLS_PSK:
//Configure a PSK key handler
TPckgBuf<MSoPskKeyHandler *> pskConfigPkg;
pskConfigPkg() = ptrToKeyHandler;
User::LeaveIfError(secureSocket->SetOpt(KSoPskConfig, KSolInetSSL, pskConfigPkg));
//set available ciphersuites
TBuf8<8> buf;
for(TInt i=0; i<4; ++i)
{
// The supported PSK ciphersuites are as follows:-
// TLS_PSK_WITH_RC4_128_SHA = { 0x00, 0x8A };
// TLS_PSK_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x8B };
// TLS_PSK_WITH_AES_128_CBC_SHA = { 0x00, 0x8C };
// TLS_PSK_WITH_AES_256_CBC_SHA = { 0x00, 0x8D };
buf[i*2]=0;
buf[i*2+1]=0x8a+i;
}
secureSocket->SetAvailableCipherSuites( buf );
//Start a connection
secureSocket->StartClientHandshake( iStatus );