Coverage Report

Created: 2024-06-12 07:07

/src/libqcow/libqcow/libqcow_encryption.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Encryption functions
3
 *
4
 * Copyright (C) 2010-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libqcow_encryption.h"
28
#include "libqcow_libcaes.h"
29
#include "libqcow_libcerror.h"
30
31
/* Creates an encryption context
32
 * Make sure the value context is referencing, is set to NULL
33
 * Returns 1 if successful or -1 on error
34
 */
35
int libqcow_encryption_initialize(
36
     libqcow_encryption_context_t **context,
37
     uint32_t method,
38
     libcerror_error_t **error )
39
136
{
40
136
  static char *function = "libqcow_encryption_initialize";
41
42
136
  if( context == NULL )
43
0
  {
44
0
    libcerror_error_set(
45
0
     error,
46
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
47
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
48
0
     "%s: invalid context.",
49
0
     function );
50
51
0
    return( -1 );
52
0
  }
53
136
  if( *context != NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
58
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
59
0
     "%s: invalid context value already set.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
136
  *context = memory_allocate_structure(
65
136
              libqcow_encryption_context_t );
66
67
136
  if( *context == NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
72
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
73
0
     "%s: unable to create context.",
74
0
     function );
75
76
0
    goto on_error;
77
0
  }
78
136
  if( memory_set(
79
136
       *context,
80
136
       0,
81
136
       sizeof( libqcow_encryption_context_t ) ) == NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
86
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
87
0
     "%s: unable to clear context.",
88
0
     function );
89
90
0
    memory_free(
91
0
     *context );
92
93
0
    *context = NULL;
94
95
0
    return( -1 );
96
0
  }
97
136
  if( libcaes_context_initialize(
98
136
       &( ( *context )->decryption_context ),
99
136
       error ) != 1 )
100
0
  {
101
0
    libcerror_error_set(
102
0
     error,
103
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
104
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
105
0
     "%s: unable initialize decryption context.",
106
0
     function );
107
108
0
    goto on_error;
109
0
  }
110
136
  if( libcaes_context_initialize(
111
136
       &( ( *context )->encryption_context ),
112
136
       error ) != 1 )
113
0
  {
114
0
    libcerror_error_set(
115
0
     error,
116
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
117
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
118
0
     "%s: unable initialize encryption context.",
119
0
     function );
120
121
0
    goto on_error;
122
0
  }
123
136
  ( *context )->method = method;
124
125
136
  return( 1 );
126
127
0
on_error:
128
0
  if( *context != NULL )
129
0
  {
130
0
    if( ( *context )->decryption_context != NULL )
131
0
    {
132
0
      libcaes_context_free(
133
0
       &( ( *context )->decryption_context ),
134
0
       NULL );
135
0
    }
136
0
    memory_free(
137
0
     *context );
138
139
0
    *context = NULL;
140
0
  }
141
0
  return( -1 );
142
136
}
143
144
/* Frees an encryption context
145
 * Returns 1 if successful or -1 on error
146
 */
147
int libqcow_encryption_free(
148
     libqcow_encryption_context_t **context,
149
     libcerror_error_t **error )
150
136
{
151
136
  static char *function = "libqcow_encryption_free";
152
136
  int result            = 1;
153
154
136
  if( context == NULL )
155
0
  {
156
0
    libcerror_error_set(
157
0
     error,
158
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
159
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
160
0
     "%s: invalid context.",
161
0
     function );
162
163
0
    return( -1 );
164
0
  }
165
136
  if( *context != NULL )
166
136
  {
167
136
    if( libcaes_context_free(
168
136
         &( ( *context )->decryption_context ),
169
136
         error ) != 1 )
170
0
    {
171
0
      libcerror_error_set(
172
0
       error,
173
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
174
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
175
0
       "%s: unable free decryption context.",
176
0
       function );
177
178
0
      result = -1;
179
0
    }
180
136
    if( libcaes_context_free(
181
136
         &( ( *context )->encryption_context ),
182
136
         error ) != 1 )
183
0
    {
184
0
      libcerror_error_set(
185
0
       error,
186
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
187
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
188
0
       "%s: unable free encryption context.",
189
0
       function );
190
191
0
      result = -1;
192
0
    }
193
136
    memory_free(
194
136
     *context );
195
196
136
    *context = NULL;
197
136
  }
198
136
  return( result );
199
136
}
200
201
/* Sets the de- and encryption keys
202
 * Returns 1 if successful or -1 on error
203
 */
204
int libqcow_encryption_set_keys(
205
     libqcow_encryption_context_t *context,
206
     const uint8_t *key,
207
     size_t key_size,
208
     libcerror_error_t **error )
209
136
{
210
136
  static char *function = "libqcow_encryption_set_keys";
211
212
136
  if( context == NULL )
213
0
  {
214
0
    libcerror_error_set(
215
0
     error,
216
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
217
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
218
0
     "%s: invalid context.",
219
0
     function );
220
221
0
    return( -1 );
222
0
  }
223
136
  if( key == NULL )
224
0
  {
225
0
    libcerror_error_set(
226
0
     error,
227
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
228
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
229
0
     "%s: invalid key.",
230
0
     function );
231
232
0
    return( -1 );
233
0
  }
234
136
  if( key_size > (size_t) SSIZE_MAX )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
240
0
     "%s: invalid key size value exceeds maximum.",
241
0
     function );
242
243
0
    return( -1 );
