static inline bool
do_check64 (size_t i, const Elf64_auxv_t (*a64)[], uint_fast8_t *elfdata)
{
  /* The AUXV pointer might not even be naturally aligned for 64-bit
     data, because note payloads in a core file are not aligned.  */

  uint64_t type = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_type);
  uint64_t val = read_8ubyte_unaligned_noncvt (&(*a64)[i].a_un.a_val);

  if (type == BE64 (PROBE_TYPE)
      && val == BE64 (PROBE_VAL64))
    {
      *elfdata = ELFDATA2MSB;
      return true;
    }

  if (type == LE64 (PROBE_TYPE)
      && val == LE64 (PROBE_VAL64))
    {
      *elfdata = ELFDATA2LSB;
      return true;
    }

  return false;
}
Exemplo n.º 2
0
/* Examine an auxv data block and determine its format.
   Return true iff we figured it out.  */
static bool
auxv_format_probe (const void *auxv, size_t size,
                   uint_fast8_t *elfclass, uint_fast8_t *elfdata)
{
    const union
    {
        char buf[size];
        Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)];
        Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)];
    } *u = auxv;

    inline bool check64 (size_t i)
    {
        /* The AUXV pointer might not even be naturally aligned for 64-bit
           data, because note payloads in a core file are not aligned.  */

        uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type);
        uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val);

        if (type == BE64 (PROBE_TYPE)
                && val == BE64 (PROBE_VAL64))
        {
            *elfdata = ELFDATA2MSB;
            return true;
        }

        if (type == LE64 (PROBE_TYPE)
                && val == LE64 (PROBE_VAL64))
        {
            *elfdata = ELFDATA2LSB;
            return true;
        }

        return false;
    }
Exemplo n.º 3
0
// Initializes IV and whitening values for sector encryption/decryption in CBC mode.
// IMPORTANT: This function has been deprecated (legacy).
static void 
InitSectorIVAndWhitening (unsigned __int64 unitNo,
	int blockSize,
	unsigned __int32 *iv,
	unsigned __int64 *ivSeed,
	unsigned __int32 *whitening)
{

	/* IMPORTANT: This function has been deprecated (legacy) */

	unsigned __int64 iv64[4];
	unsigned __int32 *iv32 = (unsigned __int32 *) iv64;

	iv64[0] = ivSeed[0] ^ LE64(unitNo);
	iv64[1] = ivSeed[1] ^ LE64(unitNo);
	iv64[2] = ivSeed[2] ^ LE64(unitNo);
	if (blockSize == 16)
	{
		iv64[3] = ivSeed[3] ^ LE64(unitNo);
	}

	iv[0] = iv32[0];
	iv[1] = iv32[1];

	switch (blockSize)
	{
	case 16:

		// 128-bit block

		iv[2] = iv32[2];
		iv[3] = iv32[3];

		whitening[0] = LE32( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) );
		whitening[1] = LE32( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) );
		break;

	case 8:

		// 64-bit block

		whitening[0] = LE32( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) );
		whitening[1] = LE32( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) );
		break;

	default:
		GST_THROW_FATAL_EXCEPTION;
	}
}
Exemplo n.º 4
0
/*
 * Helper routine to bridge to packJPG C++ lib, without changing packJPG itself.
 */
