donau-secmod-rsa.c (7713B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file util/donau-secmod-rsa.c 18 * @brief Standalone process to perform private key RSA operations 19 * @author Christian Grothoff 20 * 21 * Key design points: 22 * - EVERY thread of the exchange will have its own pair of connections to the 23 * crypto helpers. This way, every thread will also have its own /keys state 24 * and avoid the need to synchronize on those. 25 * - auditor signatures and master signatures are to be kept in the exchange DB, 26 * and merged with the public keys of the helper by the exchange HTTPD! 27 * - the main loop of the helper is SINGLE-THREADED, but there are 28 * threads for crypto-workers which do the signing in parallel, one per client. 29 * - thread-safety: signing happens in parallel, thus when REMOVING private keys, 30 * we must ensure that all signers are done before we fully free() the 31 * private key. This is done by reference counting (as work is always 32 * assigned and collected by the main thread). 33 */ 34 #include "donau_config.h" 35 #include <sys/stat.h> 36 #include <taler/taler_util.h> 37 #include "donau_util.h" 38 39 /* LSB-style exit status codes */ 40 #ifndef EXIT_INVALIDARGUMENT 41 /** 42 * Command-line arguments are invalid. 43 * Restarting useless. 44 */ 45 #define EXIT_INVALIDARGUMENT 2 46 #endif 47 48 #ifndef EXIT_NOTCONFIGURED 49 /** 50 * Key configuration settings are missing or invalid. 51 * Restarting useless. 52 */ 53 #define EXIT_NOTCONFIGURED 6 54 #endif 55 56 57 /** 58 * Set to true if the configuration is invalid. 59 */ 60 static bool config_invalid; 61 62 /** 63 * Configuration we use. 64 */ 65 static const struct GNUNET_CONFIGURATION_Handle *my_cfg; 66 67 /** 68 * Checks the donau configuration section settings. 69 * denomination_alias. 70 * 71 * @param cls must point to a `struct TALER_SECMOD_Options *` 72 * @param denomination_alias name of the denomination's section in the configuration 73 */ 74 static void 75 load_denominations (void *cls, 76 const char *denomination_alias) 77 { 78 struct TALER_SECMOD_Options *opts = cls; 79 struct GNUNET_TIME_Relative r; 80 81 if (0 != strncasecmp (denomination_alias, 82 opts->cprefix, 83 strlen (opts->cprefix))) 84 return; /* not a denomination type definition */ 85 86 if (GNUNET_OK != 87 GNUNET_CONFIGURATION_get_value_time (my_cfg, 88 denomination_alias, 89 "DURATION_WITHDRAW", 90 &r)) 91 { 92 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 93 denomination_alias, 94 "DURATION_WITHDRAW"); 95 opts->global_ret = EXIT_NOTCONFIGURED; 96 return; 97 } 98 if (GNUNET_TIME_relative_cmp (r, 99 !=, 100 GNUNET_TIME_UNIT_YEARS)) 101 { 102 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 103 denomination_alias, 104 "DURATION_WITHDRAW", 105 "Must be exactly 1 year for Donau"); 106 opts->global_ret = EXIT_NOTCONFIGURED; 107 return; 108 } 109 if (GNUNET_OK != 110 GNUNET_CONFIGURATION_get_value_time (my_cfg, 111 denomination_alias, 112 "ANCHOR_ROUND", 113 &r)) 114 { 115 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 116 denomination_alias, 117 "ANCHOR_ROUND"); 118 opts->global_ret = EXIT_NOTCONFIGURED; 119 return; 120 } 121 if (GNUNET_TIME_relative_cmp (r, 122 !=, 123 GNUNET_TIME_UNIT_YEARS)) 124 { 125 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 126 denomination_alias, 127 "ANCHOR_ROUND", 128 "Must be exactly 1 year for Donau"); 129 opts->global_ret = EXIT_NOTCONFIGURED; 130 return; 131 } 132 } 133 134 135 /** 136 * Wrapper around #TALER_SECMOD_rsa_run() that checks that the 137 * configuration abides by the Donau-constraints. 138 * 139 * @param cls must point to a `struct TALER_SECMOD_Options *` 140 * @param args remaining command-line arguments 141 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 142 * @param cfg configuration 143 */ 144 static void 145 donau_rsa_run (void *cls, 146 char *const *args, 147 const char *cfgfile, 148 const struct GNUNET_CONFIGURATION_Handle *cfg) 149 { 150 struct TALER_SECMOD_Options *opts = cls; 151 char *secname; 152 struct GNUNET_TIME_Relative overlap_duration; 153 154 my_cfg = cfg; 155 GNUNET_asprintf (&secname, 156 "%s-secmod-rsa", 157 opts->section); 158 if (GNUNET_OK != 159 GNUNET_CONFIGURATION_get_value_time (cfg, 160 secname, 161 "OVERLAP_DURATION", 162 &overlap_duration)) 163 { 164 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 165 secname, 166 "OVERLAP_DURATION"); 167 opts->global_ret = EXIT_NOTCONFIGURED; 168 GNUNET_free (secname); 169 return; 170 } 171 if (! GNUNET_TIME_relative_is_zero (overlap_duration)) 172 { 173 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 174 secname, 175 "OVERLAP_DURATION", 176 "must be zero for Donau"); 177 opts->global_ret = EXIT_NOTCONFIGURED; 178 GNUNET_free (secname); 179 return; 180 } 181 GNUNET_free (secname); 182 GNUNET_CONFIGURATION_iterate_sections (cfg, 183 &load_denominations, 184 opts); 185 if (config_invalid) 186 { 187 opts->global_ret = EXIT_NOTCONFIGURED; 188 return; 189 } 190 TALER_SECMOD_rsa_run (cls, 191 args, 192 cfgfile, 193 cfg); 194 } 195 196 197 /** 198 * The entry point. 199 * 200 * @param argc number of arguments in @a argv 201 * @param argv command-line arguments 202 * @return 0 on normal termination 203 */ 204 int 205 main (int argc, 206 char **argv) 207 { 208 struct TALER_SECMOD_Options opts = { 209 .max_workers = 16, 210 .section = "donau", 211 .cprefix = "doco_" 212 }; 213 struct GNUNET_GETOPT_CommandLineOption options[] = { 214 TALER_SECMOD_OPTIONS (&opts), 215 GNUNET_GETOPT_OPTION_END 216 }; 217 enum GNUNET_GenericReturnValue ret; 218 219 /* Restrict permissions for the key files that we create. */ 220 (void) umask (S_IWGRP | S_IROTH | S_IWOTH | S_IXOTH); 221 opts.global_now_tmp 222 = opts.global_now 223 = GNUNET_TIME_timestamp_get (); 224 ret = GNUNET_PROGRAM_run (DONAU_project_data (), 225 argc, argv, 226 "taler-exchange-secmod-rsa", 227 "Handle private RSA key operations for a Donau", 228 options, 229 &donau_rsa_run, 230 &opts); 231 if (GNUNET_NO == ret) 232 return EXIT_SUCCESS; 233 if (GNUNET_SYSERR == ret) 234 return EXIT_INVALIDARGUMENT; 235 return opts.global_ret; 236 }