VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use