PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
key.c
Go to the documentation of this file.
1#include <kernel/fs/key.h>
2
5#include <kernel/log/log.h>
6#include <kernel/log/panic.h>
10#include <kernel/sched/timer.h>
11#include <kernel/sched/wait.h>
12#include <kernel/sync/rwlock.h>
13#include <kernel/utils/map.h>
14
15#include <errno.h>
16#include <stdlib.h>
17#include <string.h>
18#include <sys/list.h>
19#include <time.h>
20
24
25static void key_base64_encode(const uint8_t* src, size_t len, char* dest)
26{
27 static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
28
29 for (size_t i = 0; i < len;)
30 {
31 uint32_t octetA = i < len ? src[i++] : 0;
32 uint32_t octetB = i < len ? src[i++] : 0;
33 uint32_t octetC = i < len ? src[i++] : 0;
34
35 uint32_t n = (octetA << 16) | (octetB << 8) | octetC;
36 *dest++ = table[(n >> 18) & 0x3F];
37 *dest++ = table[(n >> 12) & 0x3F];
38 *dest++ = table[(n >> 6) & 0x3F];
39 *dest++ = table[n & 0x3F];
40 }
41
42 *dest = '\0';
43}
44
46{
47 map_key_t mapKey;
48 do
49 {
50 assert(size <= KEY_MAX);
51 uint8_t bytes[((size - 1) / 4) * 3];
52 if (rand_gen(bytes, sizeof(bytes)) == ERR)
53 {
54 return ERR;
55 }
56 key_base64_encode(bytes, sizeof(bytes), buffer);
57 mapKey = map_key_string(buffer);
58 } while (map_get(&keyMap, &mapKey) != NULL);
59 return 0;
60}
61
62static void key_timer_handler(interrupt_frame_t* frame, cpu_t* self)
63{
64 UNUSED(frame);
65 UNUSED(self);
66
69
70 key_entry_t* entry;
71 key_entry_t* temp;
72 LIST_FOR_EACH_SAFE(entry, temp, &keyList, entry)
73 {
74 if (entry->expiry > uptime)
75 {
76 timer_set(uptime, entry->expiry);
77 break;
78 }
79
80 map_remove(&keyMap, &entry->mapEntry);
81 list_remove(&entry->entry);
82 UNREF(entry->file);
83 free(entry);
84 }
85}
86
87uint64_t key_share(char* key, uint64_t size, file_t* file, clock_t timeout)
88{
89 if (key == NULL || size == 0 || size > KEY_MAX || file == NULL)
90 {
91 errno = EINVAL;
92 return ERR;
93 }
94
95 key_entry_t* entry = malloc(sizeof(key_entry_t));
96 if (entry == NULL)
97 {
98 return ERR;
99 }
100 list_entry_init(&entry->entry);
101 map_entry_init(&entry->mapEntry);
102 entry->file = REF(file);
103 entry->expiry = CLOCKS_DEADLINE(timeout, clock_uptime());
104
106
107 if (key_generate(entry->key, size) == ERR)
108 {
109 UNREF(entry->file);
110 free(entry);
111 return ERR;
112 }
113
114 map_key_t mapKey = map_key_string(entry->key);
115 if (map_insert(&keyMap, &mapKey, &entry->mapEntry) == ERR)
116 {
117 UNREF(entry->file);
118 free(entry);
119 return ERR;
120 }
121
122 memcpy(key, entry->key, size);
124 {
125 list_push_back(&keyList, &entry->entry);
126 timer_set(clock_uptime(), entry->expiry);
127 return 0;
128 }
129
130 bool first = true;
131 key_entry_t* other;
132 LIST_FOR_EACH(other, &keyList, entry)
133 {
134 if (entry->expiry < other->expiry)
135 {
136 list_prepend(&other->entry, &entry->entry);
137 if (first)
138 timer_set(clock_uptime(), entry->expiry);
139 return 0;
140 }
141 first = false;
142 }
143
144 list_push_back(&keyList, &entry->entry);
145 return 0;
146}
147
148file_t* key_claim(const char* key)
149{
150 if (key == NULL)
151 {
152 errno = EINVAL;
153 return NULL;
154 }
155
157 map_key_t mapKey = map_key_string(key);
158 map_entry_t* mapEntry = map_get_and_remove(&keyMap, &mapKey);
159 if (mapEntry == NULL)
160 {
161 errno = ENOENT;
162 return NULL;
163 }
164
165 key_entry_t* entry = CONTAINER_OF(mapEntry, key_entry_t, mapEntry);
166 list_remove(&entry->entry);
167
168 file_t* file = entry->file;
169 free(entry);
170 return file;
171}
172
173SYSCALL_DEFINE(SYS_SHARE, uint64_t, char* key, uint64_t size, fd_t fd, clock_t timeout)
174{
175 thread_t* thread = thread_current();
176 process_t* process = thread->process;
177
178 file_t* file = file_table_get(&process->fileTable, fd);
179 if (file == NULL)
180 {
181 return ERR;
182 }
183 UNREF_DEFER(file);
184
185 char keyCopy[KEY_MAX] = {0};
186 if (key_share(keyCopy, size, file, timeout) == ERR)
187 {
188 return ERR;
189 }
190
191 if (thread_copy_to_user(thread, key, keyCopy, size) == ERR)
192 {
193 UNREF(key_claim(keyCopy));
194 return ERR;
195 }
196 return 0;
197}
198
199SYSCALL_DEFINE(SYS_CLAIM, fd_t, const char* key)
200{
201 thread_t* thread = thread_current();
202 process_t* process = thread->process;
203
204 char keyCopy[KEY_MAX];
205 if (thread_copy_from_user_string(thread, keyCopy, key, KEY_MAX) == ERR)
206 {
207 return ERR;
208 }
209
210 file_t* file = key_claim(keyCopy);
211 if (file == NULL)
212 {
213 return ERR;
214 }
215 UNREF_DEFER(file);
216
217 return file_table_open(&process->fileTable, file);
218}
#define assert(expression)
Definition assert.h:29
EFI_PHYSICAL_ADDRESS buffer
Definition main.c:237
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscall.h:172
@ SYS_SHARE
Definition syscall.h:94
@ SYS_CLAIM
Definition syscall.h:95
uint64_t rand_gen(void *buffer, uint64_t size)
Fills a buffer with random bytes.
Definition rand.c:64
file_t * file_table_get(file_table_t *table, fd_t fd)
Get a file from its file descriptor.
Definition file_table.c:33
fd_t file_table_open(file_table_t *table, file_t *file)
Allocate a new file descriptor for a file.
Definition file_table.c:52
file_t * key_claim(const char *key)
Claims a shared file using the provided key.
Definition key.c:148
uint64_t key_share(char *key, uint64_t size, file_t *file, clock_t timeout)
Generates a key that can be used to retrieve the file within the specified timeout.
Definition key.c:87
clock_t clock_uptime(void)
Retrieve the time in nanoseconds since boot.
Definition clock.c:99
static thread_t * thread_current(void)
Retrieves the currently running thread.
Definition thread.h:126
uint64_t thread_copy_from_user_string(thread_t *thread, char *dest, const char *userSrc, uint64_t size)
Safely copy a string from user space.
Definition thread.c:278
uint64_t thread_copy_to_user(thread_t *thread, void *userDest, const void *src, uint64_t length)
Safely copy data to user space.
Definition thread.c:220
#define LOCK_CREATE()
Create a lock initializer.
Definition lock.h:69
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:58
void timer_set(clock_t now, clock_t deadline)
Schedule a one-shot timer interrupt on the current CPU.
Definition timer.c:139
void map_entry_init(map_entry_t *entry)
Initialize a map entry.
Definition map.c:37
uint64_t map_insert(map_t *map, const map_key_t *key, map_entry_t *value)
Insert a key-value pair into the map.
Definition map.c:170
map_entry_t * map_get_and_remove(map_t *map, const map_key_t *key)
Get and remove a key-value pair from the map.
Definition map.c:301
void map_remove(map_t *map, map_entry_t *entry)
Remove a entry from the map.
Definition map.c:319
map_entry_t * map_get(map_t *map, const map_key_t *key)
Get a value from the map by key.
Definition map.c:253
static map_key_t map_key_string(const char *str)
Create a map key from a string.
Definition map.h:144
#define MAP_CREATE()
Create a map initializer.
Definition map.h:161
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:122
#define REF(ptr)
Increment reference count.
Definition ref.h:82
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:109
#define ENOENT
No such file or directory.
Definition errno.h:42
#define EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
#define UNUSED(x)
Mark a variable as unused.
Definition defs.h:96
#define KEY_MAX
Maximum size of a key generated by share().
Definition fs.h:518
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:58
static void list_remove(list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:290
static void list_push_back(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:322
static void list_prepend(list_entry_t *head, list_entry_t *entry)
Prepends an entry to the list.
Definition list.h:280
#define LIST_CREATE(name)
Creates a list initializer.
Definition list.h:163
#define LIST_FOR_EACH_SAFE(elem, temp, list, member)
Safely iterates over a list, allowing for element removal during iteration.
Definition list.h:73
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:210
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:173
clock_t uptime(void)
System call for retreving the time since boot.
Definition uptime.c:6
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
#define CONTAINER_OF(ptr, type, member)
Container of macro.
__UINT64_TYPE__ fd_t
File descriptor type.
Definition fd_t.h:10
#define CLOCKS_DEADLINE(timeout, uptime)
Safely calculate deadline from timeout.
Definition clock_t.h:47
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
static uint64_t key_generate(char *buffer, uint64_t size)
Definition key.c:45
static list_t keyList
Definition key.c:22
static void key_base64_encode(const uint8_t *src, size_t len, char *dest)
Definition key.c:25
static lock_t keyLock
Definition key.c:23
static map_t keyMap
Definition key.c:21
static void key_timer_handler(interrupt_frame_t *frame, cpu_t *self)
Definition key.c:62
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:61
CPU structure.
Definition cpu.h:84
File structure.
Definition file.h:39
Trap Frame Structure.
Definition interrupt.h:195
Key entry.
Definition key.h:27
clock_t expiry
Definition key.h:32
list_entry_t entry
Definition key.h:28
file_t * file
Definition key.h:31
char key[KEY_MAX]
Definition key.h:30
map_entry_t mapEntry
Definition key.h:29
A doubly linked list.
Definition list.h:46
A simple ticket lock implementation.
Definition lock.h:44
Map entry structure.
Definition map.h:69
Map key stucture.
Definition map.h:57
Hash map structure.
Definition map.h:90
Process structure.
Definition process.h:76
file_table_t fileTable
Definition process.h:88
Thread of execution structure.
Definition thread.h:61
process_t * process
The parent process that the thread executes within.
Definition thread.h:62