godot/thirdparty/mbedtls/library/sha256.c

/*
 *  FIPS-180-2 compliant SHA-256 implementation
 *
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 */
/*
 *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
 *
 *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
 */

#if defined(__clang__) &&  (__clang_major__ >= 4)

/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if,
 * but that is defined by build_info.h, and we need this block to happen first. */
#if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A')
#if __ARM_ARCH >= 8
#define MBEDTLS_SHA256_ARCH_IS_ARMV8_A
#endif
#endif

#if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO)
/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
 *
 * The intrinsic declaration are guarded by predefined ACLE macros in clang:
 * these are normally only enabled by the -march option on the command line.
 * By defining the macros ourselves we gain access to those declarations without
 * requiring -march on the command line.
 *
 * `arm_neon.h` is included by common.h, so we put these defines
 * at the top of this file, before any includes.
 */
#define __ARM_FEATURE_CRYPTO
/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions
 *
 * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it
 * for older compilers.
 */
#define __ARM_FEATURE_SHA2
#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
#endif

#endif /* defined(__clang__) &&  (__clang_major__ >= 4) */

/* Ensure that SIG_SETMASK is defined when -std=c99 is used. */
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif

#include "common.h"

#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)

#include "mbedtls/sha256.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"

#include <string.h>

#include "mbedtls/platform.h"

#if defined(MBEDTLS_ARCH_IS_ARMV8_A)

#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
#       if !defined(MBEDTLS_HAVE_NEON_INTRINSICS)
#           if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
#               warning "Target does not support NEON instructions"
#               undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
#           else
#               error "Target does not support NEON instructions"
#           endif
#       endif
#   endif

#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
/* *INDENT-OFF* */

#   if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
#      if defined(__ARMCOMPILER_VERSION)
#        if __ARMCOMPILER_VERSION <= 6090000
#          error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
#        endif
#          pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function)
#define MBEDTLS_POP_TARGET_PRAGMA
#      elif defined(__clang__)
#        if __clang_major__ < 4
#          error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
#        endif
#        pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
#define MBEDTLS_POP_TARGET_PRAGMA
#      elif defined(__GNUC__)
         /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some
          *        intrinsics are missing. Missing intrinsics could be worked around.
          */
#        if __GNUC__ < 6
#          error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
#        else
#          pragma GCC push_options
#          pragma GCC target ("arch=armv8-a+crypto")
#define MBEDTLS_POP_TARGET_PRAGMA
#        endif
#      else
#        error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
#      endif
#    endif
/* *INDENT-ON* */

#  endif
#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
#    if defined(__unix__)
#      if defined(__linux__)
/* Our preferred method of detection is getauxval() */
#        include <sys/auxv.h>
/* These are not always defined via sys/auxv.h */
#        if !defined(HWCAP_SHA2)
#define HWCAP_SHA2
#        endif
#        if !defined(HWCAP2_SHA2)
#define HWCAP2_SHA2
#        endif
#      endif
/* Use SIGILL on Unix, and fall back to it on Linux */
#      include <signal.h>
#    endif
#  endif
#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
#  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY
#  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
#endif

#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
/*
 * Capability detection code comes early, so we can disable
 * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found
 */
#if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2)
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
    return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;
}
#elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2)
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
    return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0;
}
#elif defined(__APPLE__)
static int mbedtls_a64_crypto_sha256_determine_support(void)
{
    return 1;
}
#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <processthreadsapi.h>

static int mbedtls_a64_crypto_sha256_determine_support(void)
{
    return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ?
           1 : 0;
}
#elif defined(__unix__) && defined(SIG_SETMASK)
/* Detection with SIGILL, setjmp() and longjmp() */
#include <signal.h>
#include <setjmp.h>

static jmp_buf return_from_sigill;

/*
 * Armv8-A SHA256 support detection via SIGILL
 */
static void sigill_handler(int signal)
{
    (void) signal;
    longjmp(return_from_sigill, 1);
}

