Line data Source code
1 : #ifndef HEADER_fd_src_disco_keyguard_fd_keyload_h 2 : #define HEADER_fd_src_disco_keyguard_fd_keyload_h 3 : 4 : #include "../fd_disco_base.h" 5 : 6 : /* Internal identity source selected by failover for standby nodes. */ 7 6 : #define FD_KEYLOAD_FAILOVER_JUNK "@failover-junk" 8 : 9 : /* fd_keyload_read() reads a JSON encoded keypair from the provided file 10 : descriptor. The key_path is not opened or read from, it is only used 11 : to output diagnostic error messages if reading the key fails. 12 : 13 : The keypair provided must be a full page (4096) bytes, not just 64 14 : bytes, as additional metadata will be temporarily stored in it while 15 : reading and parsing the key. 16 : 17 : If the key data from the file descriptor is not parsable, or any IO 18 : or other error is encountered while reading it, the process will be 19 : terminated with an error message. */ 20 : 21 : uchar * FD_FN_SENSITIVE 22 : fd_keyload_read( int key_fd, 23 : char const * key_path, 24 : uchar * keypair ); 25 : 26 : /* fd_keyload_load() reads the key file from disk and stores the parsed 27 : contents in a specially mapped page in memory that will not appear in 28 : core dumps, will not be paged out to disk, is read-only, and is 29 : protected by guard pages that cannot be accessed. Callers that need 30 : to mutate the key (e.g. the sign tile during a key switch) must use 31 : fd_keyload_mprotect_wr() to temporarily make the page writable. 32 : 33 : key_path must point to the first letter in a NUL-terminated cstr that 34 : is the path on disk of the key file. The key file must exist, be 35 : readable, and have the form of a Solana keypair (64 element JSON 36 : array of bytes). FD_KEYLOAD_FAILOVER_JUNK instead selects the 37 : failover junk key installed by fd_keyload_set_failover_junk. 38 : If public_key_only is non-zero, zeros out the 39 : private part of the key and returns a pointer to the first byte (of 40 : 32) of the public part of the key in binary format. If 41 : public_key_only is zero, returns a pointer to the first byte (of 64) 42 : of the key in binary format. 43 : 44 : If the key file is not found, is not parsable, or any IO or other 45 : error is encountered while reading it, the process will be terminated 46 : with an error message. 47 : 48 : The error messages assume that you are loading the identity key path 49 : that has been specified in the user configuration file of fdctl so 50 : that they are most helpful in production use. This is a slight 51 : layering violation, and the error messages might not be correct if 52 : a different key is being loaded, or it is not being loaded for use 53 : in the production binary. */ 54 : 55 : uchar const * FD_FN_SENSITIVE 56 : fd_keyload_load( char const * key_path, 57 : int public_key_only ); 58 : 59 : /* Set this tile thread's failover junk public key and private startup 60 : pipe before loading FD_KEYLOAD_FAILOVER_JUNK. Only Sign gets a pipe, 61 : other tiles pass -1 and can load only the public key. */ 62 : 63 : void 64 : fd_keyload_set_failover_junk( uchar const public_key[ 32 ], 65 : int key_fd ); 66 : 67 : /* Generate a fresh Ed25519 keypair in protected memory. The returned 68 : read-only key has the same unload contract as fd_keyload_load with 69 : public_key_only clear. No key material is written to a file. */ 70 : 71 : uchar const * FD_FN_SENSITIVE 72 : fd_keyload_generate( void ); 73 : 74 : /* fd_keyload_mprotect_wr() makes a key page loaded with 75 : fd_keyload_load writable. Accepts the const pointer returned by 76 : fd_keyload_load and returns a non-const pointer that the caller may 77 : write through. The public_key_only argument must match the one 78 : passed to fd_keyload_load. Terminates the process on failure. */ 79 : 80 : uchar * FD_FN_SENSITIVE 81 : fd_keyload_mprotect_wr( uchar const * key, 82 : int public_key_only ); 83 : 84 : /* fd_keyload_mprotect_ro() makes a key page loaded with 85 : fd_keyload_load read-only. Accepts the non-const pointer returned 86 : by fd_keyload_mprotect_wr and returns a const pointer. The 87 : public_key_only argument must match the one passed to 88 : fd_keyload_load. Terminates the process on failure. */ 89 : 90 : uchar const * FD_FN_SENSITIVE 91 : fd_keyload_mprotect_ro( uchar * key, 92 : int public_key_only ); 93 : 94 : /* fd_keyload_unload() unloads a key from shared memory that was loaded 95 : with fd_keyload_load. The argument public_key_only must match the 96 : one provided when the key was loaded. The key should not be accessed 97 : once this function returns and the memory is no longer valid. */ 98 : 99 : void FD_FN_SENSITIVE 100 : fd_keyload_unload( uchar const * key, 101 : int public_key_only ); 102 : 103 : /* fd_keyload_alloc_protected_pages allocates `page_cnt` regular (4 kB) 104 : pages of memory protected by `guard_page_cnt` pages of unreadable and 105 : unwritable memory on each side. Additionally the OS is configured so 106 : that the page_cnt pages in the middle will not be paged out to disk 107 : in a swap file, appear in core dumps, and will be wiped on fork so it 108 : is not readable by any child process forked off from this process. 109 : Terminates the calling process with FD_LOG_ERR with details if the 110 : operation fails. Returns a pointer to the first byte of the 111 : protected memory. Precisely, if ptr is the returned pointer, then 112 : ptr[i] for i in [0, 4096*page_cnt) is readable and writable, but 113 : ptr[i] for i in [-4096*guard_page_cnt, 0) U [4096*page_cnt, 114 : 4096*(page_cnt+guard_page_cnt) ) will cause a SIGSEGV. For current 115 : use cases, there's no use in freeing the pages allocated by this 116 : function, so no free function is provided. */ 117 : 118 : void * FD_FN_SENSITIVE 119 : fd_keyload_alloc_protected_pages( ulong page_cnt, 120 : ulong guard_page_cnt ); 121 : 122 : #endif /* HEADER_fd_src_disco_keyguard_fd_keyload_h */