Crypto.cpp 4.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. * Copyright (c) 2022, stelar7 <dudedbz@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Random.h>
  8. #include <AK/StringBuilder.h>
  9. #include <LibJS/Runtime/TypedArray.h>
  10. #include <LibWeb/Bindings/Wrapper.h>
  11. #include <LibWeb/Crypto/Crypto.h>
  12. #include <LibWeb/Crypto/SubtleCrypto.h>
  13. namespace Web::Crypto {
  14. Crypto::Crypto()
  15. : m_subtle(SubtleCrypto::create())
  16. {
  17. }
  18. // https://w3c.github.io/webcrypto/#dfn-Crypto-method-getRandomValues
  19. DOM::ExceptionOr<JS::Value> Crypto::get_random_values(JS::Value array) const
  20. {
  21. // 1. If array is not an Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array, then throw a TypeMismatchError and terminate the algorithm.
  22. if (!array.is_object() || !(is<JS::Int8Array>(array.as_object()) || is<JS::Uint8Array>(array.as_object()) || is<JS::Uint8ClampedArray>(array.as_object()) || is<JS::Int16Array>(array.as_object()) || is<JS::Uint16Array>(array.as_object()) || is<JS::Int32Array>(array.as_object()) || is<JS::Uint32Array>(array.as_object()) || is<JS::BigInt64Array>(array.as_object()) || is<JS::BigUint64Array>(array.as_object())))
  23. return DOM::TypeMismatchError::create("array must be one of Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array");
  24. auto& typed_array = static_cast<JS::TypedArrayBase&>(array.as_object());
  25. // 2. If the byteLength of array is greater than 65536, throw a QuotaExceededError and terminate the algorithm.
  26. if (typed_array.byte_length() > 65536)
  27. return DOM::QuotaExceededError::create("array's byteLength may not be greater than 65536");
  28. // IMPLEMENTATION DEFINED: If the viewed array buffer is detached, throw a InvalidStateError and terminate the algorithm.
  29. if (typed_array.viewed_array_buffer()->is_detached())
  30. return DOM::InvalidStateError::create("array is detached");
  31. // FIXME: Handle SharedArrayBuffers
  32. // 3. Overwrite all elements of array with cryptographically strong random values of the appropriate type.
  33. fill_with_random(typed_array.viewed_array_buffer()->buffer().data(), typed_array.viewed_array_buffer()->buffer().size());
  34. // 4. Return array.
  35. return array;
  36. }
  37. // https://w3c.github.io/webcrypto/#dfn-Crypto-method-randomUUID
  38. String Crypto::random_uuid() const
  39. {
  40. // 1. Let bytes be a byte sequence of length 16.
  41. u8 bytes[16];
  42. // 2. Fill bytes with cryptographically secure random bytes.
  43. fill_with_random(bytes, 16);
  44. // 3. Set the 4 most significant bits of bytes[6], which represent the UUID version, to 0100.
  45. bytes[6] &= ~(1 << 7);
  46. bytes[6] |= 1 << 6;
  47. bytes[6] &= ~(1 << 5);
  48. bytes[6] &= ~(1 << 4);
  49. // 4. Set the 2 most significant bits of bytes[8], which represent the UUID variant, to 10.
  50. bytes[8] |= 1 << 7;
  51. bytes[8] &= ~(1 << 6);
  52. /* 5. Return the string concatenation of
  53. «
  54. hexadecimal representation of bytes[0],
  55. hexadecimal representation of bytes[1],
  56. hexadecimal representation of bytes[2],
  57. hexadecimal representation of bytes[3],
  58. "-",
  59. hexadecimal representation of bytes[4],
  60. hexadecimal representation of bytes[5],
  61. "-",
  62. hexadecimal representation of bytes[6],
  63. hexadecimal representation of bytes[7],
  64. "-",
  65. hexadecimal representation of bytes[8],
  66. hexadecimal representation of bytes[9],
  67. "-",
  68. hexadecimal representation of bytes[10],
  69. hexadecimal representation of bytes[11],
  70. hexadecimal representation of bytes[12],
  71. hexadecimal representation of bytes[13],
  72. hexadecimal representation of bytes[14],
  73. hexadecimal representation of bytes[15]
  74. ».
  75. */
  76. StringBuilder builder;
  77. builder.appendff("{:02x}{:02x}{:02x}{:02x}-", bytes[0], bytes[1], bytes[2], bytes[3]);
  78. builder.appendff("{:02x}{:02x}-", bytes[4], bytes[5]);
  79. builder.appendff("{:02x}{:02x}-", bytes[6], bytes[7]);
  80. builder.appendff("{:02x}{:02x}-", bytes[8], bytes[9]);
  81. builder.appendff("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]);
  82. return builder.to_string();
  83. }
  84. }