crypt.cpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /*
  2. * Copyright (c) 2020, Peter Elliott <pelliott@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Base64.h>
  7. #include <AK/Types.h>
  8. #include <LibCrypto/Hash/SHA2.h>
  9. #include <crypt.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. extern "C" {
  13. static struct crypt_data crypt_data;
  14. char* crypt(char const* key, char const* salt)
  15. {
  16. crypt_data.initialized = true;
  17. return crypt_r(key, salt, &crypt_data);
  18. }
  19. static constexpr size_t crypt_salt_max = 16;
  20. static constexpr size_t sha_string_length = 44;
  21. char* crypt_r(char const* key, char const* salt, struct crypt_data* data)
  22. {
  23. if (!data->initialized) {
  24. errno = EINVAL;
  25. return nullptr;
  26. }
  27. if (salt[0] == '$') {
  28. if (salt[1] == '5') {
  29. char const* salt_value = salt + 3;
  30. size_t salt_len = min(strcspn(salt_value, "$"), crypt_salt_max);
  31. size_t header_len = salt_len + 3;
  32. bool fits = String(salt, header_len).copy_characters_to_buffer(data->result, sizeof(data->result));
  33. if (!fits) {
  34. errno = EINVAL;
  35. return nullptr;
  36. }
  37. data->result[header_len] = '$';
  38. Crypto::Hash::SHA256 sha;
  39. sha.update(StringView { key, strlen(key) });
  40. sha.update((u8 const*)salt_value, salt_len);
  41. auto digest = sha.digest();
  42. auto string = encode_base64(ReadonlyBytes(digest.immutable_data(), digest.data_length()));
  43. fits = string.copy_characters_to_buffer(data->result + header_len + 1, sizeof(data->result) - header_len - 1);
  44. if (!fits) {
  45. errno = EINVAL;
  46. return nullptr;
  47. }
  48. return data->result;
  49. }
  50. }
  51. // DES crypt is not available.
  52. errno = EINVAL;
  53. return nullptr;
  54. }
  55. }