Add PSS for TLS v1.3

This commit is contained in:
Sean Parkinson
2017-05-10 16:59:11 +10:00
parent df3abee72c
commit ec6d8f48b8
7 changed files with 251 additions and 34 deletions

View File

@ -243,6 +243,7 @@ AC_ARG_ENABLE([tls13],
if test "$ENABLED_TLS13" = "yes"
then
AM_CFLAGS="-DWOLFSSL_TLS13 -DHAVE_TLS_EXTENSIONS -DHAVE_FFDHE_2048 $AM_CFLAGS"
AM_CFLAGS="-DWC_RSA_PSS $AM_CFLAGS"
fi
# check if TLS v1.3 was enabled for conditionally running tls13.test script

View File

@ -2773,8 +2773,9 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
return ret;
}
int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz,
byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx)
int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
int hashAlgo, RsaKey* key, const byte* keyBuf, word32 keySz,
void* ctx)
{
int ret;
@ -2782,6 +2783,8 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz,
(void)keyBuf;
(void)keySz;
(void)ctx;
(void)sigAlgo;
(void)hashAlgo;
WOLFSSL_ENTER("RsaVerify");
@ -2792,7 +2795,37 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz,
else
#endif /*HAVE_PK_CALLBACKS */
{
ret = wc_RsaSSL_VerifyInline(in, inSz, out, key);
#ifdef WOLFSSL_TLS13
#ifdef WC_RSA_PSS
if (sigAlgo == rsa_pss_sa_algo) {
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
int mgf = 0;
switch (hashAlgo) {
case sha512_mac:
#ifdef WOLFSSL_SHA512
hashType = WC_HASH_TYPE_SHA512;
mgf = WC_MGF1SHA512;
#endif
break;
case sha384_mac:
#ifdef WOLFSSL_SHA384
hashType = WC_HASH_TYPE_SHA384;
mgf = WC_MGF1SHA384;
#endif
break;
case sha256_mac:
#ifndef NO_SHA256
hashType = WC_HASH_TYPE_SHA256;
mgf = WC_MGF1SHA256;
#endif
break;
}
ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key);
}
else
#endif
#endif
ret = wc_RsaSSL_VerifyInline(in, inSz, out, key);
}
/* Handle async pending response */
@ -16323,6 +16356,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
ret = RsaVerify(ssl,
args->verifySig, args->verifySigSz,
&args->output,
rsa_sa_algo, no_mac,
ssl->peerRsaKey,
#ifdef HAVE_PK_CALLBACKS
ssl->buffers.peerRsaKey.buffer,
@ -21091,6 +21125,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
input + args->idx,
args->sz,
&args->output,
rsa_sa_algo, no_mac,
ssl->peerRsaKey,
#ifdef HAVE_PK_CALLBACKS
ssl->buffers.peerRsaKey.buffer,

View File

@ -4445,6 +4445,17 @@ static word16 TLSX_SignatureAlgorithms_GetSize(byte* data)
#ifdef HAVE_SHA512
cnt++;
#endif
#ifdef WC_RSA_PSS
#ifndef NO_SHA256
cnt++;
#endif
#ifdef HAVE_SHA384
cnt++;
#endif
#ifdef HAVE_SHA512
cnt++;
#endif
#endif
#endif
#ifdef HAVE_ECC
@ -4497,6 +4508,20 @@ static word16 TLSX_SignatureAlgorithms_Write(byte* data, byte* output)
output[idx++] = 0x06;
output[idx++] = 0x01;
#endif
#ifdef WC_RSA_PSS
#ifndef NO_SHA256
output[idx++] = 0x08;
output[idx++] = 0x04;
#endif
#ifdef HAVE_SHA384
output[idx++] = 0x08;
output[idx++] = 0x05;
#endif
#ifdef HAVE_SHA512
output[idx++] = 0x08;
output[idx++] = 0x06;
#endif
#endif
#endif
#ifdef HAVE_ECC

View File

@ -2851,12 +2851,18 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType)
{
switch (input[0]) {
/* PSS signatures: 0x080[4-6] */
case 0x08:
/* PSS signatures: 0x080[4-6] */
if (input[1] <= 0x06) {
*hsType = input[0];
*hashAlgo = input[1];
}
break;
/* ED25519: 0x0807 */
/* ED448: 0x0808 */
default:
*hashAlgo = input[0];
*hsType = input[1];
*hsType = input[1];
break;
}
}
@ -3048,13 +3054,14 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo)
* based on the digest of the signature data.
*
* ssl The SSL/TLS object.
* hashAlgo The signature algorithm used to generate signature.
* hashAlgo The hash algorithm used to generate signature.
* decSig The decrypted signature.
* decSigSz The size of the decrypted signature.
* returns 0 on success, otherwise failure.
*/
static int CheckRSASignature(WOLFSSL* ssl, int hashAlgo, byte* decSig,
word32 decSigSz)
static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo,
byte* decSig, word32 decSigSz)
{
int ret = 0;
byte sigData[MAX_SIG_DATA_SZ];
@ -3066,21 +3073,38 @@ static int CheckRSASignature(WOLFSSL* ssl, int hashAlgo, byte* decSig,
#endif
word32 sigSz;
if (sigAlgo == rsa_sa_algo) {
#ifdef WOLFSSL_SMALL_STACK
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL) {
ret = MEMORY_E;
goto end;
}
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL) {
ret = MEMORY_E;
goto end;
}
#endif
CreateSigData(ssl, sigData, &sigDataSz, 1);
sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, hashAlgo);
/* Check the encoded and decrypted signature data match. */
if (decSigSz != sigSz || decSig == NULL ||
XMEMCMP(decSig, encodedSig, sigSz) != 0) {
ret = VERIFY_CERT_ERROR;
CreateSigData(ssl, sigData, &sigDataSz, 1);
sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, hashAlgo);
/* Check the encoded and decrypted signature data match. */
if (decSigSz != sigSz || decSig == NULL ||
XMEMCMP(decSig, encodedSig, sigSz) != 0) {
ret = VERIFY_CERT_ERROR;
}
}
else {
CreateSigData(ssl, sigData, &sigDataSz, 1);
sigSz = CreateECCEncodedSig(sigData, sigDataSz, hashAlgo);
if (decSigSz != sigSz || decSig == NULL)
ret = VERIFY_CERT_ERROR;
else {
decSig -= 2 * decSigSz;
XMEMCPY(decSig, sigData, decSigSz);
decSig -= 8;
XMEMSET(decSig, 0, 8);
CreateECCEncodedSig(decSig, 8 + decSigSz * 2, hashAlgo);
if (XMEMCMP(decSig, decSig + 8 + decSigSz * 2, decSigSz) != 0)
ret = VERIFY_CERT_ERROR;
}
}
#ifdef WOLFSSL_SMALL_STACK
@ -3783,8 +3807,9 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
!ssl->peerEccDsaKeyPresent) {
WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
}
if (args->sigAlgo == rsa_sa_algo &&
(ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) {
if ((args->sigAlgo == rsa_sa_algo ||
args->sigAlgo == rsa_pss_sa_algo) &&
(ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) {
WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
}
@ -3818,11 +3843,12 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
case TLS_ASYNC_DO:
{
#ifndef NO_RSA
if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent) {
if (args->sigAlgo == rsa_sa_algo ||
args->sigAlgo == rsa_pss_sa_algo) {
WOLFSSL_MSG("Doing RSA peer cert verify");
ret = RsaVerify(ssl, sig->buffer, sig->length, &args->output,
ssl->peerRsaKey,
args->sigAlgo, args->hashAlgo, ssl->peerRsaKey,
#ifdef HAVE_PK_CALLBACKS
ssl->buffers.peerRsaKey.buffer,
ssl->buffers.peerRsaKey.length,
@ -3868,7 +3894,8 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
{
#ifndef NO_RSA
if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
ret = CheckRSASignature(ssl, args->hashAlgo, args->output, args->sendSz);
ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo,
args->output, args->sendSz);
if (ret != 0)
goto exit_dcv;
}

View File

@ -261,7 +261,7 @@ int wc_FreeRsaKey(RsaKey* key)
}
#ifndef WC_NO_RSA_OAEP
#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS)
/* Uses MGF1 standard as a mask generation function
hType: hash type used
seed: seed to use for generating mask
@ -572,6 +572,50 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock,
}
#endif /* !WC_NO_RSA_OAEP */
#ifdef WC_RSA_PSS
static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock,
word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf,
void* heap)
{
int ret;
int hLen, i;
byte* s;
byte* m;
byte* h;
byte salt[WC_MAX_DIGEST_SIZE];
hLen = wc_HashGetDigestSize(hType);
if (hLen < 0)
return hLen;
s = m = pkcsBlock;
XMEMSET(m, 0, 8);
m += 8;
XMEMCPY(m, input, inputLen);
m += inputLen;
if ((ret = wc_RNG_GenerateBlock(rng, salt, hLen)) != 0)
return ret;
XMEMCPY(m, salt, hLen);
m += hLen;
h = pkcsBlock + pkcsBlockLen - 1 - hLen;
if ((ret = wc_Hash(hType, s, (word32)(m - s), h, hLen)) != 0)
return ret;
pkcsBlock[pkcsBlockLen - 1] = 0xbc;
ret = RsaMGF(mgf, h, hLen, pkcsBlock, pkcsBlockLen - hLen - 1, heap);
if (ret != 0)
return ret;
pkcsBlock[0] &= 0x7f;
m = pkcsBlock + pkcsBlockLen - 1 - hLen - hLen - 1;
*(m++) ^= 0x01;
for (i = 0; i < hLen; i++)
m[i] ^= salt[i];
return 0;
}
#endif
static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
word32 pkcsBlockLen, byte padValue, WC_RNG* rng)
@ -635,16 +679,25 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock,
case WC_RSA_PKCSV15_PAD:
/*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");*/
ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen,
padValue, rng);
padValue, rng);
break;
#ifndef WC_NO_RSA_OAEP
case WC_RSA_OAEP_PAD:
WOLFSSL_MSG("wolfSSL Using RSA OAEP padding");
ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen,
padValue, rng, hType, mgf, optLabel, labelLen, heap);
padValue, rng, hType, mgf, optLabel, labelLen, heap);
break;
#endif
#ifdef WC_RSA_PSS
case WC_RSA_PSS_PAD:
WOLFSSL_MSG("wolfSSL Using RSA PSS padding");
ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen,
rng, hType, mgf, heap);
break;
#endif
default:
WOLFSSL_MSG("Unknown RSA Pad Type");
ret = RSA_PAD_E;
@ -748,6 +801,53 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen,
}
#endif /* WC_NO_RSA_OAEP */
#ifdef WC_RSA_PSS
static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen,
byte **output, enum wc_HashType hType, int mgf,
void* heap)
{
int ret;
byte* tmp;
int hLen, i;
hLen = wc_HashGetDigestSize(hType);
if (hLen < 0)
return hLen;
if (pkcsBlock[pkcsBlockLen - 1] != 0xbc)
return BAD_PADDING_E;
tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
if ((ret = RsaMGF(mgf, pkcsBlock + pkcsBlockLen - 1 - hLen, hLen,
tmp, pkcsBlockLen - 1 - hLen, heap)) != 0) {
XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
tmp[0] &= 0x7f;
for (i = 0; i < (int)(pkcsBlockLen - 1 - hLen - hLen - 1); i++) {
if (tmp[i] != pkcsBlock[i]) {
XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
return BAD_PADDING_E;
}
}
if (tmp[i] != (pkcsBlock[i] ^ 0x01)) {
XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
return BAD_PADDING_E;
}
for (i++; i < (int)(pkcsBlockLen - 1 - hLen); i++)
pkcsBlock[i] ^= tmp[i];
XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
*output = pkcsBlock + i;
return hLen;
}
#endif
/* UnPad plaintext, set start to *output, return length of plaintext,
* < 0 on error */
@ -817,6 +917,14 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
break;
#endif
#ifdef WC_RSA_PSS
case WC_RSA_PSS_PAD:
WOLFSSL_MSG("wolfSSL Using RSA PSS un-padding");
ret = RsaUnPad_PSS((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf,
heap);
break;
#endif
default:
WOLFSSL_MSG("Unknown RSA UnPad Type");
ret = RSA_PAD_E;
@ -1105,7 +1213,8 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
pad_type : type of padding: WC_RSA_PKCSV15_PAD or WC_RSA_OAEP_PAD
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD or
WC_RSA_PSS_PAD
hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
mgf : type of mask generation function to use
label : optional label
@ -1212,7 +1321,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
pad_type : type of padding: WC_RSA_PKCSV15_PAD or WC_RSA_OAEP_PAD
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD
WC_RSA_PSS_PAD
hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
mgf : type of mask generation function to use
label : optional label
@ -1446,6 +1556,19 @@ int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng);
}
#ifdef WC_RSA_PSS
int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out,
enum wc_HashType hash, int mgf, RsaKey* key)
{
WC_RNG* rng = NULL;
#ifdef WC_RSA_BLINDING
rng = key->rng;
#endif
return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD,
hash, mgf, NULL, 0, rng);
}
#endif
int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
RsaKey* key, WC_RNG* rng)

View File

@ -2345,10 +2345,11 @@ enum KeyExchangeAlgorithm {
/* Supported Authentication Schemes */
enum SignatureAlgorithm {
anonymous_sa_algo,
rsa_sa_algo,
dsa_sa_algo,
ecc_dsa_sa_algo
anonymous_sa_algo = 0,
rsa_sa_algo = 1,
dsa_sa_algo = 2,
ecc_dsa_sa_algo = 4,
rsa_pss_sa_algo = 8
};
@ -3407,7 +3408,8 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl);
WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx);
WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz,
byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx);
byte** out, int sigAlgo, int hashAlgo, RsaKey* key,
const byte* keyBuf, word32 keySz, void* ctx);
WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out,
word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx);
WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,

View File

@ -126,6 +126,9 @@ WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out,
RsaKey* key);
WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key);
WOLFSSL_API int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out,
enum wc_HashType hash, int mgf,
RsaKey* key);
WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key);
#ifndef HAVE_FIPS /* to avoid asn duplicate symbols @wc_fips */
@ -156,6 +159,7 @@ WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng);
/* Padding types */
#define WC_RSA_PKCSV15_PAD 0
#define WC_RSA_OAEP_PAD 1
#define WC_RSA_PSS_PAD 2
WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng, int type,