Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:15

0001 /*-
0002  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
0003  *
0004  * Copyright (c) 2011 The FreeBSD Project. All rights reserved.
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0016  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0019  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0021  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0022  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0023  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0024  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0025  * SUCH DAMAGE.
0026  */
0027 
0028 /* Based on:
0029  * SHA256-based Unix crypt implementation. Released into the Public Domain by
0030  * Ulrich Drepper <drepper@redhat.com>. */
0031 
0032 #include <sys/cdefs.h>
0033 __FBSDID("$FreeBSD$");
0034 
0035 #include <sys/endian.h>
0036 #include <sys/param.h>
0037 
0038 #include <errno.h>
0039 #include <limits.h>
0040 #include <sha256.h>
0041 #include <stdbool.h>
0042 #include <stdint.h>
0043 #include <stdio.h>
0044 #include <stdlib.h>
0045 #include <string.h>
0046 
0047 #include <crypt.h>
0048 
0049 /* Define our magic string to mark salt for SHA256 "encryption" replacement. */
0050 static const char sha256_salt_prefix[] = "$5$";
0051 
0052 /* Prefix for optional rounds specification. */
0053 static const char sha256_rounds_prefix[] = "rounds=";
0054 
0055 /* Maximum salt string length. */
0056 #define SALT_LEN_MAX 16
0057 /* Default number of rounds if not explicitly specified. */
0058 #define ROUNDS_DEFAULT 5000
0059 /* Minimum number of rounds. */
0060 #define ROUNDS_MIN 1000
0061 /* Maximum number of rounds. */
0062 #define ROUNDS_MAX 999999999
0063 
0064 char *
0065 crypt_sha256_r(const char *key, const char *salt, struct crypt_data *data)
0066 {
0067     u_long srounds;
0068     int n;
0069     uint8_t alt_result[32], temp_result[32];
0070     SHA256_CTX ctx, alt_ctx;
0071     size_t salt_len, key_len, cnt, rounds;
0072     char *cp, *p_bytes, *s_bytes, *endp;
0073     const char *num;
0074     bool rounds_custom;
0075     char *buffer = &data->buffer[0];
0076     int buflen = (int)sizeof(data->buffer);
0077 
0078     /* Default number of rounds. */
0079     rounds = ROUNDS_DEFAULT;
0080     rounds_custom = false;
0081 
0082     /* Find beginning of salt string. The prefix should normally always
0083      * be present. Just in case it is not. */
0084     if (strncmp(sha256_salt_prefix, salt, sizeof(sha256_salt_prefix) - 1) == 0)
0085         /* Skip salt prefix. */
0086         salt += sizeof(sha256_salt_prefix) - 1;
0087 
0088     if (strncmp(salt, sha256_rounds_prefix, sizeof(sha256_rounds_prefix) - 1)
0089         == 0) {
0090         num = salt + sizeof(sha256_rounds_prefix) - 1;
0091         srounds = strtoul(num, &endp, 10);
0092 
0093         if (*endp == '$') {
0094             salt = endp + 1;
0095             rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
0096             rounds_custom = true;
0097         }
0098     }
0099 
0100     salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
0101     key_len = strlen(key);
0102 
0103     /* Prepare for the real work. */
0104     SHA256_Init(&ctx);
0105 
0106     /* Add the key string. */
0107     SHA256_Update(&ctx, key, key_len);
0108 
0109     /* The last part is the salt string. This must be at most 8
0110      * characters and it ends at the first `$' character (for
0111      * compatibility with existing implementations). */
0112     SHA256_Update(&ctx, salt, salt_len);
0113 
0114     /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The
0115      * final result will be added to the first context. */
0116     SHA256_Init(&alt_ctx);
0117 
0118     /* Add key. */
0119     SHA256_Update(&alt_ctx, key, key_len);
0120 
0121     /* Add salt. */
0122     SHA256_Update(&alt_ctx, salt, salt_len);
0123 
0124     /* Add key again. */
0125     SHA256_Update(&alt_ctx, key, key_len);
0126 
0127     /* Now get result of this (32 bytes) and add it to the other context. */
0128     SHA256_Final(alt_result, &alt_ctx);
0129 
0130     /* Add for any character in the key one byte of the alternate sum. */
0131     for (cnt = key_len; cnt > 32; cnt -= 32)
0132         SHA256_Update(&ctx, alt_result, 32);
0133     SHA256_Update(&ctx, alt_result, cnt);
0134 
0135     /* Take the binary representation of the length of the key and for
0136      * every 1 add the alternate sum, for every 0 the key. */
0137     for (cnt = key_len; cnt > 0; cnt >>= 1)
0138         if ((cnt & 1) != 0)
0139             SHA256_Update(&ctx, alt_result, 32);
0140         else
0141             SHA256_Update(&ctx, key, key_len);
0142 
0143     /* Create intermediate result. */
0144     SHA256_Final(alt_result, &ctx);
0145 
0146     /* Start computation of P byte sequence. */
0147     SHA256_Init(&alt_ctx);
0148 
0149     /* For every character in the password add the entire password. */
0150     for (cnt = 0; cnt < key_len; ++cnt)
0151         SHA256_Update(&alt_ctx, key, key_len);
0152 
0153     /* Finish the digest. */
0154     SHA256_Final(temp_result, &alt_ctx);
0155 
0156     /* Create byte sequence P. */
0157     cp = p_bytes = alloca(key_len);
0158     for (cnt = key_len; cnt >= 32; cnt -= 32) {
0159         memcpy(cp, temp_result, 32);
0160         cp += 32;
0161     }
0162     memcpy(cp, temp_result, cnt);
0163 
0164     /* Start computation of S byte sequence. */
0165     SHA256_Init(&alt_ctx);
0166 
0167     /* For every character in the password add the entire password. */
0168     for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
0169         SHA256_Update(&alt_ctx, salt, salt_len);
0170 
0171     /* Finish the digest. */
0172     SHA256_Final(temp_result, &alt_ctx);
0173 
0174     /* Create byte sequence S. */
0175     cp = s_bytes = alloca(salt_len);
0176     for (cnt = salt_len; cnt >= 32; cnt -= 32) {
0177         memcpy(cp, temp_result, 32);
0178         cp += 32;
0179     }
0180     memcpy(cp, temp_result, cnt);
0181 
0182     /* Repeatedly run the collected hash value through SHA256 to burn CPU
0183      * cycles. */
0184     for (cnt = 0; cnt < rounds; ++cnt) {
0185         /* New context. */
0186         SHA256_Init(&ctx);
0187 
0188         /* Add key or last result. */
0189         if ((cnt & 1) != 0)
0190             SHA256_Update(&ctx, p_bytes, key_len);
0191         else
0192             SHA256_Update(&ctx, alt_result, 32);
0193 
0194         /* Add salt for numbers not divisible by 3. */
0195         if (cnt % 3 != 0)
0196             SHA256_Update(&ctx, s_bytes, salt_len);
0197 
0198         /* Add key for numbers not divisible by 7. */
0199         if (cnt % 7 != 0)
0200             SHA256_Update(&ctx, p_bytes, key_len);
0201 
0202         /* Add key or last result. */
0203         if ((cnt & 1) != 0)
0204             SHA256_Update(&ctx, alt_result, 32);
0205         else
0206             SHA256_Update(&ctx, p_bytes, key_len);
0207 
0208         /* Create intermediate result. */
0209         SHA256_Final(alt_result, &ctx);
0210     }
0211 
0212     /* Now we can construct the result string. It consists of three
0213      * parts. */
0214     cp = stpncpy(buffer, sha256_salt_prefix, MAX(0, buflen));
0215     buflen -= sizeof(sha256_salt_prefix) - 1;
0216 
0217     if (rounds_custom) {
0218         n = snprintf(cp, MAX(0, buflen), "%s%zu$",
0219              sha256_rounds_prefix, rounds);
0220 
0221         cp += n;
0222         buflen -= n;
0223     }
0224 
0225     cp = stpncpy(cp, salt, MIN((size_t)MAX(0, buflen), salt_len));
0226     buflen -= MIN((size_t)MAX(0, buflen), salt_len);
0227 
0228     if (buflen > 0) {
0229         *cp++ = '$';
0230         --buflen;
0231     }
0232 
0233     b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4, &buflen, &cp);
0234     b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4, &buflen, &cp);
0235     b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4, &buflen, &cp);
0236     b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4, &buflen, &cp);
0237     b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4, &buflen, &cp);
0238     b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4, &buflen, &cp);
0239     b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4, &buflen, &cp);
0240     b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4, &buflen, &cp);
0241     b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4, &buflen, &cp);
0242     b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4, &buflen, &cp);
0243     b64_from_24bit(0, alt_result[31], alt_result[30], 3, &buflen, &cp);
0244     if (buflen <= 0) {
0245         errno = ERANGE;
0246         buffer = NULL;
0247     }
0248     else
0249         *cp = '\0'; /* Terminate the string. */
0250 
0251     /* Clear the buffer for the intermediate result so that people
0252      * attaching to processes or reading core dumps cannot get any
0253      * information. We do it in this way to clear correct_words[] inside
0254      * the SHA256 implementation as well. */
0255     SHA256_Init(&ctx);
0256     SHA256_Final(alt_result, &ctx);
0257     memset(temp_result, '\0', sizeof(temp_result));
0258     memset(p_bytes, '\0', key_len);
0259     memset(s_bytes, '\0', salt_len);
0260 
0261     return buffer;
0262 }
0263 
0264 struct crypt_format crypt_sha256_format =
0265     CRYPT_FORMAT_INITIALIZER(crypt_sha256_r, "$5$");