ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
key_parser.cpp
Go to the documentation of this file.
1#include <emscripten/bind.h>
2extern "C" {
3#include "../client.h"
4#include "../common/errors.h"
6}
7#include <sodium.h>
8
9#include <cstddef>
10#include <cstdint>
11#include <string>
12#include <vector>
13
17
18static emscripten::val frame_value(const asciichat_error_context_t &frame) {
19 emscripten::val result = emscripten::val::object();
20 result.set("code", static_cast<int>(frame.code));
21 result.set("message", std::string(frame.context_message));
22 result.set("file", std::string(frame.file ? extract_project_relative_path(frame.file) : ""));
23#ifdef NDEBUG
24 result.set("fullFile", std::string());
25#else
26 result.set("fullFile", std::string(frame.file ? frame.file : ""));
27#endif
28 result.set("function", std::string(frame.function ? frame.function : ""));
29 result.set("line", frame.line);
30 return result;
31}
32
33static KeyParseResult parse_key(int kind, bool binary, KeyInput input) {
34 const asciichat_errno_scope_t checkpoint = errno_checkpoint();
35 const size_t length = input["length"].as<size_t>();
36 std::vector<uint8_t> bytes(length + 1, 0);
37 if (length) {
38 emscripten::val view = emscripten::val(emscripten::typed_memory_view(length, bytes.data()));
39 view.call<void>("set", input);
40 }
41 uint8_t output[64] = {0};
42 int code = -1;
43 switch (kind) {
44 case 0:
45 code = client_parse_ssh_private_key(reinterpret_cast<const char *>(bytes.data()), output);
46 break;
47 case 1:
48 code = client_parse_ssh_public_key(reinterpret_cast<const char *>(bytes.data()), output);
49 break;
50 case 2:
51 code = binary ? client_parse_gpg_private_key_binary(bytes.data(), length, output)
52 : client_parse_gpg_private_key(reinterpret_cast<const char *>(bytes.data()), output);
53 break;
54 case 3:
55 code = binary ? client_parse_gpg_public_key_binary(bytes.data(), length, output)
56 : client_parse_gpg_public_key(reinterpret_cast<const char *>(bytes.data()), output);
57 break;
58 default:
59 code = SET_ERRNO(ERROR_INVALID_PARAM, "Invalid key parser kind: %d", kind);
60 break;
61 }
62 if (code != 0 && kind >= 0 && kind <= 3) {
64 if (!errno_peek_since(checkpoint, &context))
65 SET_ERRNO(ERROR_CRYPTO_KEY, "Cannot parse browser key");
66 }
67 const size_t output_length = code == 0 ? (kind == 0 || kind == 2 ? 64 : 32) : 0;
68 emscripten::val result_bytes = emscripten::val::global("Uint8Array").new_(output_length);
69 if (output_length)
70 result_bytes.call<void>("set", emscripten::val(emscripten::typed_memory_view(output_length, output)));
71 sodium_memzero(output, sizeof(output));
72 sodium_memzero(bytes.data(), bytes.size());
73 emscripten::val result = emscripten::val::object();
74 result.set("code", code);
75 result.set("bytes", result_bytes);
76 emscripten::val frames = emscripten::val::array();
77 if (code != 0) {
79 const asciichat_errno_snapshot_t snapshot =
80 errno_snapshot(checkpoint.thread_id, contexts, ASCIICHAT_ERRNO_MAX_DEPTH);
81 unsigned index = 0;
82 for (size_t i = 0; i < snapshot.copied; ++i) {
83 if (contexts[i].generation == checkpoint.generation && contexts[i].error_id > checkpoint.after_id)
84 frames.set(index++, frame_value(contexts[i]));
85 }
86 }
87 result.set("frames", frames);
88 return KeyParseResult(result);
89}
90
91static std::string parser_error() {
92 char buffer[1024] = {0};
93 const int status = client_get_crypto_error_message(buffer, sizeof(buffer));
94 std::string result = status == 0 ? buffer : "Invalid SSH key";
95 sodium_memzero(buffer, sizeof(buffer));
96 return result;
97}
98
99static ErrorFrameResult error_frame(size_t index) {
100 emscripten::val result = emscripten::val::object();
101 result.set("code", browser_error_code(index));
102 result.set("message", std::string(browser_error_message(index)));
103 result.set("file", std::string(browser_error_file(index)));
104 result.set("fullFile", std::string(browser_error_full_file(index)));
105 result.set("function", std::string(browser_error_function(index)));
106 result.set("line", browser_error_line(index));
107 return ErrorFrameResult(result);
108}
109
110EMSCRIPTEN_BINDINGS(ascii_chat_key_parser) {
111 emscripten::function("browser_error_dismiss", &browser_error_dismiss);
112 emscripten::register_type<KeyInput>("KeyInput", "Uint8Array");
113 emscripten::register_type<KeyParseResult>("KeyParseResult",
114 "{ code: number; bytes: Uint8Array; frames: ErrorFrameResult[] }");
115 emscripten::register_type<ErrorFrameResult>(
116 "ErrorFrameResult",
117 "{ code: number; message: string; file: string; fullFile: string; function: string; line: number }");
118 emscripten::function("parseKey", &parse_key);
119 emscripten::function("keyParserError", &parser_error);
120 emscripten::function("errorSnapshot", &browser_error_snapshot);
121 emscripten::function("errorFrame", &error_frame);
122}
bool errno_peek_since(asciichat_errno_scope_t scope, asciichat_error_context_t *out)
asciichat_errno_snapshot_t errno_snapshot(uint64_t id, asciichat_error_context_t *out, size_t capacity)
asciichat_errno_scope_t errno_checkpoint(void)
#define SET_ERRNO(code,...)
#define ASCIICHAT_ERRNO_MAX_DEPTH
unsigned char uint8_t
Definition common.h:60
@ ERROR_CRYPTO_KEY
Definition error_codes.h:94
@ ERROR_INVALID_PARAM
const char * extract_project_relative_path(const char *file, const char *const *owned_dirs)
Extract a path relative to the source root embedded by CMake.
EMSCRIPTEN_DECLARE_VAL_TYPE(KeyInput)
EMSCRIPTEN_BINDINGS(ascii_chat_key_parser)
📂 Path Manipulation Utilities
static bool size_t index
Definition queries.h:8
int client_parse_gpg_private_key(const char *armored_key, uint8_t *secret_key_out)
int client_parse_gpg_public_key_binary(const uint8_t *key_data, size_t key_data_len, uint8_t *public_key_out)
int client_parse_gpg_public_key(const char *armored_key, uint8_t *public_key_out)
int client_parse_ssh_private_key(const char *key_path, uint8_t *secret_key_out)
int client_parse_ssh_public_key(const char *key_line, uint8_t *public_key_out)
int client_get_crypto_error_message(char *output, size_t output_size)
int client_parse_gpg_private_key_binary(const uint8_t *key_data, size_t key_data_len, uint8_t *secret_key_out)
int browser_error_code(size_t index)
const char * browser_error_message(size_t index)
const char * browser_error_function(size_t index)
void browser_error_dismiss(void)
size_t browser_error_snapshot(void)
const char * browser_error_full_file(size_t index)
const char * browser_error_file(size_t index)
int browser_error_line(size_t index)
When code needs to work with asciichat errno snapshot, it keeps total, copied here instead of scatter...