size_t
packjpg_filter_process(uchar_t *in_buf, size_t len, uchar_t **out_buf)
{
	unsigned int len1;
	uchar_t *pos;

	/*
	 * Workaround for packJPG limitation, not a bug per se. Images created with
	 * Polaroid cameras appear to have some weird huffman data in the middle which
	 * appears not to be interpreted by any image viewer/editor. This data gets
	 * stripped by packJPG.
	 * So the restored images will be visually correct, but, will be smaller than the
	 * original. So we need to look at the Exif Manufacturer tag for 'Polaroid' and
	 * skip those images. This should be within the first 512 bytes of the
	 * file (really...?) so we do a simple buffer scan without trying to parse Exif
	 * data.
	 */
	pos = (uchar_t *)memchr(in_buf, 'P', 512);
	while (pos) {
		if (LE64(U64_P(pos)) == POLAROID_LE)
			return (0);
		pos++;
		pos = (uchar_t *)memchr(pos, 'P', 512);
	}
	pjglib_init_streams(in_buf, 1, len, *out_buf, 1);
	len1 = len;
	if (!pjglib_convert_stream2mem(out_buf, &len1, NULL))
		return (0);
	if (len1 == len)
		return (0);
	return (len1);
}
Exemplo n.º 5
0
SEXP LE_integer64(SEXP e1_, SEXP e2_, SEXP ret_){
  long long i, n = LENGTH(ret_);
  long long i1, n1 = LENGTH(e1_);
  long long i2, n2 = LENGTH(e2_);
  long long * e1 = (long long *) REAL(e1_);
  long long * e2 = (long long *) REAL(e2_);
  Rboolean * ret = (Rboolean *) LOGICAL(ret_);
	mod_iterate(n1, n2, i1, i2) {
		LE64(e1[i1],e2[i2],ret[i])
	}
  return ret_;
}
Exemplo n.º 6
0
/* Examine an auxv data block and determine its format.
   Return true iff we figured it out.  */
static bool
auxv_format_probe (const void *auxv, size_t size,
		   uint_fast8_t *elfclass, uint_fast8_t *elfdata)
{
  const union
  {
    char buf[size];
    Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)];
    Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)];
  } *u = auxv;

  inline bool check64 (size_t i)
  {
    if (u->a64[i].a_type == BE64 (PROBE_TYPE)
	&& u->a64[i].a_un.a_val == BE64 (PROBE_VAL64))
      {
	*elfdata = ELFDATA2MSB;
	return true;
      }

    if (u->a64[i].a_type == LE64 (PROBE_TYPE)
	&& u->a64[i].a_un.a_val == LE64 (PROBE_VAL64))
      {
	*elfdata = ELFDATA2LSB;
	return true;
      }

    return false;
  }

  inline bool check32 (size_t i)
  {
    if (u->a32[i].a_type == BE32 (PROBE_TYPE)
	&& u->a32[i].a_un.a_val == BE32 (PROBE_VAL32))
      {
	*elfdata = ELFDATA2MSB;
	return true;
      }

    if (u->a32[i].a_type == LE32 (PROBE_TYPE)
	&& u->a32[i].a_un.a_val == LE32 (PROBE_VAL32))
      {
	*elfdata = ELFDATA2LSB;
	return true;
      }

    return false;
  }

  for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
    {
      if (check64 (i))
	{
	  *elfclass = ELFCLASS64;
	  return true;
	}

      if (check32 (i * 2) || check32 (i * 2 + 1))
	{
	  *elfclass = ELFCLASS32;
	  return true;
	}
    }

  return false;
}
Exemplo n.º 7
0
static int
report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
		Dwfl *dwfl, GElf_Addr r_debug_vaddr,
		Dwfl_Memory_Callback *memory_callback,
		void *memory_callback_arg)
{
  /* Skip r_version, to aligned r_map field.  */
  GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);

  void *buffer = NULL;
  size_t buffer_available = 0;
  inline int release_buffer (int result)
  {
    if (buffer != NULL)
      (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
				 memory_callback_arg);
    return result;
  }

  GElf_Addr addrs[4];
  inline bool read_addrs (GElf_Addr vaddr, size_t n)
  {
    size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read.  */

    /* Read a new buffer if the old one doesn't cover these words.  */
    if (buffer == NULL
	|| vaddr < read_vaddr
	|| vaddr - read_vaddr + nb > buffer_available)
      {
	release_buffer (0);

	read_vaddr = vaddr;
	int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
	if (unlikely (segndx < 0)
	    || unlikely (! (*memory_callback) (dwfl, segndx,
					       &buffer, &buffer_available,
					       vaddr, nb, memory_callback_arg)))
	  return true;
      }

    const union
    {
      Elf32_Addr a32[n];
      Elf64_Addr a64[n];
    } *in = vaddr - read_vaddr + buffer;

    if (elfclass == ELFCLASS32)
      {
	if (elfdata == ELFDATA2MSB)
	  for (size_t i = 0; i < n; ++i)
	    addrs[i] = BE32 (in->a32[i]);
	else
	  for (size_t i = 0; i < n; ++i)
	    addrs[i] = LE32 (in->a32[i]);
      }
    else
      {
	if (elfdata == ELFDATA2MSB)
	  for (size_t i = 0; i < n; ++i)
	    addrs[i] = BE64 (in->a64[i]);
	else
	  for (size_t i = 0; i < n; ++i)
	    addrs[i] = LE64 (in->a64[i]);
      }

    return false;
  }
