aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/AES_PDF_native.cc
blob: afbc0bdc869efa6b491a10a7c4936efe34d8c114 (plain) (blame)
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
#include <qpdf/AES_PDF_native.hh>

#include <qpdf/QUtil.hh>
#include <cstring>
#include <assert.h>
#include <stdexcept>
#include <qpdf/rijndael.h>
#include <qpdf/QIntC.hh>
#include <string>
#include <stdlib.h>
#include <qpdf/QPDFCryptoImpl.hh>

AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key,
                               size_t key_bytes, bool cbc_mode,
                               unsigned char* cbc_block) :
    encrypt(encrypt),
    cbc_mode(cbc_mode),
    cbc_block(cbc_block),
    nrounds(0)
{
    size_t keybits = 8 * key_bytes;
    this->key = std::make_unique<unsigned char[]>(key_bytes);
    this->rk = std::make_unique<uint32_t[]>(RKLENGTH(keybits));
    size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
    std::memcpy(this->key.get(), key, key_bytes);
    std::memset(this->rk.get(), 0, rk_bytes);
    if (encrypt)
    {
	this->nrounds = rijndaelSetupEncrypt(
            this->rk.get(), this->key.get(), keybits);
    }
    else
    {
	this->nrounds = rijndaelSetupDecrypt(
            this->rk.get(), this->key.get(), keybits);
    }
}

AES_PDF_native::~AES_PDF_native()
{
}

void
AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data)
{
    if (this->encrypt)
    {
	if (this->cbc_mode)
	{
	    for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i)
	    {
		in_data[i] ^= this->cbc_block[i];
	    }
	}
	rijndaelEncrypt(this->rk.get(),
                        this->nrounds, in_data, out_data);
	if (this->cbc_mode)
	{
	    memcpy(this->cbc_block, out_data,
                   QPDFCryptoImpl::rijndael_buf_size);
	}
    }
    else
    {
	rijndaelDecrypt(this->rk.get(),
                        this->nrounds, in_data, out_data);
	if (this->cbc_mode)
	{
	    for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i)
	    {
		out_data[i] ^= this->cbc_block[i];
	    }
	    memcpy(this->cbc_block, in_data,
                   QPDFCryptoImpl::rijndael_buf_size);
	}
    }
}