From 5a72845b65d0b39bd2ac0921b3b38b60e34a7128 Mon Sep 17 00:00:00 2001 From: Janne Johansson Date: Thu, 15 Nov 2018 10:12:51 +0200 Subject: [PATCH] MatrixSSL 4.0.1 --- README.html | 3 +- apps/dtls/dtlsClient.c | 2 +- apps/dtls/dtlsServer.c | 4 + apps/ssl/client.c | 20 +- apps/ssl/server.c | 26 +- configs/default/cryptoConfig.h | 7 +- configs/default/matrixsslConfig.h | 6 +- configs/noecc/cryptoConfig.h | 7 +- configs/noecc/matrixsslConfig.h | 6 +- configs/psk/cryptoConfig.h | 23 +- configs/psk/matrixsslConfig.h | 6 +- configs/rsaonly/cryptoConfig.h | 7 +- configs/rsaonly/matrixsslConfig.h | 6 +- configs/tls/cryptoConfig.h | 7 +- configs/tls/matrixsslConfig.h | 6 +- configs/tls13/cryptoConfig.h | 7 +- configs/tls13/matrixsslConfig.h | 6 +- core/makefiles/get_CCARCH.mk | 4 +- core/makefiles/platform_specific.mk | 2 +- core/osdep/include/template.h | 13 + core/src/psStat.c | 14 +- core/src/psbuf.c | 5 +- core/src/psprintf.c | 1 + core/src/sfzclcalendar.c | 4 +- core/src/sfzclstr.c | 2 + core/testsupp/src/sfzutf/sfzutf_main_stdio.c | 2 + core/unit_tests/test_psGetFileBuf.cc | 8 +- crypto/Makefile | 1 + crypto/common/alg_info.c | 84 +- crypto/common/digest_info.c | 237 +++ crypto/cryptoApi.h | 114 +- crypto/cryptoCheck.h | 3 + crypto/cryptolib.h | 11 + crypto/digest/digest.h | 3 +- crypto/digest/hkdf.c | 7 +- crypto/keyformat/pkcs.c | 64 +- crypto/keyformat/x509.c | 475 +----- crypto/keyformat/x509.h | 1 + crypto/pubkey/dh_gen_key.c | 2 +- crypto/pubkey/dh_params.c | 5 +- crypto/pubkey/ecc_curve_config.c | 18 + crypto/pubkey/ecc_priv.c | 4 - crypto/pubkey/pubkey.c | 3 +- crypto/pubkey/pubkey.h | 58 +- crypto/pubkey/pubkey_parse_file.c | 2 +- crypto/pubkey/pubkey_sign.c | 132 +- crypto/pubkey/pubkey_verify.c | 33 +- crypto/pubkey/rsa_priv.c | 1 + crypto/pubkey/rsa_pub.c | 274 ++-- crypto/test/algorithmTest.c | 287 +++- crypto/test/eccTest.c | 2 +- doc/CHANGES_v4.0.html | 20 +- doc/CHANGES_v4.0.md | 50 +- doc/CHANGES_v4.0.txt | 51 +- doc/MatrixSSL_API.pdf | Bin 1577428 -> 1561287 bytes matrixssl/Makefile | 3 + matrixssl/cipherSuite.c | 477 +++--- matrixssl/dtls.c | 2 +- matrixssl/extDecode.c | 28 +- matrixssl/hsDecode.c | 564 ++----- matrixssl/hsHash.c | 32 +- matrixssl/hsNegotiateVersion.c | 715 ++++----- matrixssl/matrixssl.c | 916 ++--------- matrixssl/matrixsslApi.c | 25 +- matrixssl/matrixsslApi.h | 85 +- matrixssl/matrixsslCheck.h | 82 +- matrixssl/matrixsslInitVer.c | 461 ++++++ matrixssl/matrixsslKeys.c | 10 +- matrixssl/matrixsslSecConfig.c | 263 ++++ matrixssl/matrixssllib.h | 198 +-- matrixssl/matrixssllib_secconfig.h | 103 ++ matrixssl/matrixssllib_version.h | 461 ++++++ matrixssl/sslDecode.c | 402 +++-- matrixssl/sslEncode.c | 936 ++++-------- matrixssl/test/sslTest.c | 49 +- matrixssl/tls.c | 656 +------- matrixssl/tls13Authenticate.c | 2 + matrixssl/tls13CipherSuite.c | 10 +- matrixssl/tls13Decode.c | 50 +- matrixssl/tls13DecodeExt.c | 84 +- matrixssl/tls13Encode.c | 102 +- matrixssl/tls13EncodeExt.c | 217 +-- matrixssl/tls13KeyAgree.c | 253 +++- matrixssl/tls13KeySchedule.c | 53 +- matrixssl/tls13Negotiate.c | 23 +- matrixssl/tls13Psk.c | 5 +- matrixssl/tls13Resume.c | 43 +- matrixssl/tls13SigVer.c | 58 +- matrixssl/tls13TrHash.c | 6 +- matrixssl/tlsDefaults.c | 140 +- matrixssl/tlsSigVer.c | 1341 +++++++++++++++++ matrixssl/tlsTrace.c | 338 +++-- matrixssl/version.h | 4 +- ...open.html => release_notes-4-0-1-open.html | 20 +- testkeys/EC/256_EC_KEY.noparam.nopub.pem | 3 + 95 files changed, 6521 insertions(+), 4845 deletions(-) create mode 100644 crypto/common/digest_info.c create mode 100644 matrixssl/matrixsslInitVer.c create mode 100644 matrixssl/matrixsslSecConfig.c create mode 100644 matrixssl/matrixssllib_secconfig.h create mode 100644 matrixssl/matrixssllib_version.h create mode 100644 matrixssl/tlsSigVer.c rename release_notes-4-0-0-open.html => release_notes-4-0-1-open.html (76%) create mode 100644 testkeys/EC/256_EC_KEY.noparam.nopub.pem diff --git a/README.html b/README.html index bd8fe50..e7dfd6e 100644 --- a/README.html +++ b/README.html @@ -11,7 +11,8 @@

Overview

-

MatrixSSL has been continuously maintained since 2002. It is the first open source small footprint SSL stack. Until recently, releases were tracked on http://freecode.com/projects/matrixssl

+

MatrixSSL has been continuously maintained since 2002. It is the first open source small footprint SSL stack. Until recently, releases were tracked on http://freecode.com/projects/matrixssl +

MatrixSSL is an embedded SSL and TLS implementation designed for small footprint IoT devices requiring low overhead per connection. It includes client and server support through TLS 1.3, mutual authentication, session resumption, and implementations of RSA, ECC, AES, SHA1, SHA-256, ChaCha20-Poly1305 and more. The source is well documented and contains portability layers for additional operating systems, cipher suites, and cryptography providers.

