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 }