From 5ee143c499d1ed5a80d036b5eb9fc683d9615f88 Mon Sep 17 00:00:00 2001 From: wiidev Date: Thu, 31 Dec 2020 19:00:44 +0000 Subject: [PATCH] Update wolfSSL --- source/libs/libwolfssl/error-ssl.h | 1 + source/libs/libwolfssl/internal.h | 123 ++- source/libs/libwolfssl/libwolfssl.a | Bin 424450 -> 432872 bytes source/libs/libwolfssl/ocsp.h | 22 +- source/libs/libwolfssl/openssl/aes.h | 21 +- source/libs/libwolfssl/openssl/asn1.h | 23 +- source/libs/libwolfssl/openssl/bio.h | 10 + source/libs/libwolfssl/openssl/bn.h | 6 +- source/libs/libwolfssl/openssl/buffer.h | 6 + source/libs/libwolfssl/openssl/conf.h | 72 +- source/libs/libwolfssl/openssl/crypto.h | 30 +- source/libs/libwolfssl/openssl/dh.h | 2 + source/libs/libwolfssl/openssl/ec.h | 3 + source/libs/libwolfssl/openssl/evp.h | 13 +- source/libs/libwolfssl/openssl/lhash.h | 62 ++ source/libs/libwolfssl/openssl/ocsp.h | 7 + source/libs/libwolfssl/openssl/opensslv.h | 6 +- source/libs/libwolfssl/openssl/pem.h | 3 + source/libs/libwolfssl/openssl/pkcs12.h | 1 + source/libs/libwolfssl/openssl/pkcs7.h | 6 + source/libs/libwolfssl/openssl/rsa.h | 7 + source/libs/libwolfssl/openssl/srp.h | 29 + source/libs/libwolfssl/openssl/ssl.h | 97 +- source/libs/libwolfssl/openssl/stack.h | 3 - source/libs/libwolfssl/openssl/x509.h | 20 +- source/libs/libwolfssl/openssl/x509v3.h | 19 +- source/libs/libwolfssl/sniffer_error.h | 2 +- source/libs/libwolfssl/ssl.h | 241 ++++- source/libs/libwolfssl/version.h | 4 +- source/libs/libwolfssl/wolfcrypt/aes.h | 21 +- source/libs/libwolfssl/wolfcrypt/asn.h | 132 ++- source/libs/libwolfssl/wolfcrypt/asn_public.h | 1 + source/libs/libwolfssl/wolfcrypt/chacha.h | 12 + .../libwolfssl/wolfcrypt/chacha20_poly1305.h | 25 + source/libs/libwolfssl/wolfcrypt/compress.h | 2 + source/libs/libwolfssl/wolfcrypt/cpuid.h | 2 + source/libs/libwolfssl/wolfcrypt/cryptocb.h | 18 +- source/libs/libwolfssl/wolfcrypt/dh.h | 4 +- source/libs/libwolfssl/wolfcrypt/ecc.h | 35 +- source/libs/libwolfssl/wolfcrypt/fe_448.h | 15 +- source/libs/libwolfssl/wolfcrypt/hmac.h | 9 +- source/libs/libwolfssl/wolfcrypt/integer.h | 4 +- source/libs/libwolfssl/wolfcrypt/logging.h | 12 + source/libs/libwolfssl/wolfcrypt/mem_track.h | 28 +- source/libs/libwolfssl/wolfcrypt/misc.h | 14 + source/libs/libwolfssl/wolfcrypt/pkcs12.h | 2 + source/libs/libwolfssl/wolfcrypt/pkcs7.h | 8 +- source/libs/libwolfssl/wolfcrypt/poly1305.h | 3 + .../libwolfssl/wolfcrypt/port/atmel/atmel.h | 4 +- .../wolfcrypt/port/silabs/silabs_aes.h | 67 ++ .../wolfcrypt/port/silabs/silabs_ecc.h | 63 ++ .../wolfcrypt/port/silabs/silabs_hash.h | 66 ++ .../wolfcrypt/port/silabs/silabs_random.h | 35 + source/libs/libwolfssl/wolfcrypt/random.h | 5 + source/libs/libwolfssl/wolfcrypt/rsa.h | 16 +- source/libs/libwolfssl/wolfcrypt/settings.h | 128 ++- source/libs/libwolfssl/wolfcrypt/sha.h | 5 + source/libs/libwolfssl/wolfcrypt/sha256.h | 5 + source/libs/libwolfssl/wolfcrypt/sha3.h | 4 +- source/libs/libwolfssl/wolfcrypt/sha512.h | 8 + source/libs/libwolfssl/wolfcrypt/sp_int.h | 960 ++++++++++++++---- source/libs/libwolfssl/wolfcrypt/types.h | 19 +- source/libs/libwolfssl/wolfcrypt/wc_pkcs11.h | 1 - source/libs/libwolfssl/wolfcrypt/wc_port.h | 75 +- source/network/picohttpparser.c | 2 +- 65 files changed, 2212 insertions(+), 437 deletions(-) create mode 100644 source/libs/libwolfssl/openssl/srp.h create mode 100644 source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_aes.h create mode 100644 source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_ecc.h create mode 100644 source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_hash.h create mode 100644 source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_random.h diff --git a/source/libs/libwolfssl/error-ssl.h b/source/libs/libwolfssl/error-ssl.h index de412772..837d6c54 100644 --- a/source/libs/libwolfssl/error-ssl.h +++ b/source/libs/libwolfssl/error-ssl.h @@ -169,6 +169,7 @@ enum wolfSSL_ErrorCodes { TLS13_SECRET_CB_E = -438, /* TLS1.3 secret Cb fcn failure */ DTLS_SIZE_ERROR = -439, /* Trying to send too much data */ NO_CERT_ERROR = -440, /* TLS1.3 - no cert set error */ + APP_DATA_READY = -441, /* DTLS1.2 application data ready for read */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/source/libs/libwolfssl/internal.h b/source/libs/libwolfssl/internal.h index ea96bb1b..0ad318ec 100644 --- a/source/libs/libwolfssl/internal.h +++ b/source/libs/libwolfssl/internal.h @@ -146,6 +146,8 @@ /* do nothing, just don't pick Unix */ #elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS) /* do nothing */ +#elif defined(RTTHREAD) + /* do nothing */ #elif defined(EBSNET) /* do nothing */ #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) @@ -1692,6 +1694,11 @@ WOLFSSL_LOCAL int CompleteServerHello(WOLFSSL *ssl); WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv); WOLFSSL_LOCAL int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz); +#ifdef WOLF_CRYPTO_CB +WOLFSSL_LOCAL int CreateDevPrivateKey(void** pkey, byte* buffer, word32 length, + int hsType, int label, int id, + void* heap, int devId); +#endif WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word16* length); #ifdef HAVE_PK_CALLBACKS WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl); @@ -1713,9 +1720,11 @@ WOLFSSL_LOCAL int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz); WOLFSSL_LOCAL int HashInput(WOLFSSL* ssl, const byte* input, int sz); -#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#ifdef HAVE_SNI +#ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl); #endif +#endif #ifdef WOLFSSL_TLS13 WOLFSSL_LOCAL int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, const byte* aad, word16 aadSz); @@ -1727,6 +1736,7 @@ WOLFSSL_LOCAL int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz, byte* extMsgType); +WOLFSSL_LOCAL int RestartHandshakeHash(WOLFSSL* ssl); #endif int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, int pLen, int content); @@ -1998,18 +2008,22 @@ struct WOLFSSL_CERT_MANAGER { #ifndef NO_WOLFSSL_CM_VERIFY VerifyCallback verifyCallback; /* Verify callback */ #endif - CallbackCACache caCacheCallback; /* CA cache addition callback */ - CbMissingCRL cbMissingCRL; /* notify through cb of missing crl */ - CbOCSPIO ocspIOCb; /* I/O callback for OCSP lookup */ - CbOCSPRespFree ocspRespFreeCb; /* Frees OCSP Response from IO Cb */ - wolfSSL_Mutex caLock; /* CA list lock */ - byte crlEnabled; /* is CRL on ? */ - byte crlCheckAll; /* always leaf, but all ? */ - byte ocspEnabled; /* is OCSP on ? */ - byte ocspCheckAll; /* always leaf, but all ? */ - byte ocspSendNonce; /* send the OCSP nonce ? */ - byte ocspUseOverrideURL; /* ignore cert's responder, override */ - byte ocspStaplingEnabled; /* is OCSP Stapling on ? */ + CallbackCACache caCacheCallback; /* CA cache addition callback */ + CbMissingCRL cbMissingCRL; /* notify thru cb of missing crl */ + CbOCSPIO ocspIOCb; /* I/O callback for OCSP lookup */ + CbOCSPRespFree ocspRespFreeCb; /* Frees OCSP Response from IO Cb */ + wolfSSL_Mutex caLock; /* CA list lock */ + byte crlEnabled:1; /* is CRL on ? */ + byte crlCheckAll:1; /* always leaf, but all ? */ + byte ocspEnabled:1; /* is OCSP on ? */ + byte ocspCheckAll:1; /* always leaf, but all ? */ + byte ocspSendNonce:1; /* send the OCSP nonce ? */ + byte ocspUseOverrideURL:1; /* ignore cert responder, override */ + byte ocspStaplingEnabled:1; /* is OCSP Stapling on ? */ +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ +|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + byte ocspMustStaple:1; /* server must respond with staple */ +#endif #ifndef NO_RSA short minRsaKeySz; /* minimum allowed RSA key size */ @@ -2017,6 +2031,8 @@ struct WOLFSSL_CERT_MANAGER { #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) short minEccKeySz; /* minimum allowed ECC key size */ #endif + wolfSSL_Mutex refMutex; /* reference count mutex */ + int refCount; /* reference count */ }; WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*); @@ -2158,14 +2174,16 @@ typedef struct Keys { #ifdef HAVE_TLS_EXTENSIONS typedef enum { +#ifdef HAVE_SNI TLSX_SERVER_NAME = 0x0000, /* a.k.a. SNI */ +#endif TLSX_MAX_FRAGMENT_LENGTH = 0x0001, TLSX_TRUSTED_CA_KEYS = 0x0003, TLSX_TRUNCATED_HMAC = 0x0004, TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stapling */ TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ TLSX_EC_POINT_FORMATS = 0x000b, -#if !defined(WOLFSSL_NO_SIGALG) +#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) TLSX_SIGNATURE_ALGORITHMS = 0x000d, /* HELLO_EXT_SIG_ALGO */ #endif TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ @@ -2184,14 +2202,18 @@ typedef enum { TLSX_EARLY_DATA = 0x002a, #endif TLSX_SUPPORTED_VERSIONS = 0x002b, + #ifdef WOLFSSL_SEND_HRR_COOKIE TLSX_COOKIE = 0x002c, + #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d, #endif #ifdef WOLFSSL_POST_HANDSHAKE_AUTH TLSX_POST_HANDSHAKE_AUTH = 0x0031, #endif + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) TLSX_SIGNATURE_ALGORITHMS_CERT = 0x0032, + #endif TLSX_KEY_SHARE = 0x0033, #endif TLSX_RENEGOTIATION_INFO = 0xff01 @@ -2334,7 +2356,7 @@ typedef struct { union { OcspRequest ocsp; } request; -#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) +#if defined(WOLFSSL_TLS13) buffer response; #endif } CertificateStatusRequest; @@ -2620,9 +2642,14 @@ enum SetCBIO { #endif #ifdef WOLFSSL_STATIC_EPHEMERAL +/* contains static ephemeral keys */ typedef struct { - int keyAlgo; - DerBuffer* key; +#ifndef NO_DH + DerBuffer* dhKey; +#endif +#ifdef HAVE_ECC + DerBuffer* ecKey; +#endif } StaticKeyExchangeInfo_t; #endif @@ -2644,7 +2671,7 @@ struct WOLFSSL_CTX { DerBuffer* certificate; DerBuffer* certChain; /* chain after self, in DER, with leading size for each cert */ - #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY) WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; #endif #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ @@ -2656,8 +2683,9 @@ struct WOLFSSL_CTX { int certChainCnt; #endif DerBuffer* privateKey; - byte privateKeyType:7; + byte privateKeyType:6; byte privateKeyId:1; + byte privateKeyLabel:1; int privateKeySz; int privateKeyDevId; WOLFSSL_CERT_MANAGER* cm; /* our cert manager, ctx owns SSL will use */ @@ -2804,13 +2832,11 @@ struct WOLFSSL_CTX { #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; #endif -#if defined(HAVE_ALPN) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) +#if defined(HAVE_ALPN) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) CallbackALPNSelect alpnSelect; void* alpnSelectArg; #endif -#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH) )) +#ifdef HAVE_SNI CallbackSniRecv sniRecvCb; void* sniRecvCbArg; #endif @@ -3214,17 +3240,19 @@ struct WOLFSSL_SESSION { #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; #endif + byte side; /* Either WOLFSSL_CLIENT_END or + WOLFSSL_SERVER_END */ }; -WOLFSSL_LOCAL -WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte); -WOLFSSL_LOCAL -int SetSession(WOLFSSL*, WOLFSSL_SESSION*); +WOLFSSL_LOCAL WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte); +WOLFSSL_LOCAL int SetSession(WOLFSSL*, WOLFSSL_SESSION*); +WOLFSSL_LOCAL void FreeSession(WOLFSSL_SESSION*, int); typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int, int); #ifndef NO_CLIENT_CACHE + WOLFSSL_LOCAL WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int); #endif @@ -3312,8 +3340,9 @@ typedef struct Buffers { #ifndef NO_CERTS DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ - byte keyType:7; /* Type of key: RSA, ECC, Ed25519 */ + byte keyType:6; /* Type of key: RSA, ECC, Ed25519 */ byte keyId:1; /* Key data is an id not data */ + byte keyLabel:1; /* Key data is a label not data */ int keySz; /* Size of RSA key */ int keyDevId; /* Device Id for key */ DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */ @@ -3597,6 +3626,8 @@ struct WOLFSSL_STACK { * (safety measure for freeing and shortcut for count) */ #if defined(OPENSSL_ALL) wolf_sk_compare_cb comp; + wolf_sk_hash_cb hash_fn; + unsigned long hash; #endif union { @@ -3608,7 +3639,9 @@ struct WOLFSSL_STACK { WOLFSSL_CIPHER cipher; WOLFSSL_ACCESS_DESCRIPTION* access; WOLFSSL_X509_EXTENSION* ext; +#ifdef OPENSSL_EXTRA WOLFSSL_CONF_VALUE* conf; +#endif void* generic; char* string; WOLFSSL_GENERAL_NAME* gn; @@ -3629,7 +3662,7 @@ struct WOLFSSL_X509_NAME { WOLFSSL_X509_NAME_ENTRY entry[MAX_NAME_ENTRIES]; /* all entries i.e. CN */ WOLFSSL_X509* x509; /* x509 that struct belongs to */ #endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) byte raw[ASN_NAME_MAX]; int rawLen; #endif @@ -3662,6 +3695,7 @@ struct WOLFSSL_X509 { #endif /* (WOLFSSL_SEP || WOLFSSL_QT) && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) WOLFSSL_STACK* ext_sk; /* Store X509_EXTENSIONS from wolfSSL_X509_get_ext */ + WOLFSSL_STACK* ext_sk_full; /* Store X509_EXTENSIONS from wolfSSL_X509_get0_extensions */ WOLFSSL_STACK* ext_d2i;/* Store d2i extensions from wolfSSL_X509_get_ext_d2i */ #endif /* WOLFSSL_QT || OPENSSL_ALL */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) @@ -3731,10 +3765,17 @@ struct WOLFSSL_X509 { byte subjAltNameCrit:1; byte authKeyIdSet:1; byte authKeyIdCrit:1; + byte issuerSet:1; #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#ifdef WOLFSSL_CERT_REQ + byte isCSR:1; +#endif byte serial[EXTERNAL_SERIAL_SIZE]; char subjectCN[ASN_NAME_MAX]; /* common name short cut */ #ifdef WOLFSSL_CERT_REQ +#ifdef OPENSSL_ALL + WOLFSSL_X509_ATTRIBUTE* challengePwAttr; +#endif char challengePw[CTC_NAME_SIZE]; /* for REQ certs */ #endif WOLFSSL_X509_NAME issuer; @@ -3743,7 +3784,11 @@ struct WOLFSSL_X509 { WOLFSSL_X509_ALGOR algor; WOLFSSL_X509_PUBKEY key; #endif - byte issuerSet:1; +#if defined(OPENSSL_ALL) || defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT) || \ + defined(SESSION_CERTS) + byte notBeforeData[CTC_DATE_SIZE]; + byte notAfterData[CTC_DATE_SIZE]; +#endif }; @@ -4077,6 +4122,9 @@ struct WOLFSSL { int dtls_timeout_init; /* starting timeout value */ int dtls_timeout_max; /* maximum timeout value */ int dtls_timeout; /* current timeout value, changes */ +#ifndef NO_ASN_TIME + word32 dtls_start_timeout; +#endif /* !NO_ASN_TIME */ word32 dtls_tx_msg_list_sz; word32 dtls_rx_msg_list_sz; DtlsMsg* dtls_tx_msg_list; @@ -4259,6 +4307,15 @@ struct WOLFSSL { #ifdef WOLFSSL_STATIC_EPHEMERAL StaticKeyExchangeInfo_t staticKE; #endif +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) + /* Added in libest port: allow applications to get the 'tls-unique' Channel + * Binding Type (https://tools.ietf.org/html/rfc5929#section-3). This is + * used in the EST protocol to bind an enrollment to a TLS session through + * 'proof-of-possession' (https://tools.ietf.org/html/rfc7030#section-3.4 + * and https://tools.ietf.org/html/rfc7030#section-3.5). */ + byte clientFinished[TLS_FINISHED_SZ]; + byte serverFinished[TLS_FINISHED_SZ]; +#endif }; @@ -4418,6 +4475,7 @@ WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side); WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl); WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl); WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv); +WOLFSSL_LOCAL int TLSv1_3_Capable(WOLFSSL* ssl); WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl); WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree); @@ -4559,6 +4617,7 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); WOLFSSL_LOCAL int DtlsUseSCRKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int DtlsCheckOrder(WOLFSSL* ssl, int order); #endif + WOLFSSL_LOCAL int IsSCR(WOLFSSL* ssl); WOLFSSL_LOCAL void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out); @@ -4596,6 +4655,7 @@ typedef struct CipherSuiteInfo { byte minor; byte major; #endif + byte flags; } CipherSuiteInfo; WOLFSSL_LOCAL const CipherSuiteInfo* GetCipherNames(void); @@ -4617,7 +4677,8 @@ WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl); WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl); WOLFSSL_LOCAL int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, - byte* cipherSuite); + byte* cipherSuite, int* flags); + enum encrypt_side { ENCRYPT_SIDE_ONLY = 1, diff --git a/source/libs/libwolfssl/libwolfssl.a b/source/libs/libwolfssl/libwolfssl.a index e98409f4e7ad7f9b22c80aa94aba58e1c942dd76..0e690242d17b2504d7537ba7039b8614f2816916 100644 GIT binary patch delta 122460 zcmc$H4}4U`wg1fB&1REqLVyhf2oNAZLShmj;)X=nK)?_pBJ4_vNPO-WKBC@~lnL9W4lA`_dYu~#c zmV3^bnKS2{IdkUEoqMz7T%VIK^j*= ze|Mxa{!KsCny_d!U@G5#$-_1hBpFO%87`KSK7EBG7y z)qlH&-!6dqFEX+6-Q`SKGVPmx;X_QZ{#ti21wWPk`>Ws2%bD`O^Hcw~D*A?c)c-Y2 zuPlIi1vA^Go?-u6KlOjBqHm~2{nu*xKjqB!5B<>o|5$;4aenn5lJ;L*IqFvb9opMJ zSi%0zpL%)5Pg|MY`is;u`@i+4{<|yq8~oLOt9E~*a@4K35vX%+IH8Z6xJ-*oHtetyb?Z~_CxILWtn||S?iTnA; zwrjgTs-(A;M(dP?3Vn*FPi)toLm{3tX zqo`uWygMq!&%2uy*Hqn8-IW@?sh_u}U^i{iya(pi)l8}R?u42}b>Z*#3wB>vb63TE zb&Kw=s;jtb-rW`VJ*c(kDt`&{{{Im_@or)^W8Q-`_l?dA&+lK_yQ+3>#lrg+-BD9f zb^oG8HFwul+_vDJs`=qT1Cq4pN0h;BAN5}q9WEJG5Z*NGS}k>h%^g*7-`v}4!uJgQ zeR%1x0d0R6mgtC@eBX=-)7wsEZgU_ShTlzYj*4yKq4batyShbMkx7s;I76SXayb zuIMfR^)s9UUJe$98o>UDj#XU&RA;%xefQ6+tEsqs(LHxn+&%ZM8g1^}D7WUhE$Z5~bnlCb<~toVv@LnUIK@4^ z=DxbQi|R_|-d%lP?cDh_C1~}wnGjIngA9#e6r>l^a6wbl+&!0wehGx@IYXLsgscX+`3 z9JPsx^gwz1>n|AKzeEA>OvaS+mh^mVH`D^(CG%6&;*$AqWXzt1GKn(%<}T^Cb-@=h zHsCS_i@Rj_Uij4ffj4dJLfy=mBM;(klGXgOOL}`3{4K_!u{>uxWd7f`J-8r)hqv4{ zF#LzReinZ8?qTW%#=2uOg)Y8{u^t8t?cEYqkd|b?vl;7czyZdR4R|YK@dmu#&g`F!H8xg+uXiE4`3w{1wsO}(KzAt`mz~?250z6H^pz&!sOx=gC)?w-@ z99mFW@@GZnk3JfHx-KO=_1N9qslBX54NUugO`;l;Gli zRDRpIc9c(Lp@L($bLRAPuvE`6wpI1CvRqFKJBSK6m~#|j-WIkR^pK~8GYY3uB46Z7 zdJyz9PXlwRAAS`mXuqsXu_uHyGxgXxbKhS`E66a z|Gd4d&Wr%AEr=ctm>-wx7l7>&hIbnMBp$S3($(XW&1ew6ma$yn(lx6t^3}rq7Ki_X zH-~p08?5xn3-?_;T>JIS%5WY}w`A>W#nH_X56(QK9eYR_taO{E9jj1=Il4h2Ta%U@ z1T7^o9J^*XzZf2g{}+U3;s3Pok~M}8UemU9O-y&`kk^LWpY3hGCU>Mq`|rs-L-AZ} zbNuKUJNJhRe|lA)GvsZ09WZBuQp!mTc)tLNaS zXeq$quYaB#vloKFPreGZ4cIz_Cp{7TZofd&LyW5%J`Kz~<`@efeK>scb8Wm&IQIGJ z%9pRT&3S%1=kaa5wx#ma%%#j;gsxdz#T>yZmglSb{o<)1cy}f1OZT?XFQ^K?y6qR+ zN7|H6zivCV^A^tUZ=1BMTv1mKitGqFm1p-1Vp+jR0d@N_%xMD9C{RCSN}zr$etjkc zg71t91Yg9Q2cdxUZy3i`=X)7nF_$H(C%+1;9K=%dQzH@F$pQ@bWOQe`yVXg*34~u} zF0xE`5PDe6A4CUJfB0#CnB%Lf5kpGAl?|1^xc;8?Rl@v)X#>`w{29@XlX7+9whE9)~z|rHcR2aX>pCp0s~d zMwXcwuMK~^e;hv&9`^b`Dv$q@!?)vqPxz772WFJZ{1hnC zixC^9C9onf*JBJWY75Bp)!L;sw!VCh_IX}Z&k?q*lI)ash+x~>g_Z)^k?@7r2PU1D zDTcrv%->w$>^BN{N%+n;1}4>ZNk_%@V7TRtYx%bDZ{HXf_P=>mc>J3^l&HM$&2J8b zjUK@Nb=rlMydMonQLDqhc=K9*ApF^zrHUgtJmx@K_qEW!2~#OdH`yFSul;S84$L6) zPJb&CwJv^ZpjwHf)E)|D;jbW&g@B)zQ@5jl#RbK1@l)c4|0Mo7W8KI!E*Uvthi-@+ z%q?*YwcQ|sok={Svph}jm~yq8i-Dm|z|%GTk~pTg5*Ih+)=pf{e^)22r{CX+>*<*3 z=$GX8SQmUX>vnmD4cg;R+6JnxbjkO67yMus{P$h(jxP9TjP*(dO%5@(7~nzRmAYYU z!-12reLAk%3NdTVwG{9HUv9zY13w9TwPX;&M3opiCB7OswS<9VQlCuat7ZBg;Aeo# zmb3j9_(kAbMLM>8&jJyb-qd!$eKzAise#=MZz8vs4D3UJgT}V$71$}tic6NC%vj1a z5K3e^S~3N$VQ6fx1Af{_FM-cs=FvaTl3@+-Cg53;!3N;lfVWHhMa&t&gd6E^V#?jx zcK5Ge=AGLPZJED$iSv=+YrEeUzW(qhZCC#`Pf=k7W3Av!MKi>LCoU&iz?h9Y%Pn+R z*;tFjCYv+!*h7r^!?$5}BjK1NJeNZNRnWx+f6^>dX(1p#>LRiMuR$_F7;V&R8=g9!32I(mj!}99g(~mRWK4 z*%$>3`U1wTHsB`4Mj9}zGRlD45yK4_l^McyKW@T3>@q*;-vdox2+;!-cfutmqaF(x zyGAnYu^dYj1K!NoXah!Nh7di@Fm|n^_k?1GKt1y?`Wkc}!ePFF)G;>3fT3A|gx%$) zf4Bo?ySiH$%QW&FV60HWNiK6GnY7KcDCTUPzMc$)<)l?*$3m ze4eq167G|0I$fV?3msN5X1{$PT#3xz7uruYU|7`XG<{Lm-%;l8^}f%-vG z!_@uOnp*Zdi9t*r$^>NK7bOf;6fhz>jgJZ#3AhpWatT9v1&oN^li;H|Ov8jC`Opwy zOObS>)2KlCX=Jd?hO-C+cD4m&0)(-lk%>;jfo;EpQL*i)gem_;37F^ zqYmmYMQ}%o4i9XV3-f!l?(f;%;p-N4bL3VdJrKS$d$2O_jJ`e}cn0h9VT95G-H{3r z9qHkgTL(KvLt}o3R_O`D3Q-4SWE5@_!n^P9>&RRVU5<#wx@T*6aEGx_%GW{*d9p2U zWUg2nsdHfmTo4{tI&-l&Ox@2kVA8wiW#$aM%IpnkjD zork|PX(y%Sm%3Q}Xh_A9Ft2_a5>>LkOQm_xc!5w(n7$HgmsTv1otdhjg+6 zSwIMX0_9X2%MAkXS+xf4uhk118GTJjJ3XS{`D}6=zq)2;K?H(0l|abG^5`CfK>muu zpu<`c_q~?{+{LJ^iRQ0Fvrzf@Njud~&S$ISp`xAjHunfe1MIKRDQfvc@;~!ED11$Tx(~T)_{h zti=!1&dM!*Q28(Lf$HEt(f+mnX!{Glu(Z7&{v>(vyx(vz;Ql+{`6uA{G?-BOqe;N^a_TWru8!{h zJM?nYwv^XsT9J0W$%Am;uh1<$(Zoas74&)P?-W>qCxiw8>h}~p2&VvZh5jEDeshHw z;J52Bpnjen1BeH;J@Fy`nzFqSI7r{Qac?AvlSuX38DGgAnv~R^fADPal11NgYH-LNa&xhM?#vsh>%KU zEWIJPPxw$X-KjeU_YDqs*V$dZy_g+M@k3C=e^C%p`Um=VVy5G$pFfx;9IbRWCK^Hu z;J)L!b_VV*PTJ|Q!v~gOBtzHoMRb9Kjb{T(Uu7HUuD(toSr@nykHFgGA1&%xRAMrr zXh>R9+mY76MxntbvW(~z!r9EB)?c~??L8)tUuvg0;$~_-8jJ)DlNM@PYI`v{g4bU) zwMx?=bO&lXav-XZDwl1)l`8fisbI zG`zag56*}wmhTv}JZ880!G6)U)Q&M{vi);l3ABH~F=!-dl^Spl>zv6!__iA0Xqr%l^Z zABA5A=tFMWl3&XBcosQLWrE8x1Nl*?2mGlX;!pL2w|ulG`bg%(>`c+Rwgn$gbaa1T z{phQJdK|wAzrjPKldp$gIh~nwL_R2U(c|J3oMja)NlXqae;mcr!=wK=M70;p;m(GB z%+-Kh=g^DHxpFLbuGootU*=jl3oG))%pSUgM}t!^{hz~}^%)raji~+jLma8l1@j_t(Nbz_`Jgm@cC5CFZ8PfA|_vY3PJo(EXT+ z=@ljm-1j5Dzda(FJ|KI z$5M|3qzK(GA529vKnUdV%|E=;SCu5vgKA%Q!+dC51qF~+pV2oET8z~@?&LROr3NRb zRhsT6>NhwFtRfvHS6GI8BppJCiod}>N??u4{Ugta&W2LDzrY$$QdmPhp_@Zwyn>@p zQ#542DzvY(n0d&g`u35uNU5|4+Eg?PZ8>2}h=u|oIQa@$1ddJR>NAAn71F&vV?;ph zbQ(AYH3K<^;V=!QC?whuU56~9`-j)?l}`U4A^(0KDYp2C`u8}=-|~?XYU_W_N7POy zDf?z8`D-5$*3bjVv@7`s1)Ixa2wBL8BUV3A5kL^#e1FqXq@R#4e3P#jz5zce|9gEz z{T3&gZ8*t4;UkrQr;n)L6iBKqPV%ijBJy1!hRFC)`%S(I% z$O39V@)7?8^z$nQ6B--P?g&B@=NqaL)BQuxYiJi}09#0Of{i#rbu_3n*noK1U?Xt! zUlB|Ynz0`V26bY;vI+fO1|h=z>4zl_;b=c|6NE!L4K_4T>D`wGCJ_k(boWnKvy+7J zBX+2vDkRF_L5aSlheaXC76yNXK<1`rJSWu{wAH`R1AB2=`Cc%hBG4C@U;WV@fIF|1!U*gtmRf zKqJ~46=sM5XD!`*KLtYw=-YT$48NjniT({kFO{h;6%N-d#(TiDZA@JiTLfj~FEk;6 zAE;uM5~_xir0Ek8!{Pj}Ot4B!Dq5-X%tz>;7A6xD*9hk#Yl(t4AW3znqN=Lz{CVoEqxk>f{ns5o9OQQR9fbQ zw2bf-8jP@rawZ9@iMGcOEMf!7(Ci!Cd9zsMtI|;#hNDfX-@>WLaSR6`hY{@y#^hjR z73m{e$tsum2`ust_{uiD{r?VU5l(dlKaoDNgL=a^`3X&GMcS2pMMWD@SnYI}UF0~1 zvtSP)&EhP7kFT_oRsMcIp)Fl8!$Eh@9cAy89p#_)ll|Z7C+gpJlmo(1{&_z+_-%fI z{(o2onQsg#heZ4T|NF_2EBJ}p8BqR)qjdF?qgFrh?ZXzsP{-K%#Uq7}G(DV}Uhoi0 z4E+>q$N6}o+ek5C(pYNhhWX6Zv@tb3cnmu?8`bs%O7urPA`&UVw=sl01qw9#EHv!Y z2%1CCR;*)o%B!Zm83=B~kU9j+F{CzCp?np1g68`WJUeONN%?Hx*-4`31 zo*W-o@lxa>Ev<3#JF$LpX<+4bkuzA_uMb_qvb`^}hadmEZ|s>u{S@k%^_xtz9`VL2r z#gX!J4Vlc@5XV@<6lTZi+1&h8#-1C*@}3yPMg!(6IZIzz#Ik^2+c1cw&&*F9T~LWr z7|5IqLKf~RxaZ=YihCaJY3ft^y^D{$<6eB>9XBf3oP%R*MY~xp4#uZXiG0|{vmVZ@OX(eW4$6R!=_25mMvOH8i-B;xpgdj0LUP}^W- zD31Sf?B~$Qec}F7A|Kp;xsbp4rKg=GnnJ2V%84kHjFS;7f;iN?`+ZhMN3&OORwoV+ zFX4N09>oR|nnvI)e4Bo#Tz{_t&9)&2XH;-+&RK@TPITzFg|9#}M$nAi(2R|;d4r-k z=b$;qV6%#vQ+*HZxeM+26x#C$+Vl6KJ-2mfPcO8k_AEyGO#)2q=|OuI0>6ID`*;Uo zJqyCLfyF0Z45%l*qBH7=>LV~Q+}>hc58+cHZ@)m^EZ%+4+v$U!6?DL)3=Z+S?b-TS z-Yxaldbi{|v3*99xKhVhH8LZBEwPh1Pct?%8P3x#d|@`UEkgwxWOI0|&0$my>sF#k zJa}UxaZ04)BQ!}mDkou7k|sm6$wx0zd#CH0XYaqDu07*jeDSPXz2&Ui+Y;HE^Mt6d zkQjlr$cJa(+>f|w<(;xONf>8- z#6?v!YkgDsz_?vHCF(dU)rwPjuENf152W%@@i?Z#CHus@@a{MJ_PSBLAT-1GHU| z!Hh2HwK#T&e!{&nJ=i7vF*GfdG{w|NRWUEOPDNXl`7m5g2%Sca@%t@p35z2_+SVrUZ%z%4|Iob$+E$!aH!^ro+^!m2)~w9oUwx!_;|g zui|iP{VSDjN~Ild77j}&hd9a^*oExgU7Vr4Wi!C zVD|cn+PQK3KHD>q1=^in-tVg1nVuI*tpZ-Ay*-f^yUqA`O+|p+RdZL>!tZJgr=ogk-bwsc6`m0*-MsrDyeA^z9$pLV zGhuqOz<8&C z2UEi@Es9p$N9kDiaGG!MN;=i8B%jd|CWC^Kd|LQ3P`AYWqS9z}lNTe)^*xM5DFl9IZ8O9Sue1}9rX^FRJ9ZR9@0!pW}Al?`EF5xWv z&JULJB=x`(ld%HHU|7IiYNqss^O%a4N?pDxtT?M!D08WTH5OZ2^b$+UT*?VvjeAJH zvyivt>t?J#M~&0wx4a1S39@7!(!Q>x69xzsKed0?7X)Dqb`CGvG5;Nj@C8*uNB zI|(uv_tm&(Ek?y z58eLY3lzD%an z0B_f3t>Jx@YxA~0fV)FAUT%qnwTzddVrQFklGthsjLy}W|Frp9N!(uaE!i34I?PTQ zhYoAZZRq7N19qWj$!|g6#dq{};{_>Ks#(~D7BarQ;PRP+qicaFs4J*VZRRfyEl1Bx z(|e~222eZ_hVsUnDz0|wwc2NXWr%jyI$qAti1*ZcE!0k}L$6EIU&DyU{blgoPT*q+C-u$~Y2UuH z6;2a%E^`@kZ~w&)c?Va6zrtY|>T}OxtKs1x0Z)itTfWp9JXsK+v@Z0fE98g!URrpC z{6sImLVg^qx#Z1Rs<^I8W!ne+h}*dG_3PTOO}x4XoPR$#KXzCO@d|lL@Cj|xMm`|5 zzV8HjCER632X43=3Vxy}SlUq7Dgv~CY{hf%7&s;hr z($+JVHBE47zH|}x-KstC0v{LCCy4Att(OjHyI(-mDBS+p3%o$#8?_NT_$_?0_Q($Y z;Z=97Y+zXhRpLc`SAmV+1=!OtLyFyPZ;!Sz9LMr9e5_a+-{R8zQ#=Fs;sov+A zyJ4JCx3a?K!VxR?%5gTQHgzX2@Yjj=?!gh?<(R807Ac15@J$V+j{1hIHHB&gD>2wu zq!Dy7m?*oB)rs1V?d1Ks2R!?kO>NFaoM$D19Qz_K-~nyYi+sY+0K{(3TnWG0&9We0 zazh2=8^>z#tik=%du+kV3Tz#0d68=wbr3xe3}72{==TEZLyzHEXsMg(B>Liv$K0!M zCs@0C7rzk|?B2!yJ1PL1)NNn&5;ki1RoX9h;~t~EvzrfAIzG}a?dHAucKnwRx`ma~ zR;Q|eWB|RU;{`2y5B66&)@hUWpxAe}-?@iB$@?CASLELv*@kAQB#*#IT0SLm>@{t` z%lzk82j~MU)Ohr@1=uRReh7BXR}dt|et)QT>1Cc7A5f2# zOhdM;@O#QdZS*UAK&*}CqpQR3+3eb!SNPKyhAzFrGr2bOHU1YnX|4_4$GzIHy}UL# z%PzLl&ddJn!ib%ShI42S?&CwWm-q6y+HLzVmyg76|8gIH+pb*5-~Ps%+@=(jAqcVH zu~EX4@>5+b42wNCjxC^ee_|ZJ3wQO2ampXbG~qo;(4*SiA%&~mRp%lj)D zXKs>i>H7!{@Y0}DJJ}kQu>HyZ<_m4Q#S(tQvvg?eZ}?-%!B4a|e#7rm11pEZ2>3(> zc_?k_hu(vt)Z;NLF&rBnypSA>=%JVOH2A8E&Sg@$6)0oLTMSf-o{Yvb(a#D-FG6EIc z^raEsJZE96YAf+oMPCS3O$lrTOza=M1(Bp$Ul@^>mTvq#T3#YoD=pH zX_Pnk?nu$mMRV_p1gQM9aFpp}8*BKsef((e6RT4NpBNKa?H&5>m4?-Z~o5@D)}6W?0N5#B!v zB40Yb{mvu&o@m~nz4IRbiSpss+9Mr&fb!wH+Or)zU8RnXZ@A3BK<*9(#bcAa6)@zA z_Zfl#Pn3^F#7K?DB8+A$=!@s+i3cqOf_p~=>IY0fO?$diPp2UWbbJ_T52uF>WS{~> z1nR$J`0ruoH)kD2hWzNdnHk;GO9ft;Sj1f4E5)#1amqb&*6WvOs)Td3c-i1>Hv|lN z?!&*{(u07eKDYhm`{EEtQ(J2oU~pK2JtW= za#namaMuO*%wkWj`a@Okrm{d97Wh=a6%1Z*i?IIn1yLaUm7MF%Wx4c)98^qCA@)%^x@m(yUa#VB@%s2edXdBGq zBDkT5P6NH#)H0f$gs)A0WOYX*)lFkG)ump2>{vjVX*-PF72QQ;ZRsnv153U}B$uHS`E-%x)mRG}ccoxgb z^)E-UX_=2I4+r1H zbI-3aduXG0+$p|(L<<3J(MMe6P1@Oy_@80EQy=pIW46b@?|rnq#N==XwS;#!TPv-| z)qSXEJsuO%yi-0VG_0tNJ;4X6X$=)vrEom=#-s>=4VJr9ex+hE40*(ITC$rGdG#g9 zF0G(al)Z=u&1mWE-E|31wM(|piUk81!)$#06Gbf9yZh2slYcK$E>Xd{2-YlLAJWdA z;CuQzLwm&ct7@^t&&q7(t#Go!%w{DDcc1pwNvw(Ufc_^?7w%Xt)eYtz zMa?}+Eak->Djr^^lUa!eVpNmhvE?-Hd-K-*)ILR_ZbxVS0neTFWk;^HUYWiN@h%IC z+!aMF@tg3JJr{68QHyIY<~c;4Sk&S;ihHPNw<}#6@JF~rJJ5&e!-DHEX}os?OY|=3 zu>$)%iRcLK=Rniu{E<)U_46Y7&KKIJk@8KOcWb&x+xbUcHS{!*=4RL#k)S~;SgwJE za*JM4)&gEx)M6{s#(%~~s0k%-_(Ylj6zov~G=_`uyIsscJjN_b*T(6*!g!r%&Es8? zV8;w2&`_b&L35*1Rss*A6Jf$J9ua?;gx}IF1!DxdX*W0S-Eem`RM-;rg?P73Gc%$u zWMd(ZkK(zIKgzqCkrmN}9GLvlB&o+4Yyx0C$tv+>$R|W!Ug9W2{>1$J$VIdOFM27V zc`0Pm$DVGrOJBst^e|EGJ6P{GofahlKgC$?yqCIxtAg%Mv_A)ys4-qt{D@~&vD-bT=TYEER+Taq1n#B z!$K5lg%^Exh7XUYsZ6r^REgL7($^{4;LrK+$wxqPqjYIeOH6vvI_D9yd11E{JZs>q4=1>~lU7 z)6K`v^5NR8XL&APP4LX5LU;`w3QDXWfH~|qrG4cnId*V#izWfr$UM{U& z^%T9l_w_-o^v^sE-g9Yznfr?~+T(xb0|s1Lt2a|B!dY}3#e=ySsUmWFTkIa~jX(2j z<%>q`!k>BHzF*YBKaot01jka>_C+B(J!Dn~Kwz;f_6zw|ODy!J5 zeT*v9y)cDPYD(mSTW8COt!r)u7l*aTe>@$S6zfgxUivc2!vZ!}efO*z1MFq&y}SQ% zh`Jf(bL4AE{aEjo=f)|Yd0Wn$f{3j<$)MkuW~H8#yjv>gPu!>;-&4SImjgBP#3O5s6SR zDr;^=BJ)JAXQ?7$#$LeSR6J%J%NsKgM;oCqI#-&ynxf|yCEC;re0Y*QvxT)T?zt4N zU9&{M>%F_rVE6t4pQ@Z`)!w;)ud$!0(;Q#nz>-%R^A+ZOsoE^MG3~*x_&DqrjbL`~ z5?d|$GDQD;6YQ8rQ)N_@D{U+$A$TX%ZA^eL0OjShL@Ht1Gni^uuEcZ;Ww#ZD{?dUD z|E7DMR*rNXFug5jS0k+vgPW~r_t_@o*{j;_)JIhsQIS~JFc70x69td6NA4YAXE%oM z;^_$3sD*i#RVb&Qs8Ie`^vu~^_rejDrL$Ptbz47B`RraNMl_7V81nHw<+I{EBF>Ok z=VwGB;M;^UOM z4J(_ov%|G0ZVaATV({D@XM%N|=%X_` zUl7t#zUHG;6$3FkE7T1x`I_06tiu3|S7R4H`olozDdwVY>Ut`fG9~i#yGtL!3Odj) zK>5M)=$H->DT|k?EKTz8EP3e)Jf8ij!Q%<8~(gu2HNjcBNvxuZ0#_1tAn9YwV7chY@5cgf$mP>pHjvl^!iDzci zVnI_)jgMJaZN3+KEVoYHlJAW~!h2ZtdIY7LCI|GcJ1oMd$G%$PX{X83t6ptM1e>3) zyzoMTa*u;&YwNi(S$ox?+(w_vWnd((+47!(yH6Vttqe@6(@AucMOjKV9k>FmL(0?` zMD&x6r=pBM=x~d1#M5#r6brjj6vrvhyJM70eE{4#w9oq9Qw1dMfla9)JI(_?2yWj#_pEfKW zbv0^_-)HZoEr?g*N!oZ_+IX-(Ez9gR%SJP8Y68k;X%8kSqoTkqx>|cXUda^C#wnkN zjZbjWx6@0^?<1q}qqk}UP;ewvkM2M=x~`Pfi=!tZ5e?LchN&zLub9_IJD;HR=f&Ek zc-?x=Y7>OQ-5~P@?E$*&)qcIu-S@*sVH^ZvskgsPv@hv~R_LKzd-ZZXuR@=f_D)3A zR##LONMF=l5zZU8OMAQr6vRoFm9}Kx`aactawl4Y0hptTeAq;pSIrafN^A6&j>LR?Aq;aB|A0&Md(s; zwHCLM*$cKvSfG>m0dVM0sP(kx!nUL=qvO)ytb|rQ6TZ)=UsQ0L4w9p3D=sR%v;j#< z&zO@s)t0V}Nm529c9SLCN5Q@cP8dp3u2PiuwU<}f`ce<*)~LOeq-1u6NT;j;wRYPp zVS@%ux*gF5_foQzM5i{rm-47eXLzUKw?ILZ!W}2X*e?8LOB|1`I5lmF#34AZ#4k_c zV_^)kb(xMw&%x2W6~GV5^fCmSO~6-6d^UnaA@ChKuB~3hyQ{au8r3Efb{|f5x`CgQ zg)rz1CEPd&j>ikb0>Gbq`JrxBXL*>fgb18Bz^-4 z*NNlkHOwZ)y=a*Mhs)u*of7gTz>7NzFuol4G~h=5wZO|Q>Fa@$MU4ud1HRCLzYIKR z;3|+`;8=vj)(g5L|=ZNZlVPZ2om4*_h?f{+G+ zY%_XQLdmt@zW`on!C@`z5t;el2JW-q9l$Fscm((Y;10dX?5V)(fIFp0?Ah9dzRHa% zt%$^xDE_A>+WIB&XH@8YBW_QuQet9Bee zwO4{zA~Q5!p27YT*o#^sS*F7<4zjd?zXqHPY2XKdli>{fx4_9z2L2InGEAA^r!xB) z5Xf1V%L=|mM=J)tR>!04fW?)F00UvDa&bv~P#1gz${&Thq{#AJEF5(`jBy@HAE0#d zhMN#-_JT>PEKu3WPykVPcfo@Qpj$yZFY}Xm#ich%)PExIZ-M|!raytxSncvV5Lqwl;SW24IarW}` zXakk`qY)qnAU`kEjy-Jetqx{v;6>y)s12R@xhmor7&@Sm=lGY79ukYu?!C+Aq; z`z`oH;OBws-IY1fSw<8Cm!@;x3Ooc;E|BH#z^PI<(pz=YI1zuY+6FvVl?1YrxTFA2 zcfo�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 delta 114713 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 diff --git a/source/libs/libwolfssl/ocsp.h b/source/libs/libwolfssl/ocsp.h index 4dbc0b84..62313a45 100644 --- a/source/libs/libwolfssl/ocsp.h +++ b/source/libs/libwolfssl/ocsp.h @@ -38,10 +38,12 @@ typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) ||\ - defined(WOLFSSL_HAPROXY) + defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP; -typedef struct OcspRequest WOLFSSL_OCSP_CERTID; +typedef struct OcspEntry WOLFSSL_OCSP_CERTID; + +typedef struct OcspEntry WOLFSSL_OCSP_SINGLERESP; typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ; @@ -62,7 +64,7 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp OcspEntry *entry, OcspRequest *ocspRequest); #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ - defined(WOLFSSL_APACHE_HTTPD) + defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIGHTY) WOLFSSL_API int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, WOLFSSL_OCSP_CERTID *id, int *status, int *reason, @@ -82,8 +84,10 @@ WOLFSSL_API int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags); WOLFSSL_API void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response); +#ifndef NO_BIO WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, OcspResponse** response); +#endif WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, const unsigned char** data, int len); WOLFSSL_API int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, @@ -100,8 +104,20 @@ WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, WOLFSSL_API WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, WOLFSSL_OCSP_CERTID *cid); WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID*); +#ifndef NO_BIO WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out, WOLFSSL_OCSP_REQUEST *req); +#endif + +WOLFSSL_API int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID *, unsigned char **); +WOLFSSL_API const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(const WOLFSSL_OCSP_SINGLERESP *single); +WOLFSSL_API int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single, + int *reason, + WOLFSSL_ASN1_TIME **revtime, + WOLFSSL_ASN1_TIME **thisupd, + WOLFSSL_ASN1_TIME **nextupd); +WOLFSSL_API int wolfSSL_OCSP_resp_count(WOLFSSL_OCSP_BASICRESP *bs); +WOLFSSL_API WOLFSSL_OCSP_SINGLERESP* wolfSSL_OCSP_resp_get0(WOLFSSL_OCSP_BASICRESP *bs, int idx); #endif #ifdef OPENSSL_EXTRA diff --git a/source/libs/libwolfssl/openssl/aes.h b/source/libs/libwolfssl/openssl/aes.h index 6e3b65b7..83121c22 100644 --- a/source/libs/libwolfssl/openssl/aes.h +++ b/source/libs/libwolfssl/openssl/aes.h @@ -42,26 +42,7 @@ * OpenSSL compatibility layer. This makes code working with an AES structure * to need the size of the structure. */ typedef struct WOLFSSL_AES_KEY { - /* aligned and big enough for Aes from wolfssl/wolfcrypt/aes.h */ - ALIGN16 void* holder[(376 + WC_ASYNC_DEV_SIZE)/ sizeof(void*)]; - #ifdef GCM_TABLE - /* key-based fast multiplication table. */ - ALIGN16 void* M0[4096 / sizeof(void*)]; - #endif /* GCM_TABLE */ - #if defined(WOLFSSL_DEVCRYPTO) && \ - (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) - /* large enough for additional devcrypto information */ - void* devKey[288 / sizeof(void*)]; - #endif - #ifdef WOLFSSL_AFALG - void* afalg_holder[288 / sizeof(void*)]; - #endif - #ifdef HAVE_PKCS11 - void* pkcs11_holder[(AES_MAX_ID_LEN + sizeof(int)) / sizeof(void*)]; - #endif - #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) - void* async_holder[128 / sizeof(void*)]; - #endif + ALIGN16 void *buf[(sizeof(Aes) / sizeof(void *)) + 1]; } WOLFSSL_AES_KEY; typedef WOLFSSL_AES_KEY AES_KEY; diff --git a/source/libs/libwolfssl/openssl/asn1.h b/source/libs/libwolfssl/openssl/asn1.h index a8e09385..b31fda47 100644 --- a/source/libs/libwolfssl/openssl/asn1.h +++ b/source/libs/libwolfssl/openssl/asn1.h @@ -32,6 +32,10 @@ #define ASN1_STRING_set wolfSSL_ASN1_STRING_set #define ASN1_STRING_free wolfSSL_ASN1_STRING_free +#define ASN1_get_object wolfSSL_ASN1_get_object +#define d2i_ASN1_OBJECT wolfSSL_d2i_ASN1_OBJECT +#define c2i_ASN1_OBJECT wolfSSL_c2i_ASN1_OBJECT + #define V_ASN1_INTEGER 0x02 #define V_ASN1_OCTET_STRING 0x04 /* tag for ASN1_OCTET_STRING */ #define V_ASN1_NEG 0x100 @@ -66,10 +70,21 @@ #define ASN1_TIME_diff wolfSSL_ASN1_TIME_diff #define ASN1_TIME_set wolfSSL_ASN1_TIME_set +#define V_ASN1_EOC 0 #define V_ASN1_OBJECT 6 +#define V_ASN1_UTF8STRING 12 +#define V_ASN1_SEQUENCE 16 +#define V_ASN1_SET 17 +#define V_ASN1_PRINTABLESTRING 19 +#define V_ASN1_T61STRING 20 +#define V_ASN1_IA5STRING 22 #define V_ASN1_UTCTIME 23 #define V_ASN1_GENERALIZEDTIME 24 -#define V_ASN1_PRINTABLESTRING 19 +#define V_ASN1_UNIVERSALSTRING 28 +#define V_ASN1_BMPSTRING 30 + + +#define V_ASN1_CONSTRUCTED 0x20 #define ASN1_STRING_FLAG_BITS_LEFT 0x008 #define ASN1_STRING_FLAG_NDEF 0x010 @@ -83,6 +98,12 @@ WOLFSSL_API WOLFSSL_ASN1_INTEGER *wolfSSL_BN_to_ASN1_INTEGER( WOLFSSL_API void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value); +WOLFSSL_API int wolfSSL_ASN1_get_object(const unsigned char **in, long *len, int *tag, + int *cls, long inLen); + +WOLFSSL_API WOLFSSL_ASN1_OBJECT *wolfSSL_c2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a, + const unsigned char **pp, long len); + #ifdef OPENSSL_ALL /* IMPLEMENT_ASN1_FUNCTIONS is strictly for external use only. Internally * we don't use this. Some projects use OpenSSL to implement ASN1 types and diff --git a/source/libs/libwolfssl/openssl/bio.h b/source/libs/libwolfssl/openssl/bio.h index 71ef94a9..b7ced08e 100644 --- a/source/libs/libwolfssl/openssl/bio.h +++ b/source/libs/libwolfssl/openssl/bio.h @@ -40,7 +40,14 @@ #define BIO_FLAGS_SHOULD_RETRY WOLFSSL_BIO_FLAG_RETRY #define BIO_new_fp wolfSSL_BIO_new_fp +#if defined(OPENSSL_ALL) \ + || defined(HAVE_STUNNEL) \ + || defined(HAVE_LIGHTY) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) #define BIO_new_file wolfSSL_BIO_new_file +#endif #define BIO_new_fp wolfSSL_BIO_new_fp #define BIO_ctrl wolfSSL_BIO_ctrl #define BIO_ctrl_pending wolfSSL_BIO_ctrl_pending @@ -57,6 +64,7 @@ #define BIO_set_write_buf_size wolfSSL_BIO_set_write_buf_size #define BIO_make_bio_pair wolfSSL_BIO_make_bio_pair +#define BIO_new_fd wolfSSL_BIO_new_fd #define BIO_set_fp wolfSSL_BIO_set_fp #define BIO_get_fp wolfSSL_BIO_get_fp #define BIO_seek wolfSSL_BIO_seek @@ -123,6 +131,7 @@ #define BIO_meth_set_create wolfSSL_BIO_meth_set_create #define BIO_meth_set_destroy wolfSSL_BIO_meth_set_destroy +#define BIO_snprintf XSNPRINTF /* BIO CTRL */ #define BIO_CTRL_RESET 1 @@ -149,6 +158,7 @@ #define BIO_CTRL_DGRAM_QUERY_MTU 40 +#define BIO_FP_TEXT 0x00 #define BIO_NOCLOSE 0x00 #define BIO_CLOSE 0x01 diff --git a/source/libs/libwolfssl/openssl/bn.h b/source/libs/libwolfssl/openssl/bn.h index c49f3809..93be9513 100644 --- a/source/libs/libwolfssl/openssl/bn.h +++ b/source/libs/libwolfssl/openssl/bn.h @@ -40,7 +40,7 @@ typedef struct WOLFSSL_BIGNUM { int neg; /* openssh deference */ void *internal; /* our big num */ -#ifdef WOLFSSL_SP_MATH +#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) sp_int fp; #elif defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) fp_int fp; @@ -49,7 +49,7 @@ typedef struct WOLFSSL_BIGNUM { #define BN_ULONG WOLFSSL_BN_ULONG -#define WOLFSSL_BN_ULONG mp_digit +#define WOLFSSL_BN_ULONG unsigned long typedef struct WOLFSSL_BN_CTX WOLFSSL_BN_CTX; typedef struct WOLFSSL_BN_GENCB WOLFSSL_BN_GENCB; @@ -113,7 +113,7 @@ WOLFSSL_API int wolfSSL_BN_add_word(WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG); WOLFSSL_API int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM*, int); WOLFSSL_API int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM*, int); WOLFSSL_API int wolfSSL_BN_set_word(WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG); -WOLFSSL_API unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM*); +WOLFSSL_API WOLFSSL_BN_ULONG wolfSSL_BN_get_word(const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_add(WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*); diff --git a/source/libs/libwolfssl/openssl/buffer.h b/source/libs/libwolfssl/openssl/buffer.h index 50a56f40..be298d1f 100644 --- a/source/libs/libwolfssl/openssl/buffer.h +++ b/source/libs/libwolfssl/openssl/buffer.h @@ -34,12 +34,18 @@ WOLFSSL_API WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void); WOLFSSL_API int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len); WOLFSSL_API void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf); +WOLFSSL_API size_t wolfSSL_strlcpy(char *dst, const char *src, size_t dstSize); +WOLFSSL_API size_t wolfSSL_strlcat(char *dst, const char *src, size_t dstSize); #define BUF_MEM_new wolfSSL_BUF_MEM_new #define BUF_MEM_grow wolfSSL_BUF_MEM_grow #define BUF_MEM_free wolfSSL_BUF_MEM_free +#define BUF_strdup strdup +#define BUF_strlcpy wolfSSL_strlcpy +#define BUF_strlcat wolfSSL_strlcat + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/source/libs/libwolfssl/openssl/conf.h b/source/libs/libwolfssl/openssl/conf.h index 373239ff..d13f84a3 100644 --- a/source/libs/libwolfssl/openssl/conf.h +++ b/source/libs/libwolfssl/openssl/conf.h @@ -28,18 +28,76 @@ extern "C" { #endif -struct WOLFSSL_CONF_VALUE { +#include +#include + +typedef struct WOLFSSL_CONF_VALUE { char *section; char *name; char *value; -}; +} WOLFSSL_CONF_VALUE; -struct WOLFSSL_INIT_SETTINGS { - char* appname; -}; +/* ssl.h requires WOLFSSL_CONF_VALUE */ +#include -typedef struct WOLFSSL_CONF_VALUE CONF_VALUE; -typedef struct WOLFSSL_INIT_SETTINGS OPENSSL_INIT_SETTINGS; +typedef struct WOLFSSL_CONF { + void *meth_data; + WOLF_LHASH_OF(WOLFSSL_CONF_VALUE) *data; +} WOLFSSL_CONF; + +typedef WOLFSSL_CONF CONF; +typedef WOLFSSL_CONF_VALUE CONF_VALUE; + +#ifdef OPENSSL_EXTRA + +WOLFSSL_API WOLFSSL_CONF_VALUE *wolfSSL_CONF_VALUE_new(void); +WOLFSSL_API int wolfSSL_CONF_add_string(WOLFSSL_CONF *conf, + WOLFSSL_CONF_VALUE *section, WOLFSSL_CONF_VALUE *value); +WOLFSSL_API void wolfSSL_X509V3_conf_free(WOLFSSL_CONF_VALUE *val); + +WOLFSSL_API WOLFSSL_CONF *wolfSSL_NCONF_new(void *meth); +WOLFSSL_API char *wolfSSL_NCONF_get_string(const WOLFSSL_CONF *conf, + const char *group, const char *name); +WOLFSSL_API int wolfSSL_NCONF_get_number(const CONF *conf, const char *group, + const char *name, long *result); +WOLFSSL_API WOLFSSL_STACK *wolfSSL_NCONF_get_section( + const WOLFSSL_CONF *conf, const char *section); +WOLFSSL_API int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline); +WOLFSSL_API void wolfSSL_NCONF_free(WOLFSSL_CONF *conf); + +WOLFSSL_API WOLFSSL_CONF_VALUE *wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve( + WOLF_LHASH_OF(WOLFSSL_CONF_VALUE) *sk, WOLFSSL_CONF_VALUE *data); + +WOLFSSL_API int wolfSSL_CONF_modules_load(const WOLFSSL_CONF *cnf, const char *appname, + unsigned long flags); +WOLFSSL_API WOLFSSL_CONF_VALUE *wolfSSL_CONF_new_section(WOLFSSL_CONF *conf, + const char *section); +WOLFSSL_API WOLFSSL_CONF_VALUE *wolfSSL_CONF_get_section(WOLFSSL_CONF *conf, + const char *section); + +#define sk_CONF_VALUE_new wolfSSL_sk_CONF_VALUE_new +#define sk_CONF_VALUE_free wolfSSL_sk_CONF_VALUE_free +#define sk_CONF_VALUE_pop_free(a,b) wolfSSL_sk_CONF_VALUE_free(a) +#define sk_CONF_VALUE_num wolfSSL_sk_CONF_VALUE_num +#define sk_CONF_VALUE_value wolfSSL_sk_CONF_VALUE_value + +#define lh_CONF_VALUE_retrieve wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve +#define lh_CONF_VALUE_insert wolfSSL_sk_CONF_VALUE_push + +#define NCONF_new wolfSSL_NCONF_new +#define NCONF_free wolfSSL_NCONF_free +#define NCONF_get_string wolfSSL_NCONF_get_string +#define NCONF_get_section wolfSSL_NCONF_get_section +#define NCONF_get_number wolfSSL_NCONF_get_number +#define NCONF_load wolfSSL_NCONF_load + +#define CONF_modules_load wolfSSL_CONF_modules_load +#define _CONF_new_section wolfSSL_CONF_new_section +#define _CONF_get_section wolfSSL_CONF_get_section + +#define X509V3_conf_free wolfSSL_X509V3_conf_free + +#endif /* OPENSSL_EXTRA */ #ifdef __cplusplus } /* extern "C" */ diff --git a/source/libs/libwolfssl/openssl/crypto.h b/source/libs/libwolfssl/openssl/crypto.h index 2319ff3d..ebcd4079 100644 --- a/source/libs/libwolfssl/openssl/crypto.h +++ b/source/libs/libwolfssl/openssl/crypto.h @@ -24,22 +24,32 @@ #ifndef WOLFSSL_CRYPTO_H_ #define WOLFSSL_CRYPTO_H_ -#include - #include +#include +#include + #ifdef WOLFSSL_PREFIX #include "prefix_crypto.h" #endif +typedef struct WOLFSSL_INIT_SETTINGS { + char* appname; +} WOLFSSL_INIT_SETTINGS; + +typedef WOLFSSL_INIT_SETTINGS OPENSSL_INIT_SETTINGS; WOLFSSL_API const char* wolfSSLeay_version(int type); WOLFSSL_API unsigned long wolfSSLeay(void); WOLFSSL_API unsigned long wolfSSL_OpenSSL_version_num(void); #ifdef OPENSSL_EXTRA +#include + WOLFSSL_API void wolfSSL_OPENSSL_free(void*); WOLFSSL_API void *wolfSSL_OPENSSL_malloc(size_t a); + +WOLFSSL_API int wolfSSL_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); #endif #define CRYPTO_THREADID void @@ -62,14 +72,16 @@ WOLFSSL_API void *wolfSSL_OPENSSL_malloc(size_t a); #define OPENSSL_free wolfSSL_OPENSSL_free #define OPENSSL_malloc wolfSSL_OPENSSL_malloc -#ifdef WOLFSSL_QT - #define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L - #define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L - #define OPENSSL_INIT_LOAD_CONFIG 0x00000040L -#endif +#define OPENSSL_INIT_ENGINE_ALL_BUILTIN 0x00000001L +#define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L +#define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L +#define OPENSSL_INIT_LOAD_CONFIG 0x00000040L + +#define OPENSSL_init_crypto wolfSSL_OPENSSL_init_crypto + #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_EX_DATA) #define CRYPTO_set_mem_ex_functions wolfSSL_CRYPTO_set_mem_ex_functions #define FIPS_mode wolfSSL_FIPS_mode #define FIPS_mode_set wolfSSL_FIPS_mode_set @@ -86,6 +98,6 @@ typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int i #define CRYPTO_THREAD_r_lock wc_LockMutex #define CRYPTO_THREAD_unlock wc_UnLockMutex -#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_EX_DATA */ #endif /* header */ diff --git a/source/libs/libwolfssl/openssl/dh.h b/source/libs/libwolfssl/openssl/dh.h index 30fd35d8..a0454930 100644 --- a/source/libs/libwolfssl/openssl/dh.h +++ b/source/libs/libwolfssl/openssl/dh.h @@ -26,6 +26,7 @@ #define WOLFSSL_DH_H_ #include +#include #ifdef __cplusplus extern "C" { @@ -58,6 +59,7 @@ WOLFSSL_API WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH **dh, WOLFSSL_API int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out); WOLFSSL_API WOLFSSL_DH* wolfSSL_DH_new(void); WOLFSSL_API void wolfSSL_DH_free(WOLFSSL_DH*); +WOLFSSL_API WOLFSSL_DH* wolfSSL_DH_dup(WOLFSSL_DH* dh); WOLFSSL_API int wolfSSL_DH_check(const WOLFSSL_DH *dh, int *codes); WOLFSSL_API int wolfSSL_DH_size(WOLFSSL_DH*); diff --git a/source/libs/libwolfssl/openssl/ec.h b/source/libs/libwolfssl/openssl/ec.h index e616e021..d7f23839 100644 --- a/source/libs/libwolfssl/openssl/ec.h +++ b/source/libs/libwolfssl/openssl/ec.h @@ -301,6 +301,9 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, #define EC_GROUP_get_order wolfSSL_EC_GROUP_get_order #define EC_GROUP_order_bits wolfSSL_EC_GROUP_order_bits #define EC_GROUP_method_of wolfSSL_EC_GROUP_method_of +#ifndef NO_WOLFSSL_STUB +#define EC_GROUP_set_point_conversion_form(...) +#endif #define EC_METHOD_get_field_type wolfSSL_EC_METHOD_get_field_type diff --git a/source/libs/libwolfssl/openssl/evp.h b/source/libs/libwolfssl/openssl/evp.h index aaefeabe..e7c89f33 100644 --- a/source/libs/libwolfssl/openssl/evp.h +++ b/source/libs/libwolfssl/openssl/evp.h @@ -557,6 +557,9 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_derive_init(WOLFSSL_EVP_PKEY_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_PKEY_derive_set_peer(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY *peer); WOLFSSL_API int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_ctrl_str(WOLFSSL_EVP_PKEY_CTX *ctx, + const char *name, const char *value); + WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen); @@ -569,11 +572,13 @@ WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_EVP_PKEY_new(void); WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap); WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to, const WOLFSSL_EVP_PKEY *from); WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey); WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b); WOLFSSL_API int wolfSSL_EVP_PKEY_type(int type); -WOLFSSL_API int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey); -WOLFSSL_API int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_id(const WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_base_id(const WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_get_default_digest_nid(WOLFSSL_EVP_PKEY *pkey, int *pnid); WOLFSSL_API int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey); WOLFSSL_API int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type); @@ -825,11 +830,14 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_PKEY_free wolfSSL_EVP_PKEY_free #define EVP_PKEY_up_ref wolfSSL_EVP_PKEY_up_ref #define EVP_PKEY_size wolfSSL_EVP_PKEY_size +#define EVP_PKEY_copy_parameters wolfSSL_EVP_PKEY_copy_parameters #define EVP_PKEY_missing_parameters wolfSSL_EVP_PKEY_missing_parameters #define EVP_PKEY_cmp wolfSSL_EVP_PKEY_cmp #define EVP_PKEY_type wolfSSL_EVP_PKEY_type #define EVP_PKEY_base_id wolfSSL_EVP_PKEY_base_id +#define EVP_PKEY_get_default_digest_nid wolfSSL_EVP_PKEY_get_default_digest_nid #define EVP_PKEY_id wolfSSL_EVP_PKEY_id +#define EVP_PKEY_CTX_ctrl_str wolfSSL_EVP_PKEY_CTX_ctrl_str #define EVP_SignFinal wolfSSL_EVP_SignFinal #define EVP_SignInit wolfSSL_EVP_SignInit #define EVP_SignInit_ex wolfSSL_EVP_SignInit_ex @@ -917,7 +925,6 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_R_PRIVATE_KEY_DECODE_ERROR (-MIN_CODE_E + 100 + 4) #define EVP_PKEY_NONE NID_undef -#define EVP_PKEY_RSA 6 #define EVP_PKEY_RSA2 19 #define EVP_PKEY_DH 28 #define EVP_CIPHER_mode WOLFSSL_CIPHER_mode diff --git a/source/libs/libwolfssl/openssl/lhash.h b/source/libs/libwolfssl/openssl/lhash.h index 01f8535f..84e29404 100644 --- a/source/libs/libwolfssl/openssl/lhash.h +++ b/source/libs/libwolfssl/openssl/lhash.h @@ -1,2 +1,64 @@ +/* lhash.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; 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. + * + * wolfSSL is distributed in the hope that it will be useful, + * but 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + /* lhash.h for openSSL */ +#ifndef WOLFSSL_lhash_H_ +#define WOLFSSL_lhash_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include + +#ifdef OPENSSL_ALL +#define IMPLEMENT_LHASH_HASH_FN(name, type) \ + unsigned long wolfSSL_##name##_LHASH_HASH(const void *arg) \ + { \ + const type *a = arg; \ + return name##_hash(a); \ + } +#define IMPLEMENT_LHASH_COMP_FN(name, type) \ + int wolfSSL_##name##_LHASH_COMP(const void *p1, const void *p2) \ + { \ + const type *_p1 = p1; \ + const type *_p2 = p2; \ + return name##_cmp(_p1, _p2); \ + } + +#define LHASH_HASH_FN(name) wolfSSL_##name##_LHASH_HASH +#define LHASH_COMP_FN(name) wolfSSL_##name##_LHASH_COMP + +WOLFSSL_API unsigned long wolfSSL_LH_strhash(const char *str); + +WOLFSSL_API void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data); + +#define lh_strhash wolfSSL_LH_strhash + +#endif + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* WOLFSSL_lhash_H_ */ diff --git a/source/libs/libwolfssl/openssl/ocsp.h b/source/libs/libwolfssl/openssl/ocsp.h index 655a1751..f2fde405 100644 --- a/source/libs/libwolfssl/openssl/ocsp.h +++ b/source/libs/libwolfssl/openssl/ocsp.h @@ -30,6 +30,7 @@ #define OCSP_REQUEST OcspRequest #define OCSP_RESPONSE OcspResponse #define OCSP_BASICRESP WOLFSSL_OCSP_BASICRESP +#define OCSP_SINGLERESP WOLFSSL_OCSP_SINGLERESP #define OCSP_CERTID WOLFSSL_OCSP_CERTID #define OCSP_ONEREQ WOLFSSL_OCSP_ONEREQ @@ -76,6 +77,12 @@ #define i2d_OCSP_REQUEST_bio wolfSSL_i2d_OCSP_REQUEST_bio +#define i2d_OCSP_CERTID wolfSSL_i2d_OCSP_CERTID +#define OCSP_SINGLERESP_get0_id wolfSSL_OCSP_SINGLERESP_get0_id +#define OCSP_single_get0_status wolfSSL_OCSP_single_get0_status +#define OCSP_resp_count wolfSSL_OCSP_resp_count +#define OCSP_resp_get0 wolfSSL_OCSP_resp_get0 + #endif /* HAVE_OCSP */ #endif /* WOLFSSL_OCSP_H_ */ diff --git a/source/libs/libwolfssl/openssl/opensslv.h b/source/libs/libwolfssl/openssl/opensslv.h index 7f82800d..4b32dcc7 100644 --- a/source/libs/libwolfssl/openssl/opensslv.h +++ b/source/libs/libwolfssl/openssl/opensslv.h @@ -26,7 +26,11 @@ /* api version compatibility */ -#if defined(WOLFSSL_APACHE_HTTPD) +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x0090810fL) ||\ + defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x10100000L) ||\ + defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x10001040L) + /* valid version */ +#elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100000L #elif defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \ diff --git a/source/libs/libwolfssl/openssl/pem.h b/source/libs/libwolfssl/openssl/pem.h index 0fd31631..e31fb279 100644 --- a/source/libs/libwolfssl/openssl/pem.h +++ b/source/libs/libwolfssl/openssl/pem.h @@ -242,6 +242,9 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh); #define PEM_write_ECPrivateKey wolfSSL_PEM_write_ECPrivateKey #define PEM_read_bio_ECPrivateKey wolfSSL_PEM_read_bio_ECPrivateKey #define PEM_read_bio_EC_PUBKEY wolfSSL_PEM_read_bio_EC_PUBKEY +#ifndef NO_WOLFSSL_STUB +#define PEM_write_bio_ECPKParameters(...) 0 +#endif /* EVP_KEY */ #define PEM_read_bio_PrivateKey wolfSSL_PEM_read_bio_PrivateKey #define PEM_read_PUBKEY wolfSSL_PEM_read_PUBKEY diff --git a/source/libs/libwolfssl/openssl/pkcs12.h b/source/libs/libwolfssl/openssl/pkcs12.h index 55e8ba45..f7481f45 100644 --- a/source/libs/libwolfssl/openssl/pkcs12.h +++ b/source/libs/libwolfssl/openssl/pkcs12.h @@ -42,6 +42,7 @@ /* wolfSSL level using structs from ssl.h and calls down to wolfCrypt */ #define d2i_PKCS12_bio wolfSSL_d2i_PKCS12_bio #define PKCS12_parse wolfSSL_PKCS12_parse +#define PKCS12_verify_mac wolfSSL_PKCS12_verify_mac #define PKCS12_create wolfSSL_PKCS12_create #define PKCS12_PBE_add wolfSSL_PKCS12_PBE_add diff --git a/source/libs/libwolfssl/openssl/pkcs7.h b/source/libs/libwolfssl/openssl/pkcs7.h index a589a5ae..6163cc78 100644 --- a/source/libs/libwolfssl/openssl/pkcs7.h +++ b/source/libs/libwolfssl/openssl/pkcs7.h @@ -43,6 +43,7 @@ typedef struct WOLFSSL_PKCS7 PKCS7 pkcs7; unsigned char* data; int len; + WOLFSSL_STACK* certs; } WOLFSSL_PKCS7; @@ -53,8 +54,12 @@ WOLFSSL_API void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7); WOLFSSL_API PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len); WOLFSSL_API PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7); +WOLFSSL_API int wolfSSL_i2d_PKCS7_bio(WOLFSSL_BIO *bio, PKCS7 *p7); WOLFSSL_API int wolfSSL_PKCS7_verify(PKCS7* p7, WOLFSSL_STACK* certs, WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, WOLFSSL_BIO* out, int flags); +WOLFSSL_API int wolfSSL_PKCS7_encode_certs(PKCS7* p7, WOLFSSL_STACK* certs, + WOLFSSL_BIO* out); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_PKCS7_to_stack(PKCS7* pkcs7); WOLFSSL_API WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* p7, WOLFSSL_STACK* certs, int flags); WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7); @@ -65,6 +70,7 @@ WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7); #define PKCS7_SIGNED_free wolfSSL_PKCS7_SIGNED_free #define d2i_PKCS7 wolfSSL_d2i_PKCS7 #define d2i_PKCS7_bio wolfSSL_d2i_PKCS7_bio +#define i2d_PKCS7_bio wolfSSL_i2d_PKCS7_bio #define PKCS7_verify wolfSSL_PKCS7_verify #define PKCS7_get0_signers wolfSSL_PKCS7_get0_signers #define PEM_write_bio_PKCS7 wolfSSL_PEM_write_bio_PKCS7 diff --git a/source/libs/libwolfssl/openssl/rsa.h b/source/libs/libwolfssl/openssl/rsa.h index 209e7418..be514482 100644 --- a/source/libs/libwolfssl/openssl/rsa.h +++ b/source/libs/libwolfssl/openssl/rsa.h @@ -117,9 +117,16 @@ WOLFSSL_API int wolfSSL_RSA_sign(int type, const unsigned char* m, WOLFSSL_API int wolfSSL_RSA_sign_ex(int type, const unsigned char* m, unsigned int mLen, unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA*, int); +WOLFSSL_API int wolfSSL_RSA_sign_generic_padding(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA*, int, int); WOLFSSL_API int wolfSSL_RSA_verify(int type, const unsigned char* m, unsigned int mLen, const unsigned char* sig, unsigned int sigLen, WOLFSSL_RSA*); +WOLFSSL_API int wolfSSL_RSA_verify_ex(int type, const unsigned char* m, + unsigned int mLen, const unsigned char* sig, + unsigned int sigLen, WOLFSSL_RSA* rsa, + int padding); WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, unsigned char* to, WOLFSSL_RSA*, int padding); WOLFSSL_API int wolfSSL_RSA_GenAdd(WOLFSSL_RSA*); diff --git a/source/libs/libwolfssl/openssl/srp.h b/source/libs/libwolfssl/openssl/srp.h new file mode 100644 index 00000000..23657ee6 --- /dev/null +++ b/source/libs/libwolfssl/openssl/srp.h @@ -0,0 +1,29 @@ +/* srp.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; 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. + * + * wolfSSL is distributed in the hope that it will be useful, + * but 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef WOLFSSL_SRP_H_ +#define WOLFSSL_SRP_H_ + +#include + +#define SRP_MINIMAL_N SRP_MODULUS_MIN_BITS + +#endif /* WOLFSSL_SRP_H_ */ diff --git a/source/libs/libwolfssl/openssl/ssl.h b/source/libs/libwolfssl/openssl/ssl.h index 7482f82c..bf35a5d3 100644 --- a/source/libs/libwolfssl/openssl/ssl.h +++ b/source/libs/libwolfssl/openssl/ssl.h @@ -53,6 +53,8 @@ /* all NID_* values are in asn.h */ #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -67,6 +69,10 @@ #undef ASN1_INTEGER #endif +#ifdef OPENSSL_EXTRA +#include +WOLFSSL_API int wolfSSL_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); +#endif typedef WOLFSSL SSL; typedef WOLFSSL_SESSION SSL_SESSION; @@ -100,6 +106,7 @@ typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; typedef WOLFSSL_ASN1_STRING ASN1_STRING; typedef WOLFSSL_ASN1_TYPE ASN1_TYPE; +typedef WOLFSSL_X509_ATTRIBUTE X509_ATTRIBUTE; typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; typedef WOLFSSL_BUF_MEM BUF_MEM; @@ -279,9 +286,13 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_CTX_set_cert_verify_callback wolfSSL_CTX_set_cert_verify_callback #define SSL_set_verify wolfSSL_set_verify #define SSL_set_verify_result wolfSSL_set_verify_result +#define SSL_verify_client_post_handshake wolfSSL_verify_client_post_handshake +#define SSL_set_post_handshake_auth wolfSSL_set_post_handshake_auth +#define SSL_CTX_set_post_handshake_auth wolfSSL_CTX_set_post_handshake_auth #define SSL_pending wolfSSL_pending #define SSL_load_error_strings wolfSSL_load_error_strings #define SSL_library_init wolfSSL_library_init +#define OPENSSL_init_ssl wolfSSL_OPENSSL_init_ssl #define OpenSSL_add_ssl_algorithms wolfSSL_library_init #define SSL_CTX_set_session_cache_mode wolfSSL_CTX_set_session_cache_mode #define SSL_CTX_set_cipher_list wolfSSL_CTX_set_cipher_list @@ -297,6 +308,8 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_set_ex_data wolfSSL_set_ex_data #define SSL_get_shutdown wolfSSL_get_shutdown +#define SSL_get_finished wolfSSL_get_finished +#define SSL_get_peer_finished wolfSSL_get_peer_finished #define SSL_set_rfd wolfSSL_set_rfd #define SSL_set_wfd wolfSSL_set_wfd #define SSL_set_shutdown wolfSSL_set_shutdown @@ -333,6 +346,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_MODE_RELEASE_BUFFERS 0x00000010U #define ASN1_BOOLEAN WOLFSSL_ASN1_BOOLEAN #define X509_get_ext wolfSSL_X509_get_ext + #define X509_get_ext_by_OBJ wolfSSL_X509_get_ext_by_OBJ #define X509_cmp wolfSSL_X509_cmp #define X509_EXTENSION_get_object wolfSSL_X509_EXTENSION_get_object #define X509_EXTENSION_get_critical wolfSSL_X509_EXTENSION_get_critical @@ -348,11 +362,14 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define DSA_bits wolfSSL_DSA_bits #define i2d_X509_bio wolfSSL_i2d_X509_bio +#define i2d_X509_REQ_bio wolfSSL_i2d_X509_REQ_bio #define d2i_X509_bio wolfSSL_d2i_X509_bio +#define d2i_X509_REQ_bio wolfSSL_d2i_X509_REQ_bio #define d2i_X509_fp wolfSSL_d2i_X509_fp #define i2d_X509 wolfSSL_i2d_X509 #define d2i_X509 wolfSSL_d2i_X509 #define PEM_read_bio_X509 wolfSSL_PEM_read_bio_X509 +#define PEM_read_bio_X509_REQ wolfSSL_PEM_read_bio_X509_REQ #define PEM_read_bio_X509_CRL wolfSSL_PEM_read_bio_X509_CRL #define PEM_read_bio_X509_AUX wolfSSL_PEM_read_bio_X509_AUX #define PEM_read_X509 wolfSSL_PEM_read_X509 @@ -363,10 +380,18 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define i2d_PrivateKey wolfSSL_i2d_PrivateKey #define i2d_X509_REQ wolfSSL_i2d_X509_REQ +#define d2i_X509_REQ wolfSSL_d2i_X509_REQ #define X509_REQ_new wolfSSL_X509_REQ_new #define X509_REQ_free wolfSSL_X509_REQ_free #define X509_REQ_sign wolfSSL_X509_REQ_sign +#define X509_REQ_sign_ctx wolfSSL_X509_REQ_sign_ctx #define X509_REQ_add_extensions wolfSSL_X509_REQ_add_extensions +#define X509_REQ_add1_attr_by_NID wolfSSL_X509_REQ_add1_attr_by_NID +#define X509_REQ_add1_attr_by_txt wolfSSL_X509_REQ_add1_attr_by_txt +#define X509_REQ_get_attr_by_NID wolfSSL_X509_REQ_get_attr_by_NID +#define X509_REQ_get_attr wolfSSL_X509_REQ_get_attr +#define X509_ATTRIBUTE_get0_type wolfSSL_X509_ATTRIBUTE_get0_type +#define X509_to_X509_REQ wolfSSL_X509_to_X509_REQ #define X509_REQ_set_subject_name wolfSSL_X509_REQ_set_subject_name #define X509_REQ_set_pubkey wolfSSL_X509_REQ_set_pubkey #define PEM_write_bio_X509_REQ wolfSSL_PEM_write_bio_X509_REQ @@ -379,14 +404,19 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_get_ext_count wolfSSL_X509_get_ext_count #define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i #define X509V3_EXT_i2d wolfSSL_X509V3_EXT_i2d +#define X509_get0_extensions wolfSSL_X509_get0_extensions +#define X509_get_extensions wolfSSL_X509_get0_extensions +#define X509_REQ_get_extensions wolfSSL_X509_REQ_get_extensions #define X509_get_ext wolfSSL_X509_get_ext #define X509_get_ext_by_NID wolfSSL_X509_get_ext_by_NID #define X509_get_issuer_name wolfSSL_X509_get_issuer_name #define X509_issuer_name_hash wolfSSL_X509_issuer_name_hash -#define X509_get_subject_name wolfSSL_X509_get_subject_name #define X509_subject_name_hash wolfSSL_X509_subject_name_hash +#define X509_get_subject_name wolfSSL_X509_get_subject_name +#define X509_REQ_get_subject_name wolfSSL_X509_get_subject_name #define X509_get_pubkey wolfSSL_X509_get_pubkey #define X509_get0_pubkey wolfSSL_X509_get_pubkey +#define X509_REQ_get_pubkey wolfSSL_X509_get_pubkey #define X509_get_notBefore wolfSSL_X509_get_notBefore #define X509_get0_notBefore wolfSSL_X509_get_notBefore #define X509_get_notAfter wolfSSL_X509_get_notAfter @@ -408,12 +438,22 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_set_notBefore wolfSSL_X509_set_notBefore #define X509_set_serialNumber wolfSSL_X509_set_serialNumber #define X509_set_version wolfSSL_X509_set_version +#define X509_REQ_set_version wolfSSL_X509_set_version #define X509_sign wolfSSL_X509_sign +#define X509_sign_ctx wolfSSL_X509_sign_ctx #define X509_print wolfSSL_X509_print +#define X509_REQ_print wolfSSL_X509_print #define X509_print_ex wolfSSL_X509_print_ex +#define X509_print_fp wolfSSL_X509_print_fp +#define X509_REQ_print_fp wolfSSL_X509_print_fp +#define X509_signature_print wolfSSL_X509_signature_print +#define X509_get0_signature wolfSSL_X509_get0_signature #define X509_verify_cert_error_string wolfSSL_X509_verify_cert_error_string #define X509_verify_cert wolfSSL_X509_verify_cert +#define X509_verify wolfSSL_X509_verify +#define X509_REQ_verify wolfSSL_X509_REQ_verify #define X509_check_private_key wolfSSL_X509_check_private_key +#define X509_REQ_check_private_key wolfSSL_X509_check_private_key #define X509_check_ca wolfSSL_X509_check_ca #define X509_check_host wolfSSL_X509_check_host #define X509_check_ip_asc wolfSSL_X509_check_ip_asc @@ -421,6 +461,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_check_issued wolfSSL_X509_check_issued #define X509_dup wolfSSL_X509_dup #define X509_add_ext wolfSSL_X509_add_ext +#define X509_delete_ext wolfSSL_X509_delete_ext #define X509_EXTENSION_get_object wolfSSL_X509_EXTENSION_get_object #define X509_EXTENSION_get_data wolfSSL_X509_EXTENSION_get_data @@ -452,6 +493,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define sk_X509_INFO_pop wolfSSL_sk_X509_INFO_pop #define sk_X509_INFO_pop_free wolfSSL_sk_X509_INFO_pop_free #define sk_X509_INFO_free wolfSSL_sk_X509_INFO_free +#define sk_X509_INFO_shift wolfSSL_sk_X509_INFO_pop #define i2d_X509_NAME wolfSSL_i2d_X509_NAME #define d2i_X509_NAME wolfSSL_d2i_X509_NAME @@ -468,9 +510,11 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_NAME_add_entry wolfSSL_X509_NAME_add_entry #define X509_NAME_add_entry_by_txt wolfSSL_X509_NAME_add_entry_by_txt #define X509_NAME_add_entry_by_NID wolfSSL_X509_NAME_add_entry_by_NID +#define X509_NAME_delete_entry wolfSSL_X509_NAME_delete_entry #define X509_NAME_oneline wolfSSL_X509_NAME_oneline #define X509_NAME_get_index_by_NID wolfSSL_X509_NAME_get_index_by_NID #define X509_NAME_print_ex wolfSSL_X509_NAME_print_ex +#define X509_NAME_print_ex_fp wolfSSL_X509_NAME_print_ex_fp #define X509_NAME_digest wolfSSL_X509_NAME_digest #define X509_cmp_current_time wolfSSL_X509_cmp_current_time #define X509_cmp_time wolfSSL_X509_cmp_time @@ -511,6 +555,7 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define X509_STORE_CTX_free wolfSSL_X509_STORE_CTX_free #define X509_STORE_CTX_get_chain wolfSSL_X509_STORE_CTX_get_chain #define X509_STORE_CTX_get1_chain wolfSSL_X509_STORE_CTX_get1_chain +#define X509_STORE_CTX_get0_parent_ctx wolfSSL_X509_STORE_CTX_get0_parent_ctx #define X509_STORE_CTX_get_error wolfSSL_X509_STORE_CTX_get_error #define X509_STORE_CTX_get_error_depth wolfSSL_X509_STORE_CTX_get_error_depth #define X509_STORE_CTX_init wolfSSL_X509_STORE_CTX_init @@ -563,6 +608,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define X509_CRL_get_REVOKED wolfSSL_X509_CRL_get_REVOKED #define X509_get_X509_PUBKEY wolfSSL_X509_get_X509_PUBKEY +#define X509_REQ_get_X509_PUBKEY wolfSSL_X509_get_X509_PUBKEY #define X509_get0_tbs_sigalg wolfSSL_X509_get0_tbs_sigalg #define X509_PUBKEY_get0_param wolfSSL_X509_PUBKEY_get0_param #define X509_PUBKEY_get wolfSSL_X509_PUBKEY_get @@ -610,6 +656,11 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define BIO_set_write_buffer_size wolfSSL_BIO_set_write_buffer_size #define BIO_f_ssl wolfSSL_BIO_f_ssl #define BIO_new_socket wolfSSL_BIO_new_socket +#ifndef NO_WOLFSSL_STUB +#define BIO_new_connect wolfSSL_BIO_new_connect +#define BIO_set_conn_port wolfSSL_BIO_set_conn_port +#define BIO_do_connect wolfSSL_BIO_do_connect +#endif #define SSL_set_bio wolfSSL_set_bio #define BIO_set_ssl wolfSSL_BIO_set_ssl #define BIO_eof wolfSSL_BIO_eof @@ -652,15 +703,22 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define sk_ASN1_OBJECT_free wolfSSL_sk_ASN1_OBJECT_free +#define ASN1_TIME_new wolfSSL_ASN1_TIME_new +#define ASN1_UTCTIME_new wolfSSL_ASN1_TIME_new #define ASN1_TIME_free wolfSSL_ASN1_TIME_free +#define ASN1_UTCTIME_free wolfSSL_ASN1_TIME_free #define ASN1_TIME_adj wolfSSL_ASN1_TIME_adj #define ASN1_TIME_print wolfSSL_ASN1_TIME_print #define ASN1_TIME_to_generalizedtime wolfSSL_ASN1_TIME_to_generalizedtime +#define ASN1_TIME_set wolfSSL_ASN1_TIME_set +#define ASN1_TIME_set_string wolfSSL_ASN1_TIME_set_string +#define ASN1_TIME_to_string wolfSSL_ASN1_TIME_to_string #define ASN1_GENERALIZEDTIME_print wolfSSL_ASN1_GENERALIZEDTIME_print #define ASN1_GENERALIZEDTIME_free wolfSSL_ASN1_GENERALIZEDTIME_free #define ASN1_tag2str wolfSSL_ASN1_tag2str +#define a2i_ASN1_INTEGER wolfSSL_a2i_ASN1_INTEGER #define i2a_ASN1_INTEGER wolfSSL_i2a_ASN1_INTEGER #define i2c_ASN1_INTEGER wolfSSL_i2c_ASN1_INTEGER #define ASN1_INTEGER_new wolfSSL_ASN1_INTEGER_new @@ -673,13 +731,22 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define i2a_ASN1_OBJECT wolfSSL_i2a_ASN1_OBJECT #define i2d_ASN1_OBJECT wolfSSL_i2d_ASN1_OBJECT +#define ASN1_STRING_new wolfSSL_ASN1_STRING_new +#define ASN1_STRING_free wolfSSL_ASN1_STRING_free +#define ASN1_STRING_cmp wolfSSL_ASN1_STRING_cmp #define ASN1_STRING_data wolfSSL_ASN1_STRING_data #define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_data #define ASN1_STRING_length wolfSSL_ASN1_STRING_length #define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 +#define ASN1_UNIVERSALSTRING_to_string wolfSSL_ASN1_UNIVERSALSTRING_to_string #define ASN1_STRING_print_ex wolfSSL_ASN1_STRING_print_ex #define ASN1_STRING_print(x, y) wolfSSL_ASN1_STRING_print ((WOLFSSL_BIO*)(x), (WOLFSSL_ASN1_STRING*)(y)) #define d2i_DISPLAYTEXT wolfSSL_d2i_DISPLAYTEXT +#ifndef NO_WOLFSSL_STUB +#define ASN1_STRING_set_default_mask_asc(...) 1 +#endif + +#define ASN1_PRINTABLE_type(...) V_ASN1_PRINTABLESTRING #define ASN1_UTCTIME_pr wolfSSL_ASN1_UTCTIME_pr @@ -800,6 +867,13 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define PEMerr(func, reason) WOLFSSL_ERROR_LINE((reason), \ NULL, __LINE__, __FILE__, NULL) #endif +#ifndef WOLFCRYPT_ONLY +#define EVPerr(func, reason) wolfSSL_ERR_put_error(ERR_LIB_EVP, \ + (func), (reason), __FILE__, __LINE__) +#else +#define EVPerr(func, reason) WOLFSSL_ERROR_LINE((reason), \ + NULL, __LINE__, __FILE__, NULL) +#endif #define SSLv23_server_method wolfSSLv23_server_method #define SSL_CTX_set_options wolfSSL_CTX_set_options @@ -897,6 +971,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define sk_X509_NAME_find wolfSSL_sk_X509_NAME_find +#define DHparams_dup wolfSSL_DH_dup #define PEM_read_bio_DHparams wolfSSL_PEM_read_bio_DHparams #define PEM_read_bio_DSAparams wolfSSL_PEM_read_bio_DSAparams @@ -924,8 +999,6 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define ERR_LIB_SSL 20 #define SSL_R_SHORT_READ 10 #define ERR_R_PEM_LIB 9 -#define V_ASN1_IA5STRING 22 -#define V_ASN1_UTF8STRING 12 #define SSL_CTRL_MODE 33 #define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 @@ -1091,6 +1164,12 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ + +#ifndef NO_WOLFSSL_STUB +#define b2i_PrivateKey_bio(...) NULL +#define b2i_PVK_bio(...) NULL +#endif + #define SSL_CTX_get_default_passwd_cb wolfSSL_CTX_get_default_passwd_cb #define SSL_CTX_get_default_passwd_cb_userdata wolfSSL_CTX_get_default_passwd_cb_userdata @@ -1128,6 +1207,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #include #define OPENSSL_STRING WOLFSSL_STRING +#define OPENSSL_CSTRING WOLFSSL_STRING #define TLSEXT_TYPE_application_layer_protocol_negotiation 16 @@ -1164,6 +1244,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define OPENSSL_config wolfSSL_OPENSSL_config #define OPENSSL_memdup wolfSSL_OPENSSL_memdup +#define OPENSSL_cleanse wolfSSL_OPENSSL_cleanse #define SSL_CTX_get_timeout wolfSSL_SSL_CTX_get_timeout #define SSL_CTX_set_tmp_ecdh wolfSSL_SSL_CTX_set_tmp_ecdh #define SSL_CTX_remove_session wolfSSL_SSL_CTX_remove_session @@ -1176,7 +1257,11 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb #define SSL_CTX_set_tlsext_status_cb wolfSSL_CTX_set_tlsext_status_cb #define SSL_CTX_get_extra_chain_certs wolfSSL_CTX_get_extra_chain_certs +#define sk_OPENSSL_STRING_num wolfSSL_sk_WOLFSSL_STRING_num #define sk_OPENSSL_STRING_value wolfSSL_sk_WOLFSSL_STRING_value +#define sk_OPENSSL_PSTRING_num wolfSSL_sk_WOLFSSL_STRING_num +#define sk_OPENSSL_PSTRING_value (WOLFSSL_STRING*)wolfSSL_sk_WOLFSSL_STRING_value +#define sk_OPENSSL_STRING_free wolfSSL_sk_free #define SSL_get0_alpn_selected wolfSSL_get0_alpn_selected #define SSL_select_next_proto wolfSSL_select_next_proto #define SSL_CTX_set_alpn_select_cb wolfSSL_CTX_set_alpn_select_cb @@ -1198,8 +1283,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_add_client_CA wolfSSL_CTX_add_client_CA #define SSL_CTX_set_srp_password wolfSSL_CTX_set_srp_password #define SSL_CTX_set_srp_username wolfSSL_CTX_set_srp_username +#define SSL_CTX_set_srp_strength wolfSSL_CTX_set_srp_strength #define SSL_get_SSL_CTX wolfSSL_get_SSL_CTX #define SSL_get0_param wolfSSL_get0_param +#define SSL_get_srp_username wolfSSL_get_srp_username #define ERR_NUM_ERRORS 16 #define SN_pkcs9_emailAddress "Email" @@ -1231,6 +1318,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define OpenSSL_version(x) wolfSSL_OpenSSL_version() +#ifndef NO_WOLFSSL_STUB +#define OBJ_create_objects(...) +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/source/libs/libwolfssl/openssl/stack.h b/source/libs/libwolfssl/openssl/stack.h index baf38a87..559a7967 100644 --- a/source/libs/libwolfssl/openssl/stack.h +++ b/source/libs/libwolfssl/openssl/stack.h @@ -28,15 +28,12 @@ extern "C" { #endif -#include - typedef void (*wolfSSL_sk_freefunc)(void *); WOLFSSL_API void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, wolfSSL_sk_freefunc); WOLFSSL_API void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK *); WOLFSSL_API int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK *sk, void *data); WOLFSSL_API void wolfSSL_sk_pop_free(WOLFSSL_STACK *st, void (*func) (void *)); -WOLFSSL_API void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk); WOLFSSL_API WOLFSSL_STACK *wolfSSL_sk_new_null(void); WOLFSSL_API int wolfSSL_sk_CIPHER_push(WOLFSSL_STACK *st,WOLFSSL_CIPHER *cipher); diff --git a/source/libs/libwolfssl/openssl/x509.h b/source/libs/libwolfssl/openssl/x509.h index 2f8efa2f..5b151453 100644 --- a/source/libs/libwolfssl/openssl/x509.h +++ b/source/libs/libwolfssl/openssl/x509.h @@ -5,6 +5,7 @@ #include #include #include +#include /* wolfSSL_X509_print_ex flags */ #define X509_FLAG_COMPAT (0UL) @@ -23,4 +24,21 @@ #define X509_FLAG_NO_IDS (1UL << 12) #define XN_FLAG_FN_SN 0 -#define XN_FLAG_SEP_CPLUS_SPC 2 +#define XN_FLAG_ONELINE 0 +#define XN_FLAG_COMPAT 0 +#define XN_FLAG_RFC2253 1 +#define XN_FLAG_SEP_COMMA_PLUS (1 << 16) +#define XN_FLAG_SEP_CPLUS_SPC (2 << 16) +#define XN_FLAG_SEP_SPLUS_SPC (3 << 16) +#define XN_FLAG_SEP_MULTILINE (4 << 16) +#define XN_FLAG_SEP_MASK (0xF << 16) +#define XN_FLAG_DN_REV (1 << 20) +#define XN_FLAG_FN_LN (1 << 21) +#define XN_FLAG_FN_OID (2 << 21) +#define XN_FLAG_FN_NONE (3 << 21) +#define XN_FLAG_FN_MASK (3 << 21) +#define XN_FLAG_SPC_EQ (1 << 23) +#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) +#define XN_FLAG_FN_ALIGN (1 << 25) + +#define XN_FLAG_MULTILINE 0xFFFF diff --git a/source/libs/libwolfssl/openssl/x509v3.h b/source/libs/libwolfssl/openssl/x509v3.h index 853d3899..b7412651 100644 --- a/source/libs/libwolfssl/openssl/x509v3.h +++ b/source/libs/libwolfssl/openssl/x509v3.h @@ -83,6 +83,8 @@ struct WOLFSSL_X509_EXTENSION { #define X509V3_CTX WOLFSSL_X509V3_CTX +#define CTX_TEST 0x1 + typedef struct WOLFSSL_AUTHORITY_KEYID AUTHORITY_KEYID; typedef struct WOLFSSL_BASIC_CONSTRAINTS BASIC_CONSTRAINTS; typedef struct WOLFSSL_ACCESS_DESCRIPTION ACCESS_DESCRIPTION; @@ -99,6 +101,8 @@ WOLFSSL_API char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method, const WOLFSSL_ASN1_STRING *s); WOLFSSL_API int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext, unsigned long flag, int indent); +WOLFSSL_API int wolfSSL_X509V3_EXT_add_nconf(WOLFSSL_CONF *conf, WOLFSSL_X509V3_CTX *ctx, + const char *section, WOLFSSL_X509 *cert); #define BASIC_CONSTRAINTS_free wolfSSL_BASIC_CONSTRAINTS_free #define AUTHORITY_KEYID_free wolfSSL_AUTHORITY_KEYID_free @@ -107,11 +111,20 @@ WOLFSSL_API int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, #define ASN1_OCTET_STRING WOLFSSL_ASN1_STRING #define X509V3_EXT_get wolfSSL_X509V3_EXT_get #define X509V3_EXT_d2i wolfSSL_X509V3_EXT_d2i +#define X509V3_EXT_add_nconf wolfSSL_X509V3_EXT_add_nconf +#ifndef NO_WOLFSSL_STUB +#define X509V3_parse_list(...) NULL +#endif #define i2s_ASN1_OCTET_STRING wolfSSL_i2s_ASN1_STRING #define X509V3_EXT_print wolfSSL_X509V3_EXT_print -#define X509V3_EXT_conf_nid wolfSSL_X509V3_EXT_conf_nid -#define X509V3_set_ctx wolfSSL_X509V3_set_ctx -#define X509V3_set_ctx_nodb wolfSSL_X509V3_set_ctx_nodb +#define X509V3_EXT_conf_nid wolfSSL_X509V3_EXT_conf_nid +#define X509V3_set_ctx wolfSSL_X509V3_set_ctx +#ifndef NO_WOLFSSL_STUB +#define X509V3_set_nconf(...) +#endif +#define X509V3_set_ctx_test(ctx) wolfSSL_X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) +#define X509V3_set_ctx_nodb wolfSSL_X509V3_set_ctx_nodb +#define X509v3_get_ext_count wolfSSL_sk_num #ifdef __cplusplus } diff --git a/source/libs/libwolfssl/sniffer_error.h b/source/libs/libwolfssl/sniffer_error.h index 882aaeae..f2710522 100644 --- a/source/libs/libwolfssl/sniffer_error.h +++ b/source/libs/libwolfssl/sniffer_error.h @@ -109,7 +109,6 @@ #define GOT_CERT_STATUS_STR 73 #define RSA_KEY_MISSING_STR 74 #define NO_SECURE_RENEGOTIATION 75 - #define BAD_SESSION_STATS 76 #define REASSEMBLY_MAX_STR 77 #define DROPPING_LOST_FRAG_STR 78 @@ -131,6 +130,7 @@ #define STORE_DATA_FAIL_STR 92 #define CHAIN_INPUT_STR 93 #define GOT_ENC_EXT_STR 94 +#define GOT_HELLO_RETRY_REQ_STR 95 /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ diff --git a/source/libs/libwolfssl/ssl.h b/source/libs/libwolfssl/ssl.h index 5a8105bd..4fc731a8 100644 --- a/source/libs/libwolfssl/ssl.h +++ b/source/libs/libwolfssl/ssl.h @@ -40,6 +40,10 @@ #include #endif + #ifdef WOLF_CRYPTO_CB + #include +#endif + /* used internally by wolfSSL while OpenSSL types aren't */ #include @@ -98,6 +102,19 @@ extern "C" { #endif +/* LHASH is implemented as a stack */ +typedef struct WOLFSSL_STACK WOLFSSL_LHASH; +#ifndef WOLF_LHASH_OF + #define WOLF_LHASH_OF(x) WOLFSSL_LHASH +#endif + +#ifndef WOLF_STACK_OF + #define WOLF_STACK_OF(x) WOLFSSL_STACK +#endif +#ifndef DECLARE_STACK_OF + #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x); +#endif + #ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED #define WOLFSSL_WOLFSSL_TYPE_DEFINED typedef struct WOLFSSL WOLFSSL; @@ -171,7 +188,6 @@ typedef struct WOLFSSL_X509_VERIFY_PARAM WOLFSSL_X509_VERIFY_PARAM; typedef struct WOLFSSL_BIO WOLFSSL_BIO; typedef struct WOLFSSL_BIO_METHOD WOLFSSL_BIO_METHOD; typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION; -typedef struct WOLFSSL_CONF_VALUE WOLFSSL_CONF_VALUE; typedef struct WOLFSSL_ASN1_OBJECT WOLFSSL_ASN1_OBJECT; typedef struct WOLFSSL_ASN1_OTHERNAME WOLFSSL_ASN1_OTHERNAME; typedef struct WOLFSSL_X509V3_CTX WOLFSSL_X509V3_CTX; @@ -185,6 +201,7 @@ typedef struct WOLFSSL_DH WOLFSSL_DH; #endif typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; typedef struct WOLFSSL_ASN1_TYPE WOLFSSL_ASN1_TYPE; +typedef struct WOLFSSL_X509_ATTRIBUTE WOLFSSL_X509_ATTRIBUTE; typedef struct WOLFSSL_GENERAL_NAME WOLFSSL_GENERAL_NAME; typedef struct WOLFSSL_AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID; @@ -314,6 +331,12 @@ struct WOLFSSL_ASN1_TYPE { } value; }; +struct WOLFSSL_X509_ATTRIBUTE { + WOLFSSL_ASN1_OBJECT *object; + WOLFSSL_ASN1_TYPE *value; + WOLF_STACK_OF(WOLFSSL_ASN1_TYPE) *set; +}; + struct WOLFSSL_EVP_PKEY { void* heap; int type; /* openssh dereference */ @@ -468,6 +491,8 @@ struct WOLFSSL_BIO { void* heap; /* user heap hint */ void* ptr; /* WOLFSSL, file descriptor, MD, or mem buf */ void* usrCtx; /* user set pointer */ + const char* ip; /* IP address for wolfIO_TcpConnect */ + word16 port; /* Port for wolfIO_TcpConnect */ char* infoArg; /* BIO callback argument */ wolf_bio_info_cb infoCb; /* BIO callback */ int wrSz; /* write buffer size (mem) */ @@ -523,11 +548,16 @@ struct WOLFSSL_X509_STORE { }; #define WOLFSSL_NO_WILDCARDS 0x4 + +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_WPAS_SMALL) || defined(WOLFSSL_IP_ALT_NAME) + #define WOLFSSL_MAX_IPSTR 46 /* max ip size IPv4 mapped IPv6 */ +#endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */ + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) #define WOLFSSL_USE_CHECK_TIME 0x2 #define WOLFSSL_NO_CHECK_TIME 0x200000 #define WOLFSSL_HOST_NAME_MAX 256 -#define WOLFSSL_MAX_IPSTR 46 /* max ip size IPv4 mapped IPv6 */ struct WOLFSSL_X509_VERIFY_PARAM { time_t check_time; unsigned long flags; @@ -789,8 +819,15 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, #ifndef WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS #define WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS WOLFSSL_LOAD_FLAG_NONE #endif + +WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl); +WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx); +WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); #endif /* !NO_CERTS */ +#define WOLFSSL_CIPHER_SUITE_FLAG_NONE 0x0 +#define WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS 0x1 + #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) WOLFSSL_API int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX*, const char*, @@ -806,9 +843,6 @@ WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX *, const char *file, int format); WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int); -WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl); -WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx); -WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int); WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, @@ -853,6 +887,8 @@ WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char, const unsigned char); WOLFSSL_API const char* wolfSSL_get_cipher_name_iana_from_suite( const unsigned char, const unsigned char); +WOLFSSL_API int wolfSSL_get_cipher_suite_from_name(const char* name, + byte* cipherSuite0, byte* cipherSuite, int* flags); WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len); WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl); @@ -974,6 +1010,14 @@ WOLFSSL_API void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx, WOLFSSL_API void wolfSSL_set_verify(WOLFSSL*, int, VerifyCallback verify_callback); WOLFSSL_API void wolfSSL_set_verify_result(WOLFSSL*, long); + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +WOLFSSL_API int wolfSSL_verify_client_post_handshake(WOLFSSL*); +WOLFSSL_API int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX*, int); +WOLFSSL_API int wolfSSL_set_post_handshake_auth(WOLFSSL*, int); +#endif + WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL*, void*); WOLFSSL_ABI WOLFSSL_API int wolfSSL_pending(WOLFSSL*); @@ -1070,20 +1114,6 @@ WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long); /* extras */ - -/* for now LHASH is not implemented */ -typedef int WOLFSSL_LHASH; -#ifndef WOLF_LHASH_OF - #define WOLF_LHASH_OF(x) WOLFSSL_LHASH -#endif - -#ifndef WOLF_STACK_OF - #define WOLF_STACK_OF(x) WOLFSSL_STACK -#endif -#ifndef DECLARE_STACK_OF - #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x); -#endif - WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap); WOLFSSL_API void wolfSSL_sk_free(WOLFSSL_STACK* sk); WOLFSSL_API void wolfSSL_sk_free_node(WOLFSSL_STACK* in); @@ -1148,6 +1178,7 @@ WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_pop_free( WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, void (*f)(WOLFSSL_ASN1_OBJECT*)); WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in); +WOLFSSL_API int wolfSSL_ASN1_UNIVERSALSTRING_to_string(WOLFSSL_ASN1_STRING *s); WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk); WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value( WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx); @@ -1263,11 +1294,16 @@ WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); #ifndef NO_FILESYSTEM WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void); +WOLFSSL_API WOLFSSL_BIO *wolfSSL_BIO_new_fd(int fd, int close_flag); #endif WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void); WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void); +WOLFSSL_API WOLFSSL_BIO *wolfSSL_BIO_new_connect(const char *str); +WOLFSSL_API long wolfSSL_BIO_set_conn_port(WOLFSSL_BIO *b, char* port); +WOLFSSL_API long wolfSSL_BIO_do_connect(WOLFSSL_BIO *b); + WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg); WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg); @@ -1329,6 +1365,13 @@ WOLFSSL_API int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset #endif WOLFSSL_API int wolfSSL_X509_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, unsigned long nmflags, unsigned long cflag); +#ifndef NO_FILESYSTEM +WOLFSSL_API int wolfSSL_X509_print_fp(XFILE fp, WOLFSSL_X509 *x509); +#endif +WOLFSSL_API int wolfSSL_X509_signature_print(WOLFSSL_BIO *bp, + const WOLFSSL_X509_ALGOR *sigalg, const WOLFSSL_ASN1_STRING *sig); +WOLFSSL_API void wolfSSL_X509_get0_signature(const WOLFSSL_ASN1_BIT_STRING **psig, + const WOLFSSL_X509_ALGOR **palg, const WOLFSSL_X509 *x509); WOLFSSL_API int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); WOLFSSL_ABI WOLFSSL_API char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, char*, int); @@ -1353,6 +1396,9 @@ WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID( WOLFSSL_X509*, unsigned char*, int*); WOLFSSL_API int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey); +#ifdef WOLFSSL_CERT_REQ +WOLFSSL_API int wolfSSL_X509_REQ_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey); +#endif WOLFSSL_API int wolfSSL_X509_set_subject_name(WOLFSSL_X509*, WOLFSSL_X509_NAME*); WOLFSSL_API int wolfSSL_X509_set_issuer_name(WOLFSSL_X509*, @@ -1369,6 +1415,7 @@ WOLFSSL_API int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_API int wolfSSL_X509_set_version(WOLFSSL_X509* x509, long v); WOLFSSL_API int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_MD* md); +WOLFSSL_API int wolfSSL_X509_sign_ctx(WOLFSSL_X509 *x509, WOLFSSL_EVP_MD_CTX *ctx); WOLFSSL_API int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*); @@ -1383,6 +1430,7 @@ WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_dup(WOLFSSL_ASN1_STRING* as WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type); WOLFSSL_API int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1); WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn, const unsigned char **in, long len); +WOLFSSL_API int wolfSSL_ASN1_STRING_cmp(const WOLFSSL_ASN1_STRING *a, const WOLFSSL_ASN1_STRING *b); WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1); WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, int dataSz); @@ -1412,6 +1460,8 @@ WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( WOLFSSL_X509_STORE_CTX* ctx); WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain( WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API WOLFSSL_X509_STORE_CTX *wolfSSL_X509_STORE_CTX_get0_parent_ctx( + WOLFSSL_X509_STORE_CTX *ctx); WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag); WOLFSSL_API int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*); @@ -1425,7 +1475,7 @@ WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX*); WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL*); WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL*); -WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj); WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509*); WOLFSSL_API int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKEY*); @@ -1580,6 +1630,9 @@ WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg( WOLFSSL_API int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX*, WOLFSSL_X509*); WOLFSSL_API int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX*, char*); WOLFSSL_API int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX*, char*); +WOLFSSL_API int wolfSSL_CTX_set_srp_strength(WOLFSSL_CTX *ctx, int strength); + +WOLFSSL_API char* wolfSSL_get_srp_username(WOLFSSL *ssl); WOLFSSL_API long wolfSSL_set_options(WOLFSSL *s, long op); WOLFSSL_API long wolfSSL_get_options(const WOLFSSL *s); @@ -1730,7 +1783,6 @@ enum { * and auto retry */ SSL_MODE_RELEASE_BUFFERS = -1, /* For libwebsockets build. No current use. */ - BIO_FLAGS_BASE64_NO_NL = 1, BIO_CLOSE = 1, BIO_NOCLOSE = 0, @@ -1788,12 +1840,6 @@ enum { X509_R_CERT_ALREADY_IN_HASH_TABLE, - XN_FLAG_SPC_EQ = (1 << 23), - XN_FLAG_SEP_CPLUS_SPC = (2 << 16), - XN_FLAG_ONELINE = 0, - XN_FLAG_RFC2253 = 1, - XN_FLAG_DN_REV = (1 << 20), - CRYPTO_LOCK = 1, CRYPTO_NUM_LOCKS = 10, @@ -2014,7 +2060,7 @@ WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long); WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long); -#if !defined(NO_FILESYSTEM) && !defined(NO_CHECK_PRIVATE_KEY) +#if !defined(NO_CHECK_PRIVATE_KEY) WOLFSSL_API int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX*); #endif WOLFSSL_API void wolfSSL_ERR_free_strings(void); @@ -2061,13 +2107,14 @@ WOLFSSL_API int wolfSSL_ASN1_TIME_diff(int *pday, int *psec, const WOLFSSL_ASN1_TIME *from, const WOLFSSL_ASN1_TIME *to); #ifdef OPENSSL_EXTRA WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t); +WOLFSSL_API int wolfSSL_ASN1_TIME_set_string(WOLFSSL_ASN1_TIME *s, const char *str); #endif -WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_STACK* sk); -WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_STACK* sk, int i); +WOLFSSL_API int wolfSSL_sk_num(const WOLFSSL_STACK* sk); +WOLFSSL_API void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i); #if (defined(HAVE_EX_DATA) || defined(FORTRESS)) && \ - (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL)) WOLFSSL_API void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx); WOLFSSL_API int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, @@ -2164,6 +2211,10 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in, int len); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len); +#ifdef WOLFSSL_CERT_REQ +WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_REQ_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len); +#endif WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out); WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl, const unsigned char *in, int len); @@ -2182,6 +2233,10 @@ WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509* #endif WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( const unsigned char* buf, int sz, int format); +#ifdef WOLFSSL_CERT_REQ +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_REQ_load_certificate_buffer( + const unsigned char* buf, int sz, int format); +#endif #ifdef WOLFSSL_SEP WOLFSSL_API unsigned char* @@ -2209,6 +2264,8 @@ WOLFSSL_API WOLFSSL_X509_PKCS12* wolfSSL_d2i_PKCS12_fp(XFILE fp, WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca); +WOLFSSL_API int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw, + int pswLen); WOLFSSL_API WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert, WOLF_STACK_OF(WOLFSSL_X509)* ca, @@ -2310,7 +2367,13 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*, const unsigned char*, long, int); WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX*, - const unsigned char*, long, int, long); + const unsigned char*, long, + int, long); + WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX*, + const unsigned char*, long, + int); + WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX*, const char*, + int); WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*, const unsigned char*, long, int); WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*, @@ -2324,7 +2387,10 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, WOLFSSL_API int wolfSSL_use_PrivateKey_buffer(WOLFSSL*, const unsigned char*, long, int); WOLFSSL_API int wolfSSL_use_PrivateKey_id(WOLFSSL*, const unsigned char*, - long, int, long); + long, int, long); + WOLFSSL_API int wolfSSL_use_PrivateKey_Id(WOLFSSL*, const unsigned char*, + long, int); + WOLFSSL_API int wolfSSL_use_PrivateKey_Label(WOLFSSL*, const char*, int); WOLFSSL_API int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL*, const unsigned char*, long, int); WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL*, @@ -2392,7 +2458,7 @@ WOLFSSL_API int wolfSSL_CTX_GetObjectSize(void); WOLFSSL_API int wolfSSL_METHOD_GetObjectSize(void); WOLFSSL_API int wolfSSL_GetOutputSize(WOLFSSL*, int); WOLFSSL_API int wolfSSL_GetMaxOutputSize(WOLFSSL*); -WOLFSSL_API int wolfSSL_GetVersion(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_GetVersion(const WOLFSSL* ssl); WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version); /* moved to asn.c, old names kept for backwards compatibility */ @@ -2722,6 +2788,7 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap); WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void); WOLFSSL_API void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER*); + WOLFSSL_API int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER*); WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f, const char* d); @@ -2772,6 +2839,10 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_CERT_MANAGER* cm); WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling( WOLFSSL_CERT_MANAGER* cm); + WOLFSSL_API int wolfSSL_CertManagerEnableOCSPMustStaple( + WOLFSSL_CERT_MANAGER* cm); + WOLFSSL_API int wolfSSL_CertManagerDisableOCSPMustStaple( + WOLFSSL_CERT_MANAGER* cm); #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) WOLFSSL_API WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm); #endif @@ -2808,6 +2879,8 @@ WOLFSSL_API WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm) CbOCSPIO, CbOCSPRespFree, void*); WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_DisableOCSPMustStaple(WOLFSSL_CTX*); #endif /* !NO_CERTS */ @@ -2923,7 +2996,7 @@ enum { WOLFSSL_MAX_ALPN_NUMBER = 257 }; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out, unsigned char* outLen, const unsigned char* in, unsigned int inLen, void *arg); @@ -3233,7 +3306,7 @@ WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, #include struct WOLFSSL_X509_NAME_ENTRY { - WOLFSSL_ASN1_OBJECT object; /* static object just for keeping grp, type */ + WOLFSSL_ASN1_OBJECT* object; /* static object just for keeping grp, type */ WOLFSSL_ASN1_STRING* value; /* points to data, for lighttpd port */ int nid; /* i.e. ASN_COMMON_NAME */ int set; @@ -3290,7 +3363,6 @@ WOLFSSL_LOCAL int NIDToEccEnum(int n); /* end of object functions */ WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line); -WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt); WOLFSSL_API long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void)); WOLFSSL_API long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx); @@ -3310,6 +3382,8 @@ WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name, WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_NID(WOLFSSL_X509_NAME *name, int nid, int type, const unsigned char *bytes, int len, int loc, int set); +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_delete_entry( + WOLFSSL_X509_NAME *name, int loc); WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, const WOLFSSL_X509_NAME* y); WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void); @@ -3320,6 +3394,11 @@ WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); #endif /* !NO_CERTS */ #endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ + || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) +WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); +#endif + #ifdef WOLFSSL_WPAS_SMALL /* WPA Supplicant requires GEN_ values */ #include @@ -3337,6 +3416,7 @@ WOLFSSL_API int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509 *x, int nid, int WOLFSSL_API int wolfSSL_X509_add_ext(WOLFSSL_X509 *x, WOLFSSL_X509_EXTENSION *ex, int loc); WOLFSSL_API WOLFSSL_X509_EXTENSION *wolfSSL_X509V3_EXT_i2d(int nid, int crit, void *data); +WOLFSSL_API WOLFSSL_X509_EXTENSION *wolfSSL_X509_delete_ext(WOLFSSL_X509 *x509, int loc); WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_conf_nid( WOLF_LHASH_OF(CONF_VALUE)* conf, WOLFSSL_X509V3_CTX* ctx, int nid, char* value); @@ -3360,7 +3440,11 @@ WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx, #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) WOLFSSL_API int wolfSSL_X509_cmp(const WOLFSSL_X509* a, const WOLFSSL_X509* b); +WOLFSSL_API const WOLFSSL_STACK *wolfSSL_X509_get0_extensions(const WOLFSSL_X509 *x); +WOLFSSL_API const WOLFSSL_STACK *wolfSSL_X509_REQ_get_extensions(const WOLFSSL_X509 *x); WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x, int loc); +WOLFSSL_API int wolfSSL_X509_get_ext_by_OBJ(const WOLFSSL_X509 *x, + const WOLFSSL_ASN1_OBJECT *obj, int lastpos); WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x, int loc); WOLFSSL_API int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex); WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void); @@ -3382,6 +3466,9 @@ WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses); WOLFSSL_API int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +#ifdef WOLFSSL_CERT_REQ +WOLFSSL_API int wolfSSL_i2d_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +#endif #if !defined(NO_FILESYSTEM) WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509** x509); @@ -3389,6 +3476,10 @@ WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s #endif WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509); +#ifdef WOLFSSL_CERT_REQ +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_REQ_bio(WOLFSSL_BIO* bio, + WOLFSSL_X509** x509); +#endif #endif /* OPENSSL_EXTRA || OPENSSL_ALL */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) @@ -3412,6 +3503,9 @@ WOLFSSL_API int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX*, int); WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +#ifdef WOLFSSL_CERT_REQ +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +#endif WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_bio_X509_CRL(WOLFSSL_BIO *bp, WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u); WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX @@ -3491,6 +3585,7 @@ WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_fp(XFILE fp, int c); || defined(WOLFSSL_MYSQL_COMPATIBLE) \ || defined(WOLFSSL_HAPROXY) \ || defined(OPENSSL_EXTRA) +#define X509_BUFFER_SZ 8192 WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode); WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*); @@ -3510,12 +3605,31 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_REQ_new(void); WOLFSSL_API void wolfSSL_X509_REQ_free(WOLFSSL_X509* req); WOLFSSL_API int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey, const WOLFSSL_EVP_MD *md); +WOLFSSL_API int wolfSSL_X509_REQ_sign_ctx(WOLFSSL_X509 *req, + WOLFSSL_EVP_MD_CTX* md_ctx); WOLFSSL_API int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req, - WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext); + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext_sk); WOLFSSL_API int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, WOLFSSL_X509_NAME *name); WOLFSSL_API int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_X509_REQ_add1_attr_by_NID(WOLFSSL_X509 *req, + int nid, int type, + const unsigned char *bytes, + int len); +WOLFSSL_API int wolfSSL_X509_REQ_get_attr_by_NID(const WOLFSSL_X509 *req, + int nid, int lastpos); +WOLFSSL_API int wolfSSL_X509_REQ_add1_attr_by_txt(WOLFSSL_X509 *req, + const char *attrname, int type, + const unsigned char *bytes, int len); +WOLFSSL_API WOLFSSL_X509_ATTRIBUTE *wolfSSL_X509_REQ_get_attr( + const WOLFSSL_X509 *req, int loc); +WOLFSSL_API WOLFSSL_X509_ATTRIBUTE* wolfSSL_X509_ATTRIBUTE_new(void); +WOLFSSL_API void wolfSSL_X509_ATTRIBUTE_free(WOLFSSL_X509_ATTRIBUTE* attr); +WOLFSSL_API WOLFSSL_ASN1_TYPE *wolfSSL_X509_ATTRIBUTE_get0_type( + WOLFSSL_X509_ATTRIBUTE *attr, int idx); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_X509_to_X509_REQ(WOLFSSL_X509 *x, + WOLFSSL_EVP_PKEY *pkey, const WOLFSSL_EVP_MD *md); #endif @@ -3524,9 +3638,6 @@ WOLFSSL_API int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, #include -/* SNI received callback type */ -typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg); - WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), void *(*r) (void *, size_t, const char *, int), void (*f) (void *)); @@ -3578,8 +3689,9 @@ WOLFSSL_API void wolfSSL_sk_X509_INFO_pop_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)* void (*f) (WOLFSSL_X509_INFO*)); WOLFSSL_API void wolfSSL_sk_X509_INFO_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)*); -typedef int (*wolf_sk_compare_cb)(const void* const *a, - const void* const *b); +typedef int (*wolf_sk_compare_cb)(const void* a, + const void* b); +typedef unsigned long (*wolf_sk_hash_cb) (const void *v); WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new( wolf_sk_compare_cb); WOLFSSL_API int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)*, @@ -3599,6 +3711,18 @@ WOLFSSL_API int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJE WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int, unsigned long); +#ifndef NO_FILESYSTEM +WOLFSSL_API int wolfSSL_X509_NAME_print_ex_fp(XFILE,WOLFSSL_X509_NAME*,int, + unsigned long); +#endif + +WOLFSSL_API WOLFSSL_STACK *wolfSSL_sk_CONF_VALUE_new(wolf_sk_compare_cb compFunc); +WOLFSSL_API void wolfSSL_sk_CONF_VALUE_free(struct WOLFSSL_STACK *sk); +WOLFSSL_API int wolfSSL_sk_CONF_VALUE_num(const WOLFSSL_STACK *sk); +WOLFSSL_API WOLFSSL_CONF_VALUE *wolfSSL_sk_CONF_VALUE_value( + const struct WOLFSSL_STACK *sk, int i); +WOLFSSL_API int wolfSSL_sk_CONF_VALUE_push(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk, + WOLFSSL_CONF_VALUE* val); #endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || HAVE_LIGHTY */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) @@ -3657,12 +3781,22 @@ WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*); WOLFSSL_API VerifyCallback wolfSSL_get_verify_callback(WOLFSSL*); +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_LIGHTY */ + +#ifdef HAVE_SNI +/* SNI received callback type */ +typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg); + WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *, CallbackSniRecv); WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *, CallbackSniRecv); WOLFSSL_API int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*); +#endif + +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void*); @@ -3732,6 +3866,7 @@ WOLFSSL_API int wolfSSL_set_alpn_protos(WOLFSSL* ssl, const unsigned char* protos, unsigned int protos_len); WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line); +WOLFSSL_API void wolfSSL_OPENSSL_cleanse(void *ptr, size_t len); WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); #endif @@ -3761,11 +3896,12 @@ WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url); #endif -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) \ + || defined(WOLFSSL_WPAS_SMALL) WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx); WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, void *data); -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) @@ -3817,8 +3953,12 @@ WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 * WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject); -WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value( +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void); +WOLFSSL_API void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* sk); +WOLFSSL_API WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value( WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx); +WOLFSSL_API int wolfSSL_sk_WOLFSSL_STRING_num( + WOLF_STACK_OF(WOLFSSL_STRING)* strings); #endif /* HAVE_OCSP || OPENSSL_EXTRA || OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio, @@ -3867,8 +4007,8 @@ WOLFSSL_API int wolfSSL_X509_check_ip_asc(WOLFSSL_X509 *x, const char *ipasc, #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context( const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length); -WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count); -WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count); +WOLFSSL_API size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count); +WOLFSSL_API size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count); #endif WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len); @@ -3887,6 +4027,9 @@ WOLFSSL_API int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, con WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key); WOLFSSL_API int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key); WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a); +WOLFSSL_API WOLFSSL_ASN1_OBJECT *wolfSSL_d2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a, + const unsigned char **der, + long length); WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, WOLFSSL_ASN1_OBJECT *a); WOLFSSL_API int wolfSSL_i2d_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT *a, unsigned char **pp); WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)); @@ -3911,6 +4054,8 @@ WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t); WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, WOLFSSL_ASN1_TIME **out); WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp); +WOLFSSL_API int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1, + char *buf, int size); WOLFSSL_API int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE *store); WOLFSSL_API long wolfSSL_X509_get_version(const WOLFSSL_X509 *x); WOLFSSL_API int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509* x); diff --git a/source/libs/libwolfssl/version.h b/source/libs/libwolfssl/version.h index fe258fcc..4ed51502 100644 --- a/source/libs/libwolfssl/version.h +++ b/source/libs/libwolfssl/version.h @@ -28,8 +28,8 @@ extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "4.5.0" -#define LIBWOLFSSL_VERSION_HEX 0x04005000 +#define LIBWOLFSSL_VERSION_STRING "4.6.0" +#define LIBWOLFSSL_VERSION_HEX 0x04006000 #ifdef __cplusplus } diff --git a/source/libs/libwolfssl/wolfcrypt/aes.h b/source/libs/libwolfssl/wolfcrypt/aes.h index ca1e2786..cff740c4 100644 --- a/source/libs/libwolfssl/wolfcrypt/aes.h +++ b/source/libs/libwolfssl/wolfcrypt/aes.h @@ -79,6 +79,11 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #include #endif +#ifdef WOLFSSL_SILABS_SE_ACCEL + #include +#endif + + #if defined(HAVE_AESGCM) && !defined(WC_NO_RNG) #include #endif @@ -143,7 +148,8 @@ enum { #endif #ifdef HAVE_PKCS11 - AES_MAX_ID_LEN = 32, + AES_MAX_ID_LEN = 32, + AES_MAX_LABEL_LEN = 32, #endif }; @@ -171,6 +177,12 @@ struct Aes { #ifdef GCM_TABLE /* key-based fast multiplication table. */ ALIGN16 byte M0[256][AES_BLOCK_SIZE]; +#elif defined(GCM_TABLE_4BIT) + #if defined(BIG_ENDIAN_ORDER) || defined(WC_16BIT_CPU) + ALIGN16 byte M0[16][AES_BLOCK_SIZE]; + #else + ALIGN16 byte M0[32][AES_BLOCK_SIZE]; + #endif #endif /* GCM_TABLE */ #ifdef HAVE_CAVIUM_OCTEON_SYNC word32 y0; @@ -186,6 +198,8 @@ struct Aes { #ifdef HAVE_PKCS11 byte id[AES_MAX_ID_LEN]; int idLen; + char label[AES_MAX_LABEL_LEN]; + int labelLen; #endif #ifdef WOLFSSL_ASYNC_CRYPT WC_ASYNC_DEV asyncDev; @@ -231,6 +245,9 @@ struct Aes { #endif #if defined(WOLFSSL_IMXRT_DCP) dcp_handle_t handle; +#endif +#if defined(WOLFSSL_SILABS_SE_ACCEL) + silabs_aes_t ctx; #endif void* heap; /* memory hint to use */ }; @@ -431,6 +448,8 @@ WOLFSSL_API int wc_AesInit(Aes* aes, void* heap, int devId); #ifdef HAVE_PKCS11 WOLFSSL_API int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, int devId); +WOLFSSL_API int wc_AesInit_Label(Aes* aes, const char* label, void* heap, + int devId); #endif WOLFSSL_API void wc_AesFree(Aes* aes); diff --git a/source/libs/libwolfssl/wolfcrypt/asn.h b/source/libs/libwolfssl/wolfcrypt/asn.h index 883a5ee7..ea3e60ce 100644 --- a/source/libs/libwolfssl/wolfcrypt/asn.h +++ b/source/libs/libwolfssl/wolfcrypt/asn.h @@ -100,6 +100,7 @@ enum ASN_Tags { ASN_SEQUENCE = 0x10, ASN_SET = 0x11, ASN_PRINTABLE_STRING = 0x13, + ASN_IA5_STRING = 0x16, ASN_UTC_TIME = 0x17, ASN_OTHER_TYPE = 0x00, ASN_RFC822_TYPE = 0x01, @@ -142,6 +143,9 @@ enum DN_Tags { ASN_DOMAIN_COMPONENT = 0x19 /* DC */ }; +/* This is the size of the smallest possible PEM header and footer */ +extern const int pem_struct_min_sz; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) typedef struct WOLFSSL_ObjectInfo { int nid; @@ -202,6 +206,7 @@ enum NID_sha256 = 672, NID_sha384 = 673, NID_sha512 = 674, + NID_pkcs9_challengePassword = 54, NID_hw_name_oid = 73, NID_id_pkix_OCSP_basic = 74, NID_any_policy = 75, @@ -228,6 +233,7 @@ enum NID_inhibit_any_policy = 168, /* 2.5.29.54 */ NID_tlsfeature = 1020, /* id-pe 24 */ NID_commonName = 0x03, /* matches ASN_COMMON_NAME in asn.h */ + NID_buildingName = 1494, NID_surname = 0x04, /* SN */ @@ -300,7 +306,7 @@ enum Misc_ASN { #endif RSA_INTS = 8, /* RSA ints in private key */ DSA_INTS = 5, /* DSA ints in private key */ - MIN_DATE_SIZE = 13, + MIN_DATE_SIZE = 12, MAX_DATE_SIZE = 32, ASN_GEN_TIME_SZ = 15, /* 7 numbers * 2 + Zulu tag */ #ifndef NO_RSA @@ -382,6 +388,9 @@ enum Misc_ASN { MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ MAX_X509_VERSION = 3, /* Max X509 version allowed */ MIN_X509_VERSION = 0, /* Min X509 version allowed */ + WOLFSSL_X509_V1 = 0, + WOLFSSL_X509_V2 = 1, + WOLFSSL_X509_V3 = 2, #if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) @@ -422,6 +431,7 @@ enum Oid_Types { oidCertNameType = 17, oidTlsExtType = 18, oidCrlExtType = 19, + oidCsrAttrType = 20, oidIgnoreType }; @@ -588,6 +598,14 @@ enum KeyIdType { }; #endif +#ifdef WOLFSSL_CERT_REQ +enum CsrAttrType { + CHALLENGE_PASSWORD_OID = 659, + SERIAL_NUMBER_OID = 94, + EXTENSION_REQUEST_OID = 666, +}; +#endif + /* Key usage extension bits (based on RFC 5280) */ #define KEYUSE_DIGITAL_SIG 0x0080 #define KEYUSE_CONTENT_COMMIT 0x0040 @@ -660,7 +678,9 @@ struct SignatureCtx { byte* digest; #ifndef NO_RSA byte* out; - byte* plain; +#endif +#if !(defined(NO_RSA) && defined(NO_DSA)) + byte* sigCpy; #endif #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) int verify; @@ -669,6 +689,9 @@ struct SignatureCtx { #ifndef NO_RSA struct RsaKey* rsa; #endif + #ifndef NO_DSA + struct DsaKey* dsa; + #endif #ifdef HAVE_ECC struct ecc_key* ecc; #endif @@ -766,6 +789,7 @@ struct DecodedCert { DNS_entry* altNames; /* alt names list of dns entries */ #ifndef IGNORE_NAME_CONSTRAINTS DNS_entry* altEmailNames; /* alt names list of RFC822 entries */ + DNS_entry* altDirNames; /* alt names list of DIR entries */ Base_entry* permittedNames; /* Permitted name bases */ Base_entry* excludedNames; /* Excluded name bases */ #endif /* IGNORE_NAME_CONSTRAINTS */ @@ -888,6 +912,14 @@ struct DecodedCert { int extCertPoliciesNb; #endif /* defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) */ +#ifdef WOLFSSL_CERT_REQ + /* CSR attributes */ + char* cPwd; /* challengePassword */ + int cPwdLen; + char* sNum; /* Serial Number */ + int sNumLen; +#endif /* WOLFSSL_CERT_REQ */ + Signer* ca; #ifndef NO_CERTS SignatureCtx sigCtx; @@ -939,7 +971,9 @@ struct DecodedCert { #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) byte extCertPolicyCrit : 1; #endif - +#ifdef WOLFSSL_CERT_REQ + byte isCSR : 1; /* Do we intend on parsing a CSR? */ +#endif }; @@ -1036,6 +1070,12 @@ WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz, WOLFSSL_API int CheckCertSignature(const byte*,word32,void*,void* cm); WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); +#ifdef WOLFSSL_CERT_REQ +WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, void* heap, + const byte* pubKey, word32 pubKeySz, int pubKeyOID); +#endif /* WOLFSSL_CERT_REQ */ +WOLFSSL_LOCAL int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, + int sigAlgoType); WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm); WOLFSSL_LOCAL int DecodeToKey(DecodedCert*, int verify); WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate); @@ -1108,6 +1148,8 @@ WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len, word32 maxIdx, int check); WOLFSSL_LOCAL int GetOctetString(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); +WOLFSSL_LOCAL int CheckBitString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int zeroBits, byte* unusedBits); WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); WOLFSSL_LOCAL int GetSet_ex(const byte* input, word32* inOutIdx, int* len, @@ -1142,6 +1184,7 @@ WOLFSSL_LOCAL int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz); WOLFSSL_LOCAL int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz); WOLFSSL_LOCAL int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); #endif +WOLFSSL_LOCAL int SetASNInt(int len, byte firstByte, byte* output); WOLFSSL_LOCAL word32 SetBitString(word32 len, byte unusedBits, byte* output); WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output); WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output); @@ -1154,7 +1197,9 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, byte* serial, int* serialSz, word32 maxIdx); WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx); -WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der); +WOLFSSL_LOCAL int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der); +WOLFSSL_LOCAL int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, + const byte* pubKey, word32 pubKeySz, enum Key_Sum ks); WOLFSSL_LOCAL int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g); WOLFSSL_LOCAL int FlattenAltNames( byte*, word32, const DNS_entry*); @@ -1162,8 +1207,12 @@ WOLFSSL_LOCAL int FlattenAltNames( byte*, word32, const DNS_entry*); /* ASN sig helpers */ WOLFSSL_LOCAL int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s); + WOLFSSL_LOCAL int StoreECC_DSA_Sig_Bin(byte* out, word32* outLen, + const byte* r, word32 rLen, const byte* s, word32 sLen); WOLFSSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s); + WOLFSSL_LOCAL int DecodeECC_DSA_Sig_Bin(const byte* sig, word32 sigLen, + byte* r, word32* rLen, byte* s, word32* sLen); #endif #if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) WOLFSSL_API int EccEnumToNID(int n); @@ -1200,7 +1249,8 @@ enum cert_enums { NTRU_KEY = 11, ECC_KEY = 12, ED25519_KEY = 13, - ED448_KEY = 14 + ED448_KEY = 14, + DSA_KEY = 15 }; #endif /* WOLFSSL_CERT_GEN */ @@ -1251,6 +1301,9 @@ struct CertStatus { byte serial[EXTERNAL_SERIAL_SIZE]; int serialSz; +#ifdef OPENSSL_EXTRA + WOLFSSL_ASN1_INTEGER* serialInt; +#endif int status; @@ -1258,7 +1311,7 @@ struct CertStatus { byte nextDate[MAX_DATE_SIZE]; byte thisDateFormat; byte nextDateFormat; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) WOLFSSL_ASN1_TIME thisDateParsed; WOLFSSL_ASN1_TIME nextDateParsed; byte* thisDateAsn; @@ -1269,7 +1322,34 @@ struct CertStatus { word32 rawOcspResponseSz; }; +typedef struct OcspEntry OcspEntry; +#ifdef NO_SHA +#define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#else +#define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE +#endif + +struct OcspEntry +{ + OcspEntry *next; /* next entry */ + word32 hashAlgoOID; /* hash algo ID */ + byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ + byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ + CertStatus *status; /* OCSP response list */ + int totalStatus; /* number on list */ + byte* rawCertId; /* raw bytes of the CertID */ + int rawCertIdSize; /* num bytes in raw CertID */ + /* option bits - using 32-bit for alignment */ + word32 isDynamic:1; /* was dynamically allocated */ + +}; + +/* TODO: Long-term, it would be helpful if we made this struct and other OCSP + structs conform to the ASN spec as described in RFC 6960. It will help + with readability and with implementing OpenSSL compatibility API + functions, because OpenSSL's OCSP data structures conform to the + RFC. */ struct OcspResponse { int responseStatus; /* return code from Responder */ @@ -1279,8 +1359,6 @@ struct OcspResponse { byte producedDate[MAX_DATE_SIZE]; /* Date at which this response was signed */ byte producedDateFormat; /* format of the producedDate */ - byte* issuerHash; - byte* issuerKeyHash; byte* cert; word32 certSz; @@ -1289,7 +1367,7 @@ struct OcspResponse { word32 sigSz; /* Length in octets for the sig */ word32 sigOID; /* OID for hash used for sig */ - CertStatus* status; /* certificate status to fill out */ + OcspEntry* single; /* chain of OCSP single responses */ byte* nonce; /* pointer to nonce inside ASN.1 response */ int nonceSz; /* length of the nonce string */ @@ -1300,6 +1378,7 @@ struct OcspResponse { #ifdef OPENSSL_EXTRA int verifyError; #endif + void* heap; }; @@ -1320,25 +1399,9 @@ struct OcspRequest { void* ssl; }; -typedef struct OcspEntry OcspEntry; - -#ifdef NO_SHA -#define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE -#else -#define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE -#endif - -struct OcspEntry -{ - OcspEntry *next; /* next entry */ - byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ - byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ - CertStatus *status; /* OCSP response list */ - int totalStatus; /* number on list */ -}; - -WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); -WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); +WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, OcspEntry*, CertStatus*, byte*, word32, void*); +WOLFSSL_LOCAL void FreeOcspResponse(OcspResponse*); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*); WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); @@ -1416,12 +1479,13 @@ WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*); #endif enum PBESTypes { - PBE_MD5_DES = 0, - PBE_SHA1_RC4_128 = 1, - PBE_SHA1_DES = 2, - PBE_SHA1_DES3 = 3, - PBE_AES256_CBC = 4, - PBE_AES128_CBC = 5, + PBE_MD5_DES = 0, + PBE_SHA1_RC4_128 = 1, + PBE_SHA1_DES = 2, + PBE_SHA1_DES3 = 3, + PBE_AES256_CBC = 4, + PBE_AES128_CBC = 5, + PBE_SHA1_40RC2_CBC = 6, PBE_SHA1_RC4_128_SUM = 657, PBE_SHA1_DES3_SUM = 659, diff --git a/source/libs/libwolfssl/wolfcrypt/asn_public.h b/source/libs/libwolfssl/wolfcrypt/asn_public.h index c1ae0102..8b8bd414 100644 --- a/source/libs/libwolfssl/wolfcrypt/asn_public.h +++ b/source/libs/libwolfssl/wolfcrypt/asn_public.h @@ -126,6 +126,7 @@ enum CertType { /* Signature type, by OID sum */ enum Ctc_SigType { CTC_SHAwDSA = 517, + CTC_SHA256wDSA = 416, CTC_MD2wRSA = 646, CTC_MD5wRSA = 648, CTC_SHAwRSA = 649, diff --git a/source/libs/libwolfssl/wolfcrypt/chacha.h b/source/libs/libwolfssl/wolfcrypt/chacha.h index 9d7ccf92..49dc1e6d 100644 --- a/source/libs/libwolfssl/wolfcrypt/chacha.h +++ b/source/libs/libwolfssl/wolfcrypt/chacha.h @@ -55,6 +55,9 @@ Block counter is located at index 12. /* Size of IV in bytes*/ #define CHACHA_IV_BYTES 12 +#ifdef HAVE_XCHACHA +#define XCHACHA_NONCE_BYTES 24 +#endif /* Size of ChaCha chunks */ #define CHACHA_CHUNK_WORDS 16 @@ -92,8 +95,17 @@ WOLFSSL_API int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter); WOLFSSL_API int wc_Chacha_Process(ChaCha* ctx, byte* cipher, const byte* plain, word32 msglen); + +WOLFSSL_LOCAL void wc_Chacha_purge_current_block(ChaCha* ctx); + WOLFSSL_API int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz); +#ifdef HAVE_XCHACHA +WOLFSSL_API int wc_XChacha_SetKey(ChaCha *ctx, const byte *key, word32 keySz, + const byte *nonce, word32 nonceSz, + word32 counter); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/source/libs/libwolfssl/wolfcrypt/chacha20_poly1305.h b/source/libs/libwolfssl/wolfcrypt/chacha20_poly1305.h index 739f39f1..be1a0aad 100644 --- a/source/libs/libwolfssl/wolfcrypt/chacha20_poly1305.h +++ b/source/libs/libwolfssl/wolfcrypt/chacha20_poly1305.h @@ -48,6 +48,7 @@ or Authenticated Encryption with Additional Data (AEAD) algorithm. #define CHACHA20_POLY1305_AEAD_IV_SIZE 12 #define CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE 16 #define CHACHA20_POLY1305_MAX 4294967295U +#define XCHACHA20_POLY1305_AEAD_NONCE_SIZE 24 enum { CHACHA20_POLY_1305_ENC_TYPE = 8, /* cipher unique type */ @@ -123,6 +124,30 @@ WOLFSSL_API int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, WOLFSSL_API int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); +#ifdef HAVE_XCHACHA + +WOLFSSL_API int wc_XChaCha20Poly1305_Init( + ChaChaPoly_Aead* aead, + const byte *ad, word32 ad_len, + const byte *inKey, word32 inKeySz, + const byte *inIV, word32 inIVSz, + int isEncrypt); + +WOLFSSL_API int wc_XChaCha20Poly1305_Encrypt( + byte *dst, const size_t dst_space, + const byte *src, const size_t src_len, + const byte *ad, const size_t ad_len, + const byte *nonce, const size_t nonce_len, + const byte *key, const size_t key_len); + +WOLFSSL_API int wc_XChaCha20Poly1305_Decrypt( + byte *dst, const size_t dst_space, + const byte *src, const size_t src_len, + const byte *ad, const size_t ad_len, + const byte *nonce, const size_t nonce_len, + const byte *key, const size_t key_len); + +#endif /* HAVE_XCHACHA */ #ifdef __cplusplus } /* extern "C" */ diff --git a/source/libs/libwolfssl/wolfcrypt/compress.h b/source/libs/libwolfssl/wolfcrypt/compress.h index 4bfb7615..8a3760f1 100644 --- a/source/libs/libwolfssl/wolfcrypt/compress.h +++ b/source/libs/libwolfssl/wolfcrypt/compress.h @@ -47,6 +47,8 @@ WOLFSSL_API int wc_Compress_ex(byte* out, word32 outSz, const byte* in, WOLFSSL_API int wc_DeCompress(byte*, word32, const byte*, word32); WOLFSSL_API int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in, word32 inSz, int windowBits); +WOLFSSL_API int wc_DeCompressDynamic(byte** out, int max, int memoryType, + const byte* in, word32 inSz, int windowBits, void* heap); #ifdef __cplusplus } /* extern "C" */ diff --git a/source/libs/libwolfssl/wolfcrypt/cpuid.h b/source/libs/libwolfssl/wolfcrypt/cpuid.h index feade120..557c4207 100644 --- a/source/libs/libwolfssl/wolfcrypt/cpuid.h +++ b/source/libs/libwolfssl/wolfcrypt/cpuid.h @@ -34,6 +34,7 @@ #if defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \ defined(WOLFSSL_AESNI) + #define CPUID_AVX1 0x0001 #define CPUID_AVX2 0x0002 #define CPUID_RDRAND 0x0004 @@ -59,6 +60,7 @@ WOLFSSL_API void cpuid_select_flags(word32 flags); WOLFSSL_API void cpuid_set_flag(word32 flag); WOLFSSL_API void cpuid_clear_flag(word32 flag); + #endif #ifdef __cplusplus diff --git a/source/libs/libwolfssl/wolfcrypt/cryptocb.h b/source/libs/libwolfssl/wolfcrypt/cryptocb.h index 9d8c5480..18ca880b 100644 --- a/source/libs/libwolfssl/wolfcrypt/cryptocb.h +++ b/source/libs/libwolfssl/wolfcrypt/cryptocb.h @@ -85,6 +85,11 @@ typedef struct wc_CryptoInfo { WC_RNG* rng; } rsakg; #endif + struct { + RsaKey* key; + const byte* pubKey; + word32 pubKeySz; + } rsa_check; #endif #ifdef HAVE_ECC struct { @@ -115,6 +120,11 @@ typedef struct wc_CryptoInfo { int* res; ecc_key* key; } eccverify; + struct { + ecc_key* key; + const byte* pubKey; + word32 pubKeySz; + } ecc_check; #endif }; } pk; @@ -212,7 +222,7 @@ typedef struct wc_CryptoInfo { typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx); WOLFSSL_LOCAL void wc_CryptoCb_Init(void); - +WOLFSSL_LOCAL int wc_CryptoCb_GetDevIdAtIndex(int startIdx); WOLFSSL_API int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); WOLFSSL_API void wc_CryptoCb_UnRegisterDevice(int devId); @@ -229,6 +239,9 @@ WOLFSSL_LOCAL int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, WOLFSSL_LOCAL int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); #endif /* WOLFSSL_KEY_GEN */ + +WOLFSSL_LOCAL int wc_CryptoCb_RsaCheckPrivKey(RsaKey* key, const byte* pubKey, + word32 pubKeySz); #endif /* !NO_RSA */ #ifdef HAVE_ECC @@ -243,6 +256,9 @@ WOLFSSL_LOCAL int wc_CryptoCb_EccSign(const byte* in, word32 inlen, byte* out, WOLFSSL_LOCAL int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, const byte* hash, word32 hashlen, int* res, ecc_key* key); + +WOLFSSL_LOCAL int wc_CryptoCb_EccCheckPrivKey(ecc_key* key, const byte* pubKey, + word32 pubKeySz); #endif /* HAVE_ECC */ #ifndef NO_AES diff --git a/source/libs/libwolfssl/wolfcrypt/dh.h b/source/libs/libwolfssl/wolfcrypt/dh.h index 51921841..7229e55a 100644 --- a/source/libs/libwolfssl/wolfcrypt/dh.h +++ b/source/libs/libwolfssl/wolfcrypt/dh.h @@ -121,8 +121,8 @@ WOLFSSL_API int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, const byte* pub, word32 pubSz); WOLFSSL_API int wc_DhExportKeyPair(DhKey* key, byte* priv, word32* pPrivSz, byte* pub, word32* pPubSz); -#endif /* WOLFSSL_DH_EXTRA */ - +WOLFSSL_LOCAL int wc_DhKeyCopy(DhKey* src, DhKey* dst); +#endif WOLFSSL_API int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz, const byte* q, word32 qSz, int trusted, WC_RNG* rng); diff --git a/source/libs/libwolfssl/wolfcrypt/ecc.h b/source/libs/libwolfssl/wolfcrypt/ecc.h index 9ce50309..efd7233a 100644 --- a/source/libs/libwolfssl/wolfcrypt/ecc.h +++ b/source/libs/libwolfssl/wolfcrypt/ecc.h @@ -58,6 +58,10 @@ #include #endif +#ifdef WOLFSSL_SILABS_SE_ACCEL + #include +#endif + #ifdef WOLFSSL_HAVE_SP_ECC #include #endif @@ -125,7 +129,7 @@ enum { ECC_MAXNAME = 16, /* MAX CURVE NAME LENGTH */ SIG_HEADER_SZ = 7, /* ECC signature header size (30 81 87 02 42 [R] 02 42 [S]) */ ECC_BUFSIZE = 256, /* for exported keys temp buffer */ - ECC_MINSIZE = 20, /* MIN Private Key size */ + ECC_MINSIZE = ECC_MIN_KEY_SZ/8, /* MIN Private Key size */ ECC_MAXSIZE = 66, /* MAX Private Key size */ ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ ECC_MAX_OID_LEN = 16, @@ -137,6 +141,8 @@ enum { ECC_MAX_CRYPTO_HW_PUBKEY_SIZE = (ATECC_KEY_SIZE*2), #elif defined(PLUTON_CRYPTO_ECC) ECC_MAX_CRYPTO_HW_SIZE = 32, +#elif defined(WOLFSSL_SILABS_SE_ACCEL) + ECC_MAX_CRYPTO_HW_SIZE = 32, #elif defined(WOLFSSL_CRYPTOCELL) #ifndef CRYPTOCELL_KEY_SIZE CRYPTOCELL_KEY_SIZE = ECC_MAXSIZE, @@ -152,8 +158,9 @@ enum { /* Shamir's dual add constants */ SHAMIR_PRECOMP_SZ = 16, -#ifdef HAVE_PKCS11 +#ifdef WOLF_CRYPTO_CB ECC_MAX_ID_LEN = 32, + ECC_MAX_LABEL_LEN = 32, #endif }; @@ -315,7 +322,8 @@ typedef struct ecc_set_type { #endif /* determine buffer size */ -#define FP_SIZE_ECC (FP_MAX_BITS_ECC/DIGIT_BIT) +/* Add one to accommodate extra digit used by sp_mul(), sp_mulmod(), sp_sqr(), and sp_sqrmod(). */ +#define FP_SIZE_ECC ((FP_MAX_BITS_ECC/DIGIT_BIT) + 1) /* This needs to match the size of the fp_int struct, except the @@ -395,6 +403,16 @@ struct ecc_key { #if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB) int devId; #endif +#ifdef WOLFSSL_SILABS_SE_ACCEL + sl_se_command_context_t cmd_ctx; + sl_se_key_descriptor_t key; + /* Used for SiLabs "plaintext" with public X, public Y, and + * private D concatenated. These are respectively at offset `0`, + * offset `keysize`, and offset `2 * keysize`. + */ + byte key_raw[3 * ECC_MAX_CRYPTO_HW_SIZE]; +#endif + #ifdef WOLFSSL_ASYNC_CRYPT mp_int* r; /* sign/verify temps */ mp_int* s; @@ -407,9 +425,11 @@ struct ecc_key { CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ #endif #endif /* WOLFSSL_ASYNC_CRYPT */ -#ifdef HAVE_PKCS11 +#ifdef WOLF_CRYPTO_CB byte id[ECC_MAX_ID_LEN]; int idLen; + char label[ECC_MAX_LABEL_LEN]; + int labelLen; #endif #if defined(WOLFSSL_CRYPTOCELL) ecc_context_t ctx; @@ -474,6 +494,9 @@ ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, WOLFSSL_LOCAL int ecc_projective_add_point_safe(ecc_point* A, ecc_point* B, ecc_point* R, mp_int* a, mp_int* modulus, mp_digit mp, int* infinity); +WOLFSSL_LOCAL +int ecc_projective_dbl_point_safe(ecc_point* P, ecc_point* R, mp_int* a, + mp_int* modulus, mp_digit mp); #endif @@ -541,10 +564,12 @@ WOLFSSL_API int wc_ecc_init(ecc_key* key); WOLFSSL_ABI WOLFSSL_API int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); -#ifdef HAVE_PKCS11 +#ifdef WOLF_CRYPTO_CB WOLFSSL_API int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap, int devId); +WOLFSSL_API +int wc_ecc_init_label(ecc_key* key, const char* label, void* heap, int devId); #endif #ifdef WOLFSSL_CUSTOM_CURVES WOLFSSL_LOCAL diff --git a/source/libs/libwolfssl/wolfcrypt/fe_448.h b/source/libs/libwolfssl/wolfcrypt/fe_448.h index 0d85de45..0f8fd5d1 100644 --- a/source/libs/libwolfssl/wolfcrypt/fe_448.h +++ b/source/libs/libwolfssl/wolfcrypt/fe_448.h @@ -46,12 +46,15 @@ #if defined(CURVED448_128BIT) typedef int64_t fe448; - #ifdef __SIZEOF_INT128__ - typedef __uint128_t uint128_t; - typedef __int128_t int128_t; - #else - typedef unsigned long uint128_t __attribute__ ((mode(TI))); - typedef long int128_t __attribute__ ((mode(TI))); + #ifndef WOLFSSL_UINT128_T_DEFINED + #ifdef __SIZEOF_INT128__ + typedef __uint128_t uint128_t; + typedef __int128_t int128_t; + #else + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #endif + #define WOLFSSL_UINT128_T_DEFINED #endif #else typedef int32_t fe448; diff --git a/source/libs/libwolfssl/wolfcrypt/hmac.h b/source/libs/libwolfssl/wolfcrypt/hmac.h index 2b534838..aba80632 100644 --- a/source/libs/libwolfssl/wolfcrypt/hmac.h +++ b/source/libs/libwolfssl/wolfcrypt/hmac.h @@ -94,7 +94,8 @@ enum { WC_SHA3_512 = WC_HASH_TYPE_SHA3_512, #endif #ifdef HAVE_PKCS11 - HMAC_MAX_ID_LEN = 32, + HMAC_MAX_ID_LEN = 32, + HMAC_MAX_LABEL_LEN = 32, #endif }; @@ -153,6 +154,8 @@ struct Hmac { #ifdef HAVE_PKCS11 byte id[HMAC_MAX_ID_LEN]; int idLen; + char label[HMAC_MAX_LABEL_LEN]; + int labelLen; #endif #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) word16 keyLen; /* hmac key length (key in ipad) */ @@ -174,8 +177,12 @@ WOLFSSL_API int wc_HmacFinal(Hmac*, byte*); WOLFSSL_API int wc_HmacSizeByType(int type); WOLFSSL_API int wc_HmacInit(Hmac* hmac, void* heap, int devId); +#ifdef HAVE_PKCS11 WOLFSSL_API int wc_HmacInit_Id(Hmac* hmac, byte* id, int len, void* heap, int devId); +WOLFSSL_API int wc_HmacInit_Label(Hmac* hmac, const char* label, void* heap, + int devId); +#endif WOLFSSL_API void wc_HmacFree(Hmac*); WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); diff --git a/source/libs/libwolfssl/wolfcrypt/integer.h b/source/libs/libwolfssl/wolfcrypt/integer.h index dbe2dc93..8495a8b4 100644 --- a/source/libs/libwolfssl/wolfcrypt/integer.h +++ b/source/libs/libwolfssl/wolfcrypt/integer.h @@ -33,7 +33,7 @@ may not be faster on all */ #include /* will set MP_xxBIT if not default */ -#ifdef WOLFSSL_SP_MATH +#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) #include #elif defined(USE_FAST_MATH) #include @@ -161,7 +161,7 @@ extern "C" { #define MP_OKAY 0 /* ok result */ #define MP_MEM -2 /* out of mem */ #define MP_VAL -3 /* invalid input */ -#define MP_NOT_INF -4 /* point not at infinity */ +#define MP_NOT_INF -4 /* point not at infinity */ #define MP_RANGE MP_NOT_INF #define MP_YES 1 /* yes response */ diff --git a/source/libs/libwolfssl/wolfcrypt/logging.h b/source/libs/libwolfssl/wolfcrypt/logging.h index c9be0e4d..093fa521 100644 --- a/source/libs/libwolfssl/wolfcrypt/logging.h +++ b/source/libs/libwolfssl/wolfcrypt/logging.h @@ -100,6 +100,10 @@ WOLFSSL_API int wolfSSL_Debugging_ON(void); /* turn logging off */ WOLFSSL_API void wolfSSL_Debugging_OFF(void); +#ifdef HAVE_WC_INTROSPECTION + WOLFSSL_API const char *wolfSSL_configure_args(void); + WOLFSSL_API const char *wolfSSL_global_cflags(void); +#endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) WOLFSSL_LOCAL int wc_LoggingInit(void); @@ -187,6 +191,14 @@ WOLFSSL_API void wolfSSL_Debugging_OFF(void); #define WOLFSSL_ERROR_MSG(m) #endif +#ifdef HAVE_STACK_SIZE_VERBOSE + extern WOLFSSL_API THREAD_LS_T unsigned char *StackSizeCheck_myStack; + extern WOLFSSL_API THREAD_LS_T size_t StackSizeCheck_stackSize; + extern WOLFSSL_API THREAD_LS_T size_t StackSizeCheck_stackSizeHWM; + extern WOLFSSL_API THREAD_LS_T size_t *StackSizeCheck_stackSizeHWM_ptr; + extern WOLFSSL_API THREAD_LS_T void *StackSizeCheck_stackOffsetPointer; +#endif + #ifdef __cplusplus } #endif diff --git a/source/libs/libwolfssl/wolfcrypt/mem_track.h b/source/libs/libwolfssl/wolfcrypt/mem_track.h index d33e90e6..1d5ade9d 100644 --- a/source/libs/libwolfssl/wolfcrypt/mem_track.h +++ b/source/libs/libwolfssl/wolfcrypt/mem_track.h @@ -76,6 +76,15 @@ long totalBytes; /* total number of bytes allocated */ long peakBytes; /* concurrent max bytes */ long currentBytes; /* total current bytes in use */ +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + long peakAllocsTripOdometer; /* peak number of concurrent allocations, + * subject to reset by + * wolfCrypt_heap_peak_checkpoint() + */ + long peakBytesTripOdometer; /* peak concurrent bytes, subject to reset + * by wolfCrypt_heap_peak_checkpoint() + */ +#endif } memoryStats; typedef struct memHint { @@ -170,8 +179,17 @@ ourMemStats.totalAllocs++; ourMemStats.totalBytes += sz; ourMemStats.currentBytes += sz; - if (ourMemStats.currentBytes > ourMemStats.peakBytes) - ourMemStats.peakBytes = ourMemStats.currentBytes; + #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + if (ourMemStats.peakAllocsTripOdometer < ourMemStats.totalAllocs - ourMemStats.totalDeallocs) + ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - ourMemStats.totalDeallocs; + if (ourMemStats.peakBytesTripOdometer < ourMemStats.currentBytes) { + ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; + #endif + if (ourMemStats.currentBytes > ourMemStats.peakBytes) + ourMemStats.peakBytes = ourMemStats.currentBytes; + #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + } + #endif #endif #ifdef DO_MEM_LIST if (pthread_mutex_lock(&memLock) == 0) { @@ -338,8 +356,12 @@ ourMemStats.totalBytes = 0; ourMemStats.peakBytes = 0; ourMemStats.currentBytes = 0; +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + ourMemStats.peakAllocsTripOdometer = 0; + ourMemStats.peakBytesTripOdometer = 0; +#endif #endif - + #ifdef DO_MEM_LIST XMEMSET(&ourMemList, 0, sizeof(ourMemList)); diff --git a/source/libs/libwolfssl/wolfcrypt/misc.h b/source/libs/libwolfssl/wolfcrypt/misc.h index c7e6d954..632a2abe 100644 --- a/source/libs/libwolfssl/wolfcrypt/misc.h +++ b/source/libs/libwolfssl/wolfcrypt/misc.h @@ -43,11 +43,23 @@ word32 rotlFixed(word32, word32); WOLFSSL_LOCAL word32 rotrFixed(word32, word32); +#ifdef WC_RC2 +WOLFSSL_LOCAL +word16 rotlFixed16(word16, word16); +WOLFSSL_LOCAL +word16 rotrFixed16(word16, word16); +#endif + WOLFSSL_LOCAL word32 ByteReverseWord32(word32); WOLFSSL_LOCAL void ByteReverseWords(word32*, const word32*, word32); +WOLFSSL_LOCAL +void XorWordsOut(wolfssl_word* r, const wolfssl_word* a, const wolfssl_word* b, + word32 n); +WOLFSSL_LOCAL +void xorbufout(void*, const void*, const void*, word32); WOLFSSL_LOCAL void XorWords(wolfssl_word*, const wolfssl_word*, word32); WOLFSSL_LOCAL @@ -103,7 +115,9 @@ WOLFSSL_LOCAL byte ctMaskLT(int a, int b); WOLFSSL_LOCAL byte ctMaskLTE(int a, int b); WOLFSSL_LOCAL byte ctMaskEq(int a, int b); WOLFSSL_LOCAL word16 ctMask16GT(int a, int b); +WOLFSSL_LOCAL word16 ctMask16GTE(int a, int b); WOLFSSL_LOCAL word16 ctMask16LT(int a, int b); +WOLFSSL_LOCAL word16 ctMask16LTE(int a, int b); WOLFSSL_LOCAL word16 ctMask16Eq(int a, int b); WOLFSSL_LOCAL byte ctMaskNotEq(int a, int b); WOLFSSL_LOCAL byte ctMaskSel(byte m, byte a, byte b); diff --git a/source/libs/libwolfssl/wolfcrypt/pkcs12.h b/source/libs/libwolfssl/wolfcrypt/pkcs12.h index fe867796..36aadfd4 100644 --- a/source/libs/libwolfssl/wolfcrypt/pkcs12.h +++ b/source/libs/libwolfssl/wolfcrypt/pkcs12.h @@ -53,6 +53,8 @@ WOLFSSL_API int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz); WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, byte** pkey, word32* pkeySz, byte** cert, word32* certSz, WC_DerCertList** ca); +WOLFSSL_LOCAL int wc_PKCS12_verify_ex(WC_PKCS12* pkcs12, + const byte* psw, word32 pswSz); WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca, int nidKey, int nidCert, int iter, int macIter, diff --git a/source/libs/libwolfssl/wolfcrypt/pkcs7.h b/source/libs/libwolfssl/wolfcrypt/pkcs7.h index 59bcb3ae..a2698e29 100644 --- a/source/libs/libwolfssl/wolfcrypt/pkcs7.h +++ b/source/libs/libwolfssl/wolfcrypt/pkcs7.h @@ -48,8 +48,12 @@ /* Max number of certificates that PKCS7 structure can parse */ #ifndef MAX_PKCS7_CERTS +#ifdef OPENSSL_ALL + #define MAX_PKCS7_CERTS 15 +#else #define MAX_PKCS7_CERTS 4 #endif +#endif #ifndef MAX_ORI_TYPE_SZ #define MAX_ORI_TYPE_SZ MAX_OID_SZ @@ -154,8 +158,8 @@ enum Pkcs7_Misc { MAX_SEQ_SZ + ASN_NAME_MAX + MAX_SN_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ + 1 + MAX_ENCRYPTED_KEY_SZ, #if (defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION >= 2)) || (defined(HAVE_SELFTEST) && \ - (!defined(HAVE_SELFTEST_VERSION) || HAVE_SELFTEST_VERSION < 2)) + (HAVE_FIPS_VERSION <= 2)) || (defined(HAVE_SELFTEST) && \ + (!defined(HAVE_SELFTEST_VERSION) || (HAVE_SELFTEST_VERSION < 2))) /* In the event of fips cert 3389 or CAVP selftest v1 build, these enums are * not in aes.h for use with pkcs7 so enumerate it here outside the fips * boundary */ diff --git a/source/libs/libwolfssl/wolfcrypt/poly1305.h b/source/libs/libwolfssl/wolfcrypt/poly1305.h index 88c1fbd7..9683eb7b 100644 --- a/source/libs/libwolfssl/wolfcrypt/poly1305.h +++ b/source/libs/libwolfssl/wolfcrypt/poly1305.h @@ -116,6 +116,9 @@ WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag); /* AEAD Functions */ WOLFSSL_API int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad); WOLFSSL_API int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz); +#ifdef WORD64_AVAILABLE +WOLFSSL_API int wc_Poly1305_EncodeSizes64(Poly1305* ctx, word64 aadSz, word64 dataSz); +#endif WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, byte* input, word32 sz, byte* tag, word32 tagSz); diff --git a/source/libs/libwolfssl/wolfcrypt/port/atmel/atmel.h b/source/libs/libwolfssl/wolfcrypt/port/atmel/atmel.h index 6122f8f5..be1310dc 100644 --- a/source/libs/libwolfssl/wolfcrypt/port/atmel/atmel.h +++ b/source/libs/libwolfssl/wolfcrypt/port/atmel/atmel.h @@ -29,10 +29,8 @@ #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) || \ defined(WOLFSSL_ATECC_PKCB) - #undef SHA_BLOCK_SIZE - #define SHA_BLOCK_SIZE SHA_BLOCK_SIZE_REMAP - #include #undef SHA_BLOCK_SIZE + #include #endif /* ATECC508A/608A only supports ECC P-256 */ diff --git a/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_aes.h b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_aes.h new file mode 100644 index 00000000..1d16634c --- /dev/null +++ b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_aes.h @@ -0,0 +1,67 @@ +/* silabs_aes.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; 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. + * + * wolfSSL is distributed in the hope that it will be useful, + * but 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _SILABS_AES_H_ +#define _SILABS_AES_H_ + +#include + +#if defined(WOLFSSL_SILABS_SE_ACCEL) + +#include + +#include +#include + +typedef struct { + sl_se_command_context_t cmd_ctx; + sl_se_key_descriptor_t key; +} silabs_aes_t; + +typedef struct Aes Aes; + +#ifdef HAVE_AESGCM +int wc_AesGcmEncrypt_silabs (Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +int wc_AesGcmDecrypt_silabs (Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +#endif /* HAVE_AESGCM */ + +#ifdef HAVE_AESCCM +int wc_AesCcmEncrypt_silabs (Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +int wc_AesCcmDecrypt_silabs (Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +#endif /* HAVE_AESCCM */ + +#endif /* defined(WOLFSSL_SILABS_SE_ACCEL) */ + +#endif /* _SILABS_AES_H_ */ diff --git a/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_ecc.h b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_ecc.h new file mode 100644 index 00000000..0a8fd88a --- /dev/null +++ b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_ecc.h @@ -0,0 +1,63 @@ +/* silabs_ecc.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; 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. + * + * wolfSSL is distributed in the hope that it will be useful, + * but 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef _SILABS_ECC_H_ +#define _SILABS_ECC_H_ + + +#if defined(WOLFSSL_SILABS_SE_ACCEL) + +#include + +#include +#include +#include +#include + +typedef enum ecc_curve_id ecc_curve_id; +typedef struct ecc_key ecc_key; + +int silabs_ecc_sign_hash (const byte* in, word32 inlen, + byte* out, word32 *outlen, + ecc_key* key); +int silabs_ecc_verify_hash (const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, + int* stat, ecc_key* key); + + + +int silabs_ecc_make_key(ecc_key* key, int keysize); + +int silabs_ecc_import(ecc_key* key, word32 keysize); + +int silabs_ecc_import_private(ecc_key* key, word32 keysize); + +int silabs_ecc_sig_to_rs(ecc_key* key, word32 keySz); + +int silabs_ecc_import_private_raw(ecc_key* key, word32 keySz, const char* d, int encType); + +int silabs_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen); + +#endif /* WOLFSSL_SILABS_SE_ACCEL */ + +#endif /* _SILABS_ECC_H_ */ diff --git a/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_hash.h b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_hash.h new file mode 100644 index 00000000..ebb69b73 --- /dev/null +++ b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_hash.h @@ -0,0 +1,66 @@ +/* silabs_hash.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; 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. + * + * wolfSSL is distributed in the hope that it will be useful, + * but 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _SILABS_HASH_H_ +#define _SILABS_HASH_H_ + +#include + +#if defined(WOLFSSL_SILABS_SE_ACCEL) + +#include + +#include +#include + +#if defined(SL_SE_HASH_SHA384) && !defined(NO_SHA384) +#define WOLFSSL_SILABS_SHA384 +#endif + +#if defined(SL_SE_HASH_SHA512) && !defined(NO_SHA384) +#define WOLFSSL_SILABS_SHA512 +#endif + +typedef struct { + sl_se_hash_streaming_context_t hash_ctx; + sl_se_command_context_t cmd_ctx; + union hash_type_ctx_u { + sl_se_sha1_streaming_context_t sha1_ctx; + sl_se_sha224_streaming_context_t sha224_ctx; + sl_se_sha256_streaming_context_t sha256_ctx; +#ifdef WOLFSSL_SILABS_SHA384 + sl_se_sha384_streaming_context_t sha384_ctx; +#endif +#ifdef WOLFSSL_SILABS_SHA512 + sl_se_sha512_streaming_context_t sha512_ctx; +#endif + } hash_type_ctx; +} wc_silabs_sha_t; + +int wc_silabs_se_hash_init (wc_silabs_sha_t* sha, enum wc_HashType type); +int wc_silabs_se_hash_update (wc_silabs_sha_t* sha, const byte* data, word32 len); +int wc_silabs_se_hash_final (wc_silabs_sha_t* sha, byte* hash); + + + +#endif /* defined(WOLFSSL_SILABS_SE_ACCEL) */ + +#endif /* _SILABS_HASH_H_ */ diff --git a/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_random.h b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_random.h new file mode 100644 index 00000000..dd095787 --- /dev/null +++ b/source/libs/libwolfssl/wolfcrypt/port/silabs/silabs_random.h @@ -0,0 +1,35 @@ +/* silabs_random.h + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; 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. + * + * wolfSSL is distributed in the hope that it will be useful, + * but 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef _SILABS_RANDOM_H_ +#define _SILABS_RANDOM_H_ + + +#if defined(WOLFSSL_SILABS_SE_ACCEL) + +#include + +int silabs_GenerateRand(byte* output, word32 sz); + +#endif /* WOLFSSL_SILABS_SE_ACCEL */ + +#endif /* _SILABS_RANDOM_H_ */ diff --git a/source/libs/libwolfssl/wolfcrypt/random.h b/source/libs/libwolfssl/wolfcrypt/random.h index ea3e61b3..27aeebdd 100644 --- a/source/libs/libwolfssl/wolfcrypt/random.h +++ b/source/libs/libwolfssl/wolfcrypt/random.h @@ -225,7 +225,12 @@ WOLFSSL_API int wc_FreeRng(WC_RNG*); #define wc_InitRng_ex(rng, h, d) NOT_COMPILED_IN #define wc_InitRngNonce(rng, n, s) NOT_COMPILED_IN #define wc_InitRngNonce_ex(rng, n, s, h, d) NOT_COMPILED_IN +#if defined(__ghs__) || defined(WC_NO_RNG_SIMPLE) +/* some older compilers do not like macro function in expression */ +#define wc_RNG_GenerateBlock(rng, b, s) NOT_COMPILED_IN +#else #define wc_RNG_GenerateBlock(rng, b, s) ({(void)rng; (void)b; (void)s; NOT_COMPILED_IN;}) +#endif #define wc_RNG_GenerateByte(rng, b) NOT_COMPILED_IN #define wc_FreeRng(rng) (void)NOT_COMPILED_IN #endif diff --git a/source/libs/libwolfssl/wolfcrypt/rsa.h b/source/libs/libwolfssl/wolfcrypt/rsa.h index 0c63cc0d..399acc1e 100644 --- a/source/libs/libwolfssl/wolfcrypt/rsa.h +++ b/source/libs/libwolfssl/wolfcrypt/rsa.h @@ -141,8 +141,9 @@ enum { RSA_PSS_SALT_LEN_DISCOVER = -2, #endif -#ifdef HAVE_PKCS11 +#ifdef WOLF_CRYPTO_CB RSA_MAX_ID_LEN = 32, + RSA_MAX_LABEL_LEN = 32, #endif }; @@ -184,9 +185,11 @@ struct RsaKey { byte* mod; XSecure_Rsa xRsa; #endif -#ifdef HAVE_PKCS11 +#ifdef WOLF_CRYPTO_CB byte id[RSA_MAX_ID_LEN]; int idLen; + char label[RSA_MAX_LABEL_LEN]; + int labelLen; #endif #if defined(WOLFSSL_ASYNC_CRYPT) || !defined(WOLFSSL_RSA_VERIFY_INLINE) byte dataIsAlloc; @@ -213,9 +216,11 @@ struct RsaKey { WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); -#ifdef HAVE_PKCS11 +#ifdef WOLF_CRYPTO_CB WOLFSSL_API int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, void* heap, int devId); +WOLFSSL_API int wc_InitRsaKey_Label(RsaKey* key, const char* label, void* heap, + int devId); #endif WOLFSSL_API int wc_CheckRsaKey(RsaKey* key); #ifdef WOLFSSL_XILINX_CRYPT @@ -246,6 +251,9 @@ WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key); WOLFSSL_API int wc_RsaSSL_Verify_ex(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, int pad_type); +WOLFSSL_API int wc_RsaSSL_Verify_ex2(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int pad_type, + enum wc_HashType hash); WOLFSSL_API int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, enum wc_HashType hash, int mgf, RsaKey* key); @@ -367,6 +375,8 @@ WOLFSSL_LOCAL int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** ou int mgf, byte* optLabel, word32 labelLen, int saltLen, int bits, void* heap); +WOLFSSL_LOCAL int wc_hash2mgf(enum wc_HashType hType); + #endif /* HAVE_USER_RSA */ #ifdef __cplusplus diff --git a/source/libs/libwolfssl/wolfcrypt/settings.h b/source/libs/libwolfssl/wolfcrypt/settings.h index df57b1fd..51a0d38b 100644 --- a/source/libs/libwolfssl/wolfcrypt/settings.h +++ b/source/libs/libwolfssl/wolfcrypt/settings.h @@ -225,10 +225,9 @@ #include "user_settings.h" #elif defined(USE_HAL_DRIVER) && !defined(HAVE_CONFIG_H) /* STM Configuration File (generated by CubeMX) */ - #include "wolfSSL.wolfSSL_conf.h" + #include "wolfSSL.I-CUBE-wolfSSL_conf.h" #endif - /* make sure old RNG name is used with CTaoCrypt FIPS */ #ifdef HAVE_FIPS #if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2) @@ -358,12 +357,13 @@ #define NO_FILESYSTEM #define USE_FAST_MATH #define TFM_TIMING_RESISTANT - #define WOLFSSL_HAVE_MIN - #define WOLFSSL_HAVE_MAX #define NO_BIG_INT #endif #ifdef WOLFSSL_MICROCHIP_PIC32MZ + #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX + #ifndef NO_PIC32MZ_CRYPT #define WOLFSSL_PIC32MZ_CRYPT #endif @@ -678,17 +678,17 @@ extern void uITRON4_free(void *p) ; /* static char* gets(char *buff); */ static char* fgets(char *buff, int sz, XFILE fp) { - char * p = buff; - *p = '\0'; + char * s = buff; + *s = '\0'; while (1) { - *p = tm_getchar(-1); - tm_putchar(*p); - if (*p == '\r') { + *s = tm_getchar(-1); + tm_putchar(*s); + if (*s == '\r') { tm_putchar('\n'); - *p = '\0'; + *s = '\0'; break; } - p++; + s++; } return buff; } @@ -1070,7 +1070,9 @@ extern void uITRON4_free(void *p) ; #define ECC_TIMING_RESISTANT #undef HAVE_ECC + #ifndef WOLFCRYPT_FIPS_RAND #define HAVE_ECC + #endif #ifndef NO_AES #undef HAVE_AESCCM #define HAVE_AESCCM @@ -1165,7 +1167,9 @@ extern void uITRON4_free(void *p) ; #endif #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA + #ifndef WOLFCRYPT_FIPS_RAND #define FREESCALE_LTC_ECC + #endif #define FREESCALE_LTC_TFM /* the LTC PKHA hardware limit is 2048 bits (256 bytes) for integer arithmetic. @@ -1215,6 +1219,8 @@ extern void uITRON4_free(void *p) ; #define USE_CERT_BUFFERS_4096 #undef FP_MAX_BITS #define FP_MAX_BITS (8192) + #undef SP_INT_BITS + #define SP_INT_BITS (4096) #undef NO_DH #define NO_DH @@ -1387,11 +1393,18 @@ extern void uITRON4_free(void *p) ; #ifdef MICRIUM #include #include - #include - #include - #include + #if defined(RTOS_MODULE_NET_AVAIL) || (APP_CFG_TCPIP_EN == DEF_ENABLED) + #include + #include + #if (OS_VERSION < 50000) + #include + #endif + #endif #include #include + #include + #include + #include #define USE_FAST_MATH #define TFM_TIMING_RESISTANT @@ -1415,7 +1428,7 @@ extern void uITRON4_free(void *p) ; #define NO_WOLFSSL_DIR #define NO_WRITEV - #ifndef CUSTOM_RAND_GENERATE + #if ! defined(WOLFSSL_SILABS_SE_ACCEL) && !defined(CUSTOM_RAND_GENERATE) #define CUSTOM_RAND_TYPE RAND_NBR #define CUSTOM_RAND_GENERATE Math_Rand #endif @@ -1445,10 +1458,25 @@ extern void uITRON4_free(void *p) ; (CPU_SIZE_T)(size))) #define XMEMCPY(pdest, psrc, size) ((void)Mem_Copy((void *)(pdest), \ (void *)(psrc), (CPU_SIZE_T)(size))) - #define XMEMCMP(pmem_1, pmem_2, size) \ - (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), \ - (void *)(pmem_2), \ + + #if (OS_VERSION < 50000) + #define XMEMCMP(pmem_1, pmem_2, size) \ + (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), \ + (void *)(pmem_2), \ (CPU_SIZE_T)(size))) ? DEF_NO : DEF_YES) + #else + /* Work around for Micrium OS version 5.8 change in behavior + * that returns DEF_NO for 0 size compare + */ + #define XMEMCMP(pmem_1, pmem_2, size) \ + (( (size < 1 ) || \ + ((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), \ + (void *)(pmem_2), \ + (CPU_SIZE_T)(size)) == DEF_YES)) \ + ? 0 : 1) + #define XSNPRINTF snprintf + #endif + #define XMEMMOVE XMEMCPY #if (OS_CFG_MUTEX_EN == DEF_DISABLED) @@ -1746,6 +1774,21 @@ extern void uITRON4_free(void *p) ; #endif #endif +/* The minimum allowed ECC key size */ +/* Note: 224-bits is equivelant to 2048-bit RSA */ +#ifndef ECC_MIN_KEY_SZ + #ifdef WOLFSSL_MIN_ECC_BITS + #define ECC_MIN_KEY_SZ WOLFSSL_MIN_ECC_BITS + #else + #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION >= 2 + /* FIPSv2 and ready (for now) includes 192-bit support */ + #define ECC_MIN_KEY_SZ 192 + #else + #define ECC_MIN_KEY_SZ 224 + #endif + #endif +#endif + /* ECC Configs */ #ifdef HAVE_ECC /* By default enable Sign, Verify, DHE, Key Import and Key Export unless explicitly disabled */ @@ -1929,6 +1972,11 @@ extern void uITRON4_free(void *p) ; #error "FFDHE parameters are too large for FP_MAX_BIT as set" #endif #endif +#if defined(HAVE_FFDHE) && defined(SP_INT_BITS) + #if MIN_FFDHE_FP_MAX_BITS > SP_INT_BITS * 2 + #error "FFDHE parameters are too large for SP_INT_BIT as set" + #endif +#endif /* if desktop type system and fastmath increase default max bits */ #ifdef WOLFSSL_X86_64_BUILD @@ -1939,6 +1987,13 @@ extern void uITRON4_free(void *p) ; #define FP_MAX_BITS MIN_FFDHE_FP_MAX_BITS #endif #endif + #if defined(WOLFSSL_SP_MATH_ALL) && !defined(SP_INT_BITS) + #if MIN_FFDHE_FP_MAX_BITS <= 8192 + #define SP_INT_BITS 4096 + #else + #define PS_INT_BITS MIN_FFDHE_FP_MAX_BITS / 2 + #endif + #endif #endif /* If using the max strength build, ensure OLD TLS is disabled. */ @@ -2118,8 +2173,8 @@ extern void uITRON4_free(void *p) ; #ifndef USE_WOLF_STRTOK #define USE_WOLF_STRTOK #endif - #ifndef WOLFSSL_SP_MOD_WORD_RP - #define WOLFSSL_SP_MOD_WORD_RP + #ifndef WOLFSSL_SP_DIV_WORD_HALF + #define WOLFSSL_SP_DIV_WORD_HALF #endif #ifndef WOLFSSL_OLD_PRIME_CHECK #define WOLFSSL_OLD_PRIME_CHECK @@ -2138,12 +2193,6 @@ extern void uITRON4_free(void *p) ; #ifndef WOLFSSL_SP_DIV_WORD_HALF #define WOLFSSL_SP_DIV_WORD_HALF #endif - #ifndef SP_HALF_SIZE - #define SP_HALF_SIZE 32 - #endif - #ifndef SP_HALF_MAX - #define SP_HALF_MAX 4294967295U - #endif #endif @@ -2154,7 +2203,8 @@ extern void uITRON4_free(void *p) ; #undef HAVE_GMTIME_R /* don't trust macro with windows */ #endif /* WOLFSSL_MYSQL_COMPATIBLE */ -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(HAVE_LIGHTY) #define SSL_OP_NO_COMPRESSION SSL_OP_NO_COMPRESSION #define OPENSSL_NO_ENGINE #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT @@ -2175,7 +2225,7 @@ extern void uITRON4_free(void *p) ; #endif #endif -#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#ifdef HAVE_SNI #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 #endif @@ -2248,17 +2298,23 @@ extern void uITRON4_free(void *p) ; #endif /* Parts of the openssl compatibility layer require peer certs */ -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(HAVE_LIGHTY) #undef KEEP_PEER_CERT #define KEEP_PEER_CERT #endif -/* RAW hash function APIs are not implemented with ARMv8 hardware acceleration*/ -#ifdef WOLFSSL_ARMASM +/* RAW hash function APIs are not implemented */ +#if defined(WOLFSSL_ARMASM) || defined(WOLFSSL_AFALG_HASH) #undef WOLFSSL_NO_HASH_RAW #define WOLFSSL_NO_HASH_RAW #endif +/* XChacha not implemented with ARM assembly ChaCha */ +#if defined(WOLFSSL_ARMASM) + #undef HAVE_XCHACHA +#endif + #if !defined(WOLFSSL_SHA384) && !defined(WOLFSSL_SHA512) && defined(NO_AES) && \ !defined(WOLFSSL_SHA3) #undef WOLFSSL_NO_WORD64_OPS @@ -2297,7 +2353,8 @@ extern void uITRON4_free(void *p) ; #if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(WOLFSSL_SHA384) && \ !defined(WOLFSSL_SHA512) && defined(WC_NO_RNG) && \ - defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_RSA_PUBLIC_ONLY) + (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \ + defined(WOLFSSL_RSA_PUBLIC_ONLY) #undef WOLFSSL_NO_FORCE_ZERO #define WOLFSSL_NO_FORCE_ZERO #endif @@ -2323,6 +2380,13 @@ extern void uITRON4_free(void *p) ; #undef WOLFSSL_SMALL_STACK #endif +#ifdef WOLFSSL_SMALL_STACK_STATIC + #undef WOLFSSL_SMALL_STACK_STATIC + #define WOLFSSL_SMALL_STACK_STATIC static +#else + #define WOLFSSL_SMALL_STACK_STATIC +#endif + /* The client session cache requires time for timeout */ #if defined(NO_ASN_TIME) && !defined(NO_SESSION_CACHE) #define NO_SESSION_CACHE diff --git a/source/libs/libwolfssl/wolfcrypt/sha.h b/source/libs/libwolfssl/wolfcrypt/sha.h index a9d10257..4d42ea7f 100644 --- a/source/libs/libwolfssl/wolfcrypt/sha.h +++ b/source/libs/libwolfssl/wolfcrypt/sha.h @@ -75,6 +75,9 @@ #ifdef WOLFSSL_IMXRT_DCP #include #endif +#if defined(WOLFSSL_SILABS_SE_ACCEL) + #include +#endif #if !defined(NO_OLD_SHA_NAMES) #define SHA WC_SHA @@ -114,6 +117,8 @@ struct wc_Sha { ltc_hash_ctx_t ctx; #elif defined(STM32_HASH) STM32_HASH_Context stmCtx; +#elif defined(WOLFSSL_SILABS_SE_ACCEL) + wc_silabs_sha_t silabsCtx; #else word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ diff --git a/source/libs/libwolfssl/wolfcrypt/sha256.h b/source/libs/libwolfssl/wolfcrypt/sha256.h index c421fd07..1ae4f74d 100644 --- a/source/libs/libwolfssl/wolfcrypt/sha256.h +++ b/source/libs/libwolfssl/wolfcrypt/sha256.h @@ -88,6 +88,9 @@ #if defined(WOLFSSL_CRYPTOCELL) #include #endif +#if defined(WOLFSSL_SILABS_SE_ACCEL) + #include +#endif #if defined(_MSC_VER) #define SHA256_NOINLINE __declspec(noinline) @@ -138,6 +141,8 @@ struct wc_Sha256 { ltc_hash_ctx_t ctx; #elif defined(STM32_HASH_SHA2) STM32_HASH_Context stmCtx; +#elif defined(WOLFSSL_SILABS_SE_ACCEL) + wc_silabs_sha_t silabsCtx; #else /* alignment on digest and buffer speeds up ARMv8 crypto operations */ ALIGN16 word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; diff --git a/source/libs/libwolfssl/wolfcrypt/sha3.h b/source/libs/libwolfssl/wolfcrypt/sha3.h index 02be26fb..d580c42b 100644 --- a/source/libs/libwolfssl/wolfcrypt/sha3.h +++ b/source/libs/libwolfssl/wolfcrypt/sha3.h @@ -90,7 +90,7 @@ enum { #else /* Sha3 digest */ -struct Sha3 { +struct wc_Sha3 { /* State data that is processed for each block. */ word64 s[25]; /* Unprocessed message data. */ @@ -109,7 +109,7 @@ struct Sha3 { }; #ifndef WC_SHA3_TYPE_DEFINED - typedef struct Sha3 wc_Sha3; + typedef struct wc_Sha3 wc_Sha3; #define WC_SHA3_TYPE_DEFINED #endif diff --git a/source/libs/libwolfssl/wolfcrypt/sha512.h b/source/libs/libwolfssl/wolfcrypt/sha512.h index 44fa85fb..e68b7cd8 100644 --- a/source/libs/libwolfssl/wolfcrypt/sha512.h +++ b/source/libs/libwolfssl/wolfcrypt/sha512.h @@ -76,6 +76,10 @@ #ifdef WOLFSSL_ESP32WROOM32_CRYPT #include #endif +#if defined(WOLFSSL_SILABS_SE_ACCEL) + #include +#endif + #if defined(_MSC_VER) #define SHA512_NOINLINE __declspec(noinline) #elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) @@ -136,6 +140,10 @@ struct wc_Sha512 { !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) WC_ESP32SHA ctx; #endif +#if defined(WOLFSSL_SILABS_SE_ACCEL) + wc_silabs_sha_t silabsCtx; +#endif + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) word32 flags; /* enum wc_HashFlags in hash.h */ #endif diff --git a/source/libs/libwolfssl/wolfcrypt/sp_int.h b/source/libs/libwolfssl/wolfcrypt/sp_int.h index ee574608..6092d5d0 100644 --- a/source/libs/libwolfssl/wolfcrypt/sp_int.h +++ b/source/libs/libwolfssl/wolfcrypt/sp_int.h @@ -28,10 +28,120 @@ This library provides single precision (SP) integer math functions. #define WOLF_CRYPT_SP_INT_H #ifndef WOLFSSL_LINUXKM -#include #include #endif +#ifdef __cplusplus +extern "C" { +#endif + +/* Find smallest type for smallest bits. */ +#if UCHAR_MAX == 255 + #define SP_UCHAR_BITS 8 + + typedef unsigned char sp_uint8; + typedef char sp_int8; +#elif UCHAR_MAX == 127 + #define SP_UCHAR_BITS 7 + + typedef unsigned char sp_uint7; + typedef char sp_int7; +#else + #error "Size of unsigned short not detected" +#endif + +#if USHRT_MAX == 65535 + #define SP_USHORT_BITS 16 + + typedef unsigned short sp_uint16; + typedef short sp_int16; +#elif USHRT_MAX == 255 + #define SP_USHORT_BITS 8 + + #if USHRT_MAX > UCHAR_MAX + typedef unsigned short sp_uint8; + typedef short sp_int8; + #endif +#else + #error "Size of unsigned short not detected" +#endif + +#if UINT_MAX == 4294967295UL + #define SP_UINT_BITS 32 + + typedef unsigned int sp_uint32; + typedef int sp_int32; +#elif UINT_MAX == 65535 + #define SP_UINT_BITS 16 + + #if UINT_MAX > USHRT_MAX + typedef unsigned int sp_uint16; + typedef int sp_int16; + #endif +#elif UINT_MAX == 255 + #define SP_UINT_BITS 8 + + #if UINT_MAX > USHRT_MAX + typedef unsigned int sp_uint8; + typedef int sp_int8; + #endif +#else + #error "Size of unsigned int not detected" +#endif + +#if ULONG_MAX == 18446744073709551615UL + #define SP_ULONG_BITS 64 + + typedef unsigned long sp_uint64; + typedef long sp_int64; +#elif ULONG_MAX == 4294967295UL + #define SP_ULONG_BITS 32 + + #if ULONG_MAX > UINT_MAX + typedef unsigned long sp_uint32; + typedef long sp_int32; + #endif +#elif ULONG_MAX == 65535 + #define SP_ULONG_BITS 16 + + #if ULONG_MAX > UINT_MAX + typedef unsigned long sp_uint16; + typedef long sp_int16; + #endif +#else + #error "Size of unsigned long not detected" +#endif + +#if ULLONG_MAX == 18446744073709551615UL + #define SP_ULLONG_BITS 64 + + #if SP_ULLONG_BITS > SP_ULONG_BITS + typedef unsigned long long sp_uint64; + typedef long long sp_int64; + #endif +#elif ULLONG_MAX == 4294967295UL + #define SP_ULLONG_BITS 32 + + #if SP_ULLONG_BITS > SP_ULONG_BITS + typedef unsigned long long sp_uint32; + typedef long long sp_int32; + #endif +#elif ULLONG_MAX == 65535 + #define SP_ULLONG_BITS 16 + + #if SP_ULLONG_BITS > SP_ULONG_BITS + typedef unsigned long long sp_uint16; + typedef long long sp_int16; + #endif +#else + #error "Size of unsigned long long not detected" +#endif + + +#ifdef WOLFSSL_SP_DIV_32 +#define WOLFSSL_SP_DIV_WORD_HALF +#endif + /* Make sure WOLFSSL_SP_ASM build option defined when requested */ #if !defined(WOLFSSL_SP_ASM) && ( \ defined(WOLFSSL_SP_X86_64_ASM) || defined(WOLFSSL_SP_ARM32_ASM) || \ @@ -41,19 +151,47 @@ This library provides single precision (SP) integer math functions. #endif -#ifdef WOLFSSL_SP_X86_64_ASM - #define SP_WORD_SIZE 64 - - #define HAVE_INTEL_AVX1 - #define HAVE_INTEL_AVX2 -#elif defined(WOLFSSL_SP_ARM64_ASM) - #define SP_WORD_SIZE 64 -#elif defined(WOLFSSL_SP_ARM32_ASM) +/* Detemine the number of bits to use in each word. */ +#ifdef SP_WORD_SIZE +#elif defined(WOLFSSL_DSP_BUILD) #define SP_WORD_SIZE 32 -#elif defined(WOLFSSL_SP_ARM_THUMB_ASM) +#elif defined(WOLFSSL_SP_X86_64_ASM) || defined(WOLFSSL_SP_X86_64) + #if SP_ULONG_BITS == 64 + #define SP_WORD_SIZE 64 + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 + #elif SP_ULONG_BITS == 32 + #define SP_WORD_SIZE 32 + #undef WOLFSSL_SP_ASM + #elif SP_ULONG_BITS == 16 + #define SP_WORD_SIZE 16 + #undef WOLFSSL_SP_ASM + #endif +#elif defined(WOLFSSL_SP_ARM64_ASM) || defined(WOLFSSL_SP_ARM64) + #define SP_WORD_SIZE 64 +#elif defined(WOLFSSL_SP_ARM32_ASM) || defined(WOLFSSL_SP_ARM32) #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_ARM_THUMB_ASM) || defined(WOLFSSL_SP_ARM_THUMB) + #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_PPC) + #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_PPC64) + #define SP_WORD_SIZE 64 +#elif defined(WOLFSSL_SP_MIPS) + #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_MIPS64) + #define SP_WORD_SIZE 64 +#elif defined(WOLFSSL_SP_RISCV32) + #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_RISCV64) + #define SP_WORD_SIZE 64 +#elif defined(WOLFSSL_SP_S390X) + #define SP_WORD_SIZE 64 #endif +/* If no predefined or assembly required size then use maximum available + * with compiler. + */ #ifndef SP_WORD_SIZE #if defined(NO_64BIT) || !defined(HAVE___UINT128_T) #define SP_WORD_SIZE 32 @@ -62,63 +200,109 @@ This library provides single precision (SP) integer math functions. #endif #endif -#ifdef WOLFSSL_DSP_BUILD - typedef int32 sp_digit; - typedef uint32 sp_int_digit; - typedef uint64 sp_int_word; - typedef int64 sp_int_sword; - #undef SP_WORD_SIZE - #define SP_WORD_SIZE 32 -#elif !defined(WOLFSSL_SP_ASM) - #if SP_WORD_SIZE == 32 - typedef int32_t sp_digit; - typedef uint32_t sp_int_digit; - typedef uint64_t sp_int_word; - typedef int64_t sp_int_sword; - #elif SP_WORD_SIZE == 64 - typedef int64_t sp_digit; - typedef uint64_t sp_int_digit; +/* Number of bytes in each word. */ +#define SP_WORD_SIZEOF (SP_WORD_SIZE / 8) + +/* Define the types used. */ +#ifdef HAVE___UINT128_T #ifdef __SIZEOF_INT128__ - typedef __uint128_t uint128_t; - typedef __int128_t int128_t; + typedef __uint128_t sp_uint128; + typedef __int128_t sp_int128; #else - typedef unsigned long uint128_t __attribute__ ((mode(TI))); - typedef long int128_t __attribute__ ((mode(TI))); + typedef unsigned long sp_uint128 __attribute__ ((mode(TI))); + typedef long sp_int128 __attribute__ ((mode(TI))); #endif - typedef uint128_t sp_int_word; - typedef int128_t sp_int_sword; - #endif -#else - #if SP_WORD_SIZE == 32 - typedef uint32_t sp_digit; - typedef uint32_t sp_int_digit; - typedef uint64_t sp_int_word; - typedef int64_t sp_int_sword; - #elif SP_WORD_SIZE == 64 - typedef uint64_t sp_digit; - typedef uint64_t sp_int_digit; - #ifdef __SIZEOF_INT128__ - typedef __uint128_t uint128_t; - typedef __int128_t int128_t; - #else - typedef unsigned long uint128_t __attribute__ ((mode(TI))); - typedef long int128_t __attribute__ ((mode(TI))); + #ifndef WOLFSSL_UINT128_T_DEFINED + #ifdef __SIZEOF_INT128__ + typedef __uint128_t uint128_t; + typedef __int128_t int128_t; + #else + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #endif + #define WOLFSSL_UINT128_T_DEFINED #endif - typedef uint128_t sp_int_word; - typedef int128_t sp_int_sword; - #endif #endif -#if SP_WORD_SIZE == 32 - #define SP_MASK ((sp_int_digit)0xffffffffU) +#if SP_WORD_SIZE == 8 + typedef sp_uint8 sp_int_digit; + typedef sp_int8 sp_sint_digit; + typedef sp_uint16 sp_int_word; + typedef sp_int16 sp_int_sword; + + #define SP_MASK 0xffU +#elif SP_WORD_SIZE == 16 + typedef sp_uint16 sp_int_digit; + typedef sp_int16 sp_sint_digit; + typedef sp_uint32 sp_int_word; + typedef sp_int32 sp_int_sword; + + #define SP_MASK 0xffffU +#elif SP_WORD_SIZE == 32 + typedef sp_uint32 sp_int_digit; + typedef sp_int32 sp_sint_digit; + typedef sp_uint64 sp_int_word; + typedef sp_int64 sp_int_sword; + + #define SP_MASK 0xffffffffU #elif SP_WORD_SIZE == 64 - #define SP_MASK ((sp_int_digit)0xffffffffffffffffUL) + typedef sp_uint64 sp_int_digit; + typedef sp_int64 sp_sint_digit; + typedef sp_uint128 sp_int_word; + typedef sp_int128 sp_int_sword; + + #define SP_MASK 0xffffffffffffffffUL #else #error Word size not defined #endif +/* Define an SP digit. */ +#ifndef WOLFSSL_SP_ASM + /* SP C code uses n/m bits and therefore needs a signed type. */ + #if SP_WORD_SIZE == 8 + typedef sp_int8 sp_digit; + #elif SP_WORD_SIZE == 16 + typedef sp_int16 sp_digit; + #elif SP_WORD_SIZE == 32 + typedef sp_int32 sp_digit; + #elif SP_WORD_SIZE == 64 + typedef sp_int64 sp_digit; + #endif +#else + /* SP ASM code uses full size and needs an unsigned type. */ + #if SP_WORD_SIZE == 8 + typedef sp_uint8 sp_digit; + #elif SP_WORD_SIZE == 16 + typedef sp_uint16 sp_digit; + #elif SP_WORD_SIZE == 32 + typedef sp_uint32 sp_digit; + #elif SP_WORD_SIZE == 64 + typedef sp_uint64 sp_digit; + #endif +#endif + +/** Number of bits in a half a word. */ +#define SP_HALF_SIZE (SP_WORD_SIZE / 2) +/** Maximum value that can be held in a half a word. */ +#define SP_HALF_MAX (((sp_digit)1 << SP_HALF_SIZE) - 1) +/** Maximum value that can be held in a word. */ +#define SP_DIGIT_MAX SP_MASK +/* Number of bits to shift to divide by word size. */ +#if SP_WORD_SIZE == 8 + #define SP_WORD_SHIFT 3 +#elif SP_WORD_SIZE == 16 + #define SP_WORD_SHIFT 4 +#elif SP_WORD_SIZE == 32 + #define SP_WORD_SHIFT 5 +#elif SP_WORD_SIZE == 64 + #define SP_WORD_SHIFT 6 +#endif +/* Mask of word size. */ +#define SP_WORD_MASK (SP_WORD_SIZE - 1) + #if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_NONBLOCK) +/* Non-blocking ECC operation context. */ typedef struct sp_ecc_ctx { #ifdef WOLFSSL_SP_384 byte data[48*80]; /* stack data */ @@ -128,186 +312,590 @@ typedef struct sp_ecc_ctx { } sp_ecc_ctx_t; #endif -#ifdef WOLFSSL_SP_MATH +#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) #include -#if !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) - #if !defined(NO_PWDBASED) && defined(WOLFSSL_SHA512) - #define SP_INT_DIGITS ((512 + SP_WORD_SIZE) / SP_WORD_SIZE) - #elif defined(WOLFSSL_SP_384) - #define SP_INT_DIGITS ((384 + SP_WORD_SIZE) / SP_WORD_SIZE) +#ifdef SP_INT_BITS + /* Calculate number of digits to have in an sp_int based maximum size of + * numbers in bits that will be used. + * Double the size to hold multiplication result. + * Add one to accommodate extra digit used by sp_mul(), sp_mulmod(), sp_sqr(), and sp_sqrmod(). + */ + #define SP_INT_DIGITS \ + ((((SP_INT_BITS + (SP_WORD_SIZE - 1)) * 2 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) +#endif + +#ifndef SP_INT_DIGITS + /* Calculate number of digits to have in an sp_int based on features + * compiled in. + */ + #if !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) && \ + !defined(WOLFSSL_HAVE_SP_ECC) + #if !defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA) + #define SP_INT_DIGITS (((6144 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #elif defined(HAVE_ECC) + #define SP_INT_DIGITS \ + (((2 * ( 521 + SP_WORD_SIZE) + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #elif !defined(NO_PWDBASED) && defined(WOLFSSL_SHA512) + #define SP_INT_DIGITS ((( 512 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #else + #define SP_INT_DIGITS ((( 256 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #endif + #elif !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) + #ifdef WOLFSSL_SP_MATH_ALL + #define SP_INT_DIGITS \ + (((2 * ( 521 + SP_WORD_SIZE) + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #elif defined(WOLFSSL_SP_384) + #define SP_INT_DIGITS ((( 768 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #else + #define SP_INT_DIGITS ((( 512 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #endif + #elif defined(WOLFSSL_SP_4096) + #if defined(WOLFSSL_HAVE_SP_DH) + #define SP_INT_DIGITS (((8192 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #else + #define SP_INT_DIGITS (((4096 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #endif + #elif !defined(WOLFSSL_SP_NO_3072) + #if defined(WOLFSSL_HAVE_SP_DH) + #define SP_INT_DIGITS (((6144 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #else + #define SP_INT_DIGITS (((3072 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #endif #else - #define SP_INT_DIGITS ((256 + SP_WORD_SIZE) / SP_WORD_SIZE) - #endif -#elif defined(WOLFSSL_SP_4096) - #if defined(WOLFSSL_HAVE_SP_DH) - #define SP_INT_DIGITS ((8192 + SP_WORD_SIZE) / SP_WORD_SIZE) - #else - #define SP_INT_DIGITS ((4096 + SP_WORD_SIZE) / SP_WORD_SIZE) - #endif -#elif !defined(WOLFSSL_SP_NO_3072) - #if defined(WOLFSSL_HAVE_SP_DH) - #define SP_INT_DIGITS ((6144 + SP_WORD_SIZE) / SP_WORD_SIZE) - #else - #define SP_INT_DIGITS ((3072 + SP_WORD_SIZE) / SP_WORD_SIZE) - #endif -#else - #if defined(WOLFSSL_HAVE_SP_DH) - #define SP_INT_DIGITS ((4096 + SP_WORD_SIZE) / SP_WORD_SIZE) - #else - #define SP_INT_DIGITS ((2048 + SP_WORD_SIZE) / SP_WORD_SIZE) + #if defined(WOLFSSL_HAVE_SP_DH) + #define SP_INT_DIGITS (((4096 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #else + #define SP_INT_DIGITS (((2048 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #endif #endif #endif -#define sp_isodd(a) ((a)->used != 0 && ((a)->dp[0] & 1)) -#define sp_iseven(a) ((a)->used != 0 && ((a)->dp[0] & 1) == 0) -#define sp_iszero(a) ((a)->used == 0) -#define sp_isone(a) ((a)->used == 1 && (a)->dp[0] == 1) -#define sp_abs(a, b) sp_copy(a, b) +#ifndef SP_INT_MAX_BITS + /* Convert number digits to number of bits. */ + #define SP_INT_MAX_BITS (SP_INT_DIGITS * SP_WORD_SIZE) +#endif + + +/* For debugging only - format string for different digit sizes. */ +#if SP_WORD_SIZE == 64 + #if SP_ULONG_BITS == 64 + #define SP_PRINT_FMT "%016lx" + #else + #define SP_PRINT_FMT "%016llx" + #endif +#elif SP_WORD_SIZE == 32 + #if SP_UINT_BITS == 32 + #define SP_PRINT_FMT "%08x" + #else + #define SP_PRINT_FMT "%08lx" + #endif +#elif SP_WORD_SIZE == 16 + #define SP_PRINT_FMT "%04x" +#elif SP_WORD_SIZE == 8 + #define SP_PRINT_FMT "%02x" +#endif + +#ifndef NO_FILESYSTEM +/* Output is formatted to be used with script that checks calculations. */ + +/* Print out a number in big endian. */ +#ifndef WOLFSSL_SP_INT_NEGATIVE +/* Print out a positive multi-precision number. + * + * @param [in] a SP integer to print. + * @param [in] s String that describes the use of the number. + */ +#define sp_print(a, s) \ + do { \ + int ii; \ + fprintf(stderr, "%s=0x0", s); \ + for (ii = (a)->used-1; ii >= 0; ii--) { \ + fprintf(stderr, SP_PRINT_FMT, (a)->dp[ii]); \ + } \ + fprintf(stderr, "\n"); \ + } \ + while (0) +#else +/* Print out a multi-precision number. + * + * @param [in] a SP integer to print. + * @param [in] s String that describes the use of the number. + */ +#define sp_print(a, s) \ + do { \ + int ii; \ + fprintf(stderr, "%s=0x", s); \ + if ((a)->sign == MP_NEG) { \ + fprintf(stderr, "-"); \ + } \ + fprintf(stderr, "0"); \ + for (ii = (a)->used-1; ii >= 0; ii--) { \ + fprintf(stderr, SP_PRINT_FMT, (a)->dp[ii]); \ + } \ + fprintf(stderr, "\n"); \ + } \ + while (0) +#endif + +/* Print out a single multi-precision digit. + * + * @param [in] a SP integer digit to print. + * @param [in] s String that describes the use of the number. + */ +#define sp_print_digit(a, s) \ + do { \ + fprintf(stderr, "%s=0x0", s); \ + fprintf(stderr, SP_PRINT_FMT, a); \ + fprintf(stderr, "\n"); \ + } \ + while (0) + +/* Print out an integer. + * + * @param [in] a Number to print. + * @param [in] s String that describes the use of the number. + */ +#define sp_print_int(a, s) \ + do { \ + fprintf(stderr, "%s=0x0%x\n", s, a); \ + } \ + while (0) + +#else + + /* No filesystem, no output + * TODO: Use logging API? + */ + #define sp_print(a, s) + #define sp_print_digit(a, s) + #define sp_print_int(a, s) + +#endif + +/* Returns whether multi-precision number is odd + * + * Assumes a is not NULL. + * + * @param [in] a SP integer to check. + * @return 1 when odd. + * @return 0 when even. + */ +#define sp_isodd(a) (((a)->used != 0) && ((a)->dp[0] & 1)) +/* Returns whether multi-precision number is even + * + * Assumes a is not NULL. + * + * @param [in] a SP integer to check. + * @return 1 when even. + * @return 0 when odd. + */ +#define sp_iseven(a) (((a)->used != 0) && (((a)->dp[0] & 1) == 0)) +/* Returns whether multi-precision number has the value zero. + * + * Assumes a is not NULL. + * + * @param [in] a SP integer to check. + * @return 1 when zero. + * @return 0 when not zero. + */ +#define sp_iszero(a) ((a)->used == 0) +/* Returns whether multi-precision number has the value one. + * + * Assumes a is not NULL. + * + * @param [in] a SP integer to check. + * @return 1 when one. + * @return 0 when not one. + */ +#define sp_isone(a) (((a)->used == 1) && ((a)->dp[0] == 1)) +/* Returns whether multi-precision number has the value 'd'. + * + * Assumes a is not NULL. + * + * @param [in] a SP integer to check. + * @param [in] d SP integer digit. + * @return 1 when one. + * @return 0 when not one. + */ +#define sp_isword(a, d) (((a)->used == 1) && ((a)->dp[0] == d)) +#ifndef WOLFSSL_SP_INT_NEGATIVE +/* Calculate the absolute value of the multi-precision number. + * + * Negative support not compiled in so just copies. + * + * @param [in] a SP integer to calculate absolute value of. + * @param [out] r SP integer to hold result. + * + * @return MP_OKAY on success. + * @return MP_VAL when a or r is NULL. + */ +#define sp_abs(a, b) sp_copy(a, b) +/* Returns whether multi-precision number is negative. + * + * Negative support not compiled in so always returns 0 (false). + * + * @param [in] a SP integer to check. + * @param [in] d SP integer digit. + * @return 0 indicating not negative always. + */ +#define sp_isneg(a) (0) +#else +/* Returns whether multi-precision number is negative. + * + * Assumes a is not NULL. + * + * @param [in] a SP integer to check. + * @param [in] d SP integer digit. + * @return 1 when negative. + * @return 0 when not negative. + */ +#define sp_isneg(a) ((a)->sign == MP_NEG) +#endif +/* Updates the used count to exclude leading zeros. + * + * Assumes a is not NULL. + * + * @param [in] a SP integer to update. + */ +#define sp_clamp(a) \ + do { \ + int ii; \ + for (ii = a->used - 1; ii >= 0 && a->dp[ii] == 0; ii--) { \ + } \ + a->used = ii + 1; \ + } while (0) + +/* Check the compiled and linked math implementation are the same. + * Use the number of bits in a digit as indication of how code was compiled. + * + * @return 1 when the number of bits are the same. + * @return 0 when the number of bits are differnt. + */ +#define CheckFastMathSettings() (SP_WORD_SIZE == CheckRunTimeFastMath()) + + +#ifdef WOLFSSL_SP_INT_NEGATIVE + #ifdef HAVE_WOLF_BIGINT + #define SP_INT_EXTRA_OVERHEAD sizeof(int) + sizeof(struct WC_BIGINT) + #else + #define SP_INT_EXTRA_OVERHEAD sizeof(int) + #endif +#elif defined(HAVE_WOLF_BIGINT) + #define SP_INT_EXTRA_OVERHEAD sizeof(struct WC_BIGINT) +#else + #define SP_INT_EXTRA_OVERHEAD 0 +#endif +#define WOLFSSL_SP_INT_OVERHEAD \ + (sizeof(int) + sizeof(int) + SP_INT_EXTRA_OVERHEAD) + +#define MP_INT_SIZEOF(cnt) \ + (WOLFSSL_SP_INT_OVERHEAD + ((cnt) * SP_WORD_SIZEOF)) + + +/** + * A reuslt of NO. + * e.g. Is prime? NO. + */ +#define MP_NO 0 +/** + * A reuslt of YES. + * e.g. Is prime? YES. + */ +#define MP_YES 1 + +#ifdef WOLFSSL_SP_INT_NEGATIVE +/** Number is 0/positive. */ +#define MP_ZPOS 0 +/** Number is negative. */ +#define MP_NEG 1 +#endif + +/** Radix is base 10 or decimal. */ +#define MP_RADIX_DEC 10 +/** Radix is base 16 or hexadecimal. */ +#define MP_RADIX_HEX 16 + +/** Result of comparison is that the first number is greater than second. */ +#define MP_GT 1 +/** Result of comparison is they are equal. */ +#define MP_EQ 0 +/** Result of comparison is that the first number is less than second. */ +#define MP_LT -1 + +/** Error value on success. */ +#define MP_OKAY 0 +/** Error value when dynamic memory allocation fails. */ +#define MP_MEM -2 +/** Error value when value passed is not able to be used. */ +#define MP_VAL -3 +/** Error value when non-blocking operation is returning after partial + * completion. + */ +#define FP_WOULDBLOCK -4 + +/* Number of bits in each word/digit. */ +#define DIGIT_BIT SP_WORD_SIZE +/* Mask of all used bits in word/digit. */ +#define MP_MASK SP_MASK + #ifdef HAVE_WOLF_BIGINT - /* raw big integer */ + /* Raw big integer as a big-endian byte array. + * + * Useful for when using hardware - canonical format. + */ typedef struct WC_BIGINT { + /* Dynamically allocated buffer that is big-endian byte array. */ byte* buf; + /* Length of buffer in bytes. */ word32 len; + /* Hint for heap used to allocate buffer. */ void* heap; } WC_BIGINT; + + /* Ensure WC_BIGINT defined once. */ #define WOLF_BIGINT_DEFINED #endif + +/** + * SP integer. + * + * dp at end so user can allocate a smaller amount and set size. + */ typedef struct sp_int { + /** Number of words that contain data. */ int used; + /** Maximum number of words in data. */ int size; - sp_int_digit dp[SP_INT_DIGITS]; -#ifdef HAVE_WOLF_BIGINT - struct WC_BIGINT raw; /* unsigned binary (big endian) */ +#ifdef WOLFSSL_SP_INT_NEGATIVE + /** Indicates whether number is 0/positive or negative. */ + int sign; #endif +#ifdef HAVE_WOLF_BIGINT + /** Unsigned binary (big endian) representation of number. */ + struct WC_BIGINT raw; +#endif + /** Data of number. */ + sp_int_digit dp[SP_INT_DIGITS]; } sp_int; +/* Mulit-precision integer type is SP integer type. */ typedef sp_int mp_int; +/* Mulit-precision integer digit type is SP integer digit type. + * Type is unsigned. + */ typedef sp_int_digit mp_digit; + +/* Include the maths operations that are not implementation specific. */ #include +/* + * Function prototypes. + */ MP_API int sp_init(sp_int* a); -MP_API int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, - sp_int* e, sp_int* f); +MP_API int sp_init_size(sp_int* a, int size); +MP_API int sp_init_multi(sp_int* n1, sp_int* n2, sp_int* n3, sp_int* n4, + sp_int* n5, sp_int* n6); MP_API void sp_free(sp_int* a); -MP_API void sp_clear(sp_int* a); -MP_API int sp_unsigned_bin_size(sp_int* a); -MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz); -MP_API int sp_read_radix(sp_int* a, const char* in, int radix); -MP_API int sp_cmp(sp_int* a, sp_int* b); -MP_API int sp_count_bits(sp_int* a); -MP_API int sp_leading_bit(sp_int* a); -MP_API int sp_to_unsigned_bin(sp_int* a, byte* out); -MP_API int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz); -MP_API void sp_forcezero(sp_int* a); -MP_API int sp_copy(sp_int* a, sp_int* r); -MP_API int sp_set(sp_int* a, sp_int_digit d); -MP_API void sp_clamp(sp_int* a); MP_API int sp_grow(sp_int* a, int l); -MP_API int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r); -MP_API int sp_cmp_d(sp_int* a, sp_int_digit d); -MP_API int sp_sub(sp_int* a, sp_int* b, sp_int* r); -MP_API int sp_mod(sp_int* a, sp_int* m, sp_int* r); + MP_API void sp_zero(sp_int* a); -MP_API int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r); -MP_API int sp_lshd(sp_int* a, int s); -MP_API int sp_add(sp_int* a, sp_int* b, sp_int* r); -MP_API int sp_set_int(sp_int* a, unsigned long b); -MP_API int sp_tohex(sp_int* a, char* str); +MP_API void sp_clear(sp_int* a); +MP_API void sp_forcezero(sp_int* a); +MP_API int sp_init_copy (sp_int* r, sp_int* a); + +MP_API int sp_copy(sp_int* a, sp_int* r); +MP_API int sp_exch(sp_int* a, sp_int* b); +MP_API int sp_cond_swap_ct(mp_int * a, mp_int * b, int c, int m); + +#ifdef WOLFSSL_SP_INT_NEGATIVE +MP_API int sp_abs(sp_int* a, sp_int* b); +#endif +MP_API int sp_cmp_mag(sp_int* a, sp_int* b); +MP_API int sp_cmp(sp_int* a, sp_int* b); + +MP_API int sp_is_bit_set(sp_int* a, unsigned int b); +MP_API int sp_count_bits(sp_int* a); +#if defined(HAVE_ECC) && defined(HAVE_COMP_KEY) +MP_API int sp_cnt_lsb(sp_int* a); +#endif +MP_API int sp_leading_bit(sp_int* a); MP_API int sp_set_bit(sp_int* a, int i); MP_API int sp_2expt(sp_int* a, int e); -MP_API int sp_rand_prime(sp_int* r, int len, WC_RNG* rng, void* heap); + +MP_API int sp_set(sp_int* a, sp_int_digit d); +MP_API int sp_set_int(sp_int* a, unsigned long n); +MP_API int sp_cmp_d(sp_int* a, sp_int_digit d); +MP_API int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r); +MP_API int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r); +MP_API int sp_mul_d(sp_int* a, sp_int_digit d, sp_int* r); +MP_API int sp_div_d(sp_int* a, sp_int_digit d, sp_int* r, sp_int_digit* rem); +#if defined(WOLFSSL_SP_MATH_ALL) || (defined(HAVE_ECC) && \ + defined(HAVE_COMP_KEY)) +MP_API int sp_mod_d(sp_int* a, const sp_int_digit d, sp_int_digit* r); +#endif +MP_API int sp_div_2_mod_ct (sp_int* a, sp_int* b, sp_int* c); +#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) +MP_API int sp_div_2(sp_int* a, sp_int* r); +#endif + +MP_API int sp_add(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_sub(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_addmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r); +MP_API int sp_submod(sp_int* a, sp_int* b, sp_int* m, sp_int* r); +MP_API int sp_submod_ct (sp_int* a, sp_int* b, sp_int* c, sp_int* d); +MP_API int sp_addmod_ct (sp_int* a, sp_int* b, sp_int* c, sp_int* d); + +MP_API int sp_lshd(sp_int* a, int s); +MP_API void sp_rshd(sp_int* a, int c); +MP_API void sp_rshb(sp_int* a, int n, sp_int* r); + +#ifdef WOLFSSL_SP_MATH_ALL +MP_API int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem); +#endif +MP_API int sp_mod(sp_int* a, sp_int* m, sp_int* r); + MP_API int sp_mul(sp_int* a, sp_int* b, sp_int* r); MP_API int sp_mulmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r); -MP_API int sp_gcd(sp_int* a, sp_int* b, sp_int* r); + MP_API int sp_invmod(sp_int* a, sp_int* m, sp_int* r); -MP_API int sp_lcm(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_invmod_mont_ct(sp_int* a, sp_int* m, sp_int* r, sp_int_digit mp); + +MP_API int sp_exptmod_ex(sp_int* b, sp_int* e, int digits, sp_int* m, + sp_int* r); MP_API int sp_exptmod(sp_int* b, sp_int* e, sp_int* m, sp_int* r); +MP_API int sp_exptmod_nct(sp_int* b, sp_int* e, sp_int* m, sp_int* r); + +MP_API int sp_div_2d(sp_int* a, int e, sp_int* r, sp_int* rem); +MP_API int sp_mod_2d(sp_int* a, int e, sp_int* r); +MP_API int sp_mul_2d(sp_int* a, int e, sp_int* r); + +MP_API int sp_sqr(sp_int* a, sp_int* r); +MP_API int sp_sqrmod(sp_int* a, sp_int* m, sp_int* r); + +MP_API int sp_mont_red(sp_int* a, sp_int* m, sp_int_digit mp); +MP_API int sp_mont_setup(sp_int* m, sp_int_digit* rho); +MP_API int sp_mont_norm(sp_int* norm, sp_int* m); + +MP_API int sp_unsigned_bin_size(sp_int* a); +MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz); +MP_API int sp_to_unsigned_bin(sp_int* a, byte* out); +MP_API int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz); +MP_API int sp_to_unsigned_bin_at_pos(int o, sp_int* a, unsigned char* out); + +MP_API int sp_read_radix(sp_int* a, const char* in, int radix); +MP_API int sp_tohex(sp_int* a, char* str); +MP_API int sp_todecimal(mp_int* a, char* str); +MP_API int sp_toradix(mp_int* a, char* str, int radix); +MP_API int sp_radix_size(mp_int* a, int radix, int* size); + +MP_API int sp_rand_prime(sp_int* r, int len, WC_RNG* rng, void* heap); MP_API int sp_prime_is_prime(mp_int* a, int t, int* result); MP_API int sp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng); -MP_API int sp_exch(sp_int* a, sp_int* b); -MP_API int sp_get_digit_count(sp_int *a); -MP_API int sp_init_copy (sp_int * a, sp_int * b); -MP_API void sp_rshb(sp_int* a, int n, sp_int* r); -MP_API int sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r); +MP_API int sp_gcd(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_lcm(sp_int* a, sp_int* b, sp_int* r); + +WOLFSSL_API word32 CheckRunTimeFastMath(void); -#define MP_NO 0 -#define MP_YES 1 +/* Map mp functions to SP math versions. */ +/* Different name or signature. */ +#define mp_mul_2(a, r) sp_mul_2d(a, 1, r) +#define mp_div_3(a, r, rem) sp_div_d(a, 3, r, rem) +#define mp_rshb(A,x) sp_rshb(A,x,A) +#define mp_is_bit_set(a,b) sp_is_bit_set(a,(unsigned int)b) +#define mp_montgomery_reduce sp_mont_red +#define mp_montgomery_setup sp_mont_setup +#define mp_montgomery_calc_normalization sp_mont_norm -#define MP_RADIX_HEX 16 +/* Macros mappings. */ +#define mp_isodd sp_isodd +#define mp_iseven sp_iseven +#define mp_iszero sp_iszero +#define mp_isone sp_isone +#define mp_isword sp_isword +#define mp_abs sp_abs +#define mp_isneg sp_isneg +#define mp_clamp sp_clamp -#define MP_GT 1 -#define MP_EQ 0 -#define MP_LT -1 +/* One to one mappings. */ +#define mp_init sp_init +#define mp_init_size sp_init_size +#define mp_init_multi sp_init_multi +#define mp_free sp_free +#define mp_grow sp_grow +#define mp_zero sp_zero +#define mp_clear sp_clear +#define mp_forcezero sp_forcezero +#define mp_copy sp_copy +#define mp_init_copy sp_init_copy +#define mp_exch sp_exch +#define mp_cond_swap_ct sp_cond_swap_ct +#define mp_cmp_mag sp_cmp_mag +#define mp_cmp sp_cmp +#define mp_count_bits sp_count_bits +#define mp_cnt_lsb sp_cnt_lsb +#define mp_leading_bit sp_leading_bit +#define mp_set_bit sp_set_bit +#define mp_2expt sp_2expt +#define mp_set sp_set +#define mp_set_int sp_set_int +#define mp_cmp_d sp_cmp_d +#define mp_add_d sp_add_d +#define mp_sub_d sp_sub_d +#define mp_mul_d sp_mul_d +#define mp_div_d sp_div_d +#define mp_mod_d sp_mod_d +#define mp_div_2_mod_ct sp_div_2_mod_ct +#define mp_div_2 sp_div_2 +#define mp_add sp_add +#define mp_sub sp_sub +#define mp_addmod sp_addmod +#define mp_submod sp_submod +#define mp_addmod_ct sp_addmod_ct +#define mp_submod_ct sp_submod_ct +#define mp_lshd sp_lshd +#define mp_rshd sp_rshd +#define mp_div sp_div +#define mp_mod sp_mod +#define mp_mul sp_mul +#define mp_mulmod sp_mulmod +#define mp_invmod sp_invmod +#define mp_invmod_mont_ct sp_invmod_mont_ct +#define mp_exptmod_ex sp_exptmod_ex +#define mp_exptmod sp_exptmod +#define mp_exptmod_nct sp_exptmod_nct +#define mp_div_2d sp_div_2d +#define mp_mod_2d sp_mod_2d +#define mp_mul_2d sp_mul_2d +#define mp_sqr sp_sqr +#define mp_sqrmod sp_sqrmod -#define MP_OKAY 0 -#define MP_MEM -2 -#define MP_VAL -3 -#define FP_WOULDBLOCK -4 +#define mp_unsigned_bin_size sp_unsigned_bin_size +#define mp_read_unsigned_bin sp_read_unsigned_bin +#define mp_to_unsigned_bin sp_to_unsigned_bin +#define mp_to_unsigned_bin_len sp_to_unsigned_bin_len +#define mp_to_unsigned_bin_at_pos sp_to_unsigned_bin_at_pos +#define mp_read_radix sp_read_radix +#define mp_tohex sp_tohex +#define mp_todecimal sp_todecimal +#define mp_toradix sp_toradix +#define mp_radix_size sp_radix_size -#define DIGIT_BIT SP_WORD_SIZE -#define MP_MASK SP_MASK +#define mp_rand_prime sp_rand_prime +#define mp_prime_is_prime sp_prime_is_prime +#define mp_prime_is_prime_ex sp_prime_is_prime_ex +#define mp_gcd sp_gcd +#define mp_lcm sp_lcm -#define CheckFastMathSettings() 1 - -#define mp_free sp_free - -#define mp_isodd sp_isodd -#define mp_iseven sp_iseven -#define mp_iszero sp_iszero -#define mp_isone sp_isone -#define mp_abs sp_abs - -#define mp_init sp_init -#define mp_init_multi sp_init_multi -#define mp_clear sp_clear -#define mp_read_unsigned_bin sp_read_unsigned_bin -#define mp_unsigned_bin_size sp_unsigned_bin_size -#define mp_read_radix sp_read_radix -#define mp_cmp sp_cmp -#define mp_count_bits sp_count_bits -#define mp_leading_bit sp_leading_bit -#define mp_to_unsigned_bin sp_to_unsigned_bin -#define mp_to_unsigned_bin_len sp_to_unsigned_bin_len -#define mp_forcezero sp_forcezero -#define mp_copy sp_copy -#define mp_set sp_set -#define mp_clamp sp_clamp -#define mp_grow sp_grow -#define mp_sub_d sp_sub_d -#define mp_cmp_d sp_cmp_d -#define mp_sub sp_sub -#define mp_mod sp_mod -#define mp_zero sp_zero -#define mp_add_d sp_add_d -#define mp_lshd sp_lshd -#define mp_add sp_add -#define mp_set_int sp_set_int -#define mp_tohex sp_tohex -#define mp_set_bit sp_set_bit -#define mp_2expt sp_2expt -#define mp_rand_prime sp_rand_prime -#define mp_mul sp_mul -#define mp_mulmod sp_mulmod -#define mp_gcd sp_gcd -#define mp_invmod sp_invmod -#define mp_lcm sp_lcm -#define mp_exptmod sp_exptmod -#define mp_exptmod_nct sp_exptmod -#define mp_prime_is_prime sp_prime_is_prime -#define mp_prime_is_prime_ex sp_prime_is_prime_ex -#define mp_exch sp_exch -#define get_digit_count sp_get_digit_count -#define mp_init_copy sp_init_copy -#define mp_rshb(A,x) sp_rshb(A,x,A) -#define mp_mul_d sp_mul_d +#endif +#ifdef __cplusplus +} /* extern "C" */ #endif #endif /* WOLF_CRYPT_SP_H */ - diff --git a/source/libs/libwolfssl/wolfcrypt/types.h b/source/libs/libwolfssl/wolfcrypt/types.h index 59d493cf..8862c5a8 100644 --- a/source/libs/libwolfssl/wolfcrypt/types.h +++ b/source/libs/libwolfssl/wolfcrypt/types.h @@ -154,6 +154,7 @@ decouple library dependencies with standard string, memory and so on. #ifdef WORD64_AVAILABLE #define WOLFCRYPT_SLOW_WORD64 #endif + #define WC_32BIT_CPU #endif #elif defined(WC_16BIT_CPU) @@ -167,6 +168,7 @@ decouple library dependencies with standard string, memory and so on. typedef word32 wolfssl_word; #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as mp_digit, no 64 bit type so make mp_digit 16 bit */ + #define WC_32BIT_CPU #endif enum { @@ -493,11 +495,12 @@ decouple library dependencies with standard string, memory and so on. #define XSTRLEN(s1) strlen((s1)) #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n)) - /* strstr, strncmp, and strncat only used by wolfSSL proper, + /* strstr, strncmp, strcmp, and strncat only used by wolfSSL proper, * not required for wolfCrypt only */ #define XSTRSTR(s1,s2) strstr((s1),(s2)) #define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n)) #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n)) + #define XSTRCMP(s1,s2) strcmp((s1),(s2)) #define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n)) #ifdef USE_WOLF_STRSEP @@ -647,9 +650,12 @@ decouple library dependencies with standard string, memory and so on. #include #endif #if defined(HAVE_ECC) || defined(HAVE_OCSP) || \ - defined(WOLFSSL_KEY_GEN) || !defined(NO_DSA) + defined(WOLFSSL_KEY_GEN) || !defined(NO_DSA) || \ + defined(OPENSSL_EXTRA) #define XTOUPPER(c) toupper((c)) - #define XISALPHA(c) isalpha((c)) + #endif + #ifdef OPENSSL_ALL + #define XISALNUM(c) isalnum((c)) #endif /* needed by wolfSSL_check_domain_name() */ #define XTOLOWER(c) tolower((c)) @@ -784,7 +790,8 @@ decouple library dependencies with standard string, memory and so on. /* hash types */ enum wc_HashType { - #if defined(HAVE_SELFTEST) || defined(HAVE_FIPS) + #if defined(HAVE_SELFTEST) || defined(HAVE_FIPS) && \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION <= 2)) /* In selftest build, WC_* types are not mapped to WC_HASH_TYPE types. * Values here are based on old selftest hmac.h enum, with additions. * These values are fixed for backwards FIPS compatibility */ @@ -858,8 +865,10 @@ decouple library dependencies with standard string, memory and so on. WC_PK_TYPE_CURVE25519 = 7, WC_PK_TYPE_RSA_KEYGEN = 8, WC_PK_TYPE_EC_KEYGEN = 9, + WC_PK_TYPE_RSA_CHECK_PRIV_KEY = 10, + WC_PK_TYPE_EC_CHECK_PRIV_KEY = 11, - WC_PK_TYPE_MAX = WC_PK_TYPE_EC_KEYGEN + WC_PK_TYPE_MAX = WC_PK_TYPE_EC_CHECK_PRIV_KEY }; diff --git a/source/libs/libwolfssl/wolfcrypt/wc_pkcs11.h b/source/libs/libwolfssl/wolfcrypt/wc_pkcs11.h index 15a0384d..15412bfb 100644 --- a/source/libs/libwolfssl/wolfcrypt/wc_pkcs11.h +++ b/source/libs/libwolfssl/wolfcrypt/wc_pkcs11.h @@ -67,7 +67,6 @@ enum Pkcs11KeyType { PKCS11_KEY_TYPE_EC, }; - WOLFSSL_API int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap); WOLFSSL_API void wc_Pkcs11_Finalize(Pkcs11Dev* dev); diff --git a/source/libs/libwolfssl/wolfcrypt/wc_port.h b/source/libs/libwolfssl/wolfcrypt/wc_port.h index e34bd24f..5564d993 100644 --- a/source/libs/libwolfssl/wolfcrypt/wc_port.h +++ b/source/libs/libwolfssl/wolfcrypt/wc_port.h @@ -81,6 +81,7 @@ _Pragma("GCC diagnostic ignored \"-Wsign-compare\""); _Pragma("GCC diagnostic ignored \"-Wpointer-sign\""); _Pragma("GCC diagnostic ignored \"-Wbad-function-cast\""); + _Pragma("GCC diagnostic ignored \"-Wdiscarded-qualifiers\""); #include #include @@ -88,6 +89,7 @@ #include #include #include + #include #ifndef SINGLE_THREADED #include #endif @@ -99,19 +101,52 @@ #else #include #endif - #define SAVE_VECTOR_REGISTERS() kernel_fpu_begin() - #define RESTORE_VECTOR_REGISTERS() kernel_fpu_end() + #ifndef SAVE_VECTOR_REGISTERS + #define SAVE_VECTOR_REGISTERS() kernel_fpu_begin() + #endif + #ifndef RESTORE_VECTOR_REGISTERS + #define RESTORE_VECTOR_REGISTERS() kernel_fpu_end() + #endif #elif defined(WOLFSSL_ARMASM) #include - #define SAVE_VECTOR_REGISTERS() ({ preempt_disable(); fpsimd_preserve_current_state(); }) - #define RESTORE_VECTOR_REGISTERS() ({ fpsimd_restore_current_state(); preempt_enable(); }) + #ifndef SAVE_VECTOR_REGISTERS + #define SAVE_VECTOR_REGISTERS() ({ preempt_disable(); fpsimd_preserve_current_state(); }) + #endif + #ifndef RESTORE_VECTOR_REGISTERS + #define RESTORE_VECTOR_REGISTERS() ({ fpsimd_restore_current_state(); preempt_enable(); }) + #endif #else - #define SAVE_VECTOR_REGISTERS() ({}) - #define RESTORE_VECTOR_REGISTERS() ({}) + #ifndef SAVE_VECTOR_REGISTERS + #define SAVE_VECTOR_REGISTERS() ({}) + #endif + #ifndef RESTORE_VECTOR_REGISTERS + #define RESTORE_VECTOR_REGISTERS() ({}) + #endif #endif _Pragma("GCC diagnostic pop"); + /* Linux headers define these using C expressions, but we need + * them to be evaluable by the preprocessor, for use in sp_int.h. + */ + _Static_assert(sizeof(ULONG_MAX) == 8, "WOLFSSL_LINUXKM supported only on targets with 64 bit long words."); + #undef UCHAR_MAX + #define UCHAR_MAX 255 + #undef USHRT_MAX + #define USHRT_MAX 65535 + #undef UINT_MAX + #define UINT_MAX 4294967295U + #undef ULONG_MAX + #define ULONG_MAX 18446744073709551615UL + #undef ULLONG_MAX + #define ULLONG_MAX ULONG_MAX + #undef INT_MAX + #define INT_MAX 2147483647 + #undef LONG_MAX + #define LONG_MAX 9223372036854775807L + #undef LLONG_MAX + #define LLONG_MAX LONG_MAX + /* remove this multifariously conflicting macro, picked up from * Linux arch//include/asm/current.h. */ @@ -122,9 +157,17 @@ */ #define _MM_MALLOC_H_INCLUDED +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + /* kvmalloc()/kvfree() and friends added in linux commit a7c3e901 */ + #define malloc(x) kvmalloc(x, GFP_KERNEL) + #define free(x) kvfree(x) + void *lkm_realloc(void *ptr, size_t newsize); + #define realloc(x, y) lkm_realloc(x, y) +#else #define malloc(x) kmalloc(x, GFP_KERNEL) #define free(x) kfree(x) #define realloc(x,y) krealloc(x, y, GFP_KERNEL) +#endif /* min() and max() in linux/kernel.h over-aggressively type-check, producing * myriad spurious -Werrors throughout the codebase. @@ -157,8 +200,10 @@ #else /* ! WOLFSSL_LINUXKM */ - #ifdef BUILDING_WOLFSSL + #ifndef SAVE_VECTOR_REGISTERS #define SAVE_VECTOR_REGISTERS() do{}while(0) + #endif + #ifndef RESTORE_VECTOR_REGISTERS #define RESTORE_VECTOR_REGISTERS() do{}while(0) #endif @@ -193,6 +238,8 @@ /* do nothing, just don't pick Unix */ #elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS) /* do nothing */ +#elif defined(RTTHREAD) + /* do nothing */ #elif defined(EBSNET) /* do nothing */ #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) @@ -298,6 +345,9 @@ #include "FreeRTOS.h" #include "semphr.h" typedef SemaphoreHandle_t wolfSSL_Mutex; + #elif defined (RTTHREAD) + #include "rtthread.h" + typedef rt_mutex_t wolfSSL_Mutex; #elif defined(WOLFSSL_SAFERTOS) typedef struct wolfSSL_Mutex { signed char mutexBuffer[portQUEUE_OVERHEAD_BYTES]; @@ -409,6 +459,11 @@ WOLFSSL_API int wc_SetMutexCb(mutex_cb* cb); WOLFSSL_API int wolfCrypt_Init(void); WOLFSSL_API int wolfCrypt_Cleanup(void); +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + WOLFSSL_API long wolfCrypt_heap_peakAllocs_checkpoint(void); + WOLFSSL_API long wolfCrypt_heap_peakBytes_checkpoint(void); +#endif + /* FILESYSTEM SECTION */ /* filesystem abstraction layer, used by ssl.c */ @@ -564,6 +619,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #else #define XFOPEN fopen #endif + #define XFDOPEN fdopen #define XFSEEK fseek #define XFTELL ftell #define XREWIND rewind @@ -579,6 +635,9 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #include #include #include + #define XWRITE write + #define XREAD read + #define XCLOSE close #endif #endif @@ -786,7 +845,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #ifdef BUILDING_WOLFSSL /* includes are all above, with incompatible warnings masked out. */ - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) + #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0) typedef __kernel_time_t time_t; #else typedef __kernel_time64_t time_t; diff --git a/source/network/picohttpparser.c b/source/network/picohttpparser.c index f16c0924..5e5783ab 100644 --- a/source/network/picohttpparser.c +++ b/source/network/picohttpparser.c @@ -449,7 +449,7 @@ static const char *parse_response(const char *buf, const char *buf_end, int *min } PARSE_INT_3(status); - /* get message includig preceding space */ + /* get message including preceding space */ if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) { return NULL; }