donau-secmod-rsa.c (7821B)
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 config_invalid = true; 96 opts->global_ret = EXIT_NOTCONFIGURED; 97 return; 98 } 99 if (GNUNET_TIME_relative_cmp (r, 100 !=, 101 GNUNET_TIME_UNIT_YEARS)) 102 { 103 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 104 denomination_alias, 105 "DURATION_WITHDRAW", 106 "Must be exactly 1 year for Donau"); 107 config_invalid = true; 108 opts->global_ret = EXIT_NOTCONFIGURED; 109 return; 110 } 111 if (GNUNET_OK != 112 GNUNET_CONFIGURATION_get_value_time (my_cfg, 113 denomination_alias, 114 "ANCHOR_ROUND", 115 &r)) 116 { 117 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 118 denomination_alias, 119 "ANCHOR_ROUND"); 120 config_invalid = true; 121 opts->global_ret = EXIT_NOTCONFIGURED; 122 return; 123 } 124 if (GNUNET_TIME_relative_cmp (r, 125 !=, 126 GNUNET_TIME_UNIT_YEARS)) 127 { 128 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 129 denomination_alias, 130 "ANCHOR_ROUND", 131 "Must be exactly 1 year for Donau"); 132 config_invalid = true; 133 opts->global_ret = EXIT_NOTCONFIGURED; 134 return; 135 } 136 } 137 138 139 /** 140 * Wrapper around #TALER_SECMOD_rsa_run() that checks that the 141 * configuration abides by the Donau-constraints. 142 * 143 * @param cls must point to a `struct TALER_SECMOD_Options *` 144 * @param args remaining command-line arguments 145 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 146 * @param cfg configuration 147 */ 148 static void 149 donau_rsa_run (void *cls, 150 char *const *args, 151 const char *cfgfile, 152 const struct GNUNET_CONFIGURATION_Handle *cfg) 153 { 154 struct TALER_SECMOD_Options *opts = cls; 155 char *secname; 156 struct GNUNET_TIME_Relative overlap_duration; 157 158 my_cfg = cfg; 159 GNUNET_asprintf (&secname, 160 "%s-secmod-rsa", 161 opts->section); 162 if (GNUNET_OK != 163 GNUNET_CONFIGURATION_get_value_time (cfg, 164 secname, 165 "OVERLAP_DURATION", 166 &overlap_duration)) 167 { 168 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 169 secname, 170 "OVERLAP_DURATION"); 171 opts->global_ret = EXIT_NOTCONFIGURED; 172 GNUNET_free (secname); 173 return; 174 } 175 if (! GNUNET_TIME_relative_is_zero (overlap_duration)) 176 { 177 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 178 secname, 179 "OVERLAP_DURATION", 180 "must be zero for Donau"); 181 opts->global_ret = EXIT_NOTCONFIGURED; 182 GNUNET_free (secname); 183 return; 184 } 185 GNUNET_free (secname); 186 GNUNET_CONFIGURATION_iterate_sections (cfg, 187 &load_denominations, 188 opts); 189 if (config_invalid) 190 { 191 opts->global_ret = EXIT_NOTCONFIGURED; 192 return; 193 } 194 TALER_SECMOD_rsa_run (cls, 195 args, 196 cfgfile, 197 cfg); 198 } 199 200 201 /** 202 * The entry point. 203 * 204 * @param argc number of arguments in @a argv 205 * @param argv command-line arguments 206 * @return 0 on normal termination 207 */ 208 int 209 main (int argc, 210 char **argv) 211 { 212 struct TALER_SECMOD_Options opts = { 213 .max_workers = 16, 214 .section = "donau", 215 .cprefix = "doco_" 216 }; 217 struct GNUNET_GETOPT_CommandLineOption options[] = { 218 TALER_SECMOD_OPTIONS (&opts), 219 GNUNET_GETOPT_OPTION_END 220 }; 221 enum GNUNET_GenericReturnValue ret; 222 223 /* Restrict permissions for the key files that we create. */ 224 (void) umask (S_IWGRP | S_IROTH | S_IWOTH | S_IXOTH); 225 opts.global_now_tmp 226 = opts.global_now 227 = GNUNET_TIME_timestamp_get (); 228 ret = GNUNET_PROGRAM_run (DONAU_project_data (), 229 argc, argv, 230 "taler-exchange-secmod-rsa", 231 "Handle private RSA key operations for a Donau", 232 options, 233 &donau_rsa_run, 234 &opts); 235 if (GNUNET_NO == ret) 236 return EXIT_SUCCESS; 237 if (GNUNET_SYSERR == ret) 238 return EXIT_INVALIDARGUMENT; 239 return opts.global_ret; 240 }