VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/pkix-verify.cpp@ 63831

Last change on this file since 63831 was 63831, checked in by vboxsync, 9 years ago

RDP/client, Runtime: compile fixes for OpenSSL 1.1 (thanks Sebastian Andrzej Siewior)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1/* $Id: pkix-verify.cpp 63831 2016-09-14 12:03:10Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Public Key Infrastructure API, Verification.
4 */
5
6/*
7 * Copyright (C) 2006-2016 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#include "internal/iprt.h"
32#include <iprt/crypto/pkix.h>
33
34#include <iprt/err.h>
35#include <iprt/string.h>
36#include <iprt/crypto/digest.h>
37
38#ifdef IPRT_WITH_OPENSSL
39# include "internal/iprt-openssl.h"
40# include "openssl/evp.h"
41# ifndef OPENSSL_VERSION_NUMBER
42# error "Missing OPENSSL_VERSION_NUMBER!"
43# endif
44#endif
45
46
47RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
48 PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData,
49 PRTERRINFO pErrInfo)
50{
51 /*
52 * Valid input.
53 */
54 AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
55 AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);
56
57 if (pParameters)
58 {
59 AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
60 if (pParameters->enmType == RTASN1TYPE_NULL)
61 pParameters = NULL;
62 }
63
64 AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
65 AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);
66
67 AssertPtrReturn(pSignatureValue, VERR_INVALID_POINTER);
68 AssertReturn(RTAsn1BitString_IsPresent(pSignatureValue), VERR_INVALID_POINTER);
69
70 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
71 AssertReturn(cbData > 0, VERR_INVALID_PARAMETER);
72
73 /*
74 * Parameters are not currently supported (openssl code path).
75 */
76 if (pParameters)
77 return RTErrInfoSet(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_PARAMS_NOT_IMPL,
78 "Cipher algorithm parameters are not yet supported.");
79
80 /*
81 * Validate using IPRT.
82 */
83 RTCRPKIXSIGNATURE hSignature;
84 int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, false /*fSigning*/, pPublicKey, pParameters);
85 if (RT_FAILURE(rcIprt))
86 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN,
87 "Unknown public key algorithm [IPRT]: %s", pAlgorithm->szObjId);
88
89 RTCRDIGEST hDigest;
90 rcIprt = RTCrDigestCreateByObjId(&hDigest, pAlgorithm);
91 if (RT_SUCCESS(rcIprt))
92 {
93 /* Calculate the digest. */
94 rcIprt = RTCrDigestUpdate(hDigest, pvData, cbData);
95 if (RT_SUCCESS(rcIprt))
96 {
97 rcIprt = RTCrPkixSignatureVerifyBitString(hSignature, hDigest, pSignatureValue);
98 if (RT_FAILURE(rcIprt))
99 RTErrInfoSet(pErrInfo, rcIprt, "RTCrPkixSignatureVerifyBitString failed");
100 }
101 else
102 RTErrInfoSet(pErrInfo, rcIprt, "RTCrDigestUpdate failed");
103 RTCrDigestRelease(hDigest);
104 }
105 else
106 RTErrInfoSetF(pErrInfo, rcIprt, "Unknown digest algorithm [IPRT]: %s", pAlgorithm->szObjId);
107 RTCrPkixSignatureRelease(hSignature);
108
109#ifdef IPRT_WITH_OPENSSL
110 /*
111 * Validate using OpenSSL EVP.
112 */
113 rtCrOpenSslInit();
114
115 /* Translate the algorithm ID into a EVP message digest type pointer. */
116 int iAlgoNid = OBJ_txt2nid(pAlgorithm->szObjId);
117 if (iAlgoNid == NID_undef)
118 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN,
119 "Unknown public key algorithm [OpenSSL]: %s", pAlgorithm->szObjId);
120 const char *pszAlogSn = OBJ_nid2sn(iAlgoNid);
121 const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlogSn);
122 if (!pEvpMdType)
123 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
124 "EVP_get_digestbyname failed on %s (%s)", pszAlogSn, pAlgorithm->szObjId);
125
126# if OPENSSL_VERSION_NUMBER >= 0x10100000
127
128 EVP_MD_CTX *pEvpMdCtx = EVP_MD_CTX_create();
129 if (!pEvpMdCtx)
130 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED,
131 "EVP_MD_CTX_create failed");
132 if (!EVP_VerifyInit_ex(pEvpMdCtx, pEvpMdType, NULL /*engine*/))
133 {
134 EVP_MD_CTX_destroy(pEvpMdCtx);
135 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED,
136 "EVP_VerifyInit_ex failed (algorithm type is %s / %s)", pszAlogSn, pAlgorithm->szObjId);
137 }
138
139 /* Create an EVP public key. */
140 int rcOssl;
141 EVP_PKEY *pEvpPublicKey = EVP_PKEY_new();
142 if (pEvpPublicKey)
143 {
144 EVP_PKEY_set_type(pEvpPublicKey, iAlgoNid);
145 int keyType = EVP_PKEY_base_id(pEvpPublicKey);
146 if (keyType != NID_undef)
147 {
148 const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey);
149 if (d2i_PublicKey(keyType, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey)))
150 {
151 /* Digest the data. */
152 EVP_VerifyUpdate(pEvpMdCtx, pvData, cbData);
153
154 /* Verify the signature. */
155 if (EVP_VerifyFinal(pEvpMdCtx,
156 RTASN1BITSTRING_GET_BIT0_PTR(pSignatureValue),
157 RTASN1BITSTRING_GET_BYTE_SIZE(pSignatureValue),
158 pEvpPublicKey) > 0)
159 rcOssl = VINF_SUCCESS;
160 else
161 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED, "EVP_VerifyFinal failed");
162 }
163 else
164 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed");
165 }
166 else
167 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
168 "EVP_PKEY_type(%d) failed", iAlgoNid);
169 /* Cleanup and return.*/
170 EVP_PKEY_free(pEvpPublicKey);
171 }
172 else
173 rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", iAlgoNid);
174 EVP_MD_CTX_destroy(pEvpMdCtx);
175
176# else /* OPENSSL_VERSION_NUMBER < 0x1010000 */
177
178 /* Initialize the EVP message digest context. */
179 EVP_MD_CTX EvpMdCtx;
180 EVP_MD_CTX_init(&EvpMdCtx);
181 if (!EVP_VerifyInit_ex(&EvpMdCtx, pEvpMdType, NULL /*engine*/))
182 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED,
183 "EVP_VerifyInit_ex failed (algorithm type is %s / %s)", pszAlogSn, pAlgorithm->szObjId);
184
185 /* Create an EVP public key. */
186 int rcOssl;
187 EVP_PKEY *pEvpPublicKey = EVP_PKEY_new();
188 if (pEvpPublicKey)
189 {
190 pEvpPublicKey->type = EVP_PKEY_type(pEvpMdType->required_pkey_type[0]);
191 if (pEvpPublicKey->type != NID_undef)
192 {
193 const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey);
194 if (d2i_PublicKey(pEvpPublicKey->type, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey)))
195 {
196 /* Digest the data. */
197 EVP_VerifyUpdate(&EvpMdCtx, pvData, cbData);
198
199 /* Verify the signature. */
200 if (EVP_VerifyFinal(&EvpMdCtx,
201 RTASN1BITSTRING_GET_BIT0_PTR(pSignatureValue),
202 RTASN1BITSTRING_GET_BYTE_SIZE(pSignatureValue),
203 pEvpPublicKey) > 0)
204 rcOssl = VINF_SUCCESS;
205 else
206 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED, "EVP_VerifyFinal failed");
207 }
208 else
209 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed");
210 }
211 else
212 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
213 "EVP_PKEY_type(%d) failed", pEvpMdType->required_pkey_type[0]);
214 /* Cleanup and return.*/
215 EVP_PKEY_free(pEvpPublicKey);
216 }
217 else
218 rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", pEvpMdType->required_pkey_type[0]);
219 EVP_MD_CTX_cleanup(&EvpMdCtx);
220
221# endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
222
223 /*
224 * Check the result.
225 */
226 if (RT_SUCCESS(rcIprt) && RT_SUCCESS(rcOssl))
227 return VINF_SUCCESS;
228 if (RT_FAILURE_NP(rcIprt) && RT_FAILURE_NP(rcOssl))
229 return rcIprt;
230 AssertMsgFailed(("rcIprt=%Rrc rcOssl=%Rrc\n", rcIprt, rcOssl));
231 if (RT_FAILURE_NP(rcOssl))
232 return rcOssl;
233#endif /* IPRT_WITH_OPENSSL */
234
235 return rcIprt;
236}
237
238
239RTDECL(int) RTCrPkixPubKeyVerifySignedDigest(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
240 void const *pvSignedDigest, size_t cbSignedDigest, RTCRDIGEST hDigest,
241 PRTERRINFO pErrInfo)
242{
243 /*
244 * Valid input.
245 */
246 AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
247 AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);
248
249 if (pParameters)
250 {
251 AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
252 if (pParameters->enmType == RTASN1TYPE_NULL)
253 pParameters = NULL;
254 }
255
256 AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
257 AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);
258
259 AssertPtrReturn(pvSignedDigest, VERR_INVALID_POINTER);
260 AssertReturn(cbSignedDigest, VERR_INVALID_PARAMETER);
261
262 AssertPtrReturn(hDigest, VERR_INVALID_HANDLE);
263
264 /*
265 * Parameters are not currently supported (openssl code path).
266 */
267 if (pParameters)
268 return RTErrInfoSet(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_PARAMS_NOT_IMPL,
269 "Cipher algorithm parameters are not yet supported.");
270
271 /*
272 * Validate using IPRT.
273 */
274 RTCRPKIXSIGNATURE hSignature;
275 int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, false /*fSigning*/, pPublicKey, pParameters);
276 if (RT_FAILURE(rcIprt))
277 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN,
278 "Unknown public key algorithm [IPRT]: %s", pAlgorithm->szObjId);
279
280 rcIprt = RTCrPkixSignatureVerify(hSignature, hDigest, pvSignedDigest, cbSignedDigest);
281 if (RT_FAILURE(rcIprt))
282 RTErrInfoSet(pErrInfo, rcIprt, "RTCrPkixSignatureVerifyBitString failed");
283
284 RTCrPkixSignatureRelease(hSignature);
285
286#if defined(IPRT_WITH_OPENSSL) \
287 && (OPENSSL_VERSION_NUMBER > 0x10000000L) /* 0.9.8 doesn't seem to have EVP_PKEY_CTX_set_signature_md. */
288 /*
289 * Validate using OpenSSL EVP.
290 */
291 rtCrOpenSslInit();
292
293 const char *pszAlgObjId = pAlgorithm->szObjId;
294 if (!strcmp(pszAlgObjId, RTCRX509ALGORITHMIDENTIFIERID_RSA))
295 {
296 pszAlgObjId = RTCrX509AlgorithmIdentifier_CombineEncryptionOidAndDigestOid(pszAlgObjId,
297 RTCrDigestGetAlgorithmOid(hDigest));
298 AssertMsgStmt(pszAlgObjId, ("enc=%s hash=%s\n", pAlgorithm->szObjId, RTCrDigestGetAlgorithmOid(hDigest)),
299 pszAlgObjId = RTCrDigestGetAlgorithmOid(hDigest));
300 }
301
302 /* Translate the algorithm ID into a EVP message digest type pointer. */
303 int iAlgoNid = OBJ_txt2nid(pszAlgObjId);
304 if (iAlgoNid == NID_undef)
305 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN,
306 "Unknown public key algorithm [OpenSSL]: %s", pszAlgObjId);
307 const char *pszAlogSn = OBJ_nid2sn(iAlgoNid);
308 const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlogSn);
309 if (!pEvpMdType)
310 return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
311 "EVP_get_digestbyname failed on %s (%s)", pszAlogSn, pszAlgObjId);
312
313# if OPENSSL_VERSION_NUMBER >= 0x10100000
314
315 /* Create an EVP public key. */
316 int rcOssl;
317 EVP_PKEY *pEvpPublicKey = EVP_PKEY_new();
318 if (pEvpPublicKey)
319 {
320 EVP_PKEY_set_type(pEvpPublicKey, iAlgoNid);
321 int keyType = EVP_PKEY_base_id(pEvpPublicKey);
322 if (keyType != NID_undef)
323 {
324 const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey);
325 if (d2i_PublicKey(keyType, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey)))
326 {
327 /* Create an EVP public key context we can use to validate the digest. */
328 EVP_PKEY_CTX *pEvpPKeyCtx = EVP_PKEY_CTX_new(pEvpPublicKey, NULL);
329 if (pEvpPKeyCtx)
330 {
331 rcOssl = EVP_PKEY_verify_init(pEvpPKeyCtx);
332 if (rcOssl > 0)
333 {
334 rcOssl = EVP_PKEY_CTX_set_signature_md(pEvpPKeyCtx, pEvpMdType);
335 if (rcOssl > 0)
336 {
337 /* Get the digest from hDigest and verify it. */
338 rcOssl = EVP_PKEY_verify(pEvpPKeyCtx,
339 (uint8_t const *)pvSignedDigest,
340 cbSignedDigest,
341 RTCrDigestGetHash(hDigest),
342 RTCrDigestGetHashSize(hDigest));
343 if (rcOssl > 0)
344 rcOssl = VINF_SUCCESS;
345 else
346 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED,
347 "EVP_PKEY_verify failed (%d)", rcOssl);
348 }
349 else
350 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
351 "EVP_PKEY_CTX_set_signature_md failed (%d)", rcOssl);
352 }
353 else
354 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
355 "EVP_PKEY_verify_init failed (%d)", rcOssl);
356 EVP_PKEY_CTX_free(pEvpPKeyCtx);
357 }
358 else
359 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_CTX_new failed");
360 }
361 else
362 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed");
363 }
364 else
365 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
366 "EVP_PKEY_type(%d) failed", iAlgoNid);
367 /* Cleanup and return.*/
368 EVP_PKEY_free(pEvpPublicKey);
369 }
370 else
371 rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", iAlgoNid);
372
373# else /* OPENSSL_VERSION_NUMBER < 0x1010000 */
374
375 /* Create an EVP public key. */
376 int rcOssl;
377 EVP_PKEY *pEvpPublicKey = EVP_PKEY_new();
378 if (pEvpPublicKey)
379 {
380 pEvpPublicKey->type = EVP_PKEY_type(pEvpMdType->required_pkey_type[0]);
381 if (pEvpPublicKey->type != NID_undef)
382 {
383 const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey);
384 if (d2i_PublicKey(pEvpPublicKey->type, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey)))
385 {
386 /* Create an EVP public key context we can use to validate the digest. */
387 EVP_PKEY_CTX *pEvpPKeyCtx = EVP_PKEY_CTX_new(pEvpPublicKey, NULL);
388 if (pEvpPKeyCtx)
389 {
390 rcOssl = EVP_PKEY_verify_init(pEvpPKeyCtx);
391 if (rcOssl > 0)
392 {
393 rcOssl = EVP_PKEY_CTX_set_signature_md(pEvpPKeyCtx, pEvpMdType);
394 if (rcOssl > 0)
395 {
396 /* Get the digest from hDigest and verify it. */
397 rcOssl = EVP_PKEY_verify(pEvpPKeyCtx,
398 (uint8_t const *)pvSignedDigest,
399 cbSignedDigest,
400 RTCrDigestGetHash(hDigest),
401 RTCrDigestGetHashSize(hDigest));
402 if (rcOssl > 0)
403 rcOssl = VINF_SUCCESS;
404 else
405 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED,
406 "EVP_PKEY_verify failed (%d)", rcOssl);
407 }
408 else
409 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
410 "EVP_PKEY_CTX_set_signature_md failed (%d)", rcOssl);
411 }
412 else
413 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
414 "EVP_PKEY_verify_init failed (%d)", rcOssl);
415 EVP_PKEY_CTX_free(pEvpPKeyCtx);
416 }
417 else
418 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_CTX_new failed");
419 }
420 else
421 rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed");
422 }
423 else
424 rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
425 "EVP_PKEY_type(%d) failed", pEvpMdType->required_pkey_type[0]);
426 /* Cleanup and return.*/
427 EVP_PKEY_free(pEvpPublicKey);
428 }
429 else
430 rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", pEvpMdType->required_pkey_type[0]);
431
432# endif /* OPENSSL_VERSION_NUMBER < 0x1010000 */
433
434 /*
435 * Check the result.
436 */
437 if (RT_SUCCESS(rcIprt) && RT_SUCCESS(rcOssl))
438 return VINF_SUCCESS;
439 if (RT_FAILURE_NP(rcIprt) && RT_FAILURE_NP(rcOssl))
440 return rcIprt;
441 AssertMsgFailed(("rcIprt=%Rrc rcOssl=%Rrc\n", rcIprt, rcOssl));
442 if (RT_FAILURE_NP(rcOssl))
443 return rcOssl;
444#endif /* IPRT_WITH_OPENSSL */
445
446 return rcIprt;
447}
448
Note: See TracBrowser for help on using the repository browser.

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