static int mbedtls_a64_crypto_sha256_determine_support(void)
{
    struct sigaction old_action, new_action;

    sigset_t old_mask;
    if (sigprocmask(0, NULL, &old_mask)) {
        return 0;
    }

    sigemptyset(&new_action.sa_mask);
    new_action.sa_flags = 0;
    new_action.sa_handler = sigill_handler;

    sigaction(SIGILL, &new_action, &old_action);

    static int ret = 0;

    if (setjmp(return_from_sigill) == 0) {         /* First return only */
        /* If this traps, we will return a second time from setjmp() with 1 */
#if defined(MBEDTLS_ARCH_IS_ARM64)
        asm volatile ("sha256h q0, q0, v0.4s" : : : "v0");
#else
        asm volatile ("sha256h.32 q0, q0, q0" : : : "q0");
#endif
        ret = 1;
    }

    sigaction(SIGILL, &old_action, NULL);
    sigprocmask(SIG_SETMASK, &old_mask, NULL);

    return ret;
}
#else
#warning "No mechanism to detect ARMV8_CRYPTO found, using C code only"
#undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
#endif  /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */

#endif  /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */

#if !defined(MBEDTLS_SHA256_ALT)

#define SHA256_BLOCK_SIZE

void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
{}

void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
{}

void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
                          const mbedtls_sha256_context *src)
{}

/*
 * SHA-256 context setup
 */
int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
{}

#if !defined(MBEDTLS_SHA256_PROCESS_ALT)
static const uint32_t K[] =;

#endif

#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)

#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
#define mbedtls_internal_sha256_process_many_a64_crypto
#define mbedtls_internal_sha256_process_a64_crypto
#endif

static size_t mbedtls_internal_sha256_process_many_a64_crypto(
    mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len)
{
    uint32x4_t abcd = vld1q_u32(&ctx->state[0]);
    uint32x4_t efgh = vld1q_u32(&ctx->state[4]);

    size_t processed = 0;

    for (;
         len >= SHA256_BLOCK_SIZE;
         processed += SHA256_BLOCK_SIZE,
         msg += SHA256_BLOCK_SIZE,
         len -= SHA256_BLOCK_SIZE) {
        uint32x4_t tmp, abcd_prev;

        uint32x4_t abcd_orig = abcd;
        uint32x4_t efgh_orig = efgh;

        uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0));
        uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1));
        uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2));
        uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3));

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* Will be true if not defined */
                                               /* Untested on BE */
        sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0)));
        sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1)));
        sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2)));
        sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3)));
#endif

        /* Rounds 0 to 3 */
        tmp = vaddq_u32(sched0, vld1q_u32(&K[0]));
        abcd_prev = abcd;
        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);

        /* Rounds 4 to 7 */
        tmp = vaddq_u32(sched1, vld1q_u32(&K[4]));
        abcd_prev = abcd;
        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);

        /* Rounds 8 to 11 */
        tmp = vaddq_u32(sched2, vld1q_u32(&K[8]));
        abcd_prev = abcd;
        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);

        /* Rounds 12 to 15 */
        tmp = vaddq_u32(sched3, vld1q_u32(&K[12]));
        abcd_prev = abcd;
        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);

        for (int t = 16; t < 64; t += 16) {
            /* Rounds t to t + 3 */
            sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3);
            tmp = vaddq_u32(sched0, vld1q_u32(&K[t]));
            abcd_prev = abcd;
            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);

            /* Rounds t + 4 to t + 7 */
            sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0);
            tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4]));
            abcd_prev = abcd;
            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);

            /* Rounds t + 8 to t + 11 */
            sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1);
            tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8]));
            abcd_prev = abcd;
            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);

            /* Rounds t + 12 to t + 15 */
            sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2);
            tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12]));
            abcd_prev = abcd;
            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
        }

        abcd = vaddq_u32(abcd, abcd_orig);
        efgh = vaddq_u32(efgh, efgh_orig);
    }

    vst1q_u32(&ctx->state[0], abcd);
    vst1q_u32(&ctx->state[4], efgh);

    return processed;
}

