1 /* 2 * Copyright (C) 2024 Sebastian Ertz <sebastian.ertz@gmx.de> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * # Digest Functions 19 * 20 * The `digest` module bundles various digest functions. 21 * 22 * @module digest 23 */ 24 25 #include <md5.h> 26 #include <sha1.h> 27 #include <sha2.h> 28 29 #ifdef HAVE_DIGEST_EXTENDED 30 #include <md2.h> 31 #include <md4.h> 32 #endif 33 34 #include "ucode/module.h" 35 36 37 static uc_value_t * 38 uc_digest_calc_data(uc_value_t *str, char *(*fn)(const uint8_t *,size_t,char *)) 39 { 40 char buf[SHA512_DIGEST_STRING_LENGTH]; 41 42 if( ucv_type(str) != UC_STRING ) 43 return NULL; 44 45 if( fn((const uint8_t *)ucv_string_get(str), ucv_string_length(str), buf) ) 46 return ucv_string_new(buf); 47 48 return NULL; 49 } 50 51 static uc_value_t * 52 uc_digest_calc_file(uc_value_t *path, char *(fn)(const char *,char *)) 53 { 54 char buf[SHA512_DIGEST_STRING_LENGTH]; 55 56 if( ucv_type(path) != UC_STRING ) 57 return NULL; 58 59 if( fn(ucv_string_get(path), buf) ) 60 return ucv_string_new(buf); 61 62 return NULL; 63 } 64 65 static char * 66 uc_digest_fnv1a64_data_hash(const uint8_t *data, size_t len, char *out) 67 { 68 static const char hex[] = "0123456789abcdef"; 69 uint64_t hash = 0xCBF29CE484222325; 70 71 for (size_t i = 0; i < len; i++) { 72 hash ^= data[i]; 73 hash *= 0x00000100000001B3; 74 } 75 76 for (int i = 0; i < 8; i++) { 77 uint8_t byte = (hash >> ((7 - i) * 8)) & 0xFF; 78 out[i * 2] = hex[byte >> 4]; 79 out[i * 2 + 1] = hex[byte & 0xF]; 80 } 81 82 out[16] = '\0'; 83 return out; 84 } 85 86 static char * 87 uc_digest_fnv1a64_file_hash(const char *path, char *out) 88 { 89 FILE *f = fopen(path, "rb"); 90 if (!f) 91 return NULL; 92 93 static const char hex[] = "0123456789abcdef"; 94 uint64_t hash = 0xCBF29CE484222325; 95 unsigned char buf[4096]; 96 size_t n; 97 98 while ((n = fread(buf, 1, sizeof(buf), f)) > 0) { 99 for (size_t i = 0; i < n; i++) { 100 hash ^= buf[i]; 101 hash *= 0x00000100000001B3; 102 } 103 } 104 105 if (ferror(f)) { 106 fclose(f); 107 return NULL; 108 } 109 110 fclose(f); 111 112 for (int i = 0; i < 8; i++) { 113 uint8_t byte = (hash >> ((7 - i) * 8)) & 0xFF; 114 out[i * 2] = hex[byte >> 4]; 115 out[i * 2 + 1] = hex[byte & 0xF]; 116 } 117 118 out[16] = '\0'; 119 return out; 120 } 121 122 /** 123 * Calculates the MD5 hash of string and returns that hash. 124 * 125 * Returns `null` if a non-string argument is given. 126 * 127 * @function module:digest#md5 128 * 129 * @param {string} str 130 * The string to hash. 131 * 132 * @returns {?string} 133 * 134 * @example 135 * md5("This is a test"); // Returns "ce114e4501d2f4e2dcea3e17b546f339" 136 * md5(123); // Returns null 137 */ 138 static uc_value_t * 139 uc_digest_md5(uc_vm_t *vm, size_t nargs) 140 { 141 return uc_digest_calc_data(uc_fn_arg(0), MD5Data); 142 } 143 144 /** 145 * Calculates the SHA1 hash of string and returns that hash. 146 * 147 * Returns `null` if a non-string argument is given. 148 * 149 * @function module:digest#sha1 150 * 151 * @param {string} str 152 * The string to hash. 153 * 154 * @returns {?string} 155 * 156 * @example 157 * sha1("This is a test"); // Returns "a54d88e06612d820bc3be72877c74f257b561b19" 158 * sha1(123); // Returns null 159 */ 160 static uc_value_t * 161 uc_digest_sha1(uc_vm_t *vm, size_t nargs) 162 { 163 return uc_digest_calc_data(uc_fn_arg(0), SHA1Data); 164 } 165 166 /** 167 * Calculates the SHA256 hash of string and returns that hash. 168 * 169 * Returns `null` if a non-string argument is given. 170 * 171 * @function module:digest#sha256 172 * 173 * @param {string} str 174 * The string to hash. 175 * 176 * @returns {?string} 177 * 178 * @example 179 * sha256("This is a test"); // Returns "c7be1ed902fb8dd4d48997c6452f5d7e509fbcdbe2808b16bcf4edce4c07d14e" 180 * sha256(123); // Returns null 181 */ 182 static uc_value_t * 183 uc_digest_sha256(uc_vm_t *vm, size_t nargs) 184 { 185 return uc_digest_calc_data(uc_fn_arg(0), SHA256Data); 186 } 187 188 /** 189 * Calculates the 64-bit FNV-1a non-cryptographic hash of string and returns 190 * that hash. 191 * 192 * Returns `null` if a non-string argument is given. 193 * 194 * @function module:digest#fnv1a64 195 * 196 * @param {string} str 197 * The string to hash. 198 * 199 * @returns {?string} 200 * 201 * @example 202 * fnv1a64("This is a test"); // Returns "25f0b040ca8b4ce0" 203 * fnv1a64(123); // Returns null 204 */ 205 static uc_value_t * 206 uc_digest_fnv1a64(uc_vm_t *vm, size_t nargs) 207 { 208 return uc_digest_calc_data(uc_fn_arg(0), uc_digest_fnv1a64_data_hash); 209 } 210 211 /** 212 * Calculates the 64-bit FNV-1a non-cryptographic hash of a given file and 213 * returns that hash. 214 * 215 * Returns `null` if an error occurred. 216 * 217 * @function module:digest#fnv1a64_file 218 * 219 * @param {string} path 220 * The path to the file. 221 * 222 * @returns {?string} 223 */ 224 static uc_value_t * 225 uc_digest_fnv1a64_file(uc_vm_t *vm, size_t nargs) 226 { 227 return uc_digest_calc_file(uc_fn_arg(0), uc_digest_fnv1a64_file_hash); 228 } 229 230 #ifdef HAVE_DIGEST_EXTENDED 231 /** 232 * Calculates the MD2 hash of string and returns that hash. 233 * 234 * Returns `null` if a non-string argument is given. 235 * 236 * @function module:digest#md2 237 * 238 * @param {string} str 239 * The string to hash. 240 * 241 * @returns {?string} 242 * 243 * @example 244 * md2("This is a test"); // Returns "dc378580fd0722e56b82666a6994c718" 245 * md2(123); // Returns null 246 */ 247 static uc_value_t * 248 uc_digest_md2(uc_vm_t *vm, size_t nargs) 249 { 250 return uc_digest_calc_data(uc_fn_arg(0), MD2Data); 251 } 252 253 /** 254 * Calculates the MD4 hash of string and returns that hash. 255 * 256 * Returns `null` if a non-string argument is given. 257 * 258 * @function module:digest#md4 259 * 260 * @param {string} str 261 * The string to hash. 262 * 263 * @returns {?string} 264 * 265 * @example 266 * md4("This is a test"); // Returns "3b487cf6856af7e330bc4b1b7d977ef8" 267 * md4(123); // Returns null 268 */ 269 static uc_value_t * 270 uc_digest_md4(uc_vm_t *vm, size_t nargs) 271 { 272 return uc_digest_calc_data(uc_fn_arg(0), MD4Data); 273 } 274 275 /** 276 * Calculates the SHA384 hash of string and returns that hash. 277 * 278 * Returns `null` if a non-string argument is given. 279 * 280 * @function module:digest#sha384 281 * 282 * @param {string} str 283 * The string to hash. 284 * 285 * @returns {?string} 286 * 287 * @example 288 * sha384("This is a test"); // Returns "a27c7667e58200d4c0688ea136968404a0da366b1a9fc19bb38a0c7a609a1eef2bcc82837f4f4d92031a66051494b38c" 289 * sha384(123); // Returns null 290 */ 291 static uc_value_t * 292 uc_digest_sha384(uc_vm_t *vm, size_t nargs) 293 { 294 return uc_digest_calc_data(uc_fn_arg(0), SHA384Data); 295 } 296 297 /** 298 * Calculates the SHA512 hash of string and returns that hash. 299 * 300 * Returns `null` if a non-string argument is given. 301 * 302 * @function module:digest#sha512 303 * 304 * @param {string} str 305 * The string to hash. 306 * 307 * @returns {?string} 308 * 309 * @example 310 * sha512("This is a test"); // Returns "a028d4f74b602ba45eb0a93c9a4677240dcf281a1a9322f183bd32f0bed82ec72de9c3957b2f4c9a1ccf7ed14f85d73498df38017e703d47ebb9f0b3bf116f69" 311 * sha512(123); // Returns null 312 */ 313 static uc_value_t * 314 uc_digest_sha512(uc_vm_t *vm, size_t nargs) 315 { 316 return uc_digest_calc_data(uc_fn_arg(0), SHA512Data); 317 } 318 #endif 319 320 /** 321 * Calculates the MD5 hash of a given file and returns that hash. 322 * 323 * Returns `null` if an error occurred. 324 * 325 * @function module:digest#md5_file 326 * 327 * @param {string} path 328 * The path to the file. 329 * 330 * @returns {?string} 331 */ 332 static uc_value_t * 333 uc_digest_md5_file(uc_vm_t *vm, size_t nargs) 334 { 335 return uc_digest_calc_file(uc_fn_arg(0), MD5File); 336 } 337 338 /** 339 * Calculates the SHA1 hash of a given file and returns that hash. 340 * 341 * Returns `null` if an error occurred. 342 * 343 * @function module:digest#sha1_file 344 * 345 * @param {string} path 346 * The path to the file. 347 * 348 * @returns {?string} 349 */ 350 static uc_value_t * 351 uc_digest_sha1_file(uc_vm_t *vm, size_t nargs) 352 { 353 return uc_digest_calc_file(uc_fn_arg(0), SHA1File); 354 } 355 356 /** 357 * Calculates the SHA256 hash of a given file and returns that hash. 358 * 359 * Returns `null` if an error occurred. 360 * 361 * @function module:digest#sha256_file 362 * 363 * @param {string} path 364 * The path to the file. 365 * 366 * @returns {?string} 367 */ 368 static uc_value_t * 369 uc_digest_sha256_file(uc_vm_t *vm, size_t nargs) 370 { 371 return uc_digest_calc_file(uc_fn_arg(0), SHA256File); 372 } 373 374 #ifdef HAVE_DIGEST_EXTENDED 375 /** 376 * Calculates the MD2 hash of a given file and returns that hash. 377 * 378 * Returns `null` if an error occurred. 379 * 380 * @function module:digest#md2_file 381 * 382 * @param {string} path 383 * The path to the file. 384 * 385 * @returns {?string} 386 */ 387 static uc_value_t * 388 uc_digest_md2_file(uc_vm_t *vm, size_t nargs) 389 { 390 return uc_digest_calc_file(uc_fn_arg(0), MD2File); 391 } 392 393 /** 394 * Calculates the MD4 hash of a given file and returns that hash. 395 * 396 * Returns `null` if an error occurred. 397 * 398 * @function module:digest#md4_file 399 * 400 * @param {string} path 401 * The path to the file. 402 * 403 * @returns {?string} 404 */ 405 static uc_value_t * 406 uc_digest_md4_file(uc_vm_t *vm, size_t nargs) 407 { 408 return uc_digest_calc_file(uc_fn_arg(0), MD4File); 409 } 410 411 /** 412 * Calculates the SHA384 hash of a given file and returns that hash. 413 * 414 * Returns `null` if an error occurred. 415 * 416 * @function module:digest#sha384_file 417 * 418 * @param {string} path 419 * The path to the file. 420 * 421 * @returns {?string} 422 */ 423 static uc_value_t * 424 uc_digest_sha384_file(uc_vm_t *vm, size_t nargs) 425 { 426 return uc_digest_calc_file(uc_fn_arg(0), SHA384File); 427 } 428 429 /** 430 * Calculates the SHA512 hash of a given file and returns that hash. 431 * 432 * Returns `null` if an error occurred. 433 * 434 * @function module:digest#sha512_file 435 * 436 * @param {string} path 437 * The path to the file. 438 * 439 * @returns {?string} 440 */ 441 static uc_value_t * 442 uc_digest_sha512_file(uc_vm_t *vm, size_t nargs) 443 { 444 return uc_digest_calc_file(uc_fn_arg(0), SHA512File); 445 } 446 #endif 447 448 449 static const uc_function_list_t global_fns[] = { 450 { "md5", uc_digest_md5 }, 451 { "sha1", uc_digest_sha1 }, 452 { "sha256", uc_digest_sha256 }, 453 { "fnv1a64", uc_digest_fnv1a64 }, 454 { "md5_file", uc_digest_md5_file }, 455 { "sha1_file", uc_digest_sha1_file }, 456 { "sha256_file", uc_digest_sha256_file }, 457 { "fnv1a64_file",uc_digest_fnv1a64_file}, 458 #ifdef HAVE_DIGEST_EXTENDED 459 { "md2", uc_digest_md2 }, 460 { "md4", uc_digest_md4 }, 461 { "sha384", uc_digest_sha384 }, 462 { "sha512", uc_digest_sha512 }, 463 { "md2_file", uc_digest_md2_file }, 464 { "md4_file", uc_digest_md4_file }, 465 { "sha384_file", uc_digest_sha384_file }, 466 { "sha512_file", uc_digest_sha512_file }, 467 #endif 468 }; 469 470 void uc_module_init(uc_vm_t *vm, uc_value_t *scope) 471 { 472 uc_function_list_register(scope, global_fns); 473 } 474
This page was automatically generated by LXR 0.3.1. • OpenWrt