test_signkey_revocations.c (8527B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2026 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 exchangedb/test_signkey_revocations.c 18 * @brief tests for the exchangedb functions whose primary table is 19 * `signkey_revocations` 20 * @author Christian Grothoff 21 * 22 * Covers #TALER_EXCHANGEDB_insert_signkey_revocation() and 23 * #TALER_EXCHANGEDB_get_signkey_revocation(). 24 * 25 * `signkey_revocations` references `exchange_sign_keys`, and both functions 26 * find the row through the signing key rather than through the revocation's 27 * own primary key -- so an unknown signing key has to come back as "no 28 * revocation" rather than as an error. The fixture is inserted with 29 * #TALER_EXCHANGEDB_insert_signkey(), whose own table is covered by 30 * test_exchange_sign_keys.c. 31 */ 32 #include "test_common.h" 33 #include "exchange-database/insert_signkey.h" 34 #include "exchange-database/insert_signkey_revocation.h" 35 #include "exchange-database/get_signkey_revocation.h" 36 #include "exchange-database/iterate_active_signkeys.h" 37 38 39 /** 40 * Insert a signing key that is valid for another hour. 41 * 42 * @param pg the database context 43 * @param seed seed for the key and its master signature 44 * @param[out] exchange_pub set to the public key 45 */ 46 static void 47 add_signkey (struct TALER_EXCHANGEDB_PostgresContext *pg, 48 uint32_t seed, 49 struct TALER_ExchangePublicKeyP *exchange_pub) 50 { 51 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 52 struct TALER_MasterSignatureP master_sig; 53 struct TALER_EXCHANGEDB_SignkeyMetaData meta; 54 55 TDB_fill (exchange_pub, 56 sizeof (*exchange_pub), 57 seed); 58 TDB_FILL (master_sig, 59 seed); 60 meta.start = GNUNET_TIME_absolute_to_timestamp (now); 61 meta.expire_sign 62 = GNUNET_TIME_absolute_to_timestamp ( 63 GNUNET_TIME_absolute_add (now, 64 GNUNET_TIME_UNIT_HOURS)); 65 meta.expire_legal 66 = GNUNET_TIME_absolute_to_timestamp ( 67 GNUNET_TIME_absolute_add (now, 68 GNUNET_TIME_relative_multiply ( 69 GNUNET_TIME_UNIT_HOURS, 70 24))); 71 GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 72 TALER_EXCHANGEDB_insert_signkey (pg, 73 exchange_pub, 74 &meta, 75 &master_sig)); 76 } 77 78 79 /** 80 * Counts the keys the active-signkey iterator reports. 81 */ 82 struct CountContext 83 { 84 /** 85 * Key we are looking for. 86 */ 87 const struct TALER_ExchangePublicKeyP *exchange_pub; 88 89 /** 90 * How many times did we see @e exchange_pub? 91 */ 92 unsigned int matched; 93 }; 94 95 96 /** 97 * Callback for #TALER_EXCHANGEDB_iterate_active_signkeys(). 98 * 99 * @param cls a `struct CountContext *` 100 * @param exchange_pub public key of the exchange 101 * @param meta meta data of @a exchange_pub 102 * @param master_sig master signature over @a exchange_pub 103 */ 104 static void 105 count_cb (void *cls, 106 const struct TALER_ExchangePublicKeyP *exchange_pub, 107 const struct TALER_EXCHANGEDB_SignkeyMetaData *meta, 108 const struct TALER_MasterSignatureP *master_sig) 109 { 110 struct CountContext *ctx = cls; 111 112 (void) meta; 113 (void) master_sig; 114 if (0 == GNUNET_memcmp (exchange_pub, 115 ctx->exchange_pub)) 116 ctx->matched++; 117 } 118 119 120 /** 121 * A signing key that does not exist has no revocation, and revoking it 122 * does nothing. 123 * 124 * @param pg the database context 125 * @return 0 on success 126 */ 127 static int 128 check_unknown_signkey (struct TALER_EXCHANGEDB_PostgresContext *pg) 129 { 130 struct TALER_ExchangePublicKeyP exchange_pub; 131 struct TALER_MasterSignatureP master_sig; 132 struct TALER_MasterSignatureP got; 133 134 TDB_FILL (exchange_pub, 135 1); 136 TDB_FILL (master_sig, 137 1); 138 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 139 TALER_EXCHANGEDB_get_signkey_revocation (pg, 140 &exchange_pub, 141 &got)); 142 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 143 TALER_EXCHANGEDB_insert_signkey_revocation (pg, 144 &exchange_pub, 145 &master_sig)); 146 FAILIF (0 != TDB_count (pg, 147 "FROM signkey_revocations")); 148 return 0; 149 } 150 151 152 /** 153 * A key that exists but was not revoked has no revocation either. 154 * 155 * @param pg the database context 156 * @return 0 on success 157 */ 158 static int 159 check_not_revoked (struct TALER_EXCHANGEDB_PostgresContext *pg) 160 { 161 struct TALER_ExchangePublicKeyP exchange_pub; 162 struct TALER_MasterSignatureP got; 163 164 add_signkey (pg, 165 2, 166 &exchange_pub); 167 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 168 TALER_EXCHANGEDB_get_signkey_revocation (pg, 169 &exchange_pub, 170 &got)); 171 return 0; 172 } 173 174 175 /** 176 * Revoking a key records the signature and takes the key out of the 177 * active set. 178 * 179 * @param pg the database context 180 * @return 0 on success 181 */ 182 static int 183 check_revoke (struct TALER_EXCHANGEDB_PostgresContext *pg) 184 { 185 struct TALER_ExchangePublicKeyP exchange_pub; 186 struct TALER_MasterSignatureP master_sig; 187 struct TALER_MasterSignatureP got; 188 struct CountContext ctx; 189 190 add_signkey (pg, 191 3, 192 &exchange_pub); 193 TDB_FILL (master_sig, 194 33); 195 196 /* while unrevoked, the key is active */ 197 memset (&ctx, 198 0, 199 sizeof (ctx)); 200 ctx.exchange_pub = &exchange_pub; 201 FAILIF (0 >= 202 TALER_EXCHANGEDB_iterate_active_signkeys (pg, 203 &count_cb, 204 &ctx)); 205 FAILIF (1 != ctx.matched); 206 207 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 208 TALER_EXCHANGEDB_insert_signkey_revocation (pg, 209 &exchange_pub, 210 &master_sig)); 211 memset (&got, 212 0, 213 sizeof (got)); 214 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 215 TALER_EXCHANGEDB_get_signkey_revocation (pg, 216 &exchange_pub, 217 &got)); 218 FAILIF (0 != GNUNET_memcmp (&got, 219 &master_sig)); 220 221 /* ...and now it is gone from the active set */ 222 memset (&ctx, 223 0, 224 sizeof (ctx)); 225 ctx.exchange_pub = &exchange_pub; 226 FAILIF (0 > 227 TALER_EXCHANGEDB_iterate_active_signkeys (pg, 228 &count_cb, 229 &ctx)); 230 FAILIF (0 != ctx.matched); 231 232 /* the untouched key from the previous check is still fine */ 233 { 234 struct TALER_ExchangePublicKeyP other; 235 236 TDB_FILL (other, 237 2); 238 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 239 TALER_EXCHANGEDB_get_signkey_revocation (pg, 240 &other, 241 &got)); 242 } 243 FAILIF (1 != TDB_count (pg, 244 "FROM signkey_revocations")); 245 return 0; 246 } 247 248 249 /** 250 * The checks to run, in order. 251 */ 252 static const struct TDB_Test tests[] = { 253 { "signkey-revocations-unknown-signkey", 254 &check_unknown_signkey }, 255 { "signkey-revocations-not-revoked", 256 &check_not_revoked }, 257 { "signkey-revocations-revoke", 258 &check_revoke }, 259 { NULL, NULL } 260 }; 261 262 263 int 264 main (int argc, 265 char *const *argv) 266 { 267 return TDB_main (argc, 268 argv, 269 "test-signkey-revocations", 270 "Tests for the exchangedb `signkey_revocations' table", 271 tests); 272 } 273 274 275 /* end of test_signkey_revocations.c */