Exemplo n.º 8
0
// Optimized for encryption algorithms supporting intra-data-unit parallelization
static void EncryptBufferXTSParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues;
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned __int64 *dataUnitBufPtr;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	/* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the
	finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block
	number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented
	as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if
	the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is
	derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
		// whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				*whiteningValuesPtr64-- = *whiteningValuePtr64++;
				*whiteningValuesPtr64-- = *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;
#else

			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		dataUnitBufPtr = bufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		// Encrypt all blocks in this data unit

		for (block = startBlock; block < endBlock; block++)
		{
			// Pre-whitening
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		// Actual encryption
		EncipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock);
		
		bufPtr = dataUnitBufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		for (block = startBlock; block < endBlock; block++)
		{
			// Post-whitening
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;
		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
	FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
}
Exemplo n.º 9
0
// Optimized for encryption algorithms not supporting intra-data-unit parallelization
static void DecryptBufferXTSNonParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate (and apply) subsequent whitening values for blocks in this data unit and
		// decrypt all relevant blocks in this data unit
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				// Post-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr-- ^= *whiteningValuePtr64--;

				// Actual decryption
				DecipherBlock (cipher, bufPtr, ks);

				// Pre-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr++ ^= *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;

#else
			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;
		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
}
Exemplo n.º 10
0
// Optimized for encryption algorithms supporting intra-data-unit parallelization
static void DecryptBufferXTSParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValues [ENCRYPTION_DATA_UNIT_SIZE];
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuesPtr64 = (unsigned __int64 *) whiteningValues;
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned __int64 *dataUnitBufPtr;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	unsigned __int64 *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;
		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit
		// whitening values are stored in memory as a sequence of 64-bit integers in reverse order.
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				*whiteningValuesPtr64-- = *whiteningValuePtr64++;
				*whiteningValuesPtr64-- = *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;

#else
			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		dataUnitBufPtr = bufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		// Decrypt blocks in this data unit

		for (block = startBlock; block < endBlock; block++)
		{
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		DecipherBlocks (cipher, dataUnitBufPtr, ks, endBlock - startBlock);

		bufPtr = dataUnitBufPtr;
		whiteningValuesPtr64 = finalInt64WhiteningValuesPtr;

		for (block = startBlock; block < endBlock; block++)
		{
			*bufPtr++ ^= *whiteningValuesPtr64--;
			*bufPtr++ ^= *whiteningValuesPtr64--;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;

		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
	FAST_ERASE64 (whiteningValues, sizeof (whiteningValues));
}
Exemplo n.º 11
0
/*
 * Sends a KMS request via RPC and receives a response.
 * Parameters are raw (encrypted) reqeuests / responses.
 * Returns 0 on success.
 */
RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const kmsRequest, const size_t requestSize, BYTE **kmsResponse, size_t *const responseSize)
{
#define MAX_EXCESS_BYTES 16
	RPC_HEADER *RequestHeader, ResponseHeader;
	RPC_REQUEST64 *RpcRequest;
	RPC_RESPONSE64 _Response;
	int status;
	int_fast8_t useNdr64 = RpcFlags.HasNDR64 && UseClientRpcNDR64 && firstPacketSent;
	size_t size = sizeof(RPC_HEADER) + (useNdr64 ? sizeof(RPC_REQUEST64) : sizeof(RPC_REQUEST)) + requestSize;
	size_t responseSize2;

	*kmsResponse = NULL;

	BYTE *_Request = (BYTE*)vlmcsd_malloc(size);

	RequestHeader = (RPC_HEADER*)_Request;
	RpcRequest = (RPC_REQUEST64*)(_Request + sizeof(RPC_HEADER));

	createRpcHeader(RequestHeader, RPC_PT_REQUEST, (WORD)size);

	// Increment CallId for next Request
	CallId++;

	RpcRequest->Opnum = 0;

	if (useNdr64)
	{
		RpcRequest->ContextId = LE16(1); // We negotiate NDR64 always as context 1
		RpcRequest->AllocHint = LE32((DWORD)(requestSize + sizeof(RpcRequest->Ndr64)));
		RpcRequest->Ndr64.DataLength = LE64((uint64_t)requestSize);
		RpcRequest->Ndr64.DataSizeIs = LE64((uint64_t)requestSize);
		memcpy(RpcRequest->Ndr64.Data, kmsRequest, requestSize);
	}
	else
	{
		RpcRequest->ContextId = 0; // We negotiate NDR32 always as context 0
		RpcRequest->AllocHint = LE32((DWORD)(requestSize + sizeof(RpcRequest->Ndr)));
		RpcRequest->Ndr.DataLength = LE32((DWORD)requestSize);
		RpcRequest->Ndr.DataSizeIs = LE32((DWORD)requestSize);
		memcpy(RpcRequest->Ndr.Data, kmsRequest, requestSize);
	}

	for (;;)
	{
		int bytesread;

		if (!_send(sock, _Request, (int)size))
		{
			printerrorf("\nFatal: Could not send RPC request\n");
			status = RPC_S_COMM_FAILURE;
			break;
		}

		if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
		{
			printerrorf("\nFatal: No RPC response received from server\n");
			status = RPC_S_COMM_FAILURE;
			break;
		}

		if ((status = checkRpcResponseHeader(&ResponseHeader, RequestHeader, RPC_PT_RESPONSE, &printerrorf))) break;

		size = useNdr64 ? sizeof(RPC_RESPONSE64) : sizeof(RPC_RESPONSE);

		if (size > LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader))
			size = LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader);

		if (!_recv(sock, &_Response, (int)size))
		{
			printerrorf("\nFatal: RPC response is incomplete\n");
			status = RPC_S_COMM_FAILURE;
			break;
		}

		if (_Response.CancelCount != 0)
		{
			printerrorf("\nFatal: RPC response cancel count is not 0\n");
			status = RPC_S_CALL_CANCELLED;
			break;
		}

		if (_Response.ContextId != (useNdr64 ? LE16(1) : 0))
		{
			printerrorf("\nFatal: RPC response context id %u is not bound\n", (unsigned int)LE16(_Response.ContextId));
			status = RPC_X_SS_CONTEXT_DAMAGED;
			break;
		}

		int_fast8_t sizesMatch;

		if (useNdr64)
		{
			*responseSize = (size_t)LE64(_Response.Ndr64.DataLength);
			responseSize2 = (size_t)LE64(_Response.Ndr64.DataSizeIs);

			if (/*!*responseSize ||*/ !_Response.Ndr64.DataSizeMax)
			{
				status = (int)LE32(_Response.Ndr64.status);
				break;
			}

			sizesMatch = (size_t)LE64(_Response.Ndr64.DataLength) == responseSize2;
		}
		else
		{
			*responseSize = (size_t)LE32(_Response.Ndr.DataLength);
			responseSize2 = (size_t)LE32(_Response.Ndr.DataSizeIs);

			if (/*!*responseSize ||*/ !_Response.Ndr.DataSizeMax)
			{
				status = (int)LE32(_Response.Ndr.status);
				break;
			}

			sizesMatch = (size_t)LE32(_Response.Ndr.DataLength) == responseSize2;
		}

		if (!sizesMatch)
		{
			printerrorf("\nFatal: NDR data length (%u) does not match NDR data size (%u)\n",
				(uint32_t)*responseSize,
				(uint32_t)LE32(_Response.Ndr.DataSizeIs)
			);

			status = RPC_S_PROTOCOL_ERROR;
			break;
		}

		*kmsResponse = (BYTE*)vlmcsd_malloc(*responseSize + MAX_EXCESS_BYTES);

		// If RPC stub is too short, assume missing bytes are zero (same ill behavior as MS RPC)
		memset(*kmsResponse, 0, *responseSize + MAX_EXCESS_BYTES);

		// Read up to 16 bytes more than bytes expected to detect faulty KMS emulators
		if ((bytesread = recv(sock, (char*)*kmsResponse, (int)(*responseSize) + MAX_EXCESS_BYTES, 0)) < (int)*responseSize)
		{
			printerrorf("\nFatal: No or incomplete KMS response received. Required %u bytes but only got %i\n",
				(uint32_t)*responseSize,
				(int32_t)(bytesread < 0 ? 0 : bytesread)
			);

			status = RPC_S_PROTOCOL_ERROR;
			break;
		}

		DWORD *pReturnCode;

		size_t len = *responseSize + (useNdr64 ? sizeof(_Response.Ndr64) : sizeof(_Response.Ndr)) + sizeof(*pReturnCode);
		size_t pad = ((~len & 3) + 1) & 3;

		if (len + pad != LE32(_Response.AllocHint))
		{
			printerrorf("\nWarning: RPC stub size is %u, should be %u (probably incorrect padding)\n", (uint32_t)LE32(_Response.AllocHint), (uint32_t)(len + pad));
		}
		else
		{
			size_t i;
			for (i = 0; i < pad; i++)
			{
				if (*(*kmsResponse + *responseSize + sizeof(*pReturnCode) + i))
				{
					printerrorf("\nWarning: RPC stub data not padded to zeros according to Microsoft standard\n");
					break;
				}
			}
		}

		pReturnCode = (DWORD*)(*kmsResponse + *responseSize + pad);
		status = LE32(UA32(pReturnCode));

		break;
	}

	free(_Request);
	firstPacketSent = TRUE;
	return status;
