You've already forked godot
							
							
				mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 11:50:27 +00:00 
			
		
		
		
	Delete unused files of thirparty libs (zlib, mbedtls)
Signed-off-by: Yevhen Babiichuk (DustDFG) <dfgdust@gmail.com>
This commit is contained in:
		
							
								
								
									
										9
									
								
								thirdparty/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								thirdparty/README.md
									
									
									
									
										vendored
									
									
								
							@@ -556,8 +556,11 @@ File extracted from upstream release tarball:
 | 
			
		||||
 | 
			
		||||
- All `.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/`
 | 
			
		||||
  and all `.h` from `include/psa/` to `thirdparty/mbedtls/include/psa/`
 | 
			
		||||
- All `.c` and `.h` from `library/` to `thirdparty/mbedtls/library/` except
 | 
			
		||||
  for the `psa_*.c` source files
 | 
			
		||||
- All `.c` and `.h` from `library/` to `thirdparty/mbedtls/library/`
 | 
			
		||||
- From `library/` to `thirdparty/mbedtls/library/`:
 | 
			
		||||
  - All `.c` and `.h` files
 | 
			
		||||
  - Except `bignum_mod.c`, `block_cipher.c`, `ecp_curves_new.c`, `lmots.c`,
 | 
			
		||||
  `lms.c`
 | 
			
		||||
- The `LICENSE` file (edited to keep only the Apache 2.0 variant)
 | 
			
		||||
- Applied the patch `msvc-redeclaration-bug.diff` to fix a compilation error
 | 
			
		||||
  with some MSVC versions
 | 
			
		||||
@@ -1068,7 +1071,7 @@ Files extracted from upstream source:
 | 
			
		||||
 | 
			
		||||
Files extracted from upstream source:
 | 
			
		||||
 | 
			
		||||
- All `.c` and `.h` files, minus `infback.c`
 | 
			
		||||
- All `.c` and `.h` files, except `gz*.c` and `infback.c`
 | 
			
		||||
- `LICENSE`
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										394
									
								
								thirdparty/mbedtls/library/bignum_mod.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										394
									
								
								thirdparty/mbedtls/library/bignum_mod.c
									
									
									
									
										vendored
									
									
								
							@@ -1,394 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 *  Modular bignum functions
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright The Mbed TLS Contributors
 | 
			
		||||
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "mbedtls/platform_util.h"
 | 
			
		||||
#include "mbedtls/error.h"
 | 
			
		||||
#include "mbedtls/bignum.h"
 | 
			
		||||
 | 
			
		||||
#include "mbedtls/platform.h"
 | 
			
		||||
 | 
			
		||||
#include "bignum_core.h"
 | 
			
		||||
#include "bignum_mod.h"
 | 
			
		||||
#include "bignum_mod_raw.h"
 | 
			
		||||
#include "constant_time_internal.h"
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
 | 
			
		||||
                                  const mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                                  mbedtls_mpi_uint *p,
 | 
			
		||||
                                  size_t p_limbs)
 | 
			
		||||
{
 | 
			
		||||
    if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r->limbs = N->limbs;
 | 
			
		||||
    r->p = p;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r)
 | 
			
		||||
{
 | 
			
		||||
    if (r == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r->limbs = 0;
 | 
			
		||||
    r->p = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N)
 | 
			
		||||
{
 | 
			
		||||
    if (N == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    N->p = NULL;
 | 
			
		||||
    N->limbs = 0;
 | 
			
		||||
    N->bits = 0;
 | 
			
		||||
    N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
 | 
			
		||||
{
 | 
			
		||||
    if (N == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (N->int_rep) {
 | 
			
		||||
        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
 | 
			
		||||
            if (N->rep.mont.rr != NULL) {
 | 
			
		||||
                mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,
 | 
			
		||||
                                         N->limbs * sizeof(mbedtls_mpi_uint));
 | 
			
		||||
                N->rep.mont.rr = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            N->rep.mont.mm = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        case MBEDTLS_MPI_MOD_REP_OPT_RED:
 | 
			
		||||
            N->rep.ored.modp = NULL;
 | 
			
		||||
            break;
 | 
			
		||||
        case MBEDTLS_MPI_MOD_REP_INVALID:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    N->p = NULL;
 | 
			
		||||
    N->limbs = 0;
 | 
			
		||||
    N->bits = 0;
 | 
			
		||||
    N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int set_mont_const_square(const mbedtls_mpi_uint **X,
 | 
			
		||||
                                 const mbedtls_mpi_uint *A,
 | 
			
		||||
                                 size_t limbs)
 | 
			
		||||
{
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    mbedtls_mpi N;
 | 
			
		||||
    mbedtls_mpi RR;
 | 
			
		||||
    *X = NULL;
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_init(&N);
 | 
			
		||||
    mbedtls_mpi_init(&RR);
 | 
			
		||||
 | 
			
		||||
    if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) {
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mbedtls_mpi_grow(&N, limbs)) {
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs);
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
 | 
			
		||||
 | 
			
		||||
    if (ret == 0) {
 | 
			
		||||
        *X = RR.p;
 | 
			
		||||
        RR.p = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    mbedtls_mpi_free(&N);
 | 
			
		||||
    mbedtls_mpi_free(&RR);
 | 
			
		||||
    ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                                          const mbedtls_mpi_uint *p,
 | 
			
		||||
                                          size_t p_limbs,
 | 
			
		||||
                                          mbedtls_mpi_mod_rep_selector int_rep)
 | 
			
		||||
{
 | 
			
		||||
    N->p = p;
 | 
			
		||||
    N->limbs = p_limbs;
 | 
			
		||||
    N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
 | 
			
		||||
    N->int_rep = int_rep;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                                  const mbedtls_mpi_uint *p,
 | 
			
		||||
                                  size_t p_limbs)
 | 
			
		||||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);
 | 
			
		||||
    N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
 | 
			
		||||
    ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
 | 
			
		||||
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        mbedtls_mpi_mod_modulus_free(N);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                                         const mbedtls_mpi_uint *p,
 | 
			
		||||
                                         size_t p_limbs,
 | 
			
		||||
                                         mbedtls_mpi_modp_fn modp)
 | 
			
		||||
{
 | 
			
		||||
    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);
 | 
			
		||||
    N->rep.ored.modp = modp;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
 | 
			
		||||
                        const mbedtls_mpi_mod_residue *A,
 | 
			
		||||
                        const mbedtls_mpi_mod_residue *B,
 | 
			
		||||
                        const mbedtls_mpi_mod_modulus *N)
 | 
			
		||||
{
 | 
			
		||||
    if (N->limbs == 0) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL);
 | 
			
		||||
    if (T == NULL) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T);
 | 
			
		||||
 | 
			
		||||
    mbedtls_free(T);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
 | 
			
		||||
                        const mbedtls_mpi_mod_residue *A,
 | 
			
		||||
                        const mbedtls_mpi_mod_residue *B,
 | 
			
		||||
                        const mbedtls_mpi_mod_modulus *N)
 | 
			
		||||
{
 | 
			
		||||
    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X,
 | 
			
		||||
                                    const mbedtls_mpi_mod_residue *A,
 | 
			
		||||
                                    const mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                                    mbedtls_mpi_uint *working_memory)
 | 
			
		||||
{
 | 
			
		||||
    /* Input already in Montgomery form, so there's little to do */
 | 
			
		||||
    mbedtls_mpi_mod_raw_inv_prime(X->p, A->p,
 | 
			
		||||
                                  N->p, N->limbs,
 | 
			
		||||
                                  N->rep.mont.rr,
 | 
			
		||||
                                  working_memory);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,
 | 
			
		||||
                                        const mbedtls_mpi_mod_residue *A,
 | 
			
		||||
                                        const mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                                        mbedtls_mpi_uint *working_memory)
 | 
			
		||||
{
 | 
			
		||||
    /* Need to convert input into Montgomery form */
 | 
			
		||||
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_mod_modulus Nmont;
 | 
			
		||||
    mbedtls_mpi_mod_modulus_init(&Nmont);
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));
 | 
			
		||||
 | 
			
		||||
    /* We'll use X->p to hold the Montgomery form of the input A->p */
 | 
			
		||||
    mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
 | 
			
		||||
                                 Nmont.rep.mont.mm, Nmont.rep.mont.rr,
 | 
			
		||||
                                 working_memory);
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_mod_raw_inv_prime(X->p, X->p,
 | 
			
		||||
                                  Nmont.p, Nmont.limbs,
 | 
			
		||||
                                  Nmont.rep.mont.rr,
 | 
			
		||||
                                  working_memory);
 | 
			
		||||
 | 
			
		||||
    /* And convert back from Montgomery form */
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs,
 | 
			
		||||
                                   Nmont.rep.mont.mm, working_memory);
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    mbedtls_mpi_mod_modulus_free(&Nmont);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
 | 
			
		||||
                        const mbedtls_mpi_mod_residue *A,
 | 
			
		||||
                        const mbedtls_mpi_mod_modulus *N)
 | 
			
		||||
{
 | 
			
		||||
    if (X->limbs != N->limbs || A->limbs != N->limbs) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Zero has the same value regardless of Montgomery form or not */
 | 
			
		||||
    if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t working_limbs =
 | 
			
		||||
        mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs);
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs,
 | 
			
		||||
                                                      sizeof(mbedtls_mpi_uint));
 | 
			
		||||
    if (working_memory == NULL) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    switch (N->int_rep) {
 | 
			
		||||
        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
 | 
			
		||||
            ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory);
 | 
			
		||||
            break;
 | 
			
		||||
        case MBEDTLS_MPI_MOD_REP_OPT_RED:
 | 
			
		||||
            ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_zeroize_and_free(working_memory,
 | 
			
		||||
                             working_limbs * sizeof(mbedtls_mpi_uint));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
 | 
			
		||||
                        const mbedtls_mpi_mod_residue *A,
 | 
			
		||||
                        const mbedtls_mpi_mod_residue *B,
 | 
			
		||||
                        const mbedtls_mpi_mod_modulus *N)
 | 
			
		||||
{
 | 
			
		||||
    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
 | 
			
		||||
                           mbedtls_mpi_uint min,
 | 
			
		||||
                           const mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                           int (*f_rng)(void *, unsigned char *, size_t),
 | 
			
		||||
                           void *p_rng)
 | 
			
		||||
{
 | 
			
		||||
    if (X->limbs != N->limbs) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
    return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
 | 
			
		||||
                         const mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                         const unsigned char *buf,
 | 
			
		||||
                         size_t buflen,
 | 
			
		||||
                         mbedtls_mpi_mod_ext_rep ext_rep)
 | 
			
		||||
{
 | 
			
		||||
    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
 | 
			
		||||
    /* Do our best to check if r and m have been set up */
 | 
			
		||||
    if (r->limbs == 0 || N->limbs == 0) {
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
    if (r->limbs != N->limbs) {
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r->limbs = N->limbs;
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N);
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
 | 
			
		||||
                          const mbedtls_mpi_mod_modulus *N,
 | 
			
		||||
                          unsigned char *buf,
 | 
			
		||||
                          size_t buflen,
 | 
			
		||||
                          mbedtls_mpi_mod_ext_rep ext_rep)
 | 
			
		||||
{
 | 
			
		||||
    /* Do our best to check if r and m have been set up */
 | 
			
		||||
    if (r->limbs == 0 || N->limbs == 0) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
    if (r->limbs != N->limbs) {
 | 
			
		||||
        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    mbedtls_mpi_uint *working_memory = r->p;
 | 
			
		||||
    size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs;
 | 
			
		||||
 | 
			
		||||
    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
 | 
			
		||||
 | 
			
		||||
        working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint));
 | 
			
		||||
 | 
			
		||||
        if (working_memory == NULL) {
 | 
			
		||||
            ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
 | 
			
		||||
            goto cleanup;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        memcpy(working_memory, r->p, working_memory_len);
 | 
			
		||||
 | 
			
		||||
        ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N);
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
            goto cleanup;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep);
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
 | 
			
		||||
    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&
 | 
			
		||||
        working_memory != NULL) {
 | 
			
		||||
 | 
			
		||||
        mbedtls_zeroize_and_free(working_memory, working_memory_len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
 | 
			
		||||
							
								
								
									
										207
									
								
								thirdparty/mbedtls/library/block_cipher.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										207
									
								
								thirdparty/mbedtls/library/block_cipher.c
									
									
									
									
										vendored
									
									
								
							@@ -1,207 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * \file block_cipher.c
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks,
 | 
			
		||||
 * for use by the GCM and CCM modules.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright The Mbed TLS Contributors
 | 
			
		||||
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
 | 
			
		||||
#include "psa/crypto.h"
 | 
			
		||||
#include "psa_crypto_core.h"
 | 
			
		||||
#include "psa_util_internal.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "block_cipher_internal.h"
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_C)
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
 | 
			
		||||
static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id)
 | 
			
		||||
{
 | 
			
		||||
    switch (cipher_id) {
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_AES:
 | 
			
		||||
            return PSA_KEY_TYPE_AES;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
 | 
			
		||||
            return PSA_KEY_TYPE_ARIA;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
 | 
			
		||||
            return PSA_KEY_TYPE_CAMELLIA;
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            return PSA_KEY_TYPE_NONE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mbedtls_cipher_error_from_psa(psa_status_t status)
 | 
			
		||||
{
 | 
			
		||||
    return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors,
 | 
			
		||||
                                   psa_generic_status_to_mbedtls);
 | 
			
		||||
}
 | 
			
		||||
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
 | 
			
		||||
 | 
			
		||||
void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    if (ctx == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
 | 
			
		||||
    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
 | 
			
		||||
        psa_destroy_key(ctx->psa_key_id);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    switch (ctx->id) {
 | 
			
		||||
#if defined(MBEDTLS_AES_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_AES:
 | 
			
		||||
            mbedtls_aes_free(&ctx->ctx.aes);
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_ARIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
 | 
			
		||||
            mbedtls_aria_free(&ctx->ctx.aria);
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_CAMELLIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
 | 
			
		||||
            mbedtls_camellia_free(&ctx->ctx.camellia);
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,
 | 
			
		||||
                               mbedtls_cipher_id_t cipher_id)
 | 
			
		||||
{
 | 
			
		||||
    ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES :
 | 
			
		||||
              (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA :
 | 
			
		||||
              (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA :
 | 
			
		||||
              MBEDTLS_BLOCK_CIPHER_ID_NONE;
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
 | 
			
		||||
    psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id);
 | 
			
		||||
    if (psa_key_type != PSA_KEY_TYPE_NONE &&
 | 
			
		||||
        psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) {
 | 
			
		||||
        ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    switch (ctx->id) {
 | 
			
		||||
#if defined(MBEDTLS_AES_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_AES:
 | 
			
		||||
            mbedtls_aes_init(&ctx->ctx.aes);
 | 
			
		||||
            return 0;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_ARIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
 | 
			
		||||
            mbedtls_aria_init(&ctx->ctx.aria);
 | 
			
		||||
            return 0;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_CAMELLIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
 | 
			
		||||
            mbedtls_camellia_init(&ctx->ctx.camellia);
 | 
			
		||||
            return 0;
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
 | 
			
		||||
            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,
 | 
			
		||||
                                const unsigned char *key,
 | 
			
		||||
                                unsigned key_bitlen)
 | 
			
		||||
{
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
 | 
			
		||||
    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
 | 
			
		||||
        psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
 | 
			
		||||
        psa_status_t status;
 | 
			
		||||
 | 
			
		||||
        psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id));
 | 
			
		||||
        psa_set_key_bits(&key_attr, key_bitlen);
 | 
			
		||||
        psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
 | 
			
		||||
        psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
 | 
			
		||||
 | 
			
		||||
        status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id);
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            return mbedtls_cipher_error_from_psa(status);
 | 
			
		||||
        }
 | 
			
		||||
        psa_reset_key_attributes(&key_attr);
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
 | 
			
		||||
 | 
			
		||||
    switch (ctx->id) {
 | 
			
		||||
#if defined(MBEDTLS_AES_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_AES:
 | 
			
		||||
            return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen);
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_ARIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
 | 
			
		||||
            return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen);
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_CAMELLIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
 | 
			
		||||
            return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen);
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,
 | 
			
		||||
                                 const unsigned char input[16],
 | 
			
		||||
                                 unsigned char output[16])
 | 
			
		||||
{
 | 
			
		||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
 | 
			
		||||
    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
 | 
			
		||||
        psa_status_t status;
 | 
			
		||||
        size_t olen;
 | 
			
		||||
 | 
			
		||||
        status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING,
 | 
			
		||||
                                    input, 16, output, 16, &olen);
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            return mbedtls_cipher_error_from_psa(status);
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
 | 
			
		||||
 | 
			
		||||
    switch (ctx->id) {
 | 
			
		||||
#if defined(MBEDTLS_AES_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_AES:
 | 
			
		||||
            return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT,
 | 
			
		||||
                                         input, output);
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_ARIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
 | 
			
		||||
            return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output);
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(MBEDTLS_CAMELLIA_C)
 | 
			
		||||
        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
 | 
			
		||||
            return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia,
 | 
			
		||||
                                              MBEDTLS_CAMELLIA_ENCRYPT,
 | 
			
		||||
                                              input, output);
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
            return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* MBEDTLS_BLOCK_CIPHER_C */
 | 
			
		||||
							
								
								
									
										6036
									
								
								thirdparty/mbedtls/library/ecp_curves_new.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6036
									
								
								thirdparty/mbedtls/library/ecp_curves_new.c
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										786
									
								
								thirdparty/mbedtls/library/lmots.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										786
									
								
								thirdparty/mbedtls/library/lmots.c
									
									
									
									
										vendored
									
									
								
							@@ -1,786 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The LM-OTS one-time public-key signature scheme
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright The Mbed TLS Contributors
 | 
			
		||||
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  The following sources were referenced in the design of this implementation
 | 
			
		||||
 *  of the LM-OTS algorithm:
 | 
			
		||||
 *
 | 
			
		||||
 *  [1] IETF RFC8554
 | 
			
		||||
 *      D. McGrew, M. Curcio, S.Fluhrer
 | 
			
		||||
 *      https://datatracker.ietf.org/doc/html/rfc8554
 | 
			
		||||
 *
 | 
			
		||||
 *  [2] NIST Special Publication 800-208
 | 
			
		||||
 *      David A. Cooper et. al.
 | 
			
		||||
 *      https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_LMS_C)
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "lmots.h"
 | 
			
		||||
 | 
			
		||||
