mirror of
https://github.com/tursodatabase/libsql.git
synced 2025-06-06 13:21:57 +00:00
173 lines
4.2 KiB
C
173 lines
4.2 KiB
C
/*
|
|
** Name: cipher_sds_rc4.c
|
|
** Purpose: Implementation of cipher System.Data.SQLite3 RC4
|
|
** Author: Ulrich Telle
|
|
** Created: 2020-02-02
|
|
** Copyright: (c) 2006-2020 Ulrich Telle
|
|
** License: MIT
|
|
*/
|
|
|
|
#include "cipher_common.h"
|
|
|
|
/* --- RC4 cipher (System.Data.SQLite) --- */
|
|
#if HAVE_CIPHER_RC4
|
|
|
|
#define CIPHER_NAME_RC4 "rc4"
|
|
|
|
/*
|
|
** Configuration parameters for "rc4"
|
|
**
|
|
** - legacy mode : compatibility with System.Data.SQLite encryption
|
|
** (page 1 fully encrypted)
|
|
** only legacy mode is supported
|
|
** possible value: 1 = yes
|
|
*/
|
|
|
|
#define RC4_LEGACY_DEFAULT 1
|
|
|
|
SQLITE_PRIVATE CipherParams mcRC4Params[] =
|
|
{
|
|
{ "legacy", RC4_LEGACY_DEFAULT, RC4_LEGACY_DEFAULT, RC4_LEGACY_DEFAULT, RC4_LEGACY_DEFAULT },
|
|
{ "legacy_page_size", 0, 0, 0, SQLITE_MAX_PAGE_SIZE },
|
|
CIPHER_PARAMS_SENTINEL
|
|
};
|
|
|
|
|
|
#define KEYLENGTH_RC4 16
|
|
|
|
typedef struct _RC4Cipher
|
|
{
|
|
int m_legacy;
|
|
int m_legacyPageSize;
|
|
int m_keyLength;
|
|
uint8_t m_key[KEYLENGTH_RC4];
|
|
} RC4Cipher;
|
|
|
|
static void*
|
|
AllocateRC4Cipher(sqlite3* db)
|
|
{
|
|
RC4Cipher* rc4Cipher = (RC4Cipher*) sqlite3_malloc(sizeof(RC4Cipher));
|
|
if (rc4Cipher != NULL)
|
|
{
|
|
rc4Cipher->m_keyLength = KEYLENGTH_RC4;
|
|
memset(rc4Cipher->m_key, 0, KEYLENGTH_RC4);
|
|
}
|
|
if (rc4Cipher != NULL)
|
|
{
|
|
CipherParams* cipherParams = sqlite3mcGetCipherParams(db, CIPHER_NAME_RC4);
|
|
rc4Cipher->m_legacy = sqlite3mcGetCipherParameter(cipherParams, "legacy");
|
|
rc4Cipher->m_legacyPageSize = sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size");
|
|
}
|
|
return rc4Cipher;
|
|
}
|
|
|
|
static void
|
|
FreeRC4Cipher(void* cipher)
|
|
{
|
|
RC4Cipher* localCipher = (RC4Cipher*) cipher;
|
|
memset(localCipher, 0, sizeof(RC4Cipher));
|
|
sqlite3_free(localCipher);
|
|
}
|
|
|
|
static void
|
|
CloneRC4Cipher(void* cipherTo, void* cipherFrom)
|
|
{
|
|
RC4Cipher* rc4CipherTo = (RC4Cipher*) cipherTo;
|
|
RC4Cipher* rc4CipherFrom = (RC4Cipher*) cipherFrom;
|
|
rc4CipherTo->m_legacy = rc4CipherFrom->m_legacy;
|
|
rc4CipherTo->m_legacyPageSize = rc4CipherFrom->m_legacyPageSize;
|
|
rc4CipherTo->m_keyLength = rc4CipherFrom->m_keyLength;
|
|
memcpy(rc4CipherTo->m_key, rc4CipherFrom->m_key, KEYLENGTH_RC4);
|
|
}
|
|
|
|
static int
|
|
GetLegacyRC4Cipher(void* cipher)
|
|
{
|
|
RC4Cipher* rc4Cipher = (RC4Cipher*)cipher;
|
|
return rc4Cipher->m_legacy;
|
|
}
|
|
|
|
static int
|
|
GetPageSizeRC4Cipher(void* cipher)
|
|
{
|
|
RC4Cipher* rc4Cipher = (RC4Cipher*) cipher;
|
|
int pageSize = 0;
|
|
if (rc4Cipher->m_legacy != 0)
|
|
{
|
|
pageSize = rc4Cipher->m_legacyPageSize;
|
|
if ((pageSize < 512) || (pageSize > SQLITE_MAX_PAGE_SIZE) || (((pageSize - 1) & pageSize) != 0))
|
|
{
|
|
pageSize = 0;
|
|
}
|
|
}
|
|
return pageSize;
|
|
}
|
|
|
|
static int
|
|
GetReservedRC4Cipher(void* cipher)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static unsigned char*
|
|
GetSaltRC4Cipher(void* cipher)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
GenerateKeyRC4Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt)
|
|
{
|
|
RC4Cipher* rc4Cipher = (RC4Cipher*) cipher;
|
|
unsigned char digest[SHA1_DIGEST_SIZE];
|
|
sha1_ctx ctx;
|
|
|
|
sha1_init(&ctx);
|
|
sha1_update(&ctx, userPassword, passwordLength);
|
|
sha1_final(&ctx, digest);
|
|
|
|
memcpy(rc4Cipher->m_key, digest, 16);
|
|
/* memset(rc4Cipher->m_key+5, 0, rc4Cipher->m_keyLength-5);*/
|
|
}
|
|
|
|
static int
|
|
EncryptPageRC4Cipher(void* cipher, int page, unsigned char* data, int len, int reserved)
|
|
{
|
|
RC4Cipher* rc4Cipher = (RC4Cipher*) cipher;
|
|
int rc = SQLITE_OK;
|
|
|
|
/* Use the legacy encryption scheme */
|
|
unsigned char* key = rc4Cipher->m_key;
|
|
sqlite3mcRC4(key, rc4Cipher->m_keyLength, data, len, data);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int
|
|
DecryptPageRC4Cipher(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck)
|
|
{
|
|
RC4Cipher* rc4Cipher = (RC4Cipher*) cipher;
|
|
int rc = SQLITE_OK;
|
|
|
|
/* Use the legacy encryption scheme */
|
|
sqlite3mcRC4(rc4Cipher->m_key, rc4Cipher->m_keyLength, data, len, data);
|
|
|
|
return rc;
|
|
}
|
|
|
|
SQLITE_PRIVATE const CipherDescriptor mcRC4Descriptor =
|
|
{
|
|
CIPHER_NAME_RC4,
|
|
AllocateRC4Cipher,
|
|
FreeRC4Cipher,
|
|
CloneRC4Cipher,
|
|
GetLegacyRC4Cipher,
|
|
GetPageSizeRC4Cipher,
|
|
GetReservedRC4Cipher,
|
|
GetSaltRC4Cipher,
|
|
GenerateKeyRC4Cipher,
|
|
EncryptPageRC4Cipher,
|
|
DecryptPageRC4Cipher
|
|
};
|
|
#endif
|