#undef MAX_EXCESS_BYTES
}
Exemplo n.º 12
0
static void CheckRpcRequest(const RPC_REQUEST64 *const Request, const unsigned int len, WORD* NdrCtx, WORD* Ndr64Ctx, WORD Ctx)
{
	uint_fast8_t kmsMajorVersion;
	uint32_t requestSize = Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64);

	if (len < requestSize)
	{
		logger("Fatal: RPC request (including header) must be at least %i bytes but is only %i bytes.\n",
			(int)(sizeof(RPC_HEADER) + requestSize),
			(int)(len + sizeof(RPC_HEADER))
		);

		return;
	}

	if (len < requestSize + sizeof(DWORD))
	{
		logger("Fatal: KMS Request too small to contain version info (less than 4 bytes).\n");
		return;
	}

	if (Ctx != *Ndr64Ctx)
		kmsMajorVersion = (uint_fast8_t)LE16(((WORD*)Request->Ndr.Data)[1]);
	else
		kmsMajorVersion = (uint_fast8_t)LE16(((WORD*)Request->Ndr64.Data)[1]);

	if (kmsMajorVersion > 6)
	{
		logger("Fatal: KMSv%u is not supported.\n", (unsigned int)kmsMajorVersion);
	}
	else
	{
		if (len > _Versions[kmsMajorVersion - 4].RequestSize + requestSize)
			logger("Warning: %u excess bytes in RPC request.\n",
				len - (_Versions[kmsMajorVersion - 4].RequestSize + requestSize)
			);
	}

	if (Ctx != *Ndr64Ctx && Ctx != *NdrCtx)
	{
		if (*Ndr64Ctx == RPC_INVALID_CTX)
		{
			logger("Warning: Context id should be %u but is %u.\n", (unsigned int)*NdrCtx, Ctx);
		}
		else
		{
			logger("Warning: Context id should be %u (NDR32) or %u (NDR64) but is %u.\n",
				(unsigned int)*NdrCtx,
				(unsigned int)*Ndr64Ctx,
				Ctx
			);
		}
	}

	if (Request->Opnum)
		logger("Warning: OpNum should be 0 but is %u.\n",
		(unsigned int)LE16(Request->Opnum)
		);

	if (LE32(Request->AllocHint) != len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr))
		logger("Warning: Allocation hint should be %u but is %u.\n",
			len + sizeof(Request->Ndr),
			LE32(Request->AllocHint)
		);

	if (Ctx != *Ndr64Ctx)
	{
		if (LE32(Request->Ndr.DataLength) != len - sizeof(RPC_REQUEST))
			logger("Warning: NDR32 data length field should be %u but is %u.\n",
				len - sizeof(RPC_REQUEST),
				LE32(Request->Ndr.DataLength)
			);

		if (LE32(Request->Ndr.DataSizeIs) != len - sizeof(RPC_REQUEST))
			logger("Warning: NDR32 data size field should be %u but is %u.\n",
				len - sizeof(RPC_REQUEST),
				LE32(Request->Ndr.DataSizeIs)
			);
	}
	else
	{
		if (LE64(Request->Ndr64.DataLength) != len - sizeof(RPC_REQUEST64))
			logger("Warning: NDR32 data length field should be %u but is %u.\n",
				len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr),
				LE64(Request->Ndr64.DataLength)
			);

		if (LE64(Request->Ndr64.DataSizeIs) != len - sizeof(RPC_REQUEST64))
			logger("Warning: NDR32 data size field should be %u but is %u.\n",
				len - sizeof(RPC_REQUEST64),
				LE64(Request->Ndr64.DataSizeIs)
			);
	}
}
Exemplo n.º 13
0
/*
 * Handles the actual KMS request from the client.
 * Calls KMS functions (CreateResponseV4 or CreateResponseV6) in kms.c
 * Returns size of the KMS response packet or 0 on failure.
 *
 * The RPC packet size (excluding header) is actually in Response->AllocHint
 */
