1 /* 2 * Copyright 2017, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Andrew Aldridge, i80and@foxquill.com 7 */ 8 9 10 #include <assert.h> 11 #include <crypt.h> 12 #include <errno.h> 13 #include <fcntl.h> 14 #include <inttypes.h> 15 #include <math.h> 16 #include <stdio.h> 17 #include <string.h> 18 19 #include <SupportDefs.h> 20 21 #include "../musl/crypt/crypt_des.h" 22 #include "crypto_scrypt.h" 23 24 #define SALT_BYTES 32 25 #define SALT_STR_BYTES (SALT_BYTES * 2 + 1) 26 #define DEFAULT_N_LOG2 14 27 28 #define CRYPT_OUTPUT_BYTES (6 + 64 + 1 + 64 + 1) 29 #define SALT_OUTPUT_BYTES (6 + 64 + 1 + 1) 30 31 static const char* kHexAlphabet = "0123456789abcdef"; 32 static const int8 kHexLookup[] = { 33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 36 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15}; 39 40 41 static int 42 toHex(const uint8* buffer, size_t bufferLength, char* outBuffer, 43 size_t outBufferLength) 44 { 45 size_t i; 46 size_t outIndex = 0; 47 48 if (outBufferLength <= bufferLength * 2) { 49 outBuffer[0] = '\0'; 50 return 1; 51 } 52 53 for (i = 0; i < bufferLength; i += 1) { 54 const uint8 n = buffer[i]; 55 const uint8 upper = n >> 4; 56 const uint8 lower = n & 0x0f; 57 58 assert(lower < 16 && upper < 16); 59 outBuffer[outIndex++] = kHexAlphabet[upper]; 60 outBuffer[outIndex++] = kHexAlphabet[lower]; 61 outBuffer[outIndex] = '\0'; 62 } 63 64 outBuffer[outIndex] = '\0'; 65 66 return 0; 67 } 68 69 70 static size_t 71 fromHex(const char* hex, uint8* outBuffer, size_t outBufferLength) 72 { 73 size_t i = 0; 74 size_t outIndex = 0; 75 76 if (hex[0] == '\0' || outBufferLength == 0) 77 return 0; 78 79 while (hex[i] != '\0' && hex[i + 1] != '\0') { 80 const uint8 char1 = hex[i]; 81 const uint8 char2 = hex[i + 1]; 82 83 if (char1 >= sizeof(kHexLookup) || char2 >= sizeof(kHexLookup)) 84 return outIndex; 85 86 const char index1 = kHexLookup[char1]; 87 const char index2 = kHexLookup[char2]; 88 89 if (outIndex >= outBufferLength) 90 return 0; 91 92 outBuffer[outIndex++] = (index1 << 4) | index2; 93 i += 2; 94 } 95 96 return outIndex; 97 } 98 99 100 //! Generate a new salt appropriate for crypt(). 101 static int 102 crypt_gensalt_rn(char *outbuf, size_t bufsize) 103 { 104 uint8 salt[SALT_BYTES]; 105 char saltString[SALT_STR_BYTES]; 106 size_t totalBytesRead = 0; 107 108 int fd = open("/dev/random", O_RDONLY, 0); 109 if (fd < 0) 110 return -1; 111 112 while (totalBytesRead < sizeof(salt)) { 113 const ssize_t bytesRead = read(fd, 114 static_cast<void*>(salt + totalBytesRead), 115 sizeof(salt) - totalBytesRead); 116 if (bytesRead <= 0) { 117 close(fd); 118 return -1; 119 } 120 121 totalBytesRead += bytesRead; 122 } 123 close(fd); 124 125 assert(toHex(salt, sizeof(salt), saltString, sizeof(saltString)) == 0); 126 snprintf(outbuf, bufsize, "$s$%d$%s$", DEFAULT_N_LOG2, saltString); 127 return 0; 128 } 129 130 131 extern "C" char * 132 _crypt_rn(const char* key, const char* setting, struct crypt_data* data, size_t size) 133 { 134 uint8 saltBinary[SALT_BYTES]; 135 char saltString[SALT_STR_BYTES]; 136 char gensaltResult[SALT_OUTPUT_BYTES]; 137 uint8 resultBuffer[32]; 138 char hexResultBuffer[64 + 1]; 139 int nLog2 = DEFAULT_N_LOG2; 140 141 if (setting == NULL) { 142 int res = crypt_gensalt_rn(gensaltResult, sizeof(gensaltResult)); 143 144 // crypt_gensalt_r should set errno itself. 145 if (res < 0) 146 return NULL; 147 148 setting = gensaltResult; 149 } 150 151 // Some idioms existed where the password was also used as the salt. 152 // As a crude heuristic, use the old crypt algorithm if the salt is 153 // shortish. 154 if (strlen(setting) < 16) 155 return _crypt_des_r(key, setting, data->buf); 156 157 // We don't want to fall into the old algorithm by accident somehow, so 158 // if our salt is kind of like our salt, but not exactly, return an 159 // error. 160 if (sscanf(setting, "$s$%2d$%64s$", &nLog2, saltString) != 2) { 161 errno = EINVAL; 162 return NULL; 163 } 164 165 // Set a lower bound on N_log2: below 12 scrypt is weaker than bcrypt. 166 if (nLog2 < 12) { 167 errno = EINVAL; 168 return NULL; 169 } 170 171 size_t saltBinaryLength = fromHex(saltString, saltBinary, 172 sizeof(saltBinary)); 173 if (saltBinaryLength != sizeof(saltBinary)) { 174 errno = EINVAL; 175 return NULL; 176 } 177 178 long n = static_cast<long>(pow(2, nLog2)); 179 if (crypto_scrypt(reinterpret_cast<const uint8*>(key), strlen(key), 180 saltBinary, saltBinaryLength, n, 8, 1, resultBuffer, 181 sizeof(resultBuffer)) != 0) { 182 // crypto_scrypt sets errno itself 183 return NULL; 184 } 185 186 assert(toHex(resultBuffer, sizeof(resultBuffer), hexResultBuffer, 187 sizeof(hexResultBuffer)) == 0); 188 snprintf(data->buf, size - sizeof(int), "$s$%d$%s$%s", nLog2, saltString, 189 hexResultBuffer); 190 191 return data->buf; 192 } 193 194 195 char * 196 crypt(const char* key, const char* salt) 197 { 198 static struct crypt_data data; 199 return _crypt_rn(key, salt, &data, sizeof(struct crypt_data)); 200 } 201 202 203 //! To make fcrypt users happy. They don't need to call init_des. 204 char* 205 fcrypt(const char* key, const char* salt) 206 { 207 return crypt(key, salt); 208 } 209