@scriptc/cli-darwin-arm64 0.2.1 → 0.2.2
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.
- package/dist/THIRD_PARTY_NOTICES +1 -1
- package/dist/bin/scriptc +0 -0
- package/dist/bin/scriptc.json +1 -1
- package/dist/lib/declarations/scriptc-node-fallback.d.ts +59 -4
- package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
- package/dist/lib/llvm/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/runtime-pack.json +177 -177
- package/dist/lib/runtime-sources/package.json +1 -1
- package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
- package/dist/lib/runtime-sources/src/scr_async.c +12 -4
- package/dist/lib/runtime-sources/src/scr_async_dyn.c +118 -24
- package/dist/lib/runtime-sources/src/scr_bytes.c +226 -0
- package/dist/lib/runtime-sources/src/scr_bytes_io.c +52 -5
- package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
- package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +181 -43
- package/dist/lib/runtime-sources/src/scr_fetch.c +45 -1
- package/dist/lib/runtime-sources/src/scr_file_handle.c +31 -0
- package/dist/lib/runtime-sources/src/scr_island.c +1188 -392
- package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -9
- package/dist/lib/runtime-sources/src/scr_json.c +449 -52
- package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
- package/dist/lib/runtime-sources/src/scr_lib.c +816 -34
- package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
- package/dist/lib/runtime-sources/src/scr_regex.c +42 -5
- package/dist/lib/runtime-sources/src/scr_runtime.h +67 -8
- package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +12 -12
- package/dist/lib/runtime-sources/src/scr_url.c +34 -7
- package/dist/lib/runtime-sources/src/scr_web.c +129 -26
- package/package.json +1 -1
|
@@ -729,6 +729,233 @@ void scr_env_unset(const ScrStr *name) {
|
|
|
729
729
|
#endif
|
|
730
730
|
}
|
|
731
731
|
|
|
732
|
+
static ScrStr *scr_fs_read_file_core(ScrStr *path, bool env_file);
|
|
733
|
+
|
|
734
|
+
/* Node's dotenv parser trims ASCII space/tab/newline and removes every CR,
|
|
735
|
+
* including CR inside quoted values. Quoted values can span lines; only
|
|
736
|
+
* double quotes expand backslash-n. Preserve the pinned parser's ordering
|
|
737
|
+
* of empty-value and export-prefix handling, including its unusual forms. */
|
|
738
|
+
static bool scr_env_space(char c) { return c == ' ' || c == '\t' || c == '\n'; }
|
|
739
|
+
|
|
740
|
+
static void scr_env_trim(const char *text, size_t *start, size_t *end) {
|
|
741
|
+
while (*start < *end && scr_env_space(text[*start])) (*start)++;
|
|
742
|
+
while (*end > *start && scr_env_space(text[*end - 1])) (*end)--;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
static void scr_env_store(ScrDyn *out, const char *text, size_t ks, size_t ke,
|
|
746
|
+
size_t vs, size_t ve, bool expand) {
|
|
747
|
+
ScrJsonBuf value;
|
|
748
|
+
scr_jb_init(&value);
|
|
749
|
+
for (size_t i = vs; i < ve; i++) {
|
|
750
|
+
if (expand && text[i] == '\\' && i + 1 < ve && text[i + 1] == 'n') {
|
|
751
|
+
scr_jb_putc(&value, '\n');
|
|
752
|
+
i++;
|
|
753
|
+
} else scr_jb_putc(&value, text[i]);
|
|
754
|
+
}
|
|
755
|
+
ScrStr *s = scr_jb_finish(&value);
|
|
756
|
+
scr_dyn_obj_set(out, text + ks, ke - ks, scr_dyn_new_str(s));
|
|
757
|
+
scr_str_release(s);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
static int scr_env_entry_order(const void *left, const void *right) {
|
|
761
|
+
const ScrDynEntry *a = *(const ScrDynEntry *const *)left;
|
|
762
|
+
const ScrDynEntry *b = *(const ScrDynEntry *const *)right;
|
|
763
|
+
size_t n = a->key_len < b->key_len ? a->key_len : b->key_len;
|
|
764
|
+
int cmp = memcmp(a->key, b->key, n);
|
|
765
|
+
return cmp ? cmp : (a->key_len > b->key_len) - (a->key_len < b->key_len);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
static ScrDyn *scr_env_parse_content(const ScrStr *input, bool ordinary) {
|
|
769
|
+
char *text = malloc(input->len + 1);
|
|
770
|
+
if (!text) scr_trap("scriptc: out of memory\n");
|
|
771
|
+
size_t end = 0;
|
|
772
|
+
for (size_t i = 0; i < input->len; i++) if (input->data[i] != '\r') text[end++] = input->data[i];
|
|
773
|
+
text[end] = '\0';
|
|
774
|
+
size_t pos = 0;
|
|
775
|
+
scr_env_trim(text, &pos, &end);
|
|
776
|
+
ScrDyn *entries = scr_dyn_new_obj_null_proto();
|
|
777
|
+
while (pos < end) {
|
|
778
|
+
if (text[pos] == '\n' || text[pos] == '#') {
|
|
779
|
+
while (pos < end && text[pos] != '\n') pos++;
|
|
780
|
+
if (pos < end) pos++;
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
size_t equal = pos;
|
|
784
|
+
while (equal < end && text[equal] != '=' && text[equal] != '\n') equal++;
|
|
785
|
+
if (equal == end) break;
|
|
786
|
+
if (text[equal] == '\n') {
|
|
787
|
+
pos = equal + 1;
|
|
788
|
+
scr_env_trim(text, &pos, &end);
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
size_t ks = pos, ke = equal;
|
|
792
|
+
scr_env_trim(text, &ks, &ke);
|
|
793
|
+
pos = equal + 1;
|
|
794
|
+
if (pos == end || text[pos] == '\n') {
|
|
795
|
+
scr_env_store(entries, text, ks, ke, pos, pos, false);
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
scr_env_trim(text, &pos, &end);
|
|
799
|
+
if (ks == ke) continue;
|
|
800
|
+
if (ke - ks >= 7 && memcmp(text + ks, "export ", 7) == 0) {
|
|
801
|
+
ks += 7;
|
|
802
|
+
scr_env_trim(text, &ks, &ke);
|
|
803
|
+
}
|
|
804
|
+
if (pos == end) {
|
|
805
|
+
scr_env_store(entries, text, ks, ke, pos, pos, false);
|
|
806
|
+
break;
|
|
807
|
+
}
|
|
808
|
+
char quote = text[pos];
|
|
809
|
+
if (quote == '\'' || quote == '"' || quote == '`') {
|
|
810
|
+
size_t closing = pos + 1;
|
|
811
|
+
while (closing < end && text[closing] != quote) closing++;
|
|
812
|
+
if (closing < end) {
|
|
813
|
+
scr_env_store(entries, text, ks, ke, pos + 1, closing, quote == '"');
|
|
814
|
+
pos = closing + 1;
|
|
815
|
+
while (pos < end && text[pos] != '\n') pos++;
|
|
816
|
+
if (pos < end) pos++;
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
size_t newline = pos;
|
|
820
|
+
while (newline < end && text[newline] != '\n') newline++;
|
|
821
|
+
scr_env_store(entries, text, ks, ke, pos, newline, false);
|
|
822
|
+
pos = newline < end ? newline + 1 : end;
|
|
823
|
+
} else {
|
|
824
|
+
size_t newline = pos;
|
|
825
|
+
while (newline < end && text[newline] != '\n') newline++;
|
|
826
|
+
size_t vs = pos, ve = pos;
|
|
827
|
+
while (ve < newline && text[ve] != '#') ve++;
|
|
828
|
+
scr_env_trim(text, &vs, &ve);
|
|
829
|
+
scr_env_store(entries, text, ks, ke, vs, ve, false);
|
|
830
|
+
pos = newline < end ? newline + 1 : end;
|
|
831
|
+
}
|
|
832
|
+
scr_env_trim(text, &pos, &end);
|
|
833
|
+
}
|
|
834
|
+
free(text);
|
|
835
|
+
/* Node's std::map orders UTF-8 keys before installing object properties.
|
|
836
|
+
* Ordinary objects ignore string-valued __proto__ assignments; loading
|
|
837
|
+
* the native environment retains that name as an ordinary variable. */
|
|
838
|
+
size_t count = entries->v.obj.len;
|
|
839
|
+
const ScrDynEntry **sorted = count ? malloc(count * sizeof(*sorted)) : NULL;
|
|
840
|
+
if (count && !sorted) scr_trap("scriptc: out of memory\n");
|
|
841
|
+
for (size_t i = 0; i < count; i++) sorted[i] = &entries->v.obj.entries[i];
|
|
842
|
+
if (count > 1) qsort(sorted, count, sizeof(*sorted), scr_env_entry_order);
|
|
843
|
+
ScrDyn *result = ordinary ? scr_dyn_new_obj() : scr_dyn_new_obj_null_proto();
|
|
844
|
+
for (size_t i = 0; i < count; i++) {
|
|
845
|
+
const ScrDynEntry *entry = sorted[i];
|
|
846
|
+
if (ordinary && entry->key_len == 9 && memcmp(entry->key, "__proto__", 9) == 0) continue;
|
|
847
|
+
if (!ordinary) {
|
|
848
|
+
scr_dyn_obj_set(result, entry->key, entry->key_len, scr_dyn_retain(entry->value));
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
/* Convert sorted entries to JS strings after parsing. */
|
|
852
|
+
ScrStr *key = scr_str_from_utf8_lossy((const uint8_t *)entry->key, entry->key_len);
|
|
853
|
+
const ScrStr *raw = entry->value->v.str;
|
|
854
|
+
ScrStr *value = scr_str_from_utf8_lossy((const uint8_t *)raw->data, raw->len);
|
|
855
|
+
scr_dyn_obj_set(result, key->data, key->len, scr_dyn_new_str(value));
|
|
856
|
+
scr_str_release(key);
|
|
857
|
+
scr_str_release(value);
|
|
858
|
+
}
|
|
859
|
+
free(sorted);
|
|
860
|
+
scr_dyn_release(entries);
|
|
861
|
+
return result;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
ScrDyn *scr_util_parse_env(const ScrDyn *content) {
|
|
865
|
+
if (content->kind != SCR_DYN_STR) {
|
|
866
|
+
scr_dyn_arg_type_fail("content", "of type string", content);
|
|
867
|
+
return NULL;
|
|
868
|
+
}
|
|
869
|
+
return scr_env_parse_content(content->v.str, true);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
static void scr_env_invalid_path(const ScrDyn *value, const ScrStr *path) {
|
|
873
|
+
ScrJsonBuf b;
|
|
874
|
+
scr_jb_init(&b);
|
|
875
|
+
scr_jb_puts(&b, "The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received ");
|
|
876
|
+
if (value->kind == SCR_DYN_BYTES) {
|
|
877
|
+
const ScrBytes *bytes = value->v.bytes;
|
|
878
|
+
if (value->buffer) {
|
|
879
|
+
scr_jb_puts(&b, "<Buffer");
|
|
880
|
+
for (size_t i = 0; i < bytes->len; i++) {
|
|
881
|
+
char hex[4];
|
|
882
|
+
snprintf(hex, sizeof hex, " %02x", bytes->data[i]);
|
|
883
|
+
scr_jb_puts(&b, hex);
|
|
884
|
+
}
|
|
885
|
+
scr_jb_putc(&b, '>');
|
|
886
|
+
} else {
|
|
887
|
+
char length[48];
|
|
888
|
+
snprintf(length, sizeof length, "Uint8Array(%zu) [ ", bytes->len);
|
|
889
|
+
scr_jb_puts(&b, length);
|
|
890
|
+
for (size_t i = 0; i < bytes->len; i++) {
|
|
891
|
+
char number[8];
|
|
892
|
+
snprintf(number, sizeof number, "%s%u", i ? ", " : "", bytes->data[i]);
|
|
893
|
+
scr_jb_puts(&b, number);
|
|
894
|
+
}
|
|
895
|
+
scr_jb_puts(&b, " ]");
|
|
896
|
+
}
|
|
897
|
+
} else {
|
|
898
|
+
char quote = memchr(path->data, '\'', path->len) ? '"' : '\'';
|
|
899
|
+
scr_jb_putc(&b, quote);
|
|
900
|
+
for (size_t i = 0; i < path->len; i++) {
|
|
901
|
+
unsigned char c = (unsigned char)path->data[i];
|
|
902
|
+
if (c == (unsigned char)quote || c == '\\') { scr_jb_putc(&b, '\\'); scr_jb_putc(&b, (char)c); }
|
|
903
|
+
else if (c == '\n') scr_jb_puts(&b, "\\n");
|
|
904
|
+
else if (c == '\r') scr_jb_puts(&b, "\\r");
|
|
905
|
+
else if (c == '\t') scr_jb_puts(&b, "\\t");
|
|
906
|
+
else if (c < 0x20 || c == 0x7f) {
|
|
907
|
+
char escape[5];
|
|
908
|
+
snprintf(escape, sizeof escape, "\\x%02X", c);
|
|
909
|
+
scr_jb_puts(&b, escape);
|
|
910
|
+
} else scr_jb_putc(&b, (char)c);
|
|
911
|
+
}
|
|
912
|
+
scr_jb_putc(&b, quote);
|
|
913
|
+
}
|
|
914
|
+
ScrStr *message = scr_jb_finish(&b);
|
|
915
|
+
scr_throw_error_msg_code(SCR_ERR_TYPE, message->data, message->len, "ERR_INVALID_ARG_VALUE");
|
|
916
|
+
scr_str_release(message);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
void scr_process_load_env_file(const ScrDyn *value) {
|
|
920
|
+
ScrStr *path;
|
|
921
|
+
if (value->kind == SCR_DYN_UNDEF || value->kind == SCR_DYN_NULL) path = scr_str_new("./.env", 6);
|
|
922
|
+
else if (value->kind == SCR_DYN_STR) path = scr_str_retain(value->v.str);
|
|
923
|
+
else if (scr_dyn_native_url_is(value)) path = scr_url_to_path(value->v.handle.ptr);
|
|
924
|
+
else if (scr_dyn_bytes_is(value, SCR_BYTES_U8)) path = scr_str_new((const char *)value->v.bytes->data, value->v.bytes->len);
|
|
925
|
+
else {
|
|
926
|
+
scr_dyn_arg_type_fail("path", "of type string or an instance of Buffer or URL", value);
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
if (!path) return;
|
|
930
|
+
if (memchr(path->data, 0, path->len)) {
|
|
931
|
+
scr_env_invalid_path(value, path);
|
|
932
|
+
scr_str_release(path);
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
ScrStr *content = scr_fs_read_file_core(path, true);
|
|
936
|
+
scr_str_release(path);
|
|
937
|
+
if (!content) return;
|
|
938
|
+
ScrDyn *entries = scr_env_parse_content(content, false);
|
|
939
|
+
scr_str_release(content);
|
|
940
|
+
for (size_t i = 0; i < entries->v.obj.len; i++) {
|
|
941
|
+
const ScrDynEntry *entry = &entries->v.obj.entries[i];
|
|
942
|
+
/* Node normalizes each raw sorted entry immediately before checking
|
|
943
|
+
* the environment. Distinct invalid byte keys can normalize alike;
|
|
944
|
+
* the first absent name wins, rather than the last parsed entry. */
|
|
945
|
+
ScrStr *key = scr_str_from_utf8_lossy((const uint8_t *)entry->key, entry->key_len);
|
|
946
|
+
ScrStr *existing = scr_env_get(key);
|
|
947
|
+
if (!existing) {
|
|
948
|
+
const ScrStr *raw = entry->value->v.str;
|
|
949
|
+
ScrStr *value = scr_str_from_utf8_lossy((const uint8_t *)raw->data, raw->len);
|
|
950
|
+
scr_env_set(key, value);
|
|
951
|
+
scr_str_release(value);
|
|
952
|
+
}
|
|
953
|
+
scr_str_release(existing);
|
|
954
|
+
scr_str_release(key);
|
|
955
|
+
}
|
|
956
|
+
scr_dyn_release(entries);
|
|
957
|
+
}
|
|
958
|
+
|
|
732
959
|
/* The whole environment as one fresh string[] of alternating
|
|
733
960
|
* [k0, v0, k1, v1, ...] entries in environ order — the raw material of the
|
|
734
961
|
* compiler's process.env snapshot record (insertion order = environ order,
|
|
@@ -2019,13 +2246,15 @@ void scr_fs_throw(int e, const char *op, const ScrStr *path) {
|
|
|
2019
2246
|
const char *name = scr_errno_name(e, namebuf, sizeof namebuf);
|
|
2020
2247
|
const char *text = scr_errno_text(e);
|
|
2021
2248
|
char pathbuf[PATH_MAX];
|
|
2022
|
-
const char *shown = scr_fs_err_path(path, pathbuf);
|
|
2249
|
+
const char *shown = path ? scr_fs_err_path(path, pathbuf) : "";
|
|
2023
2250
|
size_t cap = strlen(name) + strlen(text) + strlen(op) + strlen(shown) + 8;
|
|
2024
2251
|
char *msg = malloc(cap);
|
|
2025
2252
|
if (!msg) {
|
|
2026
2253
|
scr_trap("scriptc: out of memory\n");
|
|
2027
2254
|
}
|
|
2028
|
-
int len =
|
|
2255
|
+
int len = path
|
|
2256
|
+
? snprintf(msg, cap, "%s: %s, %s '%s'", name, text, op, shown)
|
|
2257
|
+
: snprintf(msg, cap, "%s: %s, %s", name, text, op);
|
|
2029
2258
|
/* A real Error instance (name "Error", message = Node's text) — what a
|
|
2030
2259
|
* typed catch's `e instanceof Error` + `e.message` observes in Node —
|
|
2031
2260
|
* with `code` stamped to the errno name (the exotic-errno fallback
|
|
@@ -2055,7 +2284,7 @@ static FILE *scr_fs_fopen(const ScrStr *path, const char *mode) {
|
|
|
2055
2284
|
#endif
|
|
2056
2285
|
}
|
|
2057
2286
|
|
|
2058
|
-
ScrStr *
|
|
2287
|
+
static ScrStr *scr_fs_read_file_core(ScrStr *path, bool env_file) {
|
|
2059
2288
|
FILE *f = scr_fs_fopen(path, "rb");
|
|
2060
2289
|
if (!f) {
|
|
2061
2290
|
scr_fs_throw(errno, "open", path);
|
|
@@ -2083,7 +2312,16 @@ ScrStr *scr_fs_read_file(ScrStr *path) {
|
|
|
2083
2312
|
int e = errno;
|
|
2084
2313
|
fclose(f);
|
|
2085
2314
|
free(buf);
|
|
2086
|
-
|
|
2315
|
+
if (env_file) {
|
|
2316
|
+
ScrJsonBuf b;
|
|
2317
|
+
scr_jb_init(&b);
|
|
2318
|
+
scr_jb_puts(&b, "Contents of '");
|
|
2319
|
+
scr_jb_put_str(&b, path);
|
|
2320
|
+
scr_jb_puts(&b, "' should be a valid string.");
|
|
2321
|
+
ScrStr *message = scr_jb_finish(&b);
|
|
2322
|
+
scr_throw_error_msg_code(SCR_ERR_TYPE, message->data, message->len, "ERR_INVALID_ARG_TYPE");
|
|
2323
|
+
scr_str_release(message);
|
|
2324
|
+
} else scr_fs_throw(e, "read", path);
|
|
2087
2325
|
return NULL;
|
|
2088
2326
|
}
|
|
2089
2327
|
fclose(f);
|
|
@@ -2092,6 +2330,11 @@ ScrStr *scr_fs_read_file(ScrStr *path) {
|
|
|
2092
2330
|
return s;
|
|
2093
2331
|
}
|
|
2094
2332
|
|
|
2333
|
+
ScrStr *scr_fs_read_file(ScrStr *path) {
|
|
2334
|
+
return scr_fs_read_file_core(path, false);
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
|
|
2095
2338
|
static ScrStr *scr_fs_realpath_common(ScrStr *path, const char *op) {
|
|
2096
2339
|
#ifdef _WIN32
|
|
2097
2340
|
WCHAR *wide = scr_fs_win_wide(path);
|
|
@@ -2353,6 +2596,20 @@ double scr_fs_open_numeric(ScrStr *path, double flags, double mode) {
|
|
|
2353
2596
|
}
|
|
2354
2597
|
|
|
2355
2598
|
static void scr_fs_throw_nopath(int e, const char *op);
|
|
2599
|
+
static bool scr_fs_write_fd_valid(double fd);
|
|
2600
|
+
|
|
2601
|
+
double scr_fs_open_native(ScrStr *path, double flags, double mode) {
|
|
2602
|
+
#ifdef _WIN32
|
|
2603
|
+
WCHAR *wide = scr_fs_win_wide(path);
|
|
2604
|
+
if (!wide) { scr_fs_throw(scr_fs_win_errno(GetLastError()), "open", path); return 0; }
|
|
2605
|
+
int fd = _wopen(wide, (int)flags | O_BINARY, (int)mode);
|
|
2606
|
+
free(wide);
|
|
2607
|
+
#else
|
|
2608
|
+
int fd = open(path->data, (int)flags | O_BINARY, (mode_t)mode);
|
|
2609
|
+
#endif
|
|
2610
|
+
if (fd < 0) { scr_fs_throw(errno, "open", path); return 0; }
|
|
2611
|
+
return (double)fd;
|
|
2612
|
+
}
|
|
2356
2613
|
|
|
2357
2614
|
void scr_fs_fchmod(double fd, double mode) {
|
|
2358
2615
|
#ifdef _WIN32
|
|
@@ -2374,6 +2631,40 @@ void scr_fs_fsync(double fd) {
|
|
|
2374
2631
|
#endif
|
|
2375
2632
|
}
|
|
2376
2633
|
|
|
2634
|
+
void scr_fs_fdatasync(double fd) {
|
|
2635
|
+
if (!scr_fs_write_fd_valid(fd)) return;
|
|
2636
|
+
#if defined(_WIN32)
|
|
2637
|
+
if (_commit((int)fd) != 0) scr_fs_throw_nopath(errno, "fdatasync");
|
|
2638
|
+
#elif defined(__APPLE__)
|
|
2639
|
+
/* macOS/libuv implements fdatasync with fsync. */
|
|
2640
|
+
if (fsync((int)fd) != 0) scr_fs_throw_nopath(errno, "fdatasync");
|
|
2641
|
+
#else
|
|
2642
|
+
if (fdatasync((int)fd) != 0) scr_fs_throw_nopath(errno, "fdatasync");
|
|
2643
|
+
#endif
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
void scr_fs_ftruncate(double fd, double length) {
|
|
2647
|
+
if (!scr_fs_write_fd_valid(fd)) return;
|
|
2648
|
+
char received[48], msg[192];
|
|
2649
|
+
scr_num_received(length, received);
|
|
2650
|
+
if (!(isfinite(length) && trunc(length) == length) ||
|
|
2651
|
+
length < -9007199254740991.0 || length > 9007199254740991.0) {
|
|
2652
|
+
const char *bound = isfinite(length) && trunc(length) == length
|
|
2653
|
+
? ">= -9007199254740991 && <= 9007199254740991" : "an integer";
|
|
2654
|
+
int n = snprintf(msg, sizeof msg,
|
|
2655
|
+
"The value of \"len\" is out of range. It must be %s. Received %s", bound, received);
|
|
2656
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)n, "ERR_OUT_OF_RANGE");
|
|
2657
|
+
return;
|
|
2658
|
+
}
|
|
2659
|
+
if (length < 0) length = 0;
|
|
2660
|
+
#ifdef _WIN32
|
|
2661
|
+
int error = (int)_chsize_s((int)fd, (__int64)length);
|
|
2662
|
+
if (error) scr_fs_throw_nopath(error, "ftruncate");
|
|
2663
|
+
#else
|
|
2664
|
+
if (ftruncate((int)fd, (off_t)length) != 0) scr_fs_throw_nopath(errno, "ftruncate");
|
|
2665
|
+
#endif
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2377
2668
|
/* fs.closeSync(fd) — close(2); failure throws Node's path-less fs error
|
|
2378
2669
|
* shape ("EBADF: bad file descriptor, close"). */
|
|
2379
2670
|
|
|
@@ -2771,6 +3062,73 @@ double scr_fs_read_sync(double fd, ScrBytes *buf, double offset, double length,
|
|
|
2771
3062
|
return (double)n;
|
|
2772
3063
|
}
|
|
2773
3064
|
|
|
3065
|
+
/* Gather/scatter one contiguous window around ONE kernel operation. Multiple
|
|
3066
|
+
* scalar calls would change short I/O and pipe atomicity. This portable seam
|
|
3067
|
+
* also preserves positioned I/O on targets without preadv/pwritev. */
|
|
3068
|
+
double scr_fs_read_zero(double fd, double position) {
|
|
3069
|
+
if (!scr_fs_write_fd_valid(fd)) return 0;
|
|
3070
|
+
uint8_t dummy;
|
|
3071
|
+
ssize_t n = position < 0 ? read((int)fd, &dummy, 0)
|
|
3072
|
+
: scr_fs_pread((int)fd, &dummy, 0, position);
|
|
3073
|
+
if (n < 0) scr_fs_throw_nopath(errno, "read");
|
|
3074
|
+
return 0;
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
static double scr_fs_vector_sync(double fd, ScrArr *buffers, double position,
|
|
3078
|
+
bool writing) {
|
|
3079
|
+
size_t count = (size_t)scr_arr_len(buffers);
|
|
3080
|
+
if (writing && count == 0) return 0;
|
|
3081
|
+
if (!scr_fs_write_fd_valid(fd)) return 0;
|
|
3082
|
+
if (count == 0) { scr_fs_throw_nopath(EINVAL, "read"); return 0; }
|
|
3083
|
+
size_t length = 0;
|
|
3084
|
+
for (size_t i = 0; i < count; i++) {
|
|
3085
|
+
ScrBytes *buf = scr_arr_get_ref(buffers, (double)i);
|
|
3086
|
+
size_t n = buf->len;
|
|
3087
|
+
scr_bytes_release(buf);
|
|
3088
|
+
if (n > SIZE_MAX - length) scr_trap("scriptc: vector I/O size overflow\n");
|
|
3089
|
+
length += n;
|
|
3090
|
+
}
|
|
3091
|
+
uint8_t *data = malloc(length ? length : 1);
|
|
3092
|
+
if (!data) scr_trap("scriptc: out of memory\n");
|
|
3093
|
+
if (writing) {
|
|
3094
|
+
size_t at = 0;
|
|
3095
|
+
for (size_t i = 0; i < count; i++) {
|
|
3096
|
+
ScrBytes *buf = scr_arr_get_ref(buffers, (double)i);
|
|
3097
|
+
if (buf->len) memcpy(data + at, buf->data, buf->len);
|
|
3098
|
+
at += buf->len;
|
|
3099
|
+
scr_bytes_release(buf);
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
ScrBytes window = {SIZE_MAX, length, SCR_BYTES_U8, data, NULL};
|
|
3103
|
+
position = isfinite(position) && position >= 0 && position <= 9007199254740991.0
|
|
3104
|
+
? trunc(position) : -1;
|
|
3105
|
+
double transferred = writing
|
|
3106
|
+
? scr_fs_write_sync(fd, &window, 0, (double)length, position)
|
|
3107
|
+
: length == 0 ? scr_fs_read_zero(fd, position)
|
|
3108
|
+
: scr_fs_read_sync(fd, &window, 0, (double)length, position);
|
|
3109
|
+
if (!writing && !scr_exc_pending()) {
|
|
3110
|
+
size_t at = 0, remaining = (size_t)transferred;
|
|
3111
|
+
for (size_t i = 0; i < count && remaining; i++) {
|
|
3112
|
+
ScrBytes *buf = scr_arr_get_ref(buffers, (double)i);
|
|
3113
|
+
size_t n = buf->len < remaining ? buf->len : remaining;
|
|
3114
|
+
if (n) memcpy(buf->data, data + at, n);
|
|
3115
|
+
at += n;
|
|
3116
|
+
remaining -= n;
|
|
3117
|
+
scr_bytes_release(buf);
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
free(data);
|
|
3121
|
+
return transferred;
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3124
|
+
double scr_fs_readv_sync(double fd, ScrArr *buffers, double position) {
|
|
3125
|
+
return scr_fs_vector_sync(fd, buffers, position, false);
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3128
|
+
double scr_fs_writev_sync(double fd, ScrArr *buffers, double position) {
|
|
3129
|
+
return scr_fs_vector_sync(fd, buffers, position, true);
|
|
3130
|
+
}
|
|
3131
|
+
|
|
2774
3132
|
void scr_fs_close(double fd) {
|
|
2775
3133
|
if (close((int)fd) != 0) {
|
|
2776
3134
|
int e = errno;
|
|
@@ -4256,7 +4614,7 @@ ScrStr *scr_crypto_random_string(double n, ScrStr *enc) {
|
|
|
4256
4614
|
return out;
|
|
4257
4615
|
}
|
|
4258
4616
|
|
|
4259
|
-
/* ── incremental MD5/SHA-1/SHA-
|
|
4617
|
+
/* ── incremental MD5/SHA-1/SHA-2 and HMAC ──────────────────────────
|
|
4260
4618
|
* The first-class Hash/Hmac handles, fused one-shot paths, island bridge,
|
|
4261
4619
|
* and PBKDF2 all share these contexts. Hash.copy() is a context snapshot;
|
|
4262
4620
|
* update never buffers the full input. Differential tests pin every
|
|
@@ -4462,7 +4820,7 @@ static size_t scr_sha1_digest(const unsigned char *data, size_t len, unsigned ch
|
|
|
4462
4820
|
static ScrStr *scr_digest_encode(const unsigned char *d, size_t n, const ScrStr *enc) {
|
|
4463
4821
|
if (enc->len == 3 && memcmp(enc->data, "hex", 3) == 0) {
|
|
4464
4822
|
static const char hex[] = "0123456789abcdef";
|
|
4465
|
-
char buf[
|
|
4823
|
+
char buf[128];
|
|
4466
4824
|
for (size_t i = 0; i < n; i++) {
|
|
4467
4825
|
buf[i * 2] = hex[d[i] >> 4];
|
|
4468
4826
|
buf[i * 2 + 1] = hex[d[i] & 0x0f];
|
|
@@ -4471,7 +4829,7 @@ static ScrStr *scr_digest_encode(const unsigned char *d, size_t n, const ScrStr
|
|
|
4471
4829
|
}
|
|
4472
4830
|
/* base64, standard alphabet, '=' padded — Buffer.toString("base64"). */
|
|
4473
4831
|
static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
4474
|
-
char buf[
|
|
4832
|
+
char buf[88];
|
|
4475
4833
|
size_t o = 0;
|
|
4476
4834
|
for (size_t i = 0; i < n; i += 3) {
|
|
4477
4835
|
unsigned v = (unsigned)d[i] << 16;
|
|
@@ -4586,10 +4944,140 @@ static size_t scr_md5_final(const ScrMd5Ctx *source, unsigned char out[32]) {
|
|
|
4586
4944
|
return 16;
|
|
4587
4945
|
}
|
|
4588
4946
|
|
|
4947
|
+
/* SHA-384/SHA-512, FIPS 180-4. The 128-byte blocks and HMAC pads differ
|
|
4948
|
+
* from SHA-256; the digest dispatcher keeps that distinction explicit. */
|
|
4949
|
+
typedef struct ScrSha512Ctx {
|
|
4950
|
+
uint64_t h[8];
|
|
4951
|
+
uint64_t bytes;
|
|
4952
|
+
unsigned char tail[128];
|
|
4953
|
+
size_t tail_len;
|
|
4954
|
+
} ScrSha512Ctx;
|
|
4955
|
+
|
|
4956
|
+
static const uint64_t scr_sha512_k[80] = {
|
|
4957
|
+
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), UINT64_C(0xb5c0fbcfec4d3b2f),
|
|
4958
|
+
UINT64_C(0xe9b5dba58189dbbc), UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
|
|
4959
|
+
UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), UINT64_C(0xd807aa98a3030242),
|
|
4960
|
+
UINT64_C(0x12835b0145706fbe), UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
|
|
4961
|
+
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), UINT64_C(0x9bdc06a725c71235),
|
|
4962
|
+
UINT64_C(0xc19bf174cf692694), UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
|
|
4963
|
+
UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), UINT64_C(0x2de92c6f592b0275),
|
|
4964
|
+
UINT64_C(0x4a7484aa6ea6e483), UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
|
|
4965
|
+
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), UINT64_C(0xb00327c898fb213f),
|
|
4966
|
+
UINT64_C(0xbf597fc7beef0ee4), UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
|
|
4967
|
+
UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), UINT64_C(0x27b70a8546d22ffc),
|
|
4968
|
+
UINT64_C(0x2e1b21385c26c926), UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
|
|
4969
|
+
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), UINT64_C(0x81c2c92e47edaee6),
|
|
4970
|
+
UINT64_C(0x92722c851482353b), UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001),
|
|
4971
|
+
UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), UINT64_C(0xd192e819d6ef5218),
|
|
4972
|
+
UINT64_C(0xd69906245565a910), UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
|
|
4973
|
+
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), UINT64_C(0x2748774cdf8eeb99),
|
|
4974
|
+
UINT64_C(0x34b0bcb5e19b48a8), UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
|
|
4975
|
+
UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), UINT64_C(0x748f82ee5defb2fc),
|
|
4976
|
+
UINT64_C(0x78a5636f43172f60), UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
|
|
4977
|
+
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), UINT64_C(0xbef9a3f7b2c67915),
|
|
4978
|
+
UINT64_C(0xc67178f2e372532b), UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
|
|
4979
|
+
UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), UINT64_C(0x06f067aa72176fba),
|
|
4980
|
+
UINT64_C(0x0a637dc5a2c898a6), UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
|
|
4981
|
+
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), UINT64_C(0x3c9ebe0a15c9bebc),
|
|
4982
|
+
UINT64_C(0x431d67c49c100d4c), UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
|
|
4983
|
+
UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817),
|
|
4984
|
+
};
|
|
4985
|
+
|
|
4986
|
+
static uint64_t scr_sha512_rotr(uint64_t x, unsigned n) {
|
|
4987
|
+
return (x >> n) | (x << (64 - n));
|
|
4988
|
+
}
|
|
4989
|
+
|
|
4990
|
+
static void scr_sha512_block(uint64_t h[8], const unsigned char *data) {
|
|
4991
|
+
uint64_t w[80];
|
|
4992
|
+
for (size_t i = 0; i < 16; i++) {
|
|
4993
|
+
w[i] = 0;
|
|
4994
|
+
for (size_t b = 0; b < 8; b++) w[i] = (w[i] << 8) | data[i * 8 + b];
|
|
4995
|
+
}
|
|
4996
|
+
for (size_t i = 16; i < 80; i++) {
|
|
4997
|
+
uint64_t s0 = scr_sha512_rotr(w[i - 15], 1) ^ scr_sha512_rotr(w[i - 15], 8) ^ (w[i - 15] >> 7);
|
|
4998
|
+
uint64_t s1 = scr_sha512_rotr(w[i - 2], 19) ^ scr_sha512_rotr(w[i - 2], 61) ^ (w[i - 2] >> 6);
|
|
4999
|
+
w[i] = w[i - 16] + s0 + w[i - 7] + s1;
|
|
5000
|
+
}
|
|
5001
|
+
uint64_t a = h[0], b = h[1], c = h[2], d = h[3];
|
|
5002
|
+
uint64_t e = h[4], f = h[5], g = h[6], v = h[7];
|
|
5003
|
+
for (size_t i = 0; i < 80; i++) {
|
|
5004
|
+
uint64_t s1 = scr_sha512_rotr(e, 14) ^ scr_sha512_rotr(e, 18) ^ scr_sha512_rotr(e, 41);
|
|
5005
|
+
uint64_t t1 = v + s1 + ((e & f) ^ (~e & g)) + scr_sha512_k[i] + w[i];
|
|
5006
|
+
uint64_t s0 = scr_sha512_rotr(a, 28) ^ scr_sha512_rotr(a, 34) ^ scr_sha512_rotr(a, 39);
|
|
5007
|
+
uint64_t t2 = s0 + ((a & b) ^ (a & c) ^ (b & c));
|
|
5008
|
+
v = g; g = f; f = e; e = d + t1;
|
|
5009
|
+
d = c; c = b; b = a; a = t1 + t2;
|
|
5010
|
+
}
|
|
5011
|
+
h[0] += a; h[1] += b; h[2] += c; h[3] += d;
|
|
5012
|
+
h[4] += e; h[5] += f; h[6] += g; h[7] += v;
|
|
5013
|
+
}
|
|
5014
|
+
|
|
5015
|
+
static void scr_sha512_init(ScrSha512Ctx *ctx, bool sha384) {
|
|
5016
|
+
static const uint64_t initial512[8] = {
|
|
5017
|
+
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
|
|
5018
|
+
UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
|
|
5019
|
+
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
|
|
5020
|
+
UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)};
|
|
5021
|
+
static const uint64_t initial384[8] = {
|
|
5022
|
+
UINT64_C(0xcbbb9d5dc1059ed8), UINT64_C(0x629a292a367cd507),
|
|
5023
|
+
UINT64_C(0x9159015a3070dd17), UINT64_C(0x152fecd8f70e5939),
|
|
5024
|
+
UINT64_C(0x67332667ffc00b31), UINT64_C(0x8eb44a8768581511),
|
|
5025
|
+
UINT64_C(0xdb0c2e0d64f98fa7), UINT64_C(0x47b5481dbefa4fa4)};
|
|
5026
|
+
memcpy(ctx->h, sha384 ? initial384 : initial512, sizeof ctx->h);
|
|
5027
|
+
ctx->bytes = 0;
|
|
5028
|
+
ctx->tail_len = 0;
|
|
5029
|
+
}
|
|
5030
|
+
|
|
5031
|
+
static void scr_sha512_update(ScrSha512Ctx *ctx, const unsigned char *data, size_t len) {
|
|
5032
|
+
ctx->bytes += len;
|
|
5033
|
+
if (ctx->tail_len != 0) {
|
|
5034
|
+
size_t take = 128 - ctx->tail_len;
|
|
5035
|
+
if (take > len) take = len;
|
|
5036
|
+
memcpy(ctx->tail + ctx->tail_len, data, take);
|
|
5037
|
+
ctx->tail_len += take;
|
|
5038
|
+
data += take;
|
|
5039
|
+
len -= take;
|
|
5040
|
+
if (ctx->tail_len == 128) {
|
|
5041
|
+
scr_sha512_block(ctx->h, ctx->tail);
|
|
5042
|
+
ctx->tail_len = 0;
|
|
5043
|
+
}
|
|
5044
|
+
}
|
|
5045
|
+
while (len >= 128) {
|
|
5046
|
+
scr_sha512_block(ctx->h, data);
|
|
5047
|
+
data += 128;
|
|
5048
|
+
len -= 128;
|
|
5049
|
+
}
|
|
5050
|
+
if (len != 0) {
|
|
5051
|
+
memcpy(ctx->tail, data, len);
|
|
5052
|
+
ctx->tail_len = len;
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
|
|
5056
|
+
static size_t scr_sha512_final(const ScrSha512Ctx *source, unsigned char out[64], bool sha384) {
|
|
5057
|
+
ScrSha512Ctx ctx = *source;
|
|
5058
|
+
unsigned char tail[256] = {0};
|
|
5059
|
+
memcpy(tail, ctx.tail, ctx.tail_len);
|
|
5060
|
+
tail[ctx.tail_len] = 0x80;
|
|
5061
|
+
size_t pad = ctx.tail_len < 112 ? 128 : 256;
|
|
5062
|
+
uint64_t low = ctx.bytes << 3, high = ctx.bytes >> 61;
|
|
5063
|
+
for (size_t b = 0; b < 8; b++) {
|
|
5064
|
+
tail[pad - 1 - b] = (unsigned char)(low >> (8 * b));
|
|
5065
|
+
tail[pad - 9 - b] = (unsigned char)(high >> (8 * b));
|
|
5066
|
+
}
|
|
5067
|
+
scr_sha512_block(ctx.h, tail);
|
|
5068
|
+
if (pad == 256) scr_sha512_block(ctx.h, tail + 128);
|
|
5069
|
+
size_t len = sha384 ? 48 : 64;
|
|
5070
|
+
for (size_t i = 0; i < len; i++) out[i] = (unsigned char)(ctx.h[i / 8] >> (56 - 8 * (i % 8)));
|
|
5071
|
+
return len;
|
|
5072
|
+
}
|
|
5073
|
+
|
|
4589
5074
|
typedef enum ScrDigestAlg {
|
|
4590
5075
|
SCR_DIGEST_MD5,
|
|
4591
5076
|
SCR_DIGEST_SHA1,
|
|
5077
|
+
SCR_DIGEST_SHA224,
|
|
4592
5078
|
SCR_DIGEST_SHA256,
|
|
5079
|
+
SCR_DIGEST_SHA384,
|
|
5080
|
+
SCR_DIGEST_SHA512,
|
|
4593
5081
|
} ScrDigestAlg;
|
|
4594
5082
|
|
|
4595
5083
|
typedef struct ScrDigestCtx {
|
|
@@ -4598,6 +5086,7 @@ typedef struct ScrDigestCtx {
|
|
|
4598
5086
|
ScrMd5Ctx md5;
|
|
4599
5087
|
ScrSha1Ctx sha1;
|
|
4600
5088
|
ScrSha256Ctx sha256;
|
|
5089
|
+
ScrSha512Ctx sha512;
|
|
4601
5090
|
} state;
|
|
4602
5091
|
} ScrDigestCtx;
|
|
4603
5092
|
|
|
@@ -4617,7 +5106,10 @@ static bool scr_digest_name_is(const char *name, size_t len, const char *literal
|
|
|
4617
5106
|
static bool scr_digest_alg(const char *name, size_t len, ScrDigestAlg *out) {
|
|
4618
5107
|
if (scr_digest_name_is(name, len, "md5")) *out = SCR_DIGEST_MD5;
|
|
4619
5108
|
else if (scr_digest_name_is(name, len, "sha1")) *out = SCR_DIGEST_SHA1;
|
|
5109
|
+
else if (scr_digest_name_is(name, len, "sha224")) *out = SCR_DIGEST_SHA224;
|
|
4620
5110
|
else if (scr_digest_name_is(name, len, "sha256")) *out = SCR_DIGEST_SHA256;
|
|
5111
|
+
else if (scr_digest_name_is(name, len, "sha384")) *out = SCR_DIGEST_SHA384;
|
|
5112
|
+
else if (scr_digest_name_is(name, len, "sha512")) *out = SCR_DIGEST_SHA512;
|
|
4621
5113
|
else return false;
|
|
4622
5114
|
return true;
|
|
4623
5115
|
}
|
|
@@ -4627,7 +5119,17 @@ static void scr_digest_init(ScrDigestCtx *ctx, ScrDigestAlg alg) {
|
|
|
4627
5119
|
switch (alg) {
|
|
4628
5120
|
case SCR_DIGEST_MD5: scr_md5_init(&ctx->state.md5); break;
|
|
4629
5121
|
case SCR_DIGEST_SHA1: scr_sha1_init(&ctx->state.sha1); break;
|
|
5122
|
+
case SCR_DIGEST_SHA224: {
|
|
5123
|
+
static const uint32_t initial[8] = {
|
|
5124
|
+
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
|
5125
|
+
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
|
|
5126
|
+
scr_sha256_init(&ctx->state.sha256);
|
|
5127
|
+
memcpy(ctx->state.sha256.h, initial, sizeof initial);
|
|
5128
|
+
break;
|
|
5129
|
+
}
|
|
4630
5130
|
case SCR_DIGEST_SHA256: scr_sha256_init(&ctx->state.sha256); break;
|
|
5131
|
+
case SCR_DIGEST_SHA384: scr_sha512_init(&ctx->state.sha512, true); break;
|
|
5132
|
+
case SCR_DIGEST_SHA512: scr_sha512_init(&ctx->state.sha512, false); break;
|
|
4631
5133
|
}
|
|
4632
5134
|
}
|
|
4633
5135
|
|
|
@@ -4635,15 +5137,21 @@ static void scr_digest_update(ScrDigestCtx *ctx, const unsigned char *data, size
|
|
|
4635
5137
|
switch (ctx->alg) {
|
|
4636
5138
|
case SCR_DIGEST_MD5: scr_md5_update(&ctx->state.md5, data, len); break;
|
|
4637
5139
|
case SCR_DIGEST_SHA1: scr_sha1_update(&ctx->state.sha1, data, len); break;
|
|
5140
|
+
case SCR_DIGEST_SHA224:
|
|
4638
5141
|
case SCR_DIGEST_SHA256: scr_sha256_update(&ctx->state.sha256, data, len); break;
|
|
5142
|
+
case SCR_DIGEST_SHA384:
|
|
5143
|
+
case SCR_DIGEST_SHA512: scr_sha512_update(&ctx->state.sha512, data, len); break;
|
|
4639
5144
|
}
|
|
4640
5145
|
}
|
|
4641
5146
|
|
|
4642
|
-
static size_t scr_digest_final(const ScrDigestCtx *ctx, unsigned char out[
|
|
5147
|
+
static size_t scr_digest_final(const ScrDigestCtx *ctx, unsigned char out[64]) {
|
|
4643
5148
|
switch (ctx->alg) {
|
|
4644
5149
|
case SCR_DIGEST_MD5: return scr_md5_final(&ctx->state.md5, out);
|
|
4645
5150
|
case SCR_DIGEST_SHA1: return scr_sha1_final(&ctx->state.sha1, out);
|
|
5151
|
+
case SCR_DIGEST_SHA224: scr_sha256_final(&ctx->state.sha256, out); return 28;
|
|
4646
5152
|
case SCR_DIGEST_SHA256: return scr_sha256_final(&ctx->state.sha256, out);
|
|
5153
|
+
case SCR_DIGEST_SHA384: return scr_sha512_final(&ctx->state.sha512, out, true);
|
|
5154
|
+
case SCR_DIGEST_SHA512: return scr_sha512_final(&ctx->state.sha512, out, false);
|
|
4647
5155
|
}
|
|
4648
5156
|
return 0;
|
|
4649
5157
|
}
|
|
@@ -4655,9 +5163,10 @@ static void scr_crypto_zero(void *ptr, size_t len) {
|
|
|
4655
5163
|
|
|
4656
5164
|
static void scr_hmac_init(ScrDigestCtx *inner, ScrDigestCtx *outer, ScrDigestAlg alg,
|
|
4657
5165
|
const unsigned char *key, size_t keylen) {
|
|
4658
|
-
unsigned char kblock[
|
|
4659
|
-
|
|
4660
|
-
|
|
5166
|
+
unsigned char kblock[128] = {0};
|
|
5167
|
+
size_t block_len = alg == SCR_DIGEST_SHA384 || alg == SCR_DIGEST_SHA512 ? 128 : 64;
|
|
5168
|
+
unsigned char kd[64];
|
|
5169
|
+
if (keylen > block_len) {
|
|
4661
5170
|
ScrDigestCtx key_hash;
|
|
4662
5171
|
scr_digest_init(&key_hash, alg);
|
|
4663
5172
|
scr_digest_update(&key_hash, key, keylen);
|
|
@@ -4668,24 +5177,24 @@ static void scr_hmac_init(ScrDigestCtx *inner, ScrDigestCtx *outer, ScrDigestAlg
|
|
|
4668
5177
|
} else if (keylen != 0) {
|
|
4669
5178
|
memcpy(kblock, key, keylen);
|
|
4670
5179
|
}
|
|
4671
|
-
unsigned char ipad[
|
|
4672
|
-
unsigned char opad[
|
|
4673
|
-
for (size_t i = 0; i <
|
|
5180
|
+
unsigned char ipad[128];
|
|
5181
|
+
unsigned char opad[128];
|
|
5182
|
+
for (size_t i = 0; i < block_len; i++) {
|
|
4674
5183
|
ipad[i] = (unsigned char)(kblock[i] ^ 0x36);
|
|
4675
5184
|
opad[i] = (unsigned char)(kblock[i] ^ 0x5c);
|
|
4676
5185
|
}
|
|
4677
5186
|
scr_digest_init(inner, alg);
|
|
4678
|
-
scr_digest_update(inner, ipad,
|
|
5187
|
+
scr_digest_update(inner, ipad, block_len);
|
|
4679
5188
|
scr_digest_init(outer, alg);
|
|
4680
|
-
scr_digest_update(outer, opad,
|
|
5189
|
+
scr_digest_update(outer, opad, block_len);
|
|
4681
5190
|
scr_crypto_zero(kblock, sizeof kblock);
|
|
4682
|
-
scr_crypto_zero(ipad,
|
|
4683
|
-
scr_crypto_zero(opad,
|
|
5191
|
+
scr_crypto_zero(ipad, block_len);
|
|
5192
|
+
scr_crypto_zero(opad, block_len);
|
|
4684
5193
|
}
|
|
4685
5194
|
|
|
4686
5195
|
static size_t scr_hmac_final(const ScrDigestCtx *inner, const ScrDigestCtx *outer,
|
|
4687
|
-
unsigned char out[
|
|
4688
|
-
unsigned char inner_digest[
|
|
5196
|
+
unsigned char out[64]) {
|
|
5197
|
+
unsigned char inner_digest[64];
|
|
4689
5198
|
size_t inner_len = scr_digest_final(inner, inner_digest);
|
|
4690
5199
|
ScrDigestCtx final_outer = *outer;
|
|
4691
5200
|
scr_digest_update(&final_outer, inner_digest, inner_len);
|
|
@@ -4699,7 +5208,7 @@ static size_t scr_hmac_final(const ScrDigestCtx *inner, const ScrDigestCtx *oute
|
|
|
4699
5208
|
* helpers both use the incremental core. Returns zero for an unknown
|
|
4700
5209
|
* algorithm, preserving the island's unsupported-digest probe. */
|
|
4701
5210
|
size_t scr_crypto_digest_raw(const char *alg, const unsigned char *data, size_t len,
|
|
4702
|
-
unsigned char out[
|
|
5211
|
+
unsigned char out[64]) {
|
|
4703
5212
|
ScrDigestAlg kind;
|
|
4704
5213
|
if (!scr_digest_alg(alg, strlen(alg), &kind)) return 0;
|
|
4705
5214
|
ScrDigestCtx ctx;
|
|
@@ -4709,7 +5218,7 @@ size_t scr_crypto_digest_raw(const char *alg, const unsigned char *data, size_t
|
|
|
4709
5218
|
}
|
|
4710
5219
|
|
|
4711
5220
|
size_t scr_crypto_hmac_raw(const char *alg, const unsigned char *key, size_t keylen,
|
|
4712
|
-
const unsigned char *data, size_t len, unsigned char out[
|
|
5221
|
+
const unsigned char *data, size_t len, unsigned char out[64]) {
|
|
4713
5222
|
ScrDigestAlg kind;
|
|
4714
5223
|
if (!scr_digest_alg(alg, strlen(alg), &kind)) return 0;
|
|
4715
5224
|
ScrDigestCtx inner, outer;
|
|
@@ -4859,7 +5368,7 @@ ScrCryptoHash *scr_crypto_hash_copy(ScrCryptoHash *hash) {
|
|
|
4859
5368
|
return copy;
|
|
4860
5369
|
}
|
|
4861
5370
|
|
|
4862
|
-
static size_t scr_crypto_hash_finish(ScrCryptoHash *hash, unsigned char out[
|
|
5371
|
+
static size_t scr_crypto_hash_finish(ScrCryptoHash *hash, unsigned char out[64]) {
|
|
4863
5372
|
if (hash->finalized) {
|
|
4864
5373
|
if (hash->hmac) return 0; /* Node's repeated Hmac.digest() is empty. */
|
|
4865
5374
|
scr_crypto_hash_finalized();
|
|
@@ -4872,7 +5381,7 @@ static size_t scr_crypto_hash_finish(ScrCryptoHash *hash, unsigned char out[32])
|
|
|
4872
5381
|
}
|
|
4873
5382
|
|
|
4874
5383
|
ScrStr *scr_crypto_hash_digest_string(ScrCryptoHash *hash, ScrStr *enc) {
|
|
4875
|
-
unsigned char digest[
|
|
5384
|
+
unsigned char digest[64];
|
|
4876
5385
|
size_t n = scr_crypto_hash_finish(hash, digest);
|
|
4877
5386
|
if (n == 0) return scr_exc_pending() ? NULL : scr_str_new("", 0);
|
|
4878
5387
|
ScrStr *result = scr_digest_encode(digest, n, enc);
|
|
@@ -4881,7 +5390,7 @@ ScrStr *scr_crypto_hash_digest_string(ScrCryptoHash *hash, ScrStr *enc) {
|
|
|
4881
5390
|
}
|
|
4882
5391
|
|
|
4883
5392
|
ScrBytes *scr_crypto_hash_digest_buffer(ScrCryptoHash *hash) {
|
|
4884
|
-
unsigned char digest[
|
|
5393
|
+
unsigned char digest[64];
|
|
4885
5394
|
size_t n = scr_crypto_hash_finish(hash, digest);
|
|
4886
5395
|
if (n == 0) return scr_exc_pending() ? NULL : scr_bytes_new(SCR_BYTES_U8, 0);
|
|
4887
5396
|
ScrBytes *result = scr_bytes_new(SCR_BYTES_U8, (double)n);
|
|
@@ -4897,7 +5406,7 @@ static ScrStr *scr_hash_digest_raw(const ScrStr *alg, const unsigned char *data,
|
|
|
4897
5406
|
scr_crypto_hash_digest_unsupported(alg);
|
|
4898
5407
|
return NULL;
|
|
4899
5408
|
}
|
|
4900
|
-
unsigned char d[
|
|
5409
|
+
unsigned char d[64];
|
|
4901
5410
|
ScrDigestCtx ctx;
|
|
4902
5411
|
scr_digest_init(&ctx, kind);
|
|
4903
5412
|
scr_digest_update(&ctx, data, len);
|
|
@@ -4934,7 +5443,7 @@ bool scr_crypto_timing_safe_equal(ScrBytes *left, ScrBytes *right) {
|
|
|
4934
5443
|
ScrBytes *scr_crypto_random_fill(ScrBytes *bytes, double offset, double size) {
|
|
4935
5444
|
double length = (double)(bytes->len * scr_bytes_elem_size(bytes->elem));
|
|
4936
5445
|
if (!isfinite(offset) || floor(offset) != offset || offset < 0 || offset > length) {
|
|
4937
|
-
char value[
|
|
5446
|
+
char value[64], msg[160];
|
|
4938
5447
|
size_t value_len = scr_f64_to_str(offset, value);
|
|
4939
5448
|
int n = snprintf(msg, sizeof msg,
|
|
4940
5449
|
"The value of \"offset\" is out of range. It must be >= 0 && <= %.0f. Received %.*s",
|
|
@@ -4944,7 +5453,7 @@ ScrBytes *scr_crypto_random_fill(ScrBytes *bytes, double offset, double size) {
|
|
|
4944
5453
|
}
|
|
4945
5454
|
double available = length - offset;
|
|
4946
5455
|
if (!isfinite(size) || floor(size) != size || size < 0 || size > 2147483647.0) {
|
|
4947
|
-
char value[
|
|
5456
|
+
char value[64], msg[160];
|
|
4948
5457
|
size_t value_len = scr_f64_to_str(size, value);
|
|
4949
5458
|
int n = snprintf(msg, sizeof msg,
|
|
4950
5459
|
"The value of \"size\" is out of range. It must be >= 0 && <= 2147483647. Received %.*s",
|
|
@@ -4953,7 +5462,7 @@ ScrBytes *scr_crypto_random_fill(ScrBytes *bytes, double offset, double size) {
|
|
|
4953
5462
|
return NULL;
|
|
4954
5463
|
}
|
|
4955
5464
|
if (size > available) {
|
|
4956
|
-
char value[
|
|
5465
|
+
char value[64], msg[160];
|
|
4957
5466
|
double total = size + offset;
|
|
4958
5467
|
size_t value_len = scr_f64_to_str(total, value);
|
|
4959
5468
|
int n = snprintf(msg, sizeof msg,
|
|
@@ -4983,7 +5492,7 @@ double scr_crypto_random_int(double min, double max) {
|
|
|
4983
5492
|
return 0;
|
|
4984
5493
|
}
|
|
4985
5494
|
if (max <= min) {
|
|
4986
|
-
char min_text[
|
|
5495
|
+
char min_text[64], max_text[64], msg[192];
|
|
4987
5496
|
size_t min_len = scr_f64_to_str(min, min_text);
|
|
4988
5497
|
size_t max_len = scr_f64_to_str(max, max_text);
|
|
4989
5498
|
int n = snprintf(msg, sizeof msg,
|
|
@@ -5015,7 +5524,7 @@ static ScrBytes *scr_crypto_pbkdf2_raw(const unsigned char *password, size_t pas
|
|
|
5015
5524
|
uint32_t iterations, size_t keylen,
|
|
5016
5525
|
ScrDigestAlg alg) {
|
|
5017
5526
|
ScrDigestCtx empty;
|
|
5018
|
-
unsigned char empty_digest[
|
|
5527
|
+
unsigned char empty_digest[64];
|
|
5019
5528
|
scr_digest_init(&empty, alg);
|
|
5020
5529
|
size_t digest_len = scr_digest_final(&empty, empty_digest);
|
|
5021
5530
|
scr_crypto_zero(empty_digest, sizeof empty_digest);
|
|
@@ -5030,7 +5539,7 @@ static ScrBytes *scr_crypto_pbkdf2_raw(const unsigned char *password, size_t pas
|
|
|
5030
5539
|
block[salt_len + 2] = (unsigned char)(index >> 8);
|
|
5031
5540
|
block[salt_len + 3] = (unsigned char)index;
|
|
5032
5541
|
ScrDigestCtx inner, outer;
|
|
5033
|
-
unsigned char u[
|
|
5542
|
+
unsigned char u[64], accum[64];
|
|
5034
5543
|
scr_hmac_init(&inner, &outer, alg, password, password_len);
|
|
5035
5544
|
scr_digest_update(&inner, block, salt_len + 4);
|
|
5036
5545
|
scr_hmac_final(&inner, &outer, u);
|
|
@@ -5058,7 +5567,7 @@ ScrBytes *scr_crypto_pbkdf2(ScrBytes *password, ScrBytes *salt,
|
|
|
5058
5567
|
double iterations, double keylen, ScrStr *digest) {
|
|
5059
5568
|
if (!isfinite(iterations) || floor(iterations) != iterations ||
|
|
5060
5569
|
iterations < 1 || iterations > 2147483647.0) {
|
|
5061
|
-
char value[
|
|
5570
|
+
char value[64], msg[176];
|
|
5062
5571
|
size_t value_len = scr_f64_to_str(iterations, value);
|
|
5063
5572
|
int n = snprintf(msg, sizeof msg,
|
|
5064
5573
|
"The value of \"iterations\" is out of range. It must be >= 1 && <= 2147483647. Received %.*s",
|
|
@@ -5067,7 +5576,7 @@ ScrBytes *scr_crypto_pbkdf2(ScrBytes *password, ScrBytes *salt,
|
|
|
5067
5576
|
return NULL;
|
|
5068
5577
|
}
|
|
5069
5578
|
if (!isfinite(keylen) || floor(keylen) != keylen || keylen < 0 || keylen > 2147483647.0) {
|
|
5070
|
-
char value[
|
|
5579
|
+
char value[64], msg[176];
|
|
5071
5580
|
size_t value_len = scr_f64_to_str(keylen, value);
|
|
5072
5581
|
int n = snprintf(msg, sizeof msg,
|
|
5073
5582
|
"The value of \"keylen\" is out of range. It must be >= 0 && <= 2147483647. Received %.*s",
|
|
@@ -5086,6 +5595,279 @@ ScrBytes *scr_crypto_pbkdf2(ScrBytes *password, ScrBytes *salt,
|
|
|
5086
5595
|
(size_t)keylen, alg);
|
|
5087
5596
|
}
|
|
5088
5597
|
|
|
5598
|
+
/* RFC 5869 HKDF and RFC 7914 scrypt share the digest core in both
|
|
5599
|
+
* execution tiers. Sensitive scratch storage is cleared before release. */
|
|
5600
|
+
static bool scr_crypto_integer(double value, const char *name, double max) {
|
|
5601
|
+
if (isfinite(value) && floor(value) == value && value >= 0 && value <= max) return true;
|
|
5602
|
+
char received[64], requirement[80], message[256];
|
|
5603
|
+
size_t n = scr_f64_to_str(value, received);
|
|
5604
|
+
received[n] = '\0';
|
|
5605
|
+
if (!isfinite(value) || floor(value) != value) {
|
|
5606
|
+
snprintf(requirement, sizeof requirement, "an integer");
|
|
5607
|
+
} else {
|
|
5608
|
+
snprintf(requirement, sizeof requirement, ">= 0 && <= %.0f", max);
|
|
5609
|
+
if (fabs(value) > 4294967296.0) {
|
|
5610
|
+
char digits[40];
|
|
5611
|
+
snprintf(digits, sizeof digits, "%.0f", value);
|
|
5612
|
+
size_t len = strlen(digits), out = 0, start = digits[0] == '-' ? 1 : 0;
|
|
5613
|
+
for (size_t i = 0; i < len; i++) {
|
|
5614
|
+
if (i > start && (len - i) % 3 == 0) received[out++] = '_';
|
|
5615
|
+
received[out++] = digits[i];
|
|
5616
|
+
}
|
|
5617
|
+
received[out] = '\0';
|
|
5618
|
+
}
|
|
5619
|
+
}
|
|
5620
|
+
int len = snprintf(message, sizeof message,
|
|
5621
|
+
"The value of \"%s\" is out of range. It must be %s. Received %s", name, requirement, received);
|
|
5622
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, message, (size_t)len, "ERR_OUT_OF_RANGE");
|
|
5623
|
+
return false;
|
|
5624
|
+
}
|
|
5625
|
+
|
|
5626
|
+
ScrBytes *scr_crypto_hkdf_bytes(ScrStr *digest, ScrBytes *ikm, ScrBytes *salt,
|
|
5627
|
+
ScrBytes *info, double keylen) {
|
|
5628
|
+
if (!scr_crypto_integer(keylen, "length", 9007199254740991.0)) return NULL;
|
|
5629
|
+
size_t info_len = info->len * scr_bytes_elem_size(info->elem);
|
|
5630
|
+
if (info_len > 1024) {
|
|
5631
|
+
char message[192];
|
|
5632
|
+
int len = snprintf(message, sizeof message,
|
|
5633
|
+
"The value of \"info\" is out of range. It must be must not contain more than 1024 bytes. Received %zu", info_len);
|
|
5634
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, message, (size_t)len, "ERR_OUT_OF_RANGE");
|
|
5635
|
+
return NULL;
|
|
5636
|
+
}
|
|
5637
|
+
ScrDigestAlg alg;
|
|
5638
|
+
if (!scr_digest_alg(digest->data, digest->len, &alg)) {
|
|
5639
|
+
scr_crypto_invalid_digest(digest);
|
|
5640
|
+
return NULL;
|
|
5641
|
+
}
|
|
5642
|
+
ScrDigestCtx inner, outer;
|
|
5643
|
+
unsigned char prk[64], t[64];
|
|
5644
|
+
scr_hmac_init(&inner, &outer, alg, salt->data, salt->len * scr_bytes_elem_size(salt->elem));
|
|
5645
|
+
scr_digest_update(&inner, ikm->data, ikm->len * scr_bytes_elem_size(ikm->elem));
|
|
5646
|
+
size_t hash_len = scr_hmac_final(&inner, &outer, prk);
|
|
5647
|
+
if (keylen > 255 * hash_len) {
|
|
5648
|
+
scr_crypto_zero(prk, sizeof prk);
|
|
5649
|
+
scr_crypto_zero(&inner, sizeof inner);
|
|
5650
|
+
scr_crypto_zero(&outer, sizeof outer);
|
|
5651
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, "Invalid key length", 18, "ERR_CRYPTO_INVALID_KEYLEN");
|
|
5652
|
+
return NULL;
|
|
5653
|
+
}
|
|
5654
|
+
ScrBytes *result = scr_bytes_new(SCR_BYTES_U8, keylen);
|
|
5655
|
+
size_t offset = 0, previous_len = 0;
|
|
5656
|
+
for (unsigned counter = 1; offset < (size_t)keylen; counter++) {
|
|
5657
|
+
scr_hmac_init(&inner, &outer, alg, prk, hash_len);
|
|
5658
|
+
scr_digest_update(&inner, t, previous_len);
|
|
5659
|
+
scr_digest_update(&inner, info->data, info_len);
|
|
5660
|
+
unsigned char byte = (unsigned char)counter;
|
|
5661
|
+
scr_digest_update(&inner, &byte, 1);
|
|
5662
|
+
scr_hmac_final(&inner, &outer, t);
|
|
5663
|
+
size_t take = (size_t)keylen - offset;
|
|
5664
|
+
if (take > hash_len) take = hash_len;
|
|
5665
|
+
memcpy(result->data + offset, t, take);
|
|
5666
|
+
offset += take;
|
|
5667
|
+
previous_len = hash_len;
|
|
5668
|
+
}
|
|
5669
|
+
scr_crypto_zero(prk, sizeof prk);
|
|
5670
|
+
scr_crypto_zero(t, sizeof t);
|
|
5671
|
+
scr_crypto_zero(&inner, sizeof inner);
|
|
5672
|
+
scr_crypto_zero(&outer, sizeof outer);
|
|
5673
|
+
return result;
|
|
5674
|
+
}
|
|
5675
|
+
|
|
5676
|
+
ScrDyn *scr_crypto_hkdf(ScrStr *digest, ScrBytes *ikm, ScrBytes *salt,
|
|
5677
|
+
ScrBytes *info, double keylen) {
|
|
5678
|
+
ScrBytes *bytes = scr_crypto_hkdf_bytes(digest, ikm, salt, info, keylen);
|
|
5679
|
+
if (!bytes) return NULL;
|
|
5680
|
+
if (bytes->len == 0) {
|
|
5681
|
+
scr_bytes_release(bytes);
|
|
5682
|
+
scr_throw_error_msg(SCR_ERR_ERROR, "Deriving bits failed", 20);
|
|
5683
|
+
return NULL;
|
|
5684
|
+
}
|
|
5685
|
+
ScrDyn *result = scr_array_buffer_from_bytes(bytes);
|
|
5686
|
+
scr_bytes_release(bytes);
|
|
5687
|
+
return result;
|
|
5688
|
+
}
|
|
5689
|
+
|
|
5690
|
+
static uint32_t scr_scrypt_rotl(uint32_t x, unsigned n) {
|
|
5691
|
+
return (x << n) | (x >> (32 - n));
|
|
5692
|
+
}
|
|
5693
|
+
|
|
5694
|
+
/* Salsa20/8 core, RFC 7914 section 3. Unsigned arithmetic supplies the
|
|
5695
|
+
* specified reduction modulo 2^32 without signed-overflow UB. */
|
|
5696
|
+
static void scr_scrypt_salsa(uint32_t block[16]) {
|
|
5697
|
+
uint32_t x[16];
|
|
5698
|
+
memcpy(x, block, sizeof x);
|
|
5699
|
+
for (unsigned round = 0; round < 8; round += 2) {
|
|
5700
|
+
#define SCR_SALSA(a, b, c, n) x[a] ^= scr_scrypt_rotl(x[b] + x[c], n)
|
|
5701
|
+
SCR_SALSA(4,0,12,7); SCR_SALSA(8,4,0,9); SCR_SALSA(12,8,4,13); SCR_SALSA(0,12,8,18);
|
|
5702
|
+
SCR_SALSA(9,5,1,7); SCR_SALSA(13,9,5,9); SCR_SALSA(1,13,9,13); SCR_SALSA(5,1,13,18);
|
|
5703
|
+
SCR_SALSA(14,10,6,7); SCR_SALSA(2,14,10,9); SCR_SALSA(6,2,14,13); SCR_SALSA(10,6,2,18);
|
|
5704
|
+
SCR_SALSA(3,15,11,7); SCR_SALSA(7,3,15,9); SCR_SALSA(11,7,3,13); SCR_SALSA(15,11,7,18);
|
|
5705
|
+
SCR_SALSA(1,0,3,7); SCR_SALSA(2,1,0,9); SCR_SALSA(3,2,1,13); SCR_SALSA(0,3,2,18);
|
|
5706
|
+
SCR_SALSA(6,5,4,7); SCR_SALSA(7,6,5,9); SCR_SALSA(4,7,6,13); SCR_SALSA(5,4,7,18);
|
|
5707
|
+
SCR_SALSA(11,10,9,7); SCR_SALSA(8,11,10,9); SCR_SALSA(9,8,11,13); SCR_SALSA(10,9,8,18);
|
|
5708
|
+
SCR_SALSA(12,15,14,7); SCR_SALSA(13,12,15,9); SCR_SALSA(14,13,12,13); SCR_SALSA(15,14,13,18);
|
|
5709
|
+
#undef SCR_SALSA
|
|
5710
|
+
}
|
|
5711
|
+
for (size_t i = 0; i < 16; i++) block[i] += x[i];
|
|
5712
|
+
scr_crypto_zero(x, sizeof x);
|
|
5713
|
+
}
|
|
5714
|
+
|
|
5715
|
+
static void scr_scrypt_blockmix(uint32_t *x, uint32_t *y, size_t r) {
|
|
5716
|
+
uint32_t block[16];
|
|
5717
|
+
memcpy(block, x + (2 * r - 1) * 16, sizeof block);
|
|
5718
|
+
for (size_t i = 0; i < 2 * r; i++) {
|
|
5719
|
+
for (size_t k = 0; k < 16; k++) block[k] ^= x[i * 16 + k];
|
|
5720
|
+
scr_scrypt_salsa(block);
|
|
5721
|
+
size_t dest = (i / 2 + (i % 2) * r) * 16;
|
|
5722
|
+
memcpy(y + dest, block, sizeof block);
|
|
5723
|
+
}
|
|
5724
|
+
memcpy(x, y, 128 * r);
|
|
5725
|
+
scr_crypto_zero(block, sizeof block);
|
|
5726
|
+
}
|
|
5727
|
+
|
|
5728
|
+
static bool scr_scrypt_params(double n, double r, double p, double maxmem, size_t *memory) {
|
|
5729
|
+
uint64_t N = (uint64_t)n, R = (uint64_t)r, P = (uint64_t)p;
|
|
5730
|
+
if (N < 2 || (N & (N - 1)) != 0) {
|
|
5731
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, "Invalid scrypt params", 21, "ERR_CRYPTO_INVALID_SCRYPT_PARAMS");
|
|
5732
|
+
return false;
|
|
5733
|
+
}
|
|
5734
|
+
/* Match Node's OpenSSL 3 scrypt guard, including X/Y working buffers
|
|
5735
|
+
* and the initial PBKDF2 output; check every product before allocation. */
|
|
5736
|
+
bool overflow = R == 0 || P == 0 || P > UINT64_C(0x3fffffff) / R;
|
|
5737
|
+
if (!overflow && R <= 3 && N >= (UINT64_C(1) << (16 * R))) overflow = true;
|
|
5738
|
+
uint64_t b = overflow ? 0 : 128 * R * P;
|
|
5739
|
+
if (b > INT32_MAX || R > UINT64_MAX / 128 / (N + 2)) overflow = true;
|
|
5740
|
+
uint64_t v = overflow ? 0 : 128 * R * (N + 2);
|
|
5741
|
+
if (overflow || b > UINT64_MAX - v || b + v > (uint64_t)maxmem || b + v > SIZE_MAX) {
|
|
5742
|
+
static const char message[] = "Invalid scrypt params: error:030000AC:digital envelope routines::memory limit exceeded";
|
|
5743
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, message, sizeof message - 1, "ERR_CRYPTO_INVALID_SCRYPT_PARAMS");
|
|
5744
|
+
return false;
|
|
5745
|
+
}
|
|
5746
|
+
*memory = (size_t)(b + v);
|
|
5747
|
+
return true;
|
|
5748
|
+
}
|
|
5749
|
+
|
|
5750
|
+
ScrBytes *scr_crypto_scrypt_derive(ScrBytes *password, ScrBytes *salt, double keylen,
|
|
5751
|
+
double n, double r, double p, double maxmem) {
|
|
5752
|
+
if (!scr_crypto_integer(keylen, "keylen", 2147483647.0) ||
|
|
5753
|
+
!scr_crypto_integer(n, "N", 4294967295.0) || !scr_crypto_integer(r, "r", 4294967295.0) ||
|
|
5754
|
+
!scr_crypto_integer(p, "p", 4294967295.0) || !scr_crypto_integer(maxmem, "maxmem", 9007199254740991.0)) return NULL;
|
|
5755
|
+
if (n == 0) n = 16384;
|
|
5756
|
+
if (r == 0) r = 8;
|
|
5757
|
+
if (p == 0) p = 1;
|
|
5758
|
+
if (maxmem == 0) maxmem = 33554432;
|
|
5759
|
+
size_t memory;
|
|
5760
|
+
if (!scr_scrypt_params(n, r, p, maxmem, &memory)) return NULL;
|
|
5761
|
+
if (keylen == 0) return scr_bytes_new(SCR_BYTES_U8, 0);
|
|
5762
|
+
size_t words = 32 * (size_t)r, block_len = words * sizeof(uint32_t);
|
|
5763
|
+
size_t b_len = block_len * (size_t)p;
|
|
5764
|
+
ScrBytes *b = scr_crypto_pbkdf2_raw(password->data, password->len * scr_bytes_elem_size(password->elem),
|
|
5765
|
+
salt->data, salt->len * scr_bytes_elem_size(salt->elem), 1, b_len, SCR_DIGEST_SHA256);
|
|
5766
|
+
uint32_t *work = malloc(memory - b_len);
|
|
5767
|
+
if (!work) { scr_bytes_release(b); scr_trap("scriptc: out of memory\n"); }
|
|
5768
|
+
uint32_t *x = work, *y = x + words, *v = y + words;
|
|
5769
|
+
for (size_t part = 0; part < (size_t)p; part++) {
|
|
5770
|
+
unsigned char *bytes = b->data + part * block_len;
|
|
5771
|
+
for (size_t i = 0; i < words; i++) {
|
|
5772
|
+
x[i] = (uint32_t)bytes[i * 4] | ((uint32_t)bytes[i * 4 + 1] << 8) |
|
|
5773
|
+
((uint32_t)bytes[i * 4 + 2] << 16) | ((uint32_t)bytes[i * 4 + 3] << 24);
|
|
5774
|
+
}
|
|
5775
|
+
for (size_t i = 0; i < (size_t)n; i++) {
|
|
5776
|
+
memcpy(v + i * words, x, block_len);
|
|
5777
|
+
scr_scrypt_blockmix(x, y, (size_t)r);
|
|
5778
|
+
}
|
|
5779
|
+
for (size_t i = 0; i < (size_t)n; i++) {
|
|
5780
|
+
size_t j = (size_t)x[words - 16] & ((size_t)n - 1);
|
|
5781
|
+
for (size_t k = 0; k < words; k++) x[k] ^= v[j * words + k];
|
|
5782
|
+
scr_scrypt_blockmix(x, y, (size_t)r);
|
|
5783
|
+
}
|
|
5784
|
+
for (size_t i = 0; i < words; i++) {
|
|
5785
|
+
for (size_t k = 0; k < 4; k++) bytes[i * 4 + k] = (unsigned char)(x[i] >> (8 * k));
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
ScrBytes *result = scr_crypto_pbkdf2_raw(password->data, password->len * scr_bytes_elem_size(password->elem),
|
|
5789
|
+
b->data, b_len, 1, (size_t)keylen, SCR_DIGEST_SHA256);
|
|
5790
|
+
scr_crypto_zero(b->data, b_len);
|
|
5791
|
+
scr_bytes_release(b);
|
|
5792
|
+
scr_crypto_zero(work, memory - b_len);
|
|
5793
|
+
free(work);
|
|
5794
|
+
return result;
|
|
5795
|
+
}
|
|
5796
|
+
|
|
5797
|
+
static ScrDyn *scr_scrypt_read_option(ScrDyn *options, const char *name) {
|
|
5798
|
+
if (options->kind != SCR_DYN_TYPED_REF) return scr_dyn_obj_read(options, name, strlen(name));
|
|
5799
|
+
ScrDyn *view = scr_dyn_typed_ref_materialize(options);
|
|
5800
|
+
if (!view) return NULL;
|
|
5801
|
+
ScrDyn *value = scr_dyn_obj_read(view, name, strlen(name));
|
|
5802
|
+
scr_dyn_release(view);
|
|
5803
|
+
return value;
|
|
5804
|
+
}
|
|
5805
|
+
|
|
5806
|
+
static bool scr_scrypt_option(ScrDyn *options, const char *name, double max, double *out, bool *present) {
|
|
5807
|
+
ScrDyn *value = scr_scrypt_read_option(options, name);
|
|
5808
|
+
if (scr_exc_pending()) return false;
|
|
5809
|
+
*present = value && value->kind != SCR_DYN_UNDEF;
|
|
5810
|
+
if (*present) {
|
|
5811
|
+
scr_dyn_release(value);
|
|
5812
|
+
value = scr_scrypt_read_option(options, name);
|
|
5813
|
+
if (scr_exc_pending()) return false;
|
|
5814
|
+
if (value->kind != SCR_DYN_NUM) {
|
|
5815
|
+
scr_dyn_arg_type_fail(name, "number", value);
|
|
5816
|
+
scr_dyn_release(value);
|
|
5817
|
+
return false;
|
|
5818
|
+
}
|
|
5819
|
+
*out = value->v.num;
|
|
5820
|
+
bool valid = scr_crypto_integer(*out, name, max);
|
|
5821
|
+
scr_dyn_release(value);
|
|
5822
|
+
return valid;
|
|
5823
|
+
}
|
|
5824
|
+
scr_dyn_release(value);
|
|
5825
|
+
return true;
|
|
5826
|
+
}
|
|
5827
|
+
|
|
5828
|
+
ScrBytes *scr_crypto_scrypt(ScrBytes *password, ScrBytes *salt, double keylen, ScrDyn *options) {
|
|
5829
|
+
if (!scr_crypto_integer(keylen, "keylen", 2147483647.0)) return NULL;
|
|
5830
|
+
double values[4] = {16384, 8, 1, 33554432};
|
|
5831
|
+
if (options && scr_dyn_truthy(options)) {
|
|
5832
|
+
const char *names[3] = {"N", "r", "p"};
|
|
5833
|
+
const char *aliases[3] = {"cost", "blockSize", "parallelization"};
|
|
5834
|
+
for (size_t i = 0; i < 3; i++) {
|
|
5835
|
+
bool primary, alias;
|
|
5836
|
+
if (!scr_scrypt_option(options, names[i], 4294967295.0, &values[i], &primary)) return NULL;
|
|
5837
|
+
// Node reads the alias to test presence before checking the conflict.
|
|
5838
|
+
ScrDyn *alias_value = scr_scrypt_read_option(options, aliases[i]);
|
|
5839
|
+
if (scr_exc_pending()) return NULL;
|
|
5840
|
+
alias = alias_value && alias_value->kind != SCR_DYN_UNDEF;
|
|
5841
|
+
if (primary && alias) {
|
|
5842
|
+
char message[160];
|
|
5843
|
+
int len = snprintf(message, sizeof message, "Option \"%s\" cannot be used in combination with option \"%s\"", names[i], aliases[i]);
|
|
5844
|
+
scr_dyn_release(alias_value);
|
|
5845
|
+
scr_throw_error_msg_code(SCR_ERR_TYPE, message, (size_t)len, "ERR_INCOMPATIBLE_OPTION_PAIR");
|
|
5846
|
+
return NULL;
|
|
5847
|
+
}
|
|
5848
|
+
if (alias) {
|
|
5849
|
+
scr_dyn_release(alias_value);
|
|
5850
|
+
alias_value = scr_scrypt_read_option(options, aliases[i]);
|
|
5851
|
+
if (scr_exc_pending()) return NULL;
|
|
5852
|
+
if (alias_value->kind != SCR_DYN_NUM) {
|
|
5853
|
+
scr_dyn_arg_type_fail(aliases[i], "number", alias_value);
|
|
5854
|
+
scr_dyn_release(alias_value);
|
|
5855
|
+
return NULL;
|
|
5856
|
+
}
|
|
5857
|
+
values[i] = alias_value->v.num;
|
|
5858
|
+
if (!scr_crypto_integer(values[i], aliases[i], 4294967295.0)) {
|
|
5859
|
+
scr_dyn_release(alias_value);
|
|
5860
|
+
return NULL;
|
|
5861
|
+
}
|
|
5862
|
+
}
|
|
5863
|
+
scr_dyn_release(alias_value);
|
|
5864
|
+
}
|
|
5865
|
+
bool present;
|
|
5866
|
+
if (!scr_scrypt_option(options, "maxmem", 9007199254740991.0, &values[3], &present)) return NULL;
|
|
5867
|
+
}
|
|
5868
|
+
return scr_crypto_scrypt_derive(password, salt, keylen, values[0], values[1], values[2], values[3]);
|
|
5869
|
+
}
|
|
5870
|
+
|
|
5089
5871
|
/* The composed `new crypto.X509Certificate(data).fingerprint` read, fused
|
|
5090
5872
|
* by the compiler (no certificate handle exists). Node's .fingerprint IS
|
|
5091
5873
|
* the SHA-1 of the certificate's DER bytes, uppercase colon-separated —
|