text: /*
   * Based on John the Ripper and modified to integrate with aircrack
   *
   * 	John the Ripper copyright and license.
   *
   * John the Ripper password cracker,
   * Copyright (c) 1996-2013 by Solar Designer.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * As a special exception to the GNU General Public License terms,
   * permission is hereby granted to link the code of this program, with or
   * without modification, with any version of the OpenSSL library and/or any
   * version of unRAR, and to distribute such linked combinations.  You must
   * obey the GNU GPL in all respects for all of the code used other than
   * OpenSSL and unRAR.  If you modify this program, you may extend this
   * exception to your version of the program, but you are not obligated to
   * do so.  (In other words, you may release your derived work under pure
   * GNU GPL version 2 or later as published by the FSF.)
   *
   * (This exception from the GNU GPL is not required for the core tree of
   * John the Ripper, but arguably it is required for -jumbo.)
   *
   * 	Relaxed terms for certain components.
   *
   * In addition or alternatively to the license above, many components are
   * available to you under more relaxed terms (most commonly under cut-down
   * BSD license) as specified in the corresponding source files.
   *
   * For more information on John the Ripper licensing please visit:
   *
   * http://www.openwall.com/john/doc/LICENSE.shtml
   *
   * This file is part of John the Ripper password cracker,
   * Copyright (c) 1996-98,2003,2010-2012 by Solar Designer
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted.
   *
   * There's ABSOLUTELY NO WARRANTY, express or implied.
   */
  
  /*
   * Memory allocation routines.
   */
  
  #ifndef _MEMORY_H
  #define _MEMORY_H
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  
  #include "arch.h"
  
  #if __AVX512F__
  #define SIMD_COEF_32 16
  #define SIMD_COEF_64 8
  #elif __AVX2__
  #define SIMD_COEF_32 8
  #define SIMD_COEF_64 4
  #elif __SSE2__
  #define SIMD_COEF_32 4
  #define SIMD_COEF_64 2
  #elif __MMX__
  #define SIMD_COEF_32 2
  #define SIMD_COEF_64 1
  #endif
  
  /*
   * Standard alignments for mem_alloc_tiny().
   */
  #define MEM_ALIGN_NONE			1
  #define MEM_ALIGN_WORD			ARCH_SIZE
  /*
   * These are hopefully suitable guesses.  They are right for only a subset of
   * the architectures/CPUs we support, yet our use of them does not require that
   * they be entirely correct.
   */
  #ifdef _MSC_VER
  #define MEM_ALIGN_CACHE			64
  #else
  #define MEM_ALIGN_CACHE			(ARCH_SIZE * 8)
  #endif
  #define MEM_ALIGN_PAGE			0x1000
  
  /*
   * SIMD buffers need to be aligned to register size
   */
  #if SIMD_COEF_32
  #ifdef _MSC_VER
  #define MEM_ALIGN_SIMD			16
  #else
  #define MEM_ALIGN_SIMD			(SIMD_COEF_32 * 4)
  #endif
  #else
  #define MEM_ALIGN_SIMD			(16)
  #endif
  
  /*
   * Block size used by mem_alloc_tiny().
   */
  #define MEM_ALLOC_SIZE			0x10000
  
  /*
   * Use mem_alloc() instead of allocating a new block in mem_alloc_tiny()
   * if more than MEM_ALLOC_MAX_WASTE bytes would be lost.
   * This shouldn't be set too small, or mem_alloc_tiny() will keep calling
   * mem_alloc() for many allocations in a row, which might end up wasting even
   * more memory to malloc() overhead.
   */
  #define MEM_ALLOC_MAX_WASTE		0xff
  
  /*
   * Memory saving level, setting this high enough disables alignments (if the
   * architecture allows).
   */
  extern unsigned int mem_saving_level;
  
  /*
   * Allocates size bytes and returns a pointer to the allocated memory.
   * If an error occurs, the function does not return.
   */
  extern void *mem_alloc_func(size_t size
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  /*
   * this version same as mem_alloc, but initialized the memory
   * to NULL bytes, like CALLOC(3) function does
   */
  extern void *mem_calloc_func(size_t count, size_t size
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  
  #if defined (MEMDBG_ON)
  #define mem_alloc(a) mem_alloc_func(a,__FILE__,__LINE__)
  #define mem_calloc(a,b) mem_calloc_func(a,b,__FILE__,__LINE__)
  #define mem_alloc_tiny(a,b) mem_alloc_tiny_func(a,b,__FILE__,__LINE__)
  #define mem_calloc_tiny(a,b) mem_calloc_tiny_func(a,b,__FILE__,__LINE__)
  #define mem_alloc_copy(a,b,c) mem_alloc_copy_func(a,b,c,__FILE__,__LINE__)
  #define str_alloc_copy(a) str_alloc_copy_func(a,__FILE__,__LINE__)
  #define mem_alloc_align(a,b) mem_alloc_align_func(a,b,__FILE__,__LINE__)
  #define mem_calloc_align(a,b,c) mem_calloc_align_func(a,b,c,__FILE__,__LINE__)
  #else
  #define mem_alloc(a) mem_alloc_func(a)
  #define mem_calloc(a,b) mem_calloc_func(a,b)
  #define mem_alloc_tiny(a,b) mem_alloc_tiny_func(a,b)
  #define mem_calloc_tiny(a,b) mem_calloc_tiny_func(a,b)
  #define mem_alloc_copy(a,b,c) mem_alloc_copy_func(a,b,c)
  #define str_alloc_copy(a) str_alloc_copy_func(a)
  #define mem_alloc_align(a,b) mem_alloc_align_func(a,b)
  #define mem_calloc_align(a,b,c) mem_calloc_align_func(a,b,c)
  #endif
  
  /* These allow alignment and are wrappers to system-specific functions */
  void *mem_alloc_align_func(size_t size, size_t align
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  
  void *mem_calloc_align_func(size_t count, size_t size, size_t align
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  
  /*
   * Frees memory allocated with mem_alloc() and sets the pointer to NULL.
   * Does nothing if the pointer is already NULL.
   */
  #undef MEM_FREE
  
  #ifdef _MSC_VER
  #if !defined (MEMDBG_ON)
  #define strdup(a) strdup_MSVC(a)
  char *strdup_MSVC(const char *str);
  #define MEM_FREE(ptr) \
  { \
  	if ((ptr)) { \
  		_aligned_free((ptr)); \
  		(ptr) = NULL; \
  	} \
  }
  #else
  #define MEM_FREE(ptr) \
  { \
  	if ((ptr)) { \
  		MEMDBG_free(((const void*)ptr),__FILE__,__LINE__); \
  		(ptr) = NULL; \
  	} \
  }
  #endif
  
  #else
  #define MEM_FREE(ptr) \
  { \
  	if ((ptr)) { \
  		free((ptr)); \
  		(ptr) = NULL; \
  	} \
  }
  #endif
  
  /*
   * Similar to the above function, except the memory can't be freed.
   * This one is used to reduce the overhead.
   */
  extern void *mem_alloc_tiny_func(size_t size, size_t align
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  
  /*
   * this version same as mem_alloc_tiny, but initialized the memory
   * to NULL bytes, like CALLOC(3) function does
   */
  extern void *mem_calloc_tiny_func(size_t size, size_t align
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  
  /*
   * Uses mem_alloc_tiny() to allocate the memory, and copies src in there.
   */
  extern void *mem_alloc_copy_func(void *src, size_t size, size_t align
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  
  /*
   * Similar to the above function, but for ASCIIZ strings.
   */
  extern char *str_alloc_copy_func(char *src
  #if defined (MEMDBG_ON)
  	, char *file, int line
  #endif
  	);
  
  /*
   * This will 'cleanup' the memory allocated by mem_alloc_tiny().  All
   * of that memory was 'blindly' allocated, and not freed up during
   * the run of john.  Now, it is 'cleaned' up.
   */
  extern void cleanup_tiny_memory();
  
  
  void dump_text(void *in, int len);
  void dump_stuff(void *x, unsigned int size);
  void dump_stuff_msg(const void *msg, void *x, unsigned int size);
  void dump_stuff_noeol(void *x, unsigned int size);
  void dump_stuff_msg_sepline(const void *msg, void *x, unsigned int size);
  void dump_stuff_be(void *x, unsigned int size);
  void dump_stuff_be_msg(const void *msg, void *x, unsigned int size);
  void dump_stuff_be_noeol(void *x, unsigned int size);
  void dump_stuff_be_msg_sepline(const void *msg, void *x, unsigned int size);
  
  #if defined (SIMD_COEF_32) || defined(NT_X86_64) || defined (SIMD_PARA_MD5) || defined (SIMD_PARA_MD4) || defined (SIMD_PARA_SHA1)
  void dump_stuff_mmx(void *x, unsigned int size, unsigned int index);
  void dump_stuff_mmx_noeol(void *x, unsigned int size, unsigned int index);
  void dump_stuff_mmx_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_stuff_mmx_msg_sepline(const void *msg, void *buf, unsigned int size, unsigned int index);
  // for flat input, we do want to see SHA512 without byte swapping.
  void dump_stuff_mmx64(void *buf, unsigned int size, unsigned int index);
  void dump_stuff_mmx64_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_out_mmx(void *x, unsigned int size, unsigned int index);
  void dump_out_mmx_noeol(void *x, unsigned int size, unsigned int index);
  void dump_out_mmx_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_out_mmx_msg_sepline(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_stuff_shammx(void *x, unsigned int size, unsigned int index);
  void dump_stuff_shammx_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_out_shammx(void *x, unsigned int size, unsigned int index);
  void dump_out_shammx_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_stuff_shammx64(void *x, unsigned int size, unsigned int index);
  void dump_stuff_shammx64_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_out_shammx64(void *x, unsigned int size, unsigned int index);
  void dump_out_shammx64_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  #endif
  
  #if defined (SIMD_PARA_MD5)
  // these functions help debug arrays of contigious MD5 prepared PARA buffers. Seen in sunmd5 at the current time.
  void dump_stuff_mpara_mmx(void *x, unsigned int size, unsigned int index);
  void dump_stuff_mpara_mmx_noeol(void *x, unsigned int size, unsigned int index);
  void dump_stuff_mpara_mmx_msg(const void *msg, void *buf, unsigned int size, unsigned int index);
  void dump_stuff_mpara_mmx_msg_sepline(const void *msg, void *buf, unsigned int size, unsigned int index);
  // a 'getter' to help debugging.  Returns a flat buffer, vs printing it out.
  void getbuf_stuff_mpara_mmx(unsigned char *oBuf, void *buf, unsigned int size, unsigned int index);
  #endif
  
  /*
   * here, a stack buffer that is at least align-1 bytes LARGER than required, can be
   * properly aligned to 'align' bytes. So:   char tmpbuf[256+15], *aligned_buf=mem_align(tmpbuf,16);
   * will give you a stack buffer, aligned to 16 bytes.  There are bugs in some compilers which cause
   * JTR_ALIGN(x) to fail properly (such as a bug in bitcoin OMP mode for linux32)
   * Switched to a define macro for performance.
   */
  #define mem_align(a,b) (void*)(((char*)(a))+(((b)-1)-(((size_t)((char*)(a))-1)&((b)-1))))
  
  
  /*
   * 32-bit endian-swap a memory buffer in place. Size is in octets (so should
   * be a multiple of 4). From now on, this function may be used on any arch.
   */
  void alter_endianity(void * x, unsigned int size);
  
  /* 32-bit endian-swap a memory buffer in place. Count is in 32-bit words */
  void alter_endianity_w(void *x, unsigned int count);
  
  /* 64-bit endian-swap a memory buffer in place. Count is in 64-bit words */
  void alter_endianity_w64(void *x, unsigned int count);
  
  #if ARCH_ALLOWS_UNALIGNED
  // we can inline these, to always use JOHNSWAP/JOHNSWAP64
  // NOTE, more portable to use #defines to inline, than the MAYBE_INLINE within header files.
  #if (ARCH_LITTLE_ENDIAN==0)
  #define alter_endianity_to_BE(a,b)
  #define alter_endianity_to_BE64(a,b)
  #define alter_endianity_to_LE(ptr,word32_cnt) do{ \
      int i; \
      for (i=0;i<word32_cnt; i++) \
          ((ARCH_WORD_32*)ptr)[i] = JOHNSWAP(((ARCH_WORD_32*)ptr)[i]); \
  }while(0)
  #define alter_endianity_to_LE64(ptr,word64_cnt) do{ \
      int i; \
      for (i=0;i<word64_cnt; i++) \
          ((ARCH_WORD_64*)ptr)[i] = JOHNSWAP64(((ARCH_WORD_64*)ptr)[i]); \
  }while(0)
  #else
  #define alter_endianity_to_LE(a,b)
  #define alter_endianity_to_LE64(a,b)
  #define alter_endianity_to_BE(ptr,word32_cnt) do{ \
      int i; \
      for (i=0;i<word32_cnt; i++) \
          ((ARCH_WORD_32*)ptr)[i] = JOHNSWAP(((ARCH_WORD_32*)ptr)[i]); \
  }while(0)
  #define alter_endianity_to_BE64(ptr,word64_cnt) do{ \
      int i; \
      for (i=0;i<word64_cnt; i++) \
          ((ARCH_WORD_64*)ptr)[i] = JOHNSWAP64(((ARCH_WORD_64*)ptr)[i]); \
  }while(0)
  #endif
  #else
  #if (ARCH_LITTLE_ENDIAN==0)
  #define alter_endianity_to_BE(a,b)
  #define alter_endianity_to_LE(a,b) do{alter_endianity_w(a,b);}while(0)
  #define alter_endianity_to_BE64(a,b)
  #define alter_endianity_to_LE64(a,b) do{alter_endianity_w64(a,b);}while(0)
  #else
  #define alter_endianity_to_BE(a,b) do{alter_endianity_w(a,b);}while(0)
  #define alter_endianity_to_LE(a,b)
  #define alter_endianity_to_BE64(a,b) do{alter_endianity_w64(a,b);}while(0)
  #define alter_endianity_to_LE64(a,b)
  #endif
  #endif
  
  #endif
  