1 /* $OpenBSD: cryptutil.c,v 1.12 2015/09/13 15:33:48 guenther 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 <login_cap.h> 22 #include <errno.h> 23 24 int 25 crypt_checkpass(const char *pass, const char *goodhash) 26 { 27 char dummy[_PASSWORD_LEN]; 28 29 if (goodhash == NULL) { 30 /* fake it */ 31 goto fake; 32 } 33 34 /* empty password */ 35 if (strlen(goodhash) == 0 && strlen(pass) == 0) 36 return 0; 37 38 if (goodhash[0] == '$' && goodhash[1] == '2') { 39 if (bcrypt_checkpass(pass, goodhash)) 40 goto fail; 41 return 0; 42 } 43 44 /* unsupported. fake it. */ 45 fake: 46 bcrypt_newhash(pass, 8, dummy, sizeof(dummy)); 47 fail: 48 errno = EACCES; 49 return -1; 50 } 51 DEF_WEAK(crypt_checkpass); 52 53 int 54 crypt_newhash(const char *pass, const char *pref, char *hash, size_t hashlen) 55 { 56 int rv = -1; 57 const char *defaultpref = "blowfish,8"; 58 const char *errstr; 59 const char *choices[] = { "blowfish", "bcrypt" }; 60 size_t maxchoice = sizeof(choices) / sizeof(choices[0]); 61 int i; 62 int rounds; 63 64 if (pref == NULL) 65 pref = defaultpref; 66 67 for (i = 0; i < maxchoice; i++) { 68 const char *choice = choices[i]; 69 size_t len = strlen(choice); 70 if (strcmp(pref, choice) == 0) { 71 rounds = _bcrypt_autorounds(); 72 break; 73 } else if (strncmp(pref, choice, len) == 0 && 74 pref[len] == ',') { 75 if (strcmp(pref + len + 1, "a") == 0) { 76 rounds = _bcrypt_autorounds(); 77 } else { 78 rounds = strtonum(pref + len + 1, 4, 31, &errstr); 79 if (errstr) { 80 errno = EINVAL; 81 goto err; 82 } 83 } 84 break; 85 } 86 } 87 if (i == maxchoice) { 88 errno = EINVAL; 89 goto err; 90 } 91 92 rv = bcrypt_newhash(pass, rounds, hash, hashlen); 93 94 err: 95 return rv; 96 } 97 DEF_WEAK(crypt_newhash); 98