diff --git a/configure.ac b/configure.ac index 6f397160..617adfcf 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl Copyright (C) 2017-2023 Ulrich Telle , Vadim Zeitlin dnl dnl This file is covered by the same licence as the entire wxSQLite3 package. -AC_INIT([wxsqlite3], [4.9.7], [ulrich@telle-online.de]) +AC_INIT([wxsqlite3], [4.9.8], [ulrich@telle-online.de]) dnl This is the version tested with, might work with earlier ones. AC_PREREQ([2.69]) @@ -82,13 +82,23 @@ AC_ARG_WITH([rc4], AS_IF([test "x$with_rc4" = xno], [AC_DEFINE([WXSQLITE3_HAVE_CIPHER_RC4], [0], [Define if you have RC4 disabled])]) +AC_ARG_WITH([ascon128], + [AS_HELP_STRING([--without-ascon128], + [Disable support for Ascon 128 Encryption])], + [], + [with_ascon128=yes]) + +AS_IF([test "x$with_ascon128" = xno], + [AC_DEFINE([WXSQLITE3_HAVE_CIPHER_ASCON128], [0], [Define if you have Ascon 128 disabled])]) + AC_ARG_ENABLE(codec, [ --enable-codec[=] Specify the codec type: aes128: AES 128 Bit CBC Encryption aes256: AES 256 Bit CBC Encryption chacha20 [default]: ChaCha20-Poly1305 Encryption sqlcipher: SQLCipher Encryption - rc4: RC4 Encryption], + rc4: RC4 Encryption + ascon128: Ascon 128 Encryption], [if test "x$enableval" = "xaes128" && test "x$with_aes128cbc" = xyes ; then codec_type=CODEC_TYPE_AES128 elif test "x$enableval" = "xaes256" && test "x$with_aes256cbc" = xyes ; then @@ -99,6 +109,8 @@ AC_ARG_ENABLE(codec, codec_type=CODEC_TYPE_SQLCIPHER elif test "x$enableval" = "xrc4" && test "x$with_rc4" = xyes ; then codec_type=CODEC_TYPE_RC4 + elif test "x$enableval" = "xascon128" && test "x$with_ascon128" = xyes ; then + codec_type=CODEC_TYPE_ASCON128 else echo echo "Error!" @@ -112,7 +124,8 @@ AS_IF([test "x$with_aes128cbc" = xno && test "x$with_aes256cbc" = xno && test "x$with_chacha20" = xno && test "x$with_sqlcipher" = xno && - test "x$with_rc4" = xno], + test "x$with_rc4" = xno && + test "x$with_ascon128" = xno], [AC_DEFINE([WXSQLITE3_HAVE_CODEC], [0], [All ciphers disabled so encryption is disabled])]) dnl We only need the libraries above for the main library itself, but the diff --git a/include/wx/wxsqlite3.h b/include/wx/wxsqlite3.h index ad8b2dd6..f3d6e4ee 100644 --- a/include/wx/wxsqlite3.h +++ b/include/wx/wxsqlite3.h @@ -38,7 +38,8 @@ enum wxSQLite3CipherType WXSQLITE_CIPHER_AES256, WXSQLITE_CIPHER_CHACHA20, WXSQLITE_CIPHER_SQLCIPHER, - WXSQLITE_CIPHER_RC4 + WXSQLITE_CIPHER_RC4, + WXSQLITE_CIPHER_ASCON128 }; #define WXSQLITE_ERROR 1000 @@ -133,6 +134,7 @@ enum wxSQLite3StatementStatus #define WXSQLITE_DIRECTONLY 0x000080000 #define WXSQLITE_SUBTYPE 0x000100000 #define WXSQLITE_INNOCUOUS 0x000200000 +#define WXSQLITE_RESULT_SUBTYPE 0x001000000 inline void operator++(wxSQLite3LimitType& value) { @@ -1221,6 +1223,73 @@ class WXDLLIMPEXP_SQLITE3 wxSQLite3CipherRC4 : public wxSQLite3Cipher bool m_legacy; ///< Flag for legacy mode }; +/// Cipher class representing Ascon-128 encryption with Ascon tag +class WXDLLIMPEXP_SQLITE3 wxSQLite3CipherAscon128 : public wxSQLite3Cipher +{ +public: + /// Constructor + wxSQLite3CipherAscon128(); + + /// Copy constructor + wxSQLite3CipherAscon128(const wxSQLite3CipherAscon128& cipher); + + /// Destructor + virtual ~wxSQLite3CipherAscon128(); + + /// Initialize the cipher instance based on global default settings + /** + * The parameters of the cipher instance are initialize with the global default settings of the associated cipher type. + * \return true if the cipher instance could be initialized successfully, false otherwise + */ + virtual bool InitializeFromGlobalDefault(); + + /// Initialize the cipher instance based on current settings + /** + * The parameters of the cipher instance are initialize with the current settings of the associated cipher type + * as defined in the given database connection. + * \param db database instance representing a database connection + * \return true if the cipher instance could be initialized successfully, false otherwise + */ + virtual bool InitializeFromCurrent(wxSQLite3Database& db); + + /// Initialize the cipher instance based on current default settings + /** + * The parameters of the cipher instance are initialize with the current default settings of the associated cipher type + * as defined in the given database connection. + * \param db database instance representing a database connection + * \return true if the cipher instance could be initialized successfully, false otherwise + */ + virtual bool InitializeFromCurrentDefault(wxSQLite3Database& db); + + /// Apply the cipher parameters to a database connection + /** + * The parameters of the cipher instance are applied to the given database connection. + * \param db database instance representing a database connection + * \return true if the cipher parameters could be applied successfully, false otherwise + */ + virtual bool Apply(wxSQLite3Database& db) const; + virtual bool Apply(void* dbHandle) const; + +#if 0 + // Currently no legacy mode available + /// Set legacy mode + void SetLegacy(bool legacy) { m_legacy = legacy; } + + /// Get legacy mode + bool GetLegacy() const { return m_legacy; } +#endif + + /// Set iteration count of KDF function for ordinary key + void SetKdfIter(int kdfIter) { m_kdfIter = kdfIter; } + + /// Get iteration count of KDF function for ordinary key + int GetKdfIter() const { return m_kdfIter; } + +private: + bool m_legacy; ///< Flag for legacy mode + int m_kdfIter; ///< Iteration count for KDF function +}; + /// Interface for a user defined hook function /** diff --git a/include/wx/wxsqlite3_version.h b/include/wx/wxsqlite3_version.h index 20793f62..400a9d69 100644 --- a/include/wx/wxsqlite3_version.h +++ b/include/wx/wxsqlite3_version.h @@ -14,8 +14,8 @@ #define WXSQLITE3_MAJOR_VERSION 4 #define WXSQLITE3_MINOR_VERSION 9 -#define WXSQLITE3_RELEASE_NUMBER 7 +#define WXSQLITE3_RELEASE_NUMBER 8 #define WXSQLITE3_SUBRELEASE_NUMBER 0 -#define WXSQLITE3_VERSION_STRING "wxSQLite3 4.9.7" +#define WXSQLITE3_VERSION_STRING "wxSQLite3 4.9.8" #endif // WXSQLITE3_VERSION_H_ diff --git a/include/wx/wxsqlite3def.h b/include/wx/wxsqlite3def.h index 69fd4317..18e74e95 100644 --- a/include/wx/wxsqlite3def.h +++ b/include/wx/wxsqlite3def.h @@ -46,6 +46,13 @@
+
4.9.8 - November 2023
+
+Upgrade to SQLite3 Multiple Ciphers version 1.8.0 (SQLite version 3.44.1)
+Added new cipher scheme Ascon-128 (Lightweight Authenticated Encryption) + +
+
4.9.7 - November 2023
Upgrade to SQLite3 Multiple Ciphers version 1.7.4 (SQLite version 3.44.0)
diff --git a/readme.md b/readme.md index b7b632a5..323f0f03 100644 --- a/readme.md +++ b/readme.md @@ -28,7 +28,8 @@ Currently the following encryption schemes are supported: - AES 256 Bit CBC - No HMAC ([wxSQLite3](https://github.com/utelle/wxsqlite3)) - ChaCha20 - Poly1305 HMAC ([sqleet](https://github.com/resilar/sqleet)) (**default**) - AES 256 Bit CBC - SHA1/SHA256/SHA512 HMAC ([SQLCipher](https://www.zetetic.net/sqlcipher/) versions 1 - 4) -- RC4 - No HMAC ([System.Data.SQLite](http://system.data.sqlite.org/)) +- RC4 - No HMAC ([System.Data.SQLite](https://system.data.sqlite.org/)) +- Ascon 128 - Ascon Tag ([Ascon](https://ascon.iaik.tugraz.at/)) (since version 4.9.8) ## Important Notes @@ -48,6 +49,9 @@ Since August 2020 a new implementation of an encryption extension, capable of su ## Version history +* 4.9.8 - *November 2023* + - Upgrade to SQLite3 Multiple Ciphers version 1.8.0 (SQLite version 3.44.1) + - Added new cipher scheme Ascon-128 (Lightweight Authenticated Encryption) * 4.9.7 - *November 2023* - Upgrade to SQLite3 Multiple Ciphers version 1.7.4 (SQLite version 3.44.0) - Prevent crashes due to uninitialized cipher tables (issue #113) diff --git a/samples/treeview/treeviewapp.cpp b/samples/treeview/treeviewapp.cpp index e340362d..869d7546 100644 --- a/samples/treeview/treeviewapp.cpp +++ b/samples/treeview/treeviewapp.cpp @@ -102,6 +102,14 @@ TreeviewSampleApp::OnInit() int TreeviewSampleApp::OnExit() { + try + { + m_db.Close(); + } + catch (wxSQLite3Exception& e) + { + } + wxSQLite3Database::ShutdownSQLite(); return wxApp::OnExit(); } diff --git a/src/sqlite3mc_amalgamation.c b/src/sqlite3mc_amalgamation.c index 89bc173d..42d85f2c 100644 --- a/src/sqlite3mc_amalgamation.c +++ b/src/sqlite3mc_amalgamation.c @@ -67,6 +67,13 @@ void sqlite3mc_shutdown(void); #if !defined(_CRT_RAND_S) #define _CRT_RAND_S #endif + +#else /* !WIN32 */ + +/* Define this before is included to */ +/* retrieve memset_s() declaration if available. */ +#define __STDC_WANT_LIB_EXT1__ 1 + #endif #ifndef SQLITE_API @@ -104,7 +111,7 @@ extern SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*); /*** Begin of #include "sqlite3patched.c" ***/ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.44.0. By combining all the individual C code files into this +** version 3.44.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -122,7 +129,7 @@ extern SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*); ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** 17129ba1ff7f0daf37100ee82d507aef7827. +** d295f48e8f367b066b881780c98bdf980a1d. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 @@ -563,9 +570,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.44.0" -#define SQLITE_VERSION_NUMBER 3044000 -#define SQLITE_SOURCE_ID "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad81301" +#define SQLITE_VERSION "3.44.1" +#define SQLITE_VERSION_NUMBER 3044001 +#define SQLITE_SOURCE_ID "2023-11-22 14:18:12 d295f48e8f367b066b881780c98bdf980a1d550397d5ba0b0e49842c95b3e8b4" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -5990,13 +5997,27 @@ SQLITE_API int sqlite3_create_window_function( **
** ** [[SQLITE_SUBTYPE]]
SQLITE_SUBTYPE
-** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** Specifying this flag makes no difference for scalar or aggregate user -** functions. However, if it is not specified for a user-defined window -** function, then any sub-types belonging to arguments passed to the window -** function may be discarded before the window function is called (i.e. -** sqlite3_value_subtype() will always return 0). +** This flag instructs SQLite to omit some corner-case optimizations that +** might disrupt the operation of the [sqlite3_value_subtype()] function, +** causing it to return zero rather than the correct subtype(). +** SQL functions that invokes [sqlite3_value_subtype()] should have this +** property. If the SQLITE_SUBTYPE property is omitted, then the return +** value from [sqlite3_value_subtype()] might sometimes be zero even though +** a non-zero subtype was specified by the function argument expression. +** +** [[SQLITE_RESULT_SUBTYPE]]
SQLITE_RESULT_SUBTYPE
+** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call +** [sqlite3_result_subtype()] to cause a sub-type to be associated with its +** result. +** Every function that invokes [sqlite3_result_subtype()] should have this +** property. If it does not, then the call to [sqlite3_result_subtype()] +** might become a no-op if the function is used as term in an +** [expression index]. On the other hand, SQL functions that never invoke +** [sqlite3_result_subtype()] should avoid setting this property, as the +** purpose of this property is to disable certain optimizations that are +** incompatible with subtypes. **
**
*/ @@ -6004,6 +6025,7 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 +#define SQLITE_RESULT_SUBTYPE 0x001000000 /* ** CAPI3REF: Deprecated Functions @@ -6200,6 +6222,12 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. +** +** Every [application-defined SQL function] that invoke this interface +** should include the [SQLITE_SUBTYPE] property in the text +** encoding argument when the function is [sqlite3_create_function|registered]. +** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() +** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -6330,14 +6358,22 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); **
  • ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or **
  • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^ +** allocation error occurs.)^ +**
  • ^(during the original sqlite3_set_auxdata() call if the function +** is evaluated during query planning instead of during query execution, +** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ ** -** Note the last bullet in particular. The destructor X in +** Note the last two bullets in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. +** sqlite3_set_auxdata() has been called. Furthermore, a call to +** sqlite3_get_auxdata() that occurs immediately after a corresponding call +** to sqlite3_set_auxdata() might still return NULL if an out-of-memory +** condition occurred during the sqlite3_set_auxdata() call or if the +** function is being evaluated during query planning rather than during +** query execution. ** ** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal @@ -6611,6 +6647,20 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. +** +** Every [application-defined SQL function] that invokes this interface +** should include the [SQLITE_RESULT_SUBTYPE] property in its +** text encoding argument when the SQL function is +** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] +** property is omitted from the function that invokes sqlite3_result_subtype(), +** then in some cases the sqlite3_result_subtype() might fail to set +** the result subtype. +** +** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any +** SQL function that invokes the sqlite3_result_subtype() interface +** and that does not have the SQLITE_RESULT_SUBTYPE property will raise +** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 +** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); @@ -17926,14 +17976,15 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */ -/* 0x8000 -- available for reuse */ +#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ -#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ +/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */ #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ #define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */ +/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */ #define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ /* Identifier numbers for each in-line function */ @@ -18025,9 +18076,10 @@ struct FuncDestructor { #define MFUNCTION(zName, nArg, xPtr, xFunc) \ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} } -#define JFUNCTION(zName, nArg, iArg, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|\ - SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ +#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, iArg, xFunc) \ + {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\ + SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\ + ((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } #define INLINE_FUNC(zName, nArg, iArg, mFlags) \ {nArg, SQLITE_FUNC_BUILTIN|\ @@ -29568,7 +29620,7 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); -#elif MSVC_VERSION>=1300 +#elif MSVC_VERSION>=1400 _ReadWriteBarrier(); #elif defined(MemoryBarrier) MemoryBarrier(); @@ -61573,10 +61625,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( */ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){ Pager *pPager; + const char *p; while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ zName--; } - pPager = *(Pager**)(zName - 4 - sizeof(Pager*)); + p = zName - 4 - sizeof(Pager*); + assert( EIGHT_BYTE_ALIGNMENT(p) ); + pPager = *(Pager**)p; return pPager->fd; } @@ -83537,7 +83592,7 @@ static int valueFromFunction( #endif assert( pFunc ); if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) + || (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0 ){ return SQLITE_OK; } @@ -90078,6 +90133,18 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubt #ifdef SQLITE_ENABLE_API_ARMOR if( pCtx==0 ) return; #endif +#if defined(SQLITE_STRICT_SUBTYPE) && SQLITE_STRICT_SUBTYPE+0!=0 + if( pCtx->pFunc!=0 + && (pCtx->pFunc->funcFlags & SQLITE_RESULT_SUBTYPE)==0 + ){ + char zErr[200]; + sqlite3_snprintf(sizeof(zErr), zErr, + "misuse of sqlite3_result_subtype() by %s()", + pCtx->pFunc->zName); + sqlite3_result_error(pCtx, zErr, -1); + return; + } +#endif /* SQLITE_STRICT_SUBTYPE */ pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; @@ -100447,7 +100514,7 @@ case OP_VCheck: { /* out2 */ pTab = pOp->p4.pTab; assert( pTab!=0 ); assert( IsVirtual(pTab) ); - assert( pTab->u.vtab.p!=0 ); + if( pTab->u.vtab.p==0 ) break; pVtab = pTab->u.vtab.p->pVtab; assert( pVtab!=0 ); pModule = pVtab->pModule; @@ -114043,8 +114110,8 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB */ SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){ return sqlite3ExprCompare(0, - sqlite3ExprSkipCollateAndLikely(pA), - sqlite3ExprSkipCollateAndLikely(pB), + sqlite3ExprSkipCollate(pA), + sqlite3ExprSkipCollate(pB), iTab); } @@ -147736,10 +147803,11 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ SrcList *pTabList; SrcItem *pFrom; - assert( p->selFlags & SF_Resolved ); if( p->selFlags & SF_HasTypeInfo ) return; p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; + testcase( (p->selFlags & SF_Resolved)==0 ); + assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT ); pTabList = p->pSrc; for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; @@ -148761,6 +148829,7 @@ SQLITE_PRIVATE int sqlite3Select( TREETRACE(0x1000,pParse,p, ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); + unsetJoinExpr(p->pWhere, pItem->iCursor, 0); } } if( pItem->fg.jointype & JT_LTORJ ){ @@ -148775,17 +148844,15 @@ SQLITE_PRIVATE int sqlite3Select( TREETRACE(0x1000,pParse,p, ("RIGHT-JOIN simplifies to JOIN on term %d\n",j)); pI2->fg.jointype &= ~(JT_RIGHT|JT_OUTER); + unsetJoinExpr(p->pWhere, pI2->iCursor, 1); } } } - for(j=pTabList->nSrc-1; j>=i; j--){ + for(j=pTabList->nSrc-1; j>=0; j--){ pTabList->a[j].fg.jointype &= ~JT_LTORJ; if( pTabList->a[j].fg.jointype & JT_RIGHT ) break; } } - assert( pItem->iCursor>=0 ); - unsetJoinExpr(p->pWhere, pItem->iCursor, - pTabList->a[0].fg.jointype & JT_LTORJ); } /* No further action if this term of the FROM clause is not a subquery */ @@ -166189,6 +166256,20 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( continue; } if( sqlite3ExprIsConstant(pExpr) ) continue; + if( pExpr->op==TK_FUNCTION ){ + /* Functions that might set a subtype should not be replaced by the + ** value taken from an expression index since the index omits the + ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */ + int n; + FuncDef *pDef; + sqlite3 *db = pParse->db; + assert( ExprUseXList(pExpr) ); + n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; + pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); + if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ + continue; + } + } p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxEpr; @@ -168371,7 +168452,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ assert( ExprUseXList(pWin->pOwner) ); assert( pWin->pWFunc!=0 ); pArgs = pWin->pOwner->x.pList; - if( pWin->pWFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ + if( pWin->pWFunc->funcFlags & SQLITE_SUBTYPE ){ selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); pWin->bExprArgs = 1; @@ -179545,7 +179626,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY| - SQLITE_SUBTYPE|SQLITE_INNOCUOUS); + SQLITE_SUBTYPE|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE); enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But @@ -203134,13 +203215,19 @@ static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){ zIn++; N -= 2; while( N>0 ){ - for(i=0; i0 ){ jsonAppendRawNZ(p, zIn, i); zIn += i; N -= i; if( N==0 ) break; } + if( zIn[0]=='"' ){ + jsonAppendRawNZ(p, "\\\"", 2); + zIn++; + N--; + continue; + } assert( zIn[0]=='\\' ); switch( (u8)zIn[1] ){ case '\'': @@ -203535,7 +203622,8 @@ static void jsonReturnJson( JsonParse *pParse, /* The complete JSON */ JsonNode *pNode, /* Node to return */ sqlite3_context *pCtx, /* Return value for this function */ - int bGenerateAlt /* Also store the rendered text in zAlt */ + int bGenerateAlt, /* Also store the rendered text in zAlt */ + int omitSubtype /* Do not call sqlite3_result_subtype() */ ){ JsonString s; if( pParse->oom ){ @@ -203550,7 +203638,7 @@ static void jsonReturnJson( pParse->nAlt = s.nUsed; } jsonResult(&s); - sqlite3_result_subtype(pCtx, JSON_SUBTYPE); + if( !omitSubtype ) sqlite3_result_subtype(pCtx, JSON_SUBTYPE); } } @@ -203591,7 +203679,8 @@ static u32 jsonHexToInt4(const char *z){ static void jsonReturn( JsonParse *pParse, /* Complete JSON parse tree */ JsonNode *pNode, /* Node to return */ - sqlite3_context *pCtx /* Return value for this function */ + sqlite3_context *pCtx, /* Return value for this function */ + int omitSubtype /* Do not call sqlite3_result_subtype() */ ){ switch( pNode->eType ){ default: { @@ -203737,7 +203826,7 @@ static void jsonReturn( } case JSON_ARRAY: case JSON_OBJECT: { - jsonReturnJson(pParse, pNode, pCtx, 0); + jsonReturnJson(pParse, pNode, pCtx, 0, omitSubtype); break; } } @@ -205089,7 +205178,7 @@ static void jsonParseFunc( printf("iSubst = %u\n", p->iSubst); printf("iHold = %u\n", p->iHold); jsonDebugPrintNodeEntries(p->aNode, p->nNode); - jsonReturnJson(p, p->aNode, ctx, 1); + jsonReturnJson(p, p->aNode, ctx, 1, 0); } /* @@ -205275,15 +205364,14 @@ static void jsonExtractFunc( } if( pNode ){ if( flags & JSON_JSON ){ - jsonReturnJson(p, pNode, ctx, 0); + jsonReturnJson(p, pNode, ctx, 0, 0); }else{ - jsonReturn(p, pNode, ctx); - sqlite3_result_subtype(ctx, 0); + jsonReturn(p, pNode, ctx, 1); } } }else{ pNode = jsonLookup(p, zPath, 0, ctx); - if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx); + if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx, 0); } }else{ /* Two or more PATH arguments results in a JSON array with each @@ -205409,7 +205497,7 @@ static void jsonPatchFunc( if( pResult && pX->oom==0 ){ jsonDebugPrintParse(pX); jsonDebugPrintNode(pResult); - jsonReturnJson(pX, pResult, ctx, 0); + jsonReturnJson(pX, pResult, ctx, 0, 0); }else{ sqlite3_result_error_nomem(ctx); } @@ -205488,7 +205576,7 @@ static void jsonRemoveFunc( } } if( (pParse->aNode[0].jnFlags & JNODE_REMOVE)==0 ){ - jsonReturnJson(pParse, pParse->aNode, ctx, 1); + jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0); } remove_done: jsonDebugPrintParse(p); @@ -205617,7 +205705,7 @@ static void jsonReplaceFunc( jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); } } - jsonReturnJson(pParse, pParse->aNode, ctx, 1); + jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0); replace_err: jsonDebugPrintParse(pParse); jsonParseFree(pParse); @@ -205671,7 +205759,7 @@ static void jsonSetFunc( } } jsonDebugPrintParse(pParse); - jsonReturnJson(pParse, pParse->aNode, ctx, 1); + jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0); jsonSetDone: jsonParseFree(pParse); } @@ -206186,7 +206274,7 @@ static int jsonEachColumn( case JEACH_KEY: { if( p->i==0 ) break; if( p->eType==JSON_OBJECT ){ - jsonReturn(&p->sParse, pThis, ctx); + jsonReturn(&p->sParse, pThis, ctx, 0); }else if( p->eType==JSON_ARRAY ){ u32 iKey; if( p->bRecursive ){ @@ -206202,7 +206290,7 @@ static int jsonEachColumn( } case JEACH_VALUE: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; - jsonReturn(&p->sParse, pThis, ctx); + jsonReturn(&p->sParse, pThis, ctx, 0); break; } case JEACH_TYPE: { @@ -206213,7 +206301,7 @@ static int jsonEachColumn( case JEACH_ATOM: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; if( pThis->eType>=JSON_ARRAY ) break; - jsonReturn(&p->sParse, pThis, ctx); + jsonReturn(&p->sParse, pThis, ctx, 0); break; } case JEACH_ID: { @@ -206506,34 +206594,43 @@ static sqlite3_module jsonTreeModule = { SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ #ifndef SQLITE_OMIT_JSON static FuncDef aJsonFunc[] = { - JFUNCTION(json, 1, 0, jsonRemoveFunc), - JFUNCTION(json_array, -1, 0, jsonArrayFunc), - JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), - JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), - JFUNCTION(json_error_position,1, 0, jsonErrorFunc), - JFUNCTION(json_extract, -1, 0, jsonExtractFunc), - JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc), - JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc), - JFUNCTION(json_insert, -1, 0, jsonSetFunc), - JFUNCTION(json_object, -1, 0, jsonObjectFunc), - JFUNCTION(json_patch, 2, 0, jsonPatchFunc), - JFUNCTION(json_quote, 1, 0, jsonQuoteFunc), - JFUNCTION(json_remove, -1, 0, jsonRemoveFunc), - JFUNCTION(json_replace, -1, 0, jsonReplaceFunc), - JFUNCTION(json_set, -1, JSON_ISSET, jsonSetFunc), - JFUNCTION(json_type, 1, 0, jsonTypeFunc), - JFUNCTION(json_type, 2, 0, jsonTypeFunc), - JFUNCTION(json_valid, 1, 0, jsonValidFunc), -#if SQLITE_DEBUG - JFUNCTION(json_parse, 1, 0, jsonParseFunc), - JFUNCTION(json_test1, 1, 0, jsonTest1Func), + /* calls sqlite3_result_subtype() */ + /* | */ + /* Uses cache ______ | __ calls sqlite3_value_subtype() */ + /* | | | */ + /* Num args _________ | | | ___ Flags */ + /* | | | | | */ + /* | | | | | */ + JFUNCTION(json, 1, 1, 1, 0, 0, jsonRemoveFunc), + JFUNCTION(json_array, -1, 0, 1, 1, 0, jsonArrayFunc), + JFUNCTION(json_array_length, 1, 1, 0, 0, 0, jsonArrayLengthFunc), + JFUNCTION(json_array_length, 2, 1, 0, 0, 0, jsonArrayLengthFunc), + JFUNCTION(json_error_position,1, 1, 0, 0, 0, jsonErrorFunc), + JFUNCTION(json_extract, -1, 1, 1, 0, 0, jsonExtractFunc), + JFUNCTION(->, 2, 1, 1, 0, JSON_JSON, jsonExtractFunc), + JFUNCTION(->>, 2, 1, 0, 0, JSON_SQL, jsonExtractFunc), + JFUNCTION(json_insert, -1, 1, 1, 1, 0, jsonSetFunc), + JFUNCTION(json_object, -1, 0, 1, 1, 0, jsonObjectFunc), + JFUNCTION(json_patch, 2, 1, 1, 0, 0, jsonPatchFunc), + JFUNCTION(json_quote, 1, 0, 1, 1, 0, jsonQuoteFunc), + JFUNCTION(json_remove, -1, 1, 1, 0, 0, jsonRemoveFunc), + JFUNCTION(json_replace, -1, 1, 1, 1, 0, jsonReplaceFunc), + JFUNCTION(json_set, -1, 1, 1, 1, JSON_ISSET, jsonSetFunc), + JFUNCTION(json_type, 1, 1, 0, 0, 0, jsonTypeFunc), + JFUNCTION(json_type, 2, 1, 0, 0, 0, jsonTypeFunc), + JFUNCTION(json_valid, 1, 1, 0, 0, 0, jsonValidFunc), +#ifdef SQLITE_DEBUG + JFUNCTION(json_parse, 1, 1, 1, 0, 0, jsonParseFunc), + JFUNCTION(json_test1, 1, 1, 0, 1, 0, jsonTest1Func), #endif WAGGREGATE(json_group_array, 1, 0, 0, jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), + SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| + SQLITE_DETERMINISTIC), WAGGREGATE(json_group_object, 2, 0, 0, jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC) + SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| + SQLITE_DETERMINISTIC) }; sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); #endif @@ -236270,10 +236367,8 @@ static Fts5HashEntry *fts5HashEntryMerge( } /* -** Extract all tokens from hash table iHash and link them into a list -** in sorted order. The hash table is cleared before returning. It is -** the responsibility of the caller to free the elements of the returned -** list. +** Link all tokens from hash table iHash into a list in sorted order. The +** tokens are not removed from the hash table. */ static int fts5HashEntrySort( Fts5Hash *pHash, @@ -239139,6 +239234,14 @@ static void fts5SegIterHashInit( pLeaf->p = (u8*)pList; } } + + /* The call to sqlite3Fts5HashScanInit() causes the hash table to + ** fill the size field of all existing position lists. This means they + ** can no longer be appended to. Since the only scenario in which they + ** can be appended to is if the previous operation on this table was + ** a DELETE, by clearing the Fts5Index.bDelete flag we can avoid this + ** possibility altogether. */ + p->bDelete = 0; }else{ p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data), (const char*)pTerm, nTerm, (void**)&pLeaf, &nList @@ -240816,7 +240919,7 @@ static void fts5WriteAppendPoslistData( const u8 *a = aData; int n = nData; - assert( p->pConfig->pgsz>0 ); + assert( p->pConfig->pgsz>0 || p->rc!=SQLITE_OK ); while( p->rc==SQLITE_OK && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz ){ @@ -242076,8 +242179,9 @@ static int sqlite3Fts5IndexOptimize(Fts5Index *p){ assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); - assert( p->nContentlessDelete==0 ); + assert( p->rc!=SQLITE_OK || p->nContentlessDelete==0 ); pStruct = fts5StructureRead(p); + assert( p->rc!=SQLITE_OK || pStruct!=0 ); fts5StructureInvalidate(p); if( pStruct ){ @@ -247654,7 +247758,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad81301", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2023-11-22 14:18:12 d295f48e8f367b066b881780c98bdf980a1d550397d5ba0b0e49842c95b3e8b4", -1, SQLITE_TRANSIENT); } /* @@ -252761,7 +252865,7 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } ** Purpose: Header file for SQLite3 Multiple Ciphers compile-time configuration ** Author: Ulrich Telle ** Created: 2021-09-27 -** Copyright: (c) 2019-2022 Ulrich Telle +** Copyright: (c) 2019-2023 Ulrich Telle ** License: MIT */ @@ -252795,6 +252899,10 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } #define HAVE_CIPHER_RC4 WXSQLITE3_HAVE_CIPHER_RC4 #endif +#ifdef WXSQLITE3_HAVE_CIPHER_ASCON128 +#define HAVE_CIPHER_ASCON128 WXSQLITE3_HAVE_CIPHER_ASCON128 +#endif + /* ** Actual definitions of supported ciphers */ @@ -252818,6 +252926,10 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } #define HAVE_CIPHER_RC4 1 #endif +#ifndef HAVE_CIPHER_ASCON128 +#define HAVE_CIPHER_ASCON128 1 +#endif + /* ** Disable all built-in ciphers on request */ @@ -252832,11 +252944,13 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } #undef HAVE_CIPHER_CHACHA20 #undef HAVE_CIPHER_SQLCIPHER #undef HAVE_CIPHER_RC4 +#undef HAVE_CIPHER_ASCON128 #define HAVE_CIPHER_AES_128_CBC 0 #define HAVE_CIPHER_AES_256_CBC 0 #define HAVE_CIPHER_CHACHA20 0 #define HAVE_CIPHER_SQLCIPHER 0 #define HAVE_CIPHER_RC4 0 +#define HAVE_CIPHER_ASCON128 0 #endif /* @@ -252926,7 +253040,7 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } ** Purpose: Header file for SQLite3 Multiple Ciphers support ** Author: Ulrich Telle ** Created: 2020-03-01 -** Copyright: (c) 2019-2022 Ulrich Telle +** Copyright: (c) 2019-2023 Ulrich Telle ** License: MIT */ @@ -252953,10 +253067,10 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } #define SQLITE3MC_VERSION_H_ #define SQLITE3MC_VERSION_MAJOR 1 -#define SQLITE3MC_VERSION_MINOR 7 -#define SQLITE3MC_VERSION_RELEASE 4 +#define SQLITE3MC_VERSION_MINOR 8 +#define SQLITE3MC_VERSION_RELEASE 0 #define SQLITE3MC_VERSION_SUBRELEASE 0 -#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.7.4" +#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.8.0" #endif /* SQLITE3MC_VERSION_H_ */ /*** End of #include "sqlite3mc_version.h" ***/ @@ -253115,9 +253229,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.44.0" -#define SQLITE_VERSION_NUMBER 3044000 -#define SQLITE_SOURCE_ID "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad81301" +#define SQLITE_VERSION "3.44.1" +#define SQLITE_VERSION_NUMBER 3044001 +#define SQLITE_SOURCE_ID "2023-11-22 14:18:12 d295f48e8f367b066b881780c98bdf980a1d550397d5ba0b0e49842c95b3e8b4" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -258542,13 +258656,27 @@ SQLITE_API int sqlite3_create_window_function( ** ** ** [[SQLITE_SUBTYPE]]
    SQLITE_SUBTYPE
    -** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** Specifying this flag makes no difference for scalar or aggregate user -** functions. However, if it is not specified for a user-defined window -** function, then any sub-types belonging to arguments passed to the window -** function may be discarded before the window function is called (i.e. -** sqlite3_value_subtype() will always return 0). +** This flag instructs SQLite to omit some corner-case optimizations that +** might disrupt the operation of the [sqlite3_value_subtype()] function, +** causing it to return zero rather than the correct subtype(). +** SQL functions that invokes [sqlite3_value_subtype()] should have this +** property. If the SQLITE_SUBTYPE property is omitted, then the return +** value from [sqlite3_value_subtype()] might sometimes be zero even though +** a non-zero subtype was specified by the function argument expression. +** +** [[SQLITE_RESULT_SUBTYPE]]
    SQLITE_RESULT_SUBTYPE
    +** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call +** [sqlite3_result_subtype()] to cause a sub-type to be associated with its +** result. +** Every function that invokes [sqlite3_result_subtype()] should have this +** property. If it does not, then the call to [sqlite3_result_subtype()] +** might become a no-op if the function is used as term in an +** [expression index]. On the other hand, SQL functions that never invoke +** [sqlite3_result_subtype()] should avoid setting this property, as the +** purpose of this property is to disable certain optimizations that are +** incompatible with subtypes. **
    ** */ @@ -258556,6 +258684,7 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 +#define SQLITE_RESULT_SUBTYPE 0x001000000 /* ** CAPI3REF: Deprecated Functions @@ -258752,6 +258881,12 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. +** +** Every [application-defined SQL function] that invoke this interface +** should include the [SQLITE_SUBTYPE] property in the text +** encoding argument when the function is [sqlite3_create_function|registered]. +** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() +** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -258882,14 +259017,22 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); **
  • ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or **
  • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^ +** allocation error occurs.)^ +**
  • ^(during the original sqlite3_set_auxdata() call if the function +** is evaluated during query planning instead of during query execution, +** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ ** -** Note the last bullet in particular. The destructor X in +** Note the last two bullets in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. +** sqlite3_set_auxdata() has been called. Furthermore, a call to +** sqlite3_get_auxdata() that occurs immediately after a corresponding call +** to sqlite3_set_auxdata() might still return NULL if an out-of-memory +** condition occurred during the sqlite3_set_auxdata() call or if the +** function is being evaluated during query planning rather than during +** query execution. ** ** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal @@ -259163,6 +259306,20 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. +** +** Every [application-defined SQL function] that invokes this interface +** should include the [SQLITE_RESULT_SUBTYPE] property in its +** text encoding argument when the SQL function is +** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] +** property is omitted from the function that invokes sqlite3_result_subtype(), +** then in some cases the sqlite3_result_subtype() might fail to set +** the result subtype. +** +** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any +** SQL function that invokes the sqlite3_result_subtype() interface +** and that does not have the SQLITE_RESULT_SUBTYPE property will raise +** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 +** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); @@ -266339,7 +266496,8 @@ int sqlite3_user_delete( #define CODEC_TYPE_CHACHA20 3 #define CODEC_TYPE_SQLCIPHER 4 #define CODEC_TYPE_RC4 5 -#define CODEC_TYPE_MAX_BUILTIN 5 +#define CODEC_TYPE_ASCON128 6 +#define CODEC_TYPE_MAX_BUILTIN 6 /* ** Definition of API functions @@ -272790,6 +272948,8 @@ SQLITE_PRIVATE int sqlite3mcCodecAttach(sqlite3* db, int nDb, const char* zPath, SQLITE_PRIVATE void sqlite3mcCodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey); +SQLITE_PRIVATE void sqlite3mcSecureZeroMemory(void* v, size_t n); + /* Debugging */ #if 0 @@ -274707,6 +274867,1582 @@ SQLITE_PRIVATE const CipherDescriptor mcRC4Descriptor = #endif /*** End of #include "cipher_sds_rc4.c" ***/ +/* #include "cipher_ascon.c" */ +/*** Begin of #include "cipher_ascon.c" ***/ +/* +** Name: cipher_ascon.c +** Purpose: Implementation of cipher Ascon +** Author: Ulrich Telle +** Created: 2023-11-13 +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +/* #include "cipher_common.h" */ + + +/* --- Ascon --- */ +#if HAVE_CIPHER_ASCON128 + +#define CIPHER_NAME_ASCON128 "ascon128" + +/* +** Configuration parameters for "ascon128a" +** +** - kdf_iter : number of iterations for key derivation +*/ + +#define ASCON128_KDF_ITER_DEFAULT 64007 + +/* #include "ascon/prolog.h" */ +/*** Begin of #include "ascon/prolog.h" ***/ +/* +** Name: prolog.h +** Purpose: Include important header files, before +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Modified by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +#ifndef PROLOG_H +#define PROLOG_H + +/* #include "word.h" */ +/*** Begin of #include "word.h" ***/ +#ifndef WORD_H_ +#define WORD_H_ + +#include +#include + +/* #include "bendian.h" */ +/*** Begin of #include "bendian.h" ***/ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +/* macros for big endian machines */ +#ifdef PRAGMA_ENDIAN +#pragma message("Using macros for big endian machines") +#endif +#define ASCON_U64BIG(x) (x) +#define ASCON_U32BIG(x) (x) +#define ASCON_U16BIG(x) (x) + +#elif defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +/* macros for little endian machines */ +#ifdef PRAGMA_ENDIAN +#pragma message("Using macros for little endian machines") +#endif +#define ASCON_U64BIG(x) \ + (((0x00000000000000FFULL & (x)) << 56) | \ + ((0x000000000000FF00ULL & (x)) << 40) | \ + ((0x0000000000FF0000ULL & (x)) << 24) | \ + ((0x00000000FF000000ULL & (x)) << 8) | \ + ((0x000000FF00000000ULL & (x)) >> 8) | \ + ((0x0000FF0000000000ULL & (x)) >> 24) | \ + ((0x00FF000000000000ULL & (x)) >> 40) | \ + ((0xFF00000000000000ULL & (x)) >> 56)) +#define ASCON_U32BIG(x) \ + (((0x000000FF & (x)) << 24) | ((0x0000FF00 & (x)) << 8) | \ + ((0x00FF0000 & (x)) >> 8) | ((0xFF000000 & (x)) >> 24)) +#define ASCON_U16BIG(x) (((0x00FF & (x)) << 8) | ((0xFF00 & (x)) >> 8)) + +#else +#error "Ascon byte order macros not defined in bendian.h" +#endif + +#endif /* ENDIAN_H_ */ +/*** End of #include "bendian.h" ***/ + +/* #include "forceinline.h" */ +/*** Begin of #include "forceinline.h" ***/ +#ifndef FORCEINLINE_H_ +#define FORCEINLINE_H_ + +/* define forceinline macro */ +#ifdef _MSC_VER +#define forceinline __forceinline +#elif defined(__GNUC__) +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define forceinline inline __attribute__((__always_inline__)) +#else +#define forceinline static inline +#endif +#elif defined(__CLANG__) +#if __has_attribute(__always_inline__) +#define forceinline inline __attribute__((__always_inline__)) +#else +#define forceinline inline +#endif +#else +#define forceinline inline +#endif + +#endif /* FORCEINLINE_H_ */ +/*** End of #include "forceinline.h" ***/ + + +typedef union { + uint64_t x; + uint32_t w[2]; + uint8_t b[8]; +} word_t; + +#define ASCON_U64TOWORD(x) ASCON_U64BIG(x) +#define ASCON_WORDTOU64(x) ASCON_U64BIG(x) + +forceinline uint64_t ASCON_ROR(uint64_t x, int n) { return x >> n | x << (-n & 63); } + +forceinline uint64_t ASCON_KEYROT(uint64_t lo2hi, uint64_t hi2lo) { + return lo2hi << 32 | hi2lo >> 32; +} + +forceinline int ASCON_NOTZERO(uint64_t a, uint64_t b) { + uint64_t result = a | b; + result |= result >> 32; + result |= result >> 16; + result |= result >> 8; + return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1; +} + +forceinline uint64_t ASCON_PAD(int i) { return 0x80ull << (56 - 8 * i); } + +forceinline uint64_t ASCON_PRFS_MLEN(uint64_t len) { return len << 51; } + +forceinline uint64_t ASCON_CLEAR(uint64_t w, int n) { + /* undefined for n == 0 */ + uint64_t mask = ~0ull >> (8 * n); + return w & mask; +} + +forceinline uint64_t ASCON_MASK(int n) { + /* undefined for n == 0 */ + return ~0ull >> (64 - 8 * n); +} + +forceinline uint64_t ASCON_LOAD(const uint8_t* bytes, int n) { + uint64_t x = *(uint64_t*)bytes & ASCON_MASK(n); + return ASCON_U64TOWORD(x); +} + +forceinline void ASCON_STORE(uint8_t* bytes, uint64_t w, int n) { + *(uint64_t*)bytes &= ~ASCON_MASK(n); + *(uint64_t*)bytes |= ASCON_WORDTOU64(w); +} + +forceinline uint64_t ASCON_LOADBYTES(const uint8_t* bytes, int n) { + uint64_t x = 0; + memcpy(&x, bytes, n); + return ASCON_U64TOWORD(x); +} + +forceinline void ASCON_STOREBYTES(uint8_t* bytes, uint64_t w, int n) { + uint64_t x = ASCON_WORDTOU64(w); + memcpy(bytes, &x, n); +} + +#endif /* WORD_H_ */ +/*** End of #include "word.h" ***/ + + +#endif +/*** End of #include "ascon/prolog.h" ***/ + +/* #include "ascon/aead.c" */ +/*** Begin of #include "ascon/aead.c" ***/ +/* +** Name: aead.c +** Purpose: Stream encryption/decryption with Ascon +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Modified by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +/* #include "api.h" */ +/*** Begin of #include "api.h" ***/ +/* +** Name: api.h +** Purpose: Definition of preprocessor symbols +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Combined symbols from AEAD and HASH +** Modified by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +#define CRYPTO_VERSION "1.2.7" +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 +#define ASCON_AEAD_RATE 8 + +#define CRYPTO_BYTES 32 +#define ASCON_HASH_BYTES 32 /* HASH */ +#define ASCON_HASH_ROUNDS 12 + +#define ASCON_AEAD_KEY_LEN CRYPTO_KEYBYTES +#define ASCON_AEAD_NONCE_LEN CRYPTO_NPUBBYTES +#define ASCON_AEAD_TAG_LEN CRYPTO_ABYTES +#define ASCON_SALT_LEN CRYPTO_NPUBBYTES +/*** End of #include "api.h" ***/ + +/* #include "ascon.h" */ +/*** Begin of #include "ascon.h" ***/ +#ifndef ASCON_H_ +#define ASCON_H_ + +#include + +/* #include "api.h" */ + +/* #include "config.h" */ +/*** Begin of #include "config.h" ***/ +#ifndef CONFIG_H_ +#define CONFIG_H_ + +/* inline the ascon mode */ +#ifndef ASCON_INLINE_MODE +#define ASCON_INLINE_MODE 1 +#endif + +/* inline all permutations */ +#ifndef ASCON_INLINE_PERM +#define ASCON_INLINE_PERM 1 +#endif + +/* unroll permutation loops */ +#ifndef ASCON_UNROLL_LOOPS +#define ASCON_UNROLL_LOOPS 1 +#endif + +#endif /* CONFIG_H_ */ +/*** End of #include "config.h" ***/ + + +typedef union { + uint64_t x[5]; + uint32_t w[5][2]; + uint8_t b[5][8]; +} ascon_state_t; + +#ifdef ASCON_AEAD_RATE + +#define ASCON_KEYWORDS (CRYPTO_KEYBYTES + 7) / 8 + +typedef union { + uint64_t x[ASCON_KEYWORDS]; + uint32_t w[ASCON_KEYWORDS][2]; + uint8_t b[ASCON_KEYWORDS][8]; +} ascon_key_t; + +#if !ASCON_INLINE_MODE + +void ascon_loadkey(ascon_key_t* key, const uint8_t* k); +void ascon_initaead(ascon_state_t* s, const ascon_key_t* key, + const uint8_t* npub); +void ascon_adata(ascon_state_t* s, const uint8_t* ad, uint64_t adlen); +void ascon_encrypt(ascon_state_t* s, uint8_t* c, const uint8_t* m, + uint64_t mlen); +void ascon_decrypt(ascon_state_t* s, uint8_t* m, const uint8_t* c, + uint64_t clen); +void ascon_final(ascon_state_t* s, const ascon_key_t* k); + +#endif + +#endif + +#ifdef ASCON_HASH_BYTES + +#if !ASCON_INLINE_MODE + +void ascon_inithash(ascon_state_t* s); +void ascon_absorb(ascon_state_t* s, const uint8_t* in, uint64_t inlen); +void ascon_squeeze(ascon_state_t* s, uint8_t* out, uint64_t outlen); + +#endif + +#endif + +#endif /* ASCON_H_ */ +/*** End of #include "ascon.h" ***/ + +/* #include "crypto_aead.h" */ +/*** Begin of #include "crypto_aead.h" ***/ +/* +** Name: hash.c +** Purpose: API definition for Hash algorithm with Ascon +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Modified by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +#ifndef CRYPTO_AEAD_H +#define CRYPTO_AEAD_H + +#include + +/* +** Encryption using ASCON-AEAD. +** +** \param ctext Output buffer for encrypted text (same length as plain text) +** \param tag Output buffer for tag with fixed length of ASCON_AEAD_TAG_LEN +** \param mtext Input buffer with plain message text +** \param mlen Length of message text +** \param ad Input buffer with associated data +** \param adlen Length of associated data +** \param nonce Buffer with nonce data +** \param k Buffer with key data +*/ +int ascon_aead_encrypt(uint8_t* ctext, uint8_t tag[ASCON_AEAD_TAG_LEN], + const uint8_t* mtext, uint64_t mlen, + const uint8_t* ad, uint64_t adlen, + const uint8_t nonce[ASCON_AEAD_NONCE_LEN], + const uint8_t k[ASCON_AEAD_KEY_LEN]); + +/* +** Encryption using ASCON-AEAD. +** +** \param mtext Output buffer with decrypted plain message text (same length as encrypted text) +** \param ctext Input buffer for encrypted text +** \param clen Length of encrypted text +** \param ad Input buffer with associated data +** \param adlen Length of associated data +** \param tag Input buffer for expected tag with fixed length of ASCON_AEAD_TAG_LEN +** \param nonce Buffer with nonce data +** \param k Buffer with key data +*/ +int ascon_aead_decrypt(uint8_t* mtext, const uint8_t* ctext, uint64_t clen, + const uint8_t* ad, uint64_t adlen, + const uint8_t tag[ASCON_AEAD_TAG_LEN], + const uint8_t nonce[ASCON_AEAD_NONCE_LEN], + const uint8_t k[ASCON_AEAD_KEY_LEN]); + +#endif +/*** End of #include "crypto_aead.h" ***/ + +/* #include "permutations.h" */ +/*** Begin of #include "permutations.h" ***/ +#ifndef PERMUTATIONS_H_ +#define PERMUTATIONS_H_ + +#include + +/* #include "api.h" */ + +/* #include "ascon.h" */ + +/* #include "config.h" */ + +/* #include "constants.h" */ +/*** Begin of #include "constants.h" ***/ +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + +#include + +#define ASCON_128_KEYBYTES 16 +#define ASCON_128A_KEYBYTES 16 +#define ASCON_80PQ_KEYBYTES 20 + +#define ASCON_128_RATE 8 +#define ASCON_128A_RATE 16 +#define ASCON_HASH_RATE 8 +#define ASCON_PRF_IN_RATE 32 +#define ASCON_PRFA_IN_RATE 40 +#define ASCON_PRF_OUT_RATE 16 + +#define ASCON_128_PA_ROUNDS 12 +#define ASCON_128_PB_ROUNDS 6 +#define ASCON_128A_PA_ROUNDS 12 +#define ASCON_128A_PB_ROUNDS 8 + +#define ASCON_HASH_PA_ROUNDS 12 +#define ASCON_HASH_PB_ROUNDS 12 +#define ASCON_HASHA_PA_ROUNDS 12 +#define ASCON_HASHA_PB_ROUNDS 8 + +#define ASCON_PRF_PA_ROUNDS 12 +#define ASCON_PRF_PB_ROUNDS 12 +#define ASCON_PRFA_PA_ROUNDS 12 +#define ASCON_PRFA_PB_ROUNDS 8 + +#define ASCON_128_IV 0x80400c0600000000ull +#define ASCON_128A_IV 0x80800c0800000000ull +#define ASCON_80PQ_IV 0xa0400c0600000000ull + +#define ASCON_HASH_IV 0x00400c0000000100ull +#define ASCON_HASHA_IV 0x00400c0400000100ull +#define ASCON_XOF_IV 0x00400c0000000000ull +#define ASCON_XOFA_IV 0x00400c0400000000ull + +#define ASCON_HASH_IV0 0xee9398aadb67f03dull +#define ASCON_HASH_IV1 0x8bb21831c60f1002ull +#define ASCON_HASH_IV2 0xb48a92db98d5da62ull +#define ASCON_HASH_IV3 0x43189921b8f8e3e8ull +#define ASCON_HASH_IV4 0x348fa5c9d525e140ull + +#define ASCON_HASHA_IV0 0x01470194fc6528a6ull +#define ASCON_HASHA_IV1 0x738ec38ac0adffa7ull +#define ASCON_HASHA_IV2 0x2ec8e3296c76384cull +#define ASCON_HASHA_IV3 0xd6f6a54d7f52377dull +#define ASCON_HASHA_IV4 0xa13c42a223be8d87ull + +#define ASCON_XOF_IV0 0xb57e273b814cd416ull +#define ASCON_XOF_IV1 0x2b51042562ae2420ull +#define ASCON_XOF_IV2 0x66a3a7768ddf2218ull +#define ASCON_XOF_IV3 0x5aad0a7a8153650cull +#define ASCON_XOF_IV4 0x4f3e0e32539493b6ull + +#define ASCON_XOFA_IV0 0x44906568b77b9832ull +#define ASCON_XOFA_IV1 0xcd8d6cae53455532ull +#define ASCON_XOFA_IV2 0xf7b5212756422129ull +#define ASCON_XOFA_IV3 0x246885e1de0d225bull +#define ASCON_XOFA_IV4 0xa8cb5ce33449973full + +#define ASCON_MAC_IV 0x80808c0000000080ull +#define ASCON_MACA_IV 0x80808c0400000080ull +#define ASCON_PRF_IV 0x80808c0000000000ull +#define ASCON_PRFA_IV 0x80808c0400000000ull +#define ASCON_PRFS_IV 0x80004c8000000000ull + +#define ASCON_RC0 0xf0 +#define ASCON_RC1 0xe1 +#define ASCON_RC2 0xd2 +#define ASCON_RC3 0xc3 +#define ASCON_RC4 0xb4 +#define ASCON_RC5 0xa5 +#define ASCON_RC6 0x96 +#define ASCON_RC7 0x87 +#define ASCON_RC8 0x78 +#define ASCON_RC9 0x69 +#define ASCON_RCa 0x5a +#define ASCON_RCb 0x4b + +#define ASCON_RC(i) (i) + +#define ASCON_START(n) ((3 + (n)) << 4 | (12 - (n))) +#define ASCON_INC -0x0f +#define ASCON_END 0x3c + +#endif /* CONSTANTS_H_ */ +/*** End of #include "constants.h" ***/ + +/* #include "printstate.h" */ +/*** Begin of #include "printstate.h" ***/ +#ifndef PRINTSTATE_H_ +#define PRINTSTATE_H_ + +#ifdef ASCON_PRINT_STATE + +/* #include "ascon.h" */ + +/* #include "word.h" */ + + +void ascon_printword(const char* text, const uint64_t x); +void ascon_printstate(const char* text, const ascon_state_t* s); + +#else + +#define ascon_printword(text, w) \ + do { \ + } while (0) + +#define ascon_printstate(text, s) \ + do { \ + } while (0) + +#endif + +#endif /* PRINTSTATE_H_ */ +/*** End of #include "printstate.h" ***/ + +/* #include "round.h" */ +/*** Begin of #include "round.h" ***/ +/* +** Name: round.h +** Purpose: Selector for Ascon implementation variant for 32- resp 64-bit +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Modified by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +#ifndef ROUND_H +#define ROUND_H + +/* #include "forceinline.h" */ + + +#if defined(__LP64__) || defined(_WIN64) +/* 64-bit machine, Windows or Linux or OS X */ +/* #include "round64.h" */ +/*** Begin of #include "round64.h" ***/ +#ifndef ROUND64_H_ +#define ROUND64_H_ + +/* #include "ascon.h" */ + +/* #include "constants.h" */ + +/* #include "forceinline.h" */ + +/* #include "printstate.h" */ + +/* #include "word.h" */ + + +forceinline void ASCON_ROUND(ascon_state_t* s, uint8_t C) { + ascon_state_t t; + /* round constant */ + s->x[2] ^= C; + /* s-box layer */ + s->x[0] ^= s->x[4]; + s->x[4] ^= s->x[3]; + s->x[2] ^= s->x[1]; + t.x[0] = s->x[0] ^ (~s->x[1] & s->x[2]); + t.x[2] = s->x[2] ^ (~s->x[3] & s->x[4]); + t.x[4] = s->x[4] ^ (~s->x[0] & s->x[1]); + t.x[1] = s->x[1] ^ (~s->x[2] & s->x[3]); + t.x[3] = s->x[3] ^ (~s->x[4] & s->x[0]); + t.x[1] ^= t.x[0]; + t.x[3] ^= t.x[2]; + t.x[0] ^= t.x[4]; + /* linear layer */ + s->x[2] = t.x[2] ^ ASCON_ROR(t.x[2], 6 - 1); + s->x[3] = t.x[3] ^ ASCON_ROR(t.x[3], 17 - 10); + s->x[4] = t.x[4] ^ ASCON_ROR(t.x[4], 41 - 7); + s->x[0] = t.x[0] ^ ASCON_ROR(t.x[0], 28 - 19); + s->x[1] = t.x[1] ^ ASCON_ROR(t.x[1], 61 - 39); + s->x[2] = t.x[2] ^ ASCON_ROR(s->x[2], 1); + s->x[3] = t.x[3] ^ ASCON_ROR(s->x[3], 10); + s->x[4] = t.x[4] ^ ASCON_ROR(s->x[4], 7); + s->x[0] = t.x[0] ^ ASCON_ROR(s->x[0], 19); + s->x[1] = t.x[1] ^ ASCON_ROR(s->x[1], 39); + s->x[2] = ~s->x[2]; + ascon_printstate(" round output", s); +} + +forceinline void ASCON_PROUNDS(ascon_state_t* s, int nr) { + int i = ASCON_START(nr); + do { + ASCON_ROUND(s, ASCON_RC(i)); + i += ASCON_INC; + } while (i != ASCON_END); +} + +#endif /* ROUND64_H_ */ +/*** End of #include "round64.h" ***/ + +#else +/* 32-bit machine, Windows or Linux or OS X */ +/* #include "round32.h" */ +/*** Begin of #include "round32.h" ***/ +#ifndef ROUND32_H_ +#define ROUND32_H_ + +/* #include "ascon.h" */ + +/* #include "constants.h" */ + +/* #include "forceinline.h" */ + +/* #include "printstate.h" */ + +/* #include "word.h" */ + + +forceinline void ASCON_ROUND(ascon_state_t* s, uint8_t C) { + uint64_t xtemp; + /* round constant */ + s->x[2] ^= C; + /* s-box layer */ + s->x[0] ^= s->x[4]; + s->x[4] ^= s->x[3]; + s->x[2] ^= s->x[1]; + xtemp = s->x[0] & ~s->x[4]; + s->x[0] ^= s->x[2] & ~s->x[1]; + s->x[2] ^= s->x[4] & ~s->x[3]; + s->x[4] ^= s->x[1] & ~s->x[0]; + s->x[1] ^= s->x[3] & ~s->x[2]; + s->x[3] ^= xtemp; + s->x[1] ^= s->x[0]; + s->x[3] ^= s->x[2]; + s->x[0] ^= s->x[4]; + s->x[2] = ~s->x[2]; + /* linear layer */ + s->x[0] ^= + (s->x[0] >> 19) ^ (s->x[0] << 45) ^ (s->x[0] >> 28) ^ (s->x[0] << 36); + s->x[1] ^= + (s->x[1] >> 61) ^ (s->x[1] << 3) ^ (s->x[1] >> 39) ^ (s->x[1] << 25); + s->x[2] ^= + (s->x[2] >> 1) ^ (s->x[2] << 63) ^ (s->x[2] >> 6) ^ (s->x[2] << 58); + s->x[3] ^= + (s->x[3] >> 10) ^ (s->x[3] << 54) ^ (s->x[3] >> 17) ^ (s->x[3] << 47); + s->x[4] ^= + (s->x[4] >> 7) ^ (s->x[4] << 57) ^ (s->x[4] >> 41) ^ (s->x[4] << 23); + ascon_printstate(" round output", s); +} + +forceinline void ASCON_PROUNDS(ascon_state_t* s, int nr) { + int i = ASCON_START(nr); + do { + ASCON_ROUND(s, ASCON_RC(i)); + i += ASCON_INC; + } while (i != ASCON_END); +} + +#endif /* ROUND32_H_ */ +/*** End of #include "round32.h" ***/ + +#endif + +#endif +/*** End of #include "round.h" ***/ + + +forceinline void ASCON_P12ROUNDS(ascon_state_t* s) { + ASCON_ROUND(s, ASCON_RC0); + ASCON_ROUND(s, ASCON_RC1); + ASCON_ROUND(s, ASCON_RC2); + ASCON_ROUND(s, ASCON_RC3); + ASCON_ROUND(s, ASCON_RC4); + ASCON_ROUND(s, ASCON_RC5); + ASCON_ROUND(s, ASCON_RC6); + ASCON_ROUND(s, ASCON_RC7); + ASCON_ROUND(s, ASCON_RC8); + ASCON_ROUND(s, ASCON_RC9); + ASCON_ROUND(s, ASCON_RCa); + ASCON_ROUND(s, ASCON_RCb); +} + +forceinline void ASCON_P8ROUNDS(ascon_state_t* s) { + ASCON_ROUND(s, ASCON_RC4); + ASCON_ROUND(s, ASCON_RC5); + ASCON_ROUND(s, ASCON_RC6); + ASCON_ROUND(s, ASCON_RC7); + ASCON_ROUND(s, ASCON_RC8); + ASCON_ROUND(s, ASCON_RC9); + ASCON_ROUND(s, ASCON_RCa); + ASCON_ROUND(s, ASCON_RCb); +} + +forceinline void ASCON_P6ROUNDS(ascon_state_t* s) { + ASCON_ROUND(s, ASCON_RC6); + ASCON_ROUND(s, ASCON_RC7); + ASCON_ROUND(s, ASCON_RC8); + ASCON_ROUND(s, ASCON_RC9); + ASCON_ROUND(s, ASCON_RCa); + ASCON_ROUND(s, ASCON_RCb); +} + +#if ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS + +forceinline void ASCON_P(ascon_state_t* s, int nr) { + if (nr == 12) ASCON_P12ROUNDS(s); + if (nr == 8) ASCON_P8ROUNDS(s); + if (nr == 6) ASCON_P6ROUNDS(s); +} + +#elif !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS + +void ASCON_P12(ascon_state_t* s); +void ASCON_P8(ascon_state_t* s); +void ASCON_P6(ascon_state_t* s); + +forceinline void ASCON_P(ascon_state_t* s, int nr) { + if (nr == 12) ASCON_P12(s); + if (nr == 8) ASCON_P8(s); + if (nr == 6) ASCON_P6(s); +} + +#elif ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS + +forceinline void ASCON_P(ascon_state_t* s, int nr) { ASCON_PROUNDS(s, nr); } + +#else /* !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS */ + +void ASCON_P(ascon_state_t* s, int nr); + +#endif + +#endif /* PERMUTATIONS_H_ */ +/*** End of #include "permutations.h" ***/ + +/* #include "printstate.h" */ + + +#if !ASCON_INLINE_MODE +#undef forceinline +#define forceinline +#endif + +#ifdef ASCON_AEAD_RATE + +forceinline void ascon_loadkey(ascon_key_t* key, const uint8_t* k) { +#if CRYPTO_KEYBYTES == 16 + key->x[0] = ASCON_LOAD(k, 8); + key->x[1] = ASCON_LOAD(k + 8, 8); +#else /* CRYPTO_KEYBYTES == 20 */ + key->x[0] = ASCON_KEYROT(0, ASCON_LOADBYTES(k, 4)); + key->x[1] = ASCON_LOADBYTES(k + 4, 8); + key->x[2] = ASCON_LOADBYTES(k + 12, 8); +#endif +} + +forceinline void ascon_initaead(ascon_state_t* s, const ascon_key_t* key, + const uint8_t* npub) { +#if CRYPTO_KEYBYTES == 16 + if (ASCON_AEAD_RATE == 8) s->x[0] = ASCON_128_IV; + if (ASCON_AEAD_RATE == 16) s->x[0] = ASCON_128A_IV; + s->x[1] = key->x[0]; + s->x[2] = key->x[1]; +#else /* CRYPTO_KEYBYTES == 20 */ + s->x[0] = key->x[0] ^ ASCON_80PQ_IV; + s->x[1] = key->x[1]; + s->x[2] = key->x[2]; +#endif + s->x[3] = ASCON_LOAD(npub, 8); + s->x[4] = ASCON_LOAD(npub + 8, 8); + ascon_printstate("init 1st key xor", s); + ASCON_P(s, 12); +#if CRYPTO_KEYBYTES == 16 + s->x[3] ^= key->x[0]; + s->x[4] ^= key->x[1]; +#else /* CRYPTO_KEYBYTES == 20 */ + s->x[2] ^= key->x[0]; + s->x[3] ^= key->x[1]; + s->x[4] ^= key->x[2]; +#endif + ascon_printstate("init 2nd key xor", s); +} + +forceinline void ascon_adata(ascon_state_t* s, const uint8_t* ad, + uint64_t adlen) { + const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8; + if (adlen) { + /* full associated data blocks */ + while (adlen >= ASCON_AEAD_RATE) { + s->x[0] ^= ASCON_LOAD(ad, 8); + if (ASCON_AEAD_RATE == 16) s->x[1] ^= ASCON_LOAD(ad + 8, 8); + ascon_printstate("absorb adata", s); + ASCON_P(s, nr); + ad += ASCON_AEAD_RATE; + adlen -= ASCON_AEAD_RATE; + } + /* final associated data block */ + uint64_t* px = &s->x[0]; + if (ASCON_AEAD_RATE == 16 && adlen >= 8) { + s->x[0] ^= ASCON_LOAD(ad, 8); + px = &s->x[1]; + ad += 8; + adlen -= 8; + } + *px ^= ASCON_PAD(adlen); + if (adlen) *px ^= ASCON_LOADBYTES(ad, adlen); + ascon_printstate("pad adata", s); + ASCON_P(s, nr); + } + /* domain separation */ + s->x[4] ^= 1; + ascon_printstate("domain separation", s); +} + +forceinline void ascon_encrypt(ascon_state_t* s, uint8_t* c, const uint8_t* m, + uint64_t mlen) { + const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8; + /* full plaintext blocks */ + while (mlen >= ASCON_AEAD_RATE) { + s->x[0] ^= ASCON_LOAD(m, 8); + ASCON_STORE(c, s->x[0], 8); + if (ASCON_AEAD_RATE == 16) { + s->x[1] ^= ASCON_LOAD(m + 8, 8); + ASCON_STORE(c + 8, s->x[1], 8); + } + ascon_printstate("absorb plaintext", s); + ASCON_P(s, nr); + m += ASCON_AEAD_RATE; + c += ASCON_AEAD_RATE; + mlen -= ASCON_AEAD_RATE; + } + /* final plaintext block */ + uint64_t* px = &s->x[0]; + if (ASCON_AEAD_RATE == 16 && mlen >= 8) { + s->x[0] ^= ASCON_LOAD(m, 8); + ASCON_STORE(c, s->x[0], 8); + px = &s->x[1]; + m += 8; + c += 8; + mlen -= 8; + } + *px ^= ASCON_PAD(mlen); + if (mlen) { + *px ^= ASCON_LOADBYTES(m, mlen); + ASCON_STOREBYTES(c, *px, mlen); + } + ascon_printstate("pad plaintext", s); +} + +forceinline void ascon_decrypt(ascon_state_t* s, uint8_t* m, const uint8_t* c, + uint64_t clen) { + const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8; + /* full ciphertext blocks */ + while (clen >= ASCON_AEAD_RATE) { + uint64_t cx = ASCON_LOAD(c, 8); + s->x[0] ^= cx; + ASCON_STORE(m, s->x[0], 8); + s->x[0] = cx; + if (ASCON_AEAD_RATE == 16) { + cx = ASCON_LOAD(c + 8, 8); + s->x[1] ^= cx; + ASCON_STORE(m + 8, s->x[1], 8); + s->x[1] = cx; + } + ascon_printstate("insert ciphertext", s); + ASCON_P(s, nr); + m += ASCON_AEAD_RATE; + c += ASCON_AEAD_RATE; + clen -= ASCON_AEAD_RATE; + } + /* final ciphertext block */ + uint64_t* px = &s->x[0]; + if (ASCON_AEAD_RATE == 16 && clen >= 8) { + uint64_t cx = ASCON_LOAD(c, 8); + s->x[0] ^= cx; + ASCON_STORE(m, s->x[0], 8); + s->x[0] = cx; + px = &s->x[1]; + m += 8; + c += 8; + clen -= 8; + } + *px ^= ASCON_PAD(clen); + if (clen) { + uint64_t cx = ASCON_LOADBYTES(c, clen); + *px ^= cx; + ASCON_STOREBYTES(m, *px, clen); + *px = ASCON_CLEAR(*px, clen); + *px ^= cx; + } + ascon_printstate("pad ciphertext", s); +} + +forceinline void ascon_final(ascon_state_t* s, const ascon_key_t* key) { +#if CRYPTO_KEYBYTES == 16 + if (ASCON_AEAD_RATE == 8) { + s->x[1] ^= key->x[0]; + s->x[2] ^= key->x[1]; + } else { + s->x[2] ^= key->x[0]; + s->x[3] ^= key->x[1]; + } +#else /* CRYPTO_KEYBYTES == 20 */ + s->x[1] ^= KEYROT(key->x[0], key->x[1]); + s->x[2] ^= KEYROT(key->x[1], key->x[2]); + s->x[3] ^= KEYROT(key->x[2], 0); +#endif + ascon_printstate("final 1st key xor", s); + ASCON_P(s, 12); +#if CRYPTO_KEYBYTES == 16 + s->x[3] ^= key->x[0]; + s->x[4] ^= key->x[1]; +#else /* CRYPTO_KEYBYTES == 20 */ + s->x[3] ^= key->x[1]; + s->x[4] ^= key->x[2]; +#endif + ascon_printstate("final 2nd key xor", s); +} + +int ascon_aead_encrypt(uint8_t* ctext, + uint8_t tag[ASCON_AEAD_TAG_LEN], + const uint8_t* mtext, uint64_t mlen, + const uint8_t* ad, uint64_t adlen, + const uint8_t nonce[ASCON_AEAD_NONCE_LEN], + const uint8_t k[ASCON_AEAD_KEY_LEN]) +{ + ascon_state_t s; + /* perform ascon computation */ + ascon_key_t key; + ascon_loadkey(&key, k); + ascon_initaead(&s, &key, nonce); + ascon_adata(&s, ad, adlen); + ascon_encrypt(&s, ctext, mtext, mlen); + ascon_final(&s, &key); + /* set tag */ + ASCON_STOREBYTES(tag, s.x[3], 8); + ASCON_STOREBYTES(tag + 8, s.x[4], 8); + sqlite3mcSecureZeroMemory(&s, sizeof(ascon_state_t)); + sqlite3mcSecureZeroMemory(&key, sizeof(ascon_key_t)); + return 0; +} + +int ascon_aead_decrypt(uint8_t* mtext, + const uint8_t* ctext, uint64_t clen, + const uint8_t* ad, uint64_t adlen, + const uint8_t tag[ASCON_AEAD_TAG_LEN], + const uint8_t nonce[ASCON_AEAD_NONCE_LEN], + const uint8_t k[ASCON_AEAD_KEY_LEN]) +{ + int rc = 0; + ascon_state_t s; + if (clen < CRYPTO_ABYTES) return -1; + /* perform ascon computation */ + ascon_key_t key; + ascon_loadkey(&key, k); + ascon_initaead(&s, &key, nonce); + ascon_adata(&s, ad, adlen); + ascon_decrypt(&s, mtext, ctext, clen); + ascon_final(&s, &key); + /* verify tag (should be constant time, check compiler output) */ + s.x[3] ^= ASCON_LOADBYTES(tag, 8); + s.x[4] ^= ASCON_LOADBYTES(tag + 8, 8); + rc = ASCON_NOTZERO(s.x[3], s.x[4]); + sqlite3mcSecureZeroMemory(&s, sizeof(ascon_state_t)); + sqlite3mcSecureZeroMemory(&key, sizeof(ascon_key_t)); + return rc; +} + +#endif +/*** End of #include "ascon/aead.c" ***/ + +/* #include "ascon/hash.c" */ +/*** Begin of #include "ascon/hash.c" ***/ +/* +** Name: hash.c +** Purpose: Hash algorithm with Ascon +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Modified by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +/* #include "api.h" */ + +/* #include "ascon.h" */ + +/* #include "crypto_hash.h" */ +/*** Begin of #include "crypto_hash.h" ***/ +/* +** Name: hash.c +** Purpose: API definition for Hash algorithm with Ascon +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Modified by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +#ifndef CRYPTO_HASH_H +#define CRYPTO_HASH_H + +#include + +/* +** Derives hash value using ASCON-HASH. +** +** \param out Output buffer for hash with fixed length of ASCON_HASH_BYTES +** \param in Buffer with input data +** \param passwordlen Length of input data in bytes +*/ +int ascon_hash(uint8_t* out, const uint8_t* in, uint64_t inlen); + +#endif +/*** End of #include "crypto_hash.h" ***/ + +/* #include "permutations.h" */ + +/* #include "printstate.h" */ + + +#if !ASCON_INLINE_MODE +#undef forceinline +#define forceinline +#endif + +#ifdef ASCON_HASH_BYTES + +forceinline void ascon_inithash(ascon_state_t* s) { + int i; + /* initialize */ +#ifdef ASCON_PRINT_STATE +#if ASCON_HASH_BYTES == 32 && ASCON_HASH_ROUNDS == 12 + s->x[0] = ASCON_HASH_IV; +#elif ASCON_HASH_BYTES == 32 && ASCON_HASH_ROUNDS == 8 + s->x[0] = ASCON_HASHA_IV; +#elif ASCON_HASH_BYTES == 0 && ASCON_HASH_ROUNDS == 12 + s->x[0] = ASCON_XOF_IV; +#elif ASCON_HASH_BYTES == 0 && ASCON_HASH_ROUNDS == 8 + s->x[0] = ASCON_XOFA_IV; +#endif + for (i = 1; i < 5; ++i) s->x[i] = 0; + ascon_printstate("initial value", s); + ASCON_P(s, 12); +#endif +#if ASCON_HASH_BYTES == 32 && ASCON_HASH_ROUNDS == 12 + const uint64_t iv[5] = {ASCON_HASH_IV0, ASCON_HASH_IV1, ASCON_HASH_IV2, + ASCON_HASH_IV3, ASCON_HASH_IV4}; +#elif ASCON_HASH_BYTES == 32 && ASCON_HASH_ROUNDS == 8 + const uint64_t iv[5] = {ASCON_HASHA_IV0, ASCON_HASHA_IV1, ASCON_HASHA_IV2, + ASCON_HASHA_IV3, ASCON_HASHA_IV4}; +#elif ASCON_HASH_BYTES == 0 && ASCON_HASH_ROUNDS == 12 + const uint64_t iv[5] = {ASCON_XOF_IV0, ASCON_XOF_IV1, ASCON_XOF_IV2, + ASCON_XOF_IV3, ASCON_XOF_IV4}; +#elif ASCON_HASH_BYTES == 0 && ASCON_HASH_ROUNDS == 8 + const uint64_t iv[5] = {ASCON_XOFA_IV0, ASCON_XOFA_IV1, ASCON_XOFA_IV2, + ASCON_XOFA_IV3, ASCON_XOFA_IV4}; +#endif + for (i = 0; i < 5; ++i) s->x[i] = (iv[i]); + ascon_printstate("initialization", s); +} + +forceinline void ascon_absorb(ascon_state_t* s, const uint8_t* in, + uint64_t inlen) { + /* absorb full plaintext blocks */ + while (inlen >= ASCON_HASH_RATE) { + s->x[0] ^= ASCON_LOAD(in, 8); + ascon_printstate("absorb plaintext", s); + ASCON_P(s, ASCON_HASH_ROUNDS); + in += ASCON_HASH_RATE; + inlen -= ASCON_HASH_RATE; + } + /* absorb final plaintext block */ + s->x[0] ^= ASCON_LOADBYTES(in, inlen); + s->x[0] ^= ASCON_PAD(inlen); + ascon_printstate("pad plaintext", s); +} + +forceinline void ascon_squeeze(ascon_state_t* s, uint8_t* out, + uint64_t outlen) { + /* squeeze full output blocks */ + ASCON_P(s, 12); + while (outlen > ASCON_HASH_RATE) { + ASCON_STORE(out, s->x[0], 8); + ascon_printstate("squeeze output", s); + ASCON_P(s, ASCON_HASH_ROUNDS); + out += ASCON_HASH_RATE; + outlen -= ASCON_HASH_RATE; + } + /* squeeze final output block */ + ASCON_STOREBYTES(out, s->x[0], outlen); + ascon_printstate("squeeze output", s); +} + +int ascon_hash(uint8_t* out, const uint8_t* in, uint64_t inlen) +{ + ascon_state_t s; + ascon_inithash(&s); + ascon_absorb(&s, in, inlen); + ascon_squeeze(&s, out, ASCON_HASH_BYTES); + sqlite3mcSecureZeroMemory(&s, sizeof(ascon_state_t)); + return 0; +} + +#endif +/*** End of #include "ascon/hash.c" ***/ + +/* #include "ascon/pbkdf2.c" */ +/*** Begin of #include "ascon/pbkdf2.c" ***/ +/* +** Name: pbkdf2.c +** Purpose: Implementation of PBKDF2 algoritm with Ascon +** Based on: Public domain Ascon reference implementation +** and optimized variants for 32- and 64-bit +** (see https://github.com/ascon/ascon-c) +** and the paper "Additional Modes for ASCON Version 1.1" +** by Rhys Weatherley, Southern Storm Software, Pty Ltd. +** Remarks: API functions adapted for use in SQLite3 Multiple Ciphers +** Created by: Ulrich Telle +** Copyright: (c) 2023-2023 Ulrich Telle +** License: MIT +*/ + +#define ASCON_HASH_SIZE 32 +#define ASCON_PBKDF2_SIZE 32 + +void ascon_pbkdf2_init(ascon_state_t* state, const char* functionName, + const unsigned char* custom, uint32_t customlen, uint32_t outlen) +{ + /* Format the initial block with the function name and output length */ + uint8_t initial[ASCON_HASH_SIZE]; + size_t fnLength = functionName ? strlen(functionName) : 0; + + if (fnLength == 0) + { + /* No function name specified */ + memset(initial, 0, ASCON_HASH_SIZE); + } + else if (fnLength <= ASCON_HASH_SIZE) + { + /* Pad the function name with zeroes */ + memcpy(initial, functionName, fnLength); + memset(initial + fnLength, 0, ASCON_HASH_SIZE - fnLength); + } + else + { + ascon_hash(initial, (const uint8_t*) functionName, fnLength); + } + + state->x[0] = ASCON_HASH_IV; + state->x[1] = ASCON_LOAD(initial, 8); + state->x[2] = ASCON_LOAD(initial + 8, 8); + state->x[3] = ASCON_LOAD(initial + 16, 8); + state->x[4] = ASCON_LOAD(initial + 24, 8); + ASCON_P(state, 12); + + if (customlen > 0) + { + ascon_absorb(state, custom, customlen); + ASCON_P(state, 12); + /* domain separation */ + state->x[4] ^= 1; + } +} + +/* + * Implementation of the "F" function from RFC 8018, section 5.2 + * + * Note: Instead of HMAC like in RFC 8018, use the following PRF: + * PRF(P, X) = ASCON-cXOF(X, 256, "PBKDF2", P) + */ +static void ascon_pbkdf2_f(ascon_state_t* state, + uint8_t* T, /*uint8_t* U,*/ + const uint8_t* salt, uint32_t saltlen, + uint32_t count, uint32_t blocknum) +{ + uint32_t asconSaltLen = (saltlen < ASCON_SALT_LEN) ? saltlen : ASCON_SALT_LEN; + uint8_t temp[ASCON_SALT_LEN+4]; + ascon_state_t state2; + int j; + + memset(temp, 0, ASCON_SALT_LEN); + memcpy(temp, salt, asconSaltLen); + STORE32_BE(temp+ASCON_SALT_LEN, blocknum); + + /* Copy initial state */ + for (j = 0; j < 5; ++j) state2.x[j] = state->x[j]; + + ascon_absorb(&state2, temp, ASCON_SALT_LEN+4); + ascon_squeeze(&state2, T, ASCON_PBKDF2_SIZE); + sqlite3mcSecureZeroMemory(temp, sizeof(temp)); + + if (count > 1) + { + uint8_t U[ASCON_PBKDF2_SIZE]; + memcpy(U, T, ASCON_PBKDF2_SIZE); + while (count > 1) + { + uint8_t* dst = T; + uint8_t* src = U; + uint32_t len = ASCON_PBKDF2_SIZE; + /* Copy initial state */ + for (j = 0; j < 5; ++j) state2.x[j] = state->x[j]; + /* Absorb U */ + ascon_absorb(&state2, U, ASCON_PBKDF2_SIZE); + /* Squeeze next U */ + ascon_squeeze(&state2, U, ASCON_PBKDF2_SIZE); + /* XOR T with U */ + while (len > 0) + { + *dst++ ^= *src++; + --len; + } + --count; + } + sqlite3mcSecureZeroMemory(U, sizeof(U)); + } + sqlite3mcSecureZeroMemory(&state2, sizeof(ascon_state_t)); +} + +void ascon_pbkdf2(uint8_t* out, uint32_t outlen, + const uint8_t* password, uint32_t passwordlen, + const uint8_t* salt, uint32_t saltlen, uint32_t count) +{ + ascon_state_t state; + uint32_t blocknum = 1; + ascon_pbkdf2_init(&state, "PBKDF2", password, passwordlen, ASCON_PBKDF2_SIZE); + while (outlen > 0) + { + if (outlen >= ASCON_PBKDF2_SIZE) + { + ascon_pbkdf2_f(&state, out, /*U,*/ salt, saltlen, count, blocknum); + out += ASCON_PBKDF2_SIZE; + outlen -= ASCON_PBKDF2_SIZE; + } + else + { + uint8_t T[ASCON_PBKDF2_SIZE]; + ascon_pbkdf2_f(&state, T, /*U,*/ salt, saltlen, count, blocknum); + memcpy(out, T, outlen); + sqlite3mcSecureZeroMemory(T, sizeof(T)); + break; + } + ++blocknum; + } +} +/*** End of #include "ascon/pbkdf2.c" ***/ + + +SQLITE_PRIVATE CipherParams mcAscon128Params[] = +{ + { "kdf_iter", ASCON128_KDF_ITER_DEFAULT, ASCON128_KDF_ITER_DEFAULT, 1, 0x7fffffff }, + CIPHER_PARAMS_SENTINEL +}; + +#define KEYLENGTH_ASCON128 32 +#define SALTLENGTH_ASCON128 16 +#define PAGE_NONCE_LEN_ASCON128 16 +#define PAGE_TAG_LEN_ASCON128 16 +#define PAGE_RESERVED_ASCON128 (PAGE_NONCE_LEN_ASCON128 + PAGE_TAG_LEN_ASCON128) + +typedef struct _ascon128Cipher +{ + int m_kdfIter; + int m_keyLength; + uint8_t m_key[KEYLENGTH_ASCON128]; + uint8_t m_salt[SALTLENGTH_ASCON128]; +} Ascon128Cipher; + +static void* +AllocateAscon128Cipher(sqlite3* db) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) sqlite3_malloc(sizeof(Ascon128Cipher)); + if (ascon128Cipher != NULL) + { + memset(ascon128Cipher, 0, sizeof(Ascon128Cipher)); + ascon128Cipher->m_keyLength = KEYLENGTH_ASCON128; + memset(ascon128Cipher->m_key, 0, KEYLENGTH_ASCON128); + memset(ascon128Cipher->m_salt, 0, SALTLENGTH_ASCON128); + } + if (ascon128Cipher != NULL) + { + CipherParams* cipherParams = sqlite3mcGetCipherParams(db, CIPHER_NAME_ASCON128); + ascon128Cipher->m_kdfIter = sqlite3mcGetCipherParameter(cipherParams, "kdf_iter"); + } + return ascon128Cipher; +} + +static void +FreeAscon128Cipher(void* cipher) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher; + memset(ascon128Cipher, 0, sizeof(Ascon128Cipher)); + sqlite3_free(ascon128Cipher); +} + +static void +CloneAscon128Cipher(void* cipherTo, void* cipherFrom) +{ + Ascon128Cipher* ascon128CipherTo = (Ascon128Cipher*) cipherTo; + Ascon128Cipher* ascon128CipherFrom = (Ascon128Cipher*) cipherFrom; + ascon128CipherTo->m_kdfIter = ascon128CipherFrom->m_kdfIter; + ascon128CipherTo->m_keyLength = ascon128CipherFrom->m_keyLength; + memcpy(ascon128CipherTo->m_key, ascon128CipherFrom->m_key, KEYLENGTH_ASCON128); + memcpy(ascon128CipherTo->m_salt, ascon128CipherFrom->m_salt, SALTLENGTH_ASCON128); +} + +static int +GetLegacyAscon128Cipher(void* cipher) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*)cipher; + return 0; +} + +static int +GetPageSizeAscon128Cipher(void* cipher) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher; + int pageSize = 0; + return pageSize; +} + +static int +GetReservedAscon128Cipher(void* cipher) +{ + return PAGE_RESERVED_ASCON128; +} + +static unsigned char* +GetSaltAscon128Cipher(void* cipher) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher; + return ascon128Cipher->m_salt; +} + +static void +GenerateKeyAscon128Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher; + int bypass = 0; + + Pager *pPager = pBt->pPager; + sqlite3_file* fd = (isOpen(pPager->fd)) ? pPager->fd : NULL; + + int keyOnly = 1; + if (rekey || fd == NULL || sqlite3OsRead(fd, ascon128Cipher->m_salt, SALTLENGTH_ASCON128, 0) != SQLITE_OK) + { + chacha20_rng(ascon128Cipher->m_salt, SALTLENGTH_ASCON128); + keyOnly = 0; + } + else if (cipherSalt != NULL) + { + memcpy(ascon128Cipher->m_salt, cipherSalt, SALTLENGTH_ASCON128); + } + + /* Bypass key derivation if the key string starts with "raw:" */ + if (passwordLength > 4 && !memcmp(userPassword, "raw:", 4)) + { + const int nRaw = passwordLength - 4; + const unsigned char* zRaw = (const unsigned char*) userPassword + 4; + switch (nRaw) + { + /* Binary key (and salt) */ + case KEYLENGTH_ASCON128 + SALTLENGTH_ASCON128: + if (!keyOnly) + { + memcpy(ascon128Cipher->m_salt, zRaw + KEYLENGTH_ASCON128, SALTLENGTH_ASCON128); + } + /* fall-through */ + case KEYLENGTH_ASCON128: + memcpy(ascon128Cipher->m_key, zRaw, KEYLENGTH_ASCON128); + bypass = 1; + break; + + /* Hex-encoded key */ + case 2 * KEYLENGTH_ASCON128: + if (sqlite3mcIsHexKey(zRaw, nRaw) != 0) + { + sqlite3mcConvertHex2Bin(zRaw, nRaw, ascon128Cipher->m_key); + bypass = 1; + } + break; + + /* Hex-encoded key and salt */ + case 2 * (KEYLENGTH_ASCON128 + SALTLENGTH_ASCON128): + if (sqlite3mcIsHexKey(zRaw, nRaw) != 0) + { + sqlite3mcConvertHex2Bin(zRaw, 2 * KEYLENGTH_ASCON128, ascon128Cipher->m_key); + if (!keyOnly) + { + sqlite3mcConvertHex2Bin(zRaw + 2 * KEYLENGTH_ASCON128, 2 * SALTLENGTH_ASCON128, ascon128Cipher->m_salt); + } + bypass = 1; + } + break; + + default: + break; + } + } + + if (!bypass) + { + ascon_pbkdf2(ascon128Cipher->m_key, KEYLENGTH_ASCON128, + (const uint8_t*) userPassword, passwordLength, + ascon128Cipher->m_salt, SALTLENGTH_ASCON128, ascon128Cipher->m_kdfIter); + } + SQLITE3MC_DEBUG_LOG("generate: codec=%p pFile=%p\n", ascon128Cipher, fd); + SQLITE3MC_DEBUG_HEX("generate key:", ascon128Cipher->m_key, KEYLENGTH_ASCON128); + SQLITE3MC_DEBUG_HEX("generate salt:", ascon128Cipher->m_salt, SALTLENGTH_ASCON128); +} + +static int +AsconGenOtk(uint8_t* out, const uint8_t* key, const uint8_t* nonce, int page) +{ + ascon_state_t s; + uint8_t temp[KEYLENGTH_ASCON128+PAGE_NONCE_LEN_ASCON128+4]; + memcpy(temp, key, KEYLENGTH_ASCON128); + memcpy(temp+KEYLENGTH_ASCON128, nonce, PAGE_NONCE_LEN_ASCON128); + STORE32_BE(temp+KEYLENGTH_ASCON128+PAGE_NONCE_LEN_ASCON128, page); + ascon_inithash(&s); + ascon_absorb(&s, temp, KEYLENGTH_ASCON128+PAGE_NONCE_LEN_ASCON128+4); + ascon_squeeze(&s, out, ASCON_HASH_BYTES); + sqlite3mcSecureZeroMemory(temp, sizeof(temp)); + return 0; +} + +static int +EncryptPageAscon128Cipher(void* cipher, int page, unsigned char* data, int len, int reserved) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher; + int rc = SQLITE_OK; + int nReserved = (reserved == 0) ? 0 : GetReservedAscon128Cipher(cipher); + int n = len - nReserved; + uint64_t mlen = n; + + /* Generate one-time keys */ + uint8_t otk[ASCON_HASH_BYTES]; + int offset; + + /* Check whether number of required reserved bytes and actually reserved bytes match */ + if (nReserved > reserved) + { + return SQLITE_CORRUPT; + } + + if (nReserved > 0) + { + /* Encrypt and authenticate */ + memset(otk, 0, ASCON_HASH_BYTES); + /* Generate nonce */ + chacha20_rng(data + n + PAGE_TAG_LEN_ASCON128, PAGE_NONCE_LEN_ASCON128); + AsconGenOtk(otk, ascon128Cipher->m_key, data + n + PAGE_TAG_LEN_ASCON128, page); + + offset = (page == 1) ? CIPHER_PAGE1_OFFSET : 0; + ascon_aead_encrypt(data + offset, data + n, data + offset, mlen - offset, + NULL /* ad */, 0 /* adlen*/, + data + n + PAGE_TAG_LEN_ASCON128, otk); + if (page == 1) + { + memcpy(data, ascon128Cipher->m_salt, SALTLENGTH_ASCON128); + } + } + else + { + /* Encrypt only */ + uint8_t nonce[PAGE_NONCE_LEN_ASCON128]; + uint8_t dummyTag[PAGE_TAG_LEN_ASCON128]; + memset(dummyTag, 0, PAGE_TAG_LEN_ASCON128); + memset(otk, 0, ASCON_HASH_BYTES); + sqlite3mcGenerateInitialVector(page, nonce); + AsconGenOtk(otk, ascon128Cipher->m_key, nonce, page); + + /* Encrypt */ + offset = (page == 1) ? CIPHER_PAGE1_OFFSET : 0; + ascon_aead_encrypt(data + offset, dummyTag, data + offset, mlen - offset, + NULL /* ad */, 0 /* adlen*/, + nonce, otk); + if (page == 1) + { + memcpy(data, ascon128Cipher->m_salt, SALTLENGTH_ASCON128); + } + } + + return rc; +} + +static int +DecryptPageAscon128Cipher(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck) +{ + Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher; + int rc = SQLITE_OK; + int nReserved = (reserved == 0) ? 0 : GetReservedAscon128Cipher(cipher); + int n = len - nReserved; + uint64_t clen = n; + int tagOk; + + /* Generate one-time keys */ + uint8_t otk[ASCON_HASH_BYTES]; + int offset; + + /* Check whether number of required reserved bytes and actually reserved bytes match */ + if (nReserved > reserved) + { + return (page == 1) ? SQLITE_NOTADB : SQLITE_CORRUPT; + } + + if (nReserved > 0) + { + /* Decrypt and verify MAC */ + memset(otk, 0, ASCON_HASH_BYTES); + AsconGenOtk(otk, ascon128Cipher->m_key, data + n + PAGE_TAG_LEN_ASCON128, page); + + /* Determine MAC and decrypt */ + offset = (page == 1) ? CIPHER_PAGE1_OFFSET : 0; + tagOk = ascon_aead_decrypt(data + offset, data + offset, clen - offset, + NULL /* ad */, 0 /* adlen */, + data + n, data + n + PAGE_TAG_LEN_ASCON128, otk); + if (hmacCheck != 0) + { + /* Verify the MAC */ + if (tagOk != 0) + { + SQLITE3MC_DEBUG_LOG("decrypt: codec=%p page=%d\n", ascon128Cipher, page); + SQLITE3MC_DEBUG_HEX("decrypt key:", ascon128Cipher->m_key, 32); + SQLITE3MC_DEBUG_HEX("decrypt otk:", otk, 64); + SQLITE3MC_DEBUG_HEX("decrypt data+00:", data, 16); + SQLITE3MC_DEBUG_HEX("decrypt data+24:", data + 24, 16); + SQLITE3MC_DEBUG_HEX("decrypt data+n:", data + n, 16); + SQLITE3MC_DEBUG_HEX("decrypt tag r:", data + n + PAGE_NONCE_LEN_ASCON128, PAGE_TAG_LEN_ASCON128); + SQLITE3MC_DEBUG_HEX("decrypt tag c:", tag, PAGE_TAG_LEN_ASCON128); + /* Bad MAC */ + rc = (page == 1) ? SQLITE_NOTADB : SQLITE_CORRUPT; + } + } + if (page == 1 && rc == SQLITE_OK) + { + memcpy(data, SQLITE_FILE_HEADER, 16); + } + } + else + { + /* Decrypt only */ + uint8_t nonce[PAGE_NONCE_LEN_ASCON128]; + uint8_t dummyTag[PAGE_TAG_LEN_ASCON128]; + memset(dummyTag, 0, PAGE_TAG_LEN_ASCON128); + memset(otk, 0, ASCON_HASH_BYTES); + sqlite3mcGenerateInitialVector(page, nonce); + AsconGenOtk(otk, ascon128Cipher->m_key, nonce, page); + + /* Decrypt */ + offset = (page == 1) ? CIPHER_PAGE1_OFFSET : 0; + tagOk = ascon_aead_decrypt(data + offset, data + offset, clen - offset, + NULL /* ad */, 0 /* adlen */, + dummyTag, nonce, otk); + if (page == 1) + { + memcpy(data, SQLITE_FILE_HEADER, 16); + } + } + + return rc; +} + +SQLITE_PRIVATE const CipherDescriptor mcAscon128Descriptor = +{ + CIPHER_NAME_ASCON128, + AllocateAscon128Cipher, + FreeAscon128Cipher, + CloneAscon128Cipher, + GetLegacyAscon128Cipher, + GetPageSizeAscon128Cipher, + GetReservedAscon128Cipher, + GetSaltAscon128Cipher, + GenerateKeyAscon128Cipher, + EncryptPageAscon128Cipher, + DecryptPageAscon128Cipher +}; +#endif +/*** End of #include "cipher_ascon.c" ***/ + /* #include "cipher_common.c" */ /*** Begin of #include "cipher_common.c" ***/ /* @@ -276638,7 +278374,7 @@ sqlite3mcBtreeSetPageSize(Btree* p, int pageSize, int nReserve, int iFix) ** Change 4: Call sqlite3mcBtreeSetPageSize instead of sqlite3BtreeSetPageSize for main database ** (sqlite3mcBtreeSetPageSize allows to reduce the number of reserved bytes) ** -** This code is generated by the script rekeyvacuum.sh from SQLite version 3.44.0 amalgamation. +** This code is generated by the script rekeyvacuum.sh from SQLite version 3.44.1 amalgamation. */ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey( char **pzErrMsg, /* Write error message here */ @@ -277501,6 +279237,33 @@ sqlite3_rekey(sqlite3 *db, const void *zKey, int nKey) ** License: MIT */ +/* For memset, memset_s */ +#include + +#ifdef _WIN32 +/* For SecureZeroMemory */ +#include +#include +#endif + +SQLITE_PRIVATE void sqlite3mcSecureZeroMemory(void* v, size_t n) +{ +#ifdef _WIN32 + SecureZeroMemory(v, n); +#elif defined(__DARWIN__) || defined(__STDC_LIB_EXT1__) + /* memset_s() is available since OS X 10.9, */ + /* and may be available on other platforms. */ + memset_s(v, n, 0, n); +#elif defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 11) + /* Non-standard function */ + explicit_bzero(v, n); +#else + /* Generic implementation based on volatile pointers */ + static void* (* const volatile memset_sec)(void*, int, size_t) = &memset; + memset_sec(v, 0, n); +#endif +} + #if SQLITE3MC_SECURE_MEMORY /* Flag indicating whether securing memory allocations is initialized */ @@ -277571,7 +279334,7 @@ static void mcMemoryFree(void* pPrior) mcRandomFill((char*) pPrior, nSize) #else int nSize = mcMemorySize(pPrior); - memset(pPrior, 0, nSize); + sqlite3mcSecureZeroMemory(pPrior, 0, nSize); #endif } mcDefaultMemoryMethods.xFree(pPrior); @@ -281689,7 +283452,7 @@ SQLITE_EXTENSION_INIT1 #undef LONGDOUBLE_CONSTANT #undef LONGDOUBLE_TYPE -#if defined(__GNUC__) && defined(_WIN64) +#if defined(SQLITE_USE_QUADMATH) && defined(__GNUC__) && defined(_WIN64) #include #define LONGDOUBLE_TYPE __float128 #define LONGDOUBLE_CONSTANT(x) x##Q @@ -283214,7 +284977,7 @@ static int vsvtabColumn( { LONGDOUBLE_TYPE dv, fp, ip; -#if defined(__GNUC__) && defined(_WIN64) +#if defined(SQLITE_USE_QUADMATH) && defined(__GNUC__) && defined(_WIN64) if (!hasExtended) hasExtended = 1; #else if (!hasExtended) { @@ -301391,6 +303154,12 @@ sqlite3mc_initialize(const char* arg) rc = sqlite3mcRegisterCipher(&mcRC4Descriptor, mcRC4Params, (CODEC_TYPE_RC4 == CODEC_TYPE)); } #endif +#if HAVE_CIPHER_ASCON128 + if (rc == SQLITE_OK) + { + rc = sqlite3mcRegisterCipher(&mcAscon128Descriptor, mcAscon128Params, (CODEC_TYPE_ASCON128 == CODEC_TYPE)); + } +#endif /* ** Initialize and register MultiCipher VFS as default VFS diff --git a/src/sqlite3mc_amalgamation.h b/src/sqlite3mc_amalgamation.h index 13d26e0c..e7d42d03 100644 --- a/src/sqlite3mc_amalgamation.h +++ b/src/sqlite3mc_amalgamation.h @@ -3,7 +3,7 @@ ** Purpose: Header file for SQLite3 Multiple Ciphers support ** Author: Ulrich Telle ** Created: 2020-03-01 -** Copyright: (c) 2019-2022 Ulrich Telle +** Copyright: (c) 2019-2023 Ulrich Telle ** License: MIT */ @@ -30,10 +30,10 @@ #define SQLITE3MC_VERSION_H_ #define SQLITE3MC_VERSION_MAJOR 1 -#define SQLITE3MC_VERSION_MINOR 7 -#define SQLITE3MC_VERSION_RELEASE 4 +#define SQLITE3MC_VERSION_MINOR 8 +#define SQLITE3MC_VERSION_RELEASE 0 #define SQLITE3MC_VERSION_SUBRELEASE 0 -#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.7.4" +#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.8.0" #endif /* SQLITE3MC_VERSION_H_ */ /*** End of #include "sqlite3mc_version.h" ***/ @@ -192,9 +192,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.44.0" -#define SQLITE_VERSION_NUMBER 3044000 -#define SQLITE_SOURCE_ID "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad81301" +#define SQLITE_VERSION "3.44.1" +#define SQLITE_VERSION_NUMBER 3044001 +#define SQLITE_SOURCE_ID "2023-11-22 14:18:12 d295f48e8f367b066b881780c98bdf980a1d550397d5ba0b0e49842c95b3e8b4" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -5619,13 +5619,27 @@ SQLITE_API int sqlite3_create_window_function( ** ** ** [[SQLITE_SUBTYPE]]
    SQLITE_SUBTYPE
    -** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** Specifying this flag makes no difference for scalar or aggregate user -** functions. However, if it is not specified for a user-defined window -** function, then any sub-types belonging to arguments passed to the window -** function may be discarded before the window function is called (i.e. -** sqlite3_value_subtype() will always return 0). +** This flag instructs SQLite to omit some corner-case optimizations that +** might disrupt the operation of the [sqlite3_value_subtype()] function, +** causing it to return zero rather than the correct subtype(). +** SQL functions that invokes [sqlite3_value_subtype()] should have this +** property. If the SQLITE_SUBTYPE property is omitted, then the return +** value from [sqlite3_value_subtype()] might sometimes be zero even though +** a non-zero subtype was specified by the function argument expression. +** +** [[SQLITE_RESULT_SUBTYPE]]
    SQLITE_RESULT_SUBTYPE
    +** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call +** [sqlite3_result_subtype()] to cause a sub-type to be associated with its +** result. +** Every function that invokes [sqlite3_result_subtype()] should have this +** property. If it does not, then the call to [sqlite3_result_subtype()] +** might become a no-op if the function is used as term in an +** [expression index]. On the other hand, SQL functions that never invoke +** [sqlite3_result_subtype()] should avoid setting this property, as the +** purpose of this property is to disable certain optimizations that are +** incompatible with subtypes. **
    ** */ @@ -5633,6 +5647,7 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 +#define SQLITE_RESULT_SUBTYPE 0x001000000 /* ** CAPI3REF: Deprecated Functions @@ -5829,6 +5844,12 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. +** +** Every [application-defined SQL function] that invoke this interface +** should include the [SQLITE_SUBTYPE] property in the text +** encoding argument when the function is [sqlite3_create_function|registered]. +** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() +** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -5959,14 +5980,22 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); **
  • ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or **
  • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^ +** allocation error occurs.)^ +**
  • ^(during the original sqlite3_set_auxdata() call if the function +** is evaluated during query planning instead of during query execution, +** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ ** -** Note the last bullet in particular. The destructor X in +** Note the last two bullets in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. +** sqlite3_set_auxdata() has been called. Furthermore, a call to +** sqlite3_get_auxdata() that occurs immediately after a corresponding call +** to sqlite3_set_auxdata() might still return NULL if an out-of-memory +** condition occurred during the sqlite3_set_auxdata() call or if the +** function is being evaluated during query planning rather than during +** query execution. ** ** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal @@ -6240,6 +6269,20 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. +** +** Every [application-defined SQL function] that invokes this interface +** should include the [SQLITE_RESULT_SUBTYPE] property in its +** text encoding argument when the SQL function is +** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] +** property is omitted from the function that invokes sqlite3_result_subtype(), +** then in some cases the sqlite3_result_subtype() might fail to set +** the result subtype. +** +** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any +** SQL function that invokes the sqlite3_result_subtype() interface +** and that does not have the SQLITE_RESULT_SUBTYPE property will raise +** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 +** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); @@ -13416,7 +13459,8 @@ int sqlite3_user_delete( #define CODEC_TYPE_CHACHA20 3 #define CODEC_TYPE_SQLCIPHER 4 #define CODEC_TYPE_RC4 5 -#define CODEC_TYPE_MAX_BUILTIN 5 +#define CODEC_TYPE_ASCON128 6 +#define CODEC_TYPE_MAX_BUILTIN 6 /* ** Definition of API functions diff --git a/src/wxsqlite3.cpp b/src/wxsqlite3.cpp index a7e23671..bd9d8f35 100644 --- a/src/wxsqlite3.cpp +++ b/src/wxsqlite3.cpp @@ -6358,3 +6358,101 @@ wxSQLite3CipherRC4::Apply(void* dbHandle) const throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_CIPHER_NOT_SUPPORTED); #endif } + +wxSQLite3CipherAscon128::wxSQLite3CipherAscon128() + : wxSQLite3Cipher(WXSQLITE_CIPHER_ASCON128), m_legacy(false), m_kdfIter(64007) +{ + SetInitialized(true); +} + +wxSQLite3CipherAscon128::wxSQLite3CipherAscon128(const wxSQLite3CipherAscon128& cipher) + : wxSQLite3Cipher(cipher), m_legacy(cipher.m_legacy), m_kdfIter(cipher.m_kdfIter) +{ +} + +wxSQLite3CipherAscon128::~wxSQLite3CipherAscon128() +{ +} + +bool +wxSQLite3CipherAscon128::InitializeFromGlobalDefault() +{ +#if HAVE_CIPHER_ASCON128 +#if 0 + int legacy = sqlite3mc_config_cipher(0, "ascon128", "legacy", -1); + m_legacy = legacy != 0; +#endif + m_kdfIter = sqlite3mc_config_cipher(0, "ascon128", "kdf_iter", -1); + bool initialized = m_kdfIter > 0; + SetInitialized(initialized); + return initialized; +#else + throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_CIPHER_NOT_SUPPORTED); +#endif +} + +bool +wxSQLite3CipherAscon128::InitializeFromCurrent(wxSQLite3Database& db) +{ +#if HAVE_CIPHER_ASCON128 + sqlite3* dbHandle = (sqlite3*) GetDatabaseHandle(db); +#if 0 + int legacy = sqlite3mc_config_cipher(dbHandle, "ascon128", "legacy", -1); + m_legacy = legacy != 0; +#endif + m_kdfIter = sqlite3mc_config_cipher(dbHandle, "ascon128", "kdf_iter", -1); + bool initialized = m_kdfIter > 0; + SetInitialized(initialized); + return initialized; +#else + throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_CIPHER_NOT_SUPPORTED); +#endif +} + +bool +wxSQLite3CipherAscon128::InitializeFromCurrentDefault(wxSQLite3Database& db) +{ +#if HAVE_CIPHER_ASCON128 + sqlite3* dbHandle = (sqlite3*) GetDatabaseHandle(db); +#if 0 + int legacy = sqlite3mc_config_cipher(dbHandle, "ascon128", "default:legacy", -1); + m_legacy = legacy != 0; +#endif + m_kdfIter = sqlite3mc_config_cipher(dbHandle, "ascon128", "default:kdf_iter", -1); + bool initialized = m_kdfIter > 0; + SetInitialized(initialized); + return initialized; +#else + throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_CIPHER_NOT_SUPPORTED); +#endif +} + +bool +wxSQLite3CipherAscon128::Apply(wxSQLite3Database& db) const +{ + return Apply(GetDatabaseHandle(db)); +} + +bool +wxSQLite3CipherAscon128::Apply(void* dbHandle) const +{ +#if HAVE_CIPHER_ASCON128 + bool applied = false; + if (IsOk()) + { + if (dbHandle != NULL) + { + int newCipherType = sqlite3mc_config((sqlite3*) dbHandle, "cipher", sqlite3mc_cipher_index("ascon128")); +#if 0 + int legacy = sqlite3mc_config_cipher((sqlite3*) dbHandle, "ascon128", "legacy", (m_legacy) ? 1 : 0); + int legacyPageSize = sqlite3mc_config_cipher((sqlite3*) dbHandle, "ascon128", "legacy_page_size", GetLegacyPageSize()); +#endif + int kdfIter = sqlite3mc_config_cipher((sqlite3*) dbHandle, "ascon128", "kdf_iter", m_kdfIter); + applied = (newCipherType > 0) /* && (legacy >= 0) && (legacyPageSize >= 0) */ && (kdfIter > 0); + } + } + return applied; +#else + throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_CIPHER_NOT_SUPPORTED); +#endif +}