(root)/
libxcrypt-4.4.36/
lib/
crypt-nthash.c
       1  /*-
       2   * Copyright (c) 1998-1999 Whistle Communications, Inc.
       3   * Copyright (c) 1998-1999 Archie Cobbs <archie@freebsd.org>
       4   * Copyright (c) 2003 Michael Bretterklieber
       5   * Copyright (c) 2017-2019 Björn Esser <besser82@fedoraproject.org>
       6   * Copyright (c) 2017-2019 Zack Weinberg <zackw at panix.com>
       7   * All rights reserved.
       8   *
       9   * Redistribution and use in source and binary forms, with or without
      10   * modification, are permitted provided that the following conditions
      11   * are met:
      12   * 1. Redistributions of source code must retain the above copyright
      13   *    notice, this list of conditions and the following disclaimer.
      14   * 2. Redistributions in binary form must reproduce the above copyright
      15   *    notice, this list of conditions and the following disclaimer in the
      16   *    documentation and/or other materials provided with the distribution.
      17   *
      18   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      19   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      20   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      21   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      22   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      23   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      24   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      25   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      26   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      27   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      28   * SUCH DAMAGE.
      29   */
      30  
      31  #include "crypt-port.h"
      32  
      33  #if INCLUDE_nt
      34  
      35  #include "alg-md4.h"
      36  
      37  #include <errno.h>
      38  #include <stdlib.h>
      39  
      40  #define MD4_HASHLEN        16
      41  
      42  typedef struct
      43  {
      44    MD4_CTX ctx;
      45    uint8_t unipw[CRYPT_MAX_PASSPHRASE_SIZE * 2];
      46    unsigned char hash[MD4_HASHLEN];
      47  } crypt_nt_internal_t;
      48  
      49  static_assert (sizeof (crypt_nt_internal_t) <= ALG_SPECIFIC_SIZE,
      50                 "ALG_SPECIFIC_SIZE is too small for NTHASH.");
      51  
      52  /*
      53   * NT HASH = md4(str2unicode(phrase))
      54   */
      55  
      56  void
      57  crypt_nt_rn (const char *phrase, size_t phr_size,
      58               const char *setting, size_t ARG_UNUSED (set_size),
      59               uint8_t *output, size_t out_size,
      60               void *scratch, size_t scr_size)
      61  {
      62    static const char *magic = "$3$";
      63    static const uint8_t *hexconvtab = (const uint8_t*) "0123456789abcdef";
      64  
      65    if ((out_size < strlen (magic) + MD4_HASHLEN * 2 + 1) ||
      66        (scr_size < sizeof (crypt_nt_internal_t)))
      67      {
      68        errno = ERANGE;
      69        return;
      70      }
      71  
      72    if (strncmp (setting, magic, strlen (magic)))
      73      {
      74        errno = EINVAL;
      75        return;
      76      }
      77  
      78    crypt_nt_internal_t *intbuf = scratch;
      79  
      80    /* Convert the input to UCS-2LE, blindly assuming that it was
      81       IANA ISO_8859-1:1987 to begin with (i.e. 0x00 .. 0xFF
      82       encode U+0000 .. U+FFFF; technically this is a superset
      83       of the original ISO 8859.1).  Note that this does not
      84       U+0000-terminate intbuf->unipw.  */
      85    for (size_t i = 0; i < phr_size; i++)
      86      {
      87        intbuf->unipw[2*i    ] = (uint8_t)phrase[i];
      88        intbuf->unipw[2*i + 1] = 0x00;
      89      }
      90  
      91    /* Compute MD4 of Unicode password.  */
      92    MD4_Init (&intbuf->ctx);
      93    MD4_Update (&intbuf->ctx, intbuf->unipw, phr_size * 2);
      94    MD4_Final (intbuf->hash, &intbuf->ctx);
      95  
      96    /* Write the computed hash to the output buffer.  */
      97    output += strcpy_or_abort (output, out_size, magic);
      98    *output++ = '$';
      99    for (size_t i = 0; i < MD4_HASHLEN; i++)
     100      {
     101        *output++ = hexconvtab[intbuf->hash[i] >> 4];
     102        *output++ = hexconvtab[intbuf->hash[i] & 0xf];
     103      }
     104    *output = '\0';
     105  }
     106  
     107  /* This function simply returns the magic string '$3$',
     108     so it can be used as SETTING for the crypt function.  */
     109  void
     110  gensalt_nt_rn (unsigned long count,
     111                 ARG_UNUSED(const uint8_t *rbytes),
     112                 ARG_UNUSED(size_t nrbytes),
     113                 uint8_t *output,
     114                 size_t o_size)
     115  {
     116    const char *prefix = "$3$";
     117  
     118    /* Minimal O_SIZE to store the prefix.  */
     119    if (o_size < strlen (prefix) + 1)
     120      {
     121        errno = ERANGE;
     122        return;
     123      }
     124  
     125    if (count != 0)
     126      {
     127        errno = EINVAL;
     128        return;
     129      }
     130  
     131    strcpy_or_abort (output, o_size, prefix);
     132  }
     133  
     134  #endif