Files
mars-matrixssl/matrixssl/tls.c
Janne Johansson 83bff65b84 MatrixSSL 3.9.5
2017-12-13 16:23:52 +02:00

1730 lines
44 KiB
C

/**
* @file tls.c
* @version $Format:%h%d$
*
* TLS (SSLv3.1+) specific code.
* http://www.faqs.org/rfcs/rfc2246.html
* Primarily dealing with secret generation, message authentication codes
* and handshake hashing.
*/
/*
* Copyright (c) 2013-2017 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#include "matrixsslImpl.h"
#ifdef USE_NATIVE_TLS_ALGS
/******************************************************************************/
# ifdef USE_TLS
/******************************************************************************/
# define LABEL_SIZE 13
# define LABEL_MASTERSEC "master secret"
# define LABEL_KEY_BLOCK "key expansion"
# define LABEL_EXT_SIZE 22
# define LABEL_EXT_MASTERSEC "extended master secret"
static int32_t genKeyBlock(ssl_t *ssl)
{
unsigned char msSeed[SSL_HS_RANDOM_SIZE * 2 + LABEL_SIZE];
uint32 reqKeyLen;
int32_t rc = PS_FAIL;
memcpy(msSeed, LABEL_KEY_BLOCK, LABEL_SIZE);
memcpy(msSeed + LABEL_SIZE, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
memcpy(msSeed + LABEL_SIZE + SSL_HS_RANDOM_SIZE,
ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE);
/* We must generate enough key material to fill the various keys */
reqKeyLen = 2 * ssl->cipher->macSize +
2 * ssl->cipher->keySize +
2 * ssl->cipher->ivSize;
# ifdef USE_EAP_FAST
/**
Generate master secret with tprf.
Make space for additional key material (session key seed).
@see https://tools.ietf.org/html/rfc4851#section-5.1
*/
if (ssl->flags & SSL_FLAGS_EAP_FAST)
{
if (ssl->sid == NULL)
{
goto L_RETURN;
}
/* sid->masterSecret actually holds pac-key. Use tprf() here
to derive session masterSecret, now that we're about to use it.
masterSecret is also used after this for the finished message hash */
rc = tprf(ssl->sid->masterSecret, EAP_FAST_PAC_KEY_LEN,
msSeed + LABEL_SIZE, 2 * SSL_HS_RANDOM_SIZE,
ssl->sec.masterSecret);
if (rc < 0)
{
goto L_RETURN;
}
reqKeyLen += EAP_FAST_SESSION_KEY_SEED_LEN;
}
# endif
/* Ensure there's enough room */
if (reqKeyLen > SSL_MAX_KEY_BLOCK_SIZE)
{
rc = PS_MEM_FAIL;
goto L_RETURN;
}
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2)
{
if ((rc = prf2(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.keyBlock,
reqKeyLen, ssl->cipher->flags)) < 0)
{
goto L_RETURN;
}
}
# ifndef USE_ONLY_TLS_1_2
else
{
if ((rc = prf(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.keyBlock,
reqKeyLen)) < 0)
{
goto L_RETURN;
}
}
# endif
# else
if ((rc = prf(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.keyBlock,
reqKeyLen)) < 0)
{
goto L_RETURN;
}
# endif
if (ssl->flags & SSL_FLAGS_SERVER)
{
ssl->sec.rMACptr = ssl->sec.keyBlock;
ssl->sec.wMACptr = ssl->sec.rMACptr + ssl->cipher->macSize;
ssl->sec.rKeyptr = ssl->sec.wMACptr + ssl->cipher->macSize;
ssl->sec.wKeyptr = ssl->sec.rKeyptr + ssl->cipher->keySize;
ssl->sec.rIVptr = ssl->sec.wKeyptr + ssl->cipher->keySize;
ssl->sec.wIVptr = ssl->sec.rIVptr + ssl->cipher->ivSize;
# ifdef USE_EAP_FAST
if (ssl->flags & SSL_FLAGS_EAP_FAST)
{
ssl->sec.eap_fast_session_key_seed = ssl->sec.wIVptr + ssl->cipher->ivSize;
}
# endif
}
else
{
ssl->sec.wMACptr = ssl->sec.keyBlock;
ssl->sec.rMACptr = ssl->sec.wMACptr + ssl->cipher->macSize;
ssl->sec.wKeyptr = ssl->sec.rMACptr + ssl->cipher->macSize;
ssl->sec.rKeyptr = ssl->sec.wKeyptr + ssl->cipher->keySize;
ssl->sec.wIVptr = ssl->sec.rKeyptr + ssl->cipher->keySize;
ssl->sec.rIVptr = ssl->sec.wIVptr + ssl->cipher->ivSize;
# ifdef USE_EAP_FAST
if (ssl->flags & SSL_FLAGS_EAP_FAST)
{
ssl->sec.eap_fast_session_key_seed = ssl->sec.rIVptr + ssl->cipher->ivSize;
}
# endif
}
rc = SSL_HS_MASTER_SIZE;
L_RETURN:
memzero_s(msSeed, sizeof(msSeed));
if (rc < 0)
{
memzero_s(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE);
memzero_s(ssl->sec.keyBlock, SSL_MAX_KEY_BLOCK_SIZE);
}
return rc;
}
/******************************************************************************/
/*
* Generates all key material.
*/
int32_t tlsDeriveKeys(ssl_t *ssl)
{
unsigned char msSeed[SSL_HS_RANDOM_SIZE * 2 + LABEL_SIZE];
int32_t rc = PS_FAIL;
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1)
{
/* The keyblock is still valid from the first pass */
return SSL_HS_MASTER_SIZE;
}
# endif
/*
If this session is resumed, we want to reuse the master secret to
regenerate the key block with the new random values.
*/
if (ssl->flags & SSL_FLAGS_RESUMED)
{
return genKeyBlock(ssl);
}
# ifdef USE_EAP_FAST
/* We should only do EAP_FAST key derivation on resumed connections */
if (ssl->flags & SSL_FLAGS_EAP_FAST)
{
return PS_FAIL;
}
# endif
/*
master_secret = PRF(pre_master_secret, "master secret",
client_random + server_random);
*/
memcpy(msSeed, LABEL_MASTERSEC, LABEL_SIZE);
memcpy(msSeed + LABEL_SIZE, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
memcpy(msSeed + LABEL_SIZE + SSL_HS_RANDOM_SIZE,
ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE);
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2)
{
if ((rc = prf2(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.masterSecret,
SSL_HS_MASTER_SIZE, ssl->cipher->flags)) < 0)
{
return rc;
}
# ifndef USE_ONLY_TLS_1_2
}
else
{
if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.masterSecret,
SSL_HS_MASTER_SIZE)) < 0)
{
return rc;
}
# endif
}
# else
if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.masterSecret,
SSL_HS_MASTER_SIZE)) < 0)
{
return rc;
}
# endif
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS)
{
/*
May need premaster for retransmits. DTLS will free this when handshake
is known to be complete
*/
return genKeyBlock(ssl);
}
# endif /* USE_DTLS */
/*
premaster is now allocated for DH reasons. Can free here
*/
psFree(ssl->sec.premaster, ssl->hsPool);
ssl->sec.premaster = NULL;
ssl->sec.premasterSize = 0;
return genKeyBlock(ssl);
}
/* Master secret generation if extended_master_secret extension is used */
int32_t tlsExtendedDeriveKeys(ssl_t *ssl)
{
unsigned char msSeed[SHA384_HASHLEN + LABEL_EXT_SIZE];
unsigned char hash[SHA384_HASHLEN];
uint32_t outLen;
int32_t rc = PS_FAIL;
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1)
{
/* The keyblock is still valid from the first pass */
return SSL_HS_MASTER_SIZE;
}
# endif
/*
If this session is resumed, we should reuse the master_secret to
regenerate the key block with the new random values. We should not
be here regenerating the master_secret!
*/
if (ssl->extFlags.extended_master_secret == 0 ||
ssl->flags & SSL_FLAGS_RESUMED)
{
psTraceInfo("Invalid invokation of extended key derivation.\n");
return PS_FAIL;
}
# ifdef USE_EAP_FAST
/* We should only do EAP_FAST key derivation on resumed connections */
if (ssl->flags & SSL_FLAGS_EAP_FAST)
{
return PS_FAIL;
}
# endif
extMasterSecretSnapshotHSHash(ssl, hash, &outLen);
/*
master_secret = PRF(pre_master_secret, "extended master secret",
session_hash);
*/
memcpy(msSeed, LABEL_EXT_MASTERSEC, LABEL_EXT_SIZE);
memcpy(msSeed + LABEL_EXT_SIZE, hash, outLen);
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2)
{
if ((rc = prf2(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
outLen + LABEL_EXT_SIZE, ssl->sec.masterSecret,
SSL_HS_MASTER_SIZE, ssl->cipher->flags)) < 0)
{
return rc;
}
# ifndef USE_ONLY_TLS_1_2
}
else
{
if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
outLen + LABEL_EXT_SIZE, ssl->sec.masterSecret,
SSL_HS_MASTER_SIZE)) < 0)
{
return rc;
}
# endif
}
# else
if ((rc = prf(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
outLen + LABEL_EXT_SIZE, ssl->sec.masterSecret,
SSL_HS_MASTER_SIZE)) < 0)
{
return rc;
}
# endif
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS)
{
/*
May need premaster for retransmits. DTLS will free this when handshake
is known to be complete
*/
return genKeyBlock(ssl);
}
# endif /* USE_DTLS */
/*
premaster is now allocated for DH reasons. Can free here
*/
psFree(ssl->sec.premaster, ssl->hsPool);
ssl->sec.premaster = NULL;
ssl->sec.premasterSize = 0;
return genKeyBlock(ssl);
}
# ifdef USE_SHA_MAC
# ifdef USE_SHA1
/******************************************************************************/
/*
TLS sha1 HMAC generate/verify
*/
int32_t tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type,
unsigned char *data, uint32 len, unsigned char *mac)
{
# ifndef USE_HMAC_TLS
psHmacSha1_t ctx;
# endif
unsigned char *key, *seq;
unsigned char majVer, minVer, tmp[5];
int32 i;
# ifdef USE_DTLS
unsigned char dtls_seq[8];
# endif /* USE_DTLS */
# ifdef USE_HMAC_TLS
uint32 alt_len;
# endif /* USE_HMAC_TLS */
majVer = ssl->majVer;
minVer = ssl->minVer;
if (mode == HMAC_CREATE)
{
key = ssl->sec.writeMAC;
seq = ssl->sec.seq;
}
else /* HMAC_VERIFY */
{
key = ssl->sec.readMAC;
seq = ssl->sec.remSeq;
}
/* Sanity */
if (key == NULL)
{
return PS_FAILURE;
}
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS)
{
if (mode == HMAC_CREATE)
{
seq = dtls_seq;
memcpy(dtls_seq, ssl->epoch, 2);
memcpy(dtls_seq + 2, ssl->rsn, 6);
}
else /* HMAC_VERIFY */
{
seq = dtls_seq;
memcpy(dtls_seq, ssl->rec.epoch, 2);
memcpy(dtls_seq + 2, ssl->rec.rsn, 6);
}
}
# endif /* USE_DTLS */
tmp[0] = type;
tmp[1] = majVer;
tmp[2] = minVer;
tmp[3] = (len & 0xFF00) >> 8;
tmp[4] = len & 0xFF;
# ifdef USE_HMAC_TLS
# ifdef USE_HMAC_TLS_LUCKY13_COUNTERMEASURE
/* Lucky13 counter measure is only used when receiving record.
Decrement 4 bytes of header from amount of ssl->rec to process. */
alt_len = mode == HMAC_CREATE || ssl->rec.len < len + 4? len : ssl->rec.len - 4;
# else
alt_len = len;
# endif
(void) psHmacSha1Tls(key, SHA1_HASH_SIZE,
seq, 8,
tmp, 5,
data, len, alt_len,
mac);
# else
if (psHmacSha1Init(&ctx, key, SHA1_HASH_SIZE) < 0)
{
return PS_FAIL;
}
psHmacSha1Update(&ctx, seq, 8);
psHmacSha1Update(&ctx, tmp, 5);
psHmacSha1Update(&ctx, data, len);
psHmacSha1Final(&ctx, mac);
# endif
/* Update seq (only for normal TLS) */
for (i = 7; i >= 0; i--)
{
seq[i]++;
if (seq[i] != 0)
{
break;
}
}
return PS_SUCCESS;
}
# endif /* USE_SHA1 */
# if defined(USE_HMAC_SHA256) || defined(USE_HMAC_SHA384)
/******************************************************************************/
/*
TLS sha256/sha384 HMAC generate/verify
*/
int32_t tlsHMACSha2(ssl_t *ssl, int32 mode, unsigned char type,
unsigned char *data, uint32 len, unsigned char *mac, int32 hashLen)
{
# ifndef USE_HMAC_TLS
psHmac_t ctx;
# endif
unsigned char *key, *seq;
unsigned char majVer, minVer, tmp[5];
int32 i;
# ifdef USE_DTLS
unsigned char dtls_seq[8];
# endif /* USE_DTLS */
# ifdef USE_HMAC_TLS
uint32 alt_len;
# endif /* USE_HMAC_TLS */
majVer = ssl->majVer;
minVer = ssl->minVer;
if (mode == HMAC_CREATE)
{
key = ssl->sec.writeMAC;
seq = ssl->sec.seq;
}
else /* HMAC_VERIFY */
{
key = ssl->sec.readMAC;
seq = ssl->sec.remSeq;
}
/* Sanity */
if (key == NULL)
{
return PS_FAILURE;
}
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS)
{
if (mode == HMAC_CREATE)
{
seq = dtls_seq;
memcpy(dtls_seq, ssl->epoch, 2);
memcpy(dtls_seq + 2, ssl->rsn, 6);
}
else /* HMAC_VERIFY */
{
seq = dtls_seq;
memcpy(dtls_seq, ssl->rec.epoch, 2);
memcpy(dtls_seq + 2, ssl->rec.rsn, 6);
}
}
# endif /* USE_DTLS */
tmp[0] = type;
tmp[1] = majVer;
tmp[2] = minVer;
tmp[3] = (len & 0xFF00) >> 8;
tmp[4] = len & 0xFF;
# ifdef USE_HMAC_TLS
# ifdef USE_HMAC_TLS_LUCKY13_COUNTERMEASURE
/* Lucky13 counter measure is only used when receiving record.
Decrement 4 bytes of header from amount of ssl->rec to process. */
alt_len = mode == HMAC_CREATE || ssl->rec.len < len + 4? len : ssl->rec.len - 4;
# else
alt_len = len;
# endif
(void) psHmacSha2Tls(key, hashLen,
seq, 8,
tmp, 5,
data, len, alt_len,
mac, hashLen);
# else
switch (hashLen)
{
case SHA256_HASHLEN:
if (psHmacInit(&ctx, HMAC_SHA256, key, hashLen) < 0)
{
return PS_FAIL;
}
break;
case SHA384_HASHLEN:
if (psHmacInit(&ctx, HMAC_SHA384, key, hashLen) < 0)
{
return PS_FAIL;
}
break;
default:
return PS_FAIL;
}
psHmacUpdate(&ctx, seq, 8);
psHmacUpdate(&ctx, tmp, 5);
psHmacUpdate(&ctx, data, len);
psHmacFinal(&ctx, mac);
# endif
/* Update seq (only for normal TLS) */
for (i = 7; i >= 0; i--)
{
seq[i]++;
if (seq[i] != 0)
{
break;
}
}
return PS_SUCCESS;
}
# endif /* USE_SHA256 || USE_SHA384 */
# endif /* USE_SHA_MAC */
# ifdef USE_MD5
# ifdef USE_MD5_MAC
/******************************************************************************/
/*
TLS MD5 HMAC generate/verify
*/
int32_t tlsHMACMd5(ssl_t *ssl, int32 mode, unsigned char type,
unsigned char *data, uint32 len, unsigned char *mac)
{
psHmacMd5_t ctx;
unsigned char *key, *seq;
unsigned char majVer, minVer, tmp[5];
int32 i;
majVer = ssl->majVer;
minVer = ssl->minVer;
if (mode == HMAC_CREATE)
{
key = ssl->sec.writeMAC;
seq = ssl->sec.seq;
}
else /* HMAC_VERIFY */
{
key = ssl->sec.readMAC;
seq = ssl->sec.remSeq;
}
/* Sanity */
if (key == NULL)
{
return PS_FAILURE;
}
if (psHmacMd5Init(&ctx, key, MD5_HASH_SIZE) < 0)
{
return PS_FAIL;
}
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS)
{
if (mode == HMAC_CREATE)
{
psHmacMd5Update(&ctx, ssl->epoch, 2);
psHmacMd5Update(&ctx, ssl->rsn, 6);
}
else /* HMAC_VERIFY */
{
psHmacMd5Update(&ctx, ssl->rec.epoch, 2);
psHmacMd5Update(&ctx, ssl->rec.rsn, 6);
}
}
else
{
# endif /* USE_DTLS */
psHmacMd5Update(&ctx, seq, 8);
for (i = 7; i >= 0; i--)
{
seq[i]++;
if (seq[i] != 0)
{
break;
}
}
# ifdef USE_DTLS
}
# endif /* USE_DTLS */
tmp[0] = type;
tmp[1] = majVer;
tmp[2] = minVer;
tmp[3] = (len & 0xFF00) >> 8;
tmp[4] = len & 0xFF;
psHmacMd5Update(&ctx, tmp, 5);
psHmacMd5Update(&ctx, data, len);
psHmacMd5Final(&ctx, mac);
return PS_SUCCESS;
}
# endif /* USE_MD5_MAC */
# endif /* USE_MD5 */
# endif /* USE_TLS */
int32 sslCreateKeys(ssl_t *ssl)
{
# ifdef USE_TLS
if (ssl->flags & SSL_FLAGS_TLS)
{
return tlsDeriveKeys(ssl);
}
else
{
# ifndef DISABLE_SSLV3
return sslDeriveKeys(ssl);
# else
return PS_ARG_FAIL;
# endif /* DISABLE_SSLV3 */
}
# else /* SSLv3 only below */
# ifndef DISABLE_SSLV3
return sslDeriveKeys(ssl);
# endif /* DISABLE_SSLV3 */
# endif /* USE_TLS */
}
/******************************************************************************/
/*
Cipher suites are chosen before they are activated with the
ChangeCipherSuite message. Additionally, the read and write cipher suites
are activated at different times in the handshake process. The following
APIs activate the selected cipher suite callback functions.
*/
int32 sslActivateReadCipher(ssl_t *ssl)
{
ssl->decrypt = ssl->cipher->decrypt;
ssl->verifyMac = ssl->cipher->verifyMac;
ssl->nativeDeMacSize = ssl->cipher->macSize;
if (ssl->extFlags.truncated_hmac)
{
if (ssl->cipher->macSize > 0) /* Only for HMAC-based ciphers */
{
ssl->deMacSize = 10;
}
else
{
ssl->deMacSize = ssl->cipher->macSize;
}
}
else
{
ssl->deMacSize = ssl->cipher->macSize;
}
ssl->deBlockSize = ssl->cipher->blockSize;
ssl->deIvSize = ssl->cipher->ivSize;
/*
Reset the expected incoming sequence number for the new suite
*/
memset(ssl->sec.remSeq, 0x0, sizeof(ssl->sec.remSeq));
if (ssl->cipher->ident != SSL_NULL_WITH_NULL_NULL)
{
/* Sanity */
if (ssl->sec.rMACptr == NULL)
{
psTraceInfo("sslActivateReadCipher sanity fail\n");
return PS_FAILURE;
}
ssl->flags |= SSL_FLAGS_READ_SECURE;
# ifdef USE_TLS_1_2
if (ssl->deMacSize == 0)
{
/* Need a concept for AEAD read and write start times for the
cases surrounding changeCipherSpec if moving from one suite
to another */
ssl->flags |= SSL_FLAGS_AEAD_R;
if (ssl->cipher->flags & CRYPTO_FLAGS_CHACHA)
{
ssl->flags &= ~SSL_FLAGS_NONCE_R;
}
else
{
ssl->flags |= SSL_FLAGS_NONCE_R;
}
}
else
{
ssl->flags &= ~SSL_FLAGS_AEAD_R;
ssl->flags &= ~SSL_FLAGS_NONCE_R;
}
# endif
/*
Copy the newly activated read keys into the live buffers
*/
memcpy(ssl->sec.readMAC, ssl->sec.rMACptr, ssl->deMacSize);
memcpy(ssl->sec.readKey, ssl->sec.rKeyptr, ssl->cipher->keySize);
memcpy(ssl->sec.readIV, ssl->sec.rIVptr, ssl->cipher->ivSize);
/*
set up decrypt contexts
*/
if (ssl->cipher->init)
{
if (ssl->cipher->init(&(ssl->sec), INIT_DECRYPT_CIPHER,
ssl->cipher->keySize) < 0)
{
psTraceInfo("Unable to initialize read cipher suite\n");
return PS_FAILURE;
}
}
}
return PS_SUCCESS;
}
int32 sslActivateWriteCipher(ssl_t *ssl)
{
# ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS)
{
if (ssl->retransmit == 0)
{
ssl->oencrypt = ssl->encrypt;
ssl->ogenerateMac = ssl->generateMac;
ssl->oenMacSize = ssl->enMacSize;
ssl->oenNativeHmacSize = ssl->nativeEnMacSize;
ssl->oenBlockSize = ssl->enBlockSize;
ssl->oenIvSize = ssl->enIvSize;
memcpy(ssl->owriteMAC, ssl->sec.writeMAC, ssl->enMacSize);
memcpy(&ssl->oencryptCtx, &ssl->sec.encryptCtx,
sizeof(psCipherContext_t));
memcpy(ssl->owriteIV, ssl->sec.writeIV, ssl->cipher->ivSize);
}
}
# endif /* USE_DTLS */
ssl->encrypt = ssl->cipher->encrypt;
ssl->generateMac = ssl->cipher->generateMac;
ssl->nativeEnMacSize = ssl->cipher->macSize;
if (ssl->extFlags.truncated_hmac)
{
if (ssl->cipher->macSize > 0) /* Only for HMAC-based ciphers */
{
ssl->enMacSize = 10;
}
else
{
ssl->enMacSize = ssl->cipher->macSize;
}
}
else
{
ssl->enMacSize = ssl->cipher->macSize;
}
ssl->enBlockSize = ssl->cipher->blockSize;
ssl->enIvSize = ssl->cipher->ivSize;
/*
Reset the outgoing sequence number for the new suite
*/
memset(ssl->sec.seq, 0x0, sizeof(ssl->sec.seq));
if (ssl->cipher->ident != SSL_NULL_WITH_NULL_NULL)
{
ssl->flags |= SSL_FLAGS_WRITE_SECURE;
# ifdef USE_TLS_1_2
if (ssl->enMacSize == 0)
{
/* Need a concept for AEAD read and write start times for the
cases surrounding changeCipherSpec if moving from one suite
to another */
ssl->flags |= SSL_FLAGS_AEAD_W;
if (ssl->cipher->flags & CRYPTO_FLAGS_CHACHA)
{
ssl->flags &= ~SSL_FLAGS_NONCE_W;
}
else
{
ssl->flags |= SSL_FLAGS_NONCE_W;
}
}
else
{
ssl->flags &= ~SSL_FLAGS_AEAD_W;
ssl->flags &= ~SSL_FLAGS_NONCE_W;
}
# endif
/*
Copy the newly activated write keys into the live buffers
*/
memcpy(ssl->sec.writeMAC, ssl->sec.wMACptr, ssl->enMacSize);
memcpy(ssl->sec.writeKey, ssl->sec.wKeyptr, ssl->cipher->keySize);
memcpy(ssl->sec.writeIV, ssl->sec.wIVptr, ssl->cipher->ivSize);
/*
set up encrypt contexts
*/
if (ssl->cipher->init)
{
if (ssl->cipher->init(&(ssl->sec), INIT_ENCRYPT_CIPHER,
ssl->cipher->keySize) < 0)
{
psTraceInfo("Unable to init write cipher suite\n");
return PS_FAILURE;
}
}
}
return PS_SUCCESS;
}
/******************************************************************************/
#endif /* USE_NATIVE_TLS_ALGS */
#ifdef USE_CLIENT_SIDE_SSL
/******************************************************************************/
/*
Allocate a tlsExtension_t structure
*/
int32 matrixSslNewHelloExtension(tlsExtension_t **extension, void *userPoolPtr)
{
psPool_t *pool = NULL;
tlsExtension_t *ext;
ext = psMalloc(pool, sizeof(tlsExtension_t));
if (ext == NULL)
{
return PS_MEM_FAIL;
}
memset(ext, 0x0, sizeof(tlsExtension_t));
ext->pool = pool;
*extension = ext;
return PS_SUCCESS;
}
/******************************************************************************/
/*
Free a tlsExtension_t structure and any extensions that have been loaded
*/
void matrixSslDeleteHelloExtension(tlsExtension_t *extension)
{
tlsExtension_t *next, *ext;
if (extension == NULL)
{
return;
}
ext = extension;
/* Free first one */
if (ext->extData)
{
psFree(ext->extData, ext->pool);
}
next = ext->next;
psFree(ext, ext->pool);
/* Free others */
while (next)
{
ext = next;
next = ext->next;
if (ext->extData)
{
psFree(ext->extData, ext->pool);
}
psFree(ext, ext->pool);
}
return;
}
/*****************************************************************************/
/*
Add an outgoing CLIENT_HELLO extension to a tlsExtension_t structure
that was previously allocated with matrixSslNewHelloExtension
*/
int32 matrixSslLoadHelloExtension(tlsExtension_t *ext,
unsigned char *extension, uint32 length, uint32 extType)
{
tlsExtension_t *current, *new;
if (ext == NULL || (length > 0 && extension == NULL))
{
return PS_ARG_FAIL;
}
/*
Find first empty spot in ext. This is determined by extLen since even
an empty extension will have a length of 1 for the 0
*/
current = ext;
while (current->extLen != 0)
{
if (current->next != NULL)
{
current = current->next;
continue;
}
new = psMalloc(ext->pool, sizeof(tlsExtension_t));
if (new == NULL)
{
return PS_MEM_FAIL;
}
memset(new, 0, sizeof(tlsExtension_t));
new->pool = ext->pool;
current->next = new;
current = new;
}
/*
Supports an empty extension which is really a one byte 00:
ff 01 00 01 00 (two byte type, two byte len, one byte 00)
This will either be passed in as a NULL 'extension' with a 0 length - OR -
A pointer to a one byte 0x0 and a length of 1. In either case, the
structure will identify the ext with a length of 1 and a NULL data ptr
*/
current->extType = extType;
if (length > 0)
{
current->extLen = length;
if (length == 1 && extension[0] == '\0')
{
current->extLen = 1;
}
else
{
current->extData = psMalloc(ext->pool, length);
if (current->extData == NULL)
{
return PS_MEM_FAIL;
}
memcpy(current->extData, extension, length);
}
}
else if (length == 0)
{
current->extLen = 1;
}
return PS_SUCCESS;
}
#endif /* USE_CLIENT_SIDE_SSL */
#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH)
#ifndef USE_ONLY_PSK_CIPHER_SUITE
/**
Return PS_TRUE if sigAlg is in peerSigAlgs, PS_FALSE otherwise.
peerSigAlgs should be the a set of masks we created after
parsing the peer's supported_signature_algorithms list
in ClientHello or CertificateRequest.
*/
psBool_t peerSupportsSigAlg(int32_t sigAlg,
uint16_t peerSigAlgs)
{
uint16_t yes;
if (sigAlg == OID_MD5_RSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_MD5_RSA_MASK) != 0);
}
else if (sigAlg == OID_SHA1_RSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA1_RSA_MASK) != 0);
}
else if (sigAlg == OID_SHA256_RSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA256_RSA_MASK) != 0);
}
else if (sigAlg == OID_SHA384_RSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA384_RSA_MASK) != 0);
}
else if (sigAlg == OID_SHA512_RSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA512_RSA_MASK) != 0);
}
else if (sigAlg == OID_SHA1_ECDSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA1_ECDSA_MASK) != 0);
}
else if (sigAlg == OID_SHA256_ECDSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA256_ECDSA_MASK) != 0);
}
else if (sigAlg == OID_SHA384_ECDSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA384_ECDSA_MASK) != 0);
}
else if (sigAlg == OID_SHA512_ECDSA_SIG)
{
yes = ((peerSigAlgs & HASH_SIG_SHA512_ECDSA_MASK) != 0);
}
else
{
return PS_FALSE; /* Unknown/unsupported sig alg. */
}
if (yes)
{
return PS_TRUE;
}
else
{
return PS_FALSE;
}
}
/**
Return PS_TRUE when we support sigAlg for signature generation,
PS_FALSE otherwise.
Compile-time switches as well as FIPS or non-FIPS mode is taken
into account.
@param[in] sigAlg The signature algorithm whose support is to
be checked.
@param[in] pubKeyAlgorithm The public key algorithm of our
private/public key pair (OID_RSA_KEY_ALG or OID_ECDSA_KEY_ALG.)
*/
psBool_t weSupportSigAlg(int32_t sigAlg,
int32_t pubKeyAlgorithm)
{
uint16_t we_support = 0;
uint16_t is_non_fips = 0; /* 1 if not allowed in FIPS mode for
signature generation. */
PS_VARIABLE_SET_BUT_UNUSED(is_non_fips);
#ifndef USE_RSA
if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
{
return PS_FALSE;
}
#endif
#ifndef USE_ECC
if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
{
return PS_FALSE;
}
#endif
if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
{
if (sigAlg == OID_MD2_RSA_SIG || sigAlg == OID_MD5_RSA_SIG)
{
/* No support for generating RSA-MD2 or RSA-MD5 signatures. */
is_non_fips = 1;
we_support = 0;
}
else if (sigAlg == OID_SHA1_RSA_SIG)
{
is_non_fips = 1;
#ifdef USE_SHA1
we_support = 1;
#endif
}
else if (sigAlg == OID_SHA256_RSA_SIG)
{
#ifdef USE_SHA256
we_support = 1;
#endif
}
else if (sigAlg == OID_SHA384_RSA_SIG)
{
#ifdef USE_SHA384
we_support = 1;
#endif
}
else if (sigAlg == OID_SHA512_RSA_SIG)
{
#ifdef USE_SHA512
we_support = 1;
#endif
}
else
{
/* Our key does not support this algorithm. */
return PS_FALSE;
}
}
else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
{
if (sigAlg == OID_SHA1_ECDSA_SIG)
{
#ifdef USE_SHA1
we_support = 1;
#endif
}
else if (sigAlg == OID_SHA256_ECDSA_SIG)
{
#ifdef USE_SHA256
we_support = 1;
#endif
}
else if (sigAlg == OID_SHA384_ECDSA_SIG)
{
#ifdef USE_SHA384
we_support = 1;
#endif
}
else if (sigAlg == OID_SHA512_ECDSA_SIG)
{
#ifdef USE_SHA512
we_support = 1;
#endif
}
else
{
/* Our key does not support this algorithm. */
return PS_FALSE;
}
}
else
{
return PS_FALSE; /* Unsupported public key alg, e.g. DSA. */
}
/* The basic capability is there. Now do some further checks
if needed. */
if (we_support)
{
return PS_TRUE;
}
else
{
return PS_FALSE;
}
}
/** Return PS_TRUE when:
- We support sigAlg for signature generation.
- sigAlg is in peerSigAlgs.
@param[in] sigAlg The signature algorithm whose support to check.
@param[in] pubKeyAlgorithm The public key algorithm of our key.
@param[in] peerSigAlgs The masks of the sigAlgs supported by the
peer. This should be the one parsed from the peer's
supported_signature_algorithms list in CertificateVerify or
CertificateRequest. In this case, sigAlg \in peerSigAlgs
means that the peer supports sigAlg for signature verification.
*/
psBool_t canUseSigAlg(int32_t sigAlg,
int32_t pubKeyAlgorithm,
uint16_t peerSigAlgs)
{
return (weSupportSigAlg(sigAlg, pubKeyAlgorithm) &&
peerSupportsSigAlg(sigAlg, peerSigAlgs));
}
/**
Upgrade to a more secure signature algorithm. If the algorithm
is already the strongest possible for the key type (i.e.
RSA-SHA-512 or ECDSA-SHA-512) change to the most popular
one (i.e. RSA-SHA-256 or ECDSA-SHA-256).
*/
int32_t upgradeSigAlg(int32_t sigAlg, int32_t pubKeyAlgorithm)
{
/*
RSA:
MD2 -> SHA256
MD5 -> SHA256
SHA1 -> SHA256
SHA256 -> SHA384
SHA384 -> SHA512
SHA512 -> SHA256
*/
if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
{
if (sigAlg == OID_MD2_RSA_SIG ||
sigAlg == OID_MD5_RSA_SIG ||
sigAlg == OID_SHA1_RSA_SIG)
{
return OID_SHA256_RSA_SIG;
}
else if (sigAlg == OID_SHA256_RSA_SIG)
{
return OID_SHA384_RSA_SIG;
}
else if (sigAlg == OID_SHA384_RSA_SIG)
{
return OID_SHA512_RSA_SIG;
}
else if (sigAlg == OID_SHA512_RSA_SIG)
{
return OID_SHA256_RSA_SIG;
}
else
{
return PS_UNSUPPORTED_FAIL;
}
}
/*
ECDSA:
SHA1 -> SHA256
SHA256 -> SHA384
SHA384 -> SHA512
SHA512 -> SHA256
*/
else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
{
if (sigAlg == OID_SHA1_ECDSA_SIG)
{
return OID_SHA256_ECDSA_SIG;
}
else if (sigAlg == OID_SHA256_ECDSA_SIG)
{
return OID_SHA384_ECDSA_SIG;
}
else if (sigAlg == OID_SHA384_ECDSA_SIG)
{
return OID_SHA512_ECDSA_SIG;
}
else if (sigAlg == OID_SHA512_ECDSA_SIG)
{
return OID_SHA256_ECDSA_SIG;
}
else
{
return PS_UNSUPPORTED_FAIL;
}
}
else
{
return PS_UNSUPPORTED_FAIL;
}
}
static
psSize_t sigAlgToHashLen(int32_t sigAlg)
{
switch(sigAlg)
{
case OID_MD2_RSA_SIG:
case OID_MD5_RSA_SIG:
return MD5_HASH_SIZE;
case OID_SHA1_RSA_SIG:
case OID_SHA1_ECDSA_SIG:
return SHA1_HASH_SIZE;
case OID_SHA256_RSA_SIG:
case OID_SHA256_ECDSA_SIG:
return SHA256_HASH_SIZE;
case OID_SHA384_RSA_SIG:
case OID_SHA384_ECDSA_SIG:
return SHA384_HASH_SIZE;
case OID_SHA512_RSA_SIG:
case OID_SHA512_ECDSA_SIG:
return SHA512_HASH_SIZE;
default:
return PS_UNSUPPORTED_FAIL;
}
}
/** Return PS_TRUE if sigAlg is deemed insecure.
Return PS_FALSE otherwise.
*/
static
int32_t isInsecureSigAlg(int32_t sigAlg)
{
if (sigAlg == OID_MD2_RSA_SIG
|| sigAlg == OID_MD5_RSA_SIG
|| sigAlg == OID_SHA1_RSA_SIG
|| sigAlg == OID_SHA1_ECDSA_SIG)
{
return 1;
}
else
{
return 0;
}
}
/* Return PS_TRUE when sigAlg,modulusNBytes is an invalid
hash and modulus size combination. Return PS_FALSE
otherwise. */
static
int32_t isInvalidModulusHashSizeCombination(int32_t sigAlg,
psSize_t modulusNBytes)
{
psSize_t hashLen = sigAlgToHashLen(sigAlg);
/* Check the PKCS #1.5 restriction that there should be room
for at least 8 padding bytes before RSA encryption.
(11 = 8 pad bytes + 00 + BT + 00). */
if (modulusNBytes < (hashLen + 11))
{
return PS_TRUE;
}
return PS_FALSE;
}
static
int32_t sigAlgRsaToEcdsa(int32_t sigAlg)
{
if (sigAlg == OID_SHA1_RSA_SIG)
{
return OID_SHA1_ECDSA_SIG;
}
if (sigAlg == OID_SHA256_RSA_SIG)
{
return OID_SHA256_ECDSA_SIG;
}
if (sigAlg == OID_SHA384_RSA_SIG)
{
return OID_SHA384_ECDSA_SIG;
}
if (sigAlg == OID_SHA512_RSA_SIG)
{
return OID_SHA512_ECDSA_SIG;
}
else
{
return OID_SHA256_ECDSA_SIG;
}
}
static
int32_t ecdsaToRsa(int32_t sigAlg)
{
if (sigAlg == OID_SHA1_ECDSA_SIG)
{
return OID_SHA1_RSA_SIG;
}
if (sigAlg == OID_SHA256_ECDSA_SIG)
{
return OID_SHA256_RSA_SIG;
}
if (sigAlg == OID_SHA384_ECDSA_SIG)
{
return OID_SHA384_RSA_SIG;
}
if (sigAlg == OID_SHA512_ECDSA_SIG)
{
return OID_SHA512_RSA_SIG;
}
else
{
return OID_SHA256_RSA_SIG;
}
}
/**
Determine signature algorithm to use in the CertificateVerify or
ServerKeyExchange handshake messages in TLS 1.2.
TODO: add support for RSASSA-PSS.
This function should only be called when using TLS 1.2.
@param[in] certSigAlg The signature algorithm with which our
certificate was signed.
@param[in] keySize The size of our private key in bytes. For RSA,
this is modulus; for ECDSA, this is the curve size.
@param[in] pubKeyAlgorithm The public key algorithm to use for
authentication. This should the same algorithm our public/private key
pair is meant for. Must be either OID_RSA_KEY_ALG or
OID_ECDSA_KEY_ALG.
@param[in] peerSigAlg The list of signature algorithm masks
the peer supports (e.g. HASH_SIG_SHA*_RSA_MASK). This should
be the list created during parsing of the ClientHello or
CertificateRequest message.
@return The signature algorithm to use.
*/
int32_t chooseSigAlgInt(int32_t certSigAlg,
psSize_t keySize,
int32_t pubKeyAlgorithm,
uint16_t peerSigAlgs)
{
int32 a = certSigAlg;
#ifndef USE_RSA
if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
{
return PS_UNSUPPORTED_FAIL;
}
#endif
#ifndef USE_ECC
if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
{
return PS_UNSUPPORTED_FAIL;
}
#endif
/*
We are going to use certSigAlg as the basis of our choice.
This is because the SSL layer must ensure anyway that the peer
supports this algorithm.
*/
if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
{
if (certSigAlg == OID_SHA1_ECDSA_SIG ||
certSigAlg == OID_SHA256_ECDSA_SIG ||
certSigAlg == OID_SHA384_ECDSA_SIG ||
certSigAlg == OID_SHA512_ECDSA_SIG)
{
/* Pubkey is RSA, but cert is signed with ECDSA.
Convert certSigAlg to corresponding RSA alg. */
a = ecdsaToRsa(certSigAlg);
}
/*
For RSA signatures, RFC 5746 allows to pick any hash algorithm,
as long as it is supported by the peer, i.e. included in the
peer's signature_algorithms list.
We use this opportunity to switch from the insecure MD5 and
SHA-1 to SHA-256, if possible. We don't want to contribute
to the longevity of obsolete hash algorithms.
*/
if (isInsecureSigAlg(a))
{
/* Try to upgrade. */
a = upgradeSigAlg(a, OID_RSA_KEY_ALG);
if (!canUseSigAlg(a, OID_RSA_KEY_ALG, peerSigAlgs))
{
/* Stil not supported. Try the next alternative. */
a = upgradeSigAlg(a, OID_RSA_KEY_ALG);
if (!canUseSigAlg(a, OID_RSA_KEY_ALG, peerSigAlgs))
{
/* Unable to upgrade insecure alg. Have to use the server
cert sig alg. */
a = certSigAlg;
}
}
}
/* Not allowing e.g. RSA-SHA-512 with a 512-bit modulus. */
if (isInvalidModulusHashSizeCombination(a, keySize))
{
/* Try "next best" hash algorithm. */
a = upgradeSigAlg(a, OID_RSA_KEY_ALG);
if (isInvalidModulusHashSizeCombination(a, keySize))
{
return PS_UNSUPPORTED_FAIL;
}
}
}
else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
{
if (certSigAlg != OID_SHA1_ECDSA_SIG &&
certSigAlg != OID_SHA256_ECDSA_SIG &&
certSigAlg != OID_SHA384_ECDSA_SIG &&
certSigAlg != OID_SHA512_ECDSA_SIG)
{
/* Pubkey is ECDSA, but cert is signed with RSA.
Convert to corresponding ECDSA alg. */
a = sigAlgRsaToEcdsa(certSigAlg);
}
}
else
{
return PS_UNSUPPORTED_FAIL; /* Unknown/unsupported pub key alg. */
}
/* Validate our choice. */
if (canUseSigAlg(a, pubKeyAlgorithm, peerSigAlgs))
{
psTraceIntInfo("Chose sigAlg %d\n", a);
return a;
}
else
{
return PS_UNSUPPORTED_FAIL;
}
}
int32_t chooseSigAlg(psX509Cert_t *cert,
psPubKey_t *privKey,
uint16_t peerSigAlgs)
{
int32 pubKeyAlg;
# ifdef USE_CERT_PARSE
pubKeyAlg = cert->pubKeyAlgorithm;
# else
if (privKey->type == PS_RSA)
{
pubKeyAlg = OID_RSA_KEY_ALG;
}
else if (privKey->type == PS_ECC)
{
pubKeyAlg = OID_ECDSA_KEY_ALG;
}
else
{
return PS_UNSUPPORTED_FAIL;
}
# endif /* USE_CERT_PARSE */
return chooseSigAlgInt(cert->sigAlgorithm,
privKey->keysize,
pubKeyAlg,
peerSigAlgs);
}
/* Return the TLS 1.2 SignatureAndHashAlgorithm encoding for the
given algorithm OID. */
int32_t getSignatureAndHashAlgorithmEncoding(uint16_t sigAlgOid,
unsigned char *octet1,
unsigned char *octet2,
uint16_t *hashSize)
{
unsigned char b1, b2;
uint16_t hLen = 0;
psAssert(octet1 != NULL && octet2 != NULL && hashSize != NULL);
switch(sigAlgOid)
{
#ifdef USE_SHA1
case OID_SHA1_ECDSA_SIG:
b1 = 0x2; /* SHA-1 */
b2 = 0x3; /* ECDSA */
hLen = SHA1_HASH_SIZE;
break;
case OID_SHA1_RSA_SIG:
b1 = 0x2; /* SHA-1 */
b2 = 0x1; /* RSA */
hLen = SHA1_HASH_SIZE;
break;
#endif
#ifdef USE_SHA256
case OID_SHA256_ECDSA_SIG:
b1 = 0x4; /* SHA-256 */
b2 = 0x3; /* ECDSA */
hLen = SHA256_HASH_SIZE;
break;
case OID_SHA256_RSA_SIG:
b1 = 0x4; /* SHA-256 */
b2 = 0x1; /* RSA */
hLen = SHA256_HASH_SIZE;
break;
#endif
#ifdef USE_SHA384
case OID_SHA384_ECDSA_SIG:
b1 = 0x5; /* SHA-384 */
b2 = 0x3; /* ECDSA */
hLen = SHA384_HASH_SIZE;
break;
case OID_SHA384_RSA_SIG:
b1 = 0x5; /* SHA-384 */
b2 = 0x1; /* RSA */
hLen = SHA384_HASH_SIZE;
break;
#endif
#ifdef USE_SHA512
case OID_SHA512_ECDSA_SIG:
b1 = 0x6; /* SHA-512 */
b2 = 0x3; /* ECDSA */
hLen = SHA512_HASH_SIZE;
break;
case OID_SHA512_RSA_SIG:
b1 = 0x6; /* SHA-512 */
b2 = 0x1; /* RSA */
hLen = SHA512_HASH_SIZE;
break;
#endif
default:
return PS_UNSUPPORTED_FAIL;
}
*octet1 = b1;
*octet2 = b2;
*hashSize = hLen;
return PS_SUCCESS;
}
#endif /* ! USE_ONLY_PSK_CIPHER_SUITE */
#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */
# ifdef USE_SSL_INFORMATIONAL_TRACE
void psPrintSigAlgs(uint16_t sigAlgs, const char *where)
{
if (where)
{
psTraceStrInfo("Signature algorithms in %s:\n", where);
}
if (sigAlgs & HASH_SIG_MD5_RSA_MASK)
{
_psTrace("RSA-MD5");
}
if (sigAlgs & HASH_SIG_SHA1_RSA_MASK)
{
_psTrace(" RSA-SHA1");
}
if (sigAlgs & HASH_SIG_SHA256_RSA_MASK)
{
_psTrace(" RSA-SHA256");
}
if (sigAlgs & HASH_SIG_SHA384_RSA_MASK)
{
_psTrace(" RSA-SHA384");
}
if (sigAlgs & HASH_SIG_SHA512_RSA_MASK)
{
_psTrace(" RSA-SHA512");
}
if (sigAlgs & HASH_SIG_SHA1_ECDSA_MASK)
{
_psTrace(" ECDSA-SHA1");
}
if (sigAlgs & HASH_SIG_SHA256_ECDSA_MASK)
{
_psTrace(" ECDSA-SHA256");
}
if (sigAlgs & HASH_SIG_SHA384_ECDSA_MASK)
{
_psTrace(" ECDSA-SHA384");
}
if (sigAlgs & HASH_SIG_SHA512_ECDSA_MASK)
{
_psTrace(" ECDSA-SHA512");
}
_psTrace("\n");
}
void psPrintProtocolVersion(const char *where,
unsigned char majVer,
unsigned char minVer,
psBool_t addNewline)
{
if (where)
{
psTraceStrInfo("%s : ", where);
}
if (majVer == TLS_MAJ_VER)
{
if (minVer == TLS_1_2_MIN_VER)
{
_psTrace("TLS 1.2");
}
else if (minVer == TLS_1_1_MIN_VER)
{
_psTrace("TLS 1.1");
}
else if (minVer == TLS_1_0_MIN_VER)
{
_psTrace("TLS 1.0");
}
else if (minVer == SSL3_MIN_VER)
{
_psTrace("SSL 3.0");
}
else
{
_psTrace("Unsupported protocol version");
}
}
# ifdef USE_DTLS
else if (majVer == DTLS_MAJ_VER)
{
if (minVer == DTLS_1_2_MIN_VER)
{
_psTrace("DTLS 1.2");
}
else if (minVer == DTLS_MIN_VER)
{
_psTrace("DTLS 1.0");
}
else
{
_psTrace("Unsupported protocol version");
}
}
# endif /* USE_DTLS */
else
{
_psTrace("Unsupported protocol version");
}
if (addNewline)
{
_psTrace("\n");
}
}
# endif /* USE_SSL_INFORMATIONAL_TRACE */
/******************************************************************************/