diff --git a/apps/dtls/dtlsClient.c b/apps/dtls/dtlsClient.c index ef12a69..1193535 100644 --- a/apps/dtls/dtlsClient.c +++ b/apps/dtls/dtlsClient.c @@ -157,7 +157,7 @@ static int32 dtlsClientConnection(sslKeys_t *keys, sslSessionId_t *sid) # endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */ Memset(&options, 0x0, sizeof(sslSessOpts_t)); - options.versionFlag = SSL_FLAGS_DTLS; + options.versionFlag = SSL_FLAGS_DTLS | SSL_FLAGS_TLS_1_2; options.trustedCAindication = 1; diff --git a/apps/dtls/dtlsServer.c b/apps/dtls/dtlsServer.c index a7d3085..a89a850 100644 --- a/apps/dtls/dtlsServer.c +++ b/apps/dtls/dtlsServer.c @@ -868,6 +868,10 @@ int main(int argc, char **argv) { Memset(&options, 0x0, sizeof(sslSessOpts_t)); options.versionFlag = SSL_FLAGS_DTLS; + if (COMPILED_IN_VER(v_dtls_1_2)) + { + options.versionFlag |= SSL_FLAGS_TLS_1_2; + } options.truncHmac = -1; if (matrixSslNewServerSession(&ssl, keys, diff --git a/apps/ssl/client.c b/apps/ssl/client.c index 3122a09..8f0275e 100644 --- a/apps/ssl/client.c +++ b/apps/ssl/client.c @@ -220,7 +220,7 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, uint16_t groups[TLS_1_3_MAX_GROUPS] = {0}; # endif uint16_t sigAlgs[TLS_MAX_SIGNATURE_ALGORITHMS] = {0}; - int32_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0}; + psProtocolVersion_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0}; psSize_t i; # ifdef USE_ALPN @@ -341,6 +341,7 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, while (supportedVersion) { supportedVersions[i] = atoi((char* )supportedVersion->item); + supportedVersions[i] = DIGIT_TO_VER(supportedVersions[i]); supportedVersion = supportedVersion->next; i++; } @@ -352,7 +353,6 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, Printf("matrixSslSessOptsSetClientTlsVersions failed\n"); goto L_CLOSE_ERR; } - } else if (g_version_range_set) { @@ -366,7 +366,7 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid, } else if (g_version != 0) { - options.versionFlag = tlsMinVerToVersionFlag(g_version); + options.versionFlag = psVerToFlag(DIGIT_TO_VER(g_version)); } options.userPtr = keys; @@ -962,6 +962,8 @@ static void usage(void) " rsa (for RSA keys)\n" " ec (for EC keys ECDSA signature)\n" " ecrsa (for EC keys with RSA signature)\n" + "--psk \n" + " - Load test PSKs.\n" "--groups \n" " - Supported groups.\n" " For example: secp256r1:secp384r1\n" @@ -1220,8 +1222,9 @@ static int32 process_cmd_options(int32 argc, char **argv) case 'V': /* Single version. */ version = atoi(optarg); - if (!matrixSslTlsVersionRangeSupported(version, - version)) + if (!matrixSslTlsVersionRangeSupported( + DIGIT_TO_VER(version), + DIGIT_TO_VER(version))) { Printf("Invalid version: %d\n", version); return -1; @@ -1273,10 +1276,11 @@ static int32 process_cmd_options(int32 argc, char **argv) optarg); return -1; } - g_min_version = atoi((char *)versionRangeList->item); - g_max_version = atoi((char *)versionRangeList->next->item); + g_min_version = DIGIT_TO_VER(atoi((char *)versionRangeList->item)); + g_max_version = DIGIT_TO_VER(atoi((char *)versionRangeList->next->item)); psFreeList(versionRangeList, NULL); - if (!matrixSslTlsVersionRangeSupported(g_min_version, + if (!matrixSslTlsVersionRangeSupported( + g_min_version, g_max_version)) { Printf("Unsupported version range: %s\n", diff --git a/apps/ssl/server.c b/apps/ssl/server.c index dcc3999..059b515 100644 --- a/apps/ssl/server.c +++ b/apps/ssl/server.c @@ -116,8 +116,8 @@ static int g_require_client_auth; static DLListEntry g_conns; static int32 g_exitFlag; static int g_port; -static int g_min_version; -static int g_max_version; +static psProtocolVersion_t g_min_version; +static psProtocolVersion_t g_max_version; static int g_use_default_versions; static int g_disabledCiphers; static uint16_t g_disabledCipher[SSL_MAX_DISABLED_CIPHERS]; @@ -274,9 +274,10 @@ void SNIcallback(void *ssl, char *hostname, int32 hostnameLen, int32 setProtocolVersions(sslSessOpts_t *options) { psList_t *supportedVersion; - int32_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0}; + psProtocolVersion_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0}; psSize_t i; int32 rc; + if (g_supportedVersionsList) { supportedVersion = g_supportedVersionsList; @@ -284,6 +285,7 @@ int32 setProtocolVersions(sslSessOpts_t *options) while (supportedVersion) { supportedVersions[i] = atoi((char* )supportedVersion->item); + supportedVersions[i] = DIGIT_TO_VER(supportedVersions[i]); supportedVersion = supportedVersion->next; i++; } @@ -481,6 +483,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd) if (rc < 0) { Printf("matrixSslSessOptsSetKeyExGroups failed\n"); + close(fd); return rc; } } @@ -500,6 +503,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd) if (rc < 0) { Printf("matrixSslSessOptsSetSigAlgsCert failed\n"); + close(fd); return rc; } } @@ -514,6 +518,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd) if (sigAlgs[i] == 0) { Printf("Invalid signature algorithm parameter\n"); + close(fd); return PS_ARG_FAIL; } sigAlg = sigAlg->next; @@ -525,6 +530,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd) if (rc < 0) { Printf("matrixSslSessOptsSetSigAlgs failed\n"); + close(fd); return rc; } } @@ -1149,9 +1155,10 @@ static int32_t parse_cipher_list(char *cipherListString, encountered OR a request for help is seen (i.e. '-h' option). */ static int32 process_cmd_options(int32 argc, char **argv) { - int optionChar, str_len, version, numCiphers; + int optionChar, str_len, numCiphers; char *cipherListString; psList_t *versionRangeList; + psProtocolVersion_t version; /* Start with all options zeroized. */ Memset(g_keyfilePath, 0, MAX_KEYFILE_PATH); @@ -1163,7 +1170,7 @@ static int32 process_cmd_options(int32 argc, char **argv) Memset(g_password, 0, MAX_PASSWORD_LEN); g_port = HTTPS_PORT; - g_min_version = g_max_version = 3; + g_min_version = g_max_version = v_tls_1_2; g_disabledCiphers = 0; opterr = 0; @@ -1330,7 +1337,7 @@ static int32 process_cmd_options(int32 argc, char **argv) case 'v': /* Single version. */ - version = atoi(optarg); + version = DIGIT_TO_VER(atoi(optarg)); if (!matrixSslTlsVersionRangeSupported(version, version)) { @@ -1346,10 +1353,11 @@ static int32 process_cmd_options(int32 argc, char **argv) { Printf("Invalid version range string: %s\n", optarg); + psFreeList(versionRangeList, NULL); return -1; } - g_min_version = atoi((char *)versionRangeList->item); - g_max_version = atoi((char *)versionRangeList->next->item); + g_min_version = DIGIT_TO_VER(atoi((char *)versionRangeList->item)); + g_max_version = DIGIT_TO_VER(atoi((char *)versionRangeList->next->item)); psFreeList(versionRangeList, NULL); if (!matrixSslTlsVersionRangeSupported(g_min_version, g_max_version)) @@ -1447,6 +1455,7 @@ int32 main(int32 argc, char **argv) if (0 != process_cmd_options(argc, argv)) { + matrixSslDeleteKeys(keys); usage(); return 0; } @@ -1467,6 +1476,7 @@ int32 main(int32 argc, char **argv) || psGetPrngLocked(sessTicketName, sizeof(sessTicketName), NULL) < 0) { psTrace("Error generating session ticket encryption key\n"); + matrixSslDeleteKeys(keys); return EXIT_FAILURE; } if (matrixSslLoadSessionTicketKeys(keys, sessTicketName, diff --git a/configs/default/cryptoConfig.h b/configs/default/cryptoConfig.h index aa08c14..0e0944c 100644 --- a/configs/default/cryptoConfig.h +++ b/configs/default/cryptoConfig.h @@ -44,7 +44,7 @@ /* #define USE_CRYPTO_TRACE */ # ifdef DEBUG -/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ +/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ # endif /******************************************************************************/ @@ -179,7 +179,7 @@ SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting only with newer certificates. */ -/* #define USE_SHA224 *//**< @note Used only for cert signature */ +/* #define USE_SHA224 *//**< @note Used only for cert signature */ # define USE_SHA256/**< @note Required for TLS 1.2 and above */ # define USE_HMAC_SHA256 # define USE_SHA384/**< @pre USE_SHA512 */ @@ -274,7 +274,7 @@ # ifdef USE_OCSP # define USE_OCSP_RESPONSE # define USE_OCSP_REQUEST -# elif defined(USE_X509) && defined(USE_SHA1) +# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE) /** Enable parsing and writing of OCSP responses. This is enough to support OCSP stapling. @@ -298,4 +298,3 @@ #endif /* _h_PS_CRYPTOCONFIG */ /******************************************************************************/ - diff --git a/configs/default/matrixsslConfig.h b/configs/default/matrixsslConfig.h index 472b4b1..6c7cea3 100644 --- a/configs/default/matrixsslConfig.h +++ b/configs/default/matrixsslConfig.h @@ -108,6 +108,7 @@ extern "C" { /* TLS 1.2 ciphers */ /* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */ /* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ +/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */ /** Non-Ephemeral RSA keys/certificates */ # define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */ @@ -181,7 +182,7 @@ extern "C" { Note: The RC4 cipher suites below need to disabled according to RFC 7465. */ /* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */ - + /******************************************************************************/ /** Ephemeral key cache support. @@ -420,7 +421,7 @@ extern "C" { # define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ # define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ -/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ +/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ # endif # ifdef __cplusplus @@ -429,4 +430,3 @@ extern "C" { #endif /* _h_MATRIXCONFIG */ /******************************************************************************/ - diff --git a/configs/noecc/cryptoConfig.h b/configs/noecc/cryptoConfig.h index 30dbf7e..032a814 100644 --- a/configs/noecc/cryptoConfig.h +++ b/configs/noecc/cryptoConfig.h @@ -44,7 +44,7 @@ /* #define USE_CRYPTO_TRACE */ # ifdef DEBUG -/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ +/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ # endif /******************************************************************************/ @@ -179,7 +179,7 @@ SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting only with newer certificates. */ -/* #define USE_SHA224 *//**< @note Used only for cert signature */ +/* #define USE_SHA224 *//**< @note Used only for cert signature */ # define USE_SHA256/**< @note Required for TLS 1.2 and above */ # define USE_HMAC_SHA256 # define USE_SHA384/**< @pre USE_SHA512 */ @@ -274,7 +274,7 @@ # ifdef USE_OCSP # define USE_OCSP_RESPONSE # define USE_OCSP_REQUEST -# elif defined(USE_X509) && defined(USE_SHA1) +# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE) /** Enable parsing and writing of OCSP responses. This is enough to support OCSP stapling. @@ -298,4 +298,3 @@ #endif /* _h_PS_CRYPTOCONFIG */ /******************************************************************************/ - diff --git a/configs/noecc/matrixsslConfig.h b/configs/noecc/matrixsslConfig.h index 29e697b..1268ea1 100644 --- a/configs/noecc/matrixsslConfig.h +++ b/configs/noecc/matrixsslConfig.h @@ -108,6 +108,7 @@ extern "C" { /* TLS 1.2 ciphers */ # define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 # define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */ /** Non-Ephemeral RSA keys/certificates */ # define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */ @@ -181,7 +182,7 @@ extern "C" { Note: The RC4 cipher suites below need to disabled according to RFC 7465. */ /* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */ - + /******************************************************************************/ /** Ephemeral key cache support. @@ -420,7 +421,7 @@ extern "C" { # define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ # define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ -/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ +/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ # endif # ifdef __cplusplus @@ -429,4 +430,3 @@ extern "C" { #endif /* _h_MATRIXCONFIG */ /******************************************************************************/ - diff --git a/configs/psk/cryptoConfig.h b/configs/psk/cryptoConfig.h index 6f7c767..11798ec 100644 --- a/configs/psk/cryptoConfig.h +++ b/configs/psk/cryptoConfig.h @@ -44,7 +44,7 @@ /* #define USE_CRYPTO_TRACE */ # ifdef DEBUG -/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ +/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ # endif /******************************************************************************/ @@ -109,7 +109,7 @@ @see http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf */ # ifdef USE_ECC -/* #define USE_SECP192R1 *//**< @security FIPS allowed for sig ver only. */ +/* #define USE_SECP192R1 *//**< @security FIPS allowed for sig ver only. */ /* #define USE_SECP224R1 */ /* #define USE_SECP256R1 *//**< @security NIST_SHALL */ /* #define USE_SECP384R1 *//**< @security NIST_SHALL */ @@ -179,10 +179,10 @@ SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting only with newer certificates. */ -/* #define USE_SHA224 *//**< @note Used only for cert signature */ +/* #define USE_SHA224 *//**< @note Used only for cert signature */ # define USE_SHA256/**< @note Required for TLS 1.2 and above */ # define USE_HMAC_SHA256 -/* #define USE_SHA384 *//**< @pre USE_SHA512 */ +/* #define USE_SHA384 *//**< @pre USE_SHA512 */ /* #define USE_HMAC_SHA384 */ /* #define USE_SHA512 */ @@ -198,7 +198,7 @@ @note ENABLE_MD5_SIGNED_CERTS can additionally be configured below. */ /* #define USE_MD5 */ -/* #define USE_MD5SHA1 *//* Required for < TLS 1.2 Handshake */ +/* #define USE_MD5SHA1 *//* Required for < TLS 1.2 Handshake */ /* #define USE_HMAC_MD5 */ /** @@ -274,7 +274,7 @@ # ifdef USE_OCSP # define USE_OCSP_RESPONSE # define USE_OCSP_REQUEST -# elif defined(USE_X509) && defined(USE_SHA1) +# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE) /** Enable parsing and writing of OCSP responses. This is enough to support OCSP stapling. @@ -287,15 +287,14 @@ Various PKCS standards support */ /* #define USE_PRIVATE_KEY_PARSING */ -/* #define USE_PKCS5 *//**< v2.0 PBKDF encrypted priv keys. @pre USE_3DES */ +/* #define USE_PKCS5 *//**< v2.0 PBKDF encrypted priv keys. @pre USE_3DES */ /**< Enable PBKDF1 in priv key PEM encryption. @pre USE_PKCS5 and @pre USE_MD5. @security Not recommended. */ /* #define USE_PBKDF1 */ -/* #define USE_PKCS8 *//* Alternative private key storage format */ -/* #define USE_PKCS12 *//**< @pre USE_PKCS8 */ -/* #define USE_PKCS1_OAEP *//* OAEP padding algorithm */ -/* #define USE_PKCS1_PSS *//* PSS padding algorithm */ +/* #define USE_PKCS8 *//* Alternative private key storage format */ +/* #define USE_PKCS12 *//**< @pre USE_PKCS8 */ +/* #define USE_PKCS1_OAEP *//* OAEP padding algorithm */ +/* #define USE_PKCS1_PSS *//* PSS padding algorithm */ #endif /* _h_PS_CRYPTOCONFIG */ /******************************************************************************/ - diff --git a/configs/psk/matrixsslConfig.h b/configs/psk/matrixsslConfig.h index 008677d..b7cf2ed 100644 --- a/configs/psk/matrixsslConfig.h +++ b/configs/psk/matrixsslConfig.h @@ -108,6 +108,7 @@ extern "C" { /* TLS 1.2 ciphers */ /* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */ /* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ +/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */ /** Non-Ephemeral RSA keys/certificates */ /* #define USE_TLS_RSA_WITH_AES_128_CBC_SHA *//**< @security NIST_SHALL */ @@ -181,7 +182,7 @@ extern "C" { Note: The RC4 cipher suites below need to disabled according to RFC 7465. */ /* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */ - + /******************************************************************************/ /** Ephemeral key cache support. @@ -420,7 +421,7 @@ extern "C" { # define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ # define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ -/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ +/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ # endif # ifdef __cplusplus @@ -429,4 +430,3 @@ extern "C" { #endif /* _h_MATRIXCONFIG */ /******************************************************************************/ - diff --git a/configs/rsaonly/cryptoConfig.h b/configs/rsaonly/cryptoConfig.h index 8b4b4ba..7066a93 100644 --- a/configs/rsaonly/cryptoConfig.h +++ b/configs/rsaonly/cryptoConfig.h @@ -44,7 +44,7 @@ /* #define USE_CRYPTO_TRACE */ # ifdef DEBUG -/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ +/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ # endif /******************************************************************************/ @@ -179,7 +179,7 @@ SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting only with newer certificates. */ -/* #define USE_SHA224 *//**< @note Used only for cert signature */ +/* #define USE_SHA224 *//**< @note Used only for cert signature */ # define USE_SHA256/**< @note Required for TLS 1.2 and above */ # define USE_HMAC_SHA256 # define USE_SHA384/**< @pre USE_SHA512 */ @@ -274,7 +274,7 @@ # ifdef USE_OCSP # define USE_OCSP_RESPONSE # define USE_OCSP_REQUEST -# elif defined(USE_X509) && defined(USE_SHA1) +# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE) /** Enable parsing and writing of OCSP responses. This is enough to support OCSP stapling. @@ -298,4 +298,3 @@ #endif /* _h_PS_CRYPTOCONFIG */ /******************************************************************************/ - diff --git a/configs/rsaonly/matrixsslConfig.h b/configs/rsaonly/matrixsslConfig.h index 9b6e612..303a1b7 100644 --- a/configs/rsaonly/matrixsslConfig.h +++ b/configs/rsaonly/matrixsslConfig.h @@ -108,6 +108,7 @@ extern "C" { /* TLS 1.2 ciphers */ /* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */ /* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ +/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */ /** Non-Ephemeral RSA keys/certificates */ # define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */ @@ -181,7 +182,7 @@ extern "C" { Note: The RC4 cipher suites below need to disabled according to RFC 7465. */ /* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */ - + /******************************************************************************/ /** Ephemeral key cache support. @@ -420,7 +421,7 @@ extern "C" { # define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ # define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ -/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ +/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ # endif # ifdef __cplusplus @@ -429,4 +430,3 @@ extern "C" { #endif /* _h_MATRIXCONFIG */ /******************************************************************************/ - diff --git a/configs/tls/cryptoConfig.h b/configs/tls/cryptoConfig.h index dd3b3b7..13fee06 100644 --- a/configs/tls/cryptoConfig.h +++ b/configs/tls/cryptoConfig.h @@ -44,7 +44,7 @@ /* #define USE_CRYPTO_TRACE */ # ifdef DEBUG -/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ +/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ # endif /******************************************************************************/ @@ -179,7 +179,7 @@ SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting only with newer certificates. */ -/* #define USE_SHA224 *//**< @note Used only for cert signature */ +/* #define USE_SHA224 *//**< @note Used only for cert signature */ # define USE_SHA256/**< @note Required for TLS 1.2 and above */ # define USE_HMAC_SHA256 # define USE_SHA384/**< @pre USE_SHA512 */ @@ -274,7 +274,7 @@ # ifdef USE_OCSP # define USE_OCSP_RESPONSE # define USE_OCSP_REQUEST -# elif defined(USE_X509) && defined(USE_SHA1) +# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE) /** Enable parsing and writing of OCSP responses. This is enough to support OCSP stapling. @@ -298,4 +298,3 @@ #endif /* _h_PS_CRYPTOCONFIG */ /******************************************************************************/ - diff --git a/configs/tls/matrixsslConfig.h b/configs/tls/matrixsslConfig.h index 472b4b1..6c7cea3 100644 --- a/configs/tls/matrixsslConfig.h +++ b/configs/tls/matrixsslConfig.h @@ -108,6 +108,7 @@ extern "C" { /* TLS 1.2 ciphers */ /* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */ /* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ +/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */ /** Non-Ephemeral RSA keys/certificates */ # define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */ @@ -181,7 +182,7 @@ extern "C" { Note: The RC4 cipher suites below need to disabled according to RFC 7465. */ /* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */ - + /******************************************************************************/ /** Ephemeral key cache support. @@ -420,7 +421,7 @@ extern "C" { # define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ # define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ -/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ +/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ # endif # ifdef __cplusplus @@ -429,4 +430,3 @@ extern "C" { #endif /* _h_MATRIXCONFIG */ /******************************************************************************/ - diff --git a/configs/tls13/cryptoConfig.h b/configs/tls13/cryptoConfig.h index aa08c14..0e0944c 100644 --- a/configs/tls13/cryptoConfig.h +++ b/configs/tls13/cryptoConfig.h @@ -44,7 +44,7 @@ /* #define USE_CRYPTO_TRACE */ # ifdef DEBUG -/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ +/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */ # endif /******************************************************************************/ @@ -179,7 +179,7 @@ SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting only with newer certificates. */ -/* #define USE_SHA224 *//**< @note Used only for cert signature */ +/* #define USE_SHA224 *//**< @note Used only for cert signature */ # define USE_SHA256/**< @note Required for TLS 1.2 and above */ # define USE_HMAC_SHA256 # define USE_SHA384/**< @pre USE_SHA512 */ @@ -274,7 +274,7 @@ # ifdef USE_OCSP # define USE_OCSP_RESPONSE # define USE_OCSP_REQUEST -# elif defined(USE_X509) && defined(USE_SHA1) +# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE) /** Enable parsing and writing of OCSP responses. This is enough to support OCSP stapling. @@ -298,4 +298,3 @@ #endif /* _h_PS_CRYPTOCONFIG */ /******************************************************************************/ - diff --git a/configs/tls13/matrixsslConfig.h b/configs/tls13/matrixsslConfig.h index 472b4b1..6c7cea3 100644 --- a/configs/tls13/matrixsslConfig.h +++ b/configs/tls13/matrixsslConfig.h @@ -108,6 +108,7 @@ extern "C" { /* TLS 1.2 ciphers */ /* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */ /* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ +/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */ /** Non-Ephemeral RSA keys/certificates */ # define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */ @@ -181,7 +182,7 @@ extern "C" { Note: The RC4 cipher suites below need to disabled according to RFC 7465. */ /* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */ - + /******************************************************************************/ /** Ephemeral key cache support. @@ -420,7 +421,7 @@ extern "C" { # define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ # define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */ -/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ +/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */ # endif # ifdef __cplusplus @@ -429,4 +430,3 @@ extern "C" { #endif /* _h_MATRIXCONFIG */ /******************************************************************************/ - diff --git a/core/makefiles/get_CCARCH.mk b/core/makefiles/get_CCARCH.mk index 60b0a9e..5c8df9a 100644 --- a/core/makefiles/get_CCARCH.mk +++ b/core/makefiles/get_CCARCH.mk @@ -10,8 +10,10 @@ ifeq '$(CCARCH)' '' # some versions of GCC) CCARCH:=$(shell $(CLEAN_ENV) $(CC) -dumpmachine) +ARM_ARCH ?= armv7-a + ifeq '$(CCARCH)' '' -$(error Unable to determine compiler architecture. +$(error Unable to determine compiler architecture.) $(CC) $(CFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) -print-multiarch or $(CC) -v or $(CC) -dumpmachine does not work. Please, provide CCARCH manually via an environment variable.) endif endif diff --git a/core/makefiles/platform_specific.mk b/core/makefiles/platform_specific.mk index 8d4aabc..df906c0 100644 --- a/core/makefiles/platform_specific.mk +++ b/core/makefiles/platform_specific.mk @@ -19,7 +19,7 @@ ifneq (,$(NEON_VARIANT)) CFLAGS_ENABLE_NEON=-march=armv7-a -mfpu=neon else # No neon mentioned. Request float abi to be softfp. -CFLAGS_ENABLE_NEON=-march=armv7-a -mfloat-abi=softfp -mfpu=neon +CFLAGS_ENABLE_NEON=$(CFLAGS_ARCHITECTURE_VARIANT) -mfloat-abi=softfp -mfpu=neon endif endif diff --git a/core/osdep/include/template.h b/core/osdep/include/template.h index 6738747..7ad1f51 100644 --- a/core/osdep/include/template.h +++ b/core/osdep/include/template.h @@ -9,6 +9,18 @@ __END__ * Wrapper for system header __FILENAME__ */ +#ifdef MATRIX_COMMERCIAL +/***************************************************************************** +* Copyright (c) 2017 INSIDE Secure Oy. All Rights Reserved. +* +* This confidential and proprietary software may be used only as authorized +* by a licensing agreement from INSIDE Secure. +* +* The entire notice above must be reproduced on all authorized copies that +* may only be made to the extent permitted by a licensing agreement from +* INSIDE Secure. +*****************************************************************************/ +#else /***************************************************************************** * Copyright (c) 2017 INSIDE Secure Oy. All Rights Reserved. * @@ -33,6 +45,7 @@ __END__ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * http://www.gnu.org/copyleft/gpl.html *****************************************************************************/ +#endif /* MATRIX_COMMERCIAL */ /* This file just includes system header __TOFILE__. In case your system does not include all functions diff --git a/core/src/psStat.c b/core/src/psStat.c index a525fb6..7a01df5 100644 --- a/core/src/psStat.c +++ b/core/src/psStat.c @@ -143,12 +143,18 @@ psStatCompByteSeqResult_t psStatCompByteSeq(const unsigned char *a, res.lcss_freq = num_longest_match_runs; res.num_match_runs = num_match_runs; - res.avg_match_run_len = (int)((double)sum_match_runs / - (double)num_match_runs); + if (num_match_runs > 0) + res.avg_match_run_len = (int)((double)sum_match_runs / + (double)num_match_runs); + else + res.avg_match_run_len = 0; res.num_diff_runs = num_diff_runs; - res.avg_diff_run_len = (int)((double)sum_diff_runs / - (double)num_diff_runs); + if (num_diff_runs > 0) + res.avg_diff_run_len = (int)((double)sum_diff_runs / + (double)num_diff_runs); + else + res.avg_diff_run_len = 0; res.filled = 1; diff --git a/core/src/psbuf.c b/core/src/psbuf.c index 2610748..5267823 100644 --- a/core/src/psbuf.c +++ b/core/src/psbuf.c @@ -811,7 +811,10 @@ int32_t psDynBufAppendTlsVector(psDynBuf_t *db, return PS_ARG_FAIL; } - target = psDynBufAppendSize(db, len + extralen); + if ((target = psDynBufAppendSize(db, len + extralen)) == NULL) + { + return PS_FAIL; + } if (extralen == 1) { diff --git a/core/src/psprintf.c b/core/src/psprintf.c index fa0105c..9e3b1b5 100644 --- a/core/src/psprintf.c +++ b/core/src/psprintf.c @@ -468,6 +468,7 @@ next_ch: case 'd': l += 2; /* fall-through. */ case 'o': l += 8; + /* fall-through. */ case 'c': /* Promote "long" to "long long" on LP64 architectures. */ if (arg_size > 0 && sizeof(long) > sizeof(int)) diff --git a/core/src/sfzclcalendar.c b/core/src/sfzclcalendar.c index 72934b8..ea2a291 100644 --- a/core/src/sfzclcalendar.c +++ b/core/src/sfzclcalendar.c @@ -448,7 +448,7 @@ sfzcl_make_time(SfzclCalendarTime calendar_time, SfzclTime *time_return, { int days_per_month; - while (calendar_time->month > 12) + while (calendar_time->month > 11) { #ifdef DEBUG L_DEBUG(LF_CERTLIB, "Month too large, adjusting %d", @@ -477,7 +477,7 @@ sfzcl_make_time(SfzclCalendarTime calendar_time, SfzclTime *time_return, #endif if (calendar_time->month == 0) { - calendar_time->month = 12; + calendar_time->month = 11; calendar_time->year--; } else diff --git a/core/src/sfzclstr.c b/core/src/sfzclstr.c index ac87829..8442f4c 100644 --- a/core/src/sfzclstr.c +++ b/core/src/sfzclstr.c @@ -118,6 +118,8 @@ sfzcl_str_realloc(SfzclStr str, size_t new_length) L_DEBUG(LF_TOTAL_PROGRESS, "Failed to convert charset %u (%u bit chars).", str->charset, str->bits); + SPAL_Memory_Free(newp); + newp = NULL; break; } } diff --git a/core/testsupp/src/sfzutf/sfzutf_main_stdio.c b/core/testsupp/src/sfzutf/sfzutf_main_stdio.c index 2e97adf..03f4e35 100644 --- a/core/testsupp/src/sfzutf/sfzutf_main_stdio.c +++ b/core/testsupp/src/sfzutf/sfzutf_main_stdio.c @@ -420,6 +420,8 @@ file_readArgs( if (newArgc >= SFZUTF_FILE_MAX_ARGS) { error_p = "Too many arguments"; + SFZUTF_FREE(line_p); + SFZUTF_FREE(newArgv); return error_p; } diff --git a/core/unit_tests/test_psGetFileBuf.cc b/core/unit_tests/test_psGetFileBuf.cc index 1710a8a..302c26d 100644 --- a/core/unit_tests/test_psGetFileBuf.cc +++ b/core/unit_tests/test_psGetFileBuf.cc @@ -77,7 +77,7 @@ AUTO_TEST(TEST_psGetFileBuf_empty_file) { return SKIPPED; } - + res = psGetFileBuf(pool, file, &buf, &len); FAIL_IF(res != PS_SUCCESS); FAIL_IF(buf == NULL); @@ -100,7 +100,7 @@ AUTO_TEST(TEST_psGetFileBuf_endless_file) { return SKIPPED; } - + res = psGetFileBuf(pool, file, &buf, &len); FAIL_IF(res != PS_SUCCESS); FAIL_IF(buf == NULL); @@ -125,7 +125,7 @@ AUTO_TEST(TEST_psGetFileBuf_4294967295_bytes_file) take a long time. */ return SKIPPED; } - + FAIL_IF(system("rm " FILENAME) < -1); FAIL_IF(system("fallocate -l 4294967295 " FILENAME) < -1); if (!can_read(FILENAME)) @@ -166,7 +166,7 @@ AUTO_TEST(TEST_psGetFileBuf_4294967297_bytes_file) take a long time. */ return SKIPPED; } - + FAIL_IF(system("rm " FILENAME) < -1); FAIL_IF(system("fallocate -l 4294967297 " FILENAME) < -1); if (!can_read(FILENAME)) diff --git a/crypto/Makefile b/crypto/Makefile index 28325d5..60b4d42 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -9,6 +9,7 @@ include $(MATRIXSSL_ROOT)/common.mk SRC:=\ common/alg_info.c \ + common/digest_info.c \ symmetric/aes.c \ symmetric/aesCBC.c \ symmetric/aesGCM.c \ diff --git a/crypto/common/alg_info.c b/crypto/common/alg_info.c index 4f3a0f5..0c766b1 100644 --- a/crypto/common/alg_info.c +++ b/crypto/common/alg_info.c @@ -95,6 +95,22 @@ psResSize_t psSigAlgToHashLen(int32_t sigAlg) case OID_SHA512_RSA_SIG: case OID_SHA512_ECDSA_SIG: return SHA512_HASH_SIZE; +# ifdef USE_PKCS1_PSS + /* + The PSS IDs are not part of the same range as the above OIDs, + but they do not conflict with the OIDs either. Support them here + for convenience. Now one can always map e.g. cert->sigAlgorithm + to hash length. + */ + case PKCS1_SHA1_ID: + return SHA1_HASH_SIZE; + case PKCS1_SHA256_ID: + return SHA256_HASH_SIZE; + case PKCS1_SHA384_ID: + return SHA384_HASH_SIZE; + case PKCS1_SHA512_ID: + return SHA512_HASH_SIZE; +# endif default: return PS_UNSUPPORTED_FAIL; } @@ -218,7 +234,10 @@ int32_t psHashLenToSigAlg(psSize_t hash_len, /** Return PS_TRUE if sigAlg is deemed insecure. Return PS_FALSE otherwise. */ -psBool_t psIsInsecureSigAlg(int32_t sigAlg, int keyAlgorithm, psSize_t keySize, psSize_t hashSize) +psBool_t psIsInsecureSigAlg(int32_t sigAlg, + int keyAlgorithm, + psSize_t keySize, + psSize_t hashSize) { if (sigAlg == OID_MD2_RSA_SIG || sigAlg == OID_MD5_RSA_SIG @@ -236,6 +255,69 @@ psBool_t psIsInsecureSigAlg(int32_t sigAlg, int keyAlgorithm, psSize_t keySize, return PS_FALSE; } +/* Return PS_TRUE if hashLen is valid for sigAlg, + e.g. OID_SHA256_RSA_SIG requires hashLen == 32. */ +psBool_t psIsValidHashLenSigAlgCombination(psSize_t hashLen, + int32_t sigAlg) +{ + switch (sigAlg) + { +# ifdef USE_MD2 + case OID_MD2_RSA_SIG: + if (hashLen != MD2_HASH_SIZE) + { + return PS_FALSE; + } + break; +# endif /* USE_MD2 */ +# ifdef USE_MD5 + case OID_MD5_RSA_SIG: + if (hashLen != MD5_HASH_SIZE) + { + return PS_FALSE; + } + break; +# endif /* USE_MD5 */ + case OID_SHA1_RSA_SIG: + if (hashLen != SHA1_HASH_SIZE) + { + return PS_FALSE; + } + break; +#ifdef USE_SHA224 + case OID_SHA224_RSA_SIG: + if (hashLen != SHA224_HASH_SIZE) + { + return PS_FALSE; + } + break; +#endif /* USE_SHA224 */ + case OID_SHA256_RSA_SIG: + if (hashLen != SHA256_HASH_SIZE) + { + return PS_FALSE; + } + break; + case OID_SHA384_RSA_SIG: + if (hashLen != SHA384_HASH_SIZE) + { + return PS_FALSE; + } + break; + case OID_SHA512_RSA_SIG: + if (hashLen != SHA512_HASH_SIZE) + { + return PS_FALSE; + } + break; + default: + psTraceIntCrypto("Unsupported RSA signature alg: %d\n", sigAlg); + return PS_FALSE; + } + + return PS_TRUE; +} + /** Given the name of a signature algorithm (section 4.3.2 in TLS 1.3 draft #28), return its two-byte SignatureScheme identifier. */ uint16_t psGetNamedSigAlgId(const char *name) diff --git a/crypto/common/digest_info.c b/crypto/common/digest_info.c new file mode 100644 index 0000000..f7d9a54 --- /dev/null +++ b/crypto/common/digest_info.c @@ -0,0 +1,237 @@ +/** + * @file digest_info.c + * @version $Format:%h%d$ + * + * Static DigestInfo prefixes and querying functions for PKCS #1.5. + */ +/* + * Copyright (c) 2018 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 "../cryptoImpl.h" + +# ifdef USE_RSA + +/* + ASN.1 DER encoded DigestInfos. + In RSA signature verification, the prefix of the RSA-decrypted message + should be compared against one of these. The correct one can be fetched + with psGetDigestInfoPrefix, which takes in as arguments the sig alg ID + and the length of the decrypted message. Each DigestInfo has two variants: + one with optional NULL parameters in the AlgorithmIdentifier, the other + without. +*/ + +# ifdef USE_MD2 +static const unsigned char PKCS1Dig_MD2[] = +{ + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 +}; +static const unsigned char PKCS1Dig_MD2_ALT[] = +{ + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x02, 0x02, 0x04, 0x10 +}; +# endif /* USE_MD2 */ + +# ifdef USE_MD5 +static const unsigned char PKCS1Dig_MD5[] = +{ + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 +}; +static const unsigned char PKCS1Dig_MD5_ALT[] = +{ + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x02, 0x05, 0x04, 0x10 +}; +# endif /* USE_MD5 */ + +# ifdef USE_SHA1 +static const unsigned char PKCS1Dig_SHA1[] = +{ + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 +}; +static const unsigned char PKCS1Dig_SHA1_ALT[] = +{ + 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x04, 0x14 +}; +# endif /* USE_SHA1 */ + +#ifdef USE_SHA224 +static const unsigned char PKCS1Dig_SHA224[] = +{ + 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c +}; +static const unsigned char PKCS1Dig_SHA224_ALT[] = +{ + 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x04, 0x1c +}; +# endif /* USE_SHA224 */ + +# ifdef USE_SHA256 +static const unsigned char PKCS1Dig_SHA256[] = +{ + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 +}; +static const unsigned char PKCS1Dig_SHA256_ALT[] = +{ + 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20 +}; +# endif /* USE_SHA256 */ + +# ifdef USE_SHA384 +static const unsigned char PKCS1Dig_SHA384[] = +{ + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 +}; +static const unsigned char PKCS1Dig_SHA384_ALT[] = +{ + 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30 +}; +# endif /* USE_SHA384 */ + +# ifdef USE_SHA512 +static const unsigned char PKCS1Dig_SHA512[] = +{ + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 +}; +static const unsigned char PKCS1Dig_SHA512_ALT[] = +{ + 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40 +}; +# endif /* USE_SHA512 */ + +const +unsigned char *psGetDigestInfoPrefix(int32_t len, + int32_t sigAlg) +{ + switch (sigAlg) + { +# ifdef USE_MD2 + case OID_MD2_RSA_SIG: + if (len == sizeof(PKCS1Dig_MD2) + MD2_HASH_SIZE) + { + return PKCS1Dig_MD2; + } + else if (len == sizeof(PKCS1Dig_MD2_ALT) + MD2_HASH_SIZE) + { + return PKCS1Dig_MD2_ALT; + } + break; +# endif /* USE_MD2 */ +# ifdef USE_MD5 + case OID_MD5_RSA_SIG: + if (len == sizeof(PKCS1Dig_MD5) + MD5_HASH_SIZE) + { + return PKCS1Dig_MD5; + } + else if (len == sizeof(PKCS1Dig_MD5_ALT) + MD5_HASH_SIZE) + { + return PKCS1Dig_MD5_ALT; + } + break; +# endif /* USE_MD5 */ +# ifdef USE_SHA1 + case OID_SHA1_RSA_SIG: + if (len == sizeof(PKCS1Dig_SHA1) + SHA1_HASH_SIZE) + { + return PKCS1Dig_SHA1; + } + else if (len == sizeof(PKCS1Dig_SHA1_ALT) + SHA1_HASH_SIZE) + { + return PKCS1Dig_SHA1_ALT; + } + break; +# endif /* USE_SHA1 */ +# ifdef USE_SHA224 + case OID_SHA224_RSA_SIG: + if (len == sizeof(PKCS1Dig_SHA224) + SHA224_HASH_SIZE) + { + return PKCS1Dig_SHA224; + } + else if (len == sizeof(PKCS1Dig_SHA224_ALT) + SHA224_HASH_SIZE) + { + return PKCS1Dig_SHA224_ALT; + } + break; +# endif /* USE_SHA224 */ +# ifdef USE_SHA256 + case OID_SHA256_RSA_SIG: + if (len == sizeof(PKCS1Dig_SHA256) + SHA256_HASH_SIZE) + { + return PKCS1Dig_SHA256; + } + else if (len == sizeof(PKCS1Dig_SHA256_ALT) + SHA256_HASH_SIZE) + { + return PKCS1Dig_SHA256_ALT; + } + break; +# endif /* USE_SHA256 */ +# ifdef USE_SHA384 + case OID_SHA384_RSA_SIG: + if (len == sizeof(PKCS1Dig_SHA384) + SHA384_HASH_SIZE) + { + return PKCS1Dig_SHA384; + } + else if (len == sizeof(PKCS1Dig_SHA384_ALT) + SHA384_HASH_SIZE) + { + return PKCS1Dig_SHA384_ALT; + } + break; +# endif /* USE_SHA384 */ +# ifdef USE_SHA512 + case OID_SHA512_RSA_SIG: + if (len == sizeof(PKCS1Dig_SHA512) + SHA512_HASH_SIZE) + { + return PKCS1Dig_SHA512; + } + else if (len == sizeof(PKCS1Dig_SHA512_ALT) + SHA512_HASH_SIZE) + { + return PKCS1Dig_SHA512_ALT; + } + break; +# endif /* USE_SHA512 */ + default: + psTraceCrypto("Unsupported RSA signature algorithm\n"); + return NULL; + } + + return NULL; +} + +# endif /* USE_RSA */ diff --git a/crypto/cryptoApi.h b/crypto/cryptoApi.h index c8a0151..47408e4 100644 --- a/crypto/cryptoApi.h +++ b/crypto/cryptoApi.h @@ -625,6 +625,57 @@ PSPUBLIC void psHmacSha384Final(psHmacSha384_t * ctx, unsigned char hash[SHA384_HASHLEN]); # endif +# ifdef USE_PEM_DECODE +typedef enum { + PEM_TYPE_ANY = 0, + PEM_TYPE_KEY, + PEM_TYPE_PRIVATE_KEY, + PEM_TYPE_PUBLIC_KEY, + PEM_TYPE_CERTIFICATE +} psPemType_t; + + +PSPUBLIC int32_t +psPemFileToDer(psPool_t *pool, + const char *fileName, + const char *password, + psPemType_t expectedPemType, + unsigned char **derOut, + psSizeL_t *derOutLen); + +PSPUBLIC psBool_t +psPemCheckOk(const unsigned char *pemBuf, + psSizeL_t pemBufLen, + psPemType_t pemType, + char **startp, + char **endp, + psSizeL_t *pemlen); + +PSPUBLIC int32_t +psPemDecode(psPool_t *pool, + const unsigned char *pemBufIn, + psSizeL_t pemBufLen, + const char *password, + unsigned char **out, + psSizeL_t *outlen); + +PSPUBLIC psRes_t +psPemCertBufToList(psPool_t *pool, + const unsigned char *buf, + psSizeL_t len, + psList_t **x509certList); + +PSPUBLIC int32_t +psPemTryDecode(psPool_t *pool, + const unsigned char *in, + psSizeL_t inLen, + psPemType_t pemType, + const char *password, + unsigned char **out, + psSizeL_t *outlen); + +# endif /* USE_PEM_DECODE */ + /******************************************************************************/ /* Private Key Parsing @@ -675,58 +726,8 @@ PSPUBLIC void psPkcs5Pbkdf2(unsigned char *password, uint32 pLen, /* Public Key Cryptography */ -# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) - -typedef enum { - PEM_TYPE_ANY = 0, - PEM_TYPE_KEY, - PEM_TYPE_PRIVATE_KEY, - PEM_TYPE_PUBLIC_KEY, - PEM_TYPE_CERTIFICATE -} psPemType_t; - -# ifdef USE_PEM_DECODE - -PSPUBLIC int32_t -psPemFileToDer(psPool_t *pool, - const char *fileName, - const char *password, - psPemType_t expectedPemType, - unsigned char **derOut, - psSizeL_t *derOutLen); - -PSPUBLIC psBool_t -psPemCheckOk(const unsigned char *pemBuf, - psSizeL_t pemBufLen, - psPemType_t pemType, - char **startp, - char **endp, - psSizeL_t *pemlen); - -PSPUBLIC int32_t -psPemDecode(psPool_t *pool, - const unsigned char *pemBufIn, - psSizeL_t pemBufLen, - const char *password, - unsigned char **out, - psSizeL_t *outlen); - -PSPUBLIC psRes_t -psPemCertBufToList(psPool_t *pool, - const unsigned char *buf, - psSizeL_t len, - psList_t **x509certList); -# endif /* USE_PEM_DECODE */ - -PSPUBLIC int32_t -psPemTryDecode(psPool_t *pool, - const unsigned char *in, - psSizeL_t inLen, - psPemType_t pemType, - const char *password, - unsigned char **out, - psSizeL_t *outlen); +# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) || defined(USE_X25519) || defined(USE_ED25519) PSPUBLIC int32_t psInitPubKey(psPool_t *pool, psPubKey_t *key, uint8_t type); PSPUBLIC void psClearPubKey(psPubKey_t *key); PSPUBLIC int32_t psNewPubKey(psPool_t *pool, uint8_t type, psPubKey_t **key); @@ -1190,6 +1191,17 @@ PSPUBLIC psBool_t psIsEcdheGroup(uint16_t namedGroup); PSPUBLIC uint16_t psGetNamedGroupId(const char *name); /** Map TLS specification's signature_algorithm name to algorithm id. */ PSPUBLIC uint16_t psGetNamedSigAlgId(const char *name); + +PSPUBLIC psBool_t psIsValidHashLenSigAlgCombination(psSize_t hashLen, + int32_t sigAlg); + +# ifdef USE_RSA +/* Return the correct reference DigestInfo prefix for sigAlg, + when len bytes were RSA-decrypted. */ +PSPUBLIC const unsigned char *psGetDigestInfoPrefix(int32_t len, + int32_t sigAlg); +# endif /* USE_RSA */ + # ifdef USE_MD2 /******************************************************************************/ static inline void psMd2PreInit(psMd2_t *md2) diff --git a/crypto/cryptoCheck.h b/crypto/cryptoCheck.h index 491a706..f41859a 100644 --- a/crypto/cryptoCheck.h +++ b/crypto/cryptoCheck.h @@ -115,6 +115,9 @@ # ifndef USE_SHA1 # error "Enable USE_SHA1 in cryptoConfig.h for OCSP support" # endif +# ifndef USE_CERT_PARSE +# errro "enable USE_CERT_PARSE for USE_OCSP_RESPONSE." +# endif # endif # ifdef USE_OCSP_REQUEST diff --git a/crypto/cryptolib.h b/crypto/cryptolib.h index dbd175e..555e388 100644 --- a/crypto/cryptolib.h +++ b/crypto/cryptolib.h @@ -234,6 +234,17 @@ extern int32_t psGetPrngLocked(unsigned char *bytes, psSize_t size, # define OID_SHA512_ECDSA_SIG 526 # define OID_SHA512_ECDSA_SIG_HEX "\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x04" +/* The SSL 3.0, TLS 1.0/1.1 MD5-SHA1 based signature scheme for RSA. + Not based on an OID (because there isn't one). + This is a MatrixSSL internal ID. */ +# define OID_RSA_TLS_SIG_ALG 666 +/* Generic ID for PKCS #1.5 RSA signatures. + Hash algoritm to use must be specified in some other way. */ +# define OID_RSA_PKCS15_SIG_ALG (667 + OID_COLLISION) +/* Generic ID for ECDSA signatures in TLS. + Hash algoritm to use must be specified in some other way. */ +# define OID_ECDSA_TLS_SIG_ALG (668 + OID_COLLISION) + /* Public key algorithms */ # define OID_RSA_KEY_ALG_STR "1.2.840.113549.1.1.1" # define OID_RSA_KEY_ALG 645 diff --git a/crypto/digest/digest.h b/crypto/digest/digest.h index f4d0e32..4b27647 100644 --- a/crypto/digest/digest.h +++ b/crypto/digest/digest.h @@ -44,6 +44,7 @@ # define SHA512_HASH_SIZE 64 # define MD2_HASH_SIZE 16 # define MD5_HASH_SIZE 16 +# define MD5SHA1_HASH_SIZE 36 # define SHA1_HASHLEN 20 # define SHA224_HASHLEN 28 @@ -53,7 +54,7 @@ # define MD2_HASHLEN 16 # define MD4_HASHLEN 16 # define MD5_HASHLEN 16 -# define MD5SHA1_HASHLEN (MD5_HASHLEN + SHA1_HASHLEN) +# define MD5SHA1_HASHLEN 36 # if defined(USE_SHA512) # define MAX_HASH_SIZE SHA512_HASHLEN diff --git a/crypto/digest/hkdf.c b/crypto/digest/hkdf.c index 5e7266a..7cc7feb 100644 --- a/crypto/digest/hkdf.c +++ b/crypto/digest/hkdf.c @@ -47,7 +47,7 @@ int32_t psHkdfExpand(psCipherType_e hmacAlg, unsigned char *okm, psSize_t okmLen) { - psSize_t hashLen; + int32_t hashLen; unsigned char buf[MAX_HASH_SIZE + HKDF_MAX_INFO_LEN + 1] = {0}; unsigned char T[MAX_HASH_SIZE] = {0}; psSizeL_t i, L, stillNeeded; @@ -218,11 +218,11 @@ int32_t psHkdfExpandLabel(psPool_t *pool, rc = psDynBufAppendTlsVector(&hkdfLabelBuf, 7, 255, vector_data, vector_data_len); + psFree(vector_data, pool); if (rc < 0) { return rc; } - psFree(vector_data, pool); psDynBufUninit(&labelBuf); /* opaque context<0..255> = Context; */ @@ -236,11 +236,11 @@ int32_t psHkdfExpandLabel(psPool_t *pool, rc = psDynBufAppendTlsVector(&hkdfLabelBuf, 0, 255, vector_data, vector_data_len); + psFree(vector_data, pool); if (rc < 0) { return rc; } - psFree(vector_data, pool); psDynBufUninit(&contextBuf); /* Fetch the final HdkfLabel */ @@ -262,6 +262,7 @@ int32_t psHkdfExpandLabel(psPool_t *pool, length); if (rc < 0) { + psFree(hkdf_label, pool); return rc; } diff --git a/crypto/keyformat/pkcs.c b/crypto/keyformat/pkcs.c index 99a19aa..eac741f 100644 --- a/crypto/keyformat/pkcs.c +++ b/crypto/keyformat/pkcs.c @@ -111,14 +111,21 @@ int32_t pkcs1Pad(const unsigned char *in, psSize_t inlen, 00 00 We don't worry about v2 rollback issues because we don't support v2 + + If verifyUnpaddedLen is false, leave it up to the caller to check that + the unpadded lenght matches the expected length. */ -int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen, - unsigned char *out, psSize_t outlen, - uint8_t decryptType) +int32_t pkcs1UnpadExt(const unsigned char *in, + psSize_t inlen, + unsigned char *out, + psSize_t outlen, + uint8_t decryptType, + psBool_t verifyUnpaddedLen, + psSize_t *unpaddedLen) { const unsigned char *c, *end; - if (inlen < outlen + 10) + if (verifyUnpaddedLen && inlen < outlen + 10) { psTraceCrypto("pkcs1Unpad failure\n"); return PS_ARG_FAIL; @@ -148,15 +155,32 @@ int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen, c++; } c++; -/* - The length of the remaining data should be equal to what was expected - Combined with the initial length check, there must be >= 8 bytes of pad - ftp://ftp.rsa.com/pub/pdfs/bulletn7.pdf - */ - if ((uint32) (end - c) != outlen) + + /* + The length of the remaining data should be equal to what was expected + Combined with the initial length check, there must be >= 8 bytes of pad + ftp://ftp.rsa.com/pub/pdfs/bulletn7.pdf + */ + if (verifyUnpaddedLen) { - psTraceCrypto("pkcs1Unpad verification failure\n"); - return PS_LIMIT_FAIL; + if ((uint32) (end - c) != outlen) + { + psTraceCrypto("pkcs1Unpad verification failure\n"); + return PS_LIMIT_FAIL; + } + } + else + { + if ((uint32) (end - c) > outlen) + { + psTraceCrypto("pkcs1Unpad output buffer to small\n"); + return PS_OUTPUT_LENGTH; + } + } + + if (unpaddedLen) + { + *unpaddedLen = (psSize_t)(end - c); } /* Copy the value bytes to the out buffer */ @@ -165,9 +189,25 @@ int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen, *out = *c; out++; c++; } + return PS_SUCCESS; } +int32_t pkcs1Unpad(const unsigned char *in, + psSize_t inlen, + unsigned char *out, + psSize_t outlen, + uint8_t decryptType) +{ + return pkcs1UnpadExt(in, + inlen, + out, + outlen, + decryptType, + PS_TRUE, + NULL); +} + #ifdef USE_PRIVATE_KEY_PARSING # ifdef MATRIX_USE_FILE_SYSTEM # ifdef USE_PKCS8 diff --git a/crypto/keyformat/x509.c b/crypto/keyformat/x509.c index 74d5f7d..5832a60 100644 --- a/crypto/keyformat/x509.c +++ b/crypto/keyformat/x509.c @@ -160,12 +160,6 @@ static int32_t getImplicitBitString(psPool_t *pool, const unsigned char **pp, psSize_t len, int32_t impVal, unsigned char **bitString, psSize_t *bitLen); static int32_t issuedBefore(rfc_e rfc, const psX509Cert_t *cert); - -# ifdef USE_RSA -static int32_t x509ConfirmSignature(const unsigned char *sigHash, - const unsigned char *sigOut, psSize_t sigLen); -# endif - # endif /* USE_CERT_PARSE */ /******************************************************************************/ @@ -273,7 +267,7 @@ psRes_t psX509ParseCertFile(psPool_t *pool, const char *fileName, { psFreeList(fileList, pool); psX509FreeCert(certs); - psFree(pool, fileBuf); + psFree(fileBuf, pool); return rc; } psFree(fileBuf, pool); @@ -1076,6 +1070,9 @@ static int parse_single_cert(psPool_t *pool, const unsigned char **pp, func_rc = PS_PARSE_FAIL; goto out; } + + cert->sigHashLen = psSigAlgToHashLen(cert->sigAlgorithm); + /* Compute the hash of the cert here for CA validation */ @@ -5292,33 +5289,16 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, void *hwCtx, void *poolUserPtr) { psX509Cert_t *ic, *sc; - int32 sigType, rc; - uint32 sigLen; - void *rsaData = NULL; -# ifdef USE_ECC - int32 sigStat; -# endif /* USE_ECC */ -# ifdef USE_RSA - unsigned char sigOut[10 + MAX_HASH_SIZE + 9]; /* Max size */ - unsigned char *tempSig = NULL; -# endif /* USE_RSA */ - psPool_t *pkiPool = NULL; -# if defined(USE_PKCS1_PSS) && !defined(USE_CL_RSA) - psSize_t pssLen; -# endif - - rc = 0; - sigLen = 0; if (subjectCert == NULL) { psTraceCrypto("No subject cert given to psX509AuthenticateCert\n"); return PS_ARG_FAIL; } -/* - Determine what we've been passed - */ + /* + Determine what we've been passed + */ if (issuerCert == NULL) { /* reset auth flags in subjectCert chain and find first sc and ic */ @@ -5346,15 +5326,15 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, sc = subjectCert; } -/* - Error on first problem seen and set the subject status to FAIL - */ + /* + Error on first problem seen and set the subject status to FAIL + */ while (ic) { -/* - Certificate authority constraint only available in version 3 certs. - Only parsing version 3 certs by default though. - */ + /* + Certificate authority constraint only available in version 3 certs. + Only parsing version 3 certs by default though. + */ if ((ic->version > 1) && (ic->extensions.bc.cA != CA_TRUE)) { if (sc != ic) @@ -5365,9 +5345,9 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, } } -/* - Use sha1 hash of issuer fields computed at parse time to compare - */ + /* + Use sha1 hash of issuer fields computed at parse time to compare + */ if (Memcmp(sc->issuer.hash, ic->subject.hash, SHA1_HASH_SIZE) != 0) { #define ALLOW_INTERMEDIATES_AS_ROOTS @@ -5427,261 +5407,54 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, } # endif -/* - Signature confirmation - The sigLen is the ASN.1 size in bytes for encoding the hash. - The magic 10 is comprised of the SEQUENCE and ALGORITHM ID overhead. - The magic 9, 8, or 5 is the OID length of the corresponding algorithm. - */ - switch (sc->sigAlgorithm) - { -# ifdef USE_RSA -# ifdef ENABLE_MD5_SIGNED_CERTS -# ifdef USE_MD2 - case OID_MD2_RSA_SIG: -# endif - case OID_MD5_RSA_SIG: - sigType = RSA_TYPE_SIG; - sigLen = 10 + MD5_HASH_SIZE + 8; - break; -# endif -# ifdef ENABLE_SHA1_SIGNED_CERTS - case OID_SHA1_RSA_SIG: - case OID_SHA1_RSA_SIG2: - sigLen = 10 + SHA1_HASH_SIZE + 5; - sigType = RSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA224 - case OID_SHA224_RSA_SIG: - sigLen = 10 + SHA224_HASH_SIZE + 9; - sigType = RSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA256 - case OID_SHA256_RSA_SIG: - sigLen = 10 + SHA256_HASH_SIZE + 9; - sigType = RSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA384 - case OID_SHA384_RSA_SIG: - sigLen = 10 + SHA384_HASH_SIZE + 9; - sigType = RSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA512 - case OID_SHA512_RSA_SIG: - sigLen = 10 + SHA512_HASH_SIZE + 9; - sigType = RSA_TYPE_SIG; - break; -# endif -# endif /* USE_RSA */ -# ifdef USE_ECC -# ifdef ENABLE_SHA1_SIGNED_CERTS - case OID_SHA1_ECDSA_SIG: - sigLen = SHA1_HASH_SIZE; - sigType = ECDSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA224 - case OID_SHA224_ECDSA_SIG: - sigLen = SHA224_HASH_SIZE; - sigType = ECDSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA256 - case OID_SHA256_ECDSA_SIG: - sigLen = SHA256_HASH_SIZE; - sigType = ECDSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA384 - case OID_SHA384_ECDSA_SIG: - sigLen = SHA384_HASH_SIZE; - sigType = ECDSA_TYPE_SIG; - break; -# endif -# ifdef USE_SHA512 - case OID_SHA512_ECDSA_SIG: - sigLen = SHA512_HASH_SIZE; - sigType = ECDSA_TYPE_SIG; - break; -# endif -# endif /* USE_ECC */ -# ifdef USE_ED25519 - case OID_ED25519_KEY_ALG: - sigLen = 64; - sigType = ED25519_TYPE_SIG; - break; -# endif -# ifdef USE_PKCS1_PSS - case OID_RSASSA_PSS: - switch (sc->pssHash) - { -# ifdef ENABLE_MD5_SIGNED_CERTS - case PKCS1_MD5_ID: - sigLen = MD5_HASH_SIZE; - break; -# endif -# ifdef ENABLE_SHA1_SIGNED_CERTS - case PKCS1_SHA1_ID: - sigLen = SHA1_HASH_SIZE; - break; -# endif -# ifdef USE_SHA224 - case PKCS1_SHA224_ID: - sigLen = SHA224_HASH_SIZE; - break; -# endif -# ifdef USE_SHA256 - case PKCS1_SHA256_ID: - sigLen = SHA256_HASH_SIZE; - break; -# endif -# ifdef USE_SHA384 - case PKCS1_SHA384_ID: - sigLen = SHA384_HASH_SIZE; - break; -# endif -# ifdef USE_SHA512 - case PKCS1_SHA512_ID: - sigLen = SHA512_HASH_SIZE; - break; -# endif - default: - return PS_UNSUPPORTED_FAIL; - } - sigType = RSAPSS_TYPE_SIG; - break; -# endif - default: - sigType = PS_UNSUPPORTED_FAIL; - break; - } - - if (sigType == PS_UNSUPPORTED_FAIL) - { - sc->authStatus = PS_CERT_AUTH_FAIL_SIG; - psTraceIntCrypto("Unsupported certificate signature algorithm %d\n", - subjectCert->sigAlgorithm); - return sigType; - } - -# ifdef USE_RSA - if (sigType == RSA_TYPE_SIG || sigType == RSAPSS_TYPE_SIG) - { - } - /* Now do the signature validation */ - if (sigType == RSA_TYPE_SIG) - { - psAssert(sigLen <= sizeof(sigOut)); -/* - psRsaDecryptPub destroys the 'in' parameter so let it be a tmp - */ - tempSig = psMalloc(pool, sc->signatureLen); - if (tempSig == NULL) - { - psError("Memory allocation error: psX509AuthenticateCert\n"); - return PS_MEM_FAIL; - } - Memcpy(tempSig, sc->signature, sc->signatureLen); - - if ((rc = psRsaDecryptPub(pkiPool, &ic->publicKey.key.rsa, - tempSig, sc->signatureLen, sigOut, sigLen, rsaData)) < 0) - { - - psTraceCrypto("Unable to RSA decrypt certificate signature\n"); - sc->authStatus = PS_CERT_AUTH_FAIL_SIG; - psFree(tempSig, pool); - return rc; - } - psFree(tempSig, pool); - rc = x509ConfirmSignature(sc->sigHash, sigOut, sigLen); - } -# if defined(USE_PKCS1_PSS) && !defined(USE_CL_RSA) - if (sigType == RSAPSS_TYPE_SIG) - { - tempSig = psMalloc(pool, sc->signatureLen); - if (tempSig == NULL) - { - psError("Memory allocation error: psX509AuthenticateCert\n"); - return PS_MEM_FAIL; - } - pssLen = sc->signatureLen; - if ((rc = psRsaCrypt(pkiPool, &ic->publicKey.key.rsa, - sc->signature, sc->signatureLen, tempSig, &pssLen, - PS_PUBKEY, rsaData)) < 0) - { - psFree(tempSig, pool); - return rc; - } - - if (psPkcs1PssDecode(pkiPool, sc->sigHash, sigLen, tempSig, - pssLen, sc->saltLen, sc->pssHash, ic->publicKey.keysize * 8, - &rc) < 0) - { - psFree(tempSig, pool); - return PS_FAILURE; - } - psFree(tempSig, pool); - - if (rc == 0) - { - /* This is an indication the hash did NOT match */ - rc = -1; /* The test below is looking for < 0 */ - } - } -# endif /* defined(USE_PKCS1_PSS) && !defined(USE_CL_RSA) */ -# endif /* USE_RSA */ - -# ifdef USE_ECC - if (sigType == ECDSA_TYPE_SIG) - { - if ((rc = psEccDsaVerify(pkiPool, - &ic->publicKey.key.ecc, - sc->sigHash, sigLen, - sc->signature, sc->signatureLen, - &sigStat, rsaData)) != 0) - { - psTraceCrypto("Error validating ECDSA certificate signature\n"); - sc->authStatus = PS_CERT_AUTH_FAIL_SIG; - return rc; - } - if (sigStat == -1) - { - /* No errors, but signature didn't pass */ - psTraceCrypto("ECDSA certificate signature failed\n"); - rc = -1; - } - } -# endif /* USE_ECC */ -# ifdef USE_ED25519 - if (sigType == ED25519_TYPE_SIG) + /* + Try to verify the subject cert's signature using the issuer cert's + public key. + */ { psRes_t res; + const unsigned char *tbs = sc->sigHash; + psSizeL_t tbsLen = sc->sigHashLen; + psVerifyOptions_t opts; + psBool_t verifyResult = PS_FALSE; - res = psEd25519Verify(sc->signature, - sc->tbsCertStart, - sc->tbsCertLen, - ic->publicKey.key.ed25519.pub); - if (res != PS_SUCCESS) + memset(&opts, 0, sizeof(opts)); + opts.msgIsDigestInfo = PS_TRUE; + + /* Special cases: RSASSA-PSS, Ed25519 and DSA verification + needs some extra information. */ +# ifdef USE_PKCS1_PSS + if (sc->sigAlgorithm == OID_RSASSA_PSS) { - psTraceCrypto("Ed25519 certificate signature failed\n"); - rc = -1; + opts.rsaPssHashAlg = sc->pssHash; + opts.rsaPssHashLen = psPssHashAlgToHashLen(sc->pssHash); + opts.rsaPssSaltLen = sc->saltLen; + opts.useRsaPss = PS_TRUE; + } +# endif /* USE_PKCS1_PSS */ +# ifdef USE_ED25519 + if (sc->sigAlgorithm == OID_ED25519_KEY_ALG) + { + tbs = sc->tbsCertStart; + tbsLen = sc->tbsCertLen; + opts.msgIsDigestInfo = PS_FALSE; + } +# endif /* USE_ED25519 */ + res = psVerifySig(NULL, + tbs, + tbsLen, + sc->signature, + sc->signatureLen, + &ic->publicKey, + sc->sigAlgorithm, + &verifyResult, + &opts); + if (res != PS_SUCCESS || verifyResult != PS_TRUE) + { + sc->authStatus = PS_CERT_AUTH_FAIL_SIG; + return PS_CERT_AUTH_FAIL_SIG; } } -# endif /* USE_ED25519 */ - -/* - Test what happen in the signature test? - */ - if (rc < PS_SUCCESS) - { - sc->authStatus = PS_CERT_AUTH_FAIL_SIG; - return rc; - } - /* X.509 extension tests. Problems below here will be collected in flags and given to the user */ @@ -5742,6 +5515,7 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, will always contain the relevant information. */ if ( !(ic->extensions.keyUsageFlags & KEY_USAGE_KEY_CERT_SIGN)) { + int32 rc = 0; /* @security If keyUsageFlags is zero, it may not exist at all in the cert. This is allowed if the cert was issued before the RFC was updated to require this field for CA certificates. @@ -5750,10 +5524,7 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert, { rc = issuedBefore(RFC_3280, ic); } - else - { - rc = 0; /* Awkward code to force the compare below */ - } + /* Iff rc == 1 we won't error */ if (!rc) { @@ -5813,125 +5584,6 @@ L_INTERMEDIATE_ROOT: return PS_SUCCESS; } -# ifdef USE_RSA -/******************************************************************************/ -/* - Do the signature validation for a subject certificate against a - known CA certificate - */ -static int32_t x509ConfirmSignature(const unsigned char *sigHash, - const unsigned char *sigOut, psSize_t sigLen) -{ - const unsigned char *end; - const unsigned char *p = sigOut; - unsigned char hash[MAX_HASH_SIZE]; - int32_t oi; - psSize_t len, plen; - - end = p + sigLen; -/* - DigestInfo ::= SEQUENCE { - digestAlgorithm DigestAlgorithmIdentifier, - digest Digest } - - DigestAlgorithmIdentifier ::= AlgorithmIdentifier - - Digest ::= OCTET STRING - */ - if (getAsnSequence(&p, (uint32) (end - p), &len) < 0) - { - psTraceCrypto("Initial parse error in x509ConfirmSignature\n"); - return PS_PARSE_FAIL; - } - - /* Could be MD5 or SHA1 */ - if (getAsnAlgorithmIdentifier(&p, (uint32) (end - p), &oi, &plen) < 0) - { - psTraceCrypto("Algorithm ID parse error in x509ConfirmSignature\n"); - return PS_PARSE_FAIL; - } - psAssert(plen == 0); - if ((*p++ != ASN_OCTET_STRING) || - getAsnLength(&p, (uint32) (end - p), &len) < 0 || - (uint32) (end - p) < len) - { - psTraceCrypto("getAsnLength parse error in x509ConfirmSignature\n"); - return PS_PARSE_FAIL; - } - Memcpy(hash, p, len); - switch (oi) - { -# ifdef ENABLE_MD5_SIGNED_CERTS -# ifdef USE_MD2 - case OID_MD2_ALG: -# endif - case OID_MD5_ALG: - if (len != MD5_HASH_SIZE) - { - psTraceCrypto("MD5_HASH_SIZE error in x509ConfirmSignature\n"); - return PS_LIMIT_FAIL; - } - break; -# endif -# ifdef ENABLE_SHA1_SIGNED_CERTS - case OID_SHA1_ALG: - if (len != SHA1_HASH_SIZE) - { - psTraceCrypto("SHA1_HASH_SIZE error in x509ConfirmSignature\n"); - return PS_LIMIT_FAIL; - } - break; -# endif -# ifdef USE_SHA224 - case OID_SHA224_ALG: - if (len != SHA224_HASH_SIZE) - { - psTraceCrypto("SHA224_HASH_SIZE error in x509ConfirmSignature\n"); - return PS_LIMIT_FAIL; - } - break; -# endif -# ifdef USE_SHA256 - case OID_SHA256_ALG: - if (len != SHA256_HASH_SIZE) - { - psTraceCrypto("SHA256_HASH_SIZE error in x509ConfirmSignature\n"); - return PS_LIMIT_FAIL; - } - break; -# endif -# ifdef USE_SHA384 - case OID_SHA384_ALG: - if (len != SHA384_HASH_SIZE) - { - psTraceCrypto("SHA384_HASH_SIZE error in x509ConfirmSignature\n"); - return PS_LIMIT_FAIL; - } - break; -# endif -# ifdef USE_SHA512 - case OID_SHA512_ALG: - if (len != SHA512_HASH_SIZE) - { - psTraceCrypto("SHA512_HASH_SIZE error in x509ConfirmSignature\n"); - return PS_LIMIT_FAIL; - } - break; -# endif - default: - psTraceCrypto("Unsupported alg ID error in x509ConfirmSignature\n"); - return PS_UNSUPPORTED_FAIL; - } - /* hash should match sigHash */ - if (memcmpct(hash, sigHash, len) != 0) - { - psTraceCrypto("Signature failure in x509ConfirmSignature\n"); - return PS_SIGNATURE_MISMATCH; - } - return PS_SUCCESS; -} -# endif /* USE_RSA */ - /******************************************************************************/ # endif /* USE_CERT_PARSE */ @@ -6951,7 +6603,7 @@ int32_t psOcspResponseValidate(psPool_t *pool, psX509Cert_t *trustedOCSP, { static psValidateOCSPResponseOptions_t vOptsDefault; psX509Cert_t *curr, *issuer, *subject, *ocspResIssuer; - psOcspSingleResponse_t *subjectResponse; + psOcspSingleResponse_t *subjectResponse = NULL; unsigned char sigOut[MAX_HASH_SIZE]; int32 sigOutLen, sigType, index; psPool_t *pkiPool = NULL; @@ -7109,7 +6761,8 @@ int32_t psOcspResponseValidate(psPool_t *pool, psX509Cert_t *trustedOCSP, while (index < MAX_OCSP_RESPONSES) { subjectResponse = &response->singleResponse[index]; - if ((subject->serialNumberLen == subjectResponse->certIdSerialLen) && + if ((subject->serialNumberLen > 0) && + (subject->serialNumberLen == subjectResponse->certIdSerialLen) && (Memcmp(subject->serialNumber, subjectResponse->certIdSerial, subject->serialNumberLen) == 0)) { diff --git a/crypto/keyformat/x509.h b/crypto/keyformat/x509.h index a6c6d42..96ff597 100644 --- a/crypto/keyformat/x509.h +++ b/crypto/keyformat/x509.h @@ -657,6 +657,7 @@ typedef struct psCert int32 revokedStatus; # endif unsigned char sigHash[MAX_HASH_SIZE]; + psSize_t sigHashLen; # endif /* USE_CERT_PARSE */ # if defined(USE_OCSP_RESPONSE) || defined(USE_OCSP_REQUEST) unsigned char sha1KeyHash[SHA1_HASH_SIZE]; diff --git a/crypto/pubkey/dh_gen_key.c b/crypto/pubkey/dh_gen_key.c index 412d494..ba1b3b2 100644 --- a/crypto/pubkey/dh_gen_key.c +++ b/crypto/pubkey/dh_gen_key.c @@ -243,7 +243,7 @@ int32_t psDhGenKeyParams(psPool_t *pool, const psDhParams_t *params, else { return psDhGenKeyIntsSize(pool, params->size, ¶ms->p, - ¶ms->g, params->x_bitlen, key, usrData); + ¶ms->g, params->x_bitlen/8, key, usrData); } } diff --git a/crypto/pubkey/dh_params.c b/crypto/pubkey/dh_params.c index ccc6dc3..c99a4ba 100644 --- a/crypto/pubkey/dh_params.c +++ b/crypto/pubkey/dh_params.c @@ -95,7 +95,10 @@ int32_t psPkcs3ParseDhParamBin(psPool_t *pool, const unsigned char *dhBin, /* Read desired length of private key. (Note: currently ignored by MatrixSSL). */ pstm_int bitlen; - pstm_init_size(pool, &bitlen, 1); + if (pstm_init_size(pool, &bitlen, 1) < 0) + { + goto L_ERR; + } if (pstm_read_asn(pool, &c, (uint16_t) (end - c), &bitlen) < 0) { pstm_clear(&bitlen); diff --git a/crypto/pubkey/ecc_curve_config.c b/crypto/pubkey/ecc_curve_config.c index 23f6a77..515c95b 100644 --- a/crypto/pubkey/ecc_curve_config.c +++ b/crypto/pubkey/ecc_curve_config.c @@ -72,6 +72,7 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves const psEccCurve_t *curve; uint8_t listLen = 0; +# ifdef USE_SECP521R1 if (curves & IS_SECP521R1) { if (getEccParamById(IANA_SECP521R1, &curve) == 0) @@ -83,6 +84,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_BRAIN512R1 if (curves & IS_BRAIN512R1) { if (getEccParamById(IANA_BRAIN512R1, &curve) == 0) @@ -94,6 +97,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_SECP384R1 if (curves & IS_SECP384R1) { if (getEccParamById(IANA_SECP384R1, &curve) == 0) @@ -105,6 +110,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_BRAIN384R1 if (curves & IS_BRAIN384R1) { if (getEccParamById(IANA_BRAIN384R1, &curve) == 0) @@ -116,6 +123,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_SECP256R1 if (curves & IS_SECP256R1) { if (getEccParamById(IANA_SECP256R1, &curve) == 0) @@ -127,6 +136,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_BRAIN256R1 if (curves & IS_BRAIN256R1) { if (getEccParamById(IANA_BRAIN256R1, &curve) == 0) @@ -138,6 +149,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_SECP224R1 if (curves & IS_SECP224R1) { if (getEccParamById(IANA_SECP224R1, &curve) == 0) @@ -149,6 +162,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_BRAIN224R1 if (curves & IS_BRAIN224R1) { if (getEccParamById(IANA_BRAIN224R1, &curve) == 0) @@ -160,6 +175,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif +# ifdef USE_SECP192R1 if (curves & IS_SECP192R1) { if (getEccParamById(IANA_SECP192R1, &curve) == 0) @@ -171,6 +188,7 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves } } } +# endif *len = listLen; } diff --git a/crypto/pubkey/ecc_priv.c b/crypto/pubkey/ecc_priv.c index be8ffe1..943c569 100644 --- a/crypto/pubkey/ecc_priv.c +++ b/crypto/pubkey/ecc_priv.c @@ -201,10 +201,6 @@ int32_t psEccDsaSignCommon(psPool_t *pool, const psEccKey_t *privKey, goto error; /* s = br (b == 1). */ } } - if (err != PS_SUCCESS) - { - goto error; - } if (blinding) { diff --git a/crypto/pubkey/pubkey.c b/crypto/pubkey/pubkey.c index 4ac4741..806a49c 100644 --- a/crypto/pubkey/pubkey.c +++ b/crypto/pubkey/pubkey.c @@ -34,7 +34,7 @@ #include "../cryptoImpl.h" -#if defined(USE_RSA) || defined(USE_ECC) +# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) || defined(USE_X25519) || defined(USE_ED25519) /******************************************************************************/ @@ -124,4 +124,3 @@ void psDeletePubKey(psPubKey_t **key) /******************************************************************************/ #endif /* USE_RSA || USE_ECC */ - diff --git a/crypto/pubkey/pubkey.h b/crypto/pubkey/pubkey.h index 14020a4..d66188b 100644 --- a/crypto/pubkey/pubkey.h +++ b/crypto/pubkey/pubkey.h @@ -203,7 +203,7 @@ typedef struct psX25519Key */ typedef struct { -# if defined(USE_RSA) || defined(USE_ECC) +# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) || defined(USE_X25519) || defined(USE_ED25519) union { # ifdef USE_RSA @@ -228,19 +228,35 @@ typedef struct uint8_t type; /* PS_RSA, PS_ECC, PS_DH */ } psPubKey_t; +# define PS_SIGN_OPTS_ECDSA_INCLUDE_SIZE (1ULL << 0) +# define PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF (1ULL << 1) + typedef struct { uint32_t flags; int32_t rsaPssHashAlg; unsigned char *rsaPssSalt; psSize_t rsaPssSaltLen; + void *userData; } psSignOpts_t; -extern int32_t pkcs1Pad(const unsigned char *in, psSize_t inlen, - unsigned char *out, psSize_t outlen, - uint8_t cryptType, void *userPtr); -extern int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen, - unsigned char *out, psSize_t outlen, - uint8_t decryptType); +extern int32_t pkcs1Pad(const unsigned char *in, + psSize_t inlen, + unsigned char *out, + psSize_t outlen, + uint8_t cryptType, + void *userPtr); +extern int32_t pkcs1Unpad(const unsigned char *in, + psSize_t inlen, + unsigned char *out, + psSize_t outlen, + uint8_t decryptType); +extern int32_t pkcs1UnpadExt(const unsigned char *in, + psSize_t inlen, + unsigned char *out, + psSize_t outlen, + uint8_t decryptType, + psBool_t verifyUnpaddedLen, + psSize_t *unpaddedLen); # if defined(USE_RSA) || defined(USE_ECC) @@ -251,7 +267,7 @@ int32_t psHashLenToSigAlg(psSize_t hash_len, purposes. Compute a digest that is to be signed or whose signature is - to be verified. + to be verified. Supports only single-part operation. */ psRes_t psComputeHashForSig(const unsigned char *dataBegin, psSizeL_t dataLen, @@ -260,6 +276,27 @@ psRes_t psComputeHashForSig(const unsigned char *dataBegin, psSize_t * hashOutLen); /** Algorithm-independent function for signing hashes. + + The the signature algorithm is standard RSA (not PSS), the function + first wraps the input hash into a DigestInfo, unless the TLS 1.1 and + below signature algorithm (sigAlg == OID_RSA_TLS_SIG_ALG) + is used. + + The supported values for sigAlg are: + OID_RSA_TLS_SIG_ALG (TLS 1.1 and below custom algorithm) + OID_SHA1_RSA_SIG (PKCS #1.5) + OID_SHA256_RSA_SIG (PKCS #1.5) + OID_SHA384_RSA_SIG (PKCS #1.5) + OID_RSASSA_PSS (RSASSA-PSS) + OID_SHA256_ECDSA_SIG (ECDSA) + OID_SHA384_ECDSA_SIG (ECDSA) + OID_SHA512_ECDSA_SIG (ECDSA) + + It is also possible to use a more generic sigAlg ID. + In this case, psSign will deduce the hash algorithm to use + from inLen (e.g. inLen == 32 would imply SHA-256): + OID_RSA_PKCS15_SIG_ALG + OID_ECDSA_TLS_SIG_ALG */ int32_t psSignHash(psPool_t *pool, psPubKey_t *privKey, @@ -273,8 +310,9 @@ int32_t psSignHash(psPool_t *pool, /** Algorithm-independent function for signing arbitrary data. - The data is first hashed if the signature algorithm - is only able to sign hashes. TODO: not really. Fix. + This function is similar to psSignHash, expect that it also supports + signing arbitrary (non-hash) data with Ed25519, when sigAlg is + OID_ED25519_KEY_ALG. */ int32_t psSign(psPool_t *pool, psPubKey_t *privKey, diff --git a/crypto/pubkey/pubkey_parse_file.c b/crypto/pubkey/pubkey_parse_file.c index fb35d8c..cbb01f0 100644 --- a/crypto/pubkey/pubkey_parse_file.c +++ b/crypto/pubkey/pubkey_parse_file.c @@ -514,10 +514,10 @@ psRes_t psPkcs8ParsePrivBin(psPool_t *pool, #if 0 PKCS8_FAIL: -#endif psClearPubKey(key); psTraceCrypto("Did not parse key in PKCS#8 parse\n"); return PS_FAILURE; +#endif } # endif /* USE_PKCS8 */ diff --git a/crypto/pubkey/pubkey_sign.c b/crypto/pubkey/pubkey_sign.c index 9dac397..d058343 100644 --- a/crypto/pubkey/pubkey_sign.c +++ b/crypto/pubkey/pubkey_sign.c @@ -51,25 +51,46 @@ int32_t psSignHashEcdsaInternal(psPool_t *pool, psSize_t *outLen, psSignOpts_t *opts) { - unsigned char tmp[140]; - psSize_t sigLen; + unsigned char tmp[142]; + unsigned char *outBuf = tmp; + psSize_t sigLen = sizeof(tmp); int32_t rc; + uint8_t includeSize = 0; + psBool_t usePreAllocatedOutBuf = PS_FALSE; + + if (opts && (opts->flags & PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF)) + { + usePreAllocatedOutBuf = PS_TRUE; + } + if (opts && (opts->flags & PS_SIGN_OPTS_ECDSA_INCLUDE_SIZE)) + { + includeSize = 1; + } sigLen = sizeof(tmp); - rc = psEccDsaSign(pool, &privKey->key.ecc, - in, inLen, - tmp, &sigLen, - 0, NULL); + rc = psEccDsaSign(pool, + &privKey->key.ecc, + in, + inLen, + outBuf, + &sigLen, + includeSize, + opts ? opts->userData : NULL); if (rc < 0) { return rc; } - *out = psMalloc(pool, sigLen); + if (!usePreAllocatedOutBuf) + { + *out = psMalloc(pool, sigLen); + } + /* Check also the preallocated pointer. */ if (*out == NULL) { return PS_MEM_FAIL; } + Memcpy(*out, tmp, sigLen); *outLen = sigLen; @@ -88,31 +109,71 @@ int32_t psSignHashRsa(psPool_t *pool, psSignOpts_t *opts) { int32_t rc; + unsigned char tmp[512]; unsigned char *sig; psSize_t sigLen; + psBool_t usePreAllocatedOutBuf = PS_FALSE; - sigLen = privKey->keysize; - sig = psMalloc(pool, sigLen); - if (sig == NULL) + if (opts && (opts->flags & PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF)) { - return PS_MEM_FAIL; + usePreAllocatedOutBuf = PS_TRUE; } - rc = psRsaEncryptPriv(pool, - &privKey->key.rsa, - in, - inLen, - sig, - sigLen, - NULL); + sigLen = privKey->keysize; + + if (usePreAllocatedOutBuf) + { + sig = tmp; + } + else + { + sig = psMalloc(pool, sigLen); + if (sig == NULL) + { + return PS_MEM_FAIL; + } + } + + if (sigAlg == OID_RSA_TLS_SIG_ALG) + { + /* TLS 1.0/1.1 style RSA signature. */ + rc = psRsaEncryptPriv(pool, + &privKey->key.rsa, + in, + inLen, + sig, + sigLen, + opts ? opts->userData : NULL); + } + else + { + /* PKCS #1.5 signature. */ + rc = privRsaEncryptSignedElement(pool, + &privKey->key.rsa, + in, + inLen, + sig, + sigLen, + opts ? opts->userData : NULL); + } if (rc != PS_SUCCESS) { - psFree(sig, pool); + if (!usePreAllocatedOutBuf) + { + psFree(sig, pool); + } return rc; } - *out = sig; - *outLen = sigLen; + if (usePreAllocatedOutBuf) + { + Memcpy(*out, sig, sigLen); + } + else + { + *out = sig; + *outLen = sigLen; + } return PS_SUCCESS; } @@ -134,24 +195,40 @@ int32_t psSignHash(psPool_t *pool, case OID_SHA256_ECDSA_SIG: case OID_SHA384_ECDSA_SIG: case OID_SHA512_ECDSA_SIG: - return psSignHashEcdsaInternal(pool, privKey, sigAlg, + case OID_ECDSA_TLS_SIG_ALG: + if (privKey->type == PS_ECC || privKey->type == PS_ED25519) + { + return psSignHashEcdsaInternal(pool, privKey, sigAlg, in, inLen, out, outLen, opts); + } + break; # endif /* USE_ECC */ # ifdef USE_PKCS1_PSS case OID_RSASSA_PSS: - return psRsaPssSignHash(pool, privKey, sigAlg, + if (privKey->type == PS_RSA) + { + return psRsaPssSignHash(pool, privKey, sigAlg, in, inLen, out, outLen, opts); + } + break; # endif /* USE_PKCS1_PSS */ # ifdef USE_RSA case OID_SHA256_RSA_SIG: case OID_SHA384_RSA_SIG: case OID_SHA512_RSA_SIG: - return psSignHashRsa(pool, privKey, sigAlg, + case OID_RSA_TLS_SIG_ALG: + case OID_RSA_PKCS15_SIG_ALG: + if (privKey->type == PS_RSA) + { + return psSignHashRsa(pool, privKey, sigAlg, in, inLen, out, outLen, opts); + } # endif default: - return PS_UNSUPPORTED_FAIL; + break; } + psTraceCrypto("Invalid privKey type or sigAlg in psSignHash\n"); + return PS_UNSUPPORTED_FAIL; } int32_t psSign(psPool_t *pool, @@ -180,6 +257,11 @@ int32_t psSign(psPool_t *pool, case OID_ED25519_KEY_ALG: /* Ed25519 is used to sign arbitrary data directly without pre-hashing. */ + if (privKey->type != PS_ED25519) + { + psTraceCrypto("Invalid privKey type in psSign\n"); + return PS_MEM_FAIL; + } sigOut = psMalloc(pool, 64); if (sigOut == NULL) { diff --git a/crypto/pubkey/pubkey_verify.c b/crypto/pubkey/pubkey_verify.c index 8e494d9..407da2b 100644 --- a/crypto/pubkey/pubkey_verify.c +++ b/crypto/pubkey/pubkey_verify.c @@ -84,6 +84,7 @@ psRes_t psVerifySig(psPool_t *pool, else # endif /* USE_PKCS1_PSS */ { + if (opts && opts->msgIsDigestInfo) { /* RSA PKCS 1.5 verification of TLS signed elements. */ @@ -216,6 +217,26 @@ psRes_t psHashDataAndVerifySig(psPool_t *pool, return rc; } +# ifdef USE_PKCS1_PSS +static +int32_t get_pss_hash_sig_alg(psVerifyOptions_t *opts) +{ + switch (opts->rsaPssHashAlg) + { + case PKCS1_SHA1_ID: + return OID_SHA1_RSA_SIG; + case PKCS1_SHA256_ID: + return OID_SHA256_RSA_SIG; + case PKCS1_SHA384_ID: + return OID_SHA384_RSA_SIG; + case PKCS1_SHA512_ID: + return OID_SHA512_RSA_SIG; + default: + return PS_UNSUPPORTED_FAIL; + } +} +# endif /* USE_PKCS1_PSS */ + psRes_t psVerify(psPool_t *pool, const unsigned char *dataBegin, const psSizeL_t dataLen, @@ -230,14 +251,22 @@ psRes_t psVerify(psPool_t *pool, *verifyResult = PS_FALSE; -# if defined (USE_PKCS1_PSS) && defined(USE_CL_RSA) if (opts && opts->useRsaPss) { +# if defined (USE_PKCS1_PSS) && defined(USE_CL_RSA) /* The crypto-cl API for RSA-PSS verification does not support pre-hashing. */ needPreHash = PS_FALSE; - } # endif + if (needPreHash && signatureAlgorithm == OID_RSASSA_PSS) + { + /* psComputeHashForSig called by psHashDataAndVerifySig below + cannot operate on OID_RSASSA_PSS, since this ID does not + indicate the hash alg. So translate to one of the + OID_*_RSA_SIG IDs. */ + signatureAlgorithm = get_pss_hash_sig_alg(opts); + } + } # ifdef USE_ED25519 if (signatureAlgorithm == OID_ED25519_KEY_ALG) diff --git a/crypto/pubkey/rsa_priv.c b/crypto/pubkey/rsa_priv.c index 710ea37..3b43aa4 100644 --- a/crypto/pubkey/rsa_priv.c +++ b/crypto/pubkey/rsa_priv.c @@ -312,6 +312,7 @@ int32_t psRsaPssSignHash(psPool_t *pool, sig = psMalloc(pool, modNBytes); if (sig == NULL) { + psFree(em, pool); return PS_MEM_FAIL; } sigLen = modNBytes; diff --git a/crypto/pubkey/rsa_pub.c b/crypto/pubkey/rsa_pub.c index e91cc39..f1d57e0 100644 --- a/crypto/pubkey/rsa_pub.c +++ b/crypto/pubkey/rsa_pub.c @@ -37,14 +37,76 @@ /******************************************************************************/ /* TODO - the following functions are not implementation layer specific... move to a common file? - - Matrix-specific starts at #ifdef USE_MATRIX_RSA */ +#ifdef USE_MATRIX_RSA + #define ASN_OVERHEAD_LEN_RSA_SHA2 19 #define ASN_OVERHEAD_LEN_RSA_SHA1 15 -#ifdef USE_MATRIX_RSA +static +int32_t psRsaDecryptPubExt(psPool_t *pool, + psRsaKey_t *key, + unsigned char *in, + psSize_t inlen, + unsigned char *out, + psSize_t *outlen, + psSize_t expectedLen, + void *data) +{ + int32_t err; + psSize_t ptLen, unpaddedLen; + + if (inlen != key->size) + { + psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPub\n"); + return PS_ARG_FAIL; + } + + ptLen = inlen; + + /* Raw, in-place RSA decryption. */ + err = psRsaCrypt(pool, + key, + in, + inlen, + in, + &ptLen, + PS_PUBKEY, + data); + if (err < PS_SUCCESS) + { + psTraceCrypto("Error performing psRsaDecryptPub\n"); + return err; + } + + /* In raw RSA decryption, size of the decrypted plaintext must equal + the size of the ciphertext. */ + if (ptLen != inlen) + { + psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", ptLen); + return PS_FAILURE; + } + + /* Remove PKCS #1 padding and copy the decrypted and de-padded data + to out. */ + err = pkcs1UnpadExt(in, + inlen, + out, + ptLen, + PS_PUBKEY, + PS_FALSE, + &unpaddedLen); + if (err < 0) + { + return err; + } + + *outlen = unpaddedLen; + + return PS_SUCCESS; +} + int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key, unsigned char *in, psSize_t inlen, unsigned char *out, psSize_t outlen, @@ -65,121 +127,112 @@ int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key, signatureAlgorithm, data); } -int32_t pubRsaDecryptSignedElementExt(psPool_t *pool, psRsaKey_t *key, - unsigned char *in, psSize_t inlen, - unsigned char *out, psSize_t outlen, - int32_t signatureAlgorithm, void *data) +int32_t pubRsaDecryptSignedElementExt(psPool_t *pool, + psRsaKey_t *key, + unsigned char *in, + psSize_t inlen, + unsigned char *hashOut, + psSize_t hashOutLen, + int32_t signatureAlgorithm, + void *data) { - unsigned char *c, *front, *end; - uint16_t outlenWithAsn, len, plen; - int32_t oi, rc; + int32_t rc; + /* Reserve enough room for the largest supported decrypted and de-padded + plaintext: a SHA-512 DigestInfo (with NULL parameters). */ + unsigned char decrypted[SHA512_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2]; + psSize_t decryptedLen = sizeof(decrypted); + const unsigned char *prefix; + unsigned char *decPrefixStart; + psSize_t decPrefixLen; - /* The issue here is that the standard RSA decryption routine requires - the user to know the output length (usually just a hash size). With - these "digitally signed elements" there is an algorithm - identifier surrounding the hash so we use the known magic numbers as - additional lengths of the wrapper since it is a defined ASN sequence, - ASN algorithm oid, and ASN octet string */ - if (outlen == SHA256_HASH_SIZE) + + /* + Check input arguments + */ + if (key == NULL || in == NULL || hashOut == NULL) { - outlenWithAsn = SHA256_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2; - } - else if (outlen == SHA1_HASH_SIZE) - { - outlenWithAsn = SHA1_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA1; - } - else if (outlen == SHA384_HASH_SIZE) - { - outlenWithAsn = SHA384_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2; - } - else if (outlen == SHA512_HASH_SIZE) - { - outlenWithAsn = SHA512_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2; - } - else - { - psTraceIntCrypto("Unsupported decryptSignedElement hash %d\n", outlen); - return PS_FAILURE; + psTraceCrypto( + "ERROR: invalid argument in pubRsaDecryptSignedElement\n"); + return PS_ARG_FAIL; } - front = c = psMalloc(pool, outlenWithAsn); - if (front == NULL) + /* + Check that the hash length + signatureAlgorithm combination + is valid and that signatureAlgorithm is supported. + */ + if (!psIsValidHashLenSigAlgCombination(hashOutLen, signatureAlgorithm)) { - return PS_MEM_FAIL; + psTraceCrypto("Invalid hash length + signature alg combination: "); + psTraceIntCrypto("hash length: %d, ", hashOutLen); + psTraceIntCrypto("sig alg: %d\n", signatureAlgorithm); + return PS_ARG_FAIL; } - if ((rc = psRsaDecryptPub(pool, key, in, inlen, c, outlenWithAsn, data)) < 0) + /* + Perform RSA decryption + de-padding. After this, decryptedLen + becomes the length of the actual recovered DigestInfo. + */ + rc = psRsaDecryptPubExt(pool, + key, + in, + inlen, + decrypted, + &decryptedLen, + hashOutLen, + data); + if (rc < 0) { - psFree(front, pool); psTraceCrypto("Couldn't public decrypt signed element\n"); return rc; } - /* Parse it */ - end = c + outlenWithAsn; + /* + Two alternatives for verifying the decrypted RSA message + representative: - /* @note Below we do a typecast to const to avoid a compiler warning, - although it should be fine to pass a non const pointer into an - api declaring it const, since it is just the API declaring the - contents will not be modified within the API. */ - if (getAsnSequence((const unsigned char **) &c, - (uint16_t) (end - c), &len) < 0) + - Comparison-based: directly compare the known parts of the + DigestInfo against a reference DigestInfo. + - Parsing based: parse the decrypted DigestInfo and check that + each component is as expected. + + In both approaches, the variable part (the embedded digest itself) + needs to be directly compared against the reference digest. We don't + perform that part here; this must be done by the caller. + + We use the comparison-based approach, since its safer and easier + to implement correctly, see e.g. Kühn et al.: "Variants of + Bleichenbacher's Low-Exponent Attack on PKCS#1 RSA Signatures". + */ + + /* + Based on the signatureAlgorithm we were given, get a reference + DigestInfo prefix to compare against. + */ + prefix = psGetDigestInfoPrefix(decryptedLen, signatureAlgorithm); + if (prefix == NULL) { - psTraceCrypto("Couldn't parse signed element sequence\n"); - psFree(front, pool); - return PS_FAILURE; - } - if (getAsnAlgorithmIdentifier((const unsigned char **) &c, - (uint16_t) (end - c), &oi, &plen) < 0) - { - psTraceCrypto("Couldn't parse signed element octet string\n"); - psFree(front, pool); - return PS_FAILURE; + return PS_ARG_FAIL; } - if (oi == OID_SHA256_ALG) + /* + Check that the decrypted DigestInfo prefix is valid. + If yes, copy the decrypted digest to out. + */ + decPrefixStart = decrypted; + decPrefixLen = decryptedLen - hashOutLen; + if (memcmpct(prefix, decPrefixStart, decPrefixLen) == 0) { - psAssert(outlen == SHA256_HASH_SIZE); + Memcpy(hashOut, decrypted + decPrefixLen, hashOutLen); + rc = PS_SUCCESS; } - else if (oi == OID_SHA1_ALG) - { - psAssert(outlen == SHA1_HASH_SIZE); - } - else if (oi == OID_SHA384_ALG) - { - psAssert(outlen == SHA384_HASH_SIZE); - } -# ifdef USE_MD2 - else if (oi == OID_MD2_ALG) - { - psAssert(outlen == MD5_HASH_SIZE); - } -# endif /* USE_MD2 */ -# ifdef USE_MD5 - else if (oi == OID_MD5_ALG) - { - psAssert(outlen == MD5_HASH_SIZE); - } -# endif /* USE_MD5 */ else { - psAssert(outlen == SHA512_HASH_SIZE); + rc = PS_FAILURE; } - /* Note the last test here requires the buffer to be exactly outlen bytes */ - if ((end - c) < 1 || (*c++ != ASN_OCTET_STRING) || - getAsnLength((const unsigned char **) &c, (uint16_t) (end - c), &len) < 0 || - (uint32_t) (end - c) != outlen) - { + Memset(decrypted, 0, sizeof(decrypted)); - psTraceCrypto("Couldn't parse signed element octet string\n"); - psFree(front, pool); - return PS_FAILURE; - } - /* Will finally be sitting at the hash now */ - Memcpy(out, c, outlen); - psFree(front, pool); - return PS_SUCCESS; + return rc; } /******************************************************************************/ @@ -256,30 +309,29 @@ int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key, unsigned char *out, psSize_t outlen, void *data) { - int32_t err; + int32_t rc; psSize_t ptLen; - if (inlen != key->size) + rc = psRsaDecryptPubExt(pool, + key, + in, + inlen, + out, + &ptLen, + outlen, + data); + if (rc != PS_SUCCESS) { - psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPub\n"); - return PS_ARG_FAIL; + return rc; } - ptLen = inlen; - if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen, - PS_PUBKEY, data)) < PS_SUCCESS) + + if (ptLen != outlen) { - psTraceCrypto("Error performing psRsaDecryptPub\n"); - return err; - } - if (ptLen != inlen) - { - psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", ptLen); + psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", + ptLen); return PS_FAILURE; } - if ((err = pkcs1Unpad(in, inlen, out, outlen, PS_PUBKEY)) < 0) - { - return err; - } + return PS_SUCCESS; } diff --git a/crypto/test/algorithmTest.c b/crypto/test/algorithmTest.c index 3e76217..1b092ea 100644 --- a/crypto/test/algorithmTest.c +++ b/crypto/test/algorithmTest.c @@ -4152,12 +4152,50 @@ static int32 psRsaKeyFormatTests(void) unsigned char hashTbs[MAX_HASH_SIZE] = {0}; psSize_t hashTbsLen = sizeof(hashTbs); /* - echo -n "mytbs" \ - |openssl dgst -binary -sha256 \ - |openssl rsautl -inkey testkeys/RSA/2048_RSA_KEY.pem -sign \ + echo -n "mytbs" + |openssl dgst -binary -sha256 + |openssl pkeyutl -inkey testkeys/RSA/2048_RSA_KEY.pem -sign \ + -pkeyopt rsa_padding_mode:pkcs1 -pkeyopt digest:sha256 |xxd -i + + Note: this is a PKCS #1.5 signature (used in TLS 1.2). The hash + of "mytbs" is first wrapped into a DigestInfo. */ - unsigned char expectedSig[] = + unsigned char expectedSig1[] = + { + 0x7f, 0x91, 0xb1, 0x24, 0xc4, 0x85, 0x12, 0x2b, 0x06, 0xef, 0xf1, 0x20, + 0xbb, 0xde, 0x2b, 0x48, 0x39, 0x9b, 0x66, 0xfb, 0x1e, 0x6c, 0x8a, 0x77, + 0x60, 0xec, 0x96, 0x21, 0xe3, 0x8a, 0xa0, 0xcc, 0x2f, 0x0a, 0x97, 0x6d, + 0xa7, 0xd3, 0x6a, 0xb0, 0x89, 0xc2, 0x7a, 0xa4, 0x09, 0xbc, 0x87, 0xfa, + 0xe3, 0x54, 0xc2, 0xde, 0xb3, 0x7d, 0x35, 0x55, 0xda, 0xb1, 0x58, 0xc2, + 0x8d, 0xce, 0xfa, 0xd1, 0x5e, 0xd1, 0xd4, 0xef, 0x25, 0x22, 0x92, 0x8c, + 0xdc, 0x62, 0x3a, 0xdd, 0x87, 0x8b, 0xcf, 0xfc, 0xa1, 0x6c, 0xaf, 0x83, + 0xff, 0xbf, 0x29, 0x09, 0x05, 0xef, 0x76, 0x3a, 0xab, 0xba, 0xde, 0x3b, + 0x16, 0xc9, 0x8e, 0x2a, 0x54, 0xe4, 0x60, 0x27, 0x57, 0xa8, 0x8c, 0xf0, + 0x21, 0x05, 0xa6, 0x8e, 0x52, 0xc7, 0xe8, 0x79, 0x46, 0x46, 0x09, 0x7c, + 0x75, 0xca, 0x7f, 0xc6, 0x98, 0x19, 0xcf, 0x98, 0xdf, 0x31, 0x11, 0x12, + 0x66, 0x23, 0x56, 0xa6, 0xe9, 0x29, 0x71, 0xe4, 0x0f, 0x13, 0xb7, 0x1c, + 0x7e, 0xeb, 0x8b, 0x22, 0xc6, 0x98, 0x64, 0xde, 0x76, 0xfd, 0xa4, 0xbd, + 0x11, 0xea, 0xf5, 0x2c, 0x90, 0x12, 0xc0, 0x1c, 0xe3, 0x79, 0x19, 0xc1, + 0x2f, 0x07, 0x0b, 0x25, 0x94, 0xf8, 0xc8, 0xac, 0x85, 0x87, 0xae, 0xbb, + 0xe5, 0x24, 0xa8, 0x11, 0xeb, 0xc0, 0x46, 0x02, 0xa4, 0x39, 0xd3, 0xe6, + 0xe1, 0x12, 0xfc, 0x60, 0x44, 0x5f, 0x68, 0x1d, 0x06, 0x6a, 0xcb, 0x26, + 0x3e, 0xeb, 0xa3, 0xca, 0xba, 0x70, 0xb9, 0xd8, 0x32, 0x72, 0xf4, 0x26, + 0x2c, 0x5d, 0x5d, 0xee, 0x75, 0x20, 0xf7, 0x52, 0xcc, 0x9c, 0x9f, 0x50, + 0xf5, 0xb2, 0x2c, 0x67, 0x2e, 0x6b, 0xc1, 0xfd, 0x6c, 0xa0, 0x4b, 0x63, + 0x52, 0xe7, 0xb0, 0x4a, 0xcb, 0x87, 0x2c, 0x73, 0x1c, 0xfe, 0xfb, 0xc6, + 0xab, 0xb7, 0x81, 0x6d + }; + /* + echo -n "mytbs" \ + |openssl dgst -binary -sha256 \ + |openssl rsautl -inkey testkeys/RSA/2048_RSA_KEY.pem -sign \ + |xxd -i + + Note: this is a DigestInfoless signature (like the signatures used + in TLS 1.1 and below, but with SHA-256 instead of MD5-SHA1. + */ + unsigned char expectedSig2[] = { 0x27, 0x05, 0x37, 0x60, 0x71, 0x8f, 0x96, 0x9c, 0xbc, 0xc7, 0x29, 0x65, 0xf5, 0xc7, 0x8e, 0xf4, 0x94, 0x8d, 0x2f, 0x23, 0xca, 0x88, 0xd1, 0x68, @@ -4182,13 +4220,16 @@ static int32 psRsaKeyFormatTests(void) 0xb2, 0x65, 0xe1, 0x56, 0xdc, 0xfe, 0xe8, 0xfc, 0x59, 0x8e, 0x00, 0x2f, 0xac, 0x99, 0xac, 0xb4 }; - unsigned char *sig = NULL; - psSize_t sigLen; + unsigned char *sig1 = NULL; + psSize_t sigLen1; + unsigned char *sig2 = NULL; + psSize_t sigLen2; psPubKey_t privKey; psPubKey_t pubKey; int32_t rc; psRes_t rc2; psBool_t verifyOk; + psVerifyOptions_t verifyOpts = {0}; /* Hash some data and sign the hash with 2048_RSA_KEY, then parse 2048_RSA_PUB from PEM and try to verify the signature. */ @@ -4215,28 +4256,58 @@ static int32 psRsaKeyFormatTests(void) goto out_fail; } + /* OID_SHA256_RSA_SIG produces a PKCS #1.5 signature, + where hashTbs is first wrapped into a DigestInfo. */ rc = psSign(NULL, &privKey, OID_SHA256_RSA_SIG, hashTbs, hashTbsLen, - &sig, - &sigLen, + &sig1, + &sigLen1, NULL); if (rc != PS_SUCCESS) { - _psTrace("psSign failed\n"); + _psTrace("psSign failed for sig1\n"); goto out_fail; } - - if (sigLen != sizeof(expectedSig)) + if (sigLen1 != sizeof(expectedSig1)) { - _psTrace("psSign output sig has wrong len\n"); + _psTrace("psSign output sig1 has wrong len\n"); goto out_fail; } - if (Memcmp(sig, expectedSig, sigLen)) + if (Memcmp(sig1, expectedSig1, sigLen1)) { - _psTrace("psSign output sig is wrong\n"); + psTraceBytes("Got: ", sig1, sigLen1); + psTraceBytes("Expected: ", expectedSig1, sigLen1); + _psTrace("psSign output sig1 is wrong\n"); + goto out_fail; + } + /* OID_RSA_TLS_SIG_ALG produces a TLS 1.1 style signature + (without DigestInfo encoding). */ + rc = psSign(NULL, + &privKey, + OID_RSA_TLS_SIG_ALG, + hashTbs, + hashTbsLen, + &sig2, + &sigLen2, + NULL); + if (rc != PS_SUCCESS) + { + _psTrace("psSign failed for sig2\n"); + goto out_fail; + } + if (sigLen2 != sizeof(expectedSig2)) + { + _psTrace("psSign output sig2 has wrong len\n"); + goto out_fail; + } + if (Memcmp(sig2, expectedSig2, sigLen2)) + { + psTraceBytes("Got: ", sig2, sigLen2); + psTraceBytes("Expected: ", expectedSig2, sigLen2); + _psTrace("psSign output sig2 is wrong\n"); goto out_fail; } @@ -4254,30 +4325,67 @@ static int32 psRsaKeyFormatTests(void) pubKey.type = PS_RSA; + verifyOpts.msgIsDigestInfo = PS_TRUE; rc2 = psVerify(NULL, tbs, tbsLen, - sig, - sigLen, + sig1, + sigLen1, &pubKey, OID_SHA256_RSA_SIG, &verifyOk, - NULL); + &verifyOpts); if (rc2 != PS_SUCCESS && !verifyOk) { - _psTrace("psVerify failed\n"); + _psTrace("psVerify failed for sig 1\n"); + goto out_fail; + } + + verifyOpts.msgIsDigestInfo = PS_FALSE; + rc2 = psVerify(NULL, + tbs, + tbsLen, + sig2, + sigLen2, + &pubKey, + OID_SHA256_RSA_SIG, + &verifyOk, + &verifyOpts); + if (rc2 != PS_SUCCESS && !verifyOk) + { + _psTrace("psVerify failed for sig 2\n"); + goto out_fail; + } + + /* Now corrupt the sig a bit and ensure verification fails. */ + sig2[4] = 0x0a; + verifyOpts.msgIsDigestInfo = PS_FALSE; + rc2 = psVerify(NULL, + tbs, + tbsLen, + sig2, + sigLen2, + &pubKey, + OID_SHA256_RSA_SIG, + &verifyOk, + &verifyOpts); + if (verifyOk || rc2 == PS_SUCCESS) + { + _psTrace("psVerify wrong result for corrupted sig 2\n"); goto out_fail; } psClearPubKey(&privKey); psRsaClearKey(&pubKey.key.rsa); - psFree(sig, NULL); + psFree(sig1, NULL); + psFree(sig2, NULL); _psTrace(" PASSED\n"); return PS_SUCCESS; out_fail: - psFree(sig, NULL); + psFree(sig1, NULL); + psFree(sig2, NULL); return PS_FAILURE; } # endif /* USE_PRIVATE_KEY_PARSING */ @@ -6391,6 +6499,7 @@ static int32_t psEccTestParsePriv(void) NULL); if (rc != PS_SUCCESS) { + psEccDeleteKey(&key1); goto fail; } @@ -6446,6 +6555,138 @@ fail: return rc; } +static int32_t psEccTestSigVer() +{ + int32_t rc = PS_FAILURE; + psPubKey_t key_noparam, key_noparam_nopub; + /* This is testkeys/EC/256_EC_KEY.noparam.pem in DER form. */ + unsigned char p256_key_noparam[] = + { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x5c, 0xe9, 0x89, 0xc5, 0xb1, + 0x53, 0xa0, 0x02, 0x3c, 0x90, 0xbe, 0x3a, 0x2a, 0x73, 0xb2, 0x08, 0x16, + 0xc3, 0xed, 0xbc, 0xd5, 0xd6, 0x67, 0x26, 0x10, 0x4e, 0xec, 0x79, 0x28, + 0x0f, 0xbf, 0xcb, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x5f, 0xad, 0x62, + 0x02, 0x42, 0x48, 0xba, 0xfb, 0xe2, 0x88, 0xd8, 0x7f, 0xb9, 0x72, 0xcb, + 0x28, 0xae, 0xc3, 0x8a, 0x1e, 0xc3, 0x0e, 0x9c, 0x7d, 0x7a, 0xa4, 0xb5, + 0x7f, 0xda, 0xbd, 0x46, 0x5a, 0xb9, 0x95, 0x39, 0xe0, 0x44, 0x51, 0x71, + 0xba, 0xe3, 0xb3, 0x40, 0xf2, 0x54, 0xfd, 0x23, 0x84, 0xb2, 0xea, 0x2a, + 0x84, 0xa3, 0x4f, 0xd7, 0xb0, 0x08, 0xba, 0x6e, 0x80, 0xc3, 0xeb, 0xdf, + 0x2f + }; + /* This is testkeys/EC/256_EC_KEY.noparam.nopub.pem in DER form. */ + unsigned char p256_key_noparam_nopub[] = + { + 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0x5c, 0xe9, 0x89, 0xc5, 0xb1, + 0x53, 0xa0, 0x02, 0x3c, 0x90, 0xbe, 0x3a, 0x2a, 0x73, 0xb2, 0x08, 0x16, + 0xc3, 0xed, 0xbc, 0xd5, 0xd6, 0x67, 0x26, 0x10, 0x4e, 0xec, 0x79, 0x28, + 0x0f, 0xbf, 0xcb, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07 + }; + unsigned char tbs[] = {'i', 'n', 's', 'i', 'd', 'e'}; + unsigned char tbs_hash[64] = {0}; + psSize_t tbs_hash_len = sizeof(tbs_hash); + unsigned char sig[150] = {0}; + psSize_t sig_len = sizeof(sig); + int32 verifyResult = 0; + + /* + This is a simple pairwise sign + verify test. But in addition, it + tests that signing is possible without a public key: + key_noparam and key_noparam_nopub contain the same private key, + but key_noparam_nopub omits the optional public key. + */ + + _psTrace(" P-256 sig ver test..."); + + rc = psParseUnknownPrivKeyMem(NULL, + p256_key_noparam, + sizeof(p256_key_noparam), + NULL, + &key_noparam); + if (rc < 0) { + _psTrace("psParseUnknownPrivKeyMem failed\n"); + rc = PS_FAILURE; + goto out_no_key_1; + } + + rc = psParseUnknownPrivKeyMem(NULL, + p256_key_noparam_nopub, + sizeof(p256_key_noparam_nopub), + NULL, + &key_noparam_nopub); + if (rc < 0) { + _psTrace("psParseUnknownPrivKeyMem failed\n"); + rc = PS_FAILURE; + goto out_no_key_2; + } + + rc = psComputeHashForSig(tbs, + sizeof(tbs), + OID_SHA256_ECDSA_SIG, + tbs_hash, + &tbs_hash_len); + if (rc != PS_SUCCESS) + { + _psTraceInt("psComputeHashForSig failed: %d\n", rc); + rc = PS_FAILURE; + goto out; + } + + rc = psEccDsaSign(NULL, + &key_noparam_nopub.key.ecc, + tbs_hash, + tbs_hash_len, + sig, + &sig_len, + 0, + NULL); + if (rc != PS_SUCCESS) + { + _psTraceInt("psEccDsaSign failed : %d\n", rc); + rc = PS_FAILURE; + goto out; + } + + rc = psEccDsaVerify(NULL, + &key_noparam.key.ecc, + tbs_hash, + tbs_hash_len, + sig, + sig_len, + &verifyResult, + NULL); + if (rc != PS_SUCCESS) + { + _psTraceInt("psEccDsaVerify failed : %d\n", rc); + rc = PS_FAILURE; + goto out; + } + if (verifyResult != 1) + { + _psTrace("verification failed failed\n"); + rc = PS_FAILURE; + goto out; + } + +out: + psEccClearKey(&key_noparam_nopub.key.ecc); +out_no_key_2: + psEccClearKey(&key_noparam.key.ecc); +out_no_key_1: + + if (rc == PS_SUCCESS) + { + _psTrace(" PASSED\n"); + } + else + { + _psTrace(" FAILED\n"); + } + + return rc; +} + static int32_t psEccTest(void) { int32_t rc; @@ -6482,6 +6723,12 @@ static int32_t psEccTest(void) return rc; } + rc = psEccTestSigVer(); + if (rc != PS_SUCCESS) + { + return rc; + } + return PS_SUCCESS; } #endif /* USE_ECC */ diff --git a/crypto/test/eccTest.c b/crypto/test/eccTest.c index 7499e57..c9ae90d 100644 --- a/crypto/test/eccTest.c +++ b/crypto/test/eccTest.c @@ -40,7 +40,7 @@ int sign_verify_test1(psEccKey_t *privKey, if (psEccDsaVerify(pool, pubKey, in, sizeof(in), buffer + 2, *buffer_size_result_p - 2, - &validateStatus, NULL) < 0 || validateStatus != 1) + &validateStatus, NULL) < 0) { printf("Operation failed: Ecc Verify\n"); return 2; diff --git a/doc/CHANGES_v4.0.html b/doc/CHANGES_v4.0.html index 1e8ad36..08ce9e3 100644 --- a/doc/CHANGES_v4.0.html +++ b/doc/CHANGES_v4.0.html @@ -8,7 +8,25 @@ -

