LCOV - code coverage report
Current view: top level - feature/nodelist - torcert.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 300 316 94.9 %
Date: 2021-11-24 03:28:48 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2014-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file torcert.c
       6             :  *
       7             :  * \brief Implementation for ed25519-signed certificates as used in the Tor
       8             :  * protocol.
       9             :  *
      10             :  * This certificate format is designed to be simple and compact; it's
      11             :  * documented in tor-spec.txt in the torspec.git repository.  All of the
      12             :  * certificates in this format are signed with an Ed25519 key; the
      13             :  * contents themselves may be another Ed25519 key, a digest of a
      14             :  * RSA key, or some other material.
      15             :  *
      16             :  * In this module there is also support for a crooss-certification of
      17             :  * Ed25519 identities using (older) RSA1024 identities.
      18             :  *
      19             :  * Tor uses other types of certificate too, beyond those described in this
      20             :  * module. Notably, our use of TLS requires us to touch X.509 certificates,
      21             :  * even though sensible people would stay away from those. Our X.509
      22             :  * certificates are represented with tor_x509_cert_t, and implemented in
      23             :  * tortls.c.  We also have a separate certificate type that authorities
      24             :  * use to authenticate their RSA signing keys with their RSA identity keys:
      25             :  * that one is authority_cert_t, and it's mostly handled in routerlist.c.
      26             :  */
      27             : 
      28             : #include "core/or/or.h"
      29             : #include "app/config/config.h"
      30             : #include "lib/crypt_ops/crypto_util.h"
      31             : #include "feature/nodelist/torcert.h"
      32             : #include "trunnel/ed25519_cert.h"
      33             : #include "lib/log/log.h"
      34             : #include "trunnel/link_handshake.h"
      35             : #include "lib/tls/tortls.h"
      36             : #include "lib/tls/x509.h"
      37             : 
      38             : #include "core/or/or_handshake_certs_st.h"
      39             : 
      40             : /** As tor_cert_create(), but accept an arbitrary signed_key_type as the
      41             :  * subject key -- not just an ed25519 key.
      42             :  */
      43             : tor_cert_t *
      44         499 : tor_cert_create_raw(const ed25519_keypair_t *signing_key,
      45             :                       uint8_t cert_type,
      46             :                       uint8_t signed_key_type,
      47             :                       const uint8_t signed_key_info[32],
      48             :                       time_t now, time_t lifetime,
      49             :                       uint32_t flags)
      50             : {
      51         499 :   tor_cert_t *torcert = NULL;
      52             : 
      53         499 :   ed25519_cert_t *cert = ed25519_cert_new();
      54         499 :   tor_assert(cert); // Unlike Tor's, Trunnel's "new" functions can return NULL.
      55         499 :   cert->cert_type = cert_type;
      56         499 :   cert->exp_field = (uint32_t) CEIL_DIV(now + lifetime, 3600);
      57         499 :   cert->cert_key_type = signed_key_type;
      58         499 :   memcpy(cert->certified_key, signed_key_info, 32);
      59             : 
      60         499 :   if (flags & CERT_FLAG_INCLUDE_SIGNING_KEY) {
      61         319 :     ed25519_cert_extension_t *ext = ed25519_cert_extension_new();
      62         319 :     ext->ext_type = CERTEXT_SIGNED_WITH_KEY;
      63         319 :     memcpy(ext->un_signing_key, signing_key->pubkey.pubkey, 32);
      64         319 :     ed25519_cert_add_ext(cert, ext);
      65         319 :     ++cert->n_extensions;
      66             :   }
      67             : 
      68         499 :   const ssize_t alloc_len = ed25519_cert_encoded_len(cert);
      69         499 :   tor_assert(alloc_len > 0);
      70         499 :   uint8_t *encoded = tor_malloc(alloc_len);
      71         499 :   const ssize_t real_len = ed25519_cert_encode(encoded, alloc_len, cert);
      72         499 :   if (real_len < 0)
      73           0 :     goto err;
      74         499 :   tor_assert(real_len == alloc_len);
      75         499 :   tor_assert(real_len > ED25519_SIG_LEN);
      76         499 :   uint8_t *sig = encoded + (real_len - ED25519_SIG_LEN);
      77         499 :   tor_assert(fast_mem_is_zero((char*)sig, ED25519_SIG_LEN));
      78             : 
      79         499 :   ed25519_signature_t signature;
      80         499 :   if (ed25519_sign(&signature, encoded,
      81             :                    real_len-ED25519_SIG_LEN, signing_key)<0) {
      82             :     /* LCOV_EXCL_START */
      83             :     log_warn(LD_BUG, "Can't sign certificate");
      84             :     goto err;
      85             :     /* LCOV_EXCL_STOP */
      86             :   }
      87         499 :   memcpy(sig, signature.sig, ED25519_SIG_LEN);
      88             : 
      89         499 :   torcert = tor_cert_parse(encoded, real_len);
      90         499 :   if (! torcert) {
      91             :     /* LCOV_EXCL_START */
      92             :     log_warn(LD_BUG, "Generated a certificate we cannot parse");
      93             :     goto err;
      94             :     /* LCOV_EXCL_STOP */
      95             :   }
      96             : 
      97         499 :   if (tor_cert_checksig(torcert, &signing_key->pubkey, now) < 0) {
      98             :     /* LCOV_EXCL_START */
      99             :     log_warn(LD_BUG, "Generated a certificate whose signature we can't "
     100             :              "check: %s", tor_cert_describe_signature_status(torcert));
     101             :     goto err;
     102             :     /* LCOV_EXCL_STOP */
     103             :   }
     104             : 
     105         499 :   tor_free(encoded);
     106             : 
     107         499 :   goto done;
     108             : 
     109             :  /* LCOV_EXCL_START */
     110             :  err:
     111             :   tor_cert_free(torcert);
     112             :   torcert = NULL;
     113             :  /* LCOV_EXCL_STOP */
     114             : 
     115         499 :  done:
     116         499 :   ed25519_cert_free(cert);
     117         499 :   tor_free(encoded);
     118         499 :   return torcert;
     119             : }
     120             : 
     121             : /**
     122             :  * Create and return a new new certificate of type <b>cert_type</b> to
     123             :  * authenticate <b>signed_key</b> using the key <b>signing_key</b>.  The
     124             :  * certificate should remain valid for at least <b>lifetime</b> seconds after
     125             :  * <b>now</b>.
     126             :  *
     127             :  * If CERT_FLAG_INCLUDE_SIGNING_KEY is set in <b>flags</b>, embed
     128             :  * the public part of <b>signing_key</b> in the certificate.
     129             :  */
     130             : tor_cert_t *
     131         430 : tor_cert_create_ed25519(const ed25519_keypair_t *signing_key,
     132             :                 uint8_t cert_type,
     133             :                 const ed25519_public_key_t *signed_key,
     134             :                 time_t now, time_t lifetime,
     135             :                 uint32_t flags)
     136             : {
     137         860 :   return tor_cert_create_raw(signing_key, cert_type,
     138         430 :                             SIGNED_KEY_TYPE_ED25519, signed_key->pubkey,
     139             :                             now, lifetime, flags);
     140             : }
     141             : 
     142             : /** Release all storage held for <b>cert</b>. */
     143             : void
     144       10553 : tor_cert_free_(tor_cert_t *cert)
     145             : {
     146       10553 :   if (! cert)
     147             :     return;
     148             : 
     149        7160 :   if (cert->encoded)
     150        1139 :     memwipe(cert->encoded, 0, cert->encoded_len);
     151        7160 :   tor_free(cert->encoded);
     152             : 
     153        7160 :   memwipe(cert, 0, sizeof(tor_cert_t));
     154        7160 :   tor_free(cert);
     155             : }
     156             : 
     157             : /** Parse a certificate encoded with <b>len</b> bytes in <b>encoded</b>. */
     158             : tor_cert_t *
     159        1248 : tor_cert_parse(const uint8_t *encoded, const size_t len)
     160             : {
     161        1248 :   tor_cert_t *cert = NULL;
     162        1248 :   ed25519_cert_t *parsed = NULL;
     163        1248 :   ssize_t got_len = ed25519_cert_parse(&parsed, encoded, len);
     164        1248 :   if (got_len < 0 || (size_t) got_len != len)
     165          40 :     goto err;
     166             : 
     167        1208 :   cert = tor_malloc_zero(sizeof(tor_cert_t));
     168        1208 :   cert->encoded = tor_memdup(encoded, len);
     169        1208 :   cert->encoded_len = len;
     170             : 
     171        1208 :   memcpy(cert->signed_key.pubkey, parsed->certified_key, 32);
     172        1208 :   int64_t valid_until_64 = ((int64_t)parsed->exp_field) * 3600;
     173             : #if SIZEOF_TIME_T < 8
     174             :   if (valid_until_64 > TIME_MAX)
     175             :     valid_until_64 = TIME_MAX - 1;
     176             : #endif
     177        1208 :   cert->valid_until = (time_t) valid_until_64;
     178        1208 :   cert->cert_type = parsed->cert_type;
     179             : 
     180        2362 :   for (unsigned i = 0; i < ed25519_cert_getlen_ext(parsed); ++i) {
     181        1160 :     ed25519_cert_extension_t *ext = ed25519_cert_get_ext(parsed, i);
     182        1160 :     if (ext->ext_type == CERTEXT_SIGNED_WITH_KEY) {
     183         888 :       if (cert->signing_key_included)
     184           2 :         goto err;
     185             : 
     186         886 :       cert->signing_key_included = 1;
     187        1154 :       memcpy(cert->signing_key.pubkey, ext->un_signing_key, 32);
     188         272 :     } else if (ext->ext_flags & CERTEXT_FLAG_AFFECTS_VALIDATION) {
     189             :       /* Unrecognized extension with affects_validation set */
     190           4 :       goto err;
     191             :     }
     192             :   }
     193             : 
     194        1202 :   goto done;
     195          46 :  err:
     196          46 :   tor_cert_free(cert);
     197          46 :   cert = NULL;
     198        1248 :  done:
     199        1248 :   ed25519_cert_free(parsed);
     200        1248 :   return cert;
     201             : }
     202             : 
     203             : /** Fill in <b>checkable_out</b> with the information needed to check
     204             :  * the signature on <b>cert</b> with <b>pubkey</b>.
     205             :  *
     206             :  * On success, if <b>expiration_out</b> is provided, and it is some time
     207             :  * _after_ the expiration time of this certificate, set it to the
     208             :  * expiration time of this certificate.
     209             :  */
     210             : int
     211        1485 : tor_cert_get_checkable_sig(ed25519_checkable_t *checkable_out,
     212             :                            const tor_cert_t *cert,
     213             :                            const ed25519_public_key_t *pubkey,
     214             :                            time_t *expiration_out)
     215             : {
     216        1485 :   if (! pubkey) {
     217         152 :     if (cert->signing_key_included)
     218         151 :       pubkey = &cert->signing_key;
     219             :     else
     220             :       return -1;
     221             :   }
     222             : 
     223        1484 :   checkable_out->msg = cert->encoded;
     224        1484 :   checkable_out->pubkey = pubkey;
     225        1484 :   tor_assert(cert->encoded_len > ED25519_SIG_LEN);
     226        1484 :   const size_t signed_len = cert->encoded_len - ED25519_SIG_LEN;
     227        1484 :   checkable_out->len = signed_len;
     228        1484 :   memcpy(checkable_out->signature.sig,
     229        1484 :          cert->encoded + signed_len, ED25519_SIG_LEN);
     230             : 
     231        1484 :   if (expiration_out) {
     232        1453 :     *expiration_out = MIN(*expiration_out, cert->valid_until);
     233             :   }
     234             : 
     235             :   return 0;
     236             : }
     237             : 
     238             : /** Validates the signature on <b>cert</b> with <b>pubkey</b> relative to the
     239             :  * current time <b>now</b>.  (If <b>now</b> is 0, do not check the expiration
     240             :  * time.) Return 0 on success, -1 on failure.  Sets flags in <b>cert</b> as
     241             :  * appropriate.
     242             :  */
     243             : int
     244        1220 : tor_cert_checksig(tor_cert_t *cert,
     245             :                   const ed25519_public_key_t *pubkey, time_t now)
     246             : {
     247        1220 :   ed25519_checkable_t checkable;
     248        1220 :   int okay;
     249        1220 :   time_t expires = TIME_MAX;
     250             : 
     251        1220 :   if (tor_cert_get_checkable_sig(&checkable, cert, pubkey, &expires) < 0)
     252             :     return -1;
     253             : 
     254        1219 :   if (now && now > expires) {
     255           3 :     cert->cert_expired = 1;
     256           3 :     return -1;
     257             :   }
     258             : 
     259        1216 :   if (ed25519_checksig_batch(&okay, &checkable, 1) < 0) {
     260           4 :     cert->sig_bad = 1;
     261           4 :     return -1;
     262             :   } else {
     263        1212 :     cert->sig_ok = 1;
     264             :     /* Only copy the checkable public key when it is different from the signing
     265             :      * key of the certificate to avoid undefined behavior. */
     266        1212 :     if (cert->signing_key.pubkey != checkable.pubkey->pubkey) {
     267         830 :       memcpy(cert->signing_key.pubkey, checkable.pubkey->pubkey, 32);
     268             :     }
     269        1212 :     cert->cert_valid = 1;
     270        1212 :     return 0;
     271             :   }
     272             : }
     273             : 
     274             : /** Return a string describing the status of the signature on <b>cert</b>
     275             :  *
     276             :  * Will always be "unchecked" unless tor_cert_checksig has been called.
     277             :  */
     278             : const char *
     279           3 : tor_cert_describe_signature_status(const tor_cert_t *cert)
     280             : {
     281           3 :   if (cert->cert_expired) {
     282             :     return "expired";
     283           2 :   } else if (cert->sig_bad) {
     284             :     return "mis-signed";
     285           0 :   } else if (cert->sig_ok) {
     286             :     return "okay";
     287             :   } else {
     288           0 :     return "unchecked";
     289             :   }
     290             : }
     291             : 
     292             : /** Return a new copy of <b>cert</b> */
     293          44 : MOCK_IMPL(tor_cert_t *,
     294             : tor_cert_dup,(const tor_cert_t *cert))
     295             : {
     296          44 :   tor_cert_t *newcert = tor_memdup(cert, sizeof(tor_cert_t));
     297          44 :   if (cert->encoded)
     298          44 :     newcert->encoded = tor_memdup(cert->encoded, cert->encoded_len);
     299          44 :   return newcert;
     300             : }
     301             : 
     302             : /** Return true iff cert1 and cert2 are the same cert. */
     303             : int
     304          27 : tor_cert_eq(const tor_cert_t *cert1, const tor_cert_t *cert2)
     305             : {
     306          27 :   tor_assert(cert1);
     307          27 :   tor_assert(cert2);
     308          54 :   return cert1->encoded_len == cert2->encoded_len &&
     309          27 :     tor_memeq(cert1->encoded, cert2->encoded, cert1->encoded_len);
     310             : }
     311             : 
     312             : /** Return true iff cert1 and cert2 are the same cert, or if they are both
     313             :  * NULL. */
     314             : int
     315           6 : tor_cert_opt_eq(const tor_cert_t *cert1, const tor_cert_t *cert2)
     316             : {
     317           6 :   if (cert1 == NULL && cert2 == NULL)
     318             :     return 1;
     319           6 :   if (!cert1 || !cert2)
     320             :     return 0;
     321           6 :   return tor_cert_eq(cert1, cert2);
     322             : }
     323             : 
     324             : #define RSA_ED_CROSSCERT_PREFIX "Tor TLS RSA/Ed25519 cross-certificate"
     325             : 
     326             : /** Create new cross-certification object to certify <b>ed_key</b> as the
     327             :  * master ed25519 identity key for the RSA identity key <b>rsa_key</b>.
     328             :  * Allocates and stores the encoded certificate in *<b>cert</b>, and returns
     329             :  * the number of bytes stored. Returns negative on error.*/
     330             : ssize_t
     331         111 : tor_make_rsa_ed25519_crosscert(const ed25519_public_key_t *ed_key,
     332             :                                const crypto_pk_t *rsa_key,
     333             :                                time_t expires,
     334             :                                uint8_t **cert)
     335             : {
     336             :   // It is later than 1985, since otherwise there would be no C89
     337             :   // compilers. (Try to diagnose #22466.)
     338         111 :   tor_assert_nonfatal(expires >= 15 * 365 * 86400);
     339             : 
     340         111 :   uint8_t *res;
     341             : 
     342         111 :   rsa_ed_crosscert_t *cc = rsa_ed_crosscert_new();
     343         111 :   memcpy(cc->ed_key, ed_key->pubkey, ED25519_PUBKEY_LEN);
     344         111 :   cc->expiration = (uint32_t) CEIL_DIV(expires, 3600);
     345         111 :   cc->sig_len = crypto_pk_keysize(rsa_key);
     346         111 :   rsa_ed_crosscert_setlen_sig(cc, crypto_pk_keysize(rsa_key));
     347             : 
     348         111 :   ssize_t alloc_sz = rsa_ed_crosscert_encoded_len(cc);
     349         111 :   tor_assert(alloc_sz > 0);
     350         111 :   res = tor_malloc_zero(alloc_sz);
     351         111 :   ssize_t sz = rsa_ed_crosscert_encode(res, alloc_sz, cc);
     352         111 :   tor_assert(sz > 0 && sz <= alloc_sz);
     353             : 
     354         111 :   crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
     355         111 :   crypto_digest_add_bytes(d, RSA_ED_CROSSCERT_PREFIX,
     356             :                           strlen(RSA_ED_CROSSCERT_PREFIX));
     357             : 
     358         111 :   const int signed_part_len = 32 + 4;
     359         111 :   crypto_digest_add_bytes(d, (char*)res, signed_part_len);
     360             : 
     361         111 :   uint8_t digest[DIGEST256_LEN];
     362         111 :   crypto_digest_get_digest(d, (char*)digest, sizeof(digest));
     363         111 :   crypto_digest_free(d);
     364             : 
     365         222 :   int siglen = crypto_pk_private_sign(rsa_key,
     366         111 :                                       (char*)rsa_ed_crosscert_getarray_sig(cc),
     367             :                                       rsa_ed_crosscert_getlen_sig(cc),
     368             :                                       (char*)digest, sizeof(digest));
     369         111 :   tor_assert(siglen > 0 && siglen <= (int)crypto_pk_keysize(rsa_key));
     370         111 :   tor_assert(siglen <= UINT8_MAX);
     371         111 :   cc->sig_len = siglen;
     372         111 :   rsa_ed_crosscert_setlen_sig(cc, siglen);
     373             : 
     374         111 :   sz = rsa_ed_crosscert_encode(res, alloc_sz, cc);
     375         111 :   rsa_ed_crosscert_free(cc);
     376         111 :   *cert = res;
     377         111 :   return sz;
     378             : }
     379             : 
     380             : /**
     381             :  * Check whether the <b>crosscert_len</b> byte certificate in <b>crosscert</b>
     382             :  * is in fact a correct cross-certification of <b>master_key</b> using
     383             :  * the RSA key <b>rsa_id_key</b>.
     384             :  *
     385             :  * Also reject the certificate if it expired before
     386             :  * <b>reject_if_expired_before</b>.
     387             :  *
     388             :  * Return 0 on success, negative on failure.
     389             :  */
     390          86 : MOCK_IMPL(int,
     391             : rsa_ed25519_crosscert_check, (const uint8_t *crosscert,
     392             :                               const size_t crosscert_len,
     393             :                               const crypto_pk_t *rsa_id_key,
     394             :                               const ed25519_public_key_t *master_key,
     395             :                               const time_t reject_if_expired_before))
     396             : {
     397          86 :   rsa_ed_crosscert_t *cc = NULL;
     398          86 :   int rv;
     399             : 
     400             : #define ERR(code, s)                                            \
     401             :   do {                                                          \
     402             :     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,                      \
     403             :            "Received a bad RSA->Ed25519 crosscert: %s",         \
     404             :            (s));                                                \
     405             :     rv = (code);                                                \
     406             :     goto err;                                                   \
     407             :   } while (0)
     408             : 
     409          86 :   if (BUG(crypto_pk_keysize(rsa_id_key) > PK_BYTES))
     410           0 :     return -1;
     411             : 
     412          86 :   if (BUG(!crosscert))
     413           0 :     return -1;
     414             : 
     415          86 :   ssize_t parsed_len = rsa_ed_crosscert_parse(&cc, crosscert, crosscert_len);
     416          86 :   if (parsed_len < 0 || crosscert_len != (size_t)parsed_len) {
     417           2 :     ERR(-2, "Unparseable or overlong crosscert");
     418             :   }
     419             : 
     420          84 :   if (tor_memneq(rsa_ed_crosscert_getarray_ed_key(cc),
     421             :                  master_key->pubkey,
     422             :                  ED25519_PUBKEY_LEN)) {
     423           1 :     ERR(-3, "Crosscert did not match Ed25519 key");
     424             :   }
     425             : 
     426          83 :   const uint32_t expiration_date = rsa_ed_crosscert_get_expiration(cc);
     427          83 :   const uint64_t expiration_time = ((uint64_t)expiration_date) * 3600;
     428             : 
     429          83 :   if (reject_if_expired_before < 0 ||
     430          83 :       expiration_time < (uint64_t)reject_if_expired_before) {
     431           2 :     ERR(-4, "Crosscert is expired");
     432             :   }
     433             : 
     434          81 :   const uint8_t *eos = rsa_ed_crosscert_get_end_of_signed(cc);
     435          81 :   const uint8_t *sig = rsa_ed_crosscert_getarray_sig(cc);
     436          81 :   const uint8_t siglen = rsa_ed_crosscert_get_sig_len(cc);
     437          81 :   tor_assert(eos >= crosscert);
     438          81 :   tor_assert((size_t)(eos - crosscert) <= crosscert_len);
     439          81 :   tor_assert(siglen == rsa_ed_crosscert_getlen_sig(cc));
     440             : 
     441             :   /* Compute the digest */
     442          81 :   uint8_t digest[DIGEST256_LEN];
     443          81 :   crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
     444          81 :   crypto_digest_add_bytes(d, RSA_ED_CROSSCERT_PREFIX,
     445             :                           strlen(RSA_ED_CROSSCERT_PREFIX));
     446          81 :   crypto_digest_add_bytes(d, (char*)crosscert, eos-crosscert);
     447          81 :   crypto_digest_get_digest(d, (char*)digest, sizeof(digest));
     448          81 :   crypto_digest_free(d);
     449             : 
     450             :   /* Now check the signature */
     451          81 :   uint8_t signed_[PK_BYTES];
     452          81 :   int signed_len = crypto_pk_public_checksig(rsa_id_key,
     453             :                                           (char*)signed_, sizeof(signed_),
     454             :                                           (char*)sig, siglen);
     455          81 :   if (signed_len < DIGEST256_LEN) {
     456           2 :     ERR(-5, "Bad signature, or length of signed data not as expected");
     457             :   }
     458             : 
     459          79 :   if (tor_memneq(digest, signed_, DIGEST256_LEN)) {
     460           1 :     ERR(-6, "The signature was good, but it didn't match the data");
     461             :   }
     462             : 
     463             :   rv = 0;
     464          86 :  err:
     465          86 :   rsa_ed_crosscert_free(cc);
     466          86 :   return rv;
     467             : }
     468             : 
     469             : /** Construct and return a new empty or_handshake_certs object */
     470             : or_handshake_certs_t *
     471         101 : or_handshake_certs_new(void)
     472             : {
     473         101 :   return tor_malloc_zero(sizeof(or_handshake_certs_t));
     474             : }
     475             : 
     476             : /** Release all storage held in <b>certs</b> */
     477             : void
     478         101 : or_handshake_certs_free_(or_handshake_certs_t *certs)
     479             : {
     480         101 :   if (!certs)
     481             :     return;
     482             : 
     483         101 :   tor_x509_cert_free(certs->auth_cert);
     484         101 :   tor_x509_cert_free(certs->link_cert);
     485         101 :   tor_x509_cert_free(certs->id_cert);
     486             : 
     487         101 :   tor_cert_free(certs->ed_id_sign);
     488         101 :   tor_cert_free(certs->ed_sign_link);
     489         101 :   tor_cert_free(certs->ed_sign_auth);
     490         101 :   tor_free(certs->ed_rsa_crosscert);
     491             : 
     492         101 :   memwipe(certs, 0xBD, sizeof(*certs));
     493         101 :   tor_free(certs);
     494             : }
     495             : 
     496             : #undef ERR
     497             : #define ERR(s)                                                  \
     498             :   do {                                                          \
     499             :     log_fn(severity, LD_PROTOCOL,                               \
     500             :            "Received a bad CERTS cell: %s",                     \
     501             :            (s));                                                \
     502             :     return 0;                                                   \
     503             :   } while (0)
     504             : 
     505             : int
     506          12 : or_handshake_certs_rsa_ok(int severity,
     507             :                           or_handshake_certs_t *certs,
     508             :                           tor_tls_t *tls,
     509             :                           time_t now)
     510             : {
     511          12 :   tor_x509_cert_t *link_cert = certs->link_cert;
     512          12 :   tor_x509_cert_t *auth_cert = certs->auth_cert;
     513          12 :   tor_x509_cert_t *id_cert = certs->id_cert;
     514             : 
     515          12 :   if (certs->started_here) {
     516           8 :     if (! (id_cert && link_cert))
     517           2 :       ERR("The certs we wanted (ID, Link) were missing");
     518           6 :     if (! tor_tls_cert_matches_key(tls, link_cert))
     519           0 :       ERR("The link certificate didn't match the TLS public key");
     520           6 :     if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, now, 0))
     521           2 :       ERR("The link certificate was not valid");
     522           4 :     if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, now, 1))
     523           1 :       ERR("The ID certificate was not valid");
     524             :   } else {
     525           4 :     if (! (id_cert && auth_cert))
     526           1 :       ERR("The certs we wanted (ID, Auth) were missing");
     527           3 :     if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, now, 1))
     528           1 :       ERR("The authentication certificate was not valid");
     529           2 :     if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, now, 1))
     530           0 :       ERR("The ID certificate was not valid");
     531             :   }
     532             : 
     533             :   return 1;
     534             : }
     535             : 
     536             : /** Check all the ed25519 certificates in <b>certs</b> against each other, and
     537             :  * against the peer certificate in <b>tls</b> if appropriate.  On success,
     538             :  * return 0; on failure, return a negative value and warn at level
     539             :  * <b>severity</b> */
     540             : int
     541          19 : or_handshake_certs_ed25519_ok(int severity,
     542             :                               or_handshake_certs_t *certs,
     543             :                               tor_tls_t *tls,
     544             :                               time_t now)
     545             : {
     546          19 :   ed25519_checkable_t check[10];
     547          19 :   unsigned n_checkable = 0;
     548          19 :   time_t expiration = TIME_MAX;
     549             : 
     550             : #define ADDCERT(cert, pk)                                               \
     551             :   do {                                                                  \
     552             :     tor_assert(n_checkable < ARRAY_LENGTH(check));                      \
     553             :     if (tor_cert_get_checkable_sig(&check[n_checkable++], cert, pk,     \
     554             :                                    &expiration) < 0)                    \
     555             :       ERR("Could not get checkable cert.");                             \
     556             :   } while (0)
     557             : 
     558          19 :   if (! certs->ed_id_sign || !certs->ed_id_sign->signing_key_included) {
     559           1 :     ERR("No Ed25519 signing key");
     560             :   }
     561          18 :   ADDCERT(certs->ed_id_sign, NULL);
     562             : 
     563          18 :   if (certs->started_here) {
     564          15 :     if (! certs->ed_sign_link)
     565           2 :       ERR("No Ed25519 link key");
     566             :     {
     567             :       /* check for a match with the TLS cert. */
     568          13 :       tor_x509_cert_t *peer_cert = tor_tls_get_peer_cert(tls);
     569          13 :       if (BUG(!peer_cert)) {
     570             :         /* This is a bug, because if we got to this point, we are a connection
     571             :          * that was initiated here, and we completed a TLS handshake. The
     572             :          * other side *must* have given us a certificate! */
     573             :         ERR("No x509 peer cert"); // LCOV_EXCL_LINE
     574             :       }
     575          13 :       const common_digests_t *peer_cert_digests =
     576          13 :         tor_x509_cert_get_cert_digests(peer_cert);
     577          26 :       int okay = tor_memeq(peer_cert_digests->d[DIGEST_SHA256],
     578          13 :                            certs->ed_sign_link->signed_key.pubkey,
     579             :                            DIGEST256_LEN);
     580          13 :       tor_x509_cert_free(peer_cert);
     581          13 :       if (!okay)
     582           1 :         ERR("Link certificate does not match TLS certificate");
     583             :     }
     584             : 
     585          12 :     ADDCERT(certs->ed_sign_link, &certs->ed_id_sign->signed_key);
     586             : 
     587             :   } else {
     588           3 :     if (! certs->ed_sign_auth)
     589           1 :       ERR("No Ed25519 link authentication key");
     590           2 :     ADDCERT(certs->ed_sign_auth, &certs->ed_id_sign->signed_key);
     591             :   }
     592             : 
     593          14 :   if (expiration < now) {
     594           2 :     ERR("At least one certificate expired.");
     595             :   }
     596             : 
     597             :   /* Okay, we've gotten ready to check all the Ed25519 certificates.
     598             :    * Now, we are going to check the RSA certificate's cross-certification
     599             :    * with the ED certificates.
     600             :    *
     601             :    * FFFF In the future, we might want to make this optional.
     602             :    */
     603             : 
     604          12 :   tor_x509_cert_t *rsa_id_cert = certs->id_cert;
     605          12 :   if (!rsa_id_cert) {
     606           1 :     ERR("Missing legacy RSA ID certificate");
     607             :   }
     608          11 :   if (! tor_tls_cert_is_valid(severity, rsa_id_cert, rsa_id_cert, now, 1)) {
     609           2 :     ERR("The legacy RSA ID certificate was not valid");
     610             :   }
     611           9 :   if (! certs->ed_rsa_crosscert) {
     612           1 :     ERR("Missing RSA->Ed25519 crosscert");
     613             :   }
     614           8 :   crypto_pk_t *rsa_id_key = tor_tls_cert_get_key(rsa_id_cert);
     615           8 :   if (!rsa_id_key) {
     616           0 :     ERR("RSA ID cert had no RSA key");
     617             :   }
     618             : 
     619           8 :   if (rsa_ed25519_crosscert_check(certs->ed_rsa_crosscert,
     620             :                                   certs->ed_rsa_crosscert_len,
     621             :                                   rsa_id_key,
     622           8 :                                   &certs->ed_id_sign->signing_key,
     623             :                                   now) < 0) {
     624           3 :     crypto_pk_free(rsa_id_key);
     625           3 :     ERR("Invalid RSA->Ed25519 crosscert");
     626             :   }
     627           5 :   crypto_pk_free(rsa_id_key);
     628           5 :   rsa_id_key = NULL;
     629             : 
     630             :   /* FFFF We could save a little time in the client case by queueing
     631             :    * this batch to check it later, along with the signature from the
     632             :    * AUTHENTICATE cell. That will change our data flow a bit, though,
     633             :    * so I say "postpone". */
     634             : 
     635           5 :   if (ed25519_checksig_batch(NULL, check, n_checkable) < 0) {
     636           1 :     ERR("At least one Ed25519 certificate was badly signed");
     637             :   }
     638             : 
     639             :   return 1;
     640             : }
     641             : 
     642             : /** Check whether an RSA-TAP cross-certification is correct. Return 0 if it
     643             :  * is, -1 if it isn't. */
     644          76 : MOCK_IMPL(int,
     645             : check_tap_onion_key_crosscert,(const uint8_t *crosscert,
     646             :                                int crosscert_len,
     647             :                                const crypto_pk_t *onion_pkey,
     648             :                                const ed25519_public_key_t *master_id_pkey,
     649             :                                const uint8_t *rsa_id_digest))
     650             : {
     651          76 :   uint8_t *cc = tor_malloc(crypto_pk_keysize(onion_pkey));
     652          76 :   int cc_len =
     653          76 :     crypto_pk_public_checksig(onion_pkey,
     654             :                               (char*)cc,
     655             :                               crypto_pk_keysize(onion_pkey),
     656             :                               (const char*)crosscert,
     657             :                               crosscert_len);
     658          76 :   if (cc_len < 0) {
     659           0 :     goto err;
     660             :   }
     661          76 :   if (cc_len < DIGEST_LEN + ED25519_PUBKEY_LEN) {
     662           0 :     log_warn(LD_DIR, "Short signature on cross-certification with TAP key");
     663           0 :     goto err;
     664             :   }
     665         152 :   if (tor_memneq(cc, rsa_id_digest, DIGEST_LEN) ||
     666          76 :       tor_memneq(cc + DIGEST_LEN, master_id_pkey->pubkey,
     667             :                  ED25519_PUBKEY_LEN)) {
     668           0 :     log_warn(LD_DIR, "Incorrect cross-certification with TAP key");
     669           0 :     goto err;
     670             :   }
     671             : 
     672          76 :   tor_free(cc);
     673          76 :   return 0;
     674           0 :  err:
     675           0 :   tor_free(cc);
     676           0 :   return -1;
     677             : }
     678             : 
     679             : /**
     680             :  * Check the Ed certificates and/or the RSA certificates, as appropriate.  If
     681             :  * we obtained an Ed25519 identity, set *ed_id_out. If we obtained an RSA
     682             :  * identity, set *rs_id_out. Otherwise, set them both to NULL.
     683             :  */
     684             : void
     685          31 : or_handshake_certs_check_both(int severity,
     686             :                               or_handshake_certs_t *certs,
     687             :                               tor_tls_t *tls,
     688             :                               time_t now,
     689             :                               const ed25519_public_key_t **ed_id_out,
     690             :                               const common_digests_t **rsa_id_out)
     691             : {
     692          31 :   tor_assert(ed_id_out);
     693          31 :   tor_assert(rsa_id_out);
     694             : 
     695          31 :   *ed_id_out = NULL;
     696          31 :   *rsa_id_out = NULL;
     697             : 
     698          31 :   if (certs->ed_id_sign) {
     699          19 :     if (or_handshake_certs_ed25519_ok(severity, certs, tls, now)) {
     700           4 :       tor_assert(certs->ed_id_sign);
     701           4 :       tor_assert(certs->id_cert);
     702             : 
     703           4 :       *ed_id_out = &certs->ed_id_sign->signing_key;
     704           4 :       *rsa_id_out = tor_x509_cert_get_id_digests(certs->id_cert);
     705             : 
     706             :       /* If we reached this point, we did not look at any of the
     707             :        * subsidiary RSA certificates, so we'd better just remove them.
     708             :        */
     709           4 :       tor_x509_cert_free(certs->link_cert);
     710           4 :       tor_x509_cert_free(certs->auth_cert);
     711           4 :       certs->link_cert = certs->auth_cert = NULL;
     712             :     }
     713             :     /* We do _not_ fall through here.  If you provided us Ed25519
     714             :      * certificates, we expect to verify them! */
     715             :   } else {
     716             :     /* No ed25519 keys given in the CERTS cell */
     717          12 :     if (or_handshake_certs_rsa_ok(severity, certs, tls, now)) {
     718           5 :       *rsa_id_out = tor_x509_cert_get_id_digests(certs->id_cert);
     719             :     }
     720             :   }
     721          31 : }
     722             : 
     723             : /* === ENCODING === */
     724             : 
     725             : /* Encode the ed25519 certificate <b>cert</b> and put the newly allocated
     726             :  * string in <b>cert_str_out</b>. Return 0 on success else a negative value. */
     727             : int
     728         268 : tor_cert_encode_ed22519(const tor_cert_t *cert, char **cert_str_out)
     729             : {
     730         268 :   int ret = -1;
     731         268 :   char *ed_cert_b64 = NULL;
     732         268 :   size_t ed_cert_b64_len;
     733             : 
     734         268 :   tor_assert(cert);
     735         268 :   tor_assert(cert_str_out);
     736             : 
     737             :   /* Get the encoded size and add the NUL byte. */
     738         268 :   ed_cert_b64_len = base64_encode_size(cert->encoded_len,
     739             :                                        BASE64_ENCODE_MULTILINE) + 1;
     740         268 :   ed_cert_b64 = tor_malloc_zero(ed_cert_b64_len);
     741             : 
     742             :   /* Base64 encode the encoded certificate. */
     743         268 :   if (base64_encode(ed_cert_b64, ed_cert_b64_len,
     744         268 :                     (const char *) cert->encoded, cert->encoded_len,
     745             :                     BASE64_ENCODE_MULTILINE) < 0) {
     746             :     /* LCOV_EXCL_START */
     747             :     log_err(LD_BUG, "Couldn't base64-encode ed22519 cert!");
     748             :     goto err;
     749             :     /* LCOV_EXCL_STOP */
     750             :   }
     751             : 
     752             :   /* Put everything together in a NUL terminated string. */
     753         268 :   tor_asprintf(cert_str_out,
     754             :                "-----BEGIN ED25519 CERT-----\n"
     755             :                "%s"
     756             :                "-----END ED25519 CERT-----",
     757             :                ed_cert_b64);
     758             :   /* Success! */
     759         268 :   ret = 0;
     760             : 
     761         268 :  err:
     762         268 :   tor_free(ed_cert_b64);
     763         268 :   return ret;
     764             : }

Generated by: LCOV version 1.14