exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

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 */