LCOV - code coverage report
Current view: top level - feature/dirparse - signing.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 28 45 62.2 %
Date: 2021-11-24 03:28:48 Functions: 2 2 100.0 %

          Line data    Source code
       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          88 : router_get_dirobj_signature(const char *digest,
      23             :                             size_t digest_len,
      24             :                             const crypto_pk_t *private_key)
      25             : {
      26          88 :   char *signature;
      27          88 :   size_t i, keysize;
      28          88 :   int siglen;
      29          88 :   char *buf = NULL;
      30          88 :   size_t buf_len;
      31             :   /* overestimate of BEGIN/END lines total len. */
      32             : #define BEGIN_END_OVERHEAD_LEN 64
      33             : 
      34          88 :   keysize = crypto_pk_keysize(private_key);
      35          88 :   signature = tor_malloc(keysize);
      36          88 :   siglen = crypto_pk_private_sign(private_key, signature, keysize,
      37             :                                   digest, digest_len);
      38          88 :   if (siglen < 0) {
      39           0 :     log_warn(LD_BUG,"Couldn't sign digest.");
      40           0 :     goto err;
      41             :   }
      42             : 
      43             :   /* The *2 here is a ridiculous overestimate of base-64 overhead. */
      44          88 :   buf_len = (siglen * 2) + BEGIN_END_OVERHEAD_LEN;
      45          88 :   buf = tor_malloc(buf_len);
      46             : 
      47          88 :   if (strlcpy(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
      48           0 :     goto truncated;
      49             : 
      50          88 :   i = strlen(buf);
      51          88 :   if (base64_encode(buf+i, buf_len-i, signature, siglen,
      52             :                     BASE64_ENCODE_MULTILINE) < 0) {
      53           0 :     log_warn(LD_BUG,"couldn't base64-encode signature");
      54           0 :     goto err;
      55             :   }
      56             : 
      57          88 :   if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
      58           0 :     goto truncated;
      59             : 
      60          88 :   tor_free(signature);
      61          88 :   return buf;
      62             : 
      63           0 :  truncated:
      64           0 :   log_warn(LD_BUG,"tried to exceed string length.");
      65           0 :  err:
      66           0 :   tor_free(signature);
      67           0 :   tor_free(buf);
      68           0 :   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           6 : 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           6 :   size_t sig_len, s_len;
      83           6 :   char *sig = router_get_dirobj_signature(digest, digest_len, private_key);
      84           6 :   if (!sig) {
      85           0 :     log_warn(LD_BUG, "No signature generated");
      86           0 :     return -1;
      87             :   }
      88           6 :   sig_len = strlen(sig);
      89           6 :   s_len = strlen(buf);
      90           6 :   if (sig_len + s_len + 1 > buf_len) {
      91           0 :     log_warn(LD_BUG, "Not enough room for signature");
      92           0 :     tor_free(sig);
      93           0 :     return -1;
      94             :   }
      95           6 :   memcpy(buf+s_len, sig, sig_len+1);
      96           6 :   tor_free(sig);
      97           6 :   return 0;
      98             : }

Generated by: LCOV version 1.14