1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/*
* Codec class for SQLite3 encryption codec.
* (C) 2010 Olivier de Gaalon
*
* Distributed under the terms of the Botan license
*/
#include "codec.h"
#include <botan/init.h>
Codec::Codec(void *db)
{
InitializeCodec(db);
}
Codec::Codec(const Codec& other, void *db)
{
//Only used to copy main db key for an attached db
InitializeCodec(db);
m_hasReadKey = other.m_hasReadKey;
m_hasWriteKey = other.m_hasWriteKey;
m_readKey = other.m_readKey;
m_ivReadKey = other.m_ivReadKey;
m_writeKey = other.m_writeKey;
m_ivWriteKey = other.m_ivWriteKey;
}
void
Codec::InitializeCodec(void *db)
{
bool botanInitialized = false;
Library_State* state = swap_global_state(0);
if(state)
{
botanInitialized = true;
swap_global_state(state); // should return NULL FIXME: what if not?
}
if (!botanInitialized)
LibraryInitializer::initialize();
m_hasReadKey = false;
m_hasWriteKey = false;
m_db = db;
m_encipherFilter = get_cipher(BLOCK_CIPHER_STR, ENCRYPTION);
m_decipherFilter = get_cipher(BLOCK_CIPHER_STR, DECRYPTION);
m_cmac = new MAC_Filter(MAC_STR);
m_encipherPipe.append(m_encipherFilter);
m_decipherPipe.append(m_decipherFilter);
m_macPipe.append(m_cmac);
}
void
Codec::GenerateWriteKey(const char* userPassword, int passwordLength)
{
S2K* s2k = get_s2k(S2K_STR);
s2k->set_iterations(S2K_ITERATIONS);
s2k->change_salt((const byte*)SALT_STR.c_str(), SALT_SIZE);
SymmetricKey masterKey =
s2k->derive_key(KEY_SIZE + IV_DERIVATION_KEY_SIZE, std::string(userPassword, passwordLength));
m_writeKey = SymmetricKey(masterKey.bits_of(), KEY_SIZE);
m_ivWriteKey = SymmetricKey(masterKey.bits_of() + KEY_SIZE, IV_DERIVATION_KEY_SIZE);
m_hasWriteKey = true;
}
void
Codec::DropWriteKey()
{
m_hasWriteKey = false;
}
void
Codec::SetReadIsWrite()
{
m_readKey = m_writeKey;
m_ivReadKey = m_ivWriteKey;
m_hasReadKey = m_hasWriteKey;
}
void
Codec::SetWriteIsRead()
{
m_writeKey = m_readKey;
m_ivWriteKey = m_ivReadKey;
m_hasWriteKey = m_hasReadKey;
}
unsigned char *
Codec::Encrypt(int page, unsigned char* data, bool useWriteKey)
{
memcpy(m_page, data, m_pageSize);
m_encipherFilter->set_key(useWriteKey ? m_writeKey : m_readKey);
m_encipherFilter->set_iv(GetIVForPage(page, useWriteKey));
m_encipherPipe.process_msg(m_page, m_pageSize);
m_encipherPipe.read(m_page, m_encipherPipe.remaining(Pipe::LAST_MESSAGE), Pipe::LAST_MESSAGE);
return m_page; //return location of newly ciphered data
}
void
Codec::Decrypt(int page, unsigned char* data)
{
m_decipherFilter->set_key(m_readKey);
m_decipherFilter->set_iv(GetIVForPage(page, false));
m_decipherPipe.process_msg(data, m_pageSize);
m_decipherPipe.read(data, m_decipherPipe.remaining(Pipe::LAST_MESSAGE), Pipe::LAST_MESSAGE);
}
InitializationVector
Codec::GetIVForPage(u32bit page, bool useWriteKey)
{
static unsigned char* intiv[4];
store_le(page, (byte*)intiv);
m_cmac->set_key(useWriteKey ? m_ivWriteKey : m_ivReadKey);
m_macPipe.process_msg((byte*)intiv, 4);
return m_macPipe.read_all(Pipe::LAST_MESSAGE);
}
|