[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r10293: More v3 directory code: have authorities load certificates; (in tor/trunk: . doc src/common src/or)
- To: or-cvs@xxxxxxxxxxxxx
- Subject: [or-cvs] r10293: More v3 directory code: have authorities load certificates; (in tor/trunk: . doc src/common src/or)
- From: nickm@xxxxxxxx
- Date: Tue, 22 May 2007 13:58:28 -0400 (EDT)
- Delivered-to: archiver@seul.org
- Delivered-to: or-cvs-outgoing@seul.org
- Delivered-to: or-cvs@seul.org
- Delivery-date: Tue, 22 May 2007 13:58:38 -0400
- Reply-to: or-dev@xxxxxxxxxxxxx
- Sender: owner-or-cvs@xxxxxxxxxxxxx
Author: nickm
Date: 2007-05-22 13:58:25 -0400 (Tue, 22 May 2007)
New Revision: 10293
Modified:
tor/trunk/
tor/trunk/doc/TODO
tor/trunk/src/common/util.c
tor/trunk/src/or/config.c
tor/trunk/src/or/or.h
tor/trunk/src/or/router.c
tor/trunk/src/or/routerlist.c
tor/trunk/src/or/routerparse.c
Log:
r12898@catbus: nickm | 2007-05-22 13:11:04 -0400
More v3 directory code: have authorities load certificates; have everybody store certificates to disk and load them; provide a way to configure v3 authorities.
Property changes on: tor/trunk
___________________________________________________________________
svk:merge ticket from /tor/trunk [r12898] on 8246c3cf-6607-4228-993b-4d95d33730f1
Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO 2007-05-22 15:49:14 UTC (rev 10292)
+++ tor/trunk/doc/TODO 2007-05-22 17:58:25 UTC (rev 10293)
@@ -56,7 +56,7 @@
Things we'd like to do in 0.2.0.x:
- Proposals:
- . 101: Voting on the Tor Directory System
+ . 101: Voting on the Tor Directory System (plus 103)
o Prepare ASAP for new voting formats
o Don't flip out with warnings when voting-related URLs are
uploaded/downloaded.
@@ -68,16 +68,21 @@
o Parse key certificates
- Parse votes and consensuses
- Unit tests for above
- - Code to manage key certificates
- - Cache on disk
- - Download as needed
+ . Code to manage key certificates
+ o Generate certificates
+ o Authorities load certificates
+ o Clients cache certificates on disk
+ - Download as needed.
- Serve list as needed.
- - Avoid double-checking signatures every time we get a vote.
+ o Avoid double-checking signatures every time we get a vote.
+ - Warn about expired stuff.
- Code to generate votes
- Code to generate consensus from a list of votes
- Add a signature to a consensus.
- Code to check signatures on a consensus
- Push/pull documents as appropriate.
+ o Have clients know which authorities are v3 authorities, and what
+ their keys are.
- Start caching consensus documents once authorities make them
- Start downloading and using consensus documents once caches serve them
. 104: Long and Short Router Descriptors (by Jun 1)
@@ -98,8 +103,8 @@
- 105: Version negotiation for the Tor protocol (finalize by Jun 1)
- 108: Base "Stable" Flag on Mean Time Between Failures
- 109: No more than one server per IP address
- - 103: Splitting identity key from regularly used signing key
- - Merge with 101 into a new dir-spec.txt
+ o 103: Splitting identity key from regularly used signing key
+ o Merge with 101 into a new dir-spec.txt
- 113: Simplifying directory authority administration
- 110: prevent infinite-length circuits (phase one)
- servers should recognize relay_extend cells and pass them
Modified: tor/trunk/src/common/util.c
===================================================================
--- tor/trunk/src/common/util.c 2007-05-22 15:49:14 UTC (rev 10292)
+++ tor/trunk/src/common/util.c 2007-05-22 17:58:25 UTC (rev 10293)
@@ -1381,8 +1381,8 @@
/** Read the contents of <b>filename</b> into a newly allocated
* string; return the string on success or NULL on failure.
*
- * If <b>size_out</b> is provided, store the length of the result in
- * <b>size_out</b>.
+ * If <b>stat_out</b> is provided, store the result of stat()ing the
+ * file into <b>stat_out</b>.
*
* If <b>flags</b> & RFTS_BIN, open the file in binary mode.
* If <b>flags</b> & RFTS_IGNORE_MISSING, don't warn if the file
Modified: tor/trunk/src/or/config.c
===================================================================
--- tor/trunk/src/or/config.c 2007-05-22 15:49:14 UTC (rev 10292)
+++ tor/trunk/src/or/config.c 2007-05-22 17:58:25 UTC (rev 10293)
@@ -261,6 +261,7 @@
VAR("User", STRING, User, NULL),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
+ VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
VAR("VirtualAddrNetwork", STRING, VirtualAddrNetwork, "127.192.0.0/10"),
VAR("__AllDirActionsPrivate",BOOL, AllDirActionsPrivate, "0"),
@@ -1047,6 +1048,7 @@
if (dns_reset())
return -1;
}
+ /* XXXX020 init_keys() again if v3authoritativedir is newly set. */
}
/* Check if we need to parse and add the EntryNodes config option. */
@@ -2346,6 +2348,8 @@
*auth |= V1_AUTHORITY | V2_AUTHORITY;
else if (!strcasecmp(string, "v2"))
*auth |= V2_AUTHORITY;
+ else if (!strcasecmp(string, "v3"))
+ *auth |= V3_AUTHORITY;
else if (!strcasecmp(string, "bridge"))
*auth |= BRIDGE_AUTHORITY;
else if (!strcasecmp(string, "hidserv"))
@@ -2580,6 +2584,8 @@
"extra-info documents. Setting DownloadExtraInfo.");
options->DownloadExtraInfo = 1;
}
+ /* XXXX020 Check that at least one of Bridge/HS/V1/V2/V2{AoritativeDir}
+ * is set. */
}
if (options->AuthoritativeDir && !options->DirPort)
@@ -3588,6 +3594,7 @@
char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
uint16_t dir_port = 0, or_port = 0;
char digest[DIGEST_LEN];
+ char v3_digest[DIGEST_LEN];
authority_type_t type = V2_AUTHORITY;
int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
@@ -3625,6 +3632,15 @@
if (!ok)
log_warn(LD_CONFIG, "Invalid orport '%s' on DirServer line.",
portstring);
+ } else if (!strcasecmpstart(flag, "v3ident=")) {
+ char *idstr = flag + strlen("v3ident=");
+ if (strlen(idstr) != HEX_DIGEST_LEN ||
+ base16_decode(v3_digest, DIGEST_LEN, idstr, HEX_DIGEST_LEN)<0) {
+ log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
+ flag);
+ } else {
+ type |= V3_AUTHORITY;
+ }
} else {
log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
flag);
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2007-05-22 15:49:14 UTC (rev 10292)
+++ tor/trunk/src/or/or.h 2007-05-22 17:58:25 UTC (rev 10293)
@@ -1334,9 +1334,10 @@
NO_AUTHORITY = 0,
V1_AUTHORITY = 1 << 0,
V2_AUTHORITY = 1 << 1,
- HIDSERV_AUTHORITY = 1 << 2,
- BRIDGE_AUTHORITY = 1 << 3,
- EXTRAINFO_CACHE = 1 << 4, /* not precisely an authority type. */
+ V3_AUTHORITY = 1 << 2,
+ HIDSERV_AUTHORITY = 1 << 3,
+ BRIDGE_AUTHORITY = 1 << 4,
+ EXTRAINFO_CACHE = 1 << 5, /* not precisely an authority type. */
} authority_type_t;
#define CRYPT_PATH_MAGIC 0x70127012u
@@ -1758,6 +1759,8 @@
* for version 1 directories? */
int V2AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 2 directories? */
+ int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
+ * for version 3 directories? */
int HSAuthoritativeDir; /**< Boolean: does this an authoritative directory
* handle hidden service requests? */
int HSAuthorityRecordStats; /**< Boolean: does this HS authoritative
@@ -3057,6 +3060,9 @@
uint16_t dir_port; /**< Directory port. */
uint16_t or_port; /**< OR port: Used for tunneling connections. */
char digest[DIGEST_LEN]; /**< Digest of identity key. */
+ char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only,
+ * high-security) identity key. */
+
unsigned int is_running:1; /**< True iff we think this server is running. */
/** True iff this server has accepted the most recent server descriptor
@@ -3066,6 +3072,8 @@
/** DOCDOC */
authority_type_t type;
+ authority_cert_t *v3_cert; /**< V3 key certificate for this authority */
+
int n_networkstatus_failures; /**< How many times have we asked for this
* server's network-status unsuccessfully? */
local_routerstatus_t fake_status; /**< Used when we need to pass this trusted
@@ -3088,6 +3096,8 @@
int retry_if_no_servers);
trusted_dir_server_t *router_get_trusteddirserver_by_digest(
const char *digest);
+trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(
+ const char *digest);
void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
int must_be_running);
@@ -3197,6 +3207,10 @@
void routerlist_assert_ok(routerlist_t *rl);
void routerlist_check_bug_417(void);
+int trusted_dirs_reload_certs(void);
+int trusted_dirs_load_certs_from_string(const char *contents, int from_store);
+void trusted_dirs_flush_certs_to_disk(void);
+
/********************************* routerparse.c ************************/
#define MAX_STATUS_TAG_LEN 32
@@ -3278,7 +3292,7 @@
void authority_cert_free(authority_cert_t *cert);
authority_cert_t *authority_cert_parse_from_string(const char *s,
- char **end_of_string);
+ const char **end_of_string);
#endif
Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c 2007-05-22 15:49:14 UTC (rev 10292)
+++ tor/trunk/src/or/router.c 2007-05-22 17:58:25 UTC (rev 10293)
@@ -38,6 +38,11 @@
static crypto_pk_env_t *identitykey=NULL;
/** Digest of identitykey. */
static char identitykey_digest[DIGEST_LEN];
+/** Signing key used for v3 directory material; only set for authorities. */
+static crypto_pk_env_t *authority_signing_key = NULL;
+/** Key certificate to authenticate v3 directory material; only set for
+ * authorities. */
+static authority_cert_t *authority_key_certificate = NULL;
/** Replace the current onion key with <b>k</b>. Does not affect lastonionkey;
* to update onionkey correctly, call rotate_onion_key().
@@ -170,46 +175,48 @@
log_warn(LD_GENERAL, "Couldn't rotate onion key.");
}
-/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist,
- * create a new RSA key and save it in <b>fname</b>. Return the read/created
- * key, or NULL on error.
- */
-crypto_pk_env_t *
-init_key_from_file(const char *fname)
+/** DOCDOC */
+static crypto_pk_env_t *
+init_key_from_file_impl(const char *fname, int generate, int severity)
{
crypto_pk_env_t *prkey = NULL;
FILE *file = NULL;
if (!(prkey = crypto_new_pk_env())) {
- log_err(LD_GENERAL,"Error constructing key");
+ log(severity, LD_GENERAL,"Error constructing key");
goto error;
}
switch (file_status(fname)) {
case FN_DIR:
case FN_ERROR:
- log_err(LD_FS,"Can't read key from \"%s\"", fname);
+ log(severity, LD_FS,"Can't read key from \"%s\"", fname);
goto error;
case FN_NOENT:
- log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
- fname);
- if (crypto_pk_generate_key(prkey)) {
- log_err(LD_GENERAL,"Error generating onion key");
- goto error;
+ if (generate) {
+ log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
+ fname);
+ if (crypto_pk_generate_key(prkey)) {
+ log(severity, LD_GENERAL,"Error generating onion key");
+ goto error;
+ }
+ if (crypto_pk_check_key(prkey) <= 0) {
+ log(severity, LD_GENERAL,"Generated key seems invalid");
+ goto error;
+ }
+ log_info(LD_GENERAL, "Generated key seems valid");
+ if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
+ log(severity, LD_FS,
+ "Couldn't write generated key to \"%s\".", fname);
+ goto error;
+ }
+ } else {
+ log_info(LD_GENERAL, "No key found in \"%s\"", fname);
}
- if (crypto_pk_check_key(prkey) <= 0) {
- log_err(LD_GENERAL,"Generated key seems invalid");
- goto error;
- }
- log_info(LD_GENERAL, "Generated key seems valid");
- if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
- log_err(LD_FS,"Couldn't write generated key to \"%s\".", fname);
- goto error;
- }
return prkey;
case FN_FILE:
if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
- log_err(LD_GENERAL,"Error loading private key.");
+ log(severity, LD_GENERAL,"Error loading private key.");
goto error;
}
return prkey;
@@ -225,6 +232,71 @@
return NULL;
}
+/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist,
+ * create a new RSA key and save it in <b>fname</b>. Return the read/created
+ * key, or NULL on error.
+ */
+crypto_pk_env_t *
+init_key_from_file(const char *fname)
+{
+ return init_key_from_file_impl(fname, 1, LOG_ERR);
+}
+
+/** DOCDOC; XXXX020 maybe move to dirserv.c */
+static void
+init_v3_authority_keys(const char *keydir)
+{
+ char *fname = NULL, *cert = NULL;
+ const char *eos = NULL;
+ size_t fname_len = strlen(keydir) + 64;
+ crypto_pk_env_t *signing_key = NULL;
+ authority_cert_t *parsed = NULL;
+
+ fname = tor_malloc(fname_len);
+ tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_signing_key",
+ keydir);
+ signing_key = init_key_from_file_impl(fname, 0, LOG_INFO);
+ if (!signing_key) {
+ log_warn(LD_DIR, "No version 3 directory key found in %s", fname);
+ goto done;
+ }
+ tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_certificate",
+ keydir);
+ cert = read_file_to_str(fname, 0, NULL);
+ if (!cert) {
+ log_warn(LD_DIR, "Signing key found, but no certificate found in %s",
+ fname);
+ goto done;
+ }
+ parsed = authority_cert_parse_from_string(cert, &eos);
+ if (!parsed) {
+ log_warn(LD_DIR, "Unable to parse certificate in %s", fname);
+ goto done;
+ }
+ if (crypto_pk_cmp_keys(signing_key, parsed->signing_key) != 0) {
+ log_warn(LD_DIR, "Stored signing key does not match signing key in "
+ "certificate");
+ goto done;
+ }
+ parsed->cache_info.signed_descriptor_body = cert;
+ parsed->cache_info.signed_descriptor_len = eos-cert;
+ cert = NULL;
+
+ authority_key_certificate = parsed;
+ authority_signing_key = signing_key;
+ parsed = NULL;
+ signing_key = NULL;
+
+ done:
+ tor_free(fname);
+ tor_free(cert);
+ if (signing_key)
+ crypto_free_pk_env(signing_key);
+ if (parsed)
+ authority_cert_free(parsed);
+}
+
+
/** Initialize all OR private keys, and the TLS context, as necessary.
* On OPs, this only initializes the tls context. Return 0 on success,
* or -1 if Tor should die.
@@ -282,6 +354,11 @@
prkey = init_key_from_file(keydir);
if (!prkey) return -1;
set_identity_key(prkey);
+
+ /* 1b. Read v3 directory authority key/cert information. */
+ if (authdir_mode(options) && options->V3AuthoritativeDir)
+ init_v3_authority_keys(keydir);
+
/* 2. Read onion key. Make it if none is found. */
tor_snprintf(keydir,sizeof(keydir),
"%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_onion_key",datadir);
@@ -1592,6 +1669,10 @@
routerinfo_free(desc_routerinfo);
if (desc_extrainfo)
extrainfo_free(desc_extrainfo);
+ if (authority_signing_key)
+ crypto_free_pk_env(authority_signing_key);
+ if (authority_key_certificate)
+ authority_cert_free(authority_key_certificate);
if (warned_nonexistent_family) {
SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));
Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c 2007-05-22 15:49:14 UTC (rev 10292)
+++ tor/trunk/src/or/routerlist.c 2007-05-22 17:58:25 UTC (rev 10293)
@@ -49,6 +49,8 @@
/** Global list of a trusted_dir_server_t object for each trusted directory
* server. */
static smartlist_t *trusted_dir_servers = NULL;
+/** DOCDOC */
+static int trusted_dir_servers_certs_changed = 0;
/** Global list of all of the routers that we know about. */
static routerlist_t *routerlist = NULL;
@@ -163,6 +165,89 @@
return 0;
}
+/** DOCDOC */
+int
+trusted_dirs_reload_certs(void)
+{
+ char filename[512];
+ char *contents;
+ int r;
+
+ tor_snprintf(filename,sizeof(filename),"%s"PATH_SEPARATOR"cached-certs",
+ get_options()->DataDirectory);
+ contents = read_file_to_str(filename, 0, NULL);
+ if (!contents)
+ return -1;
+ r = trusted_dirs_load_certs_from_string(contents, 1);
+ tor_free(contents);
+ return r;
+}
+
+/** DOCDOC */
+int
+trusted_dirs_load_certs_from_string(const char *contents, int from_store)
+{
+ trusted_dir_server_t *ds;
+ const char *s, *eos;
+
+ for (s = contents; *s; s = eos) {
+ authority_cert_t *cert = authority_cert_parse_from_string(s, &eos);
+ if (!cert)
+ break;
+ ds = trusteddirserver_get_by_v3_auth_digest(
+ cert->cache_info.identity_digest);
+ if (!ds) {
+ log_info(LD_DIR, "Found cached certificate whose key didn't match "
+ "any v3 authority we recognized; skipping.");
+ authority_cert_free(cert);
+ continue;
+ }
+
+ if (ds->v3_cert) {
+ if (ds->v3_cert->expires < cert->expires) {
+ authority_cert_free(ds->v3_cert);
+ } else {
+ authority_cert_free(cert);
+ continue;
+ }
+ }
+
+ cert->cache_info.signed_descriptor_body = tor_strndup(s, eos-s);
+ cert->cache_info.signed_descriptor_len = eos-s;
+ ds->v3_cert = cert;
+ if (!from_store)
+ trusted_dir_servers_certs_changed = 1;
+ }
+ return 0;
+}
+
+/** DOCDOC */
+void
+trusted_dirs_flush_certs_to_disk(void)
+{
+ char filename[512];
+ smartlist_t *chunks = smartlist_create();
+
+ tor_snprintf(filename,sizeof(filename),"%s"PATH_SEPARATOR"cached-certs",
+ get_options()->DataDirectory);
+ SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
+ {
+ if (ds->v3_cert) {
+ sized_chunk_t *c = tor_malloc(sizeof(sized_chunk_t));
+ c->bytes = ds->v3_cert->cache_info.signed_descriptor_body;
+ c->len = ds->v3_cert->cache_info.signed_descriptor_len;
+ smartlist_add(chunks, c);
+ }
+ });
+ if (write_chunks_to_file(filename, chunks, 0)) {
+ log_warn(LD_FS, "Error writing certificates to disk.");
+ }
+ SMARTLIST_FOREACH(chunks, sized_chunk_t *, c, tor_free(c));
+ smartlist_free(chunks);
+
+ trusted_dir_servers_certs_changed = 0;
+}
+
/* Router descriptor storage.
*
* Routerdescs are stored in a big file, named "cached-routers". As new
@@ -573,6 +658,24 @@
return NULL;
}
+/** Return the trusted_dir_server_t for the directory authority whose identity
+ * key hashes to <b>digest</b>, or NULL if no such authority is known.
+ */
+trusted_dir_server_t *
+trusteddirserver_get_by_v3_auth_digest(const char *digest)
+{
+ if (!trusted_dir_servers)
+ return NULL;
+
+ SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
+ {
+ if (!memcmp(ds->v3_identity_digest, digest, DIGEST_LEN))
+ return ds;
+ });
+
+ return NULL;
+}
+
/** Try to find a running trusted dirserver. If there are no running
* trusted dirservers and <b>retry_if_no_servers</b> is non-zero,
* set them all as running again, and try again.
@@ -3477,6 +3580,8 @@
static void
trusted_dir_server_free(trusted_dir_server_t *ds)
{
+ if (ds->v3_cert)
+ authority_cert_free(ds->v3_cert);
tor_free(ds->nickname);
tor_free(ds->description);
tor_free(ds->address);
Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c 2007-05-22 15:49:14 UTC (rev 10292)
+++ tor/trunk/src/or/routerparse.c 2007-05-22 17:58:25 UTC (rev 10293)
@@ -1289,16 +1289,19 @@
/** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
* the first character after the certificate. */
authority_cert_t *
-authority_cert_parse_from_string(const char *s, char **end_of_string)
+authority_cert_parse_from_string(const char *s, const char **end_of_string)
{
authority_cert_t *cert = NULL;
smartlist_t *tokens = NULL;
char digest[DIGEST_LEN];
directory_token_t *tok;
char fp_declared[DIGEST_LEN];
+ char *eos;
+ size_t len;
+ trusted_dir_server_t *ds;
- char *eos = strstr(s, "\n-----END SIGNATURE-----\n");
- size_t len;
+ s = eat_whitespace(s);
+ eos = strstr(s, "\n-----END SIGNATURE-----\n");
if (! eos) {
log_warn(LD_DIR, "No end-of-signature found on key certificate");
return NULL;
@@ -1324,6 +1327,7 @@
}
cert = tor_malloc_zero(sizeof(authority_cert_t));
+ memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
tok = find_first_by_keyword(tokens, K_DIR_SIGNING_KEY);
tor_assert(tok && tok->key);
@@ -1371,11 +1375,20 @@
goto err;
}
- /* XXXXX This doesn't check whether the key is an authority. IS that what we
- * want? */
- if (check_signature_token(digest, tok, cert->identity_key, 0,
- "key certificate")) {
- goto err;
+ /* If we already have this cert, don't bother checking the signature. */
+ ds = trusteddirserver_get_by_v3_auth_digest(
+ cert->cache_info.identity_digest);
+ if (ds && ds->v3_cert &&
+ ds->v3_cert->cache_info.signed_descriptor_len == len &&
+ ds->v3_cert->cache_info.signed_descriptor_body &&
+ ! memcmp(s, ds->v3_cert->cache_info.signed_descriptor_body, len)) {
+ log_debug(LD_DIR, "We already checked the signature on this certificate;"
+ " no need to do so again.");
+ } else {
+ if (check_signature_token(digest, tok, cert->identity_key, 0,
+ "key certificate")) {
+ goto err;
+ }
}
cert->cache_info.signed_descriptor_len = len;
@@ -1383,7 +1396,10 @@
memcpy(cert->cache_info.signed_descriptor_body, s, len);
cert->cache_info.signed_descriptor_body[len] = 0;
cert->cache_info.saved_location = SAVED_NOWHERE;
- *end_of_string = eos;
+
+ if (end_of_string) {
+ *end_of_string = eat_whitespace(eos);
+ }
return cert;
err:
authority_cert_free(cert);