static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const Response, const DWORD RpcAssocGroup_unused, const SOCKET sock_unused, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE isValid, const char* const ipstr)
{
	int ResponseSize; // <0 = Errorcode (HRESULT)
	BYTE* requestData;
	BYTE* responseData;
	BYTE* pRpcReturnCode;
	int len;

#	ifndef SIMPLE_RPC

	WORD Ctx = LE16(Request->ContextId);

	if (Ctx == *NdrCtx)
	{
		requestData = (BYTE*)&Request->Ndr.Data;
		responseData = (BYTE*)&Response->Ndr.Data;
	}
	else if (Ctx == *Ndr64Ctx)
	{
		requestData = (BYTE*)&Request->Ndr64.Data;
		responseData = (BYTE*)&Response->Ndr64.Data;
	}
	else
	{
		return SendError(Response, RPC_NCA_UNK_IF);
	}

#	else // SIMPLE_RPC

	requestData = (BYTE*)&Request->Ndr.Data;
	responseData = (BYTE*)&Response->Ndr.Data;

#	endif // SIMPLE_RPC

	ResponseSize = 0x8007000D; // Invalid Data

	if (isValid)
	{
		uint16_t majorIndex = LE16(((WORD*)requestData)[1]) - 4;
		if (!((ResponseSize = _Versions[majorIndex].CreateResponse(requestData, responseData, ipstr)))) ResponseSize = 0x8007000D;
	}

#	ifndef SIMPLE_RPC

	if (Ctx != *Ndr64Ctx)
	{

#	endif // !SIMPLE_RPC
		if (ResponseSize < 0)
		{
			Response->Ndr.DataSizeMax = Response->Ndr.DataLength = 0;
			len = sizeof(Response->Ndr) - sizeof(Response->Ndr.DataSizeIs);
		}
		else
		{
			Response->Ndr.DataSizeMax = LE32(0x00020000);
			Response->Ndr.DataLength = Response->Ndr.DataSizeIs = LE32(ResponseSize);
			len = ResponseSize + sizeof(Response->Ndr);
		}

#	ifndef SIMPLE_RPC

	}
	else
	{
		if (ResponseSize < 0)
		{
			Response->Ndr64.DataSizeMax = Response->Ndr64.DataLength = 0;
			len = sizeof(Response->Ndr64) - sizeof(Response->Ndr64.DataSizeIs);
		}
		else
		{
			Response->Ndr64.DataSizeMax = LE64(0x00020000ULL);
			Response->Ndr64.DataLength = Response->Ndr64.DataSizeIs = LE64((uint64_t)ResponseSize);
			len = ResponseSize + sizeof(Response->Ndr64);
		}
	}

#	endif // !SIMPLE_RPC

	pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
	UA32(pRpcReturnCode) = ResponseSize < 0 ? LE32(ResponseSize) : 0;
	len += sizeof(DWORD);

	// Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
	int pad = ((~len & 3) + 1) & 3;
	memset(pRpcReturnCode + sizeof(DWORD), 0, pad);
	len += pad;

	Response->AllocHint = LE32(len);
	Response->ContextId = Request->ContextId;

	*((WORD*)&Response->CancelCount) = 0; // CancelCount + Pad1

	return len + 8;
}
Exemplo n.º 14
0
static void EncryptBufferXTS8Byte(unsigned __int8 *buffer,
						GST_LARGEST_COMPILER_UINT length,
						const UINT64_STRUCT *startDataUnitNo,
						unsigned int startCipherBlockNo,
						unsigned __int8 *ks,
						unsigned __int8 *ks2,
						int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK_SMALL];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK_SMALL];
	unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *)whiteningValue;
	unsigned __int32 *bufPtr = (unsigned __int32 *)buffer;
	unsigned __int32 startBlock = startCipherBlockNo, endBlock, block;
	GST_LARGEST_COMPILER_UINT blockCount, dataUnitNo;
	unsigned __int8 xor_ks[MAX_EXPANDED_KEY];

	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = (unsigned __int64) LE64(dataUnitNo);

	if (length % BYTES_PER_XTS_BLOCK_SMALL)
		GST_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK_SMALL;

	memcpy(xor_ks, ks, CipherGetKeyScheduleSize(cipher));

	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT_SMALL)
			endBlock = startBlock + (unsigned __int32) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT_SMALL;

		whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;

		//Generate first whitening value
		*whiteningValuePtr32 = *((unsigned __int32 *) byteBufUnitNo);
		*(whiteningValuePtr32+1) = *((unsigned __int32 *) byteBufUnitNo+1);
		EncipherBlock (cipher, whiteningValue, ks2);

		//XOR ks with the current DataUnitNo
		XorKeySchedule(cipher, ks, xor_ks, byteBufUnitNo, 8);

		//Generate subsequent whitening values for blocks
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				//Pre-whitening
				*bufPtr++ ^= *whiteningValuePtr32++;
				*bufPtr-- ^= *whiteningValuePtr32--;

				//Actual encryption
				EncipherBlock(cipher, bufPtr, xor_ks);

				//Post-whitening
				*bufPtr++ ^= *whiteningValuePtr32++;
				*bufPtr++ ^= *whiteningValuePtr32;
			}
			else
				whiteningValuePtr32++;

			//Derive the next whitening value
