VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/cipher-openssl.cpp@ 95841

Last change on this file since 95841 was 94668, checked in by vboxsync, 3 years ago

Runtime/crypto: Add additional APIs and supported algorithms for symmetric enc-/decryption, ​bugref:9955 [build fix for older openssl versions]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.6 KB
Line 
1/* $Id: cipher-openssl.cpp 94668 2022-04-21 13:55:27Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Symmetric Cipher using OpenSSL.
4 */
5
6/*
7 * Copyright (C) 2018-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#ifdef IPRT_WITH_OPENSSL
32# include "internal/iprt.h"
33# include <iprt/crypto/cipher.h>
34
35# include <iprt/asm.h>
36# include <iprt/assert.h>
37# include <iprt/err.h>
38# include <iprt/mem.h>
39# include <iprt/string.h>
40
41# include "internal/iprt-openssl.h"
42# include "internal/openssl-pre.h"
43# include <openssl/evp.h>
44# include "internal/openssl-post.h"
45
46# include "internal/magics.h"
47
48
49/*********************************************************************************************************************************
50* Defined Constants And Macros *
51*********************************************************************************************************************************/
52#if defined(EVP_CTRL_AEAD_GET_TAG)
53# define MY_EVP_CTRL_AEAD_GET_TAG EVP_CTRL_AEAD_GET_TAG
54#else
55# define MY_EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
56#endif
57
58#if defined(EVP_CTRL_AEAD_SET_TAG)
59# define MY_EVP_CTRL_AEAD_SET_TAG EVP_CTRL_AEAD_SET_TAG
60#else
61# define MY_EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
62#endif
63
64
65/*********************************************************************************************************************************
66* Structures and Typedefs *
67*********************************************************************************************************************************/
68/**
69 * OpenSSL cipher instance data.
70 */
71typedef struct RTCRCIPHERINT
72{
73 /** Magic value (RTCRCIPHERINT_MAGIC). */
74 uint32_t u32Magic;
75 /** Reference count. */
76 uint32_t volatile cRefs;
77 /** The cihper. */
78 const EVP_CIPHER *pCipher;
79 /** The IPRT cipher type, if we know it. */
80 RTCRCIPHERTYPE enmType;
81} RTCRCIPHERINT;
82
83
84/**
85 * OpenSSL cipher context data
86 */
87typedef struct RTCRCIPHERCTXINT
88{
89 /** Pointer to cipher instance data */
90 RTCRCIPHERINT *phCipher;
91 /** Pointer to cipher context */
92 EVP_CIPHER_CTX *pCipherCtx;
93 /** Is decryption */
94 bool fDecryption;
95} RTCRCIPHERCTXINT;
96
97
98RTDECL(int) RTCrCipherOpenByType(PRTCRCIPHER phCipher, RTCRCIPHERTYPE enmType, uint32_t fFlags)
99{
100 AssertPtrReturn(phCipher, VERR_INVALID_POINTER);
101 *phCipher = NIL_RTCRCIPHER;
102 AssertReturn(!fFlags, VERR_INVALID_FLAGS);
103
104 /*
105 * Translate the IPRT cipher type to EVP cipher.
106 */
107 const EVP_CIPHER *pCipher = NULL;
108 switch (enmType)
109 {
110 case RTCRCIPHERTYPE_XTS_AES_128:
111 pCipher = EVP_aes_128_xts();
112 break;
113 case RTCRCIPHERTYPE_XTS_AES_256:
114 pCipher = EVP_aes_256_xts();
115 break;
116 case RTCRCIPHERTYPE_GCM_AES_128:
117 pCipher = EVP_aes_128_gcm();
118 break;
119 case RTCRCIPHERTYPE_GCM_AES_256:
120 pCipher = EVP_aes_256_gcm();
121 break;
122 case RTCRCIPHERTYPE_CTR_AES_128:
123 pCipher = EVP_aes_128_ctr();
124 break;
125 case RTCRCIPHERTYPE_CTR_AES_256:
126 pCipher = EVP_aes_256_ctr();
127 break;
128
129 /* no default! */
130 case RTCRCIPHERTYPE_INVALID:
131 case RTCRCIPHERTYPE_END:
132 case RTCRCIPHERTYPE_32BIT_HACK:
133 AssertFailedReturn(VERR_INVALID_PARAMETER);
134 }
135 AssertReturn(pCipher, VERR_CR_CIPHER_NOT_SUPPORTED);
136
137 /*
138 * Create the instance.
139 */
140 RTCRCIPHERINT *pThis = (RTCRCIPHERINT *)RTMemAllocZ(sizeof(*pThis));
141 if (pThis)
142 {
143 pThis->u32Magic = RTCRCIPHERINT_MAGIC;
144 pThis->cRefs = 1;
145 pThis->pCipher = pCipher;
146 pThis->enmType = enmType;
147 *phCipher = pThis;
148 return VINF_SUCCESS;
149 }
150 return VERR_NO_MEMORY;
151}
152
153
154RTDECL(uint32_t) RTCrCipherRetain(RTCRCIPHER hCipher)
155{
156 RTCRCIPHERINT *pThis = hCipher;
157 AssertPtrReturn(pThis, UINT32_MAX);
158 AssertReturn(pThis->u32Magic == RTCRCIPHERINT_MAGIC, UINT32_MAX);
159
160 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
161 Assert(cRefs > 1 && cRefs < 1024);
162 return cRefs;
163}
164
165
166/**
167 * Destroys the cipher instance.
168 */
169static uint32_t rtCrCipherDestroy(RTCRCIPHER pThis)
170{
171 pThis->u32Magic= ~RTCRCIPHERINT_MAGIC;
172 pThis->pCipher = NULL;
173 RTMemFree(pThis);
174 return 0;
175}
176
177
178RTDECL(uint32_t) RTCrCipherRelease(RTCRCIPHER hCipher)
179{
180 RTCRCIPHERINT *pThis = hCipher;
181 if (pThis == NIL_RTCRCIPHER)
182 return 0;
183 AssertPtrReturn(pThis, UINT32_MAX);
184 AssertReturn(pThis->u32Magic == RTCRCIPHERINT_MAGIC, UINT32_MAX);
185
186 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
187 Assert(cRefs < 1024);
188 if (cRefs == 0)
189 return rtCrCipherDestroy(pThis);
190 return cRefs;
191}
192
193
194RTDECL(uint32_t) RTCrCipherGetKeyLength(RTCRCIPHER hCipher)
195{
196 RTCRCIPHERINT *pThis = hCipher;
197 AssertPtrReturn(pThis, 0);
198 AssertReturn(pThis->u32Magic == RTCRCIPHERINT_MAGIC, 0);
199
200 return EVP_CIPHER_key_length(pThis->pCipher);
201}
202
203
204RTDECL(uint32_t) RTCrCipherGetInitializationVectorLength(RTCRCIPHER hCipher)
205{
206 RTCRCIPHERINT *pThis = hCipher;
207 AssertPtrReturn(pThis, 0);
208 AssertReturn(pThis->u32Magic == RTCRCIPHERINT_MAGIC, 0);
209
210 return EVP_CIPHER_iv_length(pThis->pCipher);
211}
212
213
214RTDECL(uint32_t) RTCrCipherGetBlockSize(RTCRCIPHER hCipher)
215{
216 RTCRCIPHERINT *pThis = hCipher;
217 AssertPtrReturn(pThis, 0);
218 AssertReturn(pThis->u32Magic == RTCRCIPHERINT_MAGIC, 0);
219
220 return EVP_CIPHER_block_size(pThis->pCipher);
221}
222
223
224RTDECL(int) RTCrCipherCtxFree(RTCRCIPHERCTX hCipherCtx)
225{
226 AssertReturn(hCipherCtx, VERR_INVALID_PARAMETER);
227 RTCRCIPHERCTXINT *pCtx = hCipherCtx;
228
229# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
230 EVP_CIPHER_CTX_free(pCtx->pCipherCtx);
231# else
232 EVP_CIPHER_CTX_cleanup(pCtx->pCipherCtx);
233 RTMemFree(pCtx->pCipherCtx);
234# endif
235 RTMemFree(pCtx);
236
237 return VINF_SUCCESS;
238}
239
240
241RTDECL(int) RTCrCipherCtxEncryptInit(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
242 void const *pvInitVector, size_t cbInitVector,
243 void const *pvAuthData, size_t cbAuthData,
244 PRTCRCIPHERCTX phCipherCtx)
245{
246 /*
247 * Validate input.
248 */
249 RTCRCIPHERINT *pThis = hCipher;
250 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
251 AssertReturn(pThis->u32Magic == RTCRCIPHERINT_MAGIC, VERR_INVALID_HANDLE);
252 AssertMsgReturn((ssize_t)cbKey == EVP_CIPHER_key_length(pThis->pCipher),
253 ("%zu, expected %d\n", cbKey, EVP_CIPHER_key_length(pThis->pCipher)),
254 VERR_CR_CIPHER_INVALID_KEY_LENGTH);
255 AssertMsgReturn((ssize_t)cbInitVector == EVP_CIPHER_iv_length(pThis->pCipher),
256 ("%zu, expected %d\n", cbInitVector, EVP_CIPHER_iv_length(pThis->pCipher)),
257 VERR_CR_CIPHER_INVALID_INITIALIZATION_VECTOR_LENGTH);
258
259 Assert(EVP_CIPHER_block_size(pThis->pCipher) <= 1); /** @todo more complicated ciphers later */
260
261 /*
262 * Allocate and initialize the cipher context.
263 */
264 int rc = VERR_NO_MEMORY;
265 /*
266 * Create the instance.
267 */
268 RTCRCIPHERCTXINT *pCtx = (RTCRCIPHERCTXINT *)RTMemAlloc(sizeof(RTCRCIPHERCTXINT));
269 if (pCtx)
270 {
271 pCtx->phCipher = hCipher;
272 pCtx->fDecryption = false;
273# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
274 pCtx->pCipherCtx = EVP_CIPHER_CTX_new();
275 if (pCtx->pCipherCtx)
276# else
277 pCtx->pCipherCtx = (EVP_CIPHER_CTX *)RTMemAllocZ(sizeof(EVP_CIPHER_CTX));
278# endif
279 {
280 if (EVP_EncryptInit(pCtx->pCipherCtx, pCtx->phCipher->pCipher, (unsigned char const *)pvKey,
281 (unsigned char const *)pvInitVector))
282 {
283 if (pvAuthData && cbAuthData)
284 {
285 /* Add auth data. */
286 int cbEncryptedAuth = 0;
287 rc = EVP_EncryptUpdate(pCtx->pCipherCtx, NULL, &cbEncryptedAuth,
288 (unsigned char const *)pvAuthData, (int)cbAuthData) ? VINF_SUCCESS
289 : VERR_CR_CIPHER_OSSL_ENCRYPT_UPDATE_FAILED;
290 }
291 else
292 rc = VINF_SUCCESS;
293 }
294 else
295 rc = VERR_CR_CIPHER_OSSL_ENCRYPT_INIT_FAILED;
296 }
297 }
298
299 if (RT_SUCCESS(rc))
300 *phCipherCtx = pCtx;
301 else
302 RTCrCipherCtxFree(pCtx);
303 return rc;
304}
305
306
307RTDECL(int) RTCrCipherCtxEncryptProcess(RTCRCIPHERCTX hCipherCtx, void const *pvPlainText, size_t cbPlainText,
308 void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted)
309{
310 AssertReturn(hCipherCtx, VERR_INVALID_PARAMETER);
311 AssertReturn(cbPlainText > 0, VERR_NO_DATA);
312 AssertReturn((size_t)(int)cbPlainText == cbPlainText && (int)cbPlainText > 0, VERR_OUT_OF_RANGE);
313 AssertReturn(cbEncrypted >= cbPlainText, VERR_BUFFER_OVERFLOW);
314
315 RTCRCIPHERCTXINT *pCtx = hCipherCtx;
316 AssertReturn(!pCtx->fDecryption, VERR_INVALID_STATE);
317 int cbEncrypted1 = 0;
318 int rc = VERR_CR_CIPHER_OSSL_ENCRYPT_UPDATE_FAILED;
319 if (EVP_EncryptUpdate(pCtx->pCipherCtx, (unsigned char *)pvEncrypted, &cbEncrypted1,
320 (unsigned char const *)pvPlainText, (int)cbPlainText))
321 {
322 *pcbEncrypted = cbEncrypted1;
323 rc = VINF_SUCCESS;
324 }
325 return rc;
326}
327
328
329RTDECL(int) RTCrCipherCtxEncryptFinish(RTCRCIPHERCTX hCipherCtx,
330 void *pvEncrypted, size_t *pcbEncrypted,
331 void *pvTag, size_t cbTag, size_t *pcbTag)
332{
333 AssertReturn(hCipherCtx, VERR_INVALID_PARAMETER);
334 RTCRCIPHERCTXINT *pCtx = hCipherCtx;
335 AssertReturn(!pCtx->fDecryption, VERR_INVALID_STATE);
336 AssertReturn(!pvTag || (pvTag && cbTag == 16), VERR_CR_CIPHER_INVALID_TAG_LENGTH);
337 int cbEncrypted2 = 0;
338 int rc = VERR_CR_CIPHER_OSSL_ENCRYPT_FINAL_FAILED;
339 if (EVP_EncryptFinal(pCtx->pCipherCtx, (uint8_t *)pvEncrypted, &cbEncrypted2))
340 {
341 if (pvTag && cbTag)
342 {
343 if (EVP_CIPHER_CTX_ctrl(pCtx->pCipherCtx, MY_EVP_CTRL_AEAD_GET_TAG, (int)cbTag, pvTag))
344 {
345 *pcbTag = cbTag;
346 rc = VINF_SUCCESS;
347 }
348 else
349 rc = VERR_CR_CIPHER_OSSL_GET_TAG_FAILED;
350 }
351 else
352 rc = VINF_SUCCESS;
353
354 if (RT_SUCCESS(rc) && pcbEncrypted)
355 *pcbEncrypted = cbEncrypted2;
356 }
357
358 return rc;
359}
360
361
362RTDECL(int) RTCrCipherCtxDecryptInit(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
363 void const *pvInitVector, size_t cbInitVector,
364 void const *pvAuthData, size_t cbAuthData,
365 void *pvTag, size_t cbTag, PRTCRCIPHERCTX phCipherCtx)
366{
367 /*
368 * Validate input.
369 */
370 RTCRCIPHERINT *pThis = hCipher;
371 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
372 AssertReturn(pThis->u32Magic == RTCRCIPHERINT_MAGIC, VERR_INVALID_HANDLE);
373 AssertMsgReturn((ssize_t)cbKey == EVP_CIPHER_key_length(pThis->pCipher),
374 ("%zu, expected %d\n", cbKey, EVP_CIPHER_key_length(pThis->pCipher)),
375 VERR_CR_CIPHER_INVALID_KEY_LENGTH);
376 AssertMsgReturn((ssize_t)cbInitVector == EVP_CIPHER_iv_length(pThis->pCipher),
377 ("%zu, expected %d\n", cbInitVector, EVP_CIPHER_iv_length(pThis->pCipher)),
378 VERR_CR_CIPHER_INVALID_INITIALIZATION_VECTOR_LENGTH);
379 AssertReturn(!pvTag || (pvTag && cbTag == 16), VERR_CR_CIPHER_INVALID_TAG_LENGTH);
380
381 Assert(EVP_CIPHER_block_size(pThis->pCipher) <= 1); /** @todo more complicated ciphers later */
382
383 /*
384 * Allocate and initialize the cipher context.
385 */
386 int rc = VERR_NO_MEMORY;
387 /*
388 * Create the instance.
389 */
390 RTCRCIPHERCTXINT *pCtx = (RTCRCIPHERCTXINT *)RTMemAlloc(sizeof(RTCRCIPHERCTXINT));
391 if (pCtx)
392 {
393 pCtx->phCipher = hCipher;
394 pCtx->fDecryption = true;
395# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
396 pCtx->pCipherCtx = EVP_CIPHER_CTX_new();
397# else
398 pCtx->pCipherCtx = (EVP_CIPHER_CTX *)RTMemAllocZ(sizeof(EVP_CIPHER_CTX));
399# endif
400
401 if (EVP_DecryptInit(pCtx->pCipherCtx, pThis->pCipher, (unsigned char const *)pvKey,
402 (unsigned char const *)pvInitVector))
403 {
404 rc = VINF_SUCCESS;
405 if (pvTag && cbTag && !EVP_CIPHER_CTX_ctrl(pCtx->pCipherCtx, MY_EVP_CTRL_AEAD_SET_TAG, (int)cbTag, pvTag))
406 rc = VERR_CR_CIPHER_OSSL_SET_TAG_FAILED;
407
408 if (RT_SUCCESS(rc) && pvAuthData && cbAuthData)
409 {
410 /* Add auth data. */
411 int cbDecryptedAuth = 0;
412 if (!EVP_DecryptUpdate(pCtx->pCipherCtx, NULL, &cbDecryptedAuth,
413 (unsigned char const *)pvAuthData, (int)cbAuthData))
414 rc = VERR_CR_CIPHER_OSSL_DECRYPT_UPDATE_FAILED;
415 }
416 }
417 else
418 rc = VERR_CR_CIPHER_OSSL_DECRYPT_INIT_FAILED;
419 }
420
421 if (RT_SUCCESS(rc))
422 *phCipherCtx = pCtx;
423 else
424 RTCrCipherCtxFree(pCtx);
425
426 return rc;
427}
428
429
430RTDECL(int) RTCrCipherCtxDecryptProcess(RTCRCIPHERCTX hCipherCtx,
431 void const *pvEncrypted, size_t cbEncrypted,
432 void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText)
433{
434 AssertReturn(hCipherCtx, VERR_INVALID_PARAMETER);
435 AssertReturn(cbEncrypted > 0, VERR_NO_DATA);
436 AssertReturn((size_t)(int)cbEncrypted == cbEncrypted && (int)cbEncrypted > 0, VERR_OUT_OF_RANGE);
437 AssertReturn(cbPlainText >= cbEncrypted, VERR_BUFFER_OVERFLOW);
438
439 RTCRCIPHERCTXINT *pCtx = hCipherCtx;
440 AssertReturn(pCtx->fDecryption, VERR_INVALID_STATE);
441 int rc = VERR_CR_CIPHER_OSSL_DECRYPT_UPDATE_FAILED;
442 int cbDecrypted1 = 0;
443 if (EVP_DecryptUpdate(pCtx->pCipherCtx, (unsigned char *)pvPlainText, &cbDecrypted1,
444 (unsigned char const *)pvEncrypted, (int)cbEncrypted))
445 {
446 *pcbPlainText = cbDecrypted1;
447 rc = VINF_SUCCESS;
448 }
449 return rc;
450}
451
452
453RTDECL(int) RTCrCipherCtxDecryptFinish(RTCRCIPHERCTX hCipherCtx,
454 void *pvPlainText, size_t *pcbPlainText)
455{
456 AssertReturn(hCipherCtx, VERR_INVALID_PARAMETER);
457 RTCRCIPHERCTXINT *pCtx = hCipherCtx;
458 AssertReturn(pCtx->fDecryption, VERR_INVALID_STATE);
459 int cbDecrypted2 = 0;
460 int rc = VERR_CR_CIPHER_OSSL_ENCRYPT_FINAL_FAILED;
461 if (EVP_DecryptFinal(pCtx->pCipherCtx, (uint8_t *)pvPlainText, &cbDecrypted2))
462 {
463 rc = VINF_SUCCESS;
464 if (pcbPlainText)
465 *pcbPlainText = cbDecrypted2;
466 }
467
468 return rc;
469}
470
471
472RTDECL(int) RTCrCipherEncrypt(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
473 void const *pvInitVector, size_t cbInitVector,
474 void const *pvPlainText, size_t cbPlainText,
475 void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted)
476{
477 return RTCrCipherEncryptEx(hCipher, pvKey, cbKey, pvInitVector, cbInitVector,
478 NULL, 0, pvPlainText, cbPlainText, pvEncrypted, cbEncrypted,
479 pcbEncrypted, NULL, 0, NULL);
480}
481
482
483RTDECL(int) RTCrCipherDecrypt(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
484 void const *pvInitVector, size_t cbInitVector,
485 void const *pvEncrypted, size_t cbEncrypted,
486 void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText)
487{
488 return RTCrCipherDecryptEx(hCipher, pvKey, cbKey, pvInitVector, cbInitVector,
489 NULL, 0, NULL, 0, pvEncrypted, cbEncrypted,
490 pvPlainText, cbPlainText, pcbPlainText);
491}
492
493
494RTDECL(int) RTCrCipherEncryptEx(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
495 void const *pvInitVector, size_t cbInitVector,
496 void const *pvAuthData, size_t cbAuthData,
497 void const *pvPlainText, size_t cbPlainText,
498 void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted,
499 void *pvTag, size_t cbTag, size_t *pcbTag)
500{
501 size_t const cbNeeded = cbPlainText;
502 if (pcbEncrypted)
503 {
504 *pcbEncrypted = cbNeeded;
505 AssertReturn(cbEncrypted >= cbNeeded, VERR_BUFFER_OVERFLOW);
506 }
507 else
508 AssertReturn(cbEncrypted == cbNeeded, VERR_INVALID_PARAMETER);
509 AssertReturn((size_t)(int)cbPlainText == cbPlainText && (int)cbPlainText > 0, VERR_OUT_OF_RANGE);
510
511 RTCRCIPHERCTXINT *pCtx = NIL_RTCRCIPHERCTX;
512
513 int rc = RTCrCipherCtxEncryptInit(hCipher, pvKey, cbKey, pvInitVector, cbInitVector,
514 pvAuthData, cbAuthData, &pCtx);
515 if (RT_SUCCESS(rc))
516 {
517 size_t cbEncrypted1 = 0;
518 rc = RTCrCipherCtxEncryptProcess(pCtx, pvPlainText, cbPlainText, pvEncrypted, cbEncrypted, &cbEncrypted1);
519 if (RT_SUCCESS(rc))
520 {
521 size_t cbEncrypted2 = 0;
522 rc = RTCrCipherCtxEncryptFinish(pCtx, (unsigned char *)pvEncrypted + cbEncrypted1,
523 &cbEncrypted2, pvTag, cbTag, pcbTag);
524 if (RT_SUCCESS(rc))
525 {
526 Assert(cbEncrypted1 + cbEncrypted2 == cbNeeded);
527 if (pcbEncrypted)
528 *pcbEncrypted = cbEncrypted1 + cbEncrypted2;
529 }
530 }
531 }
532
533 if (pCtx != NIL_RTCRCIPHERCTX)
534 RTCrCipherCtxFree(pCtx);
535
536 return rc;
537}
538
539
540RTDECL(int) RTCrCipherDecryptEx(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
541 void const *pvInitVector, size_t cbInitVector,
542 void const *pvAuthData, size_t cbAuthData,
543 void *pvTag, size_t cbTag,
544 void const *pvEncrypted, size_t cbEncrypted,
545 void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText)
546{
547 size_t const cbNeeded = cbEncrypted;
548 if (pcbPlainText)
549 {
550 *pcbPlainText = cbNeeded;
551 AssertReturn(cbPlainText >= cbNeeded, VERR_BUFFER_OVERFLOW);
552 }
553 else
554 AssertReturn(cbPlainText == cbNeeded, VERR_INVALID_PARAMETER);
555 AssertReturn((size_t)(int)cbEncrypted == cbEncrypted && (int)cbEncrypted > 0, VERR_OUT_OF_RANGE);
556
557 RTCRCIPHERCTXINT *pCtx = NIL_RTCRCIPHERCTX;
558
559 int rc = RTCrCipherCtxDecryptInit(hCipher, pvKey, cbKey, pvInitVector, cbInitVector,
560 pvAuthData, cbAuthData, pvTag, cbTag, &pCtx);
561 if (RT_SUCCESS(rc))
562 {
563 size_t cbDecrypted1 = 0;
564 rc = RTCrCipherCtxDecryptProcess(pCtx, pvEncrypted, cbEncrypted, pvPlainText, cbPlainText, &cbDecrypted1);
565 if (RT_SUCCESS(rc))
566 {
567 size_t cbDecrypted2 = 0;
568 rc = RTCrCipherCtxDecryptFinish(pCtx, (unsigned char *)pvPlainText + cbDecrypted1,
569 &cbDecrypted2);
570 if (RT_SUCCESS(rc))
571 {
572 Assert(cbDecrypted1 + cbDecrypted2 == cbNeeded);
573 if (pcbPlainText)
574 *pcbPlainText = cbDecrypted1 + cbDecrypted2;
575 }
576 }
577 }
578
579 if (pCtx != NIL_RTCRCIPHERCTX)
580 RTCrCipherCtxFree(pCtx);
581
582 return rc;
583}
584
585#endif /* IPRT_WITH_OPENSSL */
586
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette