Blame crypt-nthash.c

Packit 13e0ca
/*-
Packit 13e0ca
 * Copyright (c) 2003 Michael Bretterklieber
Packit 13e0ca
 * All rights reserved.
Packit 13e0ca
 *
Packit 13e0ca
 * Redistribution and use in source and binary forms, with or without
Packit 13e0ca
 * modification, are permitted provided that the following conditions
Packit 13e0ca
 * are met:
Packit 13e0ca
 * 1. Redistributions of source code must retain the above copyright
Packit 13e0ca
 *    notice, this list of conditions and the following disclaimer.
Packit 13e0ca
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 13e0ca
 *    notice, this list of conditions and the following disclaimer in the
Packit 13e0ca
 *    documentation and/or other materials provided with the distribution.
Packit 13e0ca
 *
Packit 13e0ca
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
Packit 13e0ca
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 13e0ca
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 13e0ca
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
Packit 13e0ca
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 13e0ca
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 13e0ca
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 13e0ca
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 13e0ca
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 13e0ca
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 13e0ca
 * SUCH DAMAGE.
Packit 13e0ca
 *
Packit 13e0ca
 * The bogus 'gensalt_nthash_rn' function and all modifications to the other
Packit 13e0ca
 * parts of this file are
Packit 13e0ca
 *
Packit 13e0ca
 * Copyright (c) 2017 Björn Esser <besser82@fedoraproject.org>
Packit 13e0ca
 * All rights reserved.
Packit 13e0ca
 *
Packit 13e0ca
 * and is provided under the same licensing terms and conditions as the
Packit 13e0ca
 * other parts of this file.
Packit 13e0ca
 */
Packit 13e0ca
Packit 13e0ca
#include "crypt-port.h"
Packit 13e0ca
#include "alg-md4.h"
Packit 13e0ca
#include "crypt-private.h"
Packit 13e0ca
Packit 13e0ca
#include <errno.h>
Packit 13e0ca
#include <stdio.h>
Packit 13e0ca
#include <stdlib.h>
Packit 13e0ca
#include <netinet/in.h>
Packit 13e0ca
Packit 13e0ca
#if INCLUDE_nthash
Packit 13e0ca
Packit 13e0ca
/*
Packit 13e0ca
 * NT HASH = md4(str2unicode(phrase))
Packit 13e0ca
 */
Packit 13e0ca
Packit 13e0ca
void
Packit 13e0ca
crypt_nthash_rn (const char *phrase, size_t ARG_UNUSED (phr_size),
Packit 13e0ca
                 const char *setting, size_t ARG_UNUSED (set_size),
Packit 13e0ca
                 uint8_t *output, size_t out_size,
Packit 13e0ca
                 void *scratch, size_t scr_size)
Packit 13e0ca
{
Packit 13e0ca
  size_t unipwLen;
Packit 13e0ca
  int i;
Packit 13e0ca
  static const char hexconvtab[] = "0123456789abcdef";
Packit 13e0ca
  static const char *magic = "$3$";
Packit 13e0ca
  uint16_t unipw[128];
Packit 13e0ca
  unsigned char hash[16];
Packit 13e0ca
  const char *s;
Packit 13e0ca
  struct md4_ctx *ctx = scratch;
Packit 13e0ca
Packit 13e0ca
  if ((out_size < 4 + 32) ||
Packit 13e0ca
      (scr_size < sizeof (struct md4_ctx)))
Packit 13e0ca
    {
Packit 13e0ca
      errno = ERANGE;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  if (strncmp (setting, magic, strlen (magic)))
Packit 13e0ca
    {
Packit 13e0ca
      errno = EINVAL;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  XCRYPT_SECURE_MEMSET (unipw, sizeof unipw);
Packit 13e0ca
  /* convert to unicode (thanx Archie) */
Packit 13e0ca
  unipwLen = 0;
Packit 13e0ca
  for (s = phrase; unipwLen < sizeof(unipw) / 2 && *s; s++)
Packit 13e0ca
    unipw[unipwLen++] = htons((uint16_t)(*s << 8));
Packit 13e0ca
Packit 13e0ca
  /* Compute MD4 of Unicode password */
Packit 13e0ca
  md4_init_ctx (ctx);
Packit 13e0ca
  md4_process_bytes ((unsigned char *)unipw, ctx, unipwLen*sizeof(uint16_t));
Packit 13e0ca
  md4_finish_ctx (ctx, hash);
Packit 13e0ca
Packit 13e0ca
  output = (uint8_t *)stpcpy ((char *)output, magic);
Packit 13e0ca
  *output++ = '$';
Packit 13e0ca
  for (i = 0; i < 16; i++)
Packit 13e0ca
    {
Packit 13e0ca
      *output++ = (uint8_t)hexconvtab[hash[i] >> 4];
Packit 13e0ca
      *output++ = (uint8_t)hexconvtab[hash[i] & 0xf];
Packit 13e0ca
    }
Packit 13e0ca
  *output = '\0';
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
/* This function does not return any valid salt,
Packit 13e0ca
   since the NTHASH crypt function simply ignores
Packit 13e0ca
   any setting passed to it.  Anyways, the string
Packit 13e0ca
   returned in OUTPUT will start with the correct
Packit 13e0ca
   magic string '$3$', so it can be used as
Packit 13e0ca
   SETTING for the crypt function.  */
Packit 13e0ca
void
Packit 13e0ca
gensalt_nthash_rn (unsigned long count,
Packit 13e0ca
                   const uint8_t *rbytes,
Packit 13e0ca
                   size_t nrbytes,
Packit 13e0ca
                   uint8_t *output,
Packit 13e0ca
                   size_t o_size)
Packit 13e0ca
{
Packit 13e0ca
  static const char *salt = "$3$__not_used__";
Packit 13e0ca
  struct md4_ctx ctx;
Packit 13e0ca
  unsigned char hashbuf[16];
Packit 13e0ca
  char hashstr[14 + 1];
Packit 13e0ca
  unsigned long i;
Packit 13e0ca
Packit 13e0ca
  /* Minimal O_SIZE to store the fake salt.
Packit 13e0ca
     At least 1 byte of RBYTES is needed
Packit 13e0ca
     to calculate the MD4 hash used in the
Packit 13e0ca
     fake salt.  */
Packit 13e0ca
  if ((o_size < 29) || (nrbytes < 1))
Packit 13e0ca
    {
Packit 13e0ca
      errno = ERANGE;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  if (count < 20)
Packit 13e0ca
    count = 20;
Packit 13e0ca
Packit 13e0ca
  md4_init_ctx (&ctx;;
Packit 13e0ca
  for (i = 0; i < count; i++)
Packit 13e0ca
    {
Packit 13e0ca
      md4_process_bytes (salt, &ctx, (i % 15) + 1);
Packit 13e0ca
      md4_process_bytes (rbytes, &ctx, nrbytes);
Packit 13e0ca
      md4_process_bytes (salt, &ctx, 15);
Packit 13e0ca
      md4_process_bytes (salt, &ctx, 15 - (i % 15));
Packit 13e0ca
    }
Packit 13e0ca
  md4_finish_ctx (&ctx, &hashbuf);
Packit 13e0ca
Packit 13e0ca
  for (i = 0; i < 7; i++)
Packit 13e0ca
    sprintf (&(hashstr[i * 2]), "%02x", hashbuf[i]);
Packit 13e0ca
Packit 13e0ca
  memcpy (output, salt, 15);
Packit 13e0ca
  memcpy (output + 15, hashstr, 14);
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
#endif