|
Packit |
13e0ca |
/*
|
|
Packit |
13e0ca |
* FreeSec: libcrypt for NetBSD
|
|
Packit |
13e0ca |
*
|
|
Packit |
13e0ca |
* Copyright (c) 1994 David Burren
|
|
Packit |
13e0ca |
* All rights reserved.
|
|
Packit |
13e0ca |
*
|
|
Packit |
13e0ca |
* Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet
|
|
Packit |
13e0ca |
* this file should now *only* export crypt(), in order to make
|
|
Packit |
13e0ca |
* binaries of libcrypt exportable from the USA
|
|
Packit |
13e0ca |
*
|
|
Packit |
13e0ca |
* Adapted for FreeBSD-4.0 by Mark R V Murray
|
|
Packit |
13e0ca |
* this file should now *only* export crypt_des(), in order to make
|
|
Packit |
13e0ca |
* a module that can be optionally included in libcrypt.
|
|
Packit |
13e0ca |
*
|
|
Packit |
13e0ca |
* Adapted for libxcrypt by Zack Weinberg, 2017
|
|
Packit |
13e0ca |
* see notes in des.c
|
|
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 |
* 3. Neither the name of the author nor the names of other contributors
|
|
Packit |
13e0ca |
* may be used to endorse or promote products derived from this software
|
|
Packit |
13e0ca |
* without specific prior written permission.
|
|
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 |
* This is an original implementation of the DES and the crypt(3) interfaces
|
|
Packit |
13e0ca |
* by David Burren <davidb@werj.com.au>.
|
|
Packit |
13e0ca |
*/
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#include "crypt-port.h"
|
|
Packit |
13e0ca |
#include "crypt-private.h"
|
|
Packit |
13e0ca |
#include "alg-des.h"
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#include <errno.h>
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#if INCLUDE_des || INCLUDE_des_xbsd || INCLUDE_des_big
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#define DES_TRD_OUTPUT_LEN 14 /* SShhhhhhhhhhh0 */
|
|
Packit |
13e0ca |
#define DES_EXT_OUTPUT_LEN 21 /* _CCCCSSSShhhhhhhhhhh0 */
|
|
Packit |
13e0ca |
#define DES_BIG_OUTPUT_LEN ((16*11) + 2 + 1) /* SS (hhhhhhhhhhh){1,16} 0 */
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#define DES_MAX_OUTPUT_LEN \
|
|
Packit |
13e0ca |
MAX (DES_TRD_OUTPUT_LEN, MAX (DES_EXT_OUTPUT_LEN, DES_BIG_OUTPUT_LEN))
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
static_assert (DES_MAX_OUTPUT_LEN <= CRYPT_OUTPUT_SIZE,
|
|
Packit |
13e0ca |
"CRYPT_OUTPUT_SIZE is too small for DES");
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* A des_buffer holds all of the sensitive intermediate data used by
|
|
Packit |
13e0ca |
crypt_des_*. */
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
struct des_buffer
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
struct des_ctx ctx;
|
|
Packit |
13e0ca |
uint8_t keybuf[8];
|
|
Packit |
13e0ca |
uint8_t pkbuf[8];
|
|
Packit |
13e0ca |
};
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
static_assert (sizeof (struct des_buffer) <= ALG_SPECIFIC_SIZE,
|
|
Packit |
13e0ca |
"ALG_SPECIFIC_SIZE is too small for DES");
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
static const uint8_t ascii64[] =
|
|
Packit |
13e0ca |
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
Packit |
13e0ca |
/* 0000000000111111111122222222223333333333444444444455555555556666 */
|
|
Packit |
13e0ca |
/* 0123456789012345678901234567890123456789012345678901234567890123 */
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
static inline int
|
|
Packit |
13e0ca |
ascii_to_bin(char ch)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
if (ch > 'z')
|
|
Packit |
13e0ca |
return -1;
|
|
Packit |
13e0ca |
if (ch >= 'a')
|
|
Packit |
13e0ca |
return ch - 'a' + 38;
|
|
Packit |
13e0ca |
if (ch > 'Z')
|
|
Packit |
13e0ca |
return -1;
|
|
Packit |
13e0ca |
if (ch >= 'A')
|
|
Packit |
13e0ca |
return ch - 'A' + 12;
|
|
Packit |
13e0ca |
if (ch > '9')
|
|
Packit |
13e0ca |
return -1;
|
|
Packit |
13e0ca |
if (ch >= '.')
|
|
Packit |
13e0ca |
return ch - '.';
|
|
Packit |
13e0ca |
return -1;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Generate an 11-character DES password hash into the buffer at
|
|
Packit |
13e0ca |
OUTPUT, and nul-terminate it. The salt and key have already been
|
|
Packit |
13e0ca |
set. The plaintext is 64 bits of zeroes, and the raw ciphertext is
|
|
Packit |
13e0ca |
written to cbuf[]. */
|
|
Packit |
13e0ca |
static void
|
|
Packit |
13e0ca |
des_gen_hash (struct des_ctx *ctx, uint32_t count, uint8_t *output,
|
|
Packit |
13e0ca |
uint8_t cbuf[8])
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
uint8_t plaintext[8];
|
|
Packit |
13e0ca |
XCRYPT_SECURE_MEMSET (plaintext, 8);
|
|
Packit |
13e0ca |
des_crypt_block (ctx, cbuf, plaintext, count, false);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Now encode the result. */
|
|
Packit |
13e0ca |
const uint8_t *sptr = cbuf;
|
|
Packit |
13e0ca |
const uint8_t *end = sptr + 8;
|
|
Packit |
13e0ca |
unsigned int c1, c2;
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
do
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
c1 = *sptr++;
|
|
Packit |
13e0ca |
*output++ = ascii64[c1 >> 2];
|
|
Packit |
13e0ca |
c1 = (c1 & 0x03) << 4;
|
|
Packit |
13e0ca |
if (sptr >= end)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
*output++ = ascii64[c1];
|
|
Packit |
13e0ca |
break;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
c2 = *sptr++;
|
|
Packit |
13e0ca |
c1 |= c2 >> 4;
|
|
Packit |
13e0ca |
*output++ = ascii64[c1];
|
|
Packit |
13e0ca |
c1 = (c2 & 0x0f) << 2;
|
|
Packit |
13e0ca |
if (sptr >= end)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
*output++ = ascii64[c1];
|
|
Packit |
13e0ca |
break;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
c2 = *sptr++;
|
|
Packit |
13e0ca |
c1 |= c2 >> 6;
|
|
Packit |
13e0ca |
*output++ = ascii64[c1];
|
|
Packit |
13e0ca |
*output++ = ascii64[c2 & 0x3f];
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
while (sptr < end);
|
|
Packit |
13e0ca |
*output = '\0';
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
#endif
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#if INCLUDE_des
|
|
Packit |
13e0ca |
/* The original UNIX DES-based password hash, no extensions. */
|
|
Packit |
13e0ca |
void
|
|
Packit |
13e0ca |
crypt_des_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 |
/* This shouldn't ever happen, but... */
|
|
Packit |
13e0ca |
if (out_size < DES_TRD_OUTPUT_LEN || scr_size < sizeof (struct des_buffer))
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = ERANGE;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
struct des_buffer *buf = scratch;
|
|
Packit |
13e0ca |
struct des_ctx *ctx = &buf->ctx;
|
|
Packit |
13e0ca |
uint32_t salt = 0;
|
|
Packit |
13e0ca |
uint8_t *keybuf = buf->keybuf, *pkbuf = buf->pkbuf;
|
|
Packit |
13e0ca |
uint8_t *cp = output;
|
|
Packit |
13e0ca |
int i;
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* "old"-style: setting - 2 bytes of salt, phrase - up to 8 characters.
|
|
Packit |
13e0ca |
Note: ascii_to_bin maps all byte values outside the ascii64
|
|
Packit |
13e0ca |
alphabet to -1. Do not read past the end of the string. */
|
|
Packit |
13e0ca |
i = ascii_to_bin (setting[0]);
|
|
Packit |
13e0ca |
if (i < 0)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
salt = (unsigned int)i;
|
|
Packit |
13e0ca |
i = ascii_to_bin (setting[1]);
|
|
Packit |
13e0ca |
if (i < 0)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
salt |= ((unsigned int)i << 6);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Write the canonical form of the salt to the output buffer. We do
|
|
Packit |
13e0ca |
this instead of copying from the setting because the setting
|
|
Packit |
13e0ca |
might be catastrophically malformed (e.g. a 0- or 1-byte string;
|
|
Packit |
13e0ca |
this could plausibly happen if e.g. login(8) doesn't special-case
|
|
Packit |
13e0ca |
"*" or "!" in the password database). */
|
|
Packit |
13e0ca |
*cp++ = ascii64[salt & 0x3f];
|
|
Packit |
13e0ca |
*cp++ = ascii64[(salt >> 6) & 0x3f];
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Copy the first 8 characters of the password into keybuf, shifting
|
|
Packit |
13e0ca |
each character up by 1 bit and padding on the right with zeroes. */
|
|
Packit |
13e0ca |
for (i = 0; i < 8; i++)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
keybuf[i] = (uint8_t)(*phrase << 1);
|
|
Packit |
13e0ca |
if (*phrase)
|
|
Packit |
13e0ca |
phrase++;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
des_set_key (ctx, keybuf);
|
|
Packit |
13e0ca |
des_set_salt (ctx, salt);
|
|
Packit |
13e0ca |
des_gen_hash (ctx, 25, cp, pkbuf);
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
#endif
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#if INCLUDE_des_big
|
|
Packit |
13e0ca |
/* This algorithm is algorithm 0 (default) shipped with the C2 secure
|
|
Packit |
13e0ca |
implementation of Digital UNIX.
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
Disclaimer: This work is not based on the source code to Digital
|
|
Packit |
13e0ca |
UNIX, nor am I (Andy Phillips) connected to Digital Equipment Corp,
|
|
Packit |
13e0ca |
in any way other than as a customer. This code is based on
|
|
Packit |
13e0ca |
published interfaces and reasonable guesswork.
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
Description: The cleartext is divided into blocks of 8 characters
|
|
Packit |
13e0ca |
or less. Each block is encrypted using the standard UNIX libc crypt
|
|
Packit |
13e0ca |
function. The result of the encryption for one block provides the
|
|
Packit |
13e0ca |
salt for the suceeding block. The output is simply the
|
|
Packit |
13e0ca |
concatenation of all the blocks. Up to 16 blocks are supported
|
|
Packit |
13e0ca |
(that is, the password can be no more than 128 characters long).
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
Andy Phillips <atp@mssl.ucl.ac.uk> */
|
|
Packit |
13e0ca |
void
|
|
Packit |
13e0ca |
crypt_des_big_rn (const char *phrase, size_t phr_size,
|
|
Packit |
13e0ca |
const char *setting, size_t set_size,
|
|
Packit |
13e0ca |
uint8_t *output, size_t out_size,
|
|
Packit |
13e0ca |
void *scratch, size_t scr_size)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
#if INCLUDE_des
|
|
Packit |
13e0ca |
/* For backward compatibility, if the setting string is short enough
|
|
Packit |
13e0ca |
to have been generated by the traditional DES algorithm, forward
|
|
Packit |
13e0ca |
to traditional DES (which means that only the first 8 characters
|
|
Packit |
13e0ca |
of 'phrase' are significant). */
|
|
Packit |
13e0ca |
if (strlen (setting) <= 13)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
crypt_des_rn (phrase, phr_size, setting, set_size,
|
|
Packit |
13e0ca |
output, out_size, scratch, scr_size);
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
#endif
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* This shouldn't ever happen, but... */
|
|
Packit |
13e0ca |
if (out_size < DES_BIG_OUTPUT_LEN || scr_size < sizeof (struct des_buffer))
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = ERANGE;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
struct des_buffer *buf = scratch;
|
|
Packit |
13e0ca |
struct des_ctx *ctx = &buf->ctx;
|
|
Packit |
13e0ca |
uint32_t salt = 0;
|
|
Packit |
13e0ca |
uint8_t *keybuf = buf->keybuf, *pkbuf = buf->pkbuf;
|
|
Packit |
13e0ca |
uint8_t *cp = output;
|
|
Packit |
13e0ca |
int i, seg;
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* The setting string is exactly the same as for a traditional DES
|
|
Packit |
13e0ca |
hash. */
|
|
Packit |
13e0ca |
i = ascii_to_bin (setting[0]);
|
|
Packit |
13e0ca |
if (i < 0)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
salt = (unsigned int)i;
|
|
Packit |
13e0ca |
i = ascii_to_bin (setting[1]);
|
|
Packit |
13e0ca |
if (i < 0)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
salt |= ((unsigned int)i << 6);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
*cp++ = ascii64[salt & 0x3f];
|
|
Packit |
13e0ca |
*cp++ = ascii64[(salt >> 6) & 0x3f];
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
for (seg = 0; seg < 16; seg++)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
/* Copy and shift each block as for the traditional DES. */
|
|
Packit |
13e0ca |
for (i = 0; i < 8; i++)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
keybuf[i] = (uint8_t)(*phrase << 1);
|
|
Packit |
13e0ca |
if (*phrase)
|
|
Packit |
13e0ca |
phrase++;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
des_set_key (ctx, keybuf);
|
|
Packit |
13e0ca |
des_set_salt (ctx, salt);
|
|
Packit |
13e0ca |
des_gen_hash (ctx, 25, cp, pkbuf);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
if (*phrase == 0)
|
|
Packit |
13e0ca |
break;
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* change the salt (1st 2 chars of previous block) - this was found
|
|
Packit |
13e0ca |
by dowsing - no need to check for invalid characters here */
|
|
Packit |
13e0ca |
salt = (unsigned int)ascii_to_bin ((char)cp[0]);
|
|
Packit |
13e0ca |
salt |= (unsigned int)ascii_to_bin ((char)cp[1]) << 6;
|
|
Packit |
13e0ca |
cp += 11;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
#endif
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#if INCLUDE_des_xbsd
|
|
Packit |
13e0ca |
/* crypt_rn() entry point for BSD-style extended DES hashes. These
|
|
Packit |
13e0ca |
permit long passwords and have more salt and a controllable iteration
|
|
Packit |
13e0ca |
count, but are still unacceptably weak by modern standards. */
|
|
Packit |
13e0ca |
void
|
|
Packit |
13e0ca |
crypt_des_xbsd_rn (const char *phrase, size_t ARG_UNUSED (phr_size),
|
|
Packit |
13e0ca |
const char *setting, size_t set_size,
|
|
Packit |
13e0ca |
uint8_t *output, size_t out_size,
|
|
Packit |
13e0ca |
void *scratch, size_t scr_size)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
/* This shouldn't ever happen, but... */
|
|
Packit |
13e0ca |
if (out_size < DES_EXT_OUTPUT_LEN || scr_size < sizeof (struct des_buffer))
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = ERANGE;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* If this is true, this function shouldn't have been called.
|
|
Packit |
13e0ca |
Setting must be at least 9 bytes long, byte 10+ is ignored. */
|
|
Packit |
13e0ca |
if (*setting != '_' || set_size < 9)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
struct des_buffer *buf = scratch;
|
|
Packit |
13e0ca |
struct des_ctx *ctx = &buf->ctx;
|
|
Packit |
13e0ca |
uint32_t count = 0, salt = 0;
|
|
Packit |
13e0ca |
uint8_t *keybuf = buf->keybuf, *pkbuf = buf->pkbuf;
|
|
Packit |
13e0ca |
uint8_t *cp = output;
|
|
Packit |
13e0ca |
int i, x;
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* "new"-style DES hash:
|
|
Packit |
13e0ca |
setting - underscore, 4 bytes of count, 4 bytes of salt
|
|
Packit |
13e0ca |
phrase - unlimited characters
|
|
Packit |
13e0ca |
*/
|
|
Packit |
13e0ca |
for (i = 1; i < 5; i++)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
x = ascii_to_bin(setting[i]);
|
|
Packit |
13e0ca |
if (x < 0)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
count |= (unsigned int)x << ((i - 1) * 6);
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
for (i = 5; i < 9; i++)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
x = ascii_to_bin(setting[i]);
|
|
Packit |
13e0ca |
if (x < 0)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
salt |= (unsigned int)x << ((i - 5) * 6);
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
memcpy (cp, setting, 9);
|
|
Packit |
13e0ca |
cp += 9;
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Fold passwords longer than 8 bytes into a single DES key using a
|
|
Packit |
13e0ca |
procedure similar to a Merkle-Dåmgard hash construction. Each
|
|
Packit |
13e0ca |
block is shifted and padded, as for the traditional hash, then
|
|
Packit |
13e0ca |
XORed with the output of the previous round (IV all bits zero),
|
|
Packit |
13e0ca |
set as the DES key, and encrypted to produce the round output.
|
|
Packit |
13e0ca |
The salt is zero throughout this procedure. */
|
|
Packit |
13e0ca |
des_set_salt (ctx, 0);
|
|
Packit |
13e0ca |
XCRYPT_SECURE_MEMSET (pkbuf, 8);
|
|
Packit |
13e0ca |
for (;;)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
for (i = 0; i < 8; i++)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
keybuf[i] = (uint8_t)(pkbuf[i] ^ (*phrase << 1));
|
|
Packit |
13e0ca |
if (*phrase)
|
|
Packit |
13e0ca |
phrase++;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
des_set_key (ctx, keybuf);
|
|
Packit |
13e0ca |
if (*phrase == 0)
|
|
Packit |
13e0ca |
break;
|
|
Packit |
13e0ca |
des_crypt_block (ctx, pkbuf, keybuf, 1, false);
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Proceed as for the traditional DES hash. */
|
|
Packit |
13e0ca |
des_set_salt (ctx, salt);
|
|
Packit |
13e0ca |
des_gen_hash (ctx, count, cp, pkbuf);
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
#endif
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#if INCLUDE_des || INCLUDE_des_big
|
|
Packit |
13e0ca |
void
|
|
Packit |
13e0ca |
gensalt_des_rn (unsigned long count,
|
|
Packit |
13e0ca |
const uint8_t *rbytes, size_t nrbytes,
|
|
Packit |
13e0ca |
uint8_t *output, size_t output_size)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
if (output_size < 3)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = ERANGE;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
if (nrbytes < 2 || (count != 0 && count != 25))
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
output[0] = ascii64[(unsigned int) rbytes[0] & 0x3f];
|
|
Packit |
13e0ca |
output[1] = ascii64[(unsigned int) rbytes[1] & 0x3f];
|
|
Packit |
13e0ca |
output[2] = '\0';
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
#if INCLUDE_des_big
|
|
Packit |
13e0ca |
strong_alias (gensalt_des_rn, gensalt_des_big_rn);
|
|
Packit |
13e0ca |
#endif
|
|
Packit |
13e0ca |
#endif
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#if INCLUDE_des_xbsd
|
|
Packit |
13e0ca |
void
|
|
Packit |
13e0ca |
gensalt_des_xbsd_rn (unsigned long count,
|
|
Packit |
13e0ca |
const uint8_t *rbytes, size_t nrbytes,
|
|
Packit |
13e0ca |
uint8_t *output, size_t output_size)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
if (output_size < 1 + 4 + 4 + 1)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = ERANGE;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
if (count == 0)
|
|
Packit |
13e0ca |
count = 725;
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Even iteration counts make it easier to detect weak DES keys from a look
|
|
Packit |
13e0ca |
at the hash, so they should be avoided. */
|
|
Packit |
13e0ca |
if (nrbytes < 3 || count > 0xffffff || count % 2 == 0)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
unsigned long value =
|
|
Packit |
13e0ca |
((unsigned long) (unsigned char) rbytes[0] << 0) |
|
|
Packit |
13e0ca |
((unsigned long) (unsigned char) rbytes[1] << 8) |
|
|
Packit |
13e0ca |
((unsigned long) (unsigned char) rbytes[2] << 16);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
output[0] = '_';
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
output[1] = ascii64[(count >> 0) & 0x3f];
|
|
Packit |
13e0ca |
output[2] = ascii64[(count >> 6) & 0x3f];
|
|
Packit |
13e0ca |
output[3] = ascii64[(count >> 12) & 0x3f];
|
|
Packit |
13e0ca |
output[4] = ascii64[(count >> 18) & 0x3f];
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
output[5] = ascii64[(value >> 0) & 0x3f];
|
|
Packit |
13e0ca |
output[6] = ascii64[(value >> 6) & 0x3f];
|
|
Packit |
13e0ca |
output[7] = ascii64[(value >> 12) & 0x3f];
|
|
Packit |
13e0ca |
output[8] = ascii64[(value >> 18) & 0x3f];
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
output[9] = '\0';
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
#endif
|