tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

signing.c (3029B)


      1 /* Copyright (c) 2001 Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * \file signing.c
      9 * \brief Code to sign directory objects.
     10 **/
     11 
     12 #include "core/or/or.h"
     13 #include "feature/dirparse/signing.h"
     14 
     15 /** Helper: used to generate signatures for routers, directories and
     16 * network-status objects.  Given a <b>digest_len</b>-byte digest in
     17 * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded
     18 * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs,
     19 * and return the new signature on success or NULL on failure.
     20 */
     21 char *
     22 router_get_dirobj_signature(const char *digest,
     23                            size_t digest_len,
     24                            const crypto_pk_t *private_key)
     25 {
     26  char *signature;
     27  size_t i, keysize;
     28  int siglen;
     29  char *buf = NULL;
     30  size_t buf_len;
     31  /* overestimate of BEGIN/END lines total len. */
     32 #define BEGIN_END_OVERHEAD_LEN 64
     33 
     34  keysize = crypto_pk_keysize(private_key);
     35  signature = tor_malloc(keysize);
     36  siglen = crypto_pk_private_sign(private_key, signature, keysize,
     37                                  digest, digest_len);
     38  if (siglen < 0) {
     39    log_warn(LD_BUG,"Couldn't sign digest.");
     40    goto err;
     41  }
     42 
     43  /* The *2 here is a ridiculous overestimate of base-64 overhead. */
     44  buf_len = (siglen * 2) + BEGIN_END_OVERHEAD_LEN;
     45  buf = tor_malloc(buf_len);
     46 
     47  if (strlcpy(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
     48    goto truncated;
     49 
     50  i = strlen(buf);
     51  if (base64_encode(buf+i, buf_len-i, signature, siglen,
     52                    BASE64_ENCODE_MULTILINE) < 0) {
     53    log_warn(LD_BUG,"couldn't base64-encode signature");
     54    goto err;
     55  }
     56 
     57  if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
     58    goto truncated;
     59 
     60  tor_free(signature);
     61  return buf;
     62 
     63 truncated:
     64  log_warn(LD_BUG,"tried to exceed string length.");
     65 err:
     66  tor_free(signature);
     67  tor_free(buf);
     68  return NULL;
     69 }
     70 
     71 /** Helper: used to generate signatures for routers, directories and
     72 * network-status objects.  Given a digest in <b>digest</b> and a secret
     73 * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
     74 * surround it with -----BEGIN/END----- pairs, and write it to the
     75 * <b>buf_len</b>-byte buffer at <b>buf</b>.  Return 0 on success, -1 on
     76 * failure.
     77 */
     78 int
     79 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
     80                               size_t digest_len, crypto_pk_t *private_key)
     81 {
     82  size_t sig_len, s_len;
     83  char *sig = router_get_dirobj_signature(digest, digest_len, private_key);
     84  if (!sig) {
     85    log_warn(LD_BUG, "No signature generated");
     86    return -1;
     87  }
     88  sig_len = strlen(sig);
     89  s_len = strlen(buf);
     90  if (sig_len + s_len + 1 > buf_len) {
     91    log_warn(LD_BUG, "Not enough room for signature");
     92    tor_free(sig);
     93    return -1;
     94  }
     95  memcpy(buf+s_len, sig, sig_len+1);
     96  tor_free(sig);
     97  return 0;
     98 }