~laurynas-biveinis/percona-xtrabackup/BT-28340-bug1158154-2.1

« back to all changes in this revision

Viewing changes to src/xbcrypt_read.c

MergedĀ lp:~gl-az/percona-xtrabackup/BT-23557-2.1-encrypted_stream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
Copyright (c) 2011 Percona Ireland Ltd.
 
3
 
 
4
The xbcrypt format reader implementation.
 
5
 
 
6
This program is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation; version 2 of the License.
 
9
 
 
10
This program is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
GNU General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU General Public License
 
16
along with this program; if not, write to the Free Software
 
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
18
 
 
19
*******************************************************/
 
20
 
 
21
#include "xbcrypt.h"
 
22
 
 
23
struct xb_rcrypt_struct {
 
24
        void                            *userdata;
 
25
        xb_crypt_read_callback          *read;
 
26
        void                            *buffer;
 
27
        size_t                          bufsize;
 
28
        ulonglong                       offset;
 
29
};
 
30
 
 
31
xb_rcrypt_t *
 
32
xb_crypt_read_open(void *userdata, xb_crypt_read_callback *onread)
 
33
{
 
34
        xb_rcrypt_t     *crypt;
 
35
 
 
36
        xb_ad(onread);
 
37
 
 
38
        crypt = (xb_rcrypt_t *) my_malloc(sizeof(xb_rcrypt_t), MYF(MY_FAE));
 
39
 
 
40
        crypt->userdata = userdata;
 
41
        crypt->read = onread;
 
42
        crypt->buffer = NULL;
 
43
        crypt->bufsize = 0;
 
44
        crypt->offset = 0;
 
45
 
 
46
        return crypt;
 
47
}
 
48
 
 
49
xb_rcrypt_result_t
 
50
xb_crypt_read_chunk(xb_rcrypt_t *crypt, void **buf, size_t *olen, size_t *elen)
 
51
{
 
52
        uchar           tmpbuf[XB_CRYPT_CHUNK_MAGIC_SIZE + 8 + 8 + 8 + 4];
 
53
        uchar           *ptr;
 
54
        ulonglong       tmp;
 
55
        ulong           checksum, checksum_exp;
 
56
        ssize_t         bytesread;
 
57
        xb_rcrypt_result_t result = XB_CRYPT_READ_CHUNK;
 
58
 
 
59
        if ((bytesread = crypt->read(crypt->userdata, tmpbuf, sizeof(tmpbuf)))
 
60
            != sizeof(tmpbuf)) {
 
61
                if (bytesread == 0) {
 
62
                        result = XB_CRYPT_READ_EOF;
 
63
                        goto err;
 
64
                } else {
 
65
                        msg("%s:%s: unable to read chunk header data at "
 
66
                            "offset 0x%llx.\n",
 
67
                            my_progname, __FUNCTION__, crypt->offset);
 
68
                        result =  XB_CRYPT_READ_ERROR;
 
69
                        goto err;
 
70
                }
 
71
        }
 
72
 
 
73
        ptr = tmpbuf;
 
74
 
 
75
        if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC, XB_CRYPT_CHUNK_MAGIC_SIZE)
 
76
            != 0) {
 
77
                msg("%s:%s: wrong chunk magic at offset 0x%llx.\n",
 
78
                    my_progname, __FUNCTION__, crypt->offset);
 
79
                result = XB_CRYPT_READ_ERROR;
 
80
                goto err;
 
81
        }
 
82
 
 
83
        ptr += XB_CRYPT_CHUNK_MAGIC_SIZE;
 
84
        crypt->offset += XB_CRYPT_CHUNK_MAGIC_SIZE;
 
85
 
 
86
        tmp = uint8korr(ptr);   /* reserved */
 
87
        ptr += 8;
 
88
        crypt->offset += 8;
 
89
 
 
90
        tmp = uint8korr(ptr);   /* original size */
 
91
        ptr += 8;
 
