bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#include "lib.h"
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#include "mycrypt.h"
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#include "password-scheme.h"
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi#include "crypt-blowfish.h"
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi#include "randgen.h"
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk/* Lengths and limits for some crypt() algorithms. */
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#define CRYPT_BLF_ROUNDS_DEFAULT 5
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#define CRYPT_BLF_ROUNDS_MIN 4
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#define CRYPT_BLF_ROUNDS_MAX 31
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi#define CRYPT_BLF_SALT_LEN 16 /* raw salt */
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi#define CRYPT_BLF_PREFIX_LEN (7+22+1) /* $2.$nn$ + salt */
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi#define CRYPT_BLF_BUFFER_LEN 128
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi#define CRYPT_BLF_PREFIX "$2y"
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#define CRYPT_SHA2_ROUNDS_DEFAULT 5000
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#define CRYPT_SHA2_ROUNDS_MIN 1000
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#define CRYPT_SHA2_ROUNDS_MAX 999999999
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk#define CRYPT_SHA2_SALT_LEN 16
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainenstatic void
605c40c77fc3851cb2845da1c5319e32c791592aSergey Kitovcrypt_generate_des(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen const unsigned char **raw_password_r, size_t *size_r)
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen{
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen#define CRYPT_SALT_LEN 2
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen const char *password, *salt;
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen salt = password_generate_salt(CRYPT_SALT_LEN);
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen password = t_strdup(mycrypt(plaintext, salt));
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen *raw_password_r = (const unsigned char *)password;
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen *size_r = strlen(password);
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen}
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volkstatic void
58d21a174d971834cfcd6d363349222749a54650Aki Tuomicrypt_generate_blowfish(const char *plaintext, const struct password_generate_params *params,
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const unsigned char **raw_password_r, size_t *size_r)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk{
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi char salt[CRYPT_BLF_SALT_LEN];
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi char password[CRYPT_BLF_BUFFER_LEN];
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi char magic_salt[CRYPT_BLF_PREFIX_LEN];
605c40c77fc3851cb2845da1c5319e32c791592aSergey Kitov unsigned int rounds = params->rounds;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk if (rounds == 0)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_BLF_ROUNDS_DEFAULT;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else if (rounds < CRYPT_BLF_ROUNDS_MIN)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_BLF_ROUNDS_MIN;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else if (rounds > CRYPT_BLF_ROUNDS_MAX)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_BLF_ROUNDS_MAX;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi random_fill(salt, CRYPT_BLF_SALT_LEN);
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi if (crypt_gensalt_blowfish_rn(CRYPT_BLF_PREFIX, rounds,
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi salt, CRYPT_BLF_SALT_LEN,
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi magic_salt, CRYPT_BLF_PREFIX_LEN) == NULL)
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi i_fatal("crypt_gensalt_blowfish_rn failed: %m");
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi if (crypt_blowfish_rn(plaintext, magic_salt, password,
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi CRYPT_BLF_BUFFER_LEN) == NULL)
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi i_fatal("crypt_blowfish_rn failed: %m");
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi *raw_password_r = (const unsigned char *)t_strdup(password);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk *size_r = strlen(password);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk}
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomistatic int
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomicrypt_verify_blowfish(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi const unsigned char *raw_password, size_t size,
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi const char **error_r)
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi{
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi const char *password;
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi const char *salt;
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi char crypted[CRYPT_BLF_BUFFER_LEN];
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi if (size == 0) {
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi /* the default mycrypt() handler would return match */
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi return 0;
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi }
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi password = t_strndup(raw_password, size);
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi if (size < CRYPT_BLF_PREFIX_LEN ||
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi strncmp(password, "$2", 2) != 0 ||
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi password[2] < 'a' || password[2] > 'z' ||
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi password[3] != '$') {
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi *error_r = "Password is not blowfish password";
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi return -1;
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi }
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi salt = t_strndup(password, CRYPT_BLF_PREFIX_LEN);
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi if (crypt_blowfish_rn(plaintext, salt, crypted, CRYPT_BLF_BUFFER_LEN) == NULL) {
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi /* really shouldn't happen unless the system is broken */
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi *error_r = t_strdup_printf("crypt_blowfish_rn failed: %m");
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi return -1;
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi }
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi return strcmp(crypted, password) == 0 ? 1 : 0;
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi}
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volkstatic void
605c40c77fc3851cb2845da1c5319e32c791592aSergey Kitovcrypt_generate_sha256(const char *plaintext, const struct password_generate_params *params,
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const unsigned char **raw_password_r, size_t *size_r)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk{
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const char *password, *salt, *magic_salt;
605c40c77fc3851cb2845da1c5319e32c791592aSergey Kitov unsigned int rounds = params->rounds;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk if (rounds == 0)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_SHA2_ROUNDS_DEFAULT;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else if (rounds < CRYPT_SHA2_ROUNDS_MIN)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_SHA2_ROUNDS_MIN;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else if (rounds > CRYPT_SHA2_ROUNDS_MAX)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_SHA2_ROUNDS_MAX;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk salt = password_generate_salt(CRYPT_SHA2_SALT_LEN);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk if (rounds == CRYPT_SHA2_ROUNDS_DEFAULT)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk magic_salt = t_strdup_printf("$5$%s", salt);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk magic_salt = t_strdup_printf("$5$rounds=%u$%s", rounds, salt);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk password = t_strdup(mycrypt(plaintext, magic_salt));
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk *raw_password_r = (const unsigned char *)password;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk *size_r = strlen(password);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk}
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volkstatic void
605c40c77fc3851cb2845da1c5319e32c791592aSergey Kitovcrypt_generate_sha512(const char *plaintext, const struct password_generate_params *params,
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const unsigned char **raw_password_r, size_t *size_r)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk{
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const char *password, *salt, *magic_salt;
605c40c77fc3851cb2845da1c5319e32c791592aSergey Kitov unsigned int rounds = params->rounds;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk if (rounds == 0)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_SHA2_ROUNDS_DEFAULT;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else if (rounds < CRYPT_SHA2_ROUNDS_MIN)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_SHA2_ROUNDS_MIN;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else if (rounds > CRYPT_SHA2_ROUNDS_MAX)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk rounds = CRYPT_SHA2_ROUNDS_MAX;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk salt = password_generate_salt(CRYPT_SHA2_SALT_LEN);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk if (rounds == CRYPT_SHA2_ROUNDS_DEFAULT)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk magic_salt = t_strdup_printf("$6$%s", salt);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk else
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk magic_salt = t_strdup_printf("$6$rounds=%u$%s", rounds, salt);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk password = t_strdup(mycrypt(plaintext, magic_salt));
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk *raw_password_r = (const unsigned char *)password;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk *size_r = strlen(password);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk}
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk/* keep in sync with the crypt_schemes struct below */
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volkstatic const struct {
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const char *key;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const char *salt;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const char *expected;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk} sample[] = {
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen { "08/15!test~4711", "JB", "JBOZ0DgmtucwE" },
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk { "08/15!test~4711", "$5$rounds=1000$0123456789abcdef",
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk "$5$rounds=1000$0123456789abcdef$K/DksR0DT01hGc8g/kt"
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk "9McEgrbFMKi9qrb1jehe7hn4" },
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk { "08/15!test~4711", "$6$rounds=1000$0123456789abcdef",
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk "$6$rounds=1000$0123456789abcdef$ZIAd5WqfyLkpvsVCVUU1GrvqaZTq"
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk "vhJoouxdSqJO71l9Ld3tVrfOatEjarhghvEYADkq//LpDnTeO90tcbtHR1" }
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk};
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk/* keep in sync with the sample struct above */
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volkstatic const struct password_scheme crypt_schemes[] = {
cfb22f2f9b28d5888ba00ad910e47c9a490ca673Aki Tuomi { "DES-CRYPT", PW_ENCODING_NONE, 0, crypt_verify,
54a1b3574acab5f778843f7f1e04d2d26d61a852Timo Sirainen crypt_generate_des },
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk { "SHA256-CRYPT", PW_ENCODING_NONE, 0, crypt_verify,
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk crypt_generate_sha256 },
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk { "SHA512-CRYPT", PW_ENCODING_NONE, 0, crypt_verify,
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk crypt_generate_sha512 }
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk};
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomistatic const struct password_scheme blf_crypt_scheme = {
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi "BLF-CRYPT", PW_ENCODING_NONE, 0, crypt_verify_blowfish,
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi crypt_generate_blowfish
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi};
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi
cfb22f2f9b28d5888ba00ad910e47c9a490ca673Aki Tuomistatic const struct password_scheme default_crypt_scheme = {
cfb22f2f9b28d5888ba00ad910e47c9a490ca673Aki Tuomi "CRYPT", PW_ENCODING_NONE, 0, crypt_verify,
4bed0c5f99c1ed3ebe409796275a234b56a413fdAki Tuomi crypt_generate_blowfish
cfb22f2f9b28d5888ba00ad910e47c9a490ca673Aki Tuomi};
cfb22f2f9b28d5888ba00ad910e47c9a490ca673Aki Tuomi
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volkvoid password_scheme_register_crypt(void)
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk{
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk unsigned int i;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk const char *crypted;
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk
c6d1318ff2db67719a803bada0323b38a078c98bAki Tuomi i_assert(N_ELEMENTS(crypt_schemes) == N_ELEMENTS(sample));
c6d1318ff2db67719a803bada0323b38a078c98bAki Tuomi
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk for (i = 0; i < N_ELEMENTS(crypt_schemes); i++) {
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk crypted = mycrypt(sample[i].key, sample[i].salt);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk if (crypted != NULL &&
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk (strcmp(crypted, sample[i].expected) == 0))
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk password_scheme_register(&crypt_schemes[i]);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk }
1ebb6094e5105ba7ef521a0177c42d3ea81243f0Aki Tuomi password_scheme_register(&blf_crypt_scheme);
cfb22f2f9b28d5888ba00ad910e47c9a490ca673Aki Tuomi password_scheme_register(&default_crypt_scheme);
42fb278a57f1c6d7d5d0c7bd2318edb721dc0ec0Pascal Volk}