summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%google.com <devnull@localhost>2008-02-02 00:03:09 +0000
committerwtc%google.com <devnull@localhost>2008-02-02 00:03:09 +0000
commitc143cc80be3f0ebb7a5ec566552502916619f333 (patch)
treedb161e593d7131164708443f5e9b6c58d6a302a5
parent873cba8a2efe63c02b7c7f49461bf2cf48fa682a (diff)
downloadnss-hg-c143cc80be3f0ebb7a5ec566552502916619f333.tar.gz
Bug 403563: checked in Nagendra's proposed patch v5, plus
- shorten SSL_ENABLE_SESSION_TICKET_EXTENSION to SSL_ENABLE_SESSION_TICKETS - fix compiler warnings about PK11_CipherOp calls Modified Files: Tag: NSS_RFC4507BIS_BRANCH cmd/selfserv/selfserv.c cmd/strsclnt/strsclnt.c cmd/tstclnt/tstclnt.c lib/ssl/ssl.h lib/ssl/ssl3ext.c lib/ssl/ssl3prot.h lib/ssl/sslimpl.h lib/ssl/sslsnce.c lib/ssl/sslsock.c
-rw-r--r--security/nss/cmd/selfserv/selfserv.c2
-rw-r--r--security/nss/cmd/strsclnt/strsclnt.c4
-rw-r--r--security/nss/cmd/tstclnt/tstclnt.c2
-rw-r--r--security/nss/lib/ssl/ssl.h4
-rw-r--r--security/nss/lib/ssl/ssl3ext.c181
-rw-r--r--security/nss/lib/ssl/ssl3prot.h6
-rw-r--r--security/nss/lib/ssl/sslimpl.h10
-rw-r--r--security/nss/lib/ssl/sslsnce.c225
-rw-r--r--security/nss/lib/ssl/sslsock.c8
9 files changed, 363 insertions, 79 deletions
diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c
index d70743c65..09dc360d7 100644
--- a/security/nss/cmd/selfserv/selfserv.c
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -1451,7 +1451,7 @@ server_main(
}
}
if (enableSessionTicketExtension) {
- rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKET_EXTENSION,
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_SESSION_TICKETS,
PR_TRUE);
if (rv != SECSuccess) {
errExit("error enabling Session Ticket extension ");
diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c
index 540b8bafc..61d33da0d 100644
--- a/security/nss/cmd/strsclnt/strsclnt.c
+++ b/security/nss/cmd/strsclnt/strsclnt.c
@@ -1238,9 +1238,9 @@ client_main(
if (enableSessionTicketExtension) {
rv = SSL_OptionSet(model_sock,
- SSL_ENABLE_SESSION_TICKET_EXTENSION, PR_TRUE);
+ SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
if (rv != SECSuccess)
- errExit("SSL_OptionSet SSL_ENABLE_SESSION_TICKET_EXTENSION");
+ errExit("SSL_OptionSet SSL_ENABLE_SESSION_TICKETS");
}
SSL_SetURL(model_sock, hostName);
diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c
index 5a4172d37..aa576573f 100644
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -837,7 +837,7 @@ int main(int argc, char **argv)
}
/* enable Session Ticket extension. */
- rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKET_EXTENSION,
+ rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS,
enableSessionTicketExtension);
if (rv != SECSuccess) {
SECU_PrintError(progName, "error enabling Session Ticket extension");
diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h
index 06179409d..a0811c8ce 100644
--- a/security/nss/lib/ssl/ssl.h
+++ b/security/nss/lib/ssl/ssl.h
@@ -112,8 +112,8 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd);
/* step-down keys if needed. */
#define SSL_BYPASS_PKCS11 16 /* use PKCS#11 for pub key only */
#define SSL_NO_LOCKS 17 /* Don't use locks for protection */
-#define SSL_ENABLE_SESSION_TICKET_EXTENSION 18 /* Enable TLS1 SessionTicket *
- * extension (off by default) */
+#define SSL_ENABLE_SESSION_TICKETS 18 /* Enable TLS1 SessionTicket *
+ * extension (off by default) */
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
diff --git a/security/nss/lib/ssl/ssl3ext.c b/security/nss/lib/ssl/ssl3ext.c
index 6f47b6ff9..27c47b245 100644
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -50,12 +50,14 @@
#include "pk11pub.h"
#include "blapi.h"
+static uint8 key_name[SESS_TICKET_KEY_NAME_LEN];
static PK11SymKey *session_ticket_enc_key_pkcs11 = NULL;
static PK11SymKey *session_ticket_mac_key_pkcs11 = NULL;
-static PRCallOnceType generate_session_keys_once_pkcs11;
static unsigned char session_ticket_enc_key[32];
static unsigned char session_ticket_mac_key[SHA256_LENGTH];
+
+static PRBool session_ticket_keys_initialized = PR_FALSE;
static PRCallOnceType generate_session_keys_once;
static PRInt32 ssl3_SendServerNameExt(sslSocket * ss,
@@ -66,7 +68,11 @@ static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
PRUint32 bytes);
static SECStatus ssl3_AppendNumberToItem(SECItem *item, PRUint32 num,
PRInt32 lenSize);
-
+static SECStatus ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss,
+ PK11SymKey **aes_key, PK11SymKey **mac_key);
+static SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
+ PRUint32 *aes_key_length, const unsigned char **mac_key,
+ PRUint32 *mac_key_length);
/*
* Write bytes. Using this function means the SECItem structure
@@ -121,37 +127,38 @@ static SECStatus ssl3_SessionTicketShutdown(void* appData, void* nssData)
PK11_FreeSymKey(session_ticket_mac_key_pkcs11);
session_ticket_mac_key_pkcs11 = NULL;
}
- memset(&generate_session_keys_once_pkcs11, 0, sizeof(PRCallOnceType));
+ PORT_Memset(&generate_session_keys_once, 0,
+ sizeof(generate_session_keys_once));
return SECSuccess;
}
+
static PRStatus
-ssl3_GenerateSessionTicketKeysPKCS11(void)
+ssl3_GenerateSessionTicketKeysPKCS11(void *data)
{
- PK11SlotInfo *slot;
SECStatus rv;
- CK_MECHANISM_TYPE mechanism_array[2];
-
- slot = PK11_GetBestSlot(CKM_AES_CBC, NULL);
- /* no parameter, 128-bit key size */
- session_ticket_enc_key_pkcs11 =
- PK11_KeyGen(slot, CKM_AES_KEY_GEN, NULL, 16, NULL);
- PK11_FreeSlot(slot);
- if (!session_ticket_enc_key_pkcs11)
- return PR_FAILURE;
+ sslSocket *ss = (sslSocket *)data;
+ SECKEYPrivateKey *svrPrivKey = ss->serverCerts[kt_rsa].SERVERKEY;
+ SECKEYPublicKey *svrPubKey = ss->serverCerts[kt_rsa].serverKeyPair->pubKey;
- mechanism_array[0] = CKM_SHA256_HMAC;
- mechanism_array[1] = CKM_GENERIC_SECRET_KEY_GEN;
- slot = PK11_GetBestSlotMultiple(mechanism_array, 2, NULL);
- /* no parameter, 256-bit key size */
- session_ticket_mac_key_pkcs11 =
- PK11_KeyGen(slot, CKM_GENERIC_SECRET_KEY_GEN, NULL, 32, NULL);
- PK11_FreeSlot(slot);
- if (!session_ticket_mac_key_pkcs11)
+ if (svrPrivKey == NULL || svrPubKey == NULL) {
+ SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.",
+ SSL_GETPID(), ss->fd));
goto loser;
+ }
+
+ /* Get a copy of the session keys from shared memory. */
+ PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
+ sizeof(SESS_TICKET_KEY_NAME_PREFIX));
+ if (!ssl_GetSessionTicketKeysPKCS11(svrPrivKey, svrPubKey, ss->pkcs11PinArg,
+ &key_name[4], &session_ticket_enc_key_pkcs11,
+ &session_ticket_mac_key_pkcs11))
+ return PR_FAILURE;
+
rv = NSS_RegisterShutdown(ssl3_SessionTicketShutdown, NULL);
if (rv != SECSuccess)
goto loser;
+
return PR_SUCCESS;
loser:
@@ -159,41 +166,47 @@ loser:
return PR_FAILURE;
}
-SECStatus
-ssl3_GetSessionTicketKeysPKCS11(PK11SymKey **aes_key, PK11SymKey **mac_key)
+static SECStatus
+ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss, PK11SymKey **aes_key,
+ PK11SymKey **mac_key)
{
- PRStatus rv;
- rv = PR_CallOnce(&generate_session_keys_once_pkcs11,
- ssl3_GenerateSessionTicketKeysPKCS11);
- if (rv != PR_SUCCESS)
+ if (PR_CallOnceWithArg(&generate_session_keys_once,
+ ssl3_GenerateSessionTicketKeysPKCS11, ss) != PR_SUCCESS)
+ return SECFailure;
+
+ if (session_ticket_enc_key_pkcs11 == NULL ||
+ session_ticket_mac_key_pkcs11 == NULL)
return SECFailure;
*aes_key = session_ticket_enc_key_pkcs11;
*mac_key = session_ticket_mac_key_pkcs11;
-
return SECSuccess;
}
static PRStatus
ssl3_GenerateSessionTicketKeys(void)
{
- SECStatus rv = PK11_GenerateRandom(session_ticket_enc_key,
- sizeof(session_ticket_enc_key));
- if (rv != SECSuccess) return PR_FAILURE;
- rv = PK11_GenerateRandom(session_ticket_mac_key,
- sizeof(session_ticket_mac_key));
- return rv == SECSuccess ? PR_SUCCESS : PR_FAILURE;
+ PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
+ sizeof(SESS_TICKET_KEY_NAME_PREFIX));
+
+ if (!ssl_GetSessionTicketKeys(&key_name[4], session_ticket_enc_key,
+ session_ticket_mac_key))
+ return PR_FAILURE;
+
+ session_ticket_keys_initialized = PR_TRUE;
+ return PR_SUCCESS;
}
-SECStatus
+static SECStatus
ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
PRUint32 *aes_key_length, const unsigned char **mac_key,
PRUint32 *mac_key_length)
{
- PRStatus rv;
- rv = PR_CallOnce(&generate_session_keys_once,
- ssl3_GenerateSessionTicketKeys);
- if (rv != PR_SUCCESS)
+ if (PR_CallOnce(&generate_session_keys_once,
+ ssl3_GenerateSessionTicketKeys) != SECSuccess)
+ return SECFailure;
+
+ if (!session_ticket_keys_initialized)
return SECFailure;
*aes_key = session_ticket_enc_key;
@@ -462,7 +475,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
&mac_key, &mac_key_length);
} else {
- rv = ssl3_GetSessionTicketKeysPKCS11(&aes_key_pkcs11,
+ rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
&mac_key_pkcs11);
}
if (rv != SECSuccess) goto loser;
@@ -521,7 +534,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
message_length =
sizeof(ticket.ticket_lifetime_hint) /* ticket_lifetime_hint */
+ 2 /* length field for NewSessionTicket.ticket */
- + sizeof(TLS1_EX_SESS_TICKET_KEY_NAME) /* key_name */
+ + SESS_TICKET_KEY_NAME_LEN /* key_name */
+ AES_BLOCK_SIZE /* iv */
+ 2 /* length field for NewSessionTicket.ticket.encrypted_state */
+ ciphertext_length /* encrypted_state */
@@ -621,7 +634,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
if (!aes_ctx_pkcs11)
goto loser;
- rv = PK11_CipherOp(aes_ctx_pkcs11, ciphertext.data, &ciphertext.len,
+ rv = PK11_CipherOp(aes_ctx_pkcs11, ciphertext.data, (int *)&ciphertext.len,
ciphertext.len, plaintext_item.data, plaintext_item.len);
PK11_Finalize(aes_ctx_pkcs11);
PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
@@ -641,8 +654,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
goto loser;
HMAC_Begin(hmac_ctx);
- HMAC_Update(hmac_ctx, (unsigned char *)TLS1_EX_SESS_TICKET_KEY_NAME,
- sizeof(TLS1_EX_SESS_TICKET_KEY_NAME));
+ HMAC_Update(hmac_ctx, key_name, SESS_TICKET_KEY_NAME_LEN);
HMAC_Update(hmac_ctx, iv, sizeof(iv));
HMAC_Update(hmac_ctx, (unsigned char *)length_buf, 2);
HMAC_Update(hmac_ctx, ciphertext.data, ciphertext.len);
@@ -658,9 +670,8 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
goto loser;
rv = PK11_DigestBegin(hmac_ctx_pkcs11);
- rv = PK11_DigestOp(hmac_ctx_pkcs11,
- (unsigned char *)TLS1_EX_SESS_TICKET_KEY_NAME,
- sizeof(TLS1_EX_SESS_TICKET_KEY_NAME));
+ rv = PK11_DigestOp(hmac_ctx_pkcs11, key_name,
+ SESS_TICKET_KEY_NAME_LEN);
rv = PK11_DigestOp(hmac_ctx_pkcs11, iv, sizeof(iv));
rv = PK11_DigestOp(hmac_ctx_pkcs11, (unsigned char *)length_buf, 2);
rv = PK11_DigestOp(hmac_ctx_pkcs11, ciphertext.data, ciphertext.len);
@@ -682,9 +693,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
message_length - sizeof(ticket.ticket_lifetime_hint) - 2, 2);
if (rv != SECSuccess) goto loser;
- rv = ssl3_AppendHandshake(ss,
- (unsigned char *)TLS1_EX_SESS_TICKET_KEY_NAME,
- sizeof(TLS1_EX_SESS_TICKET_KEY_NAME));
+ rv = ssl3_AppendHandshake(ss, key_name, SESS_TICKET_KEY_NAME_LEN);
if (rv != SECSuccess) goto loser;
rv = ssl3_AppendHandshake(ss, iv, sizeof(iv));
@@ -750,6 +759,12 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
unsigned char computed_mac[TLS1_EX_SESS_TICKET_MAC_LENGTH];
unsigned int computed_mac_length;
const SECHashObject *hashObj;
+ const unsigned char *aes_key;
+ const unsigned char *mac_key;
+ PK11SymKey *aes_key_pkcs11;
+ PK11SymKey *mac_key_pkcs11;
+ PRUint32 aes_key_length;
+ PRUint32 mac_key_length;
PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
HMACContext *hmac_ctx;
PK11Context *hmac_ctx_pkcs11;
@@ -783,13 +798,37 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
!= SECSuccess)
return SECFailure;
+ /* Get session ticket keys. */
+ if (ss->opt.bypassPKCS11) {
+ rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
+ &mac_key, &mac_key_length);
+ } else {
+ rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
+ &mac_key_pkcs11);
+ }
+ if (rv != SECSuccess) {
+ SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.",
+ SSL_GETPID(), ss->fd));
+ goto no_ticket;
+ }
+
+ /* If the ticket sent by the client was generated under a key different
+ * from the one we have, bypass ticket processing.
+ */
+ if (PORT_Memcmp(enc_session_ticket.key_name, key_name,
+ SESS_TICKET_KEY_NAME_LEN) != 0) {
+ SSL_DBG(("%d: SSL[%d]: Session ticket key_name sent mismatch.",
+ SSL_GETPID(), ss->fd));
+ goto no_ticket;
+ }
+
/* Verify the MAC on the ticket. MAC verification may also
* fail if the MAC key has been recently refreshed.
*/
if (ss->opt.bypassPKCS11) {
hmac_ctx = (HMACContext *)hmac_ctx_buf;
hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
- if (HMAC_Init(hmac_ctx, hashObj, session_ticket_mac_key,
+ if (HMAC_Init(hmac_ctx, hashObj, mac_key,
sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess)
goto no_ticket;
HMAC_Begin(hmac_ctx);
@@ -803,9 +842,15 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
macParam.data = NULL;
macParam.len = 0;
hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
- CKA_SIGN, session_ticket_mac_key_pkcs11, &macParam);
- if (!hmac_ctx_pkcs11)
+ CKA_SIGN, mac_key_pkcs11, &macParam);
+ if (!hmac_ctx_pkcs11) {
+ SSL_DBG(("%d: SSL[%d]: Unable to create HMAC context: %d.",
+ SSL_GETPID(), ss->fd, PORT_GetError()));
goto no_ticket;
+ } else {
+ SSL_DBG(("%d: SSL[%d]: Successfully created HMAC context.",
+ SSL_GETPID(), ss->fd));
+ }
rv = PK11_DigestBegin(hmac_ctx_pkcs11);
rv = PK11_DigestOp(hmac_ctx_pkcs11, extension_data.data,
extension_data.len - TLS1_EX_SESS_TICKET_MAC_LENGTH);
@@ -820,8 +865,11 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
goto no_ticket;
}
if (PORT_Memcmp(computed_mac, enc_session_ticket.mac,
- computed_mac_length) != 0)
+ computed_mac_length) != 0) {
+ SSL_DBG(("%d: SSL[%d]: Session ticket MAC mismatch.",
+ SSL_GETPID(), ss->fd));
goto no_ticket;
+ }
/* We ignore key_name for now.
* This is ok as MAC verification succeeded.
@@ -835,11 +883,14 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
if (ss->opt.bypassPKCS11) {
aes_ctx = (AESContext *)aes_ctx_buf;
- rv = AES_InitContext(aes_ctx, session_ticket_enc_key,
+ rv = AES_InitContext(aes_ctx, aes_key,
sizeof(session_ticket_enc_key), enc_session_ticket.iv,
NSS_AES_CBC, 0,AES_BLOCK_SIZE);
- if (rv != SECSuccess)
+ if (rv != SECSuccess) {
+ SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
+ SSL_GETPID(), ss->fd));
goto no_ticket;
+ }
rv = AES_Decrypt(aes_ctx, decrypted_state->data,
&decrypted_state->len, decrypted_state->len,
@@ -852,12 +903,15 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
ivItem.data = enc_session_ticket.iv;
ivItem.len = AES_BLOCK_SIZE;
aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
- CKA_DECRYPT, session_ticket_enc_key_pkcs11, &ivItem);
- if (!aes_ctx_pkcs11)
+ CKA_DECRYPT, aes_key_pkcs11, &ivItem);
+ if (!aes_ctx_pkcs11) {
+ SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
+ SSL_GETPID(), ss->fd));
goto no_ticket;
+ }
rv = PK11_CipherOp(aes_ctx_pkcs11, decrypted_state->data,
- &decrypted_state->len, decrypted_state->len,
+ (int *)&decrypted_state->len, decrypted_state->len,
enc_session_ticket.encrypted_state.data,
enc_session_ticket.encrypted_state.len);
PK11_Finalize(aes_ctx_pkcs11);
@@ -985,7 +1039,8 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
* memory since the ticket is of no use.
*/
if (parsed_session_ticket->timestamp != 0 &&
- parsed_session_ticket->timestamp + TLS1_EX_SESS_TICKET_LIFETIME_HINT > ssl_Time()) {
+ parsed_session_ticket->timestamp +
+ TLS1_EX_SESS_TICKET_LIFETIME_HINT > ssl_Time()) {
sid = ssl3_NewSessionID(ss, PR_TRUE);
if (sid == NULL) {
@@ -1039,6 +1094,8 @@ ssl3_ServerHandleSessionTicketExt(sslSocket *ss, PRUint16 ex_type,
if (0) {
no_ticket:
+ SSL_DBG(("%d: SSL[%d]: Session ticket parsing failed.",
+ SSL_GETPID(), ss->fd));
if (sid) {
ssl_FreeSID(sid);
sid = NULL;
@@ -1084,7 +1141,7 @@ ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data,
EncryptedSessionTicket *enc_session_ticket)
{
if (ssl3_ConsumeFromItem(data, &enc_session_ticket->key_name,
- sizeof(TLS1_EX_SESS_TICKET_KEY_NAME)) != SECSuccess)
+ SESS_TICKET_KEY_NAME_LEN) != SECSuccess)
return SECFailure;
if (ssl3_ConsumeFromItem(data, &enc_session_ticket->iv,
AES_BLOCK_SIZE) != SECSuccess)
diff --git a/security/nss/lib/ssl/ssl3prot.h b/security/nss/lib/ssl/ssl3prot.h
index 83ab67e7d..e45d18bd7 100644
--- a/security/nss/lib/ssl/ssl3prot.h
+++ b/security/nss/lib/ssl/ssl3prot.h
@@ -333,6 +333,10 @@ typedef struct {
} identity;
} ClientIdentity;
+#define SESS_TICKET_KEY_NAME_PREFIX "NSS!"
+#define SESS_TICKET_KEY_NAME_LEN 16
+#define SESS_TICKET_KEY_VAR_NAME_LEN 12
+
typedef struct {
unsigned char *key_name;
unsigned char *iv;
@@ -350,7 +354,7 @@ typedef enum {
session_ticket_xtn = 35
} ExtensionType;
-#define TLS1_EX_SESS_TICKET_KEY_NAME "NSS_SESS_TICKET!"
+
#define TLS1_EX_SESS_TICKET_MAC_LENGTH 32
#endif /* __ssl3proto_h_ */
diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h
index f9f2c33e1..7aacf4f98 100644
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -1479,14 +1479,14 @@ extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
/* Hello Extension related routines. */
extern PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type);
extern PRBool ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type);
-extern SECStatus ssl3_GetSessionTicketKeysPKCS11(PK11SymKey **aes_key,
- PK11SymKey **mac_key);
-extern SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
- PRUint32 *aes_key_length, const unsigned char **mac_key,
- PRUint32 *mac_key_length);
extern SECStatus ssl3_SetSIDSessionTicket(sslSessionID *sid,
NewSessionTicket *session_ticket);
extern SECStatus ssl3_SendNewSessionTicket(sslSocket *ss);
+extern PRBool ssl_GetSessionTicketKeys(uint8 *key_name, unsigned char *encKey,
+ unsigned char *macKey);
+extern PRBool ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
+ SECKEYPublicKey *svrPubKey, void *pwArg, unsigned char *keyName,
+ PK11SymKey **aesKey, PK11SymKey **macKey);
/* Tell clients to consider tickets valid for this long. */
#define TLS1_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */
diff --git a/security/nss/lib/ssl/sslsnce.c b/security/nss/lib/ssl/sslsnce.c
index f4df588e8..b5a7279ba 100644
--- a/security/nss/lib/ssl/sslsnce.c
+++ b/security/nss/lib/ssl/sslsnce.c
@@ -67,6 +67,10 @@
* sidCacheEntry sidCacheData[ numSIDCacheEntries];
* certCacheEntry certCacheData[numCertCacheEntries];
* SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
+ * uint8 keyNameSuffix[SESS_TICKET_KEY_VAR_NAME_LEN]
+ * encKeyCacheEntry ticketEncKey; // Wrapped in non-bypass mode
+ * encKeyCacheEntry ticketMacKey; // Wrapped in non-bypass mode
+ * PRBool ticketKeysValid;
* } cacheMemCacheData;
*/
#include "nssrenam.h"
@@ -80,6 +84,7 @@
#include "sslproto.h"
#include "pk11func.h"
#include "base64.h"
+#include "keyhi.h"
#include <stdio.h>
@@ -177,6 +182,12 @@ struct sidCacheSetStr {
};
typedef struct sidCacheSetStr sidCacheSet;
+struct encKeyCacheEntryStr {
+ PRUint8 bytes[512];
+ PRInt32 length;
+};
+typedef struct encKeyCacheEntryStr encKeyCacheEntry;
+
struct cacheDescStr {
PRUint32 cacheMemSize;
@@ -213,6 +224,10 @@ struct cacheDescStr {
sidCacheEntry * sidCacheData;
certCacheEntry * certCacheData;
SSLWrappedSymWrappingKey * keyCacheData;
+ uint8 * ticketKeyNameSuffix;
+ encKeyCacheEntry * ticketEncKey;
+ encKeyCacheEntry * ticketMacKey;
+ PRUint32 * ticketKeysValid;
/* Only the private copies of these pointers are valid */
char * cacheMem;
@@ -998,9 +1013,27 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
+ cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
+
+ cache->ticketKeyNameSuffix = (uint8 *)ptr;
+ ptr = (ptrdiff_t)(cache->ticketKeyNameSuffix +
+ SESS_TICKET_KEY_VAR_NAME_LEN);
+ ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
+
+ cache->ticketEncKey = (encKeyCacheEntry *)ptr;
+ ptr = (ptrdiff_t)(cache->ticketEncKey + 1);
+ ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
+
+ cache->ticketMacKey = (encKeyCacheEntry *)ptr;
+ ptr = (ptrdiff_t)(cache->ticketMacKey + 1);
+ ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
+
+ cache->ticketKeysValid = (PRUint32 *)ptr;
+ ptr = (ptrdiff_t)(cache->ticketKeysValid + 1);
+ ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
+
cache->cacheMemSize = ptr;
- cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
if (ssl2_timeout) {
if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
@@ -1087,6 +1120,10 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
*(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
*(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
+ *(ptrdiff_t *)(&cache->ticketKeyNameSuffix) += ptr;
+ *(ptrdiff_t *)(&cache->ticketEncKey) += ptr;
+ *(ptrdiff_t *)(&cache->ticketMacKey) += ptr;
+ *(ptrdiff_t *)(&cache->ticketKeysValid) += ptr;
/* initialize the locks */
init_time = ssl_Time();
@@ -1366,6 +1403,10 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
*(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
*(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
+ *(ptrdiff_t *)(&cache->ticketKeyNameSuffix) += ptr;
+ *(ptrdiff_t *)(&cache->ticketEncKey) += ptr;
+ *(ptrdiff_t *)(&cache->ticketMacKey) += ptr;
+ *(ptrdiff_t *)(&cache->ticketKeysValid) += ptr;
cache->cacheMemMap = my.cacheMemMap;
cache->cacheMem = my.cacheMem;
@@ -1596,6 +1637,188 @@ ssl_GetWrappingKey( PRInt32 symWrapMechIndex,
return rv;
}
+PRBool
+ssl_GetSessionTicketKeys(uint8 *keyName, unsigned char *encKey,
+ unsigned char *macKey)
+{
+ PRBool rv = PR_FALSE;
+ PRUint32 now = 0;
+ cacheDesc *cache = &globalCache;
+
+ /* Grab lock. */
+ now = LockSidCacheLock(cache->keyCacheLock, now);
+ if (!now)
+ return rv;
+
+ if (!*(cache->ticketKeysValid)) {
+ if (PK11_GenerateRandom(cache->ticketKeyNameSuffix,
+ SESS_TICKET_KEY_VAR_NAME_LEN) != SECSuccess)
+ goto loser;
+ if (PK11_GenerateRandom(cache->ticketEncKey->bytes, 32) != SECSuccess)
+ goto loser;
+ if (PK11_GenerateRandom(cache->ticketMacKey->bytes,
+ SHA256_LENGTH) != SECSuccess)
+ goto loser;
+ *(cache->ticketKeysValid) = 1;
+ }
+
+ rv = PR_TRUE;
+
+ loser:
+ UnlockSidCacheLock(cache->keyCacheLock);
+ if (*(cache->ticketKeysValid)) {
+ PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
+ SESS_TICKET_KEY_VAR_NAME_LEN);
+ PORT_Memcpy(encKey, cache->ticketEncKey->bytes, 32);
+ PORT_Memcpy(macKey, cache->ticketMacKey->bytes, SHA256_LENGTH);
+ return PR_TRUE;
+ }
+ return rv;
+}
+
+PRBool
+ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
+ SECKEYPublicKey *svrPubKey, void *pwArg, unsigned char *keyName,
+ PK11SymKey **aesKey, PK11SymKey **macKey)
+{
+ PK11SlotInfo *slot;
+ PRUint32 now = 0;
+ CK_MECHANISM_TYPE mechanismArray[2];
+ PK11SymKey *aesKeyTmp = NULL;
+ PK11SymKey *macKeyTmp = NULL;
+ SECItem wrappedAesKey = {siBuffer, NULL, 0};
+ SECItem wrappedMacKey = {siBuffer, NULL, 0};
+ PRStatus rv = SECFailure;
+ cacheDesc *cache = &globalCache;
+
+ /* No need to grab a lock, we are reading. */
+ if (*(cache->ticketKeysValid)) {
+ wrappedAesKey.type = siBuffer;
+ wrappedAesKey.data = cache->ticketEncKey->bytes;
+ wrappedAesKey.len = cache->ticketEncKey->length;
+ PORT_Assert(wrappedAesKey.len <= sizeof(cache->ticketEncKey->bytes));
+ aesKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedAesKey,
+ CKM_AES_CBC, CKA_DECRYPT, 0);
+
+ wrappedMacKey.type = siBuffer;
+ wrappedMacKey.data = cache->ticketMacKey->bytes;
+ wrappedMacKey.len = cache->ticketMacKey->length;
+ PORT_Assert(wrappedMacKey.len <= sizeof(cache->ticketMacKey->bytes));
+ macKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedMacKey,
+ CKM_SHA256_HMAC, CKA_SIGN, 0);
+
+ if (aesKeyTmp == NULL || macKeyTmp == NULL) {
+ if (aesKeyTmp)
+ PK11_FreeSymKey(aesKeyTmp);
+ if (macKeyTmp)
+ PK11_FreeSymKey(macKeyTmp);
+ SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
+ SSL_GETPID(), "unknown"));
+ return PR_FALSE;
+ } else {
+ PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
+ SESS_TICKET_KEY_VAR_NAME_LEN);
+ *aesKey = aesKeyTmp;
+ *macKey = macKeyTmp;
+ SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
+ SSL_GETPID(), "unknown"));
+ return PR_TRUE;
+ }
+ }
+
+ /* Keys do not exist, create them. */
+ now = LockSidCacheLock(cache->keyCacheLock, now);
+ if (!now) {
+ SSL_DBG(("%d: SSL[%s]: Unable to grab keyCacheLock.",
+ SSL_GETPID(), "unknown"));
+ return PR_FALSE;
+ }
+
+ if (PK11_GenerateRandom(cache->ticketKeyNameSuffix,
+ SESS_TICKET_KEY_VAR_NAME_LEN) != SECSuccess) {
+ SSL_DBG(("%d: SSL[%s]: Unable to generate random key_name bytes.",
+ SSL_GETPID(), "unknown"));
+ goto loser;
+ }
+
+ mechanismArray[0] = CKM_AES_CBC;
+ mechanismArray[1] = CKM_SHA256_HMAC;
+
+ slot = PK11_GetBestSlotMultiple(mechanismArray, 2, pwArg);
+ aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL, 32, pwArg);
+ macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL, SHA256_LENGTH, pwArg);
+ PK11_FreeSlot(slot);
+
+ if (aesKeyTmp == NULL || macKeyTmp == NULL) {
+ SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
+ SSL_GETPID(), "unknown"));
+ goto loser;
+ }
+
+ /* Export the keys to the shared cache in wrapped form. */
+ wrappedAesKey.len = SECKEY_PublicKeyStrength(svrPubKey);
+ PORT_Assert(wrappedAesKey.len <= sizeof(cache->ticketEncKey->bytes));
+ if (wrappedAesKey.len > sizeof(cache->ticketEncKey->bytes))
+ goto loser;
+ wrappedAesKey.data = (unsigned char*)PORT_Alloc(wrappedAesKey.len);
+
+ if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey,
+ aesKeyTmp, &wrappedAesKey) != SECSuccess) {
+ SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket enc key.",
+ SSL_GETPID(), "unknown"));
+ goto loser;
+ }
+
+ wrappedMacKey.len = SECKEY_PublicKeyStrength(svrPubKey);
+ PORT_Assert(wrappedMacKey.len <= sizeof(cache->ticketMacKey->bytes));
+ if (wrappedMacKey.len > sizeof(cache->ticketMacKey->bytes))
+ goto loser;
+ wrappedMacKey.data = (unsigned char*)PORT_Alloc(wrappedMacKey.len);
+
+ if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey,
+ macKeyTmp, &wrappedMacKey) != SECSuccess) {
+ SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket mac key.",
+ SSL_GETPID(), "unknown"));
+ goto loser;
+ }
+
+ cache->ticketEncKey->length = wrappedAesKey.len;
+ cache->ticketMacKey->length = wrappedMacKey.len;
+
+ PORT_Memcpy(cache->ticketEncKey->bytes, wrappedAesKey.data,
+ wrappedAesKey.len);
+ PORT_Memcpy(cache->ticketMacKey->bytes, wrappedMacKey.data,
+ wrappedMacKey.len);
+ *(cache->ticketKeysValid) = 1;
+
+ PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
+ SESS_TICKET_KEY_VAR_NAME_LEN);
+ *aesKey = aesKeyTmp;
+ *macKey = macKeyTmp;
+ rv = SECSuccess;
+
+ loser:
+ UnlockSidCacheLock(cache->keyCacheLock);
+ if (wrappedAesKey.data)
+ SECITEM_FreeItem(&wrappedAesKey, PR_FALSE);
+ if (wrappedMacKey.data)
+ SECITEM_FreeItem(&wrappedMacKey, PR_FALSE);
+
+ if (rv != SECSuccess) {
+ if (aesKeyTmp) {
+ PK11_FreeSymKey(aesKeyTmp);
+ aesKeyTmp = NULL;
+ }
+ if (macKeyTmp) {
+ PK11_FreeSymKey(macKeyTmp);
+ aesKeyTmp = NULL;
+ }
+ return PR_FALSE;
+ } else {
+ return PR_TRUE;
+ }
+}
+
/* The caller passes in the new value it wants
* to set. This code tests the wrapped sym key entry in the shared memory.
* If it is uninitialized, this function writes the caller's value into
diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c
index 4354eece6..cbd735606 100644
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -700,7 +700,7 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
}
break;
- case SSL_ENABLE_SESSION_TICKET_EXTENSION:
+ case SSL_ENABLE_SESSION_TICKETS:
ss->opt.enableSessionTicketExtension = on;
break;
@@ -759,7 +759,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
case SSL_NO_STEP_DOWN: on = ss->opt.noStepDown; break;
case SSL_BYPASS_PKCS11: on = ss->opt.bypassPKCS11; break;
case SSL_NO_LOCKS: on = ss->opt.noLocks; break;
- case SSL_ENABLE_SESSION_TICKET_EXTENSION:
+ case SSL_ENABLE_SESSION_TICKETS:
on = ss->opt.enableSessionTicketExtension;
break;
default:
@@ -802,7 +802,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
case SSL_NO_STEP_DOWN: on = ssl_defaults.noStepDown; break;
case SSL_BYPASS_PKCS11: on = ssl_defaults.bypassPKCS11; break;
case SSL_NO_LOCKS: on = ssl_defaults.noLocks; break;
- case SSL_ENABLE_SESSION_TICKET_EXTENSION:
+ case SSL_ENABLE_SESSION_TICKETS:
on = ssl_defaults.enableSessionTicketExtension;
break;
@@ -932,7 +932,7 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
}
break;
- case SSL_ENABLE_SESSION_TICKET_EXTENSION:
+ case SSL_ENABLE_SESSION_TICKETS:
ssl_defaults.enableSessionTicketExtension = on;
break;