@@ -115,10 +115,11 @@ SQLITE_PRIVATE const AegisCryptFunctions mcAegisCryptFunctions[] =
115115
116116SQLITE_PRIVATE CipherParams mcAegisParams [] =
117117{
118- { "tcost" , AEGIS_TCOST_DEFAULT , AEGIS_TCOST_DEFAULT , 1 , 0x7fffffff },
119- { "mcost" , AEGIS_MCOST_DEFAULT , AEGIS_MCOST_DEFAULT , 1 , 0x7fffffff },
120- { "pcost" , AEGIS_PCOST_DEFAULT , AEGIS_PCOST_DEFAULT , 1 , 0x7fffffff },
121- { "algorithm" , AEGIS_ALGORITHM_DEFAULT , AEGIS_ALGORITHM_DEFAULT , AEGIS_ALGORITHM_MIN , AEGIS_ALGORITHM_MAX },
118+ { "tcost" , AEGIS_TCOST_DEFAULT , AEGIS_TCOST_DEFAULT , 1 , 0x7fffffff },
119+ { "mcost" , AEGIS_MCOST_DEFAULT , AEGIS_MCOST_DEFAULT , 1 , 0x7fffffff },
120+ { "pcost" , AEGIS_PCOST_DEFAULT , AEGIS_PCOST_DEFAULT , 1 , 0x7fffffff },
121+ { "algorithm" , AEGIS_ALGORITHM_DEFAULT , AEGIS_ALGORITHM_DEFAULT , AEGIS_ALGORITHM_MIN , AEGIS_ALGORITHM_MAX },
122+ { "plaintext_header_size" , 0 , 0 , 0 , 100 /* restrict to db header size */ },
122123 CIPHER_PARAMS_SENTINEL
123124};
124125
@@ -151,6 +152,7 @@ typedef struct _aegisCipher
151152 int m_argon2Mcost ;
152153 int m_argon2Pcost ;
153154 int m_aegisAlgorithm ;
155+ int m_plaintextHeaderSize ;
154156 int m_keyLength ;
155157 int m_nonceLength ;
156158 uint8_t m_key [KEYLENGTH_AEGIS_MAX ];
@@ -185,6 +187,8 @@ AllocateAegisCipher(sqlite3* db)
185187 aegisCipher -> m_keyLength = KEYLENGTH_AEGIS_256 ;
186188 aegisCipher -> m_nonceLength = PAGE_NONCE_LEN_AEGIS_256 ;
187189 }
190+ int plaintextHeaderSize = sqlite3mcGetCipherParameter (cipherParams , "plaintext_header_size" );
191+ aegisCipher -> m_plaintextHeaderSize = (plaintextHeaderSize >=0 && plaintextHeaderSize <= 100 && plaintextHeaderSize % 16 == 0 ) ? plaintextHeaderSize : 0 ;
188192 }
189193 return aegisCipher ;
190194}
@@ -208,6 +212,7 @@ CloneAegisCipher(void* cipherTo, void* cipherFrom)
208212 aegisCipherTo -> m_argon2Pcost = aegisCipherFrom -> m_argon2Pcost ;
209213
210214 aegisCipherTo -> m_aegisAlgorithm = aegisCipherFrom -> m_aegisAlgorithm ;
215+ aegisCipherTo -> m_plaintextHeaderSize = aegisCipherFrom -> m_plaintextHeaderSize ;
211216 aegisCipherTo -> m_keyLength = aegisCipherFrom -> m_keyLength ;
212217 aegisCipherTo -> m_nonceLength = aegisCipherFrom -> m_nonceLength ;
213218
@@ -347,12 +352,28 @@ EncryptPageAegisCipher(void* cipher, int page, unsigned char* data, int len, int
347352 int nReserved = (reserved == 0 ) ? 0 : GetReservedAegisCipher (cipher );
348353 int n = len - nReserved ;
349354 uint64_t mlen = n ;
355+ int usePlaintextHeader = 0 ;
350356
351357 /* Generate one-time keys */
352358 uint8_t otk [OTK_LEN_MAX_AEGIS ];
353- int offset ;
359+ int offset = 0 ;
354360 memset (otk , 0 , OTK_LEN_MAX_AEGIS );
355361
362+ /* Check whether a plaintext header should be used */
363+ if (page == 1 )
364+ {
365+ int plaintextHeaderSize = aegisCipher -> m_plaintextHeaderSize ;
366+ if (plaintextHeaderSize > 0 )
367+ {
368+ usePlaintextHeader = 1 ;
369+ offset = (plaintextHeaderSize > CIPHER_PAGE1_OFFSET ) ? plaintextHeaderSize : CIPHER_PAGE1_OFFSET ;
370+ }
371+ else
372+ {
373+ offset = CIPHER_PAGE1_OFFSET ;
374+ }
375+ }
376+
356377 /* Check whether number of required reserved bytes and actually reserved bytes match */
357378 if (nReserved > reserved )
358379 {
@@ -368,13 +389,12 @@ EncryptPageAegisCipher(void* cipher, int page, unsigned char* data, int len, int
368389 AegisGenOtk (aegisCipher , otk , aegisCipher -> m_keyLength + aegisCipher -> m_nonceLength ,
369390 data + n + PAGE_TAG_LEN_AEGIS , aegisCipher -> m_nonceLength , page );
370391
371- offset = (page == 1 ) ? CIPHER_PAGE1_OFFSET : 0 ;
372392 mcAegisCryptFunctions [aegisCipher -> m_aegisAlgorithm ].encrypt (
373393 data + offset , data + n , PAGE_TAG_LEN_AEGIS ,
374394 data + offset , mlen - offset ,
375395 NULL , 0 , otk + aegisCipher -> m_keyLength , otk );
376396
377- if (page == 1 )
397+ if (page == 1 && usePlaintextHeader == 0 )
378398 {
379399 memcpy (data , aegisCipher -> m_salt , SALTLENGTH_AEGIS );
380400 }
@@ -388,13 +408,12 @@ EncryptPageAegisCipher(void* cipher, int page, unsigned char* data, int len, int
388408 nonce , aegisCipher -> m_nonceLength , page );
389409
390410 /* Encrypt */
391- offset = (page == 1 ) ? CIPHER_PAGE1_OFFSET : 0 ;
392411 mcAegisCryptFunctions [aegisCipher -> m_aegisAlgorithm ].encryptNoTag (
393412 data + offset ,
394413 data + offset , mlen - offset ,
395414 otk + aegisCipher -> m_keyLength , otk );
396415
397- if (page == 1 )
416+ if (page == 1 && usePlaintextHeader == 0 )
398417 {
399418 memcpy (data , aegisCipher -> m_salt , SALTLENGTH_AEGIS );
400419 }
@@ -412,12 +431,28 @@ DecryptPageAegisCipher(void* cipher, int page, unsigned char* data, int len, int
412431 int n = len - nReserved ;
413432 uint64_t clen = n ;
414433 int tagOk ;
434+ int usePlaintextHeader = 0 ;
415435
416436 /* Generate one-time keys */
417437 uint8_t otk [OTK_LEN_MAX_AEGIS ];
418- int offset ;
438+ int offset = 0 ;
419439 memset (otk , 0 , OTK_LEN_MAX_AEGIS );
420440
441+ /* Check whether a plaintext header should be used */
442+ if (page == 1 )
443+ {
444+ int plaintextHeaderSize = aegisCipher -> m_plaintextHeaderSize ;
445+ if (plaintextHeaderSize > 0 )
446+ {
447+ usePlaintextHeader = 1 ;
448+ offset = (plaintextHeaderSize > CIPHER_PAGE1_OFFSET ) ? plaintextHeaderSize : CIPHER_PAGE1_OFFSET ;
449+ }
450+ else
451+ {
452+ offset = CIPHER_PAGE1_OFFSET ;
453+ }
454+ }
455+
421456 /* Check whether number of required reserved bytes and actually reserved bytes match */
422457 if (nReserved > reserved )
423458 {
@@ -431,8 +466,6 @@ DecryptPageAegisCipher(void* cipher, int page, unsigned char* data, int len, int
431466 data + n + PAGE_TAG_LEN_AEGIS , aegisCipher -> m_nonceLength , page );
432467
433468 /* Determine MAC and decrypt */
434- offset = (page == 1 ) ? CIPHER_PAGE1_OFFSET : 0 ;
435-
436469 if (hmacCheck != 0 )
437470 {
438471 /* Verify the MAC */
@@ -461,7 +494,7 @@ DecryptPageAegisCipher(void* cipher, int page, unsigned char* data, int len, int
461494 otk + aegisCipher -> m_keyLength , otk );
462495 }
463496
464- if (page == 1 && rc == SQLITE_OK )
497+ if (page == 1 && usePlaintextHeader == 0 && rc == SQLITE_OK )
465498 {
466499 memcpy (data , SQLITE_FILE_HEADER , 16 );
467500 }
@@ -475,13 +508,12 @@ DecryptPageAegisCipher(void* cipher, int page, unsigned char* data, int len, int
475508 nonce , aegisCipher -> m_nonceLength , page );
476509
477510 /* Decrypt */
478- offset = (page == 1 ) ? CIPHER_PAGE1_OFFSET : 0 ;
479511 mcAegisCryptFunctions [aegisCipher -> m_aegisAlgorithm ].decryptNoTag (
480512 data + offset ,
481513 data + offset , clen - offset ,
482514 otk + aegisCipher -> m_keyLength , otk );
483515
484- if (page == 1 )
516+ if (page == 1 && usePlaintextHeader == 0 )
485517 {
486518 memcpy (data , SQLITE_FILE_HEADER , 16 );
487519 }
0 commit comments