aboutsummaryrefslogtreecommitdiffstats
path: root/src/wrap/sqlite/codec.cpp
blob: 5dfcea82e8573dbb95c6e99f66844a89b5765c63 (plain)
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);
}