summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortedu <>2014-05-12 19:13:14 +0000
committertedu <>2014-05-12 19:13:14 +0000
commit9d93f27329372e68682819911c1e89467694ad93 (patch)
tree6b0f520cc57a8e1702644a31adcd0c82d71c728a
parent1b7bf9f1ebd8096b9d44b3bf148bd664715501ab (diff)
downloadopenbsd-9d93f27329372e68682819911c1e89467694ad93.tar.gz
openbsd-9d93f27329372e68682819911c1e89467694ad93.tar.bz2
openbsd-9d93f27329372e68682819911c1e89467694ad93.zip
remove md5crypt.
while changing things, add a crypt_checkpass wrapper that handles most of the edge cases. (not quite ready for production, though.) ok deraadt
-rw-r--r--src/lib/libc/crypt/Makefile.inc6
-rw-r--r--src/lib/libc/crypt/crypt.331
-rw-r--r--src/lib/libc/crypt/crypt.c9
-rw-r--r--src/lib/libc/crypt/cryptutil.c54
-rw-r--r--src/lib/libc/crypt/md5crypt.c160
5 files changed, 65 insertions, 195 deletions
diff --git a/src/lib/libc/crypt/Makefile.inc b/src/lib/libc/crypt/Makefile.inc
index c852523372..3676d7f646 100644
--- a/src/lib/libc/crypt/Makefile.inc
+++ b/src/lib/libc/crypt/Makefile.inc
@@ -1,12 +1,12 @@
1# $OpenBSD: Makefile.inc,v 1.19 2013/10/21 20:33:23 deraadt Exp $ 1# $OpenBSD: Makefile.inc,v 1.20 2014/05/12 19:13:14 tedu Exp $
2 2
3.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/crypt ${LIBCSRCDIR}/crypt 3.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/crypt ${LIBCSRCDIR}/crypt
4 4
5SRCS+= crypt.c crypt2.c md5crypt.c arc4random.c blowfish.c bcrypt.c 5SRCS+= crypt.c crypt2.c cryptutil.c arc4random.c blowfish.c bcrypt.c
6 6
7MAN+= crypt.3 blowfish.3 arc4random.3 7MAN+= crypt.3 blowfish.3 arc4random.3
8MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_cipher.3 8MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_cipher.3
9MLINKS+=crypt.3 bcrypt_gensalt.3 crypt.3 bcrypt.3 crypt.3 md5crypt.3 9MLINKS+=crypt.3 bcrypt_gensalt.3 crypt.3 bcrypt.3
10MLINKS+=crypt.3 des_setkey.3 blowfish.3 blf_key.3 blowfish.3 blf_enc.3 10MLINKS+=crypt.3 des_setkey.3 blowfish.3 blf_key.3 blowfish.3 blf_enc.3
11MLINKS+=blowfish.3 blf_dec.3 blowfish.3 blf_ecb_encrypt.3 11MLINKS+=blowfish.3 blf_dec.3 blowfish.3 blf_ecb_encrypt.3
12MLINKS+=blowfish.3 blf_ecb_decrypt.3 blowfish.3 blf_cbc_encrypt.3 12MLINKS+=blowfish.3 blf_ecb_decrypt.3 blowfish.3 blf_cbc_encrypt.3
diff --git a/src/lib/libc/crypt/crypt.3 b/src/lib/libc/crypt/crypt.3
index f4a78781da..b8777e39ca 100644
--- a/src/lib/libc/crypt/crypt.3
+++ b/src/lib/libc/crypt/crypt.3
@@ -1,4 +1,4 @@
1.\" $OpenBSD: crypt.3,v 1.34 2014/03/19 02:34:45 tedu Exp $ 1.\" $OpenBSD: crypt.3,v 1.35 2014/05/12 19:13:14 tedu Exp $
2.\" 2.\"
3.\" FreeSec: libcrypt 3.\" FreeSec: libcrypt
4.\" 4.\"
@@ -31,7 +31,7 @@
31.\" 31.\"
32.\" Manual page, using -mandoc macros 32.\" Manual page, using -mandoc macros
33.\" 33.\"
34.Dd $Mdocdate: March 19 2014 $ 34.Dd $Mdocdate: May 12 2014 $
35.Dt CRYPT 3 35.Dt CRYPT 3
36.Os 36.Os
37.Sh NAME 37.Sh NAME
@@ -41,8 +41,7 @@
41.Nm des_setkey , 41.Nm des_setkey ,
42.Nm des_cipher , 42.Nm des_cipher ,
43.Nm bcrypt_gensalt , 43.Nm bcrypt_gensalt ,
44.Nm bcrypt , 44.Nm bcrypt
45.Nm md5crypt
46.Nd password hashing 45.Nd password hashing
47.Sh SYNOPSIS 46.Sh SYNOPSIS
48.In stdlib.h 47.In stdlib.h
@@ -63,8 +62,6 @@
63.Fn bcrypt_gensalt "u_int8_t log_rounds" 62.Fn bcrypt_gensalt "u_int8_t log_rounds"
64.Ft char * 63.Ft char *
65.Fn bcrypt "const char *key" "const char *salt" 64.Fn bcrypt "const char *key" "const char *salt"
66.Ft char *
67.Fn md5crypt "const char *key" "const char *salt"
68.Sh DESCRIPTION 65.Sh DESCRIPTION
69The 66The
70.Fn crypt 67.Fn crypt
@@ -88,9 +85,7 @@ If it begins
88with a string character 85with a string character
89.Pq Ql $ 86.Pq Ql $
90and a number then a different algorithm is used depending on the number. 87and a number then a different algorithm is used depending on the number.
91At the moment a 88At the moment
92.Ql $1
93chooses MD5 hashing and a
94.Ql $2 89.Ql $2
95chooses Blowfish hashing; see below for more information. 90chooses Blowfish hashing; see below for more information.
96.Ss Extended crypt 91.Ss Extended crypt
@@ -113,24 +108,6 @@ This allows 24 bits for both
113.Fa count 108.Fa count
114and 109and
115.Fa salt . 110.Fa salt .
116.Ss "MD5" crypt
117For
118.Tn MD5
119crypt the version number,
120.Fa salt
121and the hashed password are separated by the
122.Ql $
123character.
124The maximum length of a password is limited by
125the length counter of the MD5 context, which is about
1262**64.
127A valid MD5 password entry looks like this:
128.Pp
129.Dq $1$caeiHQwX$hsKqOjrFRRN6K32OWkCBf1 .
130.Pp
131The whole MD5 password string is passed as
132.Fa setting
133for interpretation.
134.Ss "Blowfish" crypt 111.Ss "Blowfish" crypt
135The 112The
136.Tn Blowfish 113.Tn Blowfish
diff --git a/src/lib/libc/crypt/crypt.c b/src/lib/libc/crypt/crypt.c
index 15a784532d..ad8140e302 100644
--- a/src/lib/libc/crypt/crypt.c
+++ b/src/lib/libc/crypt/crypt.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: crypt.c,v 1.20 2005/08/08 08:05:33 espie Exp $ */ 1/* $OpenBSD: crypt.c,v 1.21 2014/05/12 19:13:14 tedu Exp $ */
2 2
3/* 3/*
4 * FreeSec: libcrypt 4 * FreeSec: libcrypt
@@ -576,15 +576,14 @@ crypt(const char *key, const char *setting)
576 u_int32_t count, salt, l, r0, r1, keybuf[2]; 576 u_int32_t count, salt, l, r0, r1, keybuf[2];
577 u_char *p, *q; 577 u_char *p, *q;
578 static u_char output[21]; 578 static u_char output[21];
579 extern char *md5crypt(const char *, const char *);
580 extern char *bcrypt(const char *, const char *); 579 extern char *bcrypt(const char *, const char *);
581 580
582 if (setting[0] == '$') { 581 if (setting[0] == '$') {
583 switch (setting[1]) { 582 switch (setting[1]) {
584 case '1': 583 case '2':
585 return (md5crypt(key, setting));
586 default:
587 return bcrypt(key, setting); 584 return bcrypt(key, setting);
585 default:
586 return (NULL);
588 } 587 }
589 } 588 }
590 589
diff --git a/src/lib/libc/crypt/cryptutil.c b/src/lib/libc/crypt/cryptutil.c
new file mode 100644
index 0000000000..36deda778e
--- /dev/null
+++ b/src/lib/libc/crypt/cryptutil.c
@@ -0,0 +1,54 @@
1/* $OpenBSD: cryptutil.c,v 1.1 2014/05/12 19:13:14 tedu Exp $ */
2/*
3 * Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <stdlib.h>
18#include <unistd.h>
19#include <string.h>
20#include <pwd.h>
21#include <errno.h>
22
23int
24crypt_checkpass(const char *pass, const char *goodhash)
25{
26 char dummy[_PASSWORD_LEN];
27 char *res;
28
29 if (goodhash == NULL) {
30 /* fake it */
31 bcrypt_newhash(pass, 8, dummy, sizeof(dummy));
32 goto fail;
33 }
34
35 /* empty password */
36 if (strlen(goodhash) == 0 && strlen(pass) == 0)
37 return 0;
38
39 if (goodhash[0] == '$' && goodhash[1] == '2') {
40 return bcrypt_checkpass(pass, goodhash);
41 }
42
43 /* have to do it the hard way */
44 res = crypt(pass, goodhash);
45 if (strlen(res) != strlen(goodhash) ||
46 timingsafe_bcmp(res, goodhash, strlen(goodhash)) != 0) {
47 goto fail;
48 }
49
50 return 0;
51fail:
52 errno = EACCES;
53 return -1;
54}
diff --git a/src/lib/libc/crypt/md5crypt.c b/src/lib/libc/crypt/md5crypt.c
deleted file mode 100644
index a855835bcc..0000000000
--- a/src/lib/libc/crypt/md5crypt.c
+++ /dev/null
@@ -1,160 +0,0 @@
1/* $OpenBSD: md5crypt.c,v 1.17 2014/04/03 15:55:29 beck Exp $ */
2
3/*
4 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * If we meet some day, and you think this stuff is worth it, you
21 * can buy me a beer in return. Poul-Henning Kamp
22 */
23
24#include <unistd.h>
25#include <stdio.h>
26#include <string.h>
27#include <md5.h>
28#include <string.h>
29
30static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
31 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
32
33static void to64(char *, u_int32_t, int);
34
35static void
36to64(char *s, u_int32_t v, int n)
37{
38 while (--n >= 0) {
39 *s++ = itoa64[v&0x3f];
40 v >>= 6;
41 }
42}
43
44/*
45 * UNIX password
46 *
47 * Use MD5 for what it is best at...
48 */
49
50char *md5crypt(const char *pw, const char *salt);
51
52char *
53md5crypt(const char *pw, const char *salt)
54{
55 /*
56 * This string is the magic for this algorithm.
57 * Having it this way, we can get better later on.
58 */
59 static unsigned char *magic = (unsigned char *)"$1$";
60
61 static char passwd[120], *p;
62 static const unsigned char *sp,*ep;
63 unsigned char final[16];
64 int sl,pl,i;
65 MD5_CTX ctx,ctx1;
66 u_int32_t l;
67
68 /* Refine the salt first */
69 sp = (const unsigned char *)salt;
70
71 /* If it starts with the magic string, then skip that */
72 if(!strncmp((const char *)sp,(const char *)magic,strlen((const char *)magic)))
73 sp += strlen((const char *)magic);
74
75 /* It stops at the first '$', max 8 chars */
76 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
77 continue;
78
79 /* get the length of the true salt */
80 sl = ep - sp;
81
82 MD5Init(&ctx);
83
84 /* The password first, since that is what is most unknown */
85 MD5Update(&ctx,(const unsigned char *)pw,strlen(pw));
86
87 /* Then our magic string */
88 MD5Update(&ctx,magic,strlen((const char *)magic));
89
90 /* Then the raw salt */
91 MD5Update(&ctx,sp,sl);
92
93 /* Then just as many characters of the MD5(pw,salt,pw) */
94 MD5Init(&ctx1);
95 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
96 MD5Update(&ctx1,sp,sl);
97 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
98 MD5Final(final,&ctx1);
99 for(pl = strlen(pw); pl > 0; pl -= 16)
100 MD5Update(&ctx,final,pl>16 ? 16 : pl);
101
102 /* Don't leave anything around in vm they could use. */
103 memset(final,0,sizeof final);
104
105 /* Then something really weird... */
106 for (i = strlen(pw); i ; i >>= 1)
107 if(i&1)
108 MD5Update(&ctx, final, 1);
109 else
110 MD5Update(&ctx, (const unsigned char *)pw, 1);
111
112 /* Now make the output string */
113 snprintf(passwd, sizeof(passwd), "%s%.*s$", (char *)magic,
114 sl, (const char *)sp);
115
116 MD5Final(final,&ctx);
117
118 /*
119 * And now, just to make sure things don't run too fast
120 * On a 60 MHz Pentium this takes 34 msec, so you would
121 * need 30 seconds to build a 1000 entry dictionary...
122 * On a modern machine, with possible GPU optimization,
123 * this will run a lot faster than that.
124 */
125 for(i=0;i<1000;i++) {
126 MD5Init(&ctx1);
127 if(i & 1)
128 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
129 else
130 MD5Update(&ctx1,final,16);
131
132 if(i % 3)
133 MD5Update(&ctx1,sp,sl);
134
135 if(i % 7)
136 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
137
138 if(i & 1)
139 MD5Update(&ctx1,final,16);
140 else
141 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
142 MD5Final(final,&ctx1);
143 }
144
145 p = passwd + strlen(passwd);
146
147 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
148 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
149 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
150 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
151 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
152 l = final[11] ; to64(p,l,2); p += 2;
153 *p = '\0';
154
155 /* Don't leave anything around in vm they could use. */
156 memset(final, 0, sizeof final);
157
158 return passwd;
159}
160