/** * @file tlsSigVer.c * @version $Format:%h%d$ * * Functions for signature generation and verification for TLS 1.2 * and below. */ /* * Copyright (c) 2013-2018 Rambus Inc. * 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 Rambus at * http://www.rambus.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" # ifndef USE_TLS_1_3_ONLY # ifndef USE_ONLY_PSK_CIPHER_SUITE # ifdef USE_ROT_CRYPTO # include "../crypto-rot/rotCommon.h" # endif # ifndef DEBUG_TLS_SIG_VER /*# define DEBUG_TLS_SIG_VER*/ # endif uint32_t getDefaultSkeHashSize(ssl_t *ssl) { uint32_t hashSize; hashSize = MD5SHA1_HASH_SIZE; /* Default for (D)TLS <1.2. */ # ifdef USE_ECC_CIPHER_SUITE if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { /* RFC 4492: SHA-1 is the default. */ hashSize = SHA1_HASH_SIZE; } # endif /* USE_ECC_CIPHER_SUITE */ return hashSize; } int32_t computeSkeHash(ssl_t *ssl, psDigestContext_t *digestCtx, uint32_t hashSize, const unsigned char *tbsStart, /* Start of ServerParams. */ const unsigned char *tbsStop, unsigned char *hsMsgHash) { /* In both TLS 1.2 and below, the SKE signature is computed over the hash of: ClientHello.random || ServerHello.random || ServerParams Unfortunately, we cannot use psComputeHashForSig, since it only supports single part operation - we would have to concatenate the above data into a single buffer, something which we are not willing to do here. */ switch (hashSize) { # ifdef USE_MD5SHA1 case MD5SHA1_HASH_SIZE: psMd5Sha1PreInit(&digestCtx->u.md5sha1); psMd5Sha1Init(&digestCtx->u.md5sha1); psMd5Sha1Update(&digestCtx->u.md5sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); psMd5Sha1Update(&digestCtx->u.md5sha1, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); psMd5Sha1Update(&digestCtx->u.md5sha1, tbsStart, (uint32) (tbsStop - tbsStart)); psMd5Sha1Final(&digestCtx->u.md5sha1, hsMsgHash); break; # endif /* USE_MD5SHA1 */ # ifdef USE_SHA1 case SHA1_HASH_SIZE: psSha1PreInit(&digestCtx->u.sha1); psSha1Init(&digestCtx->u.sha1); psSha1Update(&digestCtx->u.sha1, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); psSha1Update(&digestCtx->u.sha1, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); psSha1Update(&digestCtx->u.sha1, tbsStart, (uint32) (tbsStop - tbsStart)); psSha1Final(&digestCtx->u.sha1, hsMsgHash); break; # endif /* USE_SHA1 */ # ifdef USE_TLS_1_2 case SHA256_HASH_SIZE: psSha256PreInit(&digestCtx->u.sha256); psSha256Init(&digestCtx->u.sha256); psSha256Update(&digestCtx->u.sha256, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); psSha256Update(&digestCtx->u.sha256, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); psSha256Update(&digestCtx->u.sha256, tbsStart, (uint32) (tbsStop - tbsStart)); psSha256Final(&digestCtx->u.sha256, hsMsgHash); break; # ifdef USE_SHA384 case SHA384_HASH_SIZE: psSha384PreInit(&digestCtx->u.sha384); psSha384Init(&digestCtx->u.sha384); psSha384Update(&digestCtx->u.sha384, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); psSha384Update(&digestCtx->u.sha384, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); psSha384Update(&digestCtx->u.sha384, tbsStart, (uint32) (tbsStop - tbsStart)); psSha384Final(&digestCtx->u.sha384, hsMsgHash); break; # endif /* USE_SHA384 */ # ifdef USE_SHA512 case SHA512_HASH_SIZE: psSha512PreInit(&digestCtx->u.sha512); psSha512Init(&digestCtx->u.sha512); psSha512Update(&digestCtx->u.sha512, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE); psSha512Update(&digestCtx->u.sha512, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE); psSha512Update(&digestCtx->u.sha512, tbsStart, (uint32) (tbsStop - tbsStart)); psSha512Final(&digestCtx->u.sha512, hsMsgHash); break; # endif /* USE_SHA512 */ # endif /* USE_TLS_1_2 */ default: psTraceErrr("Unsupported hash algorithm in SKE\n"); psTraceIntInfo("Unsupported hash size: %u\n", hashSize); return PS_UNSUPPORTED_FAIL; } return PS_SUCCESS; } psRes_t computeSkeTbs(ssl_t *ssl, const unsigned char *tbsStart, const unsigned char *tbsStop, unsigned char **out, psSizeL_t *outLen) { unsigned char *tbs; psSize_t tbsLen; /* TBS length is 2x32 bytes for client_random || server_random plus the size of signed_params. */ tbsLen = 64 + (tbsStop - tbsStart); tbs = psMalloc(ssl->hsPool, tbsLen); if (tbs == NULL) { return PS_MEM_FAIL; } Memcpy(tbs, ssl->sec.clientRandom, 32); Memcpy(tbs + 32, ssl->sec.serverRandom, 32); Memcpy(tbs + 64, tbsStart, tbsStop - tbsStart); # ifdef DEBUG_TLS_SIG_VER psTraceBytes("computeSkeTbs", tbs, tbsLen); # endif *out = tbs; *outLen = tbsLen; return PS_SUCCESS; } # ifdef USE_IDENTITY_CERTIFICATES static inline int32_t chooseSkeSigAlgTls12(ssl_t *ssl, sslIdentity_t *id) { int32_t sigAlg; uint16_t sigAlgMask; if (MATRIX_IS_CLIENT(ssl)) { /* The client will always receive the servers sigalg list in CertificateRequest. */ sigAlgMask = ssl->peerSigAlg; } else { if (ssl->peerSigAlg != 0) { /* Got signature_algorithms in ClientHello. */ sigAlgMask = ssl->peerSigAlg; } else { /* No signature_algorithms received, use the "shared" list, which in this case is equal to our list. */ sigAlgMask = ssl->hashSigAlg; } } sigAlg = chooseSigAlg(id->cert, &id->privKey, sigAlgMask); if (sigAlg == PS_UNSUPPORTED_FAIL) { psTraceInfo("Unavailable sigAlgorithm for SKE write\n"); return PS_UNSUPPORTED_FAIL; } return sigAlg; } static inline int32_t chooseSkeSigAlgTls11(ssl_t *ssl, sslIdentity_t *id) { if (id->privKey.type == PS_RSA) { return 0; /* MD5SHA1-RSA does not have an OID, so use 0. */ } else { /* ECDSA uses SHA-1 by default. */ return OID_SHA1_ECDSA_SIG; } } int32_t chooseSkeSigAlg(ssl_t *ssl, sslIdentity_t *id) { # ifdef USE_TLS_1_2 if (NGTD_VER(ssl, v_tls_with_signature_algorithms)) { return chooseSkeSigAlgTls12(ssl, id); } # endif return chooseSkeSigAlgTls11(ssl, id); } /** Prepare for a postponed SKE signing operation. @precond The function is only called when the SKE message needs a signature, i.e. only when using non-PSK (EC)DHE ciphersuites. */ psRes_t tlsPrepareSkeSignature(ssl_t *ssl, int32_t skeSigAlg, unsigned char *tbsStart, unsigned char *c, psBool_t needPreHash) { sslIdentity_t *chosen = ssl->chosenIdentity; unsigned char *orig = c; psDigestContext_t digestCtx; unsigned char *hsMsgHash = NULL; unsigned char *tbs = NULL; psSizeL_t tbsLen = 0; unsigned char *tbsStop; int32_t rc; void *pkiData = ssl->userPtr; pkaAfter_t *pkaAfter; psSize_t hashSize; unsigned char sigAlgId[2]; uint16_t pkaType = 0; /* ServerDHParams params; digitally-signed struct { opaque client_random[32]; opaque server_random[32]; ServerDHParams params; } signed_params; How we shall encode the signature (a digitally-signed struct): TLS 1.2 and below: struct { SignatureAndHashAlgorithm algorithm; opaque signature<0..2^16-1>; } DigitallySigned; TLS 1.1 and below: opaque vector <0..2^16-1> */ /* [tbsStart, tbsStop] == signed_params. */ tbsStop = c; hashSize = getDefaultSkeHashSize(ssl); # ifdef USE_TLS_1_2 if (NGTD_VER(ssl, v_tls_with_signature_algorithms)) { rc = getSignatureAndHashAlgorithmEncoding(skeSigAlg, &sigAlgId[0], &sigAlgId[1], &hashSize); if (rc < 0) { return rc; } *c++ = sigAlgId[0]; *c++ = sigAlgId[1]; } # endif # if defined(USE_SM2) && defined(USE_SM3) if (skeSigAlg == OID_SM3_SM2_SIG) { needPreHash = PS_FALSE; } # endif if (needPreHash) { /* Reserve space for the hash of signed_params. */ hsMsgHash = psMalloc(ssl->hsPool, SHA512_HASH_SIZE); if (hsMsgHash == NULL) { return PS_MEM_FAIL; } /* Compute the hash. */ rc = computeSkeHash(ssl, &digestCtx, hashSize, tbsStart, tbsStop, hsMsgHash); if (rc < 0) { psFree(hsMsgHash, ssl->hsPool); return rc; } } else { /* No pre-hash, but need to provide the TBS as a contiguous buffer for later hashing and signing. */ rc = computeSkeTbs(ssl, tbsStart, tbsStop, &tbs, &tbsLen); if (rc < 0) { return rc; } } /* Compute the signature lengths and write the signature length octets. */ #ifdef USE_RSA_CIPHER_SUITE if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { /* Signature size == RSA private key modulus size. */ *c = (chosen->privKey.keysize & 0xFF00) >> 8; c++; *c = chosen->privKey.keysize & 0xFF; c++; pkaType = PKA_AFTER_RSA_SIG_GEN; # ifdef USE_TLS_1_2 if (NGTD_VER(ssl, v_tls_with_pkcs15_auth)) { /* The protocol uses PKCS #1.5 signatures. */ pkaType = PKA_AFTER_RSA_SIG_GEN_ELEMENT; } # endif /* USE_TLS_1_2 */ } #endif /* USE_RSA_CIPHER_SUITE */ # ifdef USE_ECC_CIPHER_SUITE if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { /* For ECDSA, the signature length octets are written later by psEccDsaSign in nowDoSkePka. Not being consistent is bad. But, because of the "negative ECDSA" case, we do not completely know the signature length in advance. */ pkaType = PKA_AFTER_ECDSA_SIG_GEN; } # endif /* USE_ECC_CIPHER_SUITE */ # ifdef USE_DTLS if (ACTV_VER(ssl, v_dtls_any) && (ssl->retransmit == 1)) { /* It is not optimal to have run through the above digest updates again on a retransmit just to free the hash here but the saved message is ONLY the signature portion done in nowDoSke so the few hashSigAlg bytes and keysize done above during the hash are important to rewrite */ psFree(hsMsgHash, ssl->hsPool); Memcpy(c, ssl->ckeMsg, ssl->ckeSize); c += ssl->ckeSize; if (tbs != NULL) { psFree(tbs, ssl->hsPool); } return (c - orig); } # endif /* USE_DTLS */ pkaAfter = getPkaAfter(ssl); if (pkaAfter == NULL) { psTraceErrr("getPkaAfter error\n"); psFree(hsMsgHash, ssl->hsPool); if (tbs != NULL) { psFree(tbs, ssl->hsPool); } return PS_PLATFORM_FAIL; } if (needPreHash) { pkaAfter->inbuf = hsMsgHash; pkaAfter->inlen = hashSize; } else { pkaAfter->inbuf = tbs; pkaAfter->inlen = tbsLen; } pkaAfter->outbuf = c; pkaAfter->data = pkiData; pkaAfter->type = pkaType; /* Advance write pointer by the predicted size of the signature. */ # ifdef USE_RSA_CIPHER_SUITE if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { c += chosen->privKey.keysize; } # endif # ifdef USE_ECC_CIPHER_SUITE if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA) { rc = chosen->privKey.keysize + 8; /* NEGATIVE ECDSA - Adding spot for ONE 0x0 byte in ECDSA so we'll be right 50% of the time... 521 curve doesn't need */ if (chosen->privKey.keysize != 132) { rc += 1; } /* Above we added in the 8 bytes of overhead (2 sigLen, 1 SEQ, 1 len (possibly 2!), 1 INT, 1 rLen, 1 INT, 1 sLen) and now subtract the first 3 bytes to see if the 1 len needs to be 2 */ if (rc - 3 >= 128) { rc++; } pkaAfter->user = rc; /* outlen for later */ c += rc; } # endif /* Return the predicted size of the digitally-signed struct. */ return (c - orig); } static psPool_t *getTmpPkiPool(ssl_t *ssl, pkaAfter_t *pka) { return NULL; } psRes_t tlsMakeSkeSignature(ssl_t *ssl, pkaAfter_t *pka, psBuf_t *out) { int32_t rc; psPool_t *pkiPool = getTmpPkiPool(ssl, pka); int32_t sigAlg = OID_RSA_TLS_SIG_ALG; sslIdentity_t *chosen = ssl->chosenIdentity; psPubKey_t *privKey = &chosen->privKey; unsigned char *sigBuf; psSize_t sigLen; psSignOpts_t opts = {0}; /* Prepare for the call to psSign. RSA signatures are be generated straight into pka->outbuf. ECDSA signatures use an intermediate temporary buffer. For RSA, the TLS signature vector length octets have been written in tlsPrepareSkeSignature. With ECDSA, we cannot completely predict the signature size in advance, so we ask psSign to prepend the TLS vector length (INCLUDE_SIZE option) to the signature. */ switch (pka->type) { # ifdef USE_RSA_CIPHER_SUITE case PKA_AFTER_RSA_SIG_GEN_ELEMENT: sigAlg = OID_RSA_PKCS15_SIG_ALG; sigLen = privKey->keysize; sigBuf = pka->outbuf; opts.flags |= PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF; break; case PKA_AFTER_RSA_SIG_GEN: sigAlg = OID_RSA_TLS_SIG_ALG; sigLen = privKey->keysize; sigBuf = pka->outbuf; opts.flags |= PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF; break; # endif /* USE_RSA_CIPHER_SUITE */ # ifdef USE_ECC_CIPHER_SUITE case PKA_AFTER_ECDSA_SIG_GEN: sigAlg = OID_ECDSA_TLS_SIG_ALG; # ifdef USE_DTLS ssl->ecdsaSizeChange = 0; # endif opts.flags |= PS_SIGN_OPTS_ECDSA_INCLUDE_SIZE; # if defined(USE_SM2) && defined(USE_SM3) if (privKey->key.ecc.curve->curveId == IANA_CURVESM2) { opts.flags |= PS_SIGN_OPTS_SM2_SIGN; } # endif break; # endif /* USE_ECC_CIPHER_SUITE */ default: psTraceErrr("Unsupported type of PKA operation\n"); return PS_UNSUPPORTED_FAIL; } opts.userData = pka->data; /* Compute the signature. */ rc = psSign(pkiPool, privKey, sigAlg, pka->inbuf, pka->inlen, &sigBuf, &sigLen, &opts); if (rc == PS_PENDING) { /* Async operation launched, but not complete. */ /* If the result is going directly inline to the output buffer we unflag 'type' so this function isn't called again on the way back around. Also, we can safely free inbuf because it has been copied out. */ psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL; pka->type = 0; if (sigBuf != pka->outbuf) { psFree(sigBuf, ssl->pkiPool); } return rc; } else if (rc < 0) { if (sigBuf != pka->outbuf) { psFree(sigBuf, ssl->hsPool); } psTraceErrr("SKE signature generation failed\n"); psTraceIntInfo("Signature return code: %d\n", rc); return MATRIXSSL_ERROR; } /* Signature is ready, either in sigBuf or in pka->outbuf. */ /* If the signature size is different than predicted, we need to tweak the previously encoded flight to account for this. This is a huge mess, but cannot be avoided with the current approach, where the entire flight is encoded before public key operations are used to fill the signature spots. */ # ifdef USE_ECC_CIPHER_SUITE if (pka->type == PKA_AFTER_ECDSA_SIG_GEN) { if (sigLen != pka->user) { /* Confirmed ECDSA is not default size */ psTraceInfo("Need accountForEcdsaSizeChange\n"); rc = accountForEcdsaSizeChange(ssl, pka, sigLen, sigBuf, out, SSL_HS_SERVER_KEY_EXCHANGE); if (rc < 0) { clearPkaAfter(ssl); psFree(sigBuf, ssl->hsPool); return MATRIXSSL_ERROR; } } else { Memcpy(pka->outbuf, sigBuf, pka->user); } psFree(sigBuf, pkiPool); } # endif /* USE_ECC_CIPHER_SUITE */ /* Store the signature in case of a message retransmit in DTLS. */ # ifdef USE_DTLS if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 0)) { /* Using existing ckeMsg and ckeSize that clients are using but this should be totally fine on the server side because it is freed at FINISHED parse */ ssl->ckeSize = sigLen; ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize); if (ssl->ckeMsg == NULL) { psTraceErrr("Memory allocation error ckeMsg\n"); return PS_MEM_FAIL; } Memcpy(ssl->ckeMsg, pka->outbuf, ssl->ckeSize); } # endif /* USE_DTLS */ clearPkaAfter(ssl); return rc; } #endif /* USE_IDENTITY_CERTIFICATES */ psBool_t tlsIsSupportedRsaSigAlg(int32_t alg) { switch (alg) { case OID_RSA_TLS_SIG_ALG: case sigalg_rsa_pkcs1_sha1: case sigalg_rsa_pkcs1_sha256: case sigalg_rsa_pkcs1_sha384: case sigalg_rsa_pkcs1_sha512: # ifdef USE_PKCS1_PSS case sigalg_rsa_pss_rsae_sha256: case sigalg_rsa_pss_rsae_sha384: case sigalg_rsa_pss_rsae_sha512: case sigalg_rsa_pss_pss_sha256: case sigalg_rsa_pss_pss_sha384: case sigalg_rsa_pss_pss_sha512: # endif return PS_TRUE; default: return PS_FALSE; } return PS_FALSE; } psBool_t tlsIsSupportedEcdsaSigAlg(int32_t alg) { switch (alg) { case OID_ECDSA_TLS_SIG_ALG: case sigalg_ecdsa_sha1: case sigalg_ecdsa_secp256r1_sha256: case sigalg_ecdsa_secp384r1_sha384: case sigalg_ecdsa_secp521r1_sha512: return PS_TRUE; default: return PS_FALSE; } } psResSize_t tlsSigAlgToHashLen(uint16_t alg) { /* Note: We are in TLS 1.2 context here. The sigalg_* names below are from TLS 1.3, but they are compatible with the TLS 1.2 ones. Only difference is that the TLS 1.2 ECDSA sig algs do not specify the curve. So sigalg_ecdsa_secp256r1_sha256 just means ECDSA-SHA256 here, for example. */ switch (alg) { case sigalg_rsa_pkcs1_sha1: case sigalg_ecdsa_sha1: return SHA1_HASH_SIZE; case sigalg_rsa_pkcs1_sha256: case sigalg_rsa_pss_rsae_sha256: case sigalg_rsa_pss_pss_sha256: case sigalg_ecdsa_secp256r1_sha256: return SHA256_HASH_SIZE; case sigalg_rsa_pkcs1_sha384: case sigalg_rsa_pss_rsae_sha384: case sigalg_rsa_pss_pss_sha384: case sigalg_ecdsa_secp384r1_sha384: return SHA384_HASH_SIZE; case sigalg_rsa_pkcs1_sha512: case sigalg_rsa_pss_rsae_sha512: case sigalg_rsa_pss_pss_sha512: case sigalg_ecdsa_secp521r1_sha512: return SHA512_HASH_SIZE; case sigalg_sm2sig_sm3: return SM3_HASH_SIZE; default: return PS_UNSUPPORTED_FAIL; } } int32_t tlsSigAlgToMatrix(uint16_t alg) { switch (alg) { case sigalg_rsa_pkcs1_sha1: return OID_SHA1_RSA_SIG; case sigalg_rsa_pkcs1_sha256: return OID_SHA256_RSA_SIG; case sigalg_rsa_pkcs1_sha384: return OID_SHA384_RSA_SIG; case sigalg_rsa_pkcs1_sha512: return OID_SHA512_RSA_SIG; case sigalg_rsa_pss_rsae_sha256: case sigalg_rsa_pss_rsae_sha384: case sigalg_rsa_pss_rsae_sha512: case sigalg_rsa_pss_pss_sha256: case sigalg_rsa_pss_pss_sha384: case sigalg_rsa_pss_pss_sha512: return OID_RSASSA_PSS; case sigalg_ecdsa_sha1: return OID_SHA1_ECDSA_SIG; case sigalg_ecdsa_secp256r1_sha256: return OID_SHA256_ECDSA_SIG; case sigalg_ecdsa_secp384r1_sha384: return OID_SHA384_ECDSA_SIG; case sigalg_ecdsa_secp521r1_sha512: return OID_SHA512_ECDSA_SIG; case sigalg_sm2sig_sm3: case 0x0707: /*in tls1.2 case*/ return OID_SM3_SM2_SIG; default: return PS_UNSUPPORTED_FAIL; } } int32_t tlsVerify(ssl_t *ssl, const unsigned char *tbs, psSizeL_t tbsLen, const unsigned char *c, const unsigned char *end, psPubKey_t *pubKey, psVerifyOptions_t *opts) { int32_t rc; uint16_t sigAlgTls = 0; int32_t matrixSigAlg; psSize_t sigLen; psDigestContext_t digestCtx; psResSize_t hashLen = 0; unsigned char hashBuf[SHA512_HASH_SIZE]; psVerifyOptions_t defaultOpts = {0}; psBool_t verifyResult; const unsigned char *orig_c = c; psBool_t useRsa = PS_FALSE; unsigned char *refTbs; psSizeL_t refTbsLen; if (opts == NULL) { opts = &defaultOpts; } if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA) { useRsa = PS_TRUE; /* Default for TLS 1.1 and below. */ } /* (D)TLS 1.2: struct { SignatureAndHashAlgorithm algorithm; opaque signature<0..2^16-1>; } DigitallySigned; TLS 1.1 and below: opaque vector <0..2^16-1> */ # ifdef USE_TLS_1_2 if (NGTD_VER(ssl, v_tls_with_signature_algorithms)) { if (end - c < 2) { goto out_decode_error; } sigAlgTls = *c << 8; c++; sigAlgTls += *c; c++; # if defined(USE_SM2) && defined(USE_SM3) if (sigAlgTls == 0x0707) { sigAlgTls = sigalg_sm2sig_sm3; opts->noPreHash = PS_TRUE; } # endif if (tlsIsSupportedRsaSigAlg(sigAlgTls)) { useRsa = PS_TRUE; } /* Note: this a TLS sig alg ID. */ hashLen = tlsSigAlgToHashLen(sigAlgTls); if (hashLen <= 0) { goto out_decode_error; } psTracePrintTls13SigAlg(INDENT_HS_MSG, "signature algorithm", sigAlgTls, PS_FALSE, PS_TRUE); # ifdef USE_PKCS1_PSS switch (sigAlgTls) { case sigalg_rsa_pss_rsae_sha256: case sigalg_rsa_pss_pss_sha256: opts->useRsaPss = PS_TRUE; opts->rsaPssHashAlg = PKCS1_SHA256_ID; opts->rsaPssSaltLen = SHA256_HASH_SIZE; break; case sigalg_rsa_pss_rsae_sha384: case sigalg_rsa_pss_pss_sha384: opts->useRsaPss = PS_TRUE; opts->rsaPssHashAlg = PKCS1_SHA384_ID; opts->rsaPssSaltLen = SHA384_HASH_SIZE; break; case sigalg_rsa_pss_rsae_sha512: case sigalg_rsa_pss_pss_sha512: opts->useRsaPss = PS_TRUE; opts->rsaPssHashAlg = PKCS1_SHA512_ID; opts->rsaPssSaltLen = SHA512_HASH_SIZE; break; } # ifdef USE_CL_RSA if (opts->useRsaPss) { /* The crypto-cl API for RSA-PSS verification does not support pre-hashing. */ opts->noPreHash = PS_TRUE; } # endif /* USE_CL_RSA */ # endif /* USE_PKCS1_PSS */ } # endif /* USE_TLS_1_2 */ /* Sig alg must match the ciphersuite auth alg. */ if (!useRsa && (ssl->flags & SSL_FLAGS_DHE_WITH_RSA)) { psTraceErrr("Peer used RSA signature for non-RSA suite\n"); goto out_decode_error; } if (useRsa && (ssl->flags & SSL_FLAGS_DHE_WITH_DSA)) { psTraceErrr("Peer used ECDSA signature for non-ECDSA suite\n"); goto out_decode_error; } # ifdef USE_SEC_CONFIG /* Ask the security callback whether the verify operation with this sig alg and key is allowed. */ { psSecOperation_t secOp; psSizeL_t secOpBits; if (useRsa) { secOp = secop_rsa_verify; secOpBits = pubKey->keysize * 8; } else { secOp = secop_ecdsa_verify; secOpBits = pubKey->key.ecc.curve->size * 8; } rc = matrixSslCallSecurityCallback(ssl, secOp, secOpBits, NULL); if (rc < 0) { psTraceErrr("Operation forbidden by security callback\n"); ssl->err = SSL_ALERT_INSUFFICIENT_SECURITY; return rc; } } # endif /* USE_SEC_CONFIG */ /* Parse signature vector length. */ if (end - c < 2) { psTraceErrr("Could not decode TLS signature\n"); goto out_decode_error; } sigLen = *c << 8; c++; sigLen |= *c; c++; /* Sanity check. */ if (sigLen > (end - c)) { psTraceErrr("Sig len sanity check failed\n"); goto out_decode_error; } if (opts == NULL || opts->noPreHash == PS_FALSE) { /* Compute the reference hash. */ if (hashLen == 0) { hashLen = getDefaultSkeHashSize(ssl); } rc = computeSkeHash(ssl, &digestCtx, hashLen, tbs, tbs + tbsLen, hashBuf); if (rc < 0) { goto out_illegal_parameter; } refTbs = hashBuf; refTbsLen = hashLen; } else { /* No pre-hashing before signature verification. Construct the reference tbs as a contiguous block. */ rc = computeSkeTbs(ssl, tbs, tbs + tbsLen, &refTbs, &refTbsLen); if (rc < 0) { return rc; } } /* Now verify the signature. */ if (NGTD_VER(ssl, v_tls_with_pkcs15_auth)) { opts->msgIsDigestInfo = PS_TRUE; } # if defined(USE_SM2) && defined(USE_SM3) if (sigAlgTls == sigalg_sm2sig_sm3) { opts->msgIsDigestInfo = PS_FALSE; } # endif if (sigAlgTls == 0) { matrixSigAlg = useRsa ? OID_RSA_TLS_SIG_ALG : OID_SHA1_ECDSA_SIG; } else { matrixSigAlg = tlsSigAlgToMatrix(sigAlgTls); } if (!NGTD_VER(ssl, v_tls_with_signature_algorithms)) { psTracePrintMatrixSigAlg(INDENT_HS_MSG, "signature algorithm", matrixSigAlg, PS_TRUE); } rc = psVerifySig(ssl->hsPool, refTbs, refTbsLen, c, sigLen, pubKey, matrixSigAlg, &verifyResult, opts); if (rc < 0 || verifyResult != PS_TRUE) { psTraceErrr("Can't verify serverKeyExchange sig\n"); if (refTbs != hashBuf) { psFree(refTbs, ssl->hsPool); } goto out_decrypt_error; } if (refTbs != hashBuf) { psFree(refTbs, ssl->hsPool); } c += sigLen; psAssert(c > orig_c); psAssert(c <= end); return (c - orig_c); out_illegal_parameter: ssl->err = SSL_ALERT_ILLEGAL_PARAMETER; return MATRIXSSL_ERROR; out_decode_error: ssl->err = SSL_ALERT_DECODE_ERROR; return MATRIXSSL_ERROR; out_decrypt_error: ssl->err = SSL_ALERT_DECRYPT_ERROR; return MATRIXSSL_ERROR; } #if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH) /** 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 /* , psSize_t peerSigAlgsLen) */ ) { 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 if (sigAlg == OID_SM3_SM2_SIG) { yes = ((peerSigAlgs & HASH_SIG_SM3_SM2_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 if (sigAlg == OID_SM3_SM2_SIG) { #if defined(USE_SM2) && defined(USE_SM3) we_support = 1; is_non_fips =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 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, psPubKey_t *privKey, psSize_t keySize, int32_t keyAlgorithm, uint16_t peerSigAlgs) { int32 a = certSigAlg; psResSize_t hashLen; #ifndef USE_RSA if (keyAlgorithm == OID_RSA_KEY_ALG) { return PS_UNSUPPORTED_FAIL; } #endif #ifndef USE_ECC if (keyAlgorithm == OID_ECDSA_KEY_ALG) { return PS_UNSUPPORTED_FAIL; } #endif #ifdef USE_ROT_ECC if (keyAlgorithm == OID_ECDSA_KEY_ALG) { psTraceIntInfo("keySize is %hu\n", keySize); psTraceIntInfo("curve ID is %hu\n", privKey->key.ecc.curve->curveId); return psRotCurveToSigAlg(privKey->key.ecc.curve->curveId); } #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 (keyAlgorithm == 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); } } else if (keyAlgorithm == 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 && certSigAlg != OID_SM3_SM2_SIG) { /* Pubkey is ECDSA, but cert is signed with RSA. Convert to corresponding ECDSA alg. */ a = sigAlgRsaToEcdsa(certSigAlg); } } hashLen = psSigAlgToHashLen(a); if (hashLen < 0) { /* unknown sigAlg; error on hashLen */ return hashLen; } /* For RSA signatures, RFC 5246 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 (psIsInsecureSigAlg(a, keyAlgorithm, keySize, hashLen) || !canUseSigAlg(a, keyAlgorithm, peerSigAlgs)) { /* Try to upgrade: This won't select inscure ones. */ a = upgradeSigAlg(a, keyAlgorithm); if (!canUseSigAlg(a, keyAlgorithm, peerSigAlgs)) { /* Stil not supported. Try the next alternative. */ a = upgradeSigAlg(a, keyAlgorithm); if (!canUseSigAlg(a, keyAlgorithm, peerSigAlgs)) { /* Unable to upgrade insecure alg. Have to use the server cert sig alg. */ a = certSigAlg; psTraceIntInfo("Fallback to certificate sigAlg: %d\n", a); } } } psTraceIntInfo("Chose sigAlg %d\n", a); return a; } 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, 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; 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 #if defined(USE_SM2) && defined(USE_SM3) case OID_SM3_SM2_SIG: b1 = 0x7; b2 = 0x7; hLen = SM3_HASH_SIZE; break; #endif default: return PS_UNSUPPORTED_FAIL; /* algorithm not supported */ } if (octet1 && octet2 && hashSize) { *octet1 = b1; *octet2 = b2; *hashSize = hLen; return PS_SUCCESS; } return PS_ARG_FAIL; } #endif /* ! USE_ONLY_PSK_CIPHER_SUITE */ #endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */ #endif /* USE_TLS_1_3_ONLY */