244
0
  }
245
136
  if( key_size < 16 )
246
0
  {
247
0
    libcerror_error_set(
248
0
     error,
249
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
250
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
251
0
     "%s: invalid key value too small.",
252
0
     function );
253
254
0
    return( -1 );
255
0
  }
256
136
  if( libcaes_context_set_key(
257
136
       context->decryption_context,
258
136
       LIBCAES_CRYPT_MODE_DECRYPT,
259
136
       key,
260
136
       128,
261
136
       error ) != 1 )
262
0
  {
263
0
    libcerror_error_set(
264
0
     error,
265
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
266
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
267
0
     "%s: unable to set key in decryption context.",
268
0
     function );
269
270
0
    return( -1 );
271
0
  }
272
136
  if( libcaes_context_set_key(
273
136
       context->encryption_context,
274
136
       LIBCAES_CRYPT_MODE_ENCRYPT,
275
136
       key,
276
136
       128,
277
136
       error ) != 1 )
278
0
  {
279
0
    libcerror_error_set(
280
0
     error,
281
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
282
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
283
0
     "%s: unable to set key in encryption context.",
284
0
     function );
285
286
0
    return( -1 );
287
0
  }
288
136
  return( 1 );
289
136
}
290
291
/* De- or encrypts a block of data
292
 * Returns 1 if successful or -1 on error
293
 */
294
int libqcow_encryption_crypt(
295
     libqcow_encryption_context_t *context,
296
     int mode,
297
     const uint8_t *input_data,
298
     size_t input_data_size,
299
     uint8_t *output_data,
300
     size_t output_data_size,
301
     uint64_t block_key,
302
     libcerror_error_t **error )
303
0
{
304
0
  uint8_t initialization_vector[ 16 ];
305
306
0
  static char *function = "libqcow_encryption_crypt";
307
0
  size_t data_index     = 0;
308
309
0
  if( context == NULL )
310
0
  {
311
0
    libcerror_error_set(
312
0
     error,
313
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
314
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
315
0
     "%s: invalid context.",
316
0
     function );
317
318
0
    return( -1 );
319
0
  }
320
0
  if( ( mode != LIBQCOW_ENCYPTION_CRYPT_MODE_DECRYPT )
321
0
   && ( mode != LIBQCOW_ENCYPTION_CRYPT_MODE_ENCRYPT ) )
322
0
  {
323
0
    libcerror_error_set(
324
0
     error,
325
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
326
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
327
0
     "%s: unsupported mode.",
328
0
     function );
329
330
0
    return( -1 );
331
0
  }
332
0
  if( ( input_data_size % 512 ) != 0 )
333
0
  {
334
0
    libcerror_error_set(
335
0
     error,
336
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
337
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
338
0
     "%s: invalid input data size value of bounds.",
339
0
     function );
340
341
0
    return( -1 );
342
0
  }
343
0
  if( output_data_size < input_data_size )
344
0
  {
345
0
    libcerror_error_set(
346
0
     error,
347
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
348
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
349
0
     "%s: invalid output data size value of bounds.",
350
0
     function );
351
352
0
    return( -1 );
353
0
  }
354
0
  while( data_index < input_data_size )
355
0
  {
356
0
    if( memory_set(
357
0
         initialization_vector,
358
0
         0,
359
0
         16 ) == NULL )
360
0
    {
361
0
      libcerror_error_set(
362
0
       error,
363
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
364
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
365
0
       "%s: unable to clear initialization vector.",
366
0
       function );
367
368
0
      return( -1 );
369
0
    }
370
0
    byte_stream_copy_from_uint64_little_endian(
371
0
     initialization_vector,
372
0
     block_key );
373
374
0
    if( mode == LIBQCOW_ENCYPTION_CRYPT_MODE_ENCRYPT )
375
0
    {
376
0
      if( libcaes_crypt_cbc(
377
0
           context->encryption_context,
378
0
           LIBCAES_CRYPT_MODE_ENCRYPT,
379
0
           initialization_vector,
380
0
           16,
381
0
           &( input_data[ data_index ] ),
382
0
           512,
383
0
           &( output_data[ data_index ] ),
384
0
           512,
385
0
           error ) != 1 )
386
0
      {
387
0
        libcerror_error_set(
388
0
         error,
389
0
         LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
390
0
         LIBCERROR_ENCRYPTION_ERROR_GENERIC,
391
0
         "%s: unable to AES-CBC encrypt output data.",
392
0
         function );
393
394
0
        return( -1 );
395
0
      }
396
0
    }
397
0
    else
398
0
    {
399
0
      if( libcaes_crypt_cbc(
400
0
           context->decryption_context,
401
0
           LIBCAES_CRYPT_MODE_DECRYPT,
402
0
           initialization_vector,
403
0
           16,
404
0
           &( input_data[ data_index ] ),
405
0
           512,
406
0
           &( output_data[ data_index ] ),
407
0
           512,
408
0
           error ) != 1 )
409
0
      {
410
0
        libcerror_error_set(
411
0
         error,
412
0
         LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
413
0
         LIBCERROR_ENCRYPTION_ERROR_GENERIC,
414
0
         "%s: unable to AES-CBC decrypt output data.",
415
0
         function );
416
417
0
        return( -1 );
418
0
      }
419
0
    }
420
0
    data_index += 512;
421
0
    block_key  += 1;
422
0
  }
423
0
  return( 1 );
424
0
}
425