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