qr_reader-native 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-mruby.txt +22 -0
  3. data/LICENSE-spinel.txt +19 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +61 -0
  6. data/ext/qr_reader_native/SPINEL_VERSION +1 -0
  7. data/ext/qr_reader_native/extconf.rb +8 -0
  8. data/ext/qr_reader_native/mruby/error.h +13 -0
  9. data/ext/qr_reader_native/mruby/internal.h +145 -0
  10. data/ext/qr_reader_native/mruby/string.h +22 -0
  11. data/ext/qr_reader_native/mruby.h +93 -0
  12. data/ext/qr_reader_native/mruby_shim.h +118 -0
  13. data/ext/qr_reader_native/qr_reader_native.c +13513 -0
  14. data/ext/qr_reader_native/qr_reader_native.h +29 -0
  15. data/ext/qr_reader_native/qr_reader_native_ext.c +598 -0
  16. data/ext/qr_reader_native/re_cased.h +71 -0
  17. data/ext/qr_reader_native/re_compile.c +5784 -0
  18. data/ext/qr_reader_native/re_ctype.h +3540 -0
  19. data/ext/qr_reader_native/re_exec.c +2190 -0
  20. data/ext/qr_reader_native/re_internal.h +671 -0
  21. data/ext/qr_reader_native/re_prop.h +4629 -0
  22. data/ext/qr_reader_native/re_spinel.c +363 -0
  23. data/ext/qr_reader_native/re_spinel.h +22 -0
  24. data/ext/qr_reader_native/re_spinel_utf8.inc +97 -0
  25. data/ext/qr_reader_native/re_utf8.c +156 -0
  26. data/ext/qr_reader_native/sp_alloc.c +1447 -0
  27. data/ext/qr_reader_native/sp_alloc.h +1196 -0
  28. data/ext/qr_reader_native/sp_argf.h +33 -0
  29. data/ext/qr_reader_native/sp_array.c +1052 -0
  30. data/ext/qr_reader_native/sp_array.h +456 -0
  31. data/ext/qr_reader_native/sp_bigint.c +5826 -0
  32. data/ext/qr_reader_native/sp_bigint.h +117 -0
  33. data/ext/qr_reader_native/sp_cold.c +5259 -0
  34. data/ext/qr_reader_native/sp_compat.h +402 -0
  35. data/ext/qr_reader_native/sp_core.c +818 -0
  36. data/ext/qr_reader_native/sp_core.h +56 -0
  37. data/ext/qr_reader_native/sp_crypto.c +877 -0
  38. data/ext/qr_reader_native/sp_crypto.h +169 -0
  39. data/ext/qr_reader_native/sp_dtoa.c +1533 -0
  40. data/ext/qr_reader_native/sp_dtoa.h +29 -0
  41. data/ext/qr_reader_native/sp_encoding_names.h +172 -0
  42. data/ext/qr_reader_native/sp_enum.h +86 -0
  43. data/ext/qr_reader_native/sp_exc.c +1185 -0
  44. data/ext/qr_reader_native/sp_exc.h +186 -0
  45. data/ext/qr_reader_native/sp_exc_ctx.h +56 -0
  46. data/ext/qr_reader_native/sp_fiber.c +889 -0
  47. data/ext/qr_reader_native/sp_fiber.h +162 -0
  48. data/ext/qr_reader_native/sp_fiber_ctx.h +84 -0
  49. data/ext/qr_reader_native/sp_format.c +695 -0
  50. data/ext/qr_reader_native/sp_format.h +83 -0
  51. data/ext/qr_reader_native/sp_gc.c +1793 -0
  52. data/ext/qr_reader_native/sp_gc.h +762 -0
  53. data/ext/qr_reader_native/sp_hash.c +131 -0
  54. data/ext/qr_reader_native/sp_hash.h +131 -0
  55. data/ext/qr_reader_native/sp_inspect.c +215 -0
  56. data/ext/qr_reader_native/sp_inspect.h +128 -0
  57. data/ext/qr_reader_native/sp_io.c +1676 -0
  58. data/ext/qr_reader_native/sp_io.h +272 -0
  59. data/ext/qr_reader_native/sp_iobuffer.c +1014 -0
  60. data/ext/qr_reader_native/sp_iobuffer.h +167 -0
  61. data/ext/qr_reader_native/sp_marshal.c +487 -0
  62. data/ext/qr_reader_native/sp_marshal.h +60 -0
  63. data/ext/qr_reader_native/sp_net.c +1029 -0
  64. data/ext/qr_reader_native/sp_net.h +205 -0
  65. data/ext/qr_reader_native/sp_pack.c +1254 -0
  66. data/ext/qr_reader_native/sp_poly_cold.c +1220 -0
  67. data/ext/qr_reader_native/sp_proc.c +410 -0
  68. data/ext/qr_reader_native/sp_proc.h +327 -0
  69. data/ext/qr_reader_native/sp_process.c +547 -0
  70. data/ext/qr_reader_native/sp_process_status.c +211 -0
  71. data/ext/qr_reader_native/sp_process_status.h +66 -0
  72. data/ext/qr_reader_native/sp_random.c +287 -0
  73. data/ext/qr_reader_native/sp_random.h +52 -0
  74. data/ext/qr_reader_native/sp_range.h +144 -0
  75. data/ext/qr_reader_native/sp_re.c +1379 -0
  76. data/ext/qr_reader_native/sp_re.h +186 -0
  77. data/ext/qr_reader_native/sp_re_names.h +59 -0
  78. data/ext/qr_reader_native/sp_sched.c +4044 -0
  79. data/ext/qr_reader_native/sp_sched.h +295 -0
  80. data/ext/qr_reader_native/sp_slab.c +1507 -0
  81. data/ext/qr_reader_native/sp_str.c +1462 -0
  82. data/ext/qr_reader_native/sp_str.h +306 -0
  83. data/ext/qr_reader_native/sp_str_crypt.c +23 -0
  84. data/ext/qr_reader_native/sp_string.c +92 -0
  85. data/ext/qr_reader_native/sp_string.h +253 -0
  86. data/ext/qr_reader_native/sp_system.c +78 -0
  87. data/ext/qr_reader_native/sp_system.h +18 -0
  88. data/ext/qr_reader_native/sp_time.c +860 -0
  89. data/ext/qr_reader_native/sp_time.h +100 -0
  90. data/ext/qr_reader_native/sp_types.h +292 -0
  91. data/ext/qr_reader_native/spinel_rt.h +19017 -0
  92. data/ext/qr_reader_native/unicase.c +399 -0
  93. data/ext/qr_reader_native/unicase.h +901 -0
  94. data/lib/qr_reader/native.rb +6 -0
  95. metadata +153 -0
