summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortedu <>2014-03-23 23:19:21 +0000
committertedu <>2014-03-23 23:19:21 +0000
commit6ecd5909f6d077b669db3958976e4da8d24f48c3 (patch)
treec09c8bcc755b7ba36261f229eb033d456f02cd7f /src
parentb8fc64a9347b0fd25c7bc04720bb381adc4bd035 (diff)
downloadopenbsd-6ecd5909f6d077b669db3958976e4da8d24f48c3.tar.gz
openbsd-6ecd5909f6d077b669db3958976e4da8d24f48c3.tar.bz2
openbsd-6ecd5909f6d077b669db3958976e4da8d24f48c3.zip
minimal change to implementation of bcrypt to not require static globals.
add some friendlier functions. move the classic static data api into wrapper functions. a few more changes to come...
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/crypt/bcrypt.c127
1 files changed, 88 insertions, 39 deletions
diff --git a/src/lib/libc/crypt/bcrypt.c b/src/lib/libc/crypt/bcrypt.c
index 156997b232..29ea4550c9 100644
--- a/src/lib/libc/crypt/bcrypt.c
+++ b/src/lib/libc/crypt/bcrypt.c
@@ -1,6 +1,7 @@
1/* $OpenBSD: bcrypt.c,v 1.31 2014/03/22 23:02:03 tedu Exp $ */ 1/* $OpenBSD: bcrypt.c,v 1.32 2014/03/23 23:19:21 tedu Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
4 * Copyright (c) 1997 Niels Provos <provos@umich.edu> 5 * Copyright (c) 1997 Niels Provos <provos@umich.edu>
5 * 6 *
6 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
@@ -47,37 +48,23 @@
47#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */ 48#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
48#define BCRYPT_MINLOGROUNDS 4 /* we have log2(rounds) in salt */ 49#define BCRYPT_MINLOGROUNDS 4 /* we have log2(rounds) in salt */
49 50
51#define BCRYPT_SALTSPACE (7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1)
52
50char *bcrypt_gensalt(u_int8_t); 53char *bcrypt_gensalt(u_int8_t);
51 54
52static void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
53static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t); 55static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
54static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *); 56static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *);
55 57
56static char encrypted[_PASSWORD_LEN]; 58/*
57static char gsalt[7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1]; 59 * Generates a salt for this version of crypt.
58static char error[] = ":";
59
60static void
61encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
62{
63 salt[0] = '$';
64 salt[1] = BCRYPT_VERSION;
65 salt[2] = 'a';
66 salt[3] = '$';
67
68 snprintf(salt + 4, 4, "%2.2u$", logr);
69
70 encode_base64((u_int8_t *) salt + 7, csalt, clen);
71}
72/* Generates a salt for this version of crypt.
73 Since versions may change. Keeping this here
74 seems sensible.
75 */ 60 */
76 61int
77char * 62bcrypt_initsalt(int log_rounds, uint8_t *salt, size_t saltbuflen)
78bcrypt_gensalt(u_int8_t log_rounds)
79{ 63{
80 u_int8_t csalt[BCRYPT_MAXSALT]; 64 uint8_t csalt[BCRYPT_MAXSALT];
65
66 if (saltbuflen < BCRYPT_SALTSPACE)
67 return -1;
81 68
82 arc4random_buf(csalt, sizeof(csalt)); 69 arc4random_buf(csalt, sizeof(csalt));
83 70
@@ -86,14 +73,18 @@ bcrypt_gensalt(u_int8_t log_rounds)
86 else if (log_rounds > 31) 73 else if (log_rounds > 31)
87 log_rounds = 31; 74 log_rounds = 31;
88 75
89 encode_salt(gsalt, csalt, BCRYPT_MAXSALT, log_rounds); 76 snprintf(salt, 4, "$2a$%2.2u$", log_rounds);
90 return gsalt; 77 encode_base64((uint8_t *)salt + 7, csalt, sizeof(csalt));
78
79 return 0;
91} 80}
92/* We handle $Vers$log2(NumRounds)$salt+passwd$
93 i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
94 81
95char * 82/*
96bcrypt(const char *key, const char *salt) 83 * the core bcrypt function
84 */
85int
86bcrypt_hashpass(const char *key, const char *salt, char *encrypted,
87 size_t encryptedlen)
97{ 88{
98 blf_ctx state; 89 blf_ctx state;
99 u_int32_t rounds, i, k; 90 u_int32_t rounds, i, k;
@@ -109,8 +100,7 @@ bcrypt(const char *key, const char *salt)
109 salt++; 100 salt++;
110 101
111 if (*salt > BCRYPT_VERSION) { 102 if (*salt > BCRYPT_VERSION) {
112 /* How do I handle errors ? Return ':' */ 103 return -1;
113 return error;
114 } 104 }
115 105
116 /* Check for minor versions */ 106 /* Check for minor versions */
@@ -122,7 +112,7 @@ bcrypt(const char *key, const char *salt)
122 salt++; 112 salt++;
123 break; 113 break;
124 default: 114 default:
125 return error; 115 return -1;
126 } 116 }
127 } else 117 } else
128 minor = 0; 118 minor = 0;
@@ -132,15 +122,15 @@ bcrypt(const char *key, const char *salt)
132 122
133 if (salt[2] != '$') 123 if (salt[2] != '$')
134 /* Out of sync with passwd entry */ 124 /* Out of sync with passwd entry */
135 return error; 125 return -1;
136 126
137 memcpy(arounds, salt, sizeof(arounds)); 127 memcpy(arounds, salt, sizeof(arounds));
138 if (arounds[sizeof(arounds) - 1] != '$') 128 if (arounds[sizeof(arounds) - 1] != '$')
139 return error; 129 return -1;
140 arounds[sizeof(arounds) - 1] = 0; 130 arounds[sizeof(arounds) - 1] = 0;
141 logr = strtonum(arounds, BCRYPT_MINLOGROUNDS, 31, NULL); 131 logr = strtonum(arounds, BCRYPT_MINLOGROUNDS, 31, NULL);
142 if (logr == 0) 132 if (logr == 0)
143 return error; 133 return -1;
144 /* Computer power doesn't increase linearly, 2^x should be fine */ 134 /* Computer power doesn't increase linearly, 2^x should be fine */
145 rounds = 1U << logr; 135 rounds = 1U << logr;
146 136
@@ -148,7 +138,7 @@ bcrypt(const char *key, const char *salt)
148 salt += 3; 138 salt += 3;
149 139
150 if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) 140 if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
151 return error; 141 return -1;
152 142
153 /* We dont want the base64 salt but the raw data */ 143 /* We dont want the base64 salt but the raw data */
154 decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt); 144 decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
@@ -211,9 +201,41 @@ bcrypt(const char *key, const char *salt)
211 memset(ciphertext, 0, sizeof(ciphertext)); 201 memset(ciphertext, 0, sizeof(ciphertext));
212 memset(csalt, 0, sizeof(csalt)); 202 memset(csalt, 0, sizeof(csalt));
213 memset(cdata, 0, sizeof(cdata)); 203 memset(cdata, 0, sizeof(cdata));
214 return encrypted; 204 return 0;
205}
206
207/*
208 * user friendly functions
209 */
210int
211bcrypt_newhash(const char *pass, int log_rounds, char *hash, size_t hashlen)
212{
213 char salt[BCRYPT_SALTSPACE];
214
215 if (bcrypt_initsalt(log_rounds, salt, sizeof(salt)) != 0)
216 return -1;
217
218 if (bcrypt_hashpass(pass, salt, hash, hashlen) != 0)
219 return -1;
220
221 return 0;
222}
223
224int
225bcrypt_checkpass(const char *pass, const char *goodhash)
226{
227 char hash[_PASSWORD_LEN];
228
229 if (bcrypt_hashpass(pass, goodhash, hash, sizeof(hash)) != 0)
230 return -1;
231 if (strcmp(hash, goodhash) != 0)
232 return -1;
233 return 0;
215} 234}
216 235
236/*
237 * internal utilities
238 */
217const static u_int8_t Base64Code[] = 239const static u_int8_t Base64Code[] =
218"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 240"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
219 241
@@ -298,3 +320,30 @@ encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
298 } 320 }
299 *bp = '\0'; 321 *bp = '\0';
300} 322}
323
324/*
325 * classic interface
326 */
327char *
328bcrypt_gensalt(u_int8_t log_rounds)
329{
330 static char gsalt[7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1];
331
332 bcrypt_initsalt(log_rounds, gsalt, sizeof(gsalt));
333
334 return gsalt;
335}
336
337char *
338bcrypt(const char *pass, const char *salt)
339{
340 static char gencrypted[_PASSWORD_LEN];
341 static char gerror[] = ":";
342
343 /* How do I handle errors ? Return ':' */
344 if (bcrypt_hashpass(pass, salt, gencrypted, sizeof(gencrypted)) != 0)
345 return gerror;
346
347 return gencrypted;
348}
349