mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Add cross-certification to authority key certificates. Partial implementation of proposal 157.
svn:r17610
This commit is contained in:
parent
6c2dbc56bf
commit
69ce955484
@ -19,6 +19,9 @@ Changes in version 0.2.1.9-alpha - 200?-??-??
|
|||||||
- Try not to open more than one descriptor-downloading connection to an
|
- Try not to open more than one descriptor-downloading connection to an
|
||||||
authority at once. This should reduce load on directory authorities.
|
authority at once. This should reduce load on directory authorities.
|
||||||
Fixes bug 366.
|
Fixes bug 366.
|
||||||
|
- Add cross-certification to newly generated certificates, so that
|
||||||
|
a signing key is enough information to use to look up a certificate.
|
||||||
|
Partial implementation of proposal 157.
|
||||||
|
|
||||||
o Minor features (controller):
|
o Minor features (controller):
|
||||||
- New CONSENSUS_ARRIVED event to note when a new consensus has
|
- New CONSENSUS_ARRIVED event to note when a new consensus has
|
||||||
|
@ -758,6 +758,25 @@ $Id$
|
|||||||
The directory server's public signing key. This key MUST be at
|
The directory server's public signing key. This key MUST be at
|
||||||
least 1024 bits, and MAY be longer.
|
least 1024 bits, and MAY be longer.
|
||||||
|
|
||||||
|
"dir-key-crosscert" NL CrossSignature NL
|
||||||
|
|
||||||
|
[At most once.]
|
||||||
|
|
||||||
|
NOTE: Authorities MUST include this field in all newly generated
|
||||||
|
certificates. A future version of this specification will make
|
||||||
|
the field required.
|
||||||
|
|
||||||
|
CrossSignature is a signature, made using the certificate's signing
|
||||||
|
key, of the digest of the PKCS1-padded hash of the certificate's
|
||||||
|
identity key. For backward compatibility with broken versions of the
|
||||||
|
parser, we wrap the base64-encoded signature in -----BEGIN ID
|
||||||
|
SIGNATURE---- and -----END ID SIGNATURE----- tags. Implementations
|
||||||
|
MUST allow the "ID " portion to be omitted, however.
|
||||||
|
|
||||||
|
When encountering a certificate with a dir-key-crosscert entry,
|
||||||
|
implementations MUST verify that the signature is a correct signature
|
||||||
|
of the hash of the identity key using the signing key.
|
||||||
|
|
||||||
"dir-key-certification" NL Signature NL
|
"dir-key-certification" NL Signature NL
|
||||||
|
|
||||||
[At end, exactly once.]
|
[At end, exactly once.]
|
||||||
|
@ -13,6 +13,11 @@ History:
|
|||||||
Changed name of cross certification field to match the other authority
|
Changed name of cross certification field to match the other authority
|
||||||
certificate fields.
|
certificate fields.
|
||||||
|
|
||||||
|
Status:
|
||||||
|
|
||||||
|
Cross-certification is implemented for new certificates, but not yet
|
||||||
|
required.
|
||||||
|
|
||||||
Overview:
|
Overview:
|
||||||
|
|
||||||
Tor's directory specification gives two ways to download a certificate:
|
Tor's directory specification gives two ways to download a certificate:
|
||||||
|
@ -1729,6 +1729,7 @@ typedef struct authority_cert_t {
|
|||||||
time_t expires;
|
time_t expires;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
uint16_t dir_port;
|
uint16_t dir_port;
|
||||||
|
uint8_t is_cross_certified;
|
||||||
} authority_cert_t;
|
} authority_cert_t;
|
||||||
|
|
||||||
/** Bitfield enum type listing types of directory authority/directory
|
/** Bitfield enum type listing types of directory authority/directory
|
||||||
|
@ -70,6 +70,7 @@ typedef enum {
|
|||||||
K_DIR_KEY_PUBLISHED,
|
K_DIR_KEY_PUBLISHED,
|
||||||
K_DIR_KEY_EXPIRES,
|
K_DIR_KEY_EXPIRES,
|
||||||
K_DIR_KEY_CERTIFICATION,
|
K_DIR_KEY_CERTIFICATION,
|
||||||
|
K_DIR_KEY_CROSSCERT,
|
||||||
K_DIR_ADDRESS,
|
K_DIR_ADDRESS,
|
||||||
|
|
||||||
K_VOTE_STATUS,
|
K_VOTE_STATUS,
|
||||||
@ -328,6 +329,7 @@ static token_rule_t dir_token_table[] = {
|
|||||||
T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
|
T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
|
||||||
T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
|
T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
|
||||||
T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
|
T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
|
||||||
|
T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
|
||||||
T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
|
T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
|
||||||
NO_ARGS, NEED_OBJ), \
|
NO_ARGS, NEED_OBJ), \
|
||||||
T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
|
T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
|
||||||
@ -468,10 +470,12 @@ static directory_token_t *get_next_token(memarea_t *area,
|
|||||||
const char **s,
|
const char **s,
|
||||||
const char *eos,
|
const char *eos,
|
||||||
token_rule_t *table);
|
token_rule_t *table);
|
||||||
|
#define CST_CHECK_AUTHORITY (1<<0)
|
||||||
|
#define CST_NO_CHECK_OBJTYPE (1<<1)
|
||||||
static int check_signature_token(const char *digest,
|
static int check_signature_token(const char *digest,
|
||||||
directory_token_t *tok,
|
directory_token_t *tok,
|
||||||
crypto_pk_env_t *pkey,
|
crypto_pk_env_t *pkey,
|
||||||
int check_authority,
|
int flags,
|
||||||
const char *doctype);
|
const char *doctype);
|
||||||
static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
|
static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
|
||||||
static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
|
static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
|
||||||
@ -714,7 +718,8 @@ router_parse_directory(const char *str)
|
|||||||
}
|
}
|
||||||
declared_key = find_dir_signing_key(str, str+strlen(str));
|
declared_key = find_dir_signing_key(str, str+strlen(str));
|
||||||
note_crypto_pk_op(VERIFY_DIR);
|
note_crypto_pk_op(VERIFY_DIR);
|
||||||
if (check_signature_token(digest, tok, declared_key, 1, "directory")<0)
|
if (check_signature_token(digest, tok, declared_key,
|
||||||
|
CST_CHECK_AUTHORITY, "directory")<0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
|
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
|
||||||
@ -805,7 +810,8 @@ router_parse_runningrouters(const char *str)
|
|||||||
}
|
}
|
||||||
declared_key = find_dir_signing_key(str, eos);
|
declared_key = find_dir_signing_key(str, eos);
|
||||||
note_crypto_pk_op(VERIFY_DIR);
|
note_crypto_pk_op(VERIFY_DIR);
|
||||||
if (check_signature_token(digest, tok, declared_key, 1, "running-routers")
|
if (check_signature_token(digest, tok, declared_key,
|
||||||
|
CST_CHECK_AUTHORITY, "running-routers")
|
||||||
< 0)
|
< 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -896,18 +902,22 @@ dir_signing_key_is_trusted(crypto_pk_env_t *key)
|
|||||||
|
|
||||||
/** Check whether the object body of the token in <b>tok</b> has a good
|
/** Check whether the object body of the token in <b>tok</b> has a good
|
||||||
* signature for <b>digest</b> using key <b>pkey</b>. If
|
* signature for <b>digest</b> using key <b>pkey</b>. If
|
||||||
* <b>check_authority</b> is set, make sure that <b>pkey</b> is the key of a
|
* <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
|
||||||
* directory authority. Use <b>doctype</b> as the type of the document when
|
* a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
|
||||||
* generating log messages. Return 0 on success, negative on failure.
|
* the object type of the signature object. Use <b>doctype</b> as the type of
|
||||||
|
* the document when generating log messages. Return 0 on success, negative
|
||||||
|
* on failure.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
check_signature_token(const char *digest,
|
check_signature_token(const char *digest,
|
||||||
directory_token_t *tok,
|
directory_token_t *tok,
|
||||||
crypto_pk_env_t *pkey,
|
crypto_pk_env_t *pkey,
|
||||||
int check_authority,
|
int flags,
|
||||||
const char *doctype)
|
const char *doctype)
|
||||||
{
|
{
|
||||||
char *signed_digest;
|
char *signed_digest;
|
||||||
|
const int check_authority = (flags & CST_CHECK_AUTHORITY);
|
||||||
|
const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
|
||||||
|
|
||||||
tor_assert(pkey);
|
tor_assert(pkey);
|
||||||
tor_assert(tok);
|
tor_assert(tok);
|
||||||
@ -920,9 +930,11 @@ check_signature_token(const char *digest,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(tok->object_type, "SIGNATURE")) {
|
if (check_objtype) {
|
||||||
log_warn(LD_DIR, "Bad object type on %s signature", doctype);
|
if (strcmp(tok->object_type, "SIGNATURE")) {
|
||||||
return -1;
|
log_warn(LD_DIR, "Bad object type on %s signature", doctype);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_digest = tor_malloc(tok->object_size);
|
signed_digest = tor_malloc(tok->object_size);
|
||||||
@ -1664,6 +1676,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
|
|||||||
log_debug(LD_DIR, "We already checked the signature on this "
|
log_debug(LD_DIR, "We already checked the signature on this "
|
||||||
"certificate; no need to do so again.");
|
"certificate; no need to do so again.");
|
||||||
found = 1;
|
found = 1;
|
||||||
|
cert->is_cross_certified = old_cert->is_cross_certified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
@ -1671,6 +1684,19 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
|
|||||||
"key certificate")) {
|
"key certificate")) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((tok = find_opt_by_keyword(tokens, K_DIR_KEY_CROSSCERT))) {
|
||||||
|
/* XXXX Once all authorities generate cross-certified certificates,
|
||||||
|
* make this field mandatory. */
|
||||||
|
if (check_signature_token(cert->cache_info.identity_digest,
|
||||||
|
tok,
|
||||||
|
cert->signing_key,
|
||||||
|
CST_NO_CHECK_OBJTYPE,
|
||||||
|
"key cross-certification")) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
cert->is_cross_certified = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cert->cache_info.signed_descriptor_len = len;
|
cert->cache_info.signed_descriptor_len = len;
|
||||||
|
@ -3084,6 +3084,7 @@ test_v3_networkstatus(void)
|
|||||||
/* Parse certificates and keys. */
|
/* Parse certificates and keys. */
|
||||||
cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
|
cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
|
||||||
test_assert(cert1);
|
test_assert(cert1);
|
||||||
|
test_assert(cert1->is_cross_certified);
|
||||||
cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
|
cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
|
||||||
test_assert(cert2);
|
test_assert(cert2);
|
||||||
cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
|
cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
|
||||||
@ -3360,15 +3361,15 @@ test_v3_networkstatus(void)
|
|||||||
test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/
|
test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/
|
||||||
/* The voter id digests should be in this order. */
|
/* The voter id digests should be in this order. */
|
||||||
test_assert(memcmp(cert2->cache_info.identity_digest,
|
test_assert(memcmp(cert2->cache_info.identity_digest,
|
||||||
cert3->cache_info.identity_digest,DIGEST_LEN)<0);
|
|
||||||
test_assert(memcmp(cert3->cache_info.identity_digest,
|
|
||||||
cert1->cache_info.identity_digest,DIGEST_LEN)<0);
|
cert1->cache_info.identity_digest,DIGEST_LEN)<0);
|
||||||
|
test_assert(memcmp(cert1->cache_info.identity_digest,
|
||||||
|
cert3->cache_info.identity_digest,DIGEST_LEN)<0);
|
||||||
test_same_voter(smartlist_get(con->voters, 1),
|
test_same_voter(smartlist_get(con->voters, 1),
|
||||||
smartlist_get(v2->voters, 0));
|
smartlist_get(v2->voters, 0));
|
||||||
test_same_voter(smartlist_get(con->voters, 2),
|
test_same_voter(smartlist_get(con->voters, 2),
|
||||||
smartlist_get(v3->voters, 0));
|
|
||||||
test_same_voter(smartlist_get(con->voters, 3),
|
|
||||||
smartlist_get(v1->voters, 0));
|
smartlist_get(v1->voters, 0));
|
||||||
|
test_same_voter(smartlist_get(con->voters, 3),
|
||||||
|
smartlist_get(v3->voters, 0));
|
||||||
|
|
||||||
test_assert(!con->cert);
|
test_assert(!con->cert);
|
||||||
test_eq(2, smartlist_len(con->routerstatus_list));
|
test_eq(2, smartlist_len(con->routerstatus_list));
|
||||||
@ -3412,20 +3413,22 @@ test_v3_networkstatus(void)
|
|||||||
test_assert(rs->is_valid);
|
test_assert(rs->is_valid);
|
||||||
test_assert(!rs->is_named);
|
test_assert(!rs->is_named);
|
||||||
/* XXXX check version */
|
/* XXXX check version */
|
||||||
|
// x231
|
||||||
|
// x213
|
||||||
|
|
||||||
/* Check signatures. the first voter is pseudo. The second one hasn't
|
/* Check signatures. the first voter is a pseudo-entry with a legacy key.
|
||||||
signed. The third one has signed: validate it. */
|
* The second one hasn't signed. The fourth one has signed: validate it. */
|
||||||
voter = smartlist_get(con->voters, 1);
|
voter = smartlist_get(con->voters, 1);
|
||||||
test_assert(!voter->signature);
|
test_assert(!voter->signature);
|
||||||
test_assert(!voter->good_signature);
|
test_assert(!voter->good_signature);
|
||||||
test_assert(!voter->bad_signature);
|
test_assert(!voter->bad_signature);
|
||||||
|
|
||||||
voter = smartlist_get(con->voters, 2);
|
voter = smartlist_get(con->voters, 3);
|
||||||
test_assert(voter->signature);
|
test_assert(voter->signature);
|
||||||
test_assert(!voter->good_signature);
|
test_assert(!voter->good_signature);
|
||||||
test_assert(!voter->bad_signature);
|
test_assert(!voter->bad_signature);
|
||||||
test_assert(!networkstatus_check_voter_signature(con,
|
test_assert(!networkstatus_check_voter_signature(con,
|
||||||
smartlist_get(con->voters, 2),
|
smartlist_get(con->voters, 3),
|
||||||
cert3));
|
cert3));
|
||||||
test_assert(voter->signature);
|
test_assert(voter->signature);
|
||||||
test_assert(voter->good_signature);
|
test_assert(voter->good_signature);
|
||||||
@ -3503,7 +3506,7 @@ test_v3_networkstatus(void)
|
|||||||
smartlist_get(con->voters, 1),
|
smartlist_get(con->voters, 1),
|
||||||
cert2));
|
cert2));
|
||||||
test_assert(!networkstatus_check_voter_signature(con,
|
test_assert(!networkstatus_check_voter_signature(con,
|
||||||
smartlist_get(con->voters, 3),
|
smartlist_get(con->voters, 2),
|
||||||
cert1));
|
cert1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,54 +8,60 @@ const char test_data_c_id[] =
|
|||||||
|
|
||||||
const char AUTHORITY_CERT_1[] =
|
const char AUTHORITY_CERT_1[] =
|
||||||
"dir-key-certificate-version 3\n"
|
"dir-key-certificate-version 3\n"
|
||||||
"fingerprint F810C0CB4974A9C407A8D8F5B0394E3D87BF4794\n"
|
"fingerprint D867ACF56A9D229B35C25F0090BC9867E906BE69\n"
|
||||||
"dir-key-published 2007-06-13 16:52:25\n"
|
"dir-key-published 2008-12-12 18:07:24\n"
|
||||||
"dir-key-expires 2008-06-13 16:52:25\n"
|
"dir-key-expires 2009-12-12 18:07:24\n"
|
||||||
"dir-identity-key\n"
|
"dir-identity-key\n"
|
||||||
"-----BEGIN RSA PUBLIC KEY-----\n"
|
"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||||
"MIIBigKCAYEAwqvEOhA+aSNp0JQFd0bZ2OIdamIS6EGVuhOHFkmIS4P2hw99Nkx/\n"
|
"MIIBigKCAYEAveMpKlw8oD1YqFqpJchuwSR82BDhutbqgHiez3QO9FmzOctJpV+Y\n"
|
||||||
"YJGXPbHB5uLxMYE539DHKuGztIHOanIqczG8P501F+sGfi1q00rzjYfliGuGnQRQ\n"
|
"mpTYIJLS/qC+4GBKFF1VK0C4SoBrS3zri0qdXdE+vBGcyrxrjMklpxoqSKRY2011\n"
|
||||||
"5+A7Iu6am+KeEP/cnWZt63kiPV2Jt9D8qwlnZTKqMQvnhOz10QCApV0LgFHr/2VO\n"
|
"4eqYPghKlo5RzuqteBclGCHyNxWjUJeRKDWgvh+U/gr2uYM6fRm5q0fCzg4aECE7\n"
|
||||||
"1jEO/Ve+EMO/+fZf8a6graw4ur1foVjLAwUW1fo0QUo0342WSlTA1VouyhZv1LsH\n"
|
"VP6fDGZrMbQI8jHpiMSoC9gkUASNEa6chLInlnP8/H5qUEW4TB9CN/q095pefuwL\n"
|
||||||
"LTmA0VFTQnsNnG9V1sPAuqaPDeNntSS3bAWmCAUA6eQS4LF7Pz4OAsRtAurMf98z\n"
|
"P+F+1Nz5hnM7fa5XmeMB8iM4RriUmOQlLBZgpQBMpEfWMIPcR9F1Gh3MxERqqUcH\n"
|
||||||
"Pz/thkNa9OBJfLH1zaAmaiUTdEqMNwoT1YHwqav4994tyO7oadV6PdVIAcXD2I4S\n"
|
"tmij+IZdeXg9OkCXykcabaYIhZD3meErn9Tax4oA/THduLfgli9zM0ExwzH1OooN\n"
|
||||||
"9tf0NPfaIHwfJPDUY9loKIrGNbrfBLTECrQ3QLNtU3yrYkEyQjcgT8FlBGDcDGqj\n"
|
"L8rIcJ+2eBo3bQiQUbdYW71sl9w7nSPtircbJUa1mUvWYLPWQxFliPiQSetgJLMj\n"
|
||||||
"r8diBPlz+K5iXfl0lIudie4hAFZK+uDu7yQ4y7+N5fVuoBdQDt8S0eMho/PO3Hoe\n"
|
"VQqtPmV2hvN2Xk3lLfJO50qMTK7w7Gsaw8UtV4YDM1Hcjp/hQaIB1xfwhXgl+eUU\n"
|
||||||
"638jhngjy5L5AgMBAAE=\n"
|
"btUa4c+cUTjHAgMBAAE=\n"
|
||||||
"-----END RSA PUBLIC KEY-----\n"
|
"-----END RSA PUBLIC KEY-----\n"
|
||||||
"dir-signing-key\n"
|
"dir-signing-key\n"
|
||||||
"-----BEGIN RSA PUBLIC KEY-----\n"
|
"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||||
"MIGJAoGBALQJryeKty8evkxsG1xrj3hezAt3qbTSfigptATGdd2CH+VvMKVdY7EM\n"
|
"MIGJAoGBALPSUInyuEu6NV3NjozplaniIEBzQXEjv1x9/+mqnwZABpYVmuy9A8nx\n"
|
||||||
"UiiFNuYp3iZTptIKiiUtbmEGUgPsOaL6Ab9aoY80oXWxZ/shBFoIaAjOmn1qNQiA\n"
|
"eoyY3sZFsnYwNW/IZjAgG23pEmevu3F+L4myMjjaa6ORl3MgRYQ4gmuFqpefrGdm\n"
|
||||||
"jPNH7YVbJGjZiuJydT+ZuZabqh58ij8mMgdJnflFO7wG39q3QBrdAgMBAAE=\n"
|
"ywRCleh2JerkQ4VxOuq10dn/abITzLyaZzMw30KXWp5pxKXOLtxFAgMBAAE=\n"
|
||||||
"-----END RSA PUBLIC KEY-----\n"
|
"-----END RSA PUBLIC KEY-----\n"
|
||||||
|
"dir-key-crosscert\n"
|
||||||
|
"-----BEGIN ID SIGNATURE-----\n"
|
||||||
|
"FTBJNR/Hlt4T53yUMp1r/QCSMCpkHJCbYBT0R0pvYqhqFfYN5qHRSICRXaFFImIF\n"
|
||||||
|
"0DGWmwRza6DxPKNzkm5/b7I0de9zJW1jNNdQAQK5xppAtQcAafRdu8cBonnmh9KX\n"
|
||||||
|
"k1NrAK/X00FYywju3yl/SxCn1GddVNkHYexEudmJMPM=\n"
|
||||||
|
"-----END ID SIGNATURE-----\n"
|
||||||
"dir-key-certification\n"
|
"dir-key-certification\n"
|
||||||
"-----BEGIN SIGNATURE-----\n"
|
"-----BEGIN SIGNATURE-----\n"
|
||||||
"Hp6PuryATzAOM0PsmhlxsxTqoxKcI8lv6ti2/4Gnyug4lTx1rPweoZdt4GGttFAe\n"
|
"pjWguLFBfELZDc6DywL6Do21SCl7LcutfpM92MEn4WYeSNcTXNR6lRX7reOEJk4e\n"
|
||||||
"Td9zcUfLUlC0R5eDIlWpR+rxJsRLxuHcVTSr+P0N/Y5xoFzPAqPsVYz6lnvb7vIG\n"
|
"NwEaMt+Hl7slgeR5wjnW3OmMmRPZK9bquNWbfD+sAOV9bRFZTpXIdleAQFPlwvMF\n"
|
||||||
"9XtixG9jXvVhEqpCZUwoRyPXXwjJoEZE1EuyuvPmlEny8O5thAx1gvZIwUk9hGLU\n"
|
"z/Gzwspzn4i2Yh6hySShrctMmW8YL3OM8LsBXzBhp/rG2uHlsxmIsc13DA6HWt61\n"
|
||||||
"xcErXkajDgfWEGmFWgcs+uk/Sa6n+vjPBwJD9k2hGcoCVZhelU0duCORJaz33twU\n"
|
"ffY72uNE6KckDGsQ4wPGP9q69y6g+X+TNio1KPbsILbePv6EjbO+rS8FiS4njPlg\n"
|
||||||
"tebJ/iPMAEkMBIlMvnnr+lKXk548rwE6GHUXWtu/Tho4piV58A0hKAHKpGbVUYEF\n"
|
"SPYry1RaUvxzxTkswIzdE1tjJrUiqpbWlTGxrH9N4OszoLm45Pc784KLULrjKIoi\n"
|
||||||
"+11x7n5klsYkUedltrCMajtjB8oawWmRPZZp+sUBmnEtunlCGaBnJNQ3pnCvAalJ\n"
|
"Q+vRsGrcMBAa+kDowWU6H1ryKR7KOhzRTcf2uqLE/W3ezaRwmOG+ETmoVFwbhk2X\n"
|
||||||
"yPCSGeQhrW8ZKGWE4aZ8xzyUc5K0zF0KEefPFyHpK61ZDaXr/6TQPz3UF4ndxVjS\n"
|
"OlbXEM9fWP+INvFkr6Z93VYL2jGkCjV7e3xXmre/Lb92fUcYi6t5dwzfV8gJnIoG\n"
|
||||||
"sxRWj3HyMv6Ax5bASOLgP2ikdXGnZLHau93yKJ6N8U57JjCTavxMlRXONbLS0qYe\n"
|
"eCHd0K8NrQK0ipVk/7zcPDKOPeo9Y5aj/f6X/pDHtb+Dd5sT+l82G/Tqy4DIYUYR\n"
|
||||||
"-----END SIGNATURE-----\n";
|
"-----END SIGNATURE-----\n";
|
||||||
|
|
||||||
const char AUTHORITY_SIGNKEY_1[] =
|
const char AUTHORITY_SIGNKEY_1[] =
|
||||||
"-----BEGIN RSA PRIVATE KEY-----\n"
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
"MIICXAIBAAKBgQC0Ca8nircvHr5MbBtca494XswLd6m00n4oKbQExnXdgh/lbzCl\n"
|
"MIICWwIBAAKBgQCz0lCJ8rhLujVdzY6M6ZWp4iBAc0FxI79cff/pqp8GQAaWFZrs\n"
|
||||||
"XWOxDFIohTbmKd4mU6bSCoolLW5hBlID7Dmi+gG/WqGPNKF1sWf7IQRaCGgIzpp9\n"
|
"vQPJ8XqMmN7GRbJ2MDVvyGYwIBtt6RJnr7txfi+JsjI42mujkZdzIEWEOIJrhaqX\n"
|
||||||
"ajUIgIzzR+2FWyRo2YricnU/mbmWm6oefIo/JjIHSZ35RTu8Bt/at0Aa3QIDAQAB\n"
|
"n6xnZssEQpXodiXq5EOFcTrqtdHZ/2myE8y8mmczMN9Cl1qeacSlzi7cRQIDAQAB\n"
|
||||||
"AoGAKujz+jSxnGVzbbuGeeyY8VOGxmTq6dIRh3kJEupKRVUyTPjHW2J61EPfgRDf\n"
|
"AoGASpzUkDinIbzU0eQt5ugxEnliOnvYRpK3nzAk1JbYPyan1PSIAPz4qn1JBTeV\n"
|
||||||
"GNR5wiDF7eHdMyc026MqAQ1YXv007K9D22cABhe8BivCbibhzUrmcv76vQHIRgp/\n"
|
"EB3xS7r7ITO8uvFHkFZqLZ2sH1uE6e4sAytJGO+kyqnlkiDTPEXpcGe99j8PH1yj\n"
|
||||||
"AbT9fRjhmB/NqjLf6NkBHzx2UAWKbmxcO4pAGSQIY+TnXXECQQDkqTPxUrg2y8kC\n"
|
"xUOrHRlAYWjG8NEkQi+APA+HZkswE3L/viFwR2AARoE2ac0CQQDsOLdNJa+mqn6N\n"
|
||||||
"nvEa2O1yYSCU0cB1EmPaIg0cH5vV/lA/EFbhLIBbA+CUsbX0qxuEBX6B9c36y3AO\n"
|
"1L76nEl/YgXHtKUks+beOR3IgknKEjcsJJEUHyiu0wjbXZV6gTtyQvcAePglUUD1\n"
|
||||||
"UOAi7NXnAkEAyZA8rKBIjhHFur9e/U9ApDAjvW1BSy7nDP5GKqw2ayLIt1hfnxZd\n"
|
"R2OkOOADAkEAwuCxvHEAPeQbVt8fSvxw74vqew6LITP2Utb1dQK0E26IRPF36BsJ\n"
|
||||||
"0YXb53iAsf/YHT/wk4+nBYtQ83xL2U2omwJAfgRaIgcqithoYU9jJR6kTcMFh77J\n"
|
"buO/gqMZv6ALq+/KxpA/pUsApbgog9uUFwJAYvHCvbrKX1pM1iXFtP1fv86UMzlU\n"
|
||||||
"SDvoV9EoVHV/FsJfS0If/1zdKEvMu2XtF3gtY+b7P3hOGod/rAQaYmUPxQJBALz4\n"
|
"bxI34t8zvXftZonIuGG8rxv6E3hr3k7NvNmCx/KKuZTyA9eMCPFVKEV2dwJACn8j\n"
|
||||||
"2JmzsDJaITpDXwg4PE9yvp9DBjs5nu9EmX46dM6fDvUuCoA5VP4x9IigJnA7gF9z\n"
|
"06yagLrqphE6lEVop953cM1lvRIZcHjXm8fbfzhy6pO/C6d5KJnn1NeIKYQrXMV7\n"
|
||||||
"6dY+kQWWpu+QcgAqWc8CQDYRUK/qhdbBLdv30CyGrU6Pu0Iij6KZXLGW/zavSDmw\n"
|
"vJpEc1jI3iQ/Omr3XQJAEBIt5MlP2wlrX9om7B+32XBygUssY3cw/bXybZrtSU0/\n"
|
||||||
"4FgbRYYTjukvSs3zUX+52znjYn7wTngIm312A37pHUU=\n"
|
"Yx4lqK0ca5IkTp3HevwnlWaJgbaOTUspCVshzJBhDA==\n"
|
||||||
"-----END RSA PRIVATE KEY-----\n";
|
"-----END RSA PRIVATE KEY-----\n";
|
||||||
|
|
||||||
const char AUTHORITY_CERT_2[] =
|
const char AUTHORITY_CERT_2[] =
|
||||||
|
@ -394,6 +394,20 @@ get_fingerprint(EVP_PKEY *pkey, char *out)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Set <b>out</b> to the hex-encoded fingerprint of <b>pkey</b>. */
|
||||||
|
static int
|
||||||
|
get_digest(EVP_PKEY *pkey, char *out)
|
||||||
|
{
|
||||||
|
int r = 1;
|
||||||
|
crypto_pk_env_t *pk = _crypto_new_pk_env_rsa(EVP_PKEY_get1_RSA(pkey));
|
||||||
|
if (pk) {
|
||||||
|
r = crypto_pk_get_digest(pk, out);
|
||||||
|
crypto_free_pk_env(pk);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/** Generate a new certificate for our loaded or generated keys, and write it
|
/** Generate a new certificate for our loaded or generated keys, and write it
|
||||||
* to disk. Return 0 on success, nonzero on failure. */
|
* to disk. Return 0 on success, nonzero on failure. */
|
||||||
static int
|
static int
|
||||||
@ -404,6 +418,7 @@ generate_certificate(void)
|
|||||||
struct tm tm;
|
struct tm tm;
|
||||||
char published[ISO_TIME_LEN+1];
|
char published[ISO_TIME_LEN+1];
|
||||||
char expires[ISO_TIME_LEN+1];
|
char expires[ISO_TIME_LEN+1];
|
||||||
|
char id_digest[DIGEST_LEN];
|
||||||
char fingerprint[FINGERPRINT_LEN+1];
|
char fingerprint[FINGERPRINT_LEN+1];
|
||||||
char *ident = key_to_string(identity_key);
|
char *ident = key_to_string(identity_key);
|
||||||
char *signing = key_to_string(signing_key);
|
char *signing = key_to_string(signing_key);
|
||||||
@ -414,6 +429,7 @@ generate_certificate(void)
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
get_fingerprint(identity_key, fingerprint);
|
get_fingerprint(identity_key, fingerprint);
|
||||||
|
get_digest(identity_key, id_digest);
|
||||||
|
|
||||||
tor_localtime_r(&now, &tm);
|
tor_localtime_r(&now, &tm);
|
||||||
tm.tm_mon += months_lifetime;
|
tm.tm_mon += months_lifetime;
|
||||||
@ -429,11 +445,26 @@ generate_certificate(void)
|
|||||||
"dir-key-expires %s\n"
|
"dir-key-expires %s\n"
|
||||||
"dir-identity-key\n%s"
|
"dir-identity-key\n%s"
|
||||||
"dir-signing-key\n%s"
|
"dir-signing-key\n%s"
|
||||||
"dir-key-certification\n",
|
"dir-key-crosscert\n"
|
||||||
|
"-----BEGIN ID SIGNATURE-----\n",
|
||||||
address?"\ndir-address ":"", address?address:"",
|
address?"\ndir-address ":"", address?address:"",
|
||||||
fingerprint, published, expires, ident, signing);
|
fingerprint, published, expires, ident, signing
|
||||||
|
);
|
||||||
tor_free(ident);
|
tor_free(ident);
|
||||||
tor_free(signing);
|
tor_free(signing);
|
||||||
|
|
||||||
|
/* Append a cross-certification */
|
||||||
|
r = RSA_private_encrypt(DIGEST_LEN, (unsigned char*)id_digest,
|
||||||
|
(unsigned char*)signature,
|
||||||
|
EVP_PKEY_get1_RSA(signing_key),
|
||||||
|
RSA_PKCS1_PADDING);
|
||||||
|
signed_len = strlen(buf);
|
||||||
|
base64_encode(buf+signed_len, sizeof(buf)-signed_len, signature, r);
|
||||||
|
|
||||||
|
strlcat(buf,
|
||||||
|
"-----END ID SIGNATURE-----\n"
|
||||||
|
"dir-key-certification\n", sizeof(buf));
|
||||||
|
|
||||||
signed_len = strlen(buf);
|
signed_len = strlen(buf);
|
||||||
SHA1((const unsigned char*)buf,signed_len,(unsigned char*)digest);
|
SHA1((const unsigned char*)buf,signed_len,(unsigned char*)digest);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user