#if BYTE_ORDER == LITTLE_ENDIAN

			//Little-endian platforms
			finalCarry = (*whiteningValuePtr32 & 0x80000000) ? 135 : 0;

			*whiteningValuePtr32-- <<= 1;

			if (*whiteningValuePtr32 & 0x80000000)
				*(whiteningValuePtr32 + 1) |= 1;

			*whiteningValuePtr32 <<= 1;
#else
			//Big-endian platforms
			finalCarry = (*whiteningValuePtr32 & 0x80) ? 135 : 0;

			*whiteningValuePtr32 = LE32 (LE32 (*whiteningValuePtr32) << 1);

			whiteningValuePtr32--;

			if (*whiteningValuePtr32 & 0x80)
				*(whiteningValuePtr32 + 1) |= 0x01000000;

			*whiteningValuePtr32 = LE32 (LE32 (*whiteningValuePtr32) << 1);
#endif
			whiteningValue[0] ^= finalCarry;
		}
		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;
		*((unsigned __int64 *) byteBufUnitNo) = (unsigned __int64) LE64 (dataUnitNo);
	}
	FAST_ERASE32(whiteningValue, sizeof(whiteningValue));
}
Exemplo n.º 15
0
int
salsa20_init(salsa20_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
	 uchar_t *nonce, int enc)
{
	struct timespec tp;
	uint64_t tv;
	uchar_t num[25];
	uchar_t IV[32];
	uchar_t *key = ctx->pkey;

#ifndef	_USE_PBK
	int logN;
	uint32_t r, p;
	uint64_t N;

	if (XSALSA20_CRYPTO_NONCEBYTES % 8) {
		log_msg(LOG_ERR, 0, "XSALSA20_CRYPTO_NONCEBYTES is not a multiple of 8!\n");
		return (-1);
	}
	pickparams(&logN, &r, &p);
	N = (uint64_t)(1) << logN;
	if (crypto_scrypt(pwd, pwd_len, salt, saltlen, N, r, p, key, ctx->keylen)) {
		log_msg(LOG_ERR, 0, "Scrypt failed\n");
		return (-1);
	}
#else
	rv = PKCS5_PBKDF2_HMAC(pwd, pwd_len, salt, saltlen, PBE_ROUNDS, EVP_sha256(),
			       ctx->keylen, key);
	if (rv != ctx->keylen) {
		log_msg(LOG_ERR, 0, "Key size is %d bytes - should be %d bits\n", i, ctx->keylen);
		return (-1);
	}
#endif

	/*
	 * Copy the key. XSalsa20 core cipher always uses a 256-bit key. If we are using a
	 * 128-bit key then the key value is repeated twice to form a 256-bit value.
	 * This approach is based on the Salsa20 code submitted to eSTREAM. See the function
	 * ECRYPT_keysetup() in the Salsa20 submission:
	 * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/ref/salsa20.c?rev=161&view=auto
	 * 
	 * The input values corresponding to a 256-bit key contain repeated values if key
	 * length is 128-bit.
	 */
	memcpy(ctx->key, key, ctx->keylen);
	if (ctx->keylen < XSALSA20_CRYPTO_KEYBYTES) {
		uchar_t *k;
		k = ctx->key + ctx->keylen;
		memcpy(k, key, XSALSA20_CRYPTO_KEYBYTES - ctx->keylen);
	}

	if (enc) {
		int i;
		uint64_t *n, *n1;

		// Derive 192-bit nonce
		if (RAND_status() != 1 || RAND_bytes(IV, XSALSA20_CRYPTO_NONCEBYTES) != 1) {
			if (geturandom_bytes(IV, XSALSA20_CRYPTO_NONCEBYTES) != 0) {
				if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
					time((time_t *)&tv);
				} else {
					tv = tp.tv_sec * 1000UL + tp.tv_nsec;
				}
				sprintf((char *)num, "%" PRIu64, tv);
				PKCS5_PBKDF2_HMAC((const char *)num, strlen((char *)num), salt,
						saltlen, PBE_ROUNDS, EVP_sha256(), 32, IV);
			}
		}
		n = (uint64_t *)IV;
		n1 = (uint64_t *)(ctx->nonce);
		for (i = 0; i < XSALSA20_CRYPTO_NONCEBYTES/8; i++) {
			*n1 = LE64(*n);
			n++;
			n1++;
		}

		// Nullify stack components
		memset(num, 0, 25);
		memset(IV, 0, 32);
		memset(&tp, 0, sizeof (tp));
		tv = 0;
	} else {
		memcpy(ctx->nonce, nonce, XSALSA20_CRYPTO_NONCEBYTES);
		memset(nonce, 0, XSALSA20_CRYPTO_NONCEBYTES);
	}
	return (0);
}