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 : }
|