diff options
Diffstat (limited to '')
-rw-r--r-- | src/VBox/Runtime/common/crypto/digest-builtin.cpp | 867 |
1 files changed, 867 insertions, 0 deletions
diff --git a/src/VBox/Runtime/common/crypto/digest-builtin.cpp b/src/VBox/Runtime/common/crypto/digest-builtin.cpp new file mode 100644 index 00000000..6d0c662f --- /dev/null +++ b/src/VBox/Runtime/common/crypto/digest-builtin.cpp @@ -0,0 +1,867 @@ +/* $Id: digest-builtin.cpp $ */ +/** @file + * IPRT - Crypto - Cryptographic Hash / Message Digest API, Built-in providers. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "internal/iprt.h" +#include <iprt/crypto/digest.h> + +#include <iprt/err.h> +#include <iprt/mem.h> +#include <iprt/string.h> +#include <iprt/md2.h> +#include <iprt/md4.h> +#include <iprt/md5.h> +#include <iprt/sha.h> +#include <iprt/crypto/pkix.h> + +#ifdef IPRT_WITH_OPENSSL +# include "internal/iprt-openssl.h" +# include <openssl/evp.h> +#endif + + + +/* + * MD2 + */ +#ifndef IPRT_WITHOUT_DIGEST_MD2 + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestMd2_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTMd2Update((PRTMD2CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestMd2_Final(void *pvState, uint8_t *pbHash) +{ + RTMd2Final((PRTMD2CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestMd2_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(fReInit); RT_NOREF_PV(pvOpaque); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTMd2Init((PRTMD2CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** MD2 alias ODIs. */ +static const char * const g_apszMd2Aliases[] = +{ + RTCR_PKCS1_MD2_WITH_RSA_OID, + "1.3.14.3.2.24" /* OIW md2WithRSASignature */, + NULL +}; + +/** MD2 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestMd2Desc = +{ + "md2", + "1.2.840.113549.2.2", + g_apszMd2Aliases, + RTDIGESTTYPE_MD2, + RTMD2_HASH_SIZE, + sizeof(RTMD2CONTEXT), + RTCRDIGESTDESC_F_DEPRECATED, + NULL, + NULL, + rtCrDigestMd2_Update, + rtCrDigestMd2_Final, + rtCrDigestMd2_Init, + NULL, + NULL, + NULL, + NULL, +}; +#endif /* !IPRT_WITHOUT_DIGEST_MD2 */ + + +/* + * MD4 + */ +#ifndef IPRT_WITHOUT_DIGEST_MD4 + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestMd4_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTMd4Update((PRTMD4CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestMd4_Final(void *pvState, uint8_t *pbHash) +{ + RTMd4Final((PRTMD4CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestMd4_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(fReInit); RT_NOREF_PV(pvOpaque); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTMd4Init((PRTMD4CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** MD4 alias ODIs. */ +static const char * const g_apszMd4Aliases[] = +{ + RTCR_PKCS1_MD4_WITH_RSA_OID, + NULL +}; + +/** MD4 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestMd4Desc = +{ + "md4", + "1.2.840.113549.2.4", + g_apszMd4Aliases, + RTDIGESTTYPE_MD4, + RTMD4_HASH_SIZE, + sizeof(RTMD4CONTEXT), + RTCRDIGESTDESC_F_DEPRECATED | RTCRDIGESTDESC_F_COMPROMISED | RTCRDIGESTDESC_F_SERVERELY_COMPROMISED, + NULL, + NULL, + rtCrDigestMd4_Update, + rtCrDigestMd4_Final, + rtCrDigestMd4_Init, + NULL, + NULL, + NULL, + NULL, +}; + +#endif /* !IPRT_WITHOUT_DIGEST_MD4 */ + + +/* + * MD5 + */ +#ifndef IPRT_WITHOUT_DIGEST_MD5 + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestMd5_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTMd5Update((PRTMD5CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestMd5_Final(void *pvState, uint8_t *pbHash) +{ + RTMd5Final(pbHash, (PRTMD5CONTEXT)pvState); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestMd5_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTMd5Init((PRTMD5CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** MD5 alias ODIs. */ +static const char * const g_apszMd5Aliases[] = +{ + RTCR_PKCS1_MD5_WITH_RSA_OID, + "1.3.14.3.2.25" /* OIW md5WithRSASignature */, + NULL +}; + +/** MD5 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestMd5Desc = +{ + "md5", + "1.2.840.113549.2.5", + g_apszMd5Aliases, + RTDIGESTTYPE_MD5, + RTMD5_HASH_SIZE, + sizeof(RTMD5CONTEXT), + RTCRDIGESTDESC_F_COMPROMISED, + NULL, + NULL, + rtCrDigestMd5_Update, + rtCrDigestMd5_Final, + rtCrDigestMd5_Init, + NULL, + NULL, + NULL, + NULL, +}; +#endif /* !IPRT_WITHOUT_DIGEST_MD5 */ + + +/* + * SHA-1 + */ + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestSha1_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTSha1Update((PRTSHA1CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestSha1_Final(void *pvState, uint8_t *pbHash) +{ + RTSha1Final((PRTSHA1CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestSha1_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTSha1Init((PRTSHA1CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** SHA-1 alias ODIs. */ +static const char * const g_apszSha1Aliases[] = +{ + RTCR_PKCS1_SHA1_WITH_RSA_OID, + "1.3.14.3.2.29" /* OIW sha1WithRSASignature */, + NULL +}; + +/** SHA-1 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestSha1Desc = +{ + "sha-1", + "1.3.14.3.2.26", + g_apszSha1Aliases, + RTDIGESTTYPE_SHA1, + RTSHA1_HASH_SIZE, + sizeof(RTSHA1CONTEXT), + RTCRDIGESTDESC_F_DEPRECATED, + NULL, + NULL, + rtCrDigestSha1_Update, + rtCrDigestSha1_Final, + rtCrDigestSha1_Init, + NULL, + NULL, + NULL, + NULL, +}; + + +/* + * SHA-256 + */ + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestSha256_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTSha256Update((PRTSHA256CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestSha256_Final(void *pvState, uint8_t *pbHash) +{ + RTSha256Final((PRTSHA256CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestSha256_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTSha256Init((PRTSHA256CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** SHA-256 alias ODIs. */ +static const char * const g_apszSha256Aliases[] = +{ + RTCR_PKCS1_SHA256_WITH_RSA_OID, + NULL +}; + +/** SHA-256 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestSha256Desc = +{ + "sha-256", + "2.16.840.1.101.3.4.2.1", + g_apszSha256Aliases, + RTDIGESTTYPE_SHA256, + RTSHA256_HASH_SIZE, + sizeof(RTSHA256CONTEXT), + 0, + NULL, + NULL, + rtCrDigestSha256_Update, + rtCrDigestSha256_Final, + rtCrDigestSha256_Init, + NULL, + NULL, + NULL, + NULL, +}; + + +/* + * SHA-512 + */ + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestSha512_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTSha512Update((PRTSHA512CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestSha512_Final(void *pvState, uint8_t *pbHash) +{ + RTSha512Final((PRTSHA512CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestSha512_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTSha512Init((PRTSHA512CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** SHA-512 alias ODIs. */ +static const char * const g_apszSha512Aliases[] = +{ + RTCR_PKCS1_SHA512_WITH_RSA_OID, + NULL +}; + +/** SHA-512 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestSha512Desc = +{ + "sha-512", + "2.16.840.1.101.3.4.2.3", + g_apszSha512Aliases, + RTDIGESTTYPE_SHA512, + RTSHA512_HASH_SIZE, + sizeof(RTSHA512CONTEXT), + 0, + NULL, + NULL, + rtCrDigestSha512_Update, + rtCrDigestSha512_Final, + rtCrDigestSha512_Init, + NULL, + NULL, + NULL, + NULL, +}; + + +/* + * SHA-224 + */ + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestSha224_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTSha224Update((PRTSHA224CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestSha224_Final(void *pvState, uint8_t *pbHash) +{ + RTSha224Final((PRTSHA224CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestSha224_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTSha224Init((PRTSHA224CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** SHA-224 alias ODIs. */ +static const char * const g_apszSha224Aliases[] = +{ + RTCR_PKCS1_SHA224_WITH_RSA_OID, + NULL +}; + +/** SHA-224 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestSha224Desc = +{ + "sha-224", + "2.16.840.1.101.3.4.2.4", + g_apszSha224Aliases, + RTDIGESTTYPE_SHA224, + RTSHA224_HASH_SIZE, + sizeof(RTSHA224CONTEXT), + 0, + NULL, + NULL, + rtCrDigestSha224_Update, + rtCrDigestSha224_Final, + rtCrDigestSha224_Init, + NULL, + NULL, + NULL, + NULL, +}; + + +/* + * SHA-384 + */ + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestSha384_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTSha384Update((PRTSHA384CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestSha384_Final(void *pvState, uint8_t *pbHash) +{ + RTSha384Final((PRTSHA384CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestSha384_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTSha384Init((PRTSHA384CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** SHA-384 alias ODIs. */ +static const char * const g_apszSha384Aliases[] = +{ + RTCR_PKCS1_SHA384_WITH_RSA_OID, + NULL +}; + +/** SHA-384 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestSha384Desc = +{ + "sha-384", + "2.16.840.1.101.3.4.2.2", + g_apszSha384Aliases, + RTDIGESTTYPE_SHA384, + RTSHA384_HASH_SIZE, + sizeof(RTSHA384CONTEXT), + 0, + NULL, + NULL, + rtCrDigestSha384_Update, + rtCrDigestSha384_Final, + rtCrDigestSha384_Init, + NULL, + NULL, + NULL, + NULL, +}; + + +#ifndef IPRT_WITHOUT_SHA512T224 +/* + * SHA-512/224 + */ + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestSha512t224_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTSha512t224Update((PRTSHA512T224CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestSha512t224_Final(void *pvState, uint8_t *pbHash) +{ + RTSha512t224Final((PRTSHA512T224CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestSha512t224_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTSha512t224Init((PRTSHA512T224CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** SHA-512/224 alias ODIs. */ +static const char * const g_apszSha512t224Aliases[] = +{ + NULL +}; + +/** SHA-512/224 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestSha512t224Desc = +{ + "sha-512/224", + "2.16.840.1.101.3.4.2.5", + g_apszSha512t224Aliases, + RTDIGESTTYPE_SHA512T224, + RTSHA512T224_HASH_SIZE, + sizeof(RTSHA512T224CONTEXT), + 0, + NULL, + NULL, + rtCrDigestSha512t224_Update, + rtCrDigestSha512t224_Final, + rtCrDigestSha512t224_Init, + NULL, + NULL, + NULL, + NULL, +}; +#endif /* !IPRT_WITHOUT_SHA512T224 */ + + +#ifndef IPRT_WITHOUT_SHA512T256 +/* + * SHA-512/256 + */ + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestSha512t256_Update(void *pvState, const void *pvData, size_t cbData) +{ + RTSha512t256Update((PRTSHA512T256CONTEXT)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestSha512t256_Final(void *pvState, uint8_t *pbHash) +{ + RTSha512t256Final((PRTSHA512T256CONTEXT)pvState, pbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestSha512t256_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + RT_NOREF_PV(pvOpaque); RT_NOREF_PV(fReInit); + AssertReturn(pvOpaque == NULL, VERR_INVALID_PARAMETER); + RTSha512t256Init((PRTSHA512T256CONTEXT)pvState); + return VINF_SUCCESS; +} + +/** SHA-512/256 alias ODIs. */ +static const char * const g_apszSha512t256Aliases[] = +{ + NULL +}; + +/** SHA-512/256 descriptor. */ +static RTCRDIGESTDESC const g_rtCrDigestSha512t256Desc = +{ + "sha-512/256", + "2.16.840.1.101.3.4.2.6", + g_apszSha512t256Aliases, + RTDIGESTTYPE_SHA512T256, + RTSHA512T256_HASH_SIZE, + sizeof(RTSHA512T256CONTEXT), + 0, + NULL, + NULL, + rtCrDigestSha512t256_Update, + rtCrDigestSha512t256_Final, + rtCrDigestSha512t256_Init, + NULL, + NULL, + NULL, + NULL, +}; +#endif /* !IPRT_WITHOUT_SHA512T256 */ + + +/** + * Array of built in message digest vtables. + */ +static PCRTCRDIGESTDESC const g_apDigestOps[] = +{ +#ifndef IPRT_WITHOUT_DIGEST_MD2 + &g_rtCrDigestMd2Desc, +#endif +#ifndef IPRT_WITHOUT_DIGEST_MD4 + &g_rtCrDigestMd4Desc, +#endif +#ifndef IPRT_WITHOUT_DIGEST_MD5 + &g_rtCrDigestMd5Desc, +#endif + &g_rtCrDigestSha1Desc, + &g_rtCrDigestSha256Desc, + &g_rtCrDigestSha512Desc, + &g_rtCrDigestSha224Desc, + &g_rtCrDigestSha384Desc, +#ifndef IPRT_WITHOUT_SHA512T224 + &g_rtCrDigestSha512t224Desc, +#endif +#ifndef IPRT_WITHOUT_SHA512T256 + &g_rtCrDigestSha512t256Desc, +#endif +}; + + +#ifdef IPRT_WITH_OPENSSL +/* + * OpenSSL EVP. + */ + +# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) +/** @impl_interface_method{RTCRDIGESTDESC::pfnNew} */ +static DECLCALLBACK(void*) rtCrDigestOsslEvp_New(void) +{ + return EVP_MD_CTX_new(); +} + +static DECLCALLBACK(void) rtCrDigestOsslEvp_Free(void *pvState) +{ + EVP_MD_CTX_free((EVP_MD_CTX*)pvState); +} + +# endif + +/** @impl_interface_method{RTCRDIGESTDESC::pfnUpdate} */ +static DECLCALLBACK(void) rtCrDigestOsslEvp_Update(void *pvState, const void *pvData, size_t cbData) +{ + EVP_DigestUpdate((EVP_MD_CTX *)pvState, pvData, cbData); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnFinal} */ +static DECLCALLBACK(void) rtCrDigestOsslEvp_Final(void *pvState, uint8_t *pbHash) +{ + unsigned int cbHash = EVP_MAX_MD_SIZE; + EVP_DigestFinal((EVP_MD_CTX *)pvState, (unsigned char *)pbHash, &cbHash); +} + +/** @impl_interface_method{RTCRDIGESTDESC::pfnInit} */ +static DECLCALLBACK(int) rtCrDigestOsslEvp_Init(void *pvState, void *pvOpaque, bool fReInit) +{ + EVP_MD_CTX *pThis = (EVP_MD_CTX *)pvState; + EVP_MD const *pEvpType = (EVP_MD const *)pvOpaque; + + if (fReInit) + { + pEvpType = EVP_MD_CTX_md(pThis); +# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + EVP_MD_CTX_reset(pThis); +# else + EVP_MD_CTX_cleanup(pThis); +# endif + } + + AssertPtrReturn(pEvpType, VERR_INVALID_PARAMETER); +# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + Assert(EVP_MD_block_size(pEvpType)); +# else + Assert(pEvpType->md_size); +# endif + if (EVP_DigestInit(pThis, pEvpType)) + return VINF_SUCCESS; + return VERR_CR_DIGEST_OSSL_DIGEST_INIT_ERROR; +} + + +/** @impl_interface_method{RTCRDIGESTDESC::pfn} */ +static DECLCALLBACK(void) rtCrDigestOsslEvp_Delete(void *pvState) +{ + EVP_MD_CTX *pThis = (EVP_MD_CTX *)pvState; +# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + EVP_MD_CTX_reset(pThis); +# else + EVP_MD_CTX_cleanup(pThis); +# endif +} + + +/** @impl_interface_method{RTCRDIGESTDESC::pfnClone} */ +static DECLCALLBACK(int) rtCrDigestOsslEvp_Clone(void *pvState, void const *pvSrcState) +{ + EVP_MD_CTX *pThis = (EVP_MD_CTX *)pvState; + EVP_MD_CTX const *pSrc = (EVP_MD_CTX const *)pvSrcState; + + if (EVP_MD_CTX_copy(pThis, pSrc)) + return VINF_SUCCESS; + return VERR_CR_DIGEST_OSSL_DIGEST_CTX_COPY_ERROR; +} + + +/** @impl_interface_method{RTCRDIGESTDESC::pfnGetHashSize} */ +static DECLCALLBACK(uint32_t) rtCrDigestOsslEvp_GetHashSize(void *pvState) +{ + EVP_MD_CTX *pThis = (EVP_MD_CTX *)pvState; + return EVP_MD_size(EVP_MD_CTX_md(pThis)); +} + + +/** @impl_interface_method{RTCRDIGESTDESC::pfnGetHashSize} */ +static DECLCALLBACK(RTDIGESTTYPE) rtCrDigestOsslEvp_GetDigestType(void *pvState) +{ + RT_NOREF_PV(pvState); //EVP_MD_CTX *pThis = (EVP_MD_CTX *)pvState; + /** @todo figure which digest algorithm it is! */ + return RTDIGESTTYPE_UNKNOWN; +} + + +/** Descriptor for the OpenSSL EVP base message digest provider. */ +static RTCRDIGESTDESC const g_rtCrDigestOpenSslDesc = +{ + "OpenSSL EVP", + NULL, + NULL, + RTDIGESTTYPE_UNKNOWN, + EVP_MAX_MD_SIZE, +# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + 0, +# else + sizeof(EVP_MD_CTX), +# endif + 0, +# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + rtCrDigestOsslEvp_New, + rtCrDigestOsslEvp_Free, +# else + NULL, + NULL, +# endif + rtCrDigestOsslEvp_Update, + rtCrDigestOsslEvp_Final, + rtCrDigestOsslEvp_Init, + rtCrDigestOsslEvp_Delete, + rtCrDigestOsslEvp_Clone, + rtCrDigestOsslEvp_GetHashSize, + rtCrDigestOsslEvp_GetDigestType +}; + +#endif /* IPRT_WITH_OPENSSL */ + + +RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByObjIdString(const char *pszObjId, void **ppvOpaque) +{ + if (ppvOpaque) + *ppvOpaque = NULL; + + /* + * Primary OIDs. + */ + uint32_t i = RT_ELEMENTS(g_apDigestOps); + while (i-- > 0) + if (strcmp(g_apDigestOps[i]->pszObjId, pszObjId) == 0) + return g_apDigestOps[i]; + + /* + * Alias OIDs. + */ + i = RT_ELEMENTS(g_apDigestOps); + while (i-- > 0) + { + const char * const *ppszAliases = g_apDigestOps[i]->papszObjIdAliases; + if (ppszAliases) + for (; *ppszAliases; ppszAliases++) + if (strcmp(*ppszAliases, pszObjId) == 0) + return g_apDigestOps[i]; + } + +#ifdef IPRT_WITH_OPENSSL + /* + * Try EVP and see if it knows the algorithm. + */ + if (ppvOpaque) + { + rtCrOpenSslInit(); + int iAlgoNid = OBJ_txt2nid(pszObjId); + if (iAlgoNid != NID_undef) + { + const char *pszAlogSn = OBJ_nid2sn(iAlgoNid); + const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlogSn); + if (pEvpMdType) + { + /* + * Return the OpenSSL provider descriptor and the EVP_MD address. + */ +# if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + Assert(EVP_MD_block_size(pEvpMdType)); +# else + Assert(pEvpMdType->md_size); +# endif + *ppvOpaque = (void *)pEvpMdType; + return &g_rtCrDigestOpenSslDesc; + } + } + } +#endif + return NULL; +} + + +RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByObjId(PCRTASN1OBJID pObjId, void **ppvOpaque) +{ + return RTCrDigestFindByObjIdString(pObjId->szObjId, ppvOpaque); +} + + +RTDECL(int) RTCrDigestCreateByObjIdString(PRTCRDIGEST phDigest, const char *pszObjId) +{ + void *pvOpaque; + PCRTCRDIGESTDESC pDesc = RTCrDigestFindByObjIdString(pszObjId, &pvOpaque); + if (pDesc) + return RTCrDigestCreate(phDigest, pDesc, pvOpaque); + return VERR_NOT_FOUND; +} + + +RTDECL(int) RTCrDigestCreateByObjId(PRTCRDIGEST phDigest, PCRTASN1OBJID pObjId) +{ + void *pvOpaque; + PCRTCRDIGESTDESC pDesc = RTCrDigestFindByObjId(pObjId, &pvOpaque); + if (pDesc) + return RTCrDigestCreate(phDigest, pDesc, pvOpaque); + return VERR_NOT_FOUND; +} + + +RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByType(RTDIGESTTYPE enmDigestType) +{ + AssertReturn(enmDigestType > RTDIGESTTYPE_INVALID && enmDigestType <= RTDIGESTTYPE_END, NULL); + + uint32_t i = RT_ELEMENTS(g_apDigestOps); + while (i-- > 0) + if (g_apDigestOps[i]->enmType == enmDigestType) + return g_apDigestOps[i]; + return NULL; +} + + +RTDECL(int) RTCrDigestCreateByType(PRTCRDIGEST phDigest, RTDIGESTTYPE enmDigestType) +{ + PCRTCRDIGESTDESC pDesc = RTCrDigestFindByType(enmDigestType); + if (pDesc) + return RTCrDigestCreate(phDigest, pDesc, NULL); + return VERR_NOT_FOUND; +} + |