#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
/*
 * This function is for internal use only if we are building both C and Armv8-A
 * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
 */
static
#endif
int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
                                               const unsigned char data[SHA256_BLOCK_SIZE])
{
    return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data,
                                                            SHA256_BLOCK_SIZE) ==
            SHA256_BLOCK_SIZE) ? 0 : -1;
}

#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */

#if defined(MBEDTLS_POP_TARGET_PRAGMA)
#if defined(__clang__)
#pragma clang attribute pop
#elif defined(__GNUC__)
#pragma GCC pop_options
#endif
#undef MBEDTLS_POP_TARGET_PRAGMA
#endif

#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
#define mbedtls_internal_sha256_process_many_c
#define mbedtls_internal_sha256_process_c
#endif


#if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \
    !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)

#define SHR(x, n)
#define ROTR(x, n)

#define S0(x)
#define S1(x)

#define S2(x)
#define S3(x)

#define F0(x, y, z)
#define F1(x, y, z)

#define R(t)

#define P(a, b, c, d, e, f, g, h, x, K)

#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
/*
 * This function is for internal use only if we are building both C and Armv8
 * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
 */
static
#endif
int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,
                                      const unsigned char data[SHA256_BLOCK_SIZE])
{}

#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */


#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)

static size_t mbedtls_internal_sha256_process_many_c(
    mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)
{}

#endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */


#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)

static int mbedtls_a64_crypto_sha256_has_support(void)
{
    static int done = 0;
    static int supported = 0;

    if (!done) {
        supported = mbedtls_a64_crypto_sha256_determine_support();
        done = 1;
    }

    return supported;
}

static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx,
                                                   const uint8_t *msg, size_t len)
{
    if (mbedtls_a64_crypto_sha256_has_support()) {
        return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len);
    } else {
        return mbedtls_internal_sha256_process_many_c(ctx, msg, len);
    }
}

int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
                                    const unsigned char data[SHA256_BLOCK_SIZE])
{
    if (mbedtls_a64_crypto_sha256_has_support()) {
        return mbedtls_internal_sha256_process_a64_crypto(ctx, data);
    } else {
        return mbedtls_internal_sha256_process_c(ctx, data);
    }
}

#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */


/*
 * SHA-256 process buffer
 */
int mbedtls_sha256_update(mbedtls_sha256_context *ctx,
                          const unsigned char *input,
                          size_t ilen)
{}

/*
 * SHA-256 final digest
 */
int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
                          unsigned char *output)
{}

#endif /* !MBEDTLS_SHA256_ALT */

/*
 * output = SHA-256( input buffer )
 */
int mbedtls_sha256(const unsigned char *input,
                   size_t ilen,
                   unsigned char *output,
                   int is224)
{}

#if defined(MBEDTLS_SELF_TEST)
/*
 * FIPS-180-2 test vectors
 */
static const unsigned char sha_test_buf[3][57] =;

static const size_t sha_test_buflen[3] =;

sha_test_sum_t;

/*
 * SHA-224 test vectors
 */
#if defined(MBEDTLS_SHA224_C)
static sha_test_sum_t sha224_test_sum[] =;
#endif

/*
 * SHA-256 test vectors
 */
#if defined(MBEDTLS_SHA256_C)
static sha_test_sum_t sha256_test_sum[] =;
#endif

/*
 * Checkup routine
 */
static int mbedtls_sha256_common_self_test(int verbose, int is224)
{}

#if defined(MBEDTLS_SHA256_C)
int mbedtls_sha256_self_test(int verbose)
{}
#endif /* MBEDTLS_SHA256_C */

#if defined(MBEDTLS_SHA224_C)
int mbedtls_sha224_self_test(int verbose)
{}
#endif /* MBEDTLS_SHA224_C */

#endif /* MBEDTLS_SELF_TEST */

#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */