/* * FreeSec: libcrypt for NetBSD * * Copyright (c) 1994 David Burren * All rights reserved. * * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet * this file should now *only* export crypt(), in order to make * binaries of libcrypt exportable from the USA * * Adapted for FreeBSD-4.0 by Mark R V Murray * this file should now *only* export crypt_des(), in order to make * a module that can be optionally included in libcrypt. * * Adapted for libxcrypt by Zack Weinberg, 2017 * see notes in des.c * * Adapted for libxcrypt by Björn Esser, 2019 * add function-stubs simply setting error to ENOSYS. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of other contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This is an original implementation of the DES and the crypt(3) interfaces * by David Burren . */ /* Obsolete DES symmetric cipher API - not to be used in new code. */ #include "crypt-port.h" #include "crypt-obsolete.h" #include "alg-des.h" #include #if (INCLUDE_encrypt || INCLUDE_encrypt_r || INCLUDE_setkey || INCLUDE_setkey_r) && \ !ENABLE_OBSOLETE_API_ENOSYS static_assert(sizeof (struct des_ctx) + alignof (struct des_ctx) <= CRYPT_DATA_INTERNAL_SIZE, "crypt_data.internal is too small for struct des_ctx"); /* struct crypt_data is allocated by application code and contains only char-typed fields, so its 'internal' field may not be sufficiently aligned. */ static inline struct des_ctx * get_des_ctx (struct crypt_data *data) { uintptr_t internalp = (uintptr_t) data->internal; const uintptr_t align = alignof (struct des_ctx); internalp = (internalp + align - 1) & ~(align - 1); return (struct des_ctx *)internalp; } /* For reasons lost in the mists of time, these functions operate on 64-*byte* arrays, each of which should be either 0 or 1 - only the low bit of each byte is examined. The DES primitives, much more sensibly, operate on 8-byte/64-*bit* arrays. */ static void unpack_bits (char bytev[64], const unsigned char bitv[8]) { unsigned char c; for (int i = 0; i < 8; i++) { c = bitv[i]; for (int j = 0; j < 8; j++) bytev[i*8 + j] = (c & (0x01 << (7 - j))) != 0; } } static void pack_bits (unsigned char bitv[8], const char bytev[64]) { unsigned int c; for (int i = 0; i < 8; i++) { c = 0; for (int j = 0; j < 8; j++) { c <<= 1; c |= ((unsigned char)bytev[i*8 + j] & 0x01u); } bitv[i] = (unsigned char)c; } } #endif /* Initialize DATA with a DES key, KEY, represented as a byte vector. */ #if (INCLUDE_setkey_r || INCLUDE_setkey) && !ENABLE_OBSOLETE_API_ENOSYS static void do_setkey_r (const char *key, struct des_ctx *ctx) { XCRYPT_SECURE_MEMSET (ctx, sizeof (struct des_ctx)); des_set_salt (ctx, 0); unsigned char bkey[8]; pack_bits (bkey, key); des_set_key (ctx, bkey); } #endif #if INCLUDE_setkey_r void setkey_r (ARG_UNUSED (const char *key), ARG_UNUSED (struct crypt_data *data)) { #if ENABLE_OBSOLETE_API_ENOSYS /* This function is not supported in this configuration. */ errno = ENOSYS; #else do_setkey_r (key, get_des_ctx (data)); #endif } SYMVER_setkey_r; #endif /* Encrypt or decrypt one DES block, BLOCK, using the key schedule in DATA. BLOCK is processed in place. */ #if (INCLUDE_encrypt_r || INCLUDE_encrypt) && !ENABLE_OBSOLETE_API_ENOSYS static void do_encrypt_r (char *block, int edflag, struct des_ctx *ctx) { unsigned char bin[8], bout[8]; pack_bits (bin, block); des_crypt_block (ctx, bout, bin, 1, edflag != 0); unpack_bits (block, bout); } #endif #if INCLUDE_encrypt_r void encrypt_r (char *block, ARG_UNUSED (int edflag), ARG_UNUSED (struct crypt_data *data)) { #if ENABLE_OBSOLETE_API_ENOSYS /* Make sure sensitive data is erased in case case get_random_bytes() fails. */ XCRYPT_SECURE_MEMSET(block, 64); /* Overwrite sensitive data with random data. */ get_random_bytes(block, 64); /* This function is not supported in this configuration. */ errno = ENOSYS; #else do_encrypt_r (block, edflag, get_des_ctx (data)); #endif } SYMVER_encrypt_r; #endif /* Even-more-deprecated-than-the-above nonreentrant versions. These use a separate state object from the main library's nonreentrant crypt(). Unlike with crypt() vs crypt_r(), these do not get their own file because they're not compiled into the static library anyway. */ #if (INCLUDE_setkey || INCLUDE_encrypt) && !ENABLE_OBSOLETE_API_ENOSYS static struct des_ctx nr_encrypt_ctx; #endif #if INCLUDE_setkey void setkey (ARG_UNUSED (const char *key)) { #if ENABLE_OBSOLETE_API_ENOSYS /* This function is not supported in this configuration. */ errno = ENOSYS; #else do_setkey_r (key, &nr_encrypt_ctx); #endif } SYMVER_setkey; #endif #if INCLUDE_encrypt void encrypt (char *block, ARG_UNUSED (int edflag)) { #if ENABLE_OBSOLETE_API_ENOSYS /* Make sure sensitive data is erased in case case get_random_bytes() fails. */ XCRYPT_SECURE_MEMSET(block, 64); /* Overwrite sensitive data with random data. */ get_random_bytes(block, 64); /* This function is not supported in this configuration. */ errno = ENOSYS; #else do_encrypt_r (block, edflag, &nr_encrypt_ctx); #endif } SYMVER_encrypt; #endif