#include "mbedtls/lms.h"
 | 
			
		||||
#include "mbedtls/platform_util.h"
 | 
			
		||||
#include "mbedtls/error.h"
 | 
			
		||||
#include "psa_util_internal.h"
 | 
			
		||||
 | 
			
		||||
#include "psa/crypto.h"
 | 
			
		||||
 | 
			
		||||
/* Define a local translating function to save code size by not using too many
 | 
			
		||||
 * arguments in each translating place. */
 | 
			
		||||
static int local_err_translation(psa_status_t status)
 | 
			
		||||
{
 | 
			
		||||
    return psa_status_to_mbedtls(status, psa_to_lms_errors,
 | 
			
		||||
                                 ARRAY_LENGTH(psa_to_lms_errors),
 | 
			
		||||
                                 psa_generic_status_to_mbedtls);
 | 
			
		||||
}
 | 
			
		||||
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 | 
			
		||||
 | 
			
		||||
#define PUBLIC_KEY_TYPE_OFFSET     (0)
 | 
			
		||||
#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
 | 
			
		||||
                                    MBEDTLS_LMOTS_TYPE_LEN)
 | 
			
		||||
#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
 | 
			
		||||
                                     MBEDTLS_LMOTS_I_KEY_ID_LEN)
 | 
			
		||||
#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \
 | 
			
		||||
                                    MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
 | 
			
		||||
 | 
			
		||||
/* We only support parameter sets that use 8-bit digits, as it does not require
 | 
			
		||||
 * translation logic between digits and bytes */
 | 
			
		||||
#define W_WINTERNITZ_PARAMETER (8u)
 | 
			
		||||
#define CHECKSUM_LEN           (2)
 | 
			
		||||
#define I_DIGIT_IDX_LEN        (2)
 | 
			
		||||
#define J_HASH_IDX_LEN         (1)
 | 
			
		||||
#define D_CONST_LEN            (2)
 | 
			
		||||
 | 
			
		||||
#define DIGIT_MAX_VALUE        ((1u << W_WINTERNITZ_PARAMETER) - 1u)
 | 
			
		||||
 | 
			
		||||
#define D_CONST_LEN            (2)
 | 
			
		||||
static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 };
 | 
			
		||||
static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 };
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_TEST_HOOKS)
 | 
			
		||||
int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL;
 | 
			
		||||
#endif /* defined(MBEDTLS_TEST_HOOKS) */
 | 
			
		||||
 | 
			
		||||
/* Calculate the checksum digits that are appended to the end of the LMOTS digit
 | 
			
		||||
 * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of
 | 
			
		||||
 * the checksum algorithm.
 | 
			
		||||
 *
 | 
			
		||||
 *  params              The LMOTS parameter set, I and q values which
 | 
			
		||||
 *                      describe the key being used.
 | 
			
		||||
 *
 | 
			
		||||
 *  digest              The digit string to create the digest from. As
 | 
			
		||||
 *                      this does not contain a checksum, it is the same
 | 
			
		||||
 *                      size as a hash output.
 | 
			
		||||
 */
 | 
			
		||||
static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params,
 | 
			
		||||
                                               const unsigned char *digest)
 | 
			
		||||
{
 | 
			
		||||
    size_t idx;
 | 
			
		||||
    unsigned sum = 0;
 | 
			
		||||
 | 
			
		||||
    for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) {
 | 
			
		||||
        sum += DIGIT_MAX_VALUE - digest[idx];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return sum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Create the string of digest digits (in the base determined by the Winternitz
 | 
			
		||||
 * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST
 | 
			
		||||
 * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm
 | 
			
		||||
 * 4b step 3) for details.
 | 
			
		||||
 *
 | 
			
		||||
 *  params              The LMOTS parameter set, I and q values which
 | 
			
		||||
 *                      describe the key being used.
 | 
			
		||||
 *
 | 
			
		||||
 *  msg                 The message that will be hashed to create the
 | 
			
		||||
 *                      digest.
 | 
			
		||||
 *
 | 
			
		||||
 *  msg_size            The size of the message.
 | 
			
		||||
 *
 | 
			
		||||
 *  C_random_value      The random value that will be combined with the
 | 
			
		||||
 *                      message digest. This is always the same size as a
 | 
			
		||||
 *                      hash output for whichever hash algorithm is
 | 
			
		||||
 *                      determined by the parameter set.
 | 
			
		||||
 *
 | 
			
		||||
 *  output              An output containing the digit string (+
 | 
			
		||||
 *                      checksum) of length P digits (in the case of
 | 
			
		||||
 *                      MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of
 | 
			
		||||
 *                      size P bytes).
 | 
			
		||||
 */
 | 
			
		||||
static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params,
 | 
			
		||||
                                            const unsigned char *msg,
 | 
			
		||||
                                            size_t msg_len,
 | 
			
		||||
                                            const unsigned char *C_random_value,
 | 
			
		||||
                                            unsigned char *out)
 | 
			
		||||
{
 | 
			
		||||
    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
 | 
			
		||||
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    size_t output_hash_len;
 | 
			
		||||
    unsigned short checksum;
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, params->I_key_identifier,
 | 
			
		||||
                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, params->q_leaf_identifier,
 | 
			
		||||
                             MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, C_random_value,
 | 
			
		||||
                             MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type));
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, msg, msg_len);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_finish(&op, out,
 | 
			
		||||
                             MBEDTLS_LMOTS_N_HASH_LEN(params->type),
 | 
			
		||||
                             &output_hash_len);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    checksum = lmots_checksum_calculate(params, out);
 | 
			
		||||
    MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    psa_hash_abort(&op);
 | 
			
		||||
 | 
			
		||||
    return PSA_TO_MBEDTLS_ERR(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Hash each element of the string of digits (+ checksum), producing a hash
 | 
			
		||||
 * output for each element. This is used in several places (by varying the
 | 
			
		||||
 * hash_idx_min/max_values) in order to calculate a public key from a private
 | 
			
		||||
 * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554
 | 
			
		||||
 * Algorithm 3 step 5), and to calculate a public key candidate from a
 | 
			
		||||
 * signature and message (RFC8554 Algorithm 4b step 3).
 | 
			
		||||
 *
 | 
			
		||||
 *  params              The LMOTS parameter set, I and q values which
 | 
			
		||||
 *                      describe the key being used.
 | 
			
		||||
 *
 | 
			
		||||
 *  x_digit_array       The array of digits (of size P, 34 in the case of
 | 
			
		||||
 *                      MBEDTLS_LMOTS_SHA256_N32_W8).
 | 
			
		||||
 *
 | 
			
		||||
 *  hash_idx_min_values An array of the starting values of the j iterator
 | 
			
		||||
 *                      for each of the members of the digit array. If
 | 
			
		||||
 *                      this value in NULL, then all iterators will start
 | 
			
		||||
 *                      at 0.
 | 
			
		||||
 *
 | 
			
		||||
 *  hash_idx_max_values An array of the upper bound values of the j
 | 
			
		||||
 *                      iterator for each of the members of the digit
 | 
			
		||||
 *                      array. If this value in NULL, then iterator is
 | 
			
		||||
 *                      bounded to be less than 2^w - 1 (255 in the case
 | 
			
		||||
 *                      of MBEDTLS_LMOTS_SHA256_N32_W8)
 | 
			
		||||
 *
 | 
			
		||||
 *  output              An array containing a hash output for each member
 | 
			
		||||
 *                      of the digit string P. In the case of
 | 
			
		||||
 *                      MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 *
 | 
			
		||||
 *                      34.
 | 
			
		||||
 */
 | 
			
		||||
