4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma weak _crypt = crypt
28 #pragma weak _encrypt = encrypt
29 #pragma weak _setkey = setkey
43 #include <sys/types.h>
54 #define CRYPT_ALGORITHMS_ALLOW "CRYPT_ALGORITHMS_ALLOW"
55 #define CRYPT_ALGORITHMS_DEPRECATE "CRYPT_ALGORITHMS_DEPRECATE"
56 #define CRYPT_DEFAULT "CRYPT_DEFAULT"
57 #define CRYPT_UNIX "__unix__"
59 #define CRYPT_CONFFILE "/etc/security/crypt.conf"
60 #define POLICY_CONF_FILE "/etc/security/policy.conf"
62 #define CRYPT_CONFLINELENGTH 1024
64 #define CRYPT_MODULE_ISA "/$ISA/"
66 #define CRYPT_MODULE_DIR "/usr/lib/security/64/"
67 #define CRYPT_ISA_DIR "/64/"
69 #define CRYPT_MODULE_DIR "/usr/lib/security/"
70 #define CRYPT_ISA_DIR "/"
76 * In practical terms this is probably never any bigger than about 10, but...
78 * It has to fix the encrypted password filed of struct spwd it is
79 * theoretically the maximum length of the cipher minus the magic $ sign.
80 * Though that would be unexpected.
81 * Since it also has to fit in crypt.conf it is CRYPT_CONFLINELENGTH
82 * minus the path to the module and the minimum white space.
84 * CRYPT_MAXCIPHERTEXTLEN is defined in crypt.h and is smaller than
85 * CRYPT_CONFLINELENGTH, and probably always will be.
87 #define MAX_ALGNAME_LEN (CRYPT_MAXCIPHERTEXTLEN - 1)
91 char *(*a_genhash
)(char *, const size_t, const char *,
92 const char *, const char **);
93 char *(*a_gensalt
)(char *, const size_t,
94 const char *, const struct passwd
*, const char **);
99 struct crypt_policy_s
{
105 enum crypt_policy_error_e
{
110 static struct crypt_policy_s
*getcryptpolicy(void);
111 static void free_crypt_policy(struct crypt_policy_s
*policy
);
112 static struct crypt_alg_s
*getalgbyname(const char *algname
, boolean_t
*found
);
113 static void free_crypt_alg(struct crypt_alg_s
*alg
);
114 static char *getalgfromsalt(const char *salt
);
115 static boolean_t
alg_valid(const char *algname
,
116 const struct crypt_policy_s
*policy
);
117 static char *isa_path(const char *path
);
119 static char *_unix_crypt(const char *pw
, const char *salt
, char *iobuf
);
120 static char *_unix_crypt_gensalt(char *gsbuffer
, size_t gsbufflen
,
121 const char *oldpuresalt
, const struct passwd
*userinfo
,
122 const char *params
[]);
126 * crypt - string encoding function
128 * This function encodes strings in a suitable for for secure storage
129 * as passwords. It generates the password hash given the plaintext and salt.
131 * If the first character of salt is "$" then we use crypt.conf(4) to
132 * determine which plugin to use and run the crypt_genhash_impl(3c) function
134 * Otherwise we use the old unix algorithm.
137 * On Success we return a pointer to the encoded string. The
138 * return value points to thread specific static data and should NOT
139 * be passed free(3c).
140 * On failure we return NULL and set errno to one of:
141 * EINVAL, ELIBACC, ENOMEM, ENOSYS.
144 crypt(const char *plaintext
, const char *salt
)
146 struct crypt_alg_s
*alg
;
152 ctbuffer
= tsdalloc(_T_CRYPT
, CRYPT_MAXCIPHERTEXTLEN
, NULL
);
153 if (ctbuffer
== NULL
)
155 bzero(ctbuffer
, CRYPT_MAXCIPHERTEXTLEN
);
158 * '$' is never a possible salt char with the traditional unix
159 * algorithm. If the salt passed in is NULL or the first char
160 * of the salt isn't a $ then do the traditional thing.
161 * We also do the traditional thing if the salt is only 1 char.
163 if (salt
== NULL
|| salt
[0] != '$' || strlen(salt
) == 1) {
164 return (_unix_crypt(plaintext
, salt
, ctbuffer
));
168 * Find the algorithm name from the salt and look it up in
169 * crypt.conf(4) to find out what shared object to use.
170 * If we can't find it in crypt.conf then getalgbyname would
171 * have returned with found = B_FALSE so we use the unix algorithm.
172 * If alg is NULL but found = B_TRUE then there is a problem with
173 * the plugin so we fail leaving errno set to what getalgbyname()
174 * set it to or EINVAL it if wasn't set.
176 if ((algname
= getalgfromsalt(salt
)) == NULL
) {
181 alg
= getalgbyname(algname
, &found
);
182 if ((alg
== NULL
) || !found
) {
188 ciphertext
= _unix_crypt(plaintext
, salt
, ctbuffer
);
190 ciphertext
= alg
->a_genhash(ctbuffer
, CRYPT_MAXCIPHERTEXTLEN
,
191 plaintext
, salt
, (const char **)alg
->a_params
);
202 * crypt_gensalt - generate salt string for string encoding
204 * This function generates the salt string pased to crypt(3c).
205 * If oldsalt is NULL, the use the default algorithm.
206 * Other wise check the policy in policy.conf to ensure that it is
207 * either still allowed or not deprecated.
210 * Return a pointer to the new salt, the caller is responsible
211 * for using free(3c) on the return value.
212 * Returns NULL on error and sets errno to one of:
213 * EINVAL, ELIBACC, ENOMEM
216 crypt_gensalt(const char *oldsalt
, const struct passwd
*userinfo
)
218 struct crypt_alg_s
*alg
= NULL
;
219 struct crypt_policy_s
*policy
= NULL
;
220 char *newsalt
= NULL
;
222 char *algname
= NULL
;
225 gsbuffer
= calloc(CRYPT_MAXCIPHERTEXTLEN
, sizeof (char *));
226 if (gsbuffer
== NULL
) {
231 policy
= getcryptpolicy();
232 if (policy
== NULL
) {
237 algname
= getalgfromsalt(oldsalt
);
238 if (!alg_valid(algname
, policy
)) {
240 algname
= strdup(policy
->cp_default
);
243 if (strcmp(algname
, CRYPT_UNIX
) == 0) {
244 newsalt
= _unix_crypt_gensalt(gsbuffer
, CRYPT_MAXCIPHERTEXTLEN
,
245 oldsalt
, userinfo
, NULL
);
248 alg
= getalgbyname(algname
, &found
);
249 if (alg
== NULL
|| !found
) {
254 newsalt
= alg
->a_gensalt(gsbuffer
, CRYPT_MAXCIPHERTEXTLEN
,
255 oldsalt
, userinfo
, (const char **)alg
->a_params
);
259 free_crypt_policy(policy
);
269 * ===========================================================================
270 * The remainder of this file contains internal interfaces for
271 * the implementation of crypt(3c) and crypt_gensalt(3c)
272 * ===========================================================================
277 * getalgfromsalt - extract the algorithm name from the salt string
280 getalgfromsalt(const char *salt
)
282 char algname
[CRYPT_MAXCIPHERTEXTLEN
];
286 if (salt
== NULL
|| strlen(salt
) > CRYPT_MAXCIPHERTEXTLEN
)
289 * Salts are in this format:
290 * $<algname>[,var=val,[var=val ...][$puresalt]$<ciphertext>
292 * The only bit we need to worry about here is extracting the
293 * name which is the string between the first "$" and the first
294 * of "," or second "$".
296 if (salt
[0] != '$') {
297 return (strdup(CRYPT_UNIX
));
302 while (salt
[i
] != '\0' && salt
[i
] != '$' && salt
[i
] != ',') {
303 algname
[j
] = salt
[i
];
312 return (strdup(algname
));
317 * log_invalid_policy - syslog helper
320 log_invalid_policy(enum crypt_policy_error_e error
, char *value
)
324 syslog(LOG_AUTH
| LOG_ERR
,
325 "crypt(3c): %s contains both %s and %s; only one may be "
326 "specified, using first entry in file.", POLICY_CONF_FILE
,
327 CRYPT_ALGORITHMS_ALLOW
, CRYPT_ALGORITHMS_DEPRECATE
);
330 syslog(LOG_AUTH
| LOG_ERR
,
331 "crypt(3c): %s contains multiple %s entries;"
332 "using first entry file.", POLICY_CONF_FILE
, value
);
338 getval(const char *ival
)
347 if ((tmp
= strchr(ival
, '=')) == NULL
)
350 oval
= strdup(tmp
+ 1); /* everything after the "=" */
353 off
= strlen(oval
) - 1;
358 if (oval
[off
] == '\n')
365 * getcryptpolicy - read /etc/security/policy.conf into a crypt_policy_s
367 static struct crypt_policy_s
*
372 struct crypt_policy_s
*policy
;
374 if ((pconf
= fopen(POLICY_CONF_FILE
, "rF")) == NULL
) {
378 policy
= malloc(sizeof (struct crypt_policy_s
));
379 if (policy
== NULL
) {
382 policy
->cp_default
= NULL
;
383 policy
->cp_allow
= NULL
;
384 policy
->cp_deny
= NULL
;
386 while (!feof(pconf
) &&
387 (fgets(line
, sizeof (line
), pconf
) != NULL
)) {
388 if (strncasecmp(CRYPT_DEFAULT
, line
,
389 strlen(CRYPT_DEFAULT
)) == 0) {
390 if (policy
->cp_default
!= NULL
) {
391 log_invalid_policy(CPE_MULTI
, CRYPT_DEFAULT
);
393 policy
->cp_default
= getval(line
);
396 if (strncasecmp(CRYPT_ALGORITHMS_ALLOW
, line
,
397 strlen(CRYPT_ALGORITHMS_ALLOW
)) == 0) {
398 if (policy
->cp_deny
!= NULL
) {
399 log_invalid_policy(CPE_BOTH
, NULL
);
400 } else if (policy
->cp_allow
!= NULL
) {
401 log_invalid_policy(CPE_MULTI
,
402 CRYPT_ALGORITHMS_ALLOW
);
404 policy
->cp_allow
= getval(line
);
407 if (strncasecmp(CRYPT_ALGORITHMS_DEPRECATE
, line
,
408 strlen(CRYPT_ALGORITHMS_DEPRECATE
)) == 0) {
409 if (policy
->cp_allow
!= NULL
) {
410 log_invalid_policy(CPE_BOTH
, NULL
);
411 } else if (policy
->cp_deny
!= NULL
) {
412 log_invalid_policy(CPE_MULTI
,
413 CRYPT_ALGORITHMS_DEPRECATE
);
415 policy
->cp_deny
= getval(line
);
419 (void) fclose(pconf
);
421 if (policy
->cp_default
== NULL
) {
422 policy
->cp_default
= strdup(CRYPT_UNIX
);
423 if (policy
->cp_default
== NULL
)
424 free_crypt_policy(policy
);
432 * alg_valid - is this algorithm valid given the policy ?
435 alg_valid(const char *algname
, const struct crypt_policy_s
*policy
)
440 boolean_t allowed
= B_FALSE
;
442 if ((algname
== NULL
) || (policy
== NULL
)) {
446 if (strcmp(algname
, policy
->cp_default
) == 0) {
450 if (policy
->cp_deny
!= NULL
) {
451 list
= policy
->cp_deny
;
453 } else if (policy
->cp_allow
!= NULL
) {
454 list
= policy
->cp_allow
;
458 * Neither of allow or deny policies are set so anything goes.
463 while ((entry
= strtok_r(NULL
, ",", &lasts
)) != NULL
) {
464 if (strcmp(entry
, algname
) == 0) {
473 * getalgbyname - read crypt.conf(4) looking for algname
476 * On error NULL and errno is set
477 * On success the alg details including an open handle to the lib
478 * If crypt.conf(4) is okay but algname doesn't exist in it then
479 * return NULL the caller should then use the default algorithm
482 static struct crypt_alg_s
*
483 getalgbyname(const char *algname
, boolean_t
*found
)
488 struct crypt_alg_s
*alg
= NULL
;
489 char line
[CRYPT_CONFLINELENGTH
];
492 char *pathname
= NULL
;
497 if ((algname
== NULL
) || (strcmp(algname
, CRYPT_UNIX
) == 0)) {
501 if ((configfd
= open(CRYPT_CONFFILE
, O_RDONLY
)) == -1) {
502 syslog(LOG_ALERT
, "crypt: open(%s) failed: %s",
503 CRYPT_CONFFILE
, strerror(errno
));
508 * Stat the file so we can check modes and ownerships
510 if (fstat(configfd
, &stb
) < 0) {
511 syslog(LOG_ALERT
, "crypt: stat(%s) failed: %s",
512 CRYPT_CONFFILE
, strerror(errno
));
517 * Check the ownership of the file
519 if (stb
.st_uid
!= (uid_t
)0) {
521 "crypt: Owner of %s is not root", CRYPT_CONFFILE
);
526 * Check the modes on the file
528 if (stb
.st_mode
& S_IWGRP
) {
530 "crypt: %s writable by group", CRYPT_CONFFILE
);
533 if (stb
.st_mode
& S_IWOTH
) {
535 "crypt: %s writable by world", CRYPT_CONFFILE
);
539 if ((fconf
= fdopen(configfd
, "rF")) == NULL
) {
540 syslog(LOG_ALERT
, "crypt: fdopen(%d) failed: %s",
541 configfd
, strerror(errno
));
546 * /etc/security/crypt.conf has 3 fields:
547 * <algname> <pathname> [<name[=val]>[<name[=val]>]]
551 ((fgets(line
, sizeof (line
), fconf
) != NULL
) && !feof(fconf
))) {
556 if ((line
[0] == '#') || (line
[0] == '\n')) {
560 linelen
= strlen(line
);
561 line
[--linelen
] = '\0'; /* chop the trailing \n */
563 token
= strtok_r(line
, " \t", &lasts
);
567 if (strcmp(token
, algname
) == 0) {
576 token
= strtok_r(NULL
, " \t", &lasts
);
581 syslog(LOG_ALERT
, "crypt(3c): %s may be corrupt at line %d",
582 CRYPT_CONFFILE
, lineno
);
588 if ((pathname
= isa_path(token
)) == NULL
) {
595 if ((alg
= malloc(sizeof (struct crypt_alg_s
))) == NULL
) {
599 alg
->a_libhandle
= NULL
;
600 alg
->a_genhash
= NULL
;
601 alg
->a_gensalt
= NULL
;
602 alg
->a_params
= NULL
;
606 * The rest of the line is module specific params, space
607 * seprated. We wait until after we have checked the module is
608 * valid before parsing them into a_params, this saves us
609 * having to free them later if there is a problem.
611 if ((alg
->a_libhandle
= dlopen(pathname
, RTLD_NOW
)) == NULL
) {
612 syslog(LOG_ERR
, "crypt(3c) unable to dlopen %s: %s",
613 pathname
, dlerror());
620 (char *(*)())dlsym(alg
->a_libhandle
, "crypt_genhash_impl");
621 if (alg
->a_genhash
== NULL
) {
622 syslog(LOG_ERR
, "crypt(3c) unable to find cryp_genhash_impl"
623 "symbol in %s: %s", pathname
, dlerror());
629 (char *(*)())dlsym(alg
->a_libhandle
, "crypt_gensalt_impl");
630 if (alg
->a_gensalt
== NULL
) {
631 syslog(LOG_ERR
, "crypt(3c) unable to find crypt_gensalt_impl"
632 "symbol in %s: %s", pathname
, dlerror());
639 * We have a good module so build the a_params if we have any.
640 * Count how much space we need first and then allocate an array
641 * to hold that many module params.
648 if ((tparams
= strdup(lasts
)) == NULL
) {
653 (void) strtok_r(tparams
, " \t", &tplasts
);
656 } while (strtok_r(NULL
, " \t", &tplasts
) != NULL
);
659 alg
->a_params
= calloc(nparams
+ 1, sizeof (char *));
660 if (alg
->a_params
== NULL
) {
665 while ((token
= strtok_r(NULL
, " \t", &lasts
)) != NULL
) {
666 alg
->a_params
[alg
->a_nparams
++] = token
;
671 if (*found
== B_FALSE
) {
676 if (pathname
!= NULL
) {
681 (void) fclose(fconf
);
683 (void) close(configfd
);
690 free_crypt_alg(struct crypt_alg_s
*alg
)
695 if (alg
->a_libhandle
!= NULL
) {
696 (void) dlclose(alg
->a_libhandle
);
698 if (alg
->a_nparams
!= 0) {
705 free_crypt_policy(struct crypt_policy_s
*policy
)
710 if (policy
->cp_default
!= NULL
) {
711 bzero(policy
->cp_default
, strlen(policy
->cp_default
));
712 free(policy
->cp_default
);
713 policy
->cp_default
= NULL
;
716 if (policy
->cp_allow
!= NULL
) {
717 bzero(policy
->cp_allow
, strlen(policy
->cp_allow
));
718 free(policy
->cp_allow
);
719 policy
->cp_allow
= NULL
;
722 if (policy
->cp_deny
!= NULL
) {
723 bzero(policy
->cp_deny
, strlen(policy
->cp_deny
));
724 free(policy
->cp_deny
);
725 policy
->cp_deny
= NULL
;
733 * isa_path - prepend the default dir or patch up the $ISA in path
734 * Caller is responsible for calling free(3c) on the result.
737 isa_path(const char *path
)
741 if ((path
== NULL
) || (strlen(path
) > PATH_MAX
)) {
745 ret
= calloc(PATH_MAX
, sizeof (char));
748 * Module path doesn't start with "/" then prepend
749 * the default search path CRYPT_MODULE_DIR (/usr/lib/security/$ISA)
751 if (path
[0] != '/') {
752 if (snprintf(ret
, PATH_MAX
, "%s%s", CRYPT_MODULE_DIR
,
757 } else { /* patch up $ISA */
760 if ((isa
= strstr(path
, CRYPT_MODULE_ISA
)) != NULL
) {
762 isa
+= strlen(CRYPT_MODULE_ISA
);
763 if (snprintf(ret
, PATH_MAX
, "%s%s%s", path
,
764 CRYPT_ISA_DIR
, isa
) > PATH_MAX
) {
780 _unix_crypt_gensalt(char *gsbuffer
,
782 const char *oldpuresalt
,
783 const struct passwd
*userinfo
,
786 static const char saltchars
[] =
787 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
790 (void) gettimeofday(&tv
, NULL
);
791 srand48(tv
.tv_sec
^ tv
.tv_usec
);
792 gsbuffer
[0] = saltchars
[lrand48() % 64]; /* lrand48() is MT-SAFE */
793 gsbuffer
[1] = saltchars
[lrand48() % 64]; /* lrand48() is MT-SAFE */
800 * The rest of the code below comes from the old crypt.c and is the
801 * implementation of the hardwired/fallback traditional algorithm
802 * It has been otimized to take better advantage of MT features.
804 * It is included here to reduce the overhead of dlopen()
805 * for the common case.
809 /* Copyright (c) 1988 AT&T */
810 /* All Rights Reserved */
815 * This program implements a data encryption algorithm to encrypt passwords.
818 static mutex_t crypt_lock
= DEFAULTMUTEX
;
819 #define TSDBUFSZ (66 + 16)
821 static const char IP
[] = {
822 58, 50, 42, 34, 26, 18, 10, 2,
823 60, 52, 44, 36, 28, 20, 12, 4,
824 62, 54, 46, 38, 30, 22, 14, 6,
825 64, 56, 48, 40, 32, 24, 16, 8,
826 57, 49, 41, 33, 25, 17, 9, 1,
827 59, 51, 43, 35, 27, 19, 11, 3,
828 61, 53, 45, 37, 29, 21, 13, 5,
829 63, 55, 47, 39, 31, 23, 15, 7,
832 static const char FP
[] = {
833 40, 8, 48, 16, 56, 24, 64, 32,
834 39, 7, 47, 15, 55, 23, 63, 31,
835 38, 6, 46, 14, 54, 22, 62, 30,
836 37, 5, 45, 13, 53, 21, 61, 29,
837 36, 4, 44, 12, 52, 20, 60, 28,
838 35, 3, 43, 11, 51, 19, 59, 27,
839 34, 2, 42, 10, 50, 18, 58, 26,
840 33, 1, 41, 9, 49, 17, 57, 25,
843 static const char PC1_C
[] = {
844 57, 49, 41, 33, 25, 17, 9,
845 1, 58, 50, 42, 34, 26, 18,
846 10, 2, 59, 51, 43, 35, 27,
847 19, 11, 3, 60, 52, 44, 36,
850 static const char PC1_D
[] = {
851 63, 55, 47, 39, 31, 23, 15,
852 7, 62, 54, 46, 38, 30, 22,
853 14, 6, 61, 53, 45, 37, 29,
854 21, 13, 5, 28, 20, 12, 4,
857 static const char shifts
[] = {
858 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
861 static const char PC2_C
[] = {
862 14, 17, 11, 24, 1, 5,
863 3, 28, 15, 6, 21, 10,
864 23, 19, 12, 4, 26, 8,
865 16, 7, 27, 20, 13, 2,
868 static const char PC2_D
[] = {
869 41, 52, 31, 37, 47, 55,
870 30, 40, 51, 45, 33, 48,
871 44, 49, 39, 56, 34, 53,
872 46, 42, 50, 36, 29, 32,
880 static const char e2
[] = {
883 8, 9, 10, 11, 12, 13,
884 12, 13, 14, 15, 16, 17,
885 16, 17, 18, 19, 20, 21,
886 20, 21, 22, 23, 24, 25,
887 24, 25, 26, 27, 28, 29,
888 28, 29, 30, 31, 32, 1,
892 * The KS array (768 bytes) is allocated once, and only if
893 * one of _unix_crypt(), encrypt() or setkey() is called.
894 * The complexity below is due to the fact that calloc()
895 * must not be called while holding any locks.
904 if (KS
!= NULL
) { /* already allocated */
909 ks
= calloc(16, 48 * sizeof (char));
911 lmutex_lock(&crypt_lock
);
912 if (KS
!= NULL
) { /* someone else got here first */
917 if ((KS
= ks
) == NULL
) /* calloc() failed */
920 lmutex_unlock(&crypt_lock
);
927 unlocked_setkey(const char *key
)
932 for (i
= 0; i
< 28; i
++) {
933 C
[i
] = key
[PC1_C
[i
]-1];
934 D
[i
] = key
[PC1_D
[i
]-1];
936 for (i
= 0; i
< 16; i
++) {
937 for (k
= 0; k
< shifts
[i
]; k
++) {
939 for (j
= 0; j
< 28-1; j
++)
943 for (j
= 0; j
< 28-1; j
++)
947 for (j
= 0; j
< 24; j
++) {
950 *(KS
+index
+j
) = C
[PC2_C
[j
]-1];
951 *(KS
+index
+j
+24) = D
[PC2_D
[j
]-28-1];
954 for (i
= 0; i
< 48; i
++)
958 static const char S
[8][64] = {
959 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
960 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
961 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
962 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
964 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
965 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
966 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
967 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
969 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
970 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
971 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
972 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
974 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
975 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
976 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
977 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
979 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
980 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
981 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
982 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
984 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
985 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
986 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
987 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
989 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
990 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
991 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
992 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
994 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
995 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
996 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
997 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
1000 static const char P
[] = {
1012 static char tempL
[32];
1015 static char preS
[48];
1019 unlocked_encrypt(char *block
, int fake
)
1025 for (j
= 0; j
< 64; j
++)
1026 L
[j
] = block
[IP
[j
]-1];
1027 for (i
= 0; i
< 16; i
++) {
1030 for (j
= 0; j
< 32; j
++)
1032 for (j
= 0; j
< 48; j
++)
1033 preS
[j
] = R
[E
[j
]-1] ^ *(KS
+index
+j
);
1034 for (j
= 0; j
< 8; j
++) {
1036 k
= S
[j
][(preS
[t
+0]<<5) +
1048 for (j
= 0; j
< 32; j
++)
1049 R
[j
] = L
[j
] ^ f
[P
[j
]-1];
1050 for (j
= 0; j
< 32; j
++)
1053 for (j
= 0; j
< 32; j
++) {
1058 for (j
= 0; j
< 64; j
++)
1059 block
[j
] = L
[FP
[j
]-1];
1063 _unix_crypt(const char *pw
, const char *salt
, char *iobuf
)
1075 if (allocate_KS() != 0)
1077 lmutex_lock(&crypt_lock
);
1078 for (i
= 0; i
< 66; i
++)
1080 for (i
= 0; (c
= *pw
) != '\0' && i
< 64; pw
++) {
1081 for (j
= 0; j
< 7; j
++, i
++)
1082 block
[i
] = (c
>>(6-j
)) & 01;
1086 unlocked_setkey(block
);
1088 for (i
= 0; i
< 66; i
++)
1091 for (i
= 0; i
< 2; i
++) {
1099 for (j
= 0; j
< 6; j
++) {
1102 E
[6*i
+j
] = E
[6*i
+j
+24];
1108 for (i
= 0; i
< 25; i
++)
1109 unlocked_encrypt(block
, 0);
1111 lmutex_unlock(&crypt_lock
);
1112 for (i
= 0; i
< 11; i
++) {
1114 for (j
= 0; j
< 6; j
++) {
1123 iobuf
[i
+2] = (char)c
;
1127 iobuf
[1] = iobuf
[0];
1134 encrypt(char *block
, int fake
)
1140 if (allocate_KS() != 0)
1142 lmutex_lock(&crypt_lock
);
1143 unlocked_encrypt(block
, fake
);
1144 lmutex_unlock(&crypt_lock
);
1149 setkey(const char *key
)
1151 if (allocate_KS() != 0)
1153 lmutex_lock(&crypt_lock
);
1154 unlocked_setkey(key
);
1155 lmutex_unlock(&crypt_lock
);