MatrixSSL 4.0 changelog

+

MatrixSSL 4.x changelog

+

Changes between 4.0.0 and 4.0.1 [November 2018]

+

This version improves the security of RSA PKCS #1.5 signature verification and adds better support for run-time security configuration.

+
    +
  • TLS:

    +
      +
    • Added a run-time security callback feature (matrixSslRegisterSecurityCallback). The security callback can allow or deny a cryptographic operation based on the operation type and the key size. Currently only authentication and key exchange operations are supported. The default security callback supports pre-defined security profiles (matrixSslSetSecurityProfile).

    • +
    • Added an example security profile: WPA3 1.0 Enterprise 192-bit mode restrictions for EAP-TLS.

    • +
    • Added support for the TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ciphersuite.

    • +
    • Changed the way how protocol version IDs are stored internally and rewrote most of the version negotiation code. This is almost entirely an internal code refactoring. To the API user, the only visible change is that version selection APIs now take in an argument of type psProtocolVersion_t instead of int32_t. See the API reference guide for details.

    • +
    • Refactored ServerKeyExchange signature generation and verification code.

    • +
  • +
  • Crypto:

    +
      +
    • Changed from a parsing-based to a comparison-based approach in DigestInfo validation when verifying RSA PKCS #1.5 signatures. There are no known practical attacks against the old code, but the comparison-based approach is theoretically more sound. Thanks to Sze Yiu Chau from Purdue University for pointing this out.

    • +
    • (MatrixSSL FIPS Edition only:) Fix DH key exchange when using DH parameter files containing optional privateValueLength argument.

    • +
    • psX509AuthenticateCert now uses the common psVerifySig API for signature verification. Previously, CRLs and certificates used different code paths for signature verification.

    • +
  • +

Changes between 3.9.5 and 4.0.0 [August 2018]

This version adds support for RFC 8446 (TLS 1.3), new APIs for configuring session options as well as fixes to security vulnerabilities.