static int hash_digit_array(const mbedtls_lmots_parameters_t *params,
 | 
			
		||||
                            const unsigned char *x_digit_array,
 | 
			
		||||
                            const unsigned char *hash_idx_min_values,
 | 
			
		||||
                            const unsigned char *hash_idx_max_values,
 | 
			
		||||
                            unsigned char *output)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int i_digit_idx;
 | 
			
		||||
    unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN];
 | 
			
		||||
    unsigned int j_hash_idx;
 | 
			
		||||
    unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN];
 | 
			
		||||
    unsigned int j_hash_idx_min;
 | 
			
		||||
    unsigned int j_hash_idx_max;
 | 
			
		||||
    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
 | 
			
		||||
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    size_t output_hash_len;
 | 
			
		||||
    unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
 | 
			
		||||
 | 
			
		||||
    for (i_digit_idx = 0;
 | 
			
		||||
         i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type);
 | 
			
		||||
         i_digit_idx++) {
 | 
			
		||||
 | 
			
		||||
        memcpy(tmp_hash,
 | 
			
		||||
               &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
 | 
			
		||||
               MBEDTLS_LMOTS_N_HASH_LEN(params->type));
 | 
			
		||||
 | 
			
		||||
        j_hash_idx_min = hash_idx_min_values != NULL ?
 | 
			
		||||
                         hash_idx_min_values[i_digit_idx] : 0;
 | 
			
		||||
        j_hash_idx_max = hash_idx_max_values != NULL ?
 | 
			
		||||
                         hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE;
 | 
			
		||||
 | 
			
		||||
        for (j_hash_idx = j_hash_idx_min;
 | 
			
		||||
             j_hash_idx < j_hash_idx_max;
 | 
			
		||||
             j_hash_idx++) {
 | 
			
		||||
            status = psa_hash_setup(&op, PSA_ALG_SHA_256);
 | 
			
		||||
            if (status != PSA_SUCCESS) {
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            status = psa_hash_update(&op,
 | 
			
		||||
                                     params->I_key_identifier,
 | 
			
		||||
                                     MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
            if (status != PSA_SUCCESS) {
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            status = psa_hash_update(&op,
 | 
			
		||||
                                     params->q_leaf_identifier,
 | 
			
		||||
                                     MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
 | 
			
		||||
            if (status != PSA_SUCCESS) {
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
 | 
			
		||||
            status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
 | 
			
		||||
            if (status != PSA_SUCCESS) {
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            j_hash_idx_bytes[0] = (uint8_t) j_hash_idx;
 | 
			
		||||
            status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN);
 | 
			
		||||
            if (status != PSA_SUCCESS) {
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            status = psa_hash_update(&op, tmp_hash,
 | 
			
		||||
                                     MBEDTLS_LMOTS_N_HASH_LEN(params->type));
 | 
			
		||||
            if (status != PSA_SUCCESS) {
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash),
 | 
			
		||||
                                     &output_hash_len);
 | 
			
		||||
            if (status != PSA_SUCCESS) {
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            psa_hash_abort(&op);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
 | 
			
		||||
               tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    psa_hash_abort(&op);
 | 
			
		||||
    mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash));
 | 
			
		||||
 | 
			
		||||
    return PSA_TO_MBEDTLS_ERR(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Combine the hashes of the digit array into a public key. This is used in
 | 
			
		||||
 * in order to calculate a public key from a private key (RFC8554 Algorithm 1
 | 
			
		||||
 * step 4), and to calculate a public key candidate from a signature and message
 | 
			
		||||
 * (RFC8554 Algorithm 4b step 3).
 | 
			
		||||
 *
 | 
			
		||||
 *  params           The LMOTS parameter set, I and q values which describe
 | 
			
		||||
 *                   the key being used.
 | 
			
		||||
 *  y_hashed_digits  The array of hashes, one hash for each digit of the
 | 
			
		||||
 *                   symbol array (which is of size P, 34 in the case of
 | 
			
		||||
 *                   MBEDTLS_LMOTS_SHA256_N32_W8)
 | 
			
		||||
 *
 | 
			
		||||
 *  pub_key          The output public key (or candidate public key in
 | 
			
		||||
 *                   case this is being run as part of signature
 | 
			
		||||
 *                   verification), in the form of a hash output.
 | 
			
		||||
 */
 | 
			
		||||
static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params,
 | 
			
		||||
                                              const unsigned char *y_hashed_digits,
 | 
			
		||||
                                              unsigned char *pub_key)
 | 
			
		||||
{
 | 
			
		||||
    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
 | 
			
		||||
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    size_t output_hash_len;
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op,
 | 
			
		||||
                             params->I_key_identifier,
 | 
			
		||||
                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, params->q_leaf_identifier,
 | 
			
		||||
                             MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, y_hashed_digits,
 | 
			
		||||
                             MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) *
 | 
			
		||||
                             MBEDTLS_LMOTS_N_HASH_LEN(params->type));
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_finish(&op, pub_key,
 | 
			
		||||
                             MBEDTLS_LMOTS_N_HASH_LEN(params->type),
 | 
			
		||||
                             &output_hash_len);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
        psa_hash_abort(&op);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return PSA_TO_MBEDTLS_ERR(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 | 
			
		||||
int mbedtls_lms_error_from_psa(psa_status_t status)
 | 
			
		||||
{
 | 
			
		||||
    switch (status) {
 | 
			
		||||
        case PSA_SUCCESS:
 | 
			
		||||
            return 0;
 | 
			
		||||
        case PSA_ERROR_HARDWARE_FAILURE:
 | 
			
		||||
            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
 | 
			
		||||
        case PSA_ERROR_NOT_SUPPORTED:
 | 
			
		||||
            return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
 | 
			
		||||
        case PSA_ERROR_BUFFER_TOO_SMALL:
 | 
			
		||||
            return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
 | 
			
		||||
        case PSA_ERROR_INVALID_ARGUMENT:
 | 
			
		||||
            return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
        default:
 | 
			
		||||
            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 | 
			
		||||
 | 
			
		||||
void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    memset(ctx, 0, sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    if (ctx == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
 | 
			
		||||
                                    const unsigned char *key, size_t key_len)
 | 
			
		||||
{
 | 
			
		||||
    if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx->params.type = (mbedtls_lmots_algorithm_type_t)
 | 
			
		||||
                       MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
 | 
			
		||||
 | 
			
		||||
    if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(ctx->params.I_key_identifier,
 | 
			
		||||
           key + PUBLIC_KEY_I_KEY_ID_OFFSET,
 | 
			
		||||
           MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
 | 
			
		||||
    memcpy(ctx->params.q_leaf_identifier,
 | 
			
		||||
           key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
 | 
			
		||||
           MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
 | 
			
		||||
 | 
			
		||||
    memcpy(ctx->public_key,
 | 
			
		||||
           key + PUBLIC_KEY_KEY_HASH_OFFSET,
 | 
			
		||||
           MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    ctx->have_public_key = 1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
 | 
			
		||||
                                    unsigned char *key, size_t key_size,
 | 
			
		||||
                                    size_t *key_len)
 | 
			
		||||
{
 | 
			
		||||
    if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!ctx->have_public_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
 | 
			
		||||
 | 
			
		||||
    memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
 | 
			
		||||
           ctx->params.I_key_identifier,
 | 
			
		||||
           MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
 | 
			
		||||
    memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
 | 
			
		||||
           ctx->params.q_leaf_identifier,
 | 
			
		||||
           MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
 | 
			
		||||
 | 
			
		||||
    memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key,
 | 
			
		||||
           MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    if (key_len != NULL) {
 | 
			
		||||
        *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,
 | 
			
		||||
                                                 const unsigned char  *msg,
 | 
			
		||||
                                                 size_t msg_size,
 | 
			
		||||
                                                 const unsigned char *sig,
 | 
			
		||||
                                                 size_t sig_size,
 | 
			
		||||
                                                 unsigned char *out,
 | 
			
		||||
                                                 size_t out_size,
 | 
			
		||||
                                                 size_t *out_len)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
 | 
			
		||||
    unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    if (msg == NULL && msg_size != 0) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) ||
 | 
			
		||||
        out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = create_digit_array_with_checksum(params, msg, msg_size,
 | 
			
		||||
                                           sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET,
 | 
			
		||||
                                           tmp_digit_array);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = hash_digit_array(params,
 | 
			
		||||
                           sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type),
 | 
			
		||||
                           tmp_digit_array, NULL, (unsigned char *) y_hashed_digits);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = public_key_from_hashed_digit_array(params,
 | 
			
		||||
                                             (unsigned char *) y_hashed_digits,
 | 
			
		||||
                                             out);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (out_len != NULL) {
 | 
			
		||||
        *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
 | 
			
		||||
                         const unsigned char *msg, size_t msg_size,
 | 
			
		||||
                         const unsigned char *sig, size_t sig_size)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    if (msg == NULL && msg_size != 0) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!ctx->have_public_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params,
 | 
			
		||||
                                                       msg, msg_size, sig, sig_size,
 | 
			
		||||
                                                       Kc_public_key_candidate,
 | 
			
		||||
                                                       MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
 | 
			
		||||
                                                       NULL);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (memcmp(&Kc_public_key_candidate, ctx->public_key,
 | 
			
		||||
               sizeof(ctx->public_key))) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_LMS_PRIVATE)
 | 
			
		||||
 | 
			
		||||
void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    memset(ctx, 0, sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    if (ctx == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_platform_zeroize(ctx,
 | 
			
		||||
                             sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
 | 
			
		||||
                                       mbedtls_lmots_algorithm_type_t type,
 | 
			
		||||
                                       const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
 | 
			
		||||
                                       uint32_t q_leaf_identifier,
 | 
			
		||||
                                       const unsigned char *seed,
 | 
			
		||||
                                       size_t seed_size)
 | 
			
		||||
{
 | 
			
		||||
    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
 | 
			
		||||
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    size_t output_hash_len;
 | 
			
		||||
    unsigned int i_digit_idx;
 | 
			
		||||
    unsigned char i_digit_idx_bytes[2];
 | 
			
		||||
    unsigned char const_bytes[1] = { 0xFF };
 | 
			
		||||
 | 
			
		||||
    if (ctx->have_private_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (type != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx->params.type = type;
 | 
			
		||||
 | 
			
		||||
    memcpy(ctx->params.I_key_identifier,
 | 
			
		||||
           I_key_identifier,
 | 
			
		||||
           sizeof(ctx->params.I_key_identifier));
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0);
 | 
			
		||||
 | 
			
		||||
    for (i_digit_idx = 0;
 | 
			
		||||
         i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type);
 | 
			
		||||
         i_digit_idx++) {
 | 
			
		||||
        status = psa_hash_setup(&op, PSA_ALG_SHA_256);
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        status = psa_hash_update(&op,
 | 
			
		||||
                                 ctx->params.I_key_identifier,
 | 
			
		||||
                                 sizeof(ctx->params.I_key_identifier));
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        status = psa_hash_update(&op,
 | 
			
		||||
                                 ctx->params.q_leaf_identifier,
 | 
			
		||||
                                 MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
 | 
			
		||||
        status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        status = psa_hash_update(&op, const_bytes, sizeof(const_bytes));
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        status = psa_hash_update(&op, seed, seed_size);
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        status = psa_hash_finish(&op,
 | 
			
		||||
                                 ctx->private_key[i_digit_idx],
 | 
			
		||||
                                 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
 | 
			
		||||
                                 &output_hash_len);
 | 
			
		||||
        if (status != PSA_SUCCESS) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        psa_hash_abort(&op);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx->have_private_key = 1;
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    psa_hash_abort(&op);
 | 
			
		||||
 | 
			
		||||
    return PSA_TO_MBEDTLS_ERR(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
 | 
			
		||||
                                       const mbedtls_lmots_private_t *priv_ctx)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    /* Check that a private key is loaded */
 | 
			
		||||
    if (!priv_ctx->have_private_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = hash_digit_array(&priv_ctx->params,
 | 
			
		||||
                           (unsigned char *) priv_ctx->private_key, NULL,
 | 
			
		||||
                           NULL, (unsigned char *) y_hashed_digits);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = public_key_from_hashed_digit_array(&priv_ctx->params,
 | 
			
		||||
                                             (unsigned char *) y_hashed_digits,
 | 
			
		||||
                                             ctx->public_key);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(&ctx->params, &priv_ctx->params,
 | 
			
		||||
           sizeof(ctx->params));
 | 
			
		||||
 | 
			
		||||
    ctx->have_public_key = 1;
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
 | 
			
		||||
                       int (*f_rng)(void *, unsigned char *, size_t),
 | 
			
		||||
                       void *p_rng, const unsigned char *msg, size_t msg_size,
 | 
			
		||||
                       unsigned char *sig, size_t sig_size, size_t *sig_len)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
 | 
			
		||||
    /* Create a temporary buffer to prepare the signature in. This allows us to
 | 
			
		||||
     * finish creating a signature (ensuring the process doesn't fail), and then
 | 
			
		||||
     * erase the private key **before** writing any data into the sig parameter
 | 
			
		||||
     * buffer. If data were directly written into the sig buffer, it might leak
 | 
			
		||||
     * a partial signature on failure, which effectively compromises the private
 | 
			
		||||
     * key.
 | 
			
		||||
     */
 | 
			
		||||
    unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
 | 
			
		||||
    unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    if (msg == NULL && msg_size != 0) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check that a private key is loaded */
 | 
			
		||||
    if (!ctx->have_private_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = f_rng(p_rng, tmp_c_random,
 | 
			
		||||
                MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = create_digit_array_with_checksum(&ctx->params,
 | 
			
		||||
                                           msg, msg_size,
 | 
			
		||||
                                           tmp_c_random,
 | 
			
		||||
                                           tmp_digit_array);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key,
 | 
			
		||||
                           NULL, tmp_digit_array, (unsigned char *) tmp_sig);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
 | 
			
		||||
 | 
			
		||||
    /* Test hook to check if sig is being written to before we invalidate the
 | 
			
		||||
     * private key.
 | 
			
		||||
     */
 | 
			
		||||
#if defined(MBEDTLS_TEST_HOOKS)
 | 
			
		||||
    if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) {
 | 
			
		||||
        ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig);
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif /* defined(MBEDTLS_TEST_HOOKS) */
 | 
			
		||||
 | 
			
		||||
    /* We've got a valid signature now, so it's time to make sure the private
 | 
			
		||||
     * key can't be reused.
 | 
			
		||||
     */
 | 
			
		||||
    ctx->have_private_key = 0;
 | 
			
		||||
    mbedtls_platform_zeroize(ctx->private_key,
 | 
			
		||||
                             sizeof(ctx->private_key));
 | 
			
		||||
 | 
			
		||||
    memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random,
 | 
			
		||||
           MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig,
 | 
			
		||||
           MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type)
 | 
			
		||||
           * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    if (sig_len != NULL) {
 | 
			
		||||
        *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = 0;
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array));
 | 
			
		||||
    mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
 | 
			
		||||
#endif /* defined(MBEDTLS_LMS_C) */
 | 
			
		||||
							
								
								
									
										769
									
								
								thirdparty/mbedtls/library/lms.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										769
									
								
								thirdparty/mbedtls/library/lms.c
									
									
									
									
										vendored
									
									
								
							@@ -1,769 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  The LMS stateful-hash public-key signature scheme
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright The Mbed TLS Contributors
 | 
			
		||||
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  The following sources were referenced in the design of this implementation
 | 
			
		||||
 *  of the LMS algorithm:
 | 
			
		||||
 *
 | 
			
		||||
 *  [1] IETF RFC8554
 | 
			
		||||
 *      D. McGrew, M. Curcio, S.Fluhrer
 | 
			
		||||
 *      https://datatracker.ietf.org/doc/html/rfc8554
 | 
			
		||||
 *
 | 
			
		||||
 *  [2] NIST Special Publication 800-208
 | 
			
		||||
 *      David A. Cooper et. al.
 | 
			
		||||
 *      https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_LMS_C)
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "lmots.h"
 | 
			
		||||
 | 
			
		||||
#include "psa/crypto.h"
 | 
			
		||||
#include "psa_util_internal.h"
 | 
			
		||||
#include "mbedtls/lms.h"
 | 
			
		||||
#include "mbedtls/error.h"
 | 
			
		||||
#include "mbedtls/platform_util.h"
 | 
			
		||||
 | 
			
		||||
#include "mbedtls/platform.h"
 | 
			
		||||
 | 
			
		||||
/* Define a local translating function to save code size by not using too many
 | 
			
		||||
 * arguments in each translating place. */
 | 
			
		||||
static int local_err_translation(psa_status_t status)
 | 
			
		||||
{
 | 
			
		||||
    return psa_status_to_mbedtls(status, psa_to_lms_errors,
 | 
			
		||||
                                 ARRAY_LENGTH(psa_to_lms_errors),
 | 
			
		||||
                                 psa_generic_status_to_mbedtls);
 | 
			
		||||
}
 | 
			
		||||
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 | 
			
		||||
 | 
			
		||||
#define SIG_Q_LEAF_ID_OFFSET     (0)
 | 
			
		||||
#define SIG_OTS_SIG_OFFSET       (SIG_Q_LEAF_ID_OFFSET + \
 | 
			
		||||
                                  MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
 | 
			
		||||
#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET   + \
 | 
			
		||||
                                  MBEDTLS_LMOTS_SIG_LEN(otstype))
 | 
			
		||||
#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \
 | 
			
		||||
                                  MBEDTLS_LMS_TYPE_LEN)
 | 
			
		||||
 | 
			
		||||
#define PUBLIC_KEY_TYPE_OFFSET      (0)
 | 
			
		||||
#define PUBLIC_KEY_OTSTYPE_OFFSET   (PUBLIC_KEY_TYPE_OFFSET + \
 | 
			
		||||
                                     MBEDTLS_LMS_TYPE_LEN)
 | 
			
		||||
#define PUBLIC_KEY_I_KEY_ID_OFFSET  (PUBLIC_KEY_OTSTYPE_OFFSET  + \
 | 
			
		||||
                                     MBEDTLS_LMOTS_TYPE_LEN)
 | 
			
		||||
#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
 | 
			
		||||
                                     MBEDTLS_LMOTS_I_KEY_ID_LEN)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Currently only support H=10 */
 | 
			
		||||
#define H_TREE_HEIGHT_MAX                  10
 | 
			
		||||
#define MERKLE_TREE_NODE_AM(type)          ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
 | 
			
		||||
#define MERKLE_TREE_LEAF_NODE_AM(type)     ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
 | 
			
		||||
#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \
 | 
			
		||||
                                            (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))
 | 
			
		||||
 | 
			
		||||
#define D_CONST_LEN           (2)
 | 
			
		||||
static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };
 | 
			
		||||
static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a
 | 
			
		||||
 * public key and some other parameters like the leaf index). This function
 | 
			
		||||
 * implements RFC8554 section 5.3, in the case where r >= 2^h.
 | 
			
		||||
 *
 | 
			
		||||
 *  params              The LMS parameter set, the underlying LMOTS
 | 
			
		||||
 *                      parameter set, and I value which describe the key
 | 
			
		||||
 *                      being used.
 | 
			
		||||
 *
 | 
			
		||||
 *  pub_key             The public key of the private whose index
 | 
			
		||||
 *                      corresponds to the index of this leaf node. This
 | 
			
		||||
 *                      is a hash output.
 | 
			
		||||
 *
 | 
			
		||||
 *  r_node_idx          The index of this node in the Merkle tree. Note
 | 
			
		||||
 *                      that the root node of the Merkle tree is
 | 
			
		||||
 *                      1-indexed.
 | 
			
		||||
 *
 | 
			
		||||
 *  out                 The output node value, which is a hash output.
 | 
			
		||||
 */
 | 
			
		||||
static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params,
 | 
			
		||||
                                    unsigned char *pub_key,
 | 
			
		||||
                                    unsigned int r_node_idx,
 | 
			
		||||
                                    unsigned char *out)
 | 
			
		||||
{
 | 
			
		||||
    psa_hash_operation_t op;
 | 
			
		||||
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    size_t output_hash_len;
 | 
			
		||||
    unsigned char r_node_idx_bytes[4];
 | 
			
		||||
 | 
			
		||||
    op = psa_hash_operation_init();
 | 
			
		||||
    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, params->I_key_identifier,
 | 
			
		||||
                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
 | 
			
		||||
    status = psa_hash_update(&op, r_node_idx_bytes, 4);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, pub_key,
 | 
			
		||||
                             MBEDTLS_LMOTS_N_HASH_LEN(params->otstype));
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
 | 
			
		||||
                             &output_hash_len);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    psa_hash_abort(&op);
 | 
			
		||||
 | 
			
		||||
    return PSA_TO_MBEDTLS_ERR(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Calculate the value of an internal node of the Merkle tree (which is a hash
 | 
			
		||||
 * of a public key and some other parameters like the node index). This function
 | 
			
		||||
 * implements RFC8554 section 5.3, in the case where r < 2^h.
 | 
			
		||||
 *
 | 
			
		||||
 *  params              The LMS parameter set, the underlying LMOTS
 | 
			
		||||
 *                      parameter set, and I value which describe the key
 | 
			
		||||
 *                      being used.
 | 
			
		||||
 *
 | 
			
		||||
 *  left_node           The value of the child of this node which is on
 | 
			
		||||
 *                      the left-hand side. As with all nodes on the
 | 
			
		||||
 *                      Merkle tree, this is a hash output.
 | 
			
		||||
 *
 | 
			
		||||
 *  right_node          The value of the child of this node which is on
 | 
			
		||||
 *                      the right-hand side. As with all nodes on the
 | 
			
		||||
 *                      Merkle tree, this is a hash output.
 | 
			
		||||
 *
 | 
			
		||||
 *  r_node_idx          The index of this node in the Merkle tree. Note
 | 
			
		||||
 *                      that the root node of the Merkle tree is
 | 
			
		||||
 *                      1-indexed.
 | 
			
		||||
 *
 | 
			
		||||
 *  out                 The output node value, which is a hash output.
 | 
			
		||||
 */
 | 
			
		||||
static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params,
 | 
			
		||||
                                        const unsigned char *left_node,
 | 
			
		||||
                                        const unsigned char *right_node,
 | 
			
		||||
                                        unsigned int r_node_idx,
 | 
			
		||||
                                        unsigned char *out)
 | 
			
		||||
{
 | 
			
		||||
    psa_hash_operation_t op;
 | 
			
		||||
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    size_t output_hash_len;
 | 
			
		||||
    unsigned char r_node_idx_bytes[4];
 | 
			
		||||
 | 
			
		||||
    op = psa_hash_operation_init();
 | 
			
		||||
    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, params->I_key_identifier,
 | 
			
		||||
                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
 | 
			
		||||
    status = psa_hash_update(&op, r_node_idx_bytes, 4);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, left_node,
 | 
			
		||||
                             MBEDTLS_LMS_M_NODE_BYTES(params->type));
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_update(&op, right_node,
 | 
			
		||||
                             MBEDTLS_LMS_M_NODE_BYTES(params->type));
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
 | 
			
		||||
                             &output_hash_len);
 | 
			
		||||
    if (status != PSA_SUCCESS) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    psa_hash_abort(&op);
 | 
			
		||||
 | 
			
		||||
    return PSA_TO_MBEDTLS_ERR(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    memset(ctx, 0, sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    if (ctx == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
 | 
			
		||||
                                  const unsigned char *key, size_t key_size)
 | 
			
		||||
{
 | 
			
		||||
    mbedtls_lms_algorithm_type_t type;
 | 
			
		||||
    mbedtls_lmots_algorithm_type_t otstype;
 | 
			
		||||
 | 
			
		||||
    type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET);
 | 
			
		||||
    if (type != MBEDTLS_LMS_SHA256_M32_H10) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
    ctx->params.type = type;
 | 
			
		||||
 | 
			
		||||
    if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    otstype = (mbedtls_lmots_algorithm_type_t)
 | 
			
		||||
              MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET);
 | 
			
		||||
    if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
    ctx->params.otstype = otstype;
 | 
			
		||||
 | 
			
		||||
    memcpy(ctx->params.I_key_identifier,
 | 
			
		||||
           key + PUBLIC_KEY_I_KEY_ID_OFFSET,
 | 
			
		||||
           MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET,
 | 
			
		||||
           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    ctx->have_public_key = 1;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,
 | 
			
		||||
                                  unsigned char *key,
 | 
			
		||||
                                  size_t key_size, size_t *key_len)
 | 
			
		||||
{
 | 
			
		||||
    if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!ctx->have_public_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET);
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET);
 | 
			
		||||
    memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
 | 
			
		||||
           ctx->params.I_key_identifier,
 | 
			
		||||
           MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET,
 | 
			
		||||
           ctx->T_1_pub_key,
 | 
			
		||||
           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    if (key_len != NULL) {
 | 
			
		||||
        *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
 | 
			
		||||
                       const unsigned char *msg, size_t msg_size,
 | 
			
		||||
                       const unsigned char *sig, size_t sig_size)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int q_leaf_identifier;
 | 
			
		||||
    unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
 | 
			
		||||
    unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX];
 | 
			
		||||
    unsigned int height;
 | 
			
		||||
    unsigned int curr_node_id;
 | 
			
		||||
    unsigned int parent_node_id;
 | 
			
		||||
    const unsigned char *left_node;
 | 
			
		||||
    const unsigned char *right_node;
 | 
			
		||||
    mbedtls_lmots_parameters_t ots_params;
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    if (!ctx->have_public_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ctx->params.type
 | 
			
		||||
        != MBEDTLS_LMS_SHA256_M32_H10) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ctx->params.otstype
 | 
			
		||||
        != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
 | 
			
		||||
        != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype))
 | 
			
		||||
        != MBEDTLS_LMS_SHA256_M32_H10) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET);
 | 
			
		||||
 | 
			
		||||
    if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(ots_params.I_key_identifier,
 | 
			
		||||
           ctx->params.I_key_identifier,
 | 
			
		||||
           MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0);
 | 
			
		||||
    ots_params.type = ctx->params.otstype;
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params,
 | 
			
		||||
                                                       msg,
 | 
			
		||||
                                                       msg_size,
 | 
			
		||||
                                                       sig + SIG_OTS_SIG_OFFSET,
 | 
			
		||||
                                                       MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype),
 | 
			
		||||
                                                       Kc_candidate_ots_pub_key,
 | 
			
		||||
                                                       sizeof(Kc_candidate_ots_pub_key),
 | 
			
		||||
                                                       NULL);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    create_merkle_leaf_value(
 | 
			
		||||
        &ctx->params,
 | 
			
		||||
        Kc_candidate_ots_pub_key,
 | 
			
		||||
        MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
 | 
			
		||||
        Tc_candidate_root_node);
 | 
			
		||||
 | 
			
		||||
    curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) +
 | 
			
		||||
                   q_leaf_identifier;
 | 
			
		||||
 | 
			
		||||
    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
 | 
			
		||||
         height++) {
 | 
			
		||||
        parent_node_id = curr_node_id / 2;
 | 
			
		||||
 | 
			
		||||
        /* Left/right node ordering matters for the hash */
 | 
			
		||||
        if (curr_node_id & 1) {
 | 
			
		||||
            left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
 | 
			
		||||
                        height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
 | 
			
		||||
            right_node = Tc_candidate_root_node;
 | 
			
		||||
        } else {
 | 
			
		||||
            left_node = Tc_candidate_root_node;
 | 
			
		||||
            right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
 | 
			
		||||
                         height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        create_merkle_internal_value(&ctx->params, left_node, right_node,
 | 
			
		||||
                                     parent_node_id, Tc_candidate_root_node);
 | 
			
		||||
 | 
			
		||||
        curr_node_id /= 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key,
 | 
			
		||||
               MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_LMS_PRIVATE)
 | 
			
		||||
 | 
			
		||||
/* Calculate a full Merkle tree based on a private key. This function
 | 
			
		||||
 * implements RFC8554 section 5.3, and is used to generate a public key (as the
 | 
			
		||||
 * public key is the root node of the Merkle tree).
 | 
			
		||||
 *
 | 
			
		||||
 *  ctx                 The LMS private context, containing a parameter
 | 
			
		||||
 *                      set and private key material consisting of both
 | 
			
		||||
 *                      public and private OTS.
 | 
			
		||||
 *
 | 
			
		||||
 *  tree                The output tree, which is 2^(H + 1) hash outputs.
 | 
			
		||||
 *                      In the case of H=10 we have 2048 tree nodes (of
 | 
			
		||||
 *                      which 1024 of them are leaf nodes). Note that
 | 
			
		||||
 *                      because the Merkle tree root is 1-indexed, the 0
 | 
			
		||||
 *                      index tree node is never used.
 | 
			
		||||
 */
 | 
			
		||||
static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx,
 | 
			
		||||
                                 unsigned char *tree)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int priv_key_idx;
 | 
			
		||||
    unsigned int r_node_idx;
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    /* First create the leaf nodes, in ascending order */
 | 
			
		||||
    for (priv_key_idx = 0;
 | 
			
		||||
         priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type);
 | 
			
		||||
         priv_key_idx++) {
 | 
			
		||||
        r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx;
 | 
			
		||||
 | 
			
		||||
        ret = create_merkle_leaf_value(&ctx->params,
 | 
			
		||||
                                       ctx->ots_public_keys[priv_key_idx].public_key,
 | 
			
		||||
                                       r_node_idx,
 | 
			
		||||
                                       &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(
 | 
			
		||||
                                                 ctx->params.type)]);
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Then the internal nodes, in reverse order so that we can guarantee the
 | 
			
		||||
     * parent has been created */
 | 
			
		||||
    for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1;
 | 
			
		||||
         r_node_idx > 0;
 | 
			
		||||
         r_node_idx--) {
 | 
			
		||||
        ret = create_merkle_internal_value(&ctx->params,
 | 
			
		||||
                                           &tree[(r_node_idx * 2) *
 | 
			
		||||
                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
 | 
			
		||||
                                           &tree[(r_node_idx * 2 + 1) *
 | 
			
		||||
                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
 | 
			
		||||
                                           r_node_idx,
 | 
			
		||||
                                           &tree[r_node_idx *
 | 
			
		||||
                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]);
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Calculate a path from a leaf node of the Merkle tree to the root of the tree,
 | 
			
		||||
 * and return the full path. This function implements RFC8554 section 5.4.1, as
 | 
			
		||||
 * the Merkle path is the main component of an LMS signature.
 | 
			
		||||
 *
 | 
			
		||||
 *  ctx                 The LMS private context, containing a parameter
 | 
			
		||||
 *                      set and private key material consisting of both
 | 
			
		||||
 *                      public and private OTS.
 | 
			
		||||
 *
 | 
			
		||||
 *  leaf_node_id        Which leaf node to calculate the path from.
 | 
			
		||||
 *
 | 
			
		||||
 *  path                The output path, which is H hash outputs.
 | 
			
		||||
 */
 | 
			
		||||
static int get_merkle_path(mbedtls_lms_private_t *ctx,
 | 
			
		||||
                           unsigned int leaf_node_id,
 | 
			
		||||
                           unsigned char *path)
 | 
			
		||||
{
 | 
			
		||||
    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
 | 
			
		||||
    unsigned int curr_node_id = leaf_node_id;
 | 
			
		||||
    unsigned int adjacent_node_id;
 | 
			
		||||
    unsigned char *tree = NULL;
 | 
			
		||||
    unsigned int height;
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type),
 | 
			
		||||
                          node_bytes);
 | 
			
		||||
    if (tree == NULL) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = calculate_merkle_tree(ctx, tree);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
 | 
			
		||||
         height++) {
 | 
			
		||||
        adjacent_node_id = curr_node_id ^ 1;
 | 
			
		||||
 | 
			
		||||
        memcpy(&path[height * node_bytes],
 | 
			
		||||
               &tree[adjacent_node_id * node_bytes], node_bytes);
 | 
			
		||||
 | 
			
		||||
        curr_node_id >>= 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = 0;
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    mbedtls_zeroize_and_free(tree, node_bytes *
 | 
			
		||||
                             (size_t) MERKLE_TREE_NODE_AM(ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    memset(ctx, 0, sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx)
 | 
			
		||||
{
 | 
			
		||||
    if (ctx == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned int idx;
 | 
			
		||||
 | 
			
		||||
    if (ctx->have_private_key) {
 | 
			
		||||
        if (ctx->ots_private_keys != NULL) {
 | 
			
		||||
            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
 | 
			
		||||
                mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ctx->ots_public_keys != NULL) {
 | 
			
		||||
            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
 | 
			
		||||
                mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mbedtls_free(ctx->ots_private_keys);
 | 
			
		||||
        mbedtls_free(ctx->ots_public_keys);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,
 | 
			
		||||
                                     mbedtls_lms_algorithm_type_t type,
 | 
			
		||||
                                     mbedtls_lmots_algorithm_type_t otstype,
 | 
			
		||||
                                     int (*f_rng)(void *, unsigned char *, size_t),
 | 
			
		||||
                                     void *p_rng, const unsigned char *seed,
 | 
			
		||||
                                     size_t seed_size)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int idx = 0;
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    if (type != MBEDTLS_LMS_SHA256_M32_H10) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ctx->have_private_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx->params.type = type;
 | 
			
		||||
    ctx->params.otstype = otstype;
 | 
			
		||||
    ctx->have_private_key = 1;
 | 
			
		||||
 | 
			
		||||
    ret = f_rng(p_rng,
 | 
			
		||||
                ctx->params.I_key_identifier,
 | 
			
		||||
                MBEDTLS_LMOTS_I_KEY_ID_LEN);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Requires a cast to size_t to avoid an implicit cast warning on certain
 | 
			
		||||
     * platforms (particularly Windows) */
 | 
			
		||||
    ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
 | 
			
		||||
                                           sizeof(*ctx->ots_private_keys));
 | 
			
		||||
    if (ctx->ots_private_keys == NULL) {
 | 
			
		||||
        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Requires a cast to size_t to avoid an implicit cast warning on certain
 | 
			
		||||
     * platforms (particularly Windows) */
 | 
			
		||||
    ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
 | 
			
		||||
                                          sizeof(*ctx->ots_public_keys));
 | 
			
		||||
    if (ctx->ots_public_keys == NULL) {
 | 
			
		||||
        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
 | 
			
		||||
        mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]);
 | 
			
		||||
        mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
 | 
			
		||||
        ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx],
 | 
			
		||||
                                                 otstype,
 | 
			
		||||
                                                 ctx->params.I_key_identifier,
 | 
			
		||||
                                                 idx, seed, seed_size);
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx],
 | 
			
		||||
                                                 &ctx->ots_private_keys[idx]);
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx->q_next_usable_key = 0;
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        mbedtls_lms_private_free(ctx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
 | 
			
		||||
                                     const mbedtls_lms_private_t *priv_ctx)
 | 
			
		||||
{
 | 
			
		||||
    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
    unsigned char *tree = NULL;
 | 
			
		||||
 | 
			
		||||
    if (!priv_ctx->have_private_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (priv_ctx->params.type
 | 
			
		||||
        != MBEDTLS_LMS_SHA256_M32_H10) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (priv_ctx->params.otstype
 | 
			
		||||
        != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type),
 | 
			
		||||
                          node_bytes);
 | 
			
		||||
    if (tree == NULL) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memcpy(&ctx->params, &priv_ctx->params,
 | 
			
		||||
           sizeof(mbedtls_lmots_parameters_t));
 | 
			
		||||
 | 
			
		||||
    ret = calculate_merkle_tree(priv_ctx, tree);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Root node is always at position 1, due to 1-based indexing */
 | 
			
		||||
    memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes);
 | 
			
		||||
 | 
			
		||||
    ctx->have_public_key = 1;
 | 
			
		||||
 | 
			
		||||
    ret = 0;
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    mbedtls_zeroize_and_free(tree, node_bytes *
 | 
			
		||||
                             (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int mbedtls_lms_sign(mbedtls_lms_private_t *ctx,
 | 
			
		||||
                     int (*f_rng)(void *, unsigned char *, size_t),
 | 
			
		||||
                     void *p_rng, const unsigned char *msg,
 | 
			
		||||
                     unsigned int msg_size, unsigned char *sig, size_t sig_size,
 | 
			
		||||
                     size_t *sig_len)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t q_leaf_identifier;
 | 
			
		||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
			
		||||
 | 
			
		||||
    if (!ctx->have_private_key) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ctx->params.otstype
 | 
			
		||||
        != MBEDTLS_LMOTS_SHA256_N32_W8) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    q_leaf_identifier = ctx->q_next_usable_key;
 | 
			
		||||
    /* This new value must _always_ be written back to the disk before the
 | 
			
		||||
     * signature is returned.
 | 
			
		||||
     */
 | 
			
		||||
    ctx->q_next_usable_key += 1;
 | 
			
		||||
 | 
			
		||||
    if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)
 | 
			
		||||
        < SIG_OTS_SIG_OFFSET) {
 | 
			
		||||
        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier],
 | 
			
		||||
                             f_rng,
 | 
			
		||||
                             p_rng,
 | 
			
		||||
                             msg,
 | 
			
		||||
                             msg_size,
 | 
			
		||||
                             sig + SIG_OTS_SIG_OFFSET,
 | 
			
		||||
                             MBEDTLS_LMS_SIG_LEN(ctx->params.type,
 | 
			
		||||
                                                 ctx->params.otstype) - SIG_OTS_SIG_OFFSET,
 | 
			
		||||
                             NULL);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype));
 | 
			
		||||
    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET);
 | 
			
		||||
 | 
			
		||||
    ret = get_merkle_path(ctx,
 | 
			
		||||
                          MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
 | 
			
		||||
                          sig + SIG_PATH_OFFSET(ctx->params.otstype));
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sig_len != NULL) {
 | 
			
		||||
        *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
 | 
			
		||||
#endif /* defined(MBEDTLS_LMS_C) */
 | 
			
		||||
							
								
								
									
										23
									
								
								thirdparty/zlib/gzclose.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								thirdparty/zlib/gzclose.c
									
									
									
									
										vendored
									
									
								
							@@ -1,23 +0,0 @@
 | 
			
		||||
/* gzclose.c -- zlib gzclose() function
 | 
			
		||||
 * Copyright (C) 2004, 2010 Mark Adler
 | 
			
		||||
 * For conditions of distribution and use, see copyright notice in zlib.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gzguts.h"
 | 
			
		||||
 | 
			
		||||
/* gzclose() is in a separate file so that it is linked in only if it is used.
 | 
			
		||||
   That way the other gzclose functions can be used instead to avoid linking in
 | 
			
		||||
   unneeded compression or decompression routines. */
 | 
			
		||||
int ZEXPORT gzclose(gzFile file) {
 | 
			
		||||
#ifndef NO_GZCOMPRESS
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
 | 
			
		||||
#else
 | 
			
		||||
    return gzclose_r(file);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										582
									
								
								thirdparty/zlib/gzlib.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										582
									
								
								thirdparty/zlib/gzlib.c
									
									
									
									
										vendored
									
									
								
							@@ -1,582 +0,0 @@
 | 
			
		||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
 | 
			
		||||
 * Copyright (C) 2004-2024 Mark Adler
 | 
			
		||||
 * For conditions of distribution and use, see copyright notice in zlib.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gzguts.h"
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) && !defined(__BORLANDC__)
 | 
			
		||||
#  define LSEEK _lseeki64
 | 
			
		||||
#else
 | 
			
		||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
 | 
			
		||||
#  define LSEEK lseek64
 | 
			
		||||
#else
 | 
			
		||||
#  define LSEEK lseek
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined UNDER_CE
 | 
			
		||||
 | 
			
		||||
/* Map the Windows error number in ERROR to a locale-dependent error message
 | 
			
		||||
   string and return a pointer to it.  Typically, the values for ERROR come
 | 
			
		||||
   from GetLastError.
 | 
			
		||||
 | 
			
		||||
   The string pointed to shall not be modified by the application, but may be
 | 
			
		||||
   overwritten by a subsequent call to gz_strwinerror
 | 
			
		||||
 | 
			
		||||
   The gz_strwinerror function does not change the current setting of
 | 
			
		||||
   GetLastError. */
 | 
			
		||||
char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
 | 
			
		||||
    static char buf[1024];
 | 
			
		||||
 | 
			
		||||
    wchar_t *msgbuf;
 | 
			
		||||
    DWORD lasterr = GetLastError();
 | 
			
		||||
    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
 | 
			
		||||
        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
 | 
			
		||||
        NULL,
 | 
			
		||||
        error,
 | 
			
		||||
        0, /* Default language */
 | 
			
		||||
        (LPVOID)&msgbuf,
 | 
			
		||||
        0,
 | 
			
		||||
        NULL);
 | 
			
		||||
    if (chars != 0) {
 | 
			
		||||
        /* If there is an \r\n appended, zap it.  */
 | 
			
		||||
        if (chars >= 2
 | 
			
		||||
            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
 | 
			
		||||
            chars -= 2;
 | 
			
		||||
            msgbuf[chars] = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (chars > sizeof (buf) - 1) {
 | 
			
		||||
            chars = sizeof (buf) - 1;
 | 
			
		||||
            msgbuf[chars] = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        wcstombs(buf, msgbuf, chars + 1);
 | 
			
		||||
        LocalFree(msgbuf);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        sprintf(buf, "unknown win32 error (%ld)", error);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SetLastError(lasterr);
 | 
			
		||||
    return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* UNDER_CE */
 | 
			
		||||
 | 
			
		||||
/* Reset gzip file state */
 | 
			
		||||
local void gz_reset(gz_statep state) {
 | 
			
		||||
    state->x.have = 0;              /* no output data available */
 | 
			
		||||
    if (state->mode == GZ_READ) {   /* for reading ... */
 | 
			
		||||
        state->eof = 0;             /* not at end of file */
 | 
			
		||||
        state->past = 0;            /* have not read past end yet */
 | 
			
		||||
        state->how = LOOK;          /* look for gzip header */
 | 
			
		||||
    }
 | 
			
		||||
    else                            /* for writing ... */
 | 
			
		||||
        state->reset = 0;           /* no deflateReset pending */
 | 
			
		||||
    state->seek = 0;                /* no seek request pending */
 | 
			
		||||
    gz_error(state, Z_OK, NULL);    /* clear error */
 | 
			
		||||
    state->x.pos = 0;               /* no uncompressed data yet */
 | 
			
		||||
    state->strm.avail_in = 0;       /* no input data yet */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Open a gzip file either by name or file descriptor. */
 | 
			
		||||
local gzFile gz_open(const void *path, int fd, const char *mode) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
    z_size_t len;
 | 
			
		||||
    int oflag;
 | 
			
		||||
#ifdef O_CLOEXEC
 | 
			
		||||
    int cloexec = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef O_EXCL
 | 
			
		||||
    int exclusive = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* check input */
 | 
			
		||||
    if (path == NULL)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    /* allocate gzFile structure to return */
 | 
			
		||||
    state = (gz_statep)malloc(sizeof(gz_state));
 | 
			
		||||
    if (state == NULL)
 | 
			
		||||
        return NULL;
 | 
			
		||||
    state->size = 0;            /* no buffers allocated yet */
 | 
			
		||||
    state->want = GZBUFSIZE;    /* requested buffer size */
 | 
			
		||||
    state->msg = NULL;          /* no error message yet */
 | 
			
		||||
 | 
			
		||||
    /* interpret mode */
 | 
			
		||||
    state->mode = GZ_NONE;
 | 
			
		||||
    state->level = Z_DEFAULT_COMPRESSION;
 | 
			
		||||
    state->strategy = Z_DEFAULT_STRATEGY;
 | 
			
		||||
    state->direct = 0;
 | 
			
		||||
    while (*mode) {
 | 
			
		||||
        if (*mode >= '0' && *mode <= '9')
 | 
			
		||||
            state->level = *mode - '0';
 | 
			
		||||
        else
 | 
			
		||||
            switch (*mode) {
 | 
			
		||||
            case 'r':
 | 
			
		||||
                state->mode = GZ_READ;
 | 
			
		||||
                break;
 | 
			
		||||
#ifndef NO_GZCOMPRESS
 | 
			
		||||
            case 'w':
 | 
			
		||||
                state->mode = GZ_WRITE;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'a':
 | 
			
		||||
                state->mode = GZ_APPEND;
 | 
			
		||||
                break;
 | 
			
		||||
#endif
 | 
			
		||||
            case '+':       /* can't read and write at the same time */
 | 
			
		||||
                free(state);
 | 
			
		||||
                return NULL;
 | 
			
		||||
            case 'b':       /* ignore -- will request binary anyway */
 | 
			
		||||
                break;
 | 
			
		||||
#ifdef O_CLOEXEC
 | 
			
		||||
            case 'e':
 | 
			
		||||
                cloexec = 1;
 | 
			
		||||
                break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef O_EXCL
 | 
			
		||||
            case 'x':
 | 
			
		||||
                exclusive = 1;
 | 
			
		||||
                break;
 | 
			
		||||
#endif
 | 
			
		||||
            case 'f':
 | 
			
		||||
                state->strategy = Z_FILTERED;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'h':
 | 
			
		||||
                state->strategy = Z_HUFFMAN_ONLY;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'R':
 | 
			
		||||
                state->strategy = Z_RLE;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'F':
 | 
			
		||||
                state->strategy = Z_FIXED;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'T':
 | 
			
		||||
                state->direct = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            default:        /* could consider as an error, but just ignore */
 | 
			
		||||
                ;
 | 
			
		||||
            }
 | 
			
		||||
        mode++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* must provide an "r", "w", or "a" */
 | 
			
		||||
    if (state->mode == GZ_NONE) {
 | 
			
		||||
        free(state);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* can't force transparent read */
 | 
			
		||||
    if (state->mode == GZ_READ) {
 | 
			
		||||
        if (state->direct) {
 | 
			
		||||
            free(state);
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
        state->direct = 1;      /* for empty file */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* save the path name for error messages */
 | 
			
		||||
#ifdef WIDECHAR
 | 
			
		||||
    if (fd == -2) {
 | 
			
		||||
        len = wcstombs(NULL, path, 0);
 | 
			
		||||
        if (len == (z_size_t)-1)
 | 
			
		||||
            len = 0;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
#endif
 | 
			
		||||
        len = strlen((const char *)path);
 | 
			
		||||
    state->path = (char *)malloc(len + 1);
 | 
			
		||||
    if (state->path == NULL) {
 | 
			
		||||
        free(state);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
#ifdef WIDECHAR
 | 
			
		||||
    if (fd == -2)
 | 
			
		||||
        if (len)
 | 
			
		||||
            wcstombs(state->path, path, len + 1);
 | 
			
		||||
        else
 | 
			
		||||
            *(state->path) = 0;
 | 
			
		||||
    else
 | 
			
		||||
#endif
 | 
			
		||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 | 
			
		||||
        (void)snprintf(state->path, len + 1, "%s", (const char *)path);
 | 
			
		||||
#else
 | 
			
		||||
        strcpy(state->path, path);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* compute the flags for open() */
 | 
			
		||||
    oflag =
 | 
			
		||||
#ifdef O_LARGEFILE
 | 
			
		||||
        O_LARGEFILE |
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef O_BINARY
 | 
			
		||||
        O_BINARY |
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef O_CLOEXEC
 | 
			
		||||
        (cloexec ? O_CLOEXEC : 0) |
 | 
			
		||||
#endif
 | 
			
		||||
        (state->mode == GZ_READ ?
 | 
			
		||||
         O_RDONLY :
 | 
			
		||||
         (O_WRONLY | O_CREAT |
 | 
			
		||||
#ifdef O_EXCL
 | 
			
		||||
          (exclusive ? O_EXCL : 0) |
 | 
			
		||||
#endif
 | 
			
		||||
          (state->mode == GZ_WRITE ?
 | 
			
		||||
           O_TRUNC :
 | 
			
		||||
           O_APPEND)));
 | 
			
		||||
 | 
			
		||||
    /* open the file with the appropriate flags (or just use fd) */
 | 
			
		||||
    state->fd = fd > -1 ? fd : (
 | 
			
		||||
#ifdef WIDECHAR
 | 
			
		||||
        fd == -2 ? _wopen(path, oflag, 0666) :
 | 
			
		||||
#endif
 | 
			
		||||
        open((const char *)path, oflag, 0666));
 | 
			
		||||
    if (state->fd == -1) {
 | 
			
		||||
        free(state->path);
 | 
			
		||||
        free(state);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (state->mode == GZ_APPEND) {
 | 
			
		||||
        LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */
 | 
			
		||||
        state->mode = GZ_WRITE;         /* simplify later checks */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* save the current position for rewinding (only if reading) */
 | 
			
		||||
    if (state->mode == GZ_READ) {
 | 
			
		||||
        state->start = LSEEK(state->fd, 0, SEEK_CUR);
 | 
			
		||||
        if (state->start == -1) state->start = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* initialize stream */
 | 
			
		||||
    gz_reset(state);
 | 
			
		||||
 | 
			
		||||
    /* return stream */
 | 
			
		||||
    return (gzFile)state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
gzFile ZEXPORT gzopen(const char *path, const char *mode) {
 | 
			
		||||
    return gz_open(path, -1, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
 | 
			
		||||
    return gz_open(path, -1, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
gzFile ZEXPORT gzdopen(int fd, const char *mode) {
 | 
			
		||||
    char *path;         /* identifier for error messages */
 | 
			
		||||
    gzFile gz;
 | 
			
		||||
 | 
			
		||||
    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
 | 
			
		||||
        return NULL;
 | 
			
		||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 | 
			
		||||
    (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
 | 
			
		||||
#else
 | 
			
		||||
    sprintf(path, "<fd:%d>", fd);   /* for debugging */
 | 
			
		||||
#endif
 | 
			
		||||
    gz = gz_open(path, fd, mode);
 | 
			
		||||
    free(path);
 | 
			
		||||
    return gz;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
#ifdef WIDECHAR
 | 
			
		||||
gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
 | 
			
		||||
    return gz_open(path, -2, mode);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzbuffer(gzFile file, unsigned size) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure and check integrity */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* make sure we haven't already allocated memory */
 | 
			
		||||
    if (state->size != 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* check and set requested size */
 | 
			
		||||
    if ((size << 1) < size)
 | 
			
		||||
        return -1;              /* need to be able to double it */
 | 
			
		||||
    if (size < 8)
 | 
			
		||||
        size = 8;               /* needed to behave well with flushing */
 | 
			
		||||
    state->want = size;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzrewind(gzFile file) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're reading and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_READ ||
 | 
			
		||||
            (state->err != Z_OK && state->err != Z_BUF_ERROR))
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* back up and start over */
 | 
			
		||||
    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
 | 
			
		||||
        return -1;
 | 
			
		||||
    gz_reset(state);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
 | 
			
		||||
    unsigned n;
 | 
			
		||||
    z_off64_t ret;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure and check integrity */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* check that there's no error */
 | 
			
		||||
    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* can only seek from start or relative to current position */
 | 
			
		||||
    if (whence != SEEK_SET && whence != SEEK_CUR)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* normalize offset to a SEEK_CUR specification */
 | 
			
		||||
    if (whence == SEEK_SET)
 | 
			
		||||
        offset -= state->x.pos;
 | 
			
		||||
    else if (state->seek)
 | 
			
		||||
        offset += state->skip;
 | 
			
		||||
    state->seek = 0;
 | 
			
		||||
 | 
			
		||||
    /* if within raw area while reading, just go there */
 | 
			
		||||
    if (state->mode == GZ_READ && state->how == COPY &&
 | 
			
		||||
            state->x.pos + offset >= 0) {
 | 
			
		||||
        ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
 | 
			
		||||
        if (ret == -1)
 | 
			
		||||
            return -1;
 | 
			
		||||
        state->x.have = 0;
 | 
			
		||||
        state->eof = 0;
 | 
			
		||||
        state->past = 0;
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        gz_error(state, Z_OK, NULL);
 | 
			
		||||
        state->strm.avail_in = 0;
 | 
			
		||||
        state->x.pos += offset;
 | 
			
		||||
        return state->x.pos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* calculate skip amount, rewinding if needed for back seek when reading */
 | 
			
		||||
    if (offset < 0) {
 | 
			
		||||
        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
 | 
			
		||||
            return -1;
 | 
			
		||||
        offset += state->x.pos;
 | 
			
		||||
        if (offset < 0)                     /* before start of file! */
 | 
			
		||||
            return -1;
 | 
			
		||||
        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* if reading, skip what's in output buffer (one less gzgetc() check) */
 | 
			
		||||
    if (state->mode == GZ_READ) {
 | 
			
		||||
        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
 | 
			
		||||
            (unsigned)offset : state->x.have;
 | 
			
		||||
        state->x.have -= n;
 | 
			
		||||
        state->x.next += n;
 | 
			
		||||
        state->x.pos += n;
 | 
			
		||||
        offset -= n;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* request skip (if not zero) */
 | 
			
		||||
    if (offset) {
 | 
			
		||||
        state->seek = 1;
 | 
			
		||||
        state->skip = offset;
 | 
			
		||||
    }
 | 
			
		||||
    return state->x.pos + offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
 | 
			
		||||
    z_off64_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = gzseek64(file, (z_off64_t)offset, whence);
 | 
			
		||||
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_off64_t ZEXPORT gztell64(gzFile file) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure and check integrity */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* return position */
 | 
			
		||||
    return state->x.pos + (state->seek ? state->skip : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_off_t ZEXPORT gztell(gzFile file) {
 | 
			
		||||
    z_off64_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = gztell64(file);
 | 
			
		||||
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_off64_t ZEXPORT gzoffset64(gzFile file) {
 | 
			
		||||
    z_off64_t offset;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure and check integrity */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* compute and return effective offset in file */
 | 
			
		||||
    offset = LSEEK(state->fd, 0, SEEK_CUR);
 | 
			
		||||
    if (offset == -1)
 | 
			
		||||
        return -1;
 | 
			
		||||
    if (state->mode == GZ_READ)             /* reading */
 | 
			
		||||
        offset -= state->strm.avail_in;     /* don't count buffered input */
 | 
			
		||||
    return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_off_t ZEXPORT gzoffset(gzFile file) {
 | 
			
		||||
    z_off64_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = gzoffset64(file);
 | 
			
		||||
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzeof(gzFile file) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure and check integrity */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return 0;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* return end-of-file state */
 | 
			
		||||
    return state->mode == GZ_READ ? state->past : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
const char * ZEXPORT gzerror(gzFile file, int *errnum) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure and check integrity */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return NULL;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    /* return error information */
 | 
			
		||||
    if (errnum != NULL)
 | 
			
		||||
        *errnum = state->err;
 | 
			
		||||
    return state->err == Z_MEM_ERROR ? "out of memory" :
 | 
			
		||||
                                       (state->msg == NULL ? "" : state->msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
void ZEXPORT gzclearerr(gzFile file) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure and check integrity */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* clear error and end-of-file */
 | 
			
		||||
    if (state->mode == GZ_READ) {
 | 
			
		||||
        state->eof = 0;
 | 
			
		||||
        state->past = 0;
 | 
			
		||||
    }
 | 
			
		||||
    gz_error(state, Z_OK, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Create an error message in allocated memory and set state->err and
 | 
			
		||||
   state->msg accordingly.  Free any previous error message already there.  Do
 | 
			
		||||
   not try to free or allocate space if the error is Z_MEM_ERROR (out of
 | 
			
		||||
   memory).  Simply save the error message as a static string.  If there is an
 | 
			
		||||
   allocation failure constructing the error message, then convert the error to
 | 
			
		||||
   out of memory. */
 | 
			
		||||
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
 | 
			
		||||
    /* free previously allocated message and clear */
 | 
			
		||||
    if (state->msg != NULL) {
 | 
			
		||||
        if (state->err != Z_MEM_ERROR)
 | 
			
		||||
            free(state->msg);
 | 
			
		||||
        state->msg = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
 | 
			
		||||
    if (err != Z_OK && err != Z_BUF_ERROR)
 | 
			
		||||
        state->x.have = 0;
 | 
			
		||||
 | 
			
		||||
    /* set error code, and if no message, then done */
 | 
			
		||||
    state->err = err;
 | 
			
		||||
    if (msg == NULL)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* for an out of memory error, return literal string when requested */
 | 
			
		||||
    if (err == Z_MEM_ERROR)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* construct error message with path */
 | 
			
		||||
    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
 | 
			
		||||
            NULL) {
 | 
			
		||||
        state->err = Z_MEM_ERROR;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
 | 
			
		||||
    (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
 | 
			
		||||
                   "%s%s%s", state->path, ": ", msg);
 | 
			
		||||
#else
 | 
			
		||||
    strcpy(state->msg, state->path);
 | 
			
		||||
    strcat(state->msg, ": ");
 | 
			
		||||
    strcat(state->msg, msg);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* portably return maximum value for an int (when limits.h presumed not
 | 
			
		||||
   available) -- we need to do this to cover cases where 2's complement not
 | 
			
		||||
   used, since C standard permits 1's complement and sign-bit representations,
 | 
			
		||||
   otherwise we could just use ((unsigned)-1) >> 1 */
 | 
			
		||||
unsigned ZLIB_INTERNAL gz_intmax(void) {
 | 
			
		||||
#ifdef INT_MAX
 | 
			
		||||
    return INT_MAX;
 | 
			
		||||
#else
 | 
			
		||||
    unsigned p = 1, q;
 | 
			
		||||
    do {
 | 
			
		||||
        q = p;
 | 
			
		||||
        p <<= 1;
 | 
			
		||||
        p++;
 | 
			
		||||
    } while (p > q);
 | 
			
		||||
    return q >> 1;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										602
									
								
								thirdparty/zlib/gzread.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										602
									
								
								thirdparty/zlib/gzread.c
									
									
									
									
										vendored
									
									
								
							@@ -1,602 +0,0 @@
 | 
			
		||||
/* gzread.c -- zlib functions for reading gzip files
 | 
			
		||||
 * Copyright (C) 2004-2017 Mark Adler
 | 
			
		||||
 * For conditions of distribution and use, see copyright notice in zlib.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gzguts.h"
 | 
			
		||||
 | 
			
		||||
/* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
 | 
			
		||||
   state->fd, and update state->eof, state->err, and state->msg as appropriate.
 | 
			
		||||
   This function needs to loop on read(), since read() is not guaranteed to
 | 
			
		||||
   read the number of bytes requested, depending on the type of descriptor. */
 | 
			
		||||
local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
 | 
			
		||||
                  unsigned *have) {
 | 
			
		||||
    int ret;
 | 
			
		||||
    unsigned get, max = ((unsigned)-1 >> 2) + 1;
 | 
			
		||||
 | 
			
		||||
    *have = 0;
 | 
			
		||||
    do {
 | 
			
		||||
        get = len - *have;
 | 
			
		||||
        if (get > max)
 | 
			
		||||
            get = max;
 | 
			
		||||
        ret = read(state->fd, buf + *have, get);
 | 
			
		||||
        if (ret <= 0)
 | 
			
		||||
            break;
 | 
			
		||||
        *have += (unsigned)ret;
 | 
			
		||||
    } while (*have < len);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        gz_error(state, Z_ERRNO, zstrerror());
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    if (ret == 0)
 | 
			
		||||
        state->eof = 1;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
 | 
			
		||||
   error, 0 otherwise.  Note that the eof flag is set when the end of the input
 | 
			
		||||
   file is reached, even though there may be unused data in the buffer.  Once
 | 
			
		||||
   that data has been used, no more attempts will be made to read the file.
 | 
			
		||||
   If strm->avail_in != 0, then the current data is moved to the beginning of
 | 
			
		||||
   the input buffer, and then the remainder of the buffer is loaded with the
 | 
			
		||||
   available data from the input file. */
 | 
			
		||||
local int gz_avail(gz_statep state) {
 | 
			
		||||
    unsigned got;
 | 
			
		||||
    z_streamp strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
 | 
			
		||||
        return -1;
 | 
			
		||||
    if (state->eof == 0) {
 | 
			
		||||
        if (strm->avail_in) {       /* copy what's there to the start */
 | 
			
		||||
            unsigned char *p = state->in;
 | 
			
		||||
            unsigned const char *q = strm->next_in;
 | 
			
		||||
            unsigned n = strm->avail_in;
 | 
			
		||||
            do {
 | 
			
		||||
                *p++ = *q++;
 | 
			
		||||
            } while (--n);
 | 
			
		||||
        }
 | 
			
		||||
        if (gz_load(state, state->in + strm->avail_in,
 | 
			
		||||
                    state->size - strm->avail_in, &got) == -1)
 | 
			
		||||
            return -1;
 | 
			
		||||
        strm->avail_in += got;
 | 
			
		||||
        strm->next_in = state->in;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.
 | 
			
		||||
   If this is the first time in, allocate required memory.  state->how will be
 | 
			
		||||
   left unchanged if there is no more input data available, will be set to COPY
 | 
			
		||||
   if there is no gzip header and direct copying will be performed, or it will
 | 
			
		||||
   be set to GZIP for decompression.  If direct copying, then leftover input
 | 
			
		||||
   data from the input buffer will be copied to the output buffer.  In that
 | 
			
		||||
   case, all further file reads will be directly to either the output buffer or
 | 
			
		||||
   a user buffer.  If decompressing, the inflate state will be initialized.
 | 
			
		||||
   gz_look() will return 0 on success or -1 on failure. */
 | 
			
		||||
local int gz_look(gz_statep state) {
 | 
			
		||||
    z_streamp strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* allocate read buffers and inflate memory */
 | 
			
		||||
    if (state->size == 0) {
 | 
			
		||||
        /* allocate buffers */
 | 
			
		||||
        state->in = (unsigned char *)malloc(state->want);
 | 
			
		||||
        state->out = (unsigned char *)malloc(state->want << 1);
 | 
			
		||||
        if (state->in == NULL || state->out == NULL) {
 | 
			
		||||
            free(state->out);
 | 
			
		||||
            free(state->in);
 | 
			
		||||
            gz_error(state, Z_MEM_ERROR, "out of memory");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        state->size = state->want;
 | 
			
		||||
 | 
			
		||||
        /* allocate inflate memory */
 | 
			
		||||
        state->strm.zalloc = Z_NULL;
 | 
			
		||||
        state->strm.zfree = Z_NULL;
 | 
			
		||||
        state->strm.opaque = Z_NULL;
 | 
			
		||||
        state->strm.avail_in = 0;
 | 
			
		||||
        state->strm.next_in = Z_NULL;
 | 
			
		||||
        if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) {    /* gunzip */
 | 
			
		||||
            free(state->out);
 | 
			
		||||
            free(state->in);
 | 
			
		||||
            state->size = 0;
 | 
			
		||||
            gz_error(state, Z_MEM_ERROR, "out of memory");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* get at least the magic bytes in the input buffer */
 | 
			
		||||
    if (strm->avail_in < 2) {
 | 
			
		||||
        if (gz_avail(state) == -1)
 | 
			
		||||
            return -1;
 | 
			
		||||
        if (strm->avail_in == 0)
 | 
			
		||||
            return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
 | 
			
		||||
       a logical dilemma here when considering the case of a partially written
 | 
			
		||||
       gzip file, to wit, if a single 31 byte is written, then we cannot tell
 | 
			
		||||
       whether this is a single-byte file, or just a partially written gzip
 | 
			
		||||
       file -- for here we assume that if a gzip file is being written, then
 | 
			
		||||
       the header will be written in a single operation, so that reading a
 | 
			
		||||
       single byte is sufficient indication that it is not a gzip file) */
 | 
			
		||||
    if (strm->avail_in > 1 &&
 | 
			
		||||
            strm->next_in[0] == 31 && strm->next_in[1] == 139) {
 | 
			
		||||
        inflateReset(strm);
 | 
			
		||||
        state->how = GZIP;
 | 
			
		||||
        state->direct = 0;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* no gzip header -- if we were decoding gzip before, then this is trailing
 | 
			
		||||
       garbage.  Ignore the trailing garbage and finish. */
 | 
			
		||||
    if (state->direct == 0) {
 | 
			
		||||
        strm->avail_in = 0;
 | 
			
		||||
        state->eof = 1;
 | 
			
		||||
        state->x.have = 0;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* doing raw i/o, copy any leftover input to output -- this assumes that
 | 
			
		||||
       the output buffer is larger than the input buffer, which also assures
 | 
			
		||||
       space for gzungetc() */
 | 
			
		||||
    state->x.next = state->out;
 | 
			
		||||
    memcpy(state->x.next, strm->next_in, strm->avail_in);
 | 
			
		||||
    state->x.have = strm->avail_in;
 | 
			
		||||
    strm->avail_in = 0;
 | 
			
		||||
    state->how = COPY;
 | 
			
		||||
    state->direct = 1;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Decompress from input to the provided next_out and avail_out in the state.
 | 
			
		||||
   On return, state->x.have and state->x.next point to the just decompressed
 | 
			
		||||
   data.  If the gzip stream completes, state->how is reset to LOOK to look for
 | 
			
		||||
   the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
 | 
			
		||||
   on success, -1 on failure. */
 | 
			
		||||
local int gz_decomp(gz_statep state) {
 | 
			
		||||
    int ret = Z_OK;
 | 
			
		||||
    unsigned had;
 | 
			
		||||
    z_streamp strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* fill output buffer up to end of deflate stream */
 | 
			
		||||
    had = strm->avail_out;
 | 
			
		||||
    do {
 | 
			
		||||
        /* get more input for inflate() */
 | 
			
		||||
        if (strm->avail_in == 0 && gz_avail(state) == -1)
 | 
			
		||||
            return -1;
 | 
			
		||||
        if (strm->avail_in == 0) {
 | 
			
		||||
            gz_error(state, Z_BUF_ERROR, "unexpected end of file");
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* decompress and handle errors */
 | 
			
		||||
        ret = inflate(strm, Z_NO_FLUSH);
 | 
			
		||||
        if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
 | 
			
		||||
            gz_error(state, Z_STREAM_ERROR,
 | 
			
		||||
                     "internal error: inflate stream corrupt");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (ret == Z_MEM_ERROR) {
 | 
			
		||||
            gz_error(state, Z_MEM_ERROR, "out of memory");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
 | 
			
		||||
            gz_error(state, Z_DATA_ERROR,
 | 
			
		||||
                     strm->msg == NULL ? "compressed data error" : strm->msg);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    } while (strm->avail_out && ret != Z_STREAM_END);
 | 
			
		||||
 | 
			
		||||
    /* update available output */
 | 
			
		||||
    state->x.have = had - strm->avail_out;
 | 
			
		||||
    state->x.next = strm->next_out - state->x.have;
 | 
			
		||||
 | 
			
		||||
    /* if the gzip stream completed successfully, look for another */
 | 
			
		||||
    if (ret == Z_STREAM_END)
 | 
			
		||||
        state->how = LOOK;
 | 
			
		||||
 | 
			
		||||
    /* good decompression */
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
 | 
			
		||||
   Data is either copied from the input file or decompressed from the input
 | 
			
		||||
   file depending on state->how.  If state->how is LOOK, then a gzip header is
 | 
			
		||||
   looked for to determine whether to copy or decompress.  Returns -1 on error,
 | 
			
		||||
   otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
 | 
			
		||||
   end of the input file has been reached and all data has been processed.  */
 | 
			
		||||
local int gz_fetch(gz_statep state) {
 | 
			
		||||
    z_streamp strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        switch(state->how) {
 | 
			
		||||
        case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */
 | 
			
		||||
            if (gz_look(state) == -1)
 | 
			
		||||
                return -1;
 | 
			
		||||
            if (state->how == LOOK)
 | 
			
		||||
                return 0;
 | 
			
		||||
            break;
 | 
			
		||||
        case COPY:      /* -> COPY */
 | 
			
		||||
            if (gz_load(state, state->out, state->size << 1, &(state->x.have))
 | 
			
		||||
                    == -1)
 | 
			
		||||
                return -1;
 | 
			
		||||
            state->x.next = state->out;
 | 
			
		||||
            return 0;
 | 
			
		||||
        case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */
 | 
			
		||||
            strm->avail_out = state->size << 1;
 | 
			
		||||
            strm->next_out = state->out;
 | 
			
		||||
            if (gz_decomp(state) == -1)
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
    } while (state->x.have == 0 && (!state->eof || strm->avail_in));
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
 | 
			
		||||
local int gz_skip(gz_statep state, z_off64_t len) {
 | 
			
		||||
    unsigned n;
 | 
			
		||||
 | 
			
		||||
    /* skip over len bytes or reach end-of-file, whichever comes first */
 | 
			
		||||
    while (len)
 | 
			
		||||
        /* skip over whatever is in output buffer */
 | 
			
		||||
        if (state->x.have) {
 | 
			
		||||
            n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
 | 
			
		||||
                (unsigned)len : state->x.have;
 | 
			
		||||
            state->x.have -= n;
 | 
			
		||||
            state->x.next += n;
 | 
			
		||||
            state->x.pos += n;
 | 
			
		||||
            len -= n;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* output buffer empty -- return if we're at the end of the input */
 | 
			
		||||
        else if (state->eof && state->strm.avail_in == 0)
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        /* need more data to skip -- load up output buffer */
 | 
			
		||||
        else {
 | 
			
		||||
            /* get more output, looking for header if required */
 | 
			
		||||
            if (gz_fetch(state) == -1)
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Read len bytes into buf from file, or less than len up to the end of the
 | 
			
		||||
   input.  Return the number of bytes read.  If zero is returned, either the
 | 
			
		||||
   end of file was reached, or there was an error.  state->err must be
 | 
			
		||||
   consulted in that case to determine which. */
 | 
			
		||||
local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
 | 
			
		||||
    z_size_t got;
 | 
			
		||||
    unsigned n;
 | 
			
		||||
 | 
			
		||||
    /* if len is zero, avoid unnecessary operations */
 | 
			
		||||
    if (len == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* process a skip request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_skip(state, state->skip) == -1)
 | 
			
		||||
            return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* get len bytes to buf, or less than len if at the end */
 | 
			
		||||
    got = 0;
 | 
			
		||||
    do {
 | 
			
		||||
        /* set n to the maximum amount of len that fits in an unsigned int */
 | 
			
		||||
        n = (unsigned)-1;
 | 
			
		||||
        if (n > len)
 | 
			
		||||
            n = (unsigned)len;
 | 
			
		||||
 | 
			
		||||
        /* first just try copying data from the output buffer */
 | 
			
		||||
        if (state->x.have) {
 | 
			
		||||
            if (state->x.have < n)
 | 
			
		||||
                n = state->x.have;
 | 
			
		||||
            memcpy(buf, state->x.next, n);
 | 
			
		||||
            state->x.next += n;
 | 
			
		||||
            state->x.have -= n;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* output buffer empty -- return if we're at the end of the input */
 | 
			
		||||
        else if (state->eof && state->strm.avail_in == 0) {
 | 
			
		||||
            state->past = 1;        /* tried to read past end */
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* need output data -- for small len or new stream load up our output
 | 
			
		||||
           buffer */
 | 
			
		||||
        else if (state->how == LOOK || n < (state->size << 1)) {
 | 
			
		||||
            /* get more output, looking for header if required */
 | 
			
		||||
            if (gz_fetch(state) == -1)
 | 
			
		||||
                return 0;
 | 
			
		||||
            continue;       /* no progress yet -- go back to copy above */
 | 
			
		||||
            /* the copy above assures that we will leave with space in the
 | 
			
		||||
               output buffer, allowing at least one gzungetc() to succeed */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* large len -- read directly into user buffer */
 | 
			
		||||
        else if (state->how == COPY) {      /* read directly */
 | 
			
		||||
            if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* large len -- decompress directly into user buffer */
 | 
			
		||||
        else {  /* state->how == GZIP */
 | 
			
		||||
            state->strm.avail_out = n;
 | 
			
		||||
            state->strm.next_out = (unsigned char *)buf;
 | 
			
		||||
            if (gz_decomp(state) == -1)
 | 
			
		||||
                return 0;
 | 
			
		||||
            n = state->x.have;
 | 
			
		||||
            state->x.have = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* update progress */
 | 
			
		||||
        len -= n;
 | 
			
		||||
        buf = (char *)buf + n;
 | 
			
		||||
        got += n;
 | 
			
		||||
        state->x.pos += n;
 | 
			
		||||
    } while (len);
 | 
			
		||||
 | 
			
		||||
    /* return number of bytes read into user buffer */
 | 
			
		||||
    return got;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're reading and that there's no (serious) error */
 | 
			
		||||
    if (state->mode != GZ_READ ||
 | 
			
		||||
            (state->err != Z_OK && state->err != Z_BUF_ERROR))
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* since an int is returned, make sure len fits in one, otherwise return
 | 
			
		||||
       with an error (this avoids a flaw in the interface) */
 | 
			
		||||
    if ((int)len < 0) {
 | 
			
		||||
        gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* read len or fewer bytes to buf */
 | 
			
		||||
    len = (unsigned)gz_read(state, buf, len);
 | 
			
		||||
 | 
			
		||||
    /* check for an error */
 | 
			
		||||
    if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* return the number of bytes read (this is assured to fit in an int) */
 | 
			
		||||
    return (int)len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
 | 
			
		||||
    z_size_t len;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return 0;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're reading and that there's no (serious) error */
 | 
			
		||||
    if (state->mode != GZ_READ ||
 | 
			
		||||
            (state->err != Z_OK && state->err != Z_BUF_ERROR))
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* compute bytes to read -- error on overflow */
 | 
			
		||||
    len = nitems * size;
 | 
			
		||||
    if (size && len / size != nitems) {
 | 
			
		||||
        gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* read len or fewer bytes to buf, return the number of full items read */
 | 
			
		||||
    return len ? gz_read(state, buf, len) / size : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
#ifdef Z_PREFIX_SET
 | 
			
		||||
#  undef z_gzgetc
 | 
			
		||||
#else
 | 
			
		||||
#  undef gzgetc
 | 
			
		||||
#endif
 | 
			
		||||
int ZEXPORT gzgetc(gzFile file) {
 | 
			
		||||
    unsigned char buf[1];
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're reading and that there's no (serious) error */
 | 
			
		||||
    if (state->mode != GZ_READ ||
 | 
			
		||||
        (state->err != Z_OK && state->err != Z_BUF_ERROR))
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* try output buffer (no need to check for skip request) */
 | 
			
		||||
    if (state->x.have) {
 | 
			
		||||
        state->x.have--;
 | 
			
		||||
        state->x.pos++;
 | 
			
		||||
        return *(state->x.next)++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* nothing there -- try gz_read() */
 | 
			
		||||
    return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ZEXPORT gzgetc_(gzFile file) {
 | 
			
		||||
    return gzgetc(file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzungetc(int c, gzFile file) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* in case this was just opened, set up the input buffer */
 | 
			
		||||
    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
 | 
			
		||||
        (void)gz_look(state);
 | 
			
		||||
 | 
			
		||||
    /* check that we're reading and that there's no (serious) error */
 | 
			
		||||
    if (state->mode != GZ_READ ||
 | 
			
		||||
        (state->err != Z_OK && state->err != Z_BUF_ERROR))
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* process a skip request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_skip(state, state->skip) == -1)
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* can't push EOF */
 | 
			
		||||
    if (c < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* if output buffer empty, put byte at end (allows more pushing) */
 | 
			
		||||
    if (state->x.have == 0) {
 | 
			
		||||
        state->x.have = 1;
 | 
			
		||||
        state->x.next = state->out + (state->size << 1) - 1;
 | 
			
		||||
        state->x.next[0] = (unsigned char)c;
 | 
			
		||||
        state->x.pos--;
 | 
			
		||||
        state->past = 0;
 | 
			
		||||
        return c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* if no room, give up (must have already done a gzungetc()) */
 | 
			
		||||
    if (state->x.have == (state->size << 1)) {
 | 
			
		||||
        gz_error(state, Z_DATA_ERROR, "out of room to push characters");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* slide output data if needed and insert byte before existing data */
 | 
			
		||||
    if (state->x.next == state->out) {
 | 
			
		||||
        unsigned char *src = state->out + state->x.have;
 | 
			
		||||
        unsigned char *dest = state->out + (state->size << 1);
 | 
			
		||||
        while (src > state->out)
 | 
			
		||||
            *--dest = *--src;
 | 
			
		||||
        state->x.next = dest;
 | 
			
		||||
    }
 | 
			
		||||
    state->x.have++;
 | 
			
		||||
    state->x.next--;
 | 
			
		||||
    state->x.next[0] = (unsigned char)c;
 | 
			
		||||
    state->x.pos--;
 | 
			
		||||
    state->past = 0;
 | 
			
		||||
    return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
 | 
			
		||||
    unsigned left, n;
 | 
			
		||||
    char *str;
 | 
			
		||||
    unsigned char *eol;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* check parameters and get internal structure */
 | 
			
		||||
    if (file == NULL || buf == NULL || len < 1)
 | 
			
		||||
        return NULL;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're reading and that there's no (serious) error */
 | 
			
		||||
    if (state->mode != GZ_READ ||
 | 
			
		||||
        (state->err != Z_OK && state->err != Z_BUF_ERROR))
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    /* process a skip request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_skip(state, state->skip) == -1)
 | 
			
		||||
            return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* copy output bytes up to new line or len - 1, whichever comes first --
 | 
			
		||||
       append a terminating zero to the string (we don't check for a zero in
 | 
			
		||||
       the contents, let the user worry about that) */
 | 
			
		||||
    str = buf;
 | 
			
		||||
    left = (unsigned)len - 1;
 | 
			
		||||
    if (left) do {
 | 
			
		||||
        /* assure that something is in the output buffer */
 | 
			
		||||
        if (state->x.have == 0 && gz_fetch(state) == -1)
 | 
			
		||||
            return NULL;                /* error */
 | 
			
		||||
        if (state->x.have == 0) {       /* end of file */
 | 
			
		||||
            state->past = 1;            /* read past end */
 | 
			
		||||
            break;                      /* return what we have */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* look for end-of-line in current output buffer */
 | 
			
		||||
        n = state->x.have > left ? left : state->x.have;
 | 
			
		||||
        eol = (unsigned char *)memchr(state->x.next, '\n', n);
 | 
			
		||||
        if (eol != NULL)
 | 
			
		||||
            n = (unsigned)(eol - state->x.next) + 1;
 | 
			
		||||
 | 
			
		||||
        /* copy through end-of-line, or remainder if not found */
 | 
			
		||||
        memcpy(buf, state->x.next, n);
 | 
			
		||||
        state->x.have -= n;
 | 
			
		||||
        state->x.next += n;
 | 
			
		||||
        state->x.pos += n;
 | 
			
		||||
        left -= n;
 | 
			
		||||
        buf += n;
 | 
			
		||||
    } while (left && eol == NULL);
 | 
			
		||||
 | 
			
		||||
    /* return terminated string, or if nothing, end of file */
 | 
			
		||||
    if (buf == str)
 | 
			
		||||
        return NULL;
 | 
			
		||||
    buf[0] = 0;
 | 
			
		||||
    return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzdirect(gzFile file) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return 0;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* if the state is not known, but we can find out, then do so (this is
 | 
			
		||||
       mainly for right after a gzopen() or gzdopen()) */
 | 
			
		||||
    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
 | 
			
		||||
        (void)gz_look(state);
 | 
			
		||||
 | 
			
		||||
    /* return 1 if transparent, 0 if processing a gzip stream */
 | 
			
		||||
    return state->direct;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzclose_r(gzFile file) {
 | 
			
		||||
    int ret, err;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're reading */
 | 
			
		||||
    if (state->mode != GZ_READ)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* free memory and close file */
 | 
			
		||||
    if (state->size) {
 | 
			
		||||
        inflateEnd(&(state->strm));
 | 
			
		||||
        free(state->out);
 | 
			
		||||
        free(state->in);
 | 
			
		||||
    }
 | 
			
		||||
    err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
 | 
			
		||||
    gz_error(state, Z_OK, NULL);
 | 
			
		||||
    free(state->path);
 | 
			
		||||
    ret = close(state->fd);
 | 
			
		||||
    free(state);
 | 
			
		||||
    return ret ? Z_ERRNO : err;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										631
									
								
								thirdparty/zlib/gzwrite.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										631
									
								
								thirdparty/zlib/gzwrite.c
									
									
									
									
										vendored
									
									
								
							@@ -1,631 +0,0 @@
 | 
			
		||||
/* gzwrite.c -- zlib functions for writing gzip files
 | 
			
		||||
 * Copyright (C) 2004-2019 Mark Adler
 | 
			
		||||
 * For conditions of distribution and use, see copyright notice in zlib.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gzguts.h"
 | 
			
		||||
 | 
			
		||||
/* Initialize state for writing a gzip file.  Mark initialization by setting
 | 
			
		||||
   state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
 | 
			
		||||
   success. */
 | 
			
		||||
local int gz_init(gz_statep state) {
 | 
			
		||||
    int ret;
 | 
			
		||||
    z_streamp strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* allocate input buffer (double size for gzprintf) */
 | 
			
		||||
    state->in = (unsigned char *)malloc(state->want << 1);
 | 
			
		||||
    if (state->in == NULL) {
 | 
			
		||||
        gz_error(state, Z_MEM_ERROR, "out of memory");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* only need output buffer and deflate state if compressing */
 | 
			
		||||
    if (!state->direct) {
 | 
			
		||||
        /* allocate output buffer */
 | 
			
		||||
        state->out = (unsigned char *)malloc(state->want);
 | 
			
		||||
        if (state->out == NULL) {
 | 
			
		||||
            free(state->in);
 | 
			
		||||
            gz_error(state, Z_MEM_ERROR, "out of memory");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* allocate deflate memory, set up for gzip compression */
 | 
			
		||||
        strm->zalloc = Z_NULL;
 | 
			
		||||
        strm->zfree = Z_NULL;
 | 
			
		||||
        strm->opaque = Z_NULL;
 | 
			
		||||
        ret = deflateInit2(strm, state->level, Z_DEFLATED,
 | 
			
		||||
                           MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
 | 
			
		||||
        if (ret != Z_OK) {
 | 
			
		||||
            free(state->out);
 | 
			
		||||
            free(state->in);
 | 
			
		||||
            gz_error(state, Z_MEM_ERROR, "out of memory");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        strm->next_in = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* mark state as initialized */
 | 
			
		||||
    state->size = state->want;
 | 
			
		||||
 | 
			
		||||
    /* initialize write buffer if compressing */
 | 
			
		||||
    if (!state->direct) {
 | 
			
		||||
        strm->avail_out = state->size;
 | 
			
		||||
        strm->next_out = state->out;
 | 
			
		||||
        state->x.next = strm->next_out;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Compress whatever is at avail_in and next_in and write to the output file.
 | 
			
		||||
   Return -1 if there is an error writing to the output file or if gz_init()
 | 
			
		||||
   fails to allocate memory, otherwise 0.  flush is assumed to be a valid
 | 
			
		||||
   deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
 | 
			
		||||
   reset to start a new gzip stream.  If gz->direct is true, then simply write
 | 
			
		||||
   to the output file without compressing, and ignore flush. */
 | 
			
		||||
local int gz_comp(gz_statep state, int flush) {
 | 
			
		||||
    int ret, writ;
 | 
			
		||||
    unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
 | 
			
		||||
    z_streamp strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* allocate memory if this is the first time through */
 | 
			
		||||
    if (state->size == 0 && gz_init(state) == -1)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* write directly if requested */
 | 
			
		||||
    if (state->direct) {
 | 
			
		||||
        while (strm->avail_in) {
 | 
			
		||||
            put = strm->avail_in > max ? max : strm->avail_in;
 | 
			
		||||
            writ = write(state->fd, strm->next_in, put);
 | 
			
		||||
            if (writ < 0) {
 | 
			
		||||
                gz_error(state, Z_ERRNO, zstrerror());
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            strm->avail_in -= (unsigned)writ;
 | 
			
		||||
            strm->next_in += writ;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* check for a pending reset */
 | 
			
		||||
    if (state->reset) {
 | 
			
		||||
        /* don't start a new gzip member unless there is data to write */
 | 
			
		||||
        if (strm->avail_in == 0)
 | 
			
		||||
            return 0;
 | 
			
		||||
        deflateReset(strm);
 | 
			
		||||
        state->reset = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* run deflate() on provided input until it produces no more output */
 | 
			
		||||
    ret = Z_OK;
 | 
			
		||||
    do {
 | 
			
		||||
        /* write out current buffer contents if full, or if flushing, but if
 | 
			
		||||
           doing Z_FINISH then don't write until we get to Z_STREAM_END */
 | 
			
		||||
        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
 | 
			
		||||
            (flush != Z_FINISH || ret == Z_STREAM_END))) {
 | 
			
		||||
            while (strm->next_out > state->x.next) {
 | 
			
		||||
                put = strm->next_out - state->x.next > (int)max ? max :
 | 
			
		||||
                      (unsigned)(strm->next_out - state->x.next);
 | 
			
		||||
                writ = write(state->fd, state->x.next, put);
 | 
			
		||||
                if (writ < 0) {
 | 
			
		||||
                    gz_error(state, Z_ERRNO, zstrerror());
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
                state->x.next += writ;
 | 
			
		||||
            }
 | 
			
		||||
            if (strm->avail_out == 0) {
 | 
			
		||||
                strm->avail_out = state->size;
 | 
			
		||||
                strm->next_out = state->out;
 | 
			
		||||
                state->x.next = state->out;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* compress */
 | 
			
		||||
        have = strm->avail_out;
 | 
			
		||||
        ret = deflate(strm, flush);
 | 
			
		||||
        if (ret == Z_STREAM_ERROR) {
 | 
			
		||||
            gz_error(state, Z_STREAM_ERROR,
 | 
			
		||||
                      "internal error: deflate stream corrupt");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        have -= strm->avail_out;
 | 
			
		||||
    } while (have);
 | 
			
		||||
 | 
			
		||||
    /* if that completed a deflate stream, allow another to start */
 | 
			
		||||
    if (flush == Z_FINISH)
 | 
			
		||||
        state->reset = 1;
 | 
			
		||||
 | 
			
		||||
    /* all done, no errors */
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Compress len zeros to output.  Return -1 on a write error or memory
 | 
			
		||||
   allocation failure by gz_comp(), or 0 on success. */
 | 
			
		||||
local int gz_zero(gz_statep state, z_off64_t len) {
 | 
			
		||||
    int first;
 | 
			
		||||
    unsigned n;
 | 
			
		||||
    z_streamp strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* consume whatever's left in the input buffer */
 | 
			
		||||
    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* compress len zeros (len guaranteed > 0) */
 | 
			
		||||
    first = 1;
 | 
			
		||||
    while (len) {
 | 
			
		||||
        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
 | 
			
		||||
            (unsigned)len : state->size;
 | 
			
		||||
        if (first) {
 | 
			
		||||
            memset(state->in, 0, n);
 | 
			
		||||
            first = 0;
 | 
			
		||||
        }
 | 
			
		||||
        strm->avail_in = n;
 | 
			
		||||
        strm->next_in = state->in;
 | 
			
		||||
        state->x.pos += n;
 | 
			
		||||
        if (gz_comp(state, Z_NO_FLUSH) == -1)
 | 
			
		||||
            return -1;
 | 
			
		||||
        len -= n;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write len bytes from buf to file.  Return the number of bytes written.  If
 | 
			
		||||
   the returned value is less than len, then there was an error. */
 | 
			
		||||
local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
 | 
			
		||||
    z_size_t put = len;
 | 
			
		||||
 | 
			
		||||
    /* if len is zero, avoid unnecessary operations */
 | 
			
		||||
    if (len == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* allocate memory if this is the first time through */
 | 
			
		||||
    if (state->size == 0 && gz_init(state) == -1)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* check for seek request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_zero(state, state->skip) == -1)
 | 
			
		||||
            return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* for small len, copy to input buffer, otherwise compress directly */
 | 
			
		||||
    if (len < state->size) {
 | 
			
		||||
        /* copy to input buffer, compress when full */
 | 
			
		||||
        do {
 | 
			
		||||
            unsigned have, copy;
 | 
			
		||||
 | 
			
		||||
            if (state->strm.avail_in == 0)
 | 
			
		||||
                state->strm.next_in = state->in;
 | 
			
		||||
            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
 | 
			
		||||
                              state->in);
 | 
			
		||||
            copy = state->size - have;
 | 
			
		||||
            if (copy > len)
 | 
			
		||||
                copy = (unsigned)len;
 | 
			
		||||
            memcpy(state->in + have, buf, copy);
 | 
			
		||||
            state->strm.avail_in += copy;
 | 
			
		||||
            state->x.pos += copy;
 | 
			
		||||
            buf = (const char *)buf + copy;
 | 
			
		||||
            len -= copy;
 | 
			
		||||
            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
 | 
			
		||||
                return 0;
 | 
			
		||||
        } while (len);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        /* consume whatever's left in the input buffer */
 | 
			
		||||
        if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        /* directly compress user buffer to file */
 | 
			
		||||
        state->strm.next_in = (z_const Bytef *)buf;
 | 
			
		||||
        do {
 | 
			
		||||
            unsigned n = (unsigned)-1;
 | 
			
		||||
            if (n > len)
 | 
			
		||||
                n = (unsigned)len;
 | 
			
		||||
            state->strm.avail_in = n;
 | 
			
		||||
            state->x.pos += n;
 | 
			
		||||
            if (gz_comp(state, Z_NO_FLUSH) == -1)
 | 
			
		||||
                return 0;
 | 
			
		||||
            len -= n;
 | 
			
		||||
        } while (len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* input was all buffered or compressed */
 | 
			
		||||
    return put;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return 0;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* since an int is returned, make sure len fits in one, otherwise return
 | 
			
		||||
       with an error (this avoids a flaw in the interface) */
 | 
			
		||||
    if ((int)len < 0) {
 | 
			
		||||
        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* write len bytes from buf (the return value will fit in an int) */
 | 
			
		||||
    return (int)gz_write(state, buf, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
 | 
			
		||||
                          gzFile file) {
 | 
			
		||||
    z_size_t len;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return 0;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* compute bytes to read -- error on overflow */
 | 
			
		||||
    len = nitems * size;
 | 
			
		||||
    if (size && len / size != nitems) {
 | 
			
		||||
        gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* write len bytes to buf, return the number of full items written */
 | 
			
		||||
    return len ? gz_write(state, buf, len) / size : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzputc(gzFile file, int c) {
 | 
			
		||||
    unsigned have;
 | 
			
		||||
    unsigned char buf[1];
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
    z_streamp strm;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* check for seek request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_zero(state, state->skip) == -1)
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* try writing to input buffer for speed (state->size == 0 if buffer not
 | 
			
		||||
       initialized) */
 | 
			
		||||
    if (state->size) {
 | 
			
		||||
        if (strm->avail_in == 0)
 | 
			
		||||
            strm->next_in = state->in;
 | 
			
		||||
        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
 | 
			
		||||
        if (have < state->size) {
 | 
			
		||||
            state->in[have] = (unsigned char)c;
 | 
			
		||||
            strm->avail_in++;
 | 
			
		||||
            state->x.pos++;
 | 
			
		||||
            return c & 0xff;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* no room in buffer or not initialized, use gz_write() */
 | 
			
		||||
    buf[0] = (unsigned char)c;
 | 
			
		||||
    if (gz_write(state, buf, 1) != 1)
 | 
			
		||||
        return -1;
 | 
			
		||||
    return c & 0xff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzputs(gzFile file, const char *s) {
 | 
			
		||||
    z_size_t len, put;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return -1;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    /* write string */
 | 
			
		||||
    len = strlen(s);
 | 
			
		||||
    if ((int)len < 0 || (unsigned)len != len) {
 | 
			
		||||
        gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    put = gz_write(state, s, len);
 | 
			
		||||
    return put < len ? -1 : (int)len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
 | 
			
		||||
    int len;
 | 
			
		||||
    unsigned left;
 | 
			
		||||
    char *next;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
    z_streamp strm;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* make sure we have some buffer space */
 | 
			
		||||
    if (state->size == 0 && gz_init(state) == -1)
 | 
			
		||||
        return state->err;
 | 
			
		||||
 | 
			
		||||
    /* check for seek request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_zero(state, state->skip) == -1)
 | 
			
		||||
            return state->err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* do the printf() into the input buffer, put length in len -- the input
 | 
			
		||||
       buffer is double-sized just for this function, so there is guaranteed to
 | 
			
		||||
       be state->size bytes available after the current contents */
 | 
			
		||||
    if (strm->avail_in == 0)
 | 
			
		||||
        strm->next_in = state->in;
 | 
			
		||||
    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
 | 
			
		||||
    next[state->size - 1] = 0;
 | 
			
		||||
#ifdef NO_vsnprintf
 | 
			
		||||
#  ifdef HAS_vsprintf_void
 | 
			
		||||
    (void)vsprintf(next, format, va);
 | 
			
		||||
    for (len = 0; len < state->size; len++)
 | 
			
		||||
        if (next[len] == 0) break;
 | 
			
		||||
#  else
 | 
			
		||||
    len = vsprintf(next, format, va);
 | 
			
		||||
#  endif
 | 
			
		||||
#else
 | 
			
		||||
#  ifdef HAS_vsnprintf_void
 | 
			
		||||
    (void)vsnprintf(next, state->size, format, va);
 | 
			
		||||
    len = strlen(next);
 | 
			
		||||
#  else
 | 
			
		||||
    len = vsnprintf(next, state->size, format, va);
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* check that printf() results fit in buffer */
 | 
			
		||||
    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* update buffer and position, compress first half if past that */
 | 
			
		||||
    strm->avail_in += (unsigned)len;
 | 
			
		||||
    state->x.pos += len;
 | 
			
		||||
    if (strm->avail_in >= state->size) {
 | 
			
		||||
        left = strm->avail_in - state->size;
 | 
			
		||||
        strm->avail_in = state->size;
 | 
			
		||||
        if (gz_comp(state, Z_NO_FLUSH) == -1)
 | 
			
		||||
            return state->err;
 | 
			
		||||
        memmove(state->in, state->in + state->size, left);
 | 
			
		||||
        strm->next_in = state->in;
 | 
			
		||||
        strm->avail_in = left;
 | 
			
		||||
    }
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
 | 
			
		||||
    va_list va;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    va_start(va, format);
 | 
			
		||||
    ret = gzvprintf(file, format, va);
 | 
			
		||||
    va_end(va);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else /* !STDC && !Z_HAVE_STDARG_H */
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
 | 
			
		||||
                       int a4, int a5, int a6, int a7, int a8, int a9, int a10,
 | 
			
		||||
                       int a11, int a12, int a13, int a14, int a15, int a16,
 | 
			
		||||
                       int a17, int a18, int a19, int a20) {
 | 
			
		||||
    unsigned len, left;
 | 
			
		||||
    char *next;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
    z_streamp strm;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* check that can really pass pointer in ints */
 | 
			
		||||
    if (sizeof(int) != sizeof(void *))
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* make sure we have some buffer space */
 | 
			
		||||
    if (state->size == 0 && gz_init(state) == -1)
 | 
			
		||||
        return state->error;
 | 
			
		||||
 | 
			
		||||
    /* check for seek request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_zero(state, state->skip) == -1)
 | 
			
		||||
            return state->error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* do the printf() into the input buffer, put length in len -- the input
 | 
			
		||||
       buffer is double-sized just for this function, so there is guaranteed to
 | 
			
		||||
       be state->size bytes available after the current contents */
 | 
			
		||||
    if (strm->avail_in == 0)
 | 
			
		||||
        strm->next_in = state->in;
 | 
			
		||||
    next = (char *)(strm->next_in + strm->avail_in);
 | 
			
		||||
    next[state->size - 1] = 0;
 | 
			
		||||
#ifdef NO_snprintf
 | 
			
		||||
#  ifdef HAS_sprintf_void
 | 
			
		||||
    sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
 | 
			
		||||
            a13, a14, a15, a16, a17, a18, a19, a20);
 | 
			
		||||
    for (len = 0; len < size; len++)
 | 
			
		||||
        if (next[len] == 0)
 | 
			
		||||
            break;
 | 
			
		||||
#  else
 | 
			
		||||
    len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
 | 
			
		||||
                  a12, a13, a14, a15, a16, a17, a18, a19, a20);
 | 
			
		||||
#  endif
 | 
			
		||||
#else
 | 
			
		||||
#  ifdef HAS_snprintf_void
 | 
			
		||||
    snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
 | 
			
		||||
             a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 | 
			
		||||
    len = strlen(next);
 | 
			
		||||
#  else
 | 
			
		||||
    len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
 | 
			
		||||
                   a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* check that printf() results fit in buffer */
 | 
			
		||||
    if (len == 0 || len >= state->size || next[state->size - 1] != 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* update buffer and position, compress first half if past that */
 | 
			
		||||
    strm->avail_in += len;
 | 
			
		||||
    state->x.pos += len;
 | 
			
		||||
    if (strm->avail_in >= state->size) {
 | 
			
		||||
        left = strm->avail_in - state->size;
 | 
			
		||||
        strm->avail_in = state->size;
 | 
			
		||||
        if (gz_comp(state, Z_NO_FLUSH) == -1)
 | 
			
		||||
            return state->err;
 | 
			
		||||
        memmove(state->in, state->in + state->size, left);
 | 
			
		||||
        strm->next_in = state->in;
 | 
			
		||||
        strm->avail_in = left;
 | 
			
		||||
    }
 | 
			
		||||
    return (int)len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzflush(gzFile file, int flush) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* check flush parameter */
 | 
			
		||||
    if (flush < 0 || flush > Z_FINISH)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* check for seek request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_zero(state, state->skip) == -1)
 | 
			
		||||
            return state->err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* compress remaining data with requested flush */
 | 
			
		||||
    (void)gz_comp(state, flush);
 | 
			
		||||
    return state->err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
    z_streamp strm;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
    strm = &(state->strm);
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing and that there's no error */
 | 
			
		||||
    if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* if no change is requested, then do nothing */
 | 
			
		||||
    if (level == state->level && strategy == state->strategy)
 | 
			
		||||
        return Z_OK;
 | 
			
		||||
 | 
			
		||||
    /* check for seek request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_zero(state, state->skip) == -1)
 | 
			
		||||
            return state->err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* change compression parameters for subsequent input */
 | 
			
		||||
    if (state->size) {
 | 
			
		||||
        /* flush previous input with previous parameters before changing */
 | 
			
		||||
        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
 | 
			
		||||
            return state->err;
 | 
			
		||||
        deflateParams(strm, level, strategy);
 | 
			
		||||
    }
 | 
			
		||||
    state->level = level;
 | 
			
		||||
    state->strategy = strategy;
 | 
			
		||||
    return Z_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -- see zlib.h -- */
 | 
			
		||||
int ZEXPORT gzclose_w(gzFile file) {
 | 
			
		||||
    int ret = Z_OK;
 | 
			
		||||
    gz_statep state;
 | 
			
		||||
 | 
			
		||||
    /* get internal structure */
 | 
			
		||||
    if (file == NULL)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
    state = (gz_statep)file;
 | 
			
		||||
 | 
			
		||||
    /* check that we're writing */
 | 
			
		||||
    if (state->mode != GZ_WRITE)
 | 
			
		||||
        return Z_STREAM_ERROR;
 | 
			
		||||
 | 
			
		||||
    /* check for seek request */
 | 
			
		||||
    if (state->seek) {
 | 
			
		||||
        state->seek = 0;
 | 
			
		||||
        if (gz_zero(state, state->skip) == -1)
 | 
			
		||||
            ret = state->err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* flush, free memory, and close file */
 | 
			
		||||
    if (gz_comp(state, Z_FINISH) == -1)
 | 
			
		||||
        ret = state->err;
 | 
			
		||||
    if (state->size) {
 | 
			
		||||
        if (!state->direct) {
 | 
			
		||||
            (void)deflateEnd(&(state->strm));
 | 
			
		||||
            free(state->out);
 | 
			
		||||
        }
 | 
			
		||||
        free(state->in);
 | 
			
		||||
    }
 | 
			
		||||
    gz_error(state, Z_OK, NULL);
 | 
			
		||||
    free(state->path);
 | 
			
		||||
    if (close(state->fd) == -1)
 | 
			
		||||
        ret = Z_ERRNO;
 | 
			
		||||
    free(state);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user