@@ -0,0 +1,169 @@
1
+ /* sp_crypto.h -- Compact SHA-256 / HMAC / PBKDF2 / Base64URL / CSPRNG
2
+ *
3
+ * Pure C, no spinel-runtime dependency. Intended for spinel programs
4
+ * that need a small in-tree crypto surface without dragging in
5
+ * OpenSSL or libsodium. Sibling to sp_bigint.{h,c} in scope: a
6
+ * vendored, audit-sized C helper that ships with spinel so apps
7
+ * don't each reinvent it.
8
+ *
9
+ * The seven functions below are the canonical surface tep ended up
10
+ * with after a year of building on the same primitives -- if you
11
+ * find yourself wanting a different shape, please file an issue
12
+ * before adding to this list. The point is to keep the surface
13
+ * small enough to read in one sitting.
14
+ *
15
+ * Naming
16
+ * ------
17
+ * All exported symbols use the `sp_crypto_` prefix (matches the
18
+ * `sp_bigint_` convention). State buffers are per-function statics
19
+ * -- the next call to the same function clobbers the buffer, so
20
+ * copy on the caller side if the value must outlive the next call.
21
+ *
22
+ * Inputs
23
+ * ------
24
+ * String inputs are NUL-terminated. Length is taken via strlen()
25
+ * inside each function. For binary-safe inputs (containing embedded
26
+ * NULs), use the explicit-length internal API exposed by including
27
+ * this header in your own .c file -- see sp_crypto.c for the
28
+ * declarations.
29
+ *
30
+ * Thread safety
31
+ * -------------
32
+ * The return buffers are SP_TLS, so an answer belongs to the thread
33
+ * that asked for it. The clobber rule above still holds, per thread:
34
+ * the next call to the same function on the SAME thread overwrites
35
+ * it, and a caller that needs the value to outlive that call still
36
+ * copies.
37
+ *
38
+ * They were process-global until #4174, whose SecureRandom draw made
39
+ * the cost visible -- eight threads minting tokens got about a third
40
+ * of them from another thread's buffer. Every function here has the
41
+ * same window, because every call site copies out of the buffer after
42
+ * the call has RETURNED. "Caller-side serialize" was not a contract
43
+ * a caller could keep: Digest::SHA256.hexdigest is an ordinary Ruby
44
+ * method with nothing at the call site to serialize against.
45
+ *
46
+ * SP_TLS is __thread only in the -DSP_THREADS runtime variant, so a
47
+ * program that never threads pays nothing: its sp_crypto.o is the
48
+ * byte-identical object it was. The threaded variant pays the buffers
49
+ * per WORKER -- ~32 KiB of that is the two 16 KiB base64url buffers
50
+ * and everything else together is under 600 bytes -- and the worker
51
+ * pool is bounded by min(cores, SPINEL_WORKERS), not by the number of
52
+ * Ruby threads the program starts.
53
+ */
54
+ #ifndef SP_CRYPTO_H
55
+ #define SP_CRYPTO_H
56
+
57
+ #ifdef __cplusplus
58
+ extern "C" {
59
+ #endif
60
+
61
+ /* SHA-1(msg) -> 40-char lowercase hex. Legacy hash, kept for
62
+ * WebSocket handshake (RFC 6455 §1.3 requires SHA-1). Do NOT
63
+ * use for new security designs; SHA-256 is the right primitive. */
64
+ const char *sp_crypto_sha1_hex(const char *msg);
65
+
66
+ /* SHA-256(msg) -> 64-char lowercase hex. */
67
+ const char *sp_crypto_sha256_hex(const char *msg);
68
+
69
+ /* Raw digest bytes: 32 for SHA-256, 20 for SHA-1. The result is NOT
70
+ * NUL-terminated data -- it is arbitrary bytes -- so the length is published
71
+ * in sp_ffi_bin_len (sp_alloc.h) for the `:cbinstr` / `:binstr` return modes
72
+ * to pick up. Callers reading these directly must use the same length. */
73
+ const char *sp_crypto_sha256_bin(const char *msg);
74
+ const char *sp_crypto_sha1_bin(const char *msg);
75
+
76
+ /* MD5(msg) -> 32-char lowercase hex / the raw 16 digest bytes. Legacy hash,
77
+ * bound for Digest::MD5 (Active Storage's direct-upload checksum). Do NOT
78
+ * use for new security designs. */
79
+ const char *sp_crypto_md5_hex(const char *msg);
80
+ const char *sp_crypto_md5_bin(const char *msg);
81
+
82
+ /* Digest::X.base64digest: strict base64 of the raw digest (24, 28 and 44
83
+ * chars, `=` padded). */
84
+ const char *sp_crypto_md5_b64(const char *msg);
85
+ const char *sp_crypto_sha1_b64(const char *msg);
86
+ const char *sp_crypto_sha256_b64(const char *msg);
87
+
88
+ /* Sec-WebSocket-Accept = base64(SHA-1(client_key + GUID)) per
89
+ * RFC 6455 §1.3. Returns a 28-char string ending in `=`. The
90
+ * only modern use case for SHA-1 in this codebase; sugars the
91
+ * concat+sha1+base64 dance into one call. */
92
+ const char *sp_crypto_websocket_accept(const char *client_key);
93
+
94
+ /* HMAC-SHA256(key, msg) -> 64-char lowercase hex. */
95
+ const char *sp_crypto_hmac_sha256_hex(const char *key, const char *msg);
96
+
97
+ /* HMAC-SHA256(key, msg) -> 43-char unpadded base64url. */
98
+ const char *sp_crypto_hmac_sha256_b64url(const char *key, const char *msg);
99
+
100
+ /* HMAC-SHA256(key, msg) / HMAC-SHA1(key, msg) -> the raw digest bytes
101
+ * (32 and 20). Same buffer contract as sp_crypto_sha256_bin above: the
102
+ * result is not NUL-terminated, and its length rides sp_ffi_bin_len.
103
+ *
104
+ * The hex spellings beside these are the right primitive when a human or
105
+ * a protocol header reads the answer. These are for when it feeds another
106
+ * primitive: HKDF (RFC 5869) is HMAC over raw bytes twice, and hex-then-
107
+ * decode would be a lossless detour with a chance to get the decode
108
+ * wrong. */
109
+ const char *sp_crypto_hmac_sha256_bin(const char *key, const char *msg);
110
+ const char *sp_crypto_hmac_sha1_bin(const char *key, const char *msg);
111
+
112
+ /* HMAC-SHA1(key, msg) -> 40-char lowercase hex. Here for the same
113
+ * reason sp_crypto_websocket_accept is -- an existing protocol names
114
+ * SHA-1 and reproducing it is not a new security design. Rails signs
115
+ * cookies with HMAC-SHA1 unless the app sets
116
+ * config.action_dispatch.cookies_digest, so a program reading one has
117
+ * no choice of digest. Do NOT reach for this when you do have a
118
+ * choice; sp_crypto_hmac_sha256_hex is the right primitive. */
119
+ const char *sp_crypto_hmac_sha1_hex(const char *key, const char *msg);
120
+
121
+ /* Base64URL (RFC 4648 §5, no padding) encode/decode. Max input
122
+ * length ~12 KiB (encode) / ~16 KiB (decode), bump the buffer in
123
+ * sp_crypto.c if your callers need more. The decode answers bytes that
124
+ * may hold a NUL and sets sp_ffi_bin_len to their count (0 on bad input):
125
+ * bind it `:binstr`, as a `:str` return stops at the first NUL. */
126
+ const char *sp_crypto_b64url_encode(const char *src);
127
+ const char *sp_crypto_b64url_decode(const char *src);
128
+
129
+ /* PBKDF2-HMAC-SHA256(password, salt, iters) -> 43-char unpadded
130
+ * base64url (32 bytes derived -- the one-block case). */
131
+ const char *sp_crypto_pbkdf2_sha256_b64url(const char *password, const char *salt, int iters);
132
+
133
+ /* Same, with an explicit derived length in BYTES (clamped to [1, 64]);
134
+ * 64 bytes -> 86 unpadded b64url chars. Rails derives its signed-cookie
135
+ * and signed-id keys at dkLen 64 (ActiveSupport::KeyGenerator#
136
+ * generate_key's default key_size), so a spinel program that reads or
137
+ * mints one needs the two-block form. */
138
+ const char *sp_crypto_pbkdf2_sha256_b64url_len(const char *password, const char *salt,
139
+ int iters, int dklen);
140
+
141
+ /* Largest single draw the raw-bytes entry point below serves. Covers
142
+ * every SecureRandom shape a program reaches for (a v4 uuid is 16, a
143
+ * session token 24, a 256-bit key 32); a larger request is an
144
+ * ArgumentError rather than a silently short answer. */
145
+ #define SPC_RANDOM_MAX 256
146
+
147
+ /* nbytes raw CSPRNG bytes, with the count published in sp_ffi_bin_len
148
+ * for the `:cbinstr` return mode (random bytes contain NULs). Uses
149
+ * arc4random_buf on BSD/macOS; on Linux/POSIX getrandom(2), then
150
+ * /dev/urandom. RAISES when no secure source is available -- a caller
151
+ * asking for random bytes is minting a token, and there is no answer
152
+ * to give. The bundled `securerandom` package binds this. */
153
+ /* Fill `out` with `nbytes` of kernel-sourced entropy. 1 on success, 0 when
154
+ there is no secure source -- callers fail closed rather than fall back to
155
+ weak randomness. The one place that decides what counts as secure. */
156
+ int sp_crypto_entropy(unsigned char *out, int nbytes);
157
+ const char *sp_crypto_random_bin(int nbytes);
158
+
159
+ /* CSPRNG: nbytes random bytes (clamped to [1, 64]) as unpadded
160
+ * base64url. Uses arc4random_buf on BSD/macOS; on Linux/POSIX
161
+ * getrandom(2), then /dev/urandom. Returns NULL when no secure source
162
+ * is available (fails closed -- never degrades to weak randomness). */
163
+ const char *sp_crypto_random_b64url(int nbytes);
164
+
165
+ #ifdef __cplusplus
166
+ }
167
+ #endif
168
+
169
+ #endif /* SP_CRYPTO_H */