xref: /freebsd/lib/libcrypt/crypt.c (revision a2f733abcff64628b7771a47089628b7327a88bd)
15280a314SDag-Erling Smørgrav /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni  *
45280a314SDag-Erling Smørgrav  * Copyright (c) 1999 Mark Murray
55280a314SDag-Erling Smørgrav  * Copyright (c) 2014 Dag-Erling Smørgrav
65280a314SDag-Erling Smørgrav  * All rights reserved.
7e9a56ad5SMark Murray  *
8e9a56ad5SMark Murray  * Redistribution and use in source and binary forms, with or without
9e9a56ad5SMark Murray  * modification, are permitted provided that the following conditions
10e9a56ad5SMark Murray  * are met:
11e9a56ad5SMark Murray  * 1. Redistributions of source code must retain the above copyright
12e9a56ad5SMark Murray  *    notice, this list of conditions and the following disclaimer.
13e9a56ad5SMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14e9a56ad5SMark Murray  *    notice, this list of conditions and the following disclaimer in the
15e9a56ad5SMark Murray  *    documentation and/or other materials provided with the distribution.
16e9a56ad5SMark Murray  *
17e9a56ad5SMark Murray  * THIS SOFTWARE IS PROVIDED BY MARK MURRAY AND CONTRIBUTORS ``AS IS'' AND
18e9a56ad5SMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19e9a56ad5SMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20e9a56ad5SMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL MARK MURRAY OR CONTRIBUTORS BE LIABLE
21e9a56ad5SMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22e9a56ad5SMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23e9a56ad5SMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24e9a56ad5SMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25e9a56ad5SMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26e9a56ad5SMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27e9a56ad5SMark Murray  * SUCH DAMAGE.
28da5c7089SBrandon Gillespie  */
290e27b8d5SGeoff Rehmet 
309886bcdfSPeter Wemm #include <sys/types.h>
315280a314SDag-Erling Smørgrav 
325280a314SDag-Erling Smørgrav #include <string.h>
33f2ac424aSMark Murray #include <unistd.h>
345280a314SDag-Erling Smørgrav 
35e9a56ad5SMark Murray #include "crypt.h"
364fdd3d54SMark Murray 
375280a314SDag-Erling Smørgrav /*
38e4978d34SDag-Erling Smørgrav  * List of supported crypt(3) formats.
39e4978d34SDag-Erling Smørgrav  *
40e4978d34SDag-Erling Smørgrav  * The default algorithm is the last entry in the list (second-to-last
41e4978d34SDag-Erling Smørgrav  * array element since the last is a sentinel).  The reason for placing
42e4978d34SDag-Erling Smørgrav  * the default last rather than first is that DES needs to be at the
43e4978d34SDag-Erling Smørgrav  * bottom for the algorithm guessing logic in crypt(3) to work correctly,
44e4978d34SDag-Erling Smørgrav  * and it needs to be the default for backward compatibility.
455280a314SDag-Erling Smørgrav  */
465280a314SDag-Erling Smørgrav static const struct crypt_format {
475f521d7bSEd Schouten 	const char *name;
485f521d7bSEd Schouten 	int (*func)(const char *, const char *, char *);
495f521d7bSEd Schouten 	const char *magic;
505280a314SDag-Erling Smørgrav } crypt_formats[] = {
515280a314SDag-Erling Smørgrav 	{ "md5",	crypt_md5,		"$1$"	},
525c129616SMark Murray #ifdef HAS_BLOWFISH
535280a314SDag-Erling Smørgrav 	{ "blf",	crypt_blowfish,		"$2"	},
545c129616SMark Murray #endif
555280a314SDag-Erling Smørgrav 	{ "nth",	crypt_nthash,		"$3$"	},
565280a314SDag-Erling Smørgrav 	{ "sha256",	crypt_sha256,		"$5$"	},
57e4978d34SDag-Erling Smørgrav 	{ "sha512",	crypt_sha512,		"$6$"	},
585280a314SDag-Erling Smørgrav #ifdef HAS_DES
595280a314SDag-Erling Smørgrav 	{ "des",	crypt_des,		"_"	},
605280a314SDag-Erling Smørgrav #endif
615280a314SDag-Erling Smørgrav 
625280a314SDag-Erling Smørgrav 	/* sentinel */
635280a314SDag-Erling Smørgrav 	{ NULL,		NULL,			NULL	}
6404c9749fSBrian Feldman };
6504c9749fSBrian Feldman 
66e4978d34SDag-Erling Smørgrav static const struct crypt_format *crypt_format =
67e4978d34SDag-Erling Smørgrav     &crypt_formats[(sizeof crypt_formats / sizeof *crypt_formats) - 2];
68a0ee974fSDag-Erling Smørgrav 
695280a314SDag-Erling Smørgrav #define DES_SALT_ALPHABET \
705280a314SDag-Erling Smørgrav 	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
719886bcdfSPeter Wemm 
725280a314SDag-Erling Smørgrav /*
735280a314SDag-Erling Smørgrav  * Returns the name of the currently selected format.
745280a314SDag-Erling Smørgrav  */
7504c9749fSBrian Feldman const char *
crypt_get_format(void)769886bcdfSPeter Wemm crypt_get_format(void)
779886bcdfSPeter Wemm {
7804c9749fSBrian Feldman 
795280a314SDag-Erling Smørgrav 	return (crypt_format->name);
8004c9749fSBrian Feldman }
8104c9749fSBrian Feldman 
825280a314SDag-Erling Smørgrav /*
835280a314SDag-Erling Smørgrav  * Selects the format to use for subsequent crypt(3) invocations.
845280a314SDag-Erling Smørgrav  */
8504c9749fSBrian Feldman int
crypt_set_format(const char * format)865280a314SDag-Erling Smørgrav crypt_set_format(const char *format)
879886bcdfSPeter Wemm {
885280a314SDag-Erling Smørgrav 	const struct crypt_format *cf;
8904c9749fSBrian Feldman 
905280a314SDag-Erling Smørgrav 	for (cf = crypt_formats; cf->name != NULL; ++cf) {
915280a314SDag-Erling Smørgrav 		if (strcasecmp(cf->name, format) == 0) {
925280a314SDag-Erling Smørgrav 			crypt_format = cf;
9304c9749fSBrian Feldman 			return (1);
9404c9749fSBrian Feldman 		}
9504c9749fSBrian Feldman 	}
9604c9749fSBrian Feldman 	return (0);
9704c9749fSBrian Feldman }
9804c9749fSBrian Feldman 
995280a314SDag-Erling Smørgrav /*
1005280a314SDag-Erling Smørgrav  * Hash the given password with the given salt.  If the salt begins with a
1015280a314SDag-Erling Smørgrav  * magic string (e.g. "$6$" for sha512), the corresponding format is used;
1025280a314SDag-Erling Smørgrav  * otherwise, the currently selected format is used.
1035280a314SDag-Erling Smørgrav  */
1044fdd3d54SMark Murray char *
crypt_r(const char * passwd,const char * salt,struct crypt_data * data)1055f521d7bSEd Schouten crypt_r(const char *passwd, const char *salt, struct crypt_data *data)
1060e27b8d5SGeoff Rehmet {
1075280a314SDag-Erling Smørgrav 	const struct crypt_format *cf;
1085f521d7bSEd Schouten 	int (*func)(const char *, const char *, char *);
1090cb06892SHajimu UMEMOTO #ifdef HAS_DES
1100cb06892SHajimu UMEMOTO 	int len;
1110cb06892SHajimu UMEMOTO #endif
11204c9749fSBrian Feldman 
1135280a314SDag-Erling Smørgrav 	for (cf = crypt_formats; cf->name != NULL; ++cf)
1145f521d7bSEd Schouten 		if (cf->magic != NULL && strstr(salt, cf->magic) == salt) {
1155f521d7bSEd Schouten 			func = cf->func;
1165f521d7bSEd Schouten 			goto match;
1175f521d7bSEd Schouten 		}
1185280a314SDag-Erling Smørgrav #ifdef HAS_DES
1190cb06892SHajimu UMEMOTO 	len = strlen(salt);
1205f521d7bSEd Schouten 	if ((len == 13 || len == 2) && strspn(salt, DES_SALT_ALPHABET) == len) {
1215f521d7bSEd Schouten 		func = crypt_des;
1225f521d7bSEd Schouten 		goto match;
1235f521d7bSEd Schouten 	}
1245280a314SDag-Erling Smørgrav #endif
1255f521d7bSEd Schouten 	func = crypt_format->func;
1265f521d7bSEd Schouten match:
1275f521d7bSEd Schouten 	if (func(passwd, salt, data->__buf) != 0)
1285f521d7bSEd Schouten 		return (NULL);
1295f521d7bSEd Schouten 	return (data->__buf);
1305f521d7bSEd Schouten }
1315f521d7bSEd Schouten 
1325f521d7bSEd Schouten char *
crypt(const char * passwd,const char * salt)1335f521d7bSEd Schouten crypt(const char *passwd, const char *salt)
1345f521d7bSEd Schouten {
1355f521d7bSEd Schouten 	static struct crypt_data data;
1365f521d7bSEd Schouten 
1375f521d7bSEd Schouten 	return (crypt_r(passwd, salt, &data));
1380e27b8d5SGeoff Rehmet }
139