92
        if (tmp > INT_MAX) {
 
93
                msg("%s:%s: invalid original size at offset 0x%llx.\n",
 
94
                    my_progname, __FUNCTION__, crypt->offset);
 
95
                result = XB_CRYPT_READ_ERROR;
 
96
                goto err;
 
97
        }
 
98
        crypt->offset += 8;
 
99
        *olen = (size_t)tmp;
 
100
 
 
101
        tmp = uint8korr(ptr);   /* encrypted size */
 
102
        ptr += 8;
 
103
        if (tmp > INT_MAX) {
 
104
                msg("%s:%s: invalid encrypted size at offset 0x%llx.\n",
 
105
                    my_progname, __FUNCTION__, crypt->offset);
 
106
                result = XB_CRYPT_READ_ERROR;
 
107
                goto err;
 
108
        }
 
109
        crypt->offset += 8;
 
110
        *elen = (size_t)tmp;
 
111
 
 
112
        checksum_exp = uint4korr(ptr);  /* checksum */
 
113
        ptr += 4;
 
114
        crypt->offset += 4;
 
115
 
 
116
        if (*olen > crypt->bufsize) {
 
117
                if (crypt->buffer) {
 
118
                        crypt->buffer = my_realloc(crypt->buffer, *olen,
 
119
                                                   MYF(MY_WME));
 
120
                        if (crypt->buffer == NULL) {
 
121
                                msg("%s:%s: failed to increase buffer to "
 
122
                                    "%llu bytes.\n", my_progname, __FUNCTION__,
 
123
                                    (ulonglong)*olen);
 
124
                                result = XB_CRYPT_READ_ERROR;
 
125
                                goto err;
 
126
                        }
 
127
                } else {
 
128
                        crypt->buffer = my_malloc(*olen, MYF(MY_WME));
 
129
                        if (crypt->buffer == NULL) {
 
130
                                msg("%s:%s: failed to allocate buffer of "
 
131
                                    "%llu bytes.\n", my_progname, __FUNCTION__,
 
132
                                    (ulonglong)*olen);
 
133
                                result = XB_CRYPT_READ_ERROR;
 
134
                                goto err;
 
135
                        }
 
136
                }
 
137
                crypt->bufsize = *olen;
 
138
        }
 
139
 
 
140
        if (*elen > 0) {
 
141
                if (crypt->read(crypt->userdata, crypt->buffer, *elen)
 
142
                    != (ssize_t)*elen) {
 
143
                        msg("%s:%s: failed to read %lld bytes for chunk payload "
 
144
                            "at offset 0x%llx.\n", my_progname, __FUNCTION__,
 
145
                            (ulonglong)*elen, crypt->offset);
 
146
                        result = XB_CRYPT_READ_ERROR;
 
147
                        goto err;
 
148
                }
 
149
        }
 
150
 
 
151
        checksum = crc32(0, crypt->buffer, *elen);
 
152
        if (checksum != checksum_exp) {
 
153
                msg("%s:%s invalid checksum at offset 0x%llx, "
 
154
                    "expected 0x%lx, actual 0x%lx.\n", my_progname, __FUNCTION__,
 
155
                    crypt->offset, checksum_exp, checksum);
 
156
                result = XB_CRYPT_READ_ERROR;
 
157
                goto err;
 
158
        }
 
159
 
 
160
        crypt->offset += *elen;
 
161
        *buf = crypt->buffer;
 
162
        goto exit;
 
163
 
 
164
err:
 
165
        *buf = NULL;
 
166
        *olen = 0;
 
167
        *elen = 0;
 
168
exit:
 
169
        return result;
 
170
}
 
171
 
 
172
int xb_crypt_read_close(xb_rcrypt_t *crypt)
 
173
{
 
174
        if (crypt->buffer)
 
175
                MY_FREE(crypt->buffer);
 
176
        MY_FREE(crypt);
 
177
 
 
178
        return 0;
 
179
}
 
180