return r;
}
-int crypto_pk_DER64_encode_key(crypto_pk_env_t *env, char **out)
+/** Allocate a new string in *<b>out</b>, containing the public portion of the
+ * RSA key in <b>env</b>, encoded first with DER, then in base-64. Return the
+ * length of the encoded representation on success, and -1 on failure.
+ *
+ * <i>This function is for temporary use only. We need a simple
+ * one-line representation for keys to work around a bug in parsing
+ * directories containing "opt keyword\n-----BEGIN OBJECT----" entries
+ * in versions of Tor up to 0.0.9pre2.</i>
+ */
+int crypto_pk_DER64_encode_public_key(crypto_pk_env_t *env, char **out)
{
int len;
- char *s, *sp;
+ char buf[PK_BYTES*2]; /* Too long, but hey, stacks are big. */
tor_assert(env && out);
- len = i2d_RSAPublicKey(env->key, NULL);
+ len = crypto_pk_asn1_encode(env, buf, sizeof(buf));
if (len < 0) {
return -1;
}
- s = sp = tor_malloc(len+1);
- i2d_RSAPublicKey(env->key, &sp); /* modifies sp */
*out = tor_malloc(len * 2); /* too long, but safe. */
- if (base64_encode(*out, len*2, s, len) < 0) {
+ if (base64_encode(*out, len*2, buf, len) < 0) {
log_fn(LOG_WARN, "Error base64-encoding DER-encoded key");
tor_free(*out);
- tor_free(s);
return -1;
}
- tor_free(s);
- return len;
+ /* Remove spaces */
+ tor_strstrip(*out, " \r\n\t");
+ return strlen(*out);
}
-int crypto_pk_DER64_decode_key(crypto_pk_env_t *env, const char *in)
+/** Decode a base-64 encoded DER representation of an RSA key from <b>in</b>,
+ * and store the result in <b>env</b>. Return 0 on success, -1 on failure.
+ *
+ * <i>This function is for temporary use only. We need a simple
+ * one-line representation for keys to work around a bug in parsing
+ * directories containing "opt keyword\n-----BEGIN OBJECT----" entries
+ * in versions of Tor up to 0.0.9pre2.</i>
+ */
+crypto_pk_env_t *crypto_pk_DER64_decode_public_key(const char *in)
{
- char *buf, *bufp;
- RSA *rsa;
+ char buf1[PK_BYTES*2 + PK_BYTES/64 + 2];
+ char buf[PK_BYTES*2];
int len;
- tor_assert(env && in);
+ int i;
+ tor_assert(in);
len = strlen(in);
- buf = bufp = tor_malloc(len+1);
- if (base64_decode(buf, len+1, in, len)<0) {
- tor_free(buf);
+
+ if (strlen(in) > PK_BYTES*2) {
+ return NULL;
+ }
+ /* base64_decode doesn't work unless we insert linebreaks every 64
+ * characters. how dumb. */
+ for(i=0;i*64<len;i+=1) {
+ strncpy(buf1+(64+1)*i, in+64*i, 64);
+ strcpy(buf1+(64+1)*i + 64, "\n");
+ }
+ len = base64_decode(buf, sizeof(buf), buf1, strlen(buf1));
+ if (len<0) {
log_fn(LOG_WARN,"Error base-64 decoding key");
- return -1;
+ return NULL;
}
- rsa = d2i_RSAPublicKey(NULL, &bufp, strlen(buf));
- tor_free(buf);
- if (!rsa)
- return -1;
- if (env->key) RSA_free(env->key);
- env->key = rsa;
- return 0;
+ return crypto_pk_asn1_decode(buf, len);
}
/** Return true iff <b>env</b> has a valid key.
int crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env, const char *fname);
int crypto_pk_check_key(crypto_pk_env_t *env);
int crypto_pk_read_private_key_from_filename(crypto_pk_env_t *env, const char *keyfile);
+int crypto_pk_DER64_encode_public_key(crypto_pk_env_t *env, char **dest);
+crypto_pk_env_t *crypto_pk_DER64_decode_public_key(const char *in);
+
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b);
crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig);
#define tor_free(p) do {if(p) {free(p); (p)=NULL;}} while(0)
void tor_strlower(char *s);
int strcmpstart(const char *s1, const char *s2);
+int tor_strstrip(char *s, const char *strip);
/* Some platforms segfault when you try to access a multi-byte type
* that isn't aligned to a word boundary. The macros and/or functions
char signature[128];
char published[33];
time_t published_on;
- int i, identity_pkeylen;
+ int i;
eos = s+maxlen;
if (!descriptor_list)
if (list_running_servers(&cp))
return -1;
-#if 0
- /* PEM-encode the identity key key */
- if(crypto_pk_write_public_key_to_string(private_key,
- &identity_pkey,&identity_pkeylen)<0) {
+
+ /* ASN.1-encode the public key. This is a temporary measure; once
+ * everyone is running 0.0.9pre3 or later, we can shift to using a
+ * PEM-encoded key instead.
+ */
+ if(crypto_pk_DER64_encode_public_key(private_key, &identity_pkey)<0) {
log_fn(LOG_WARN,"write identity_pkey to string failed!");
return -1;
}
-#endif
dirserv_remove_old_servers(ROUTER_MAX_AGE);
published_on = time(NULL);
format_iso_time(published, published_on);
"signed-directory\n"
"published %s\n"
"recommended-software %s\n"
- "running-routers %s\n\n",
- published, options.RecommendedVersions, cp);
+ "running-routers %s\n"
+ "opt dir-signing-key %s\n\n",
+ published, options.RecommendedVersions, cp, identity_pkey);
tor_free(cp);
tor_free(identity_pkey);
test_assert(! crypto_pk_write_public_key_to_string(pk1, &cp, &i));
test_assert(! crypto_pk_read_public_key_from_string(pk2, cp, i));
test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
+ tor_free(cp);
+
+ /* Check DER encoding */
+ i=crypto_pk_DER64_encode_public_key(pk1, &cp);
+ test_assert(i>0);
+ test_assert(cp);
+ test_assert(!strchr(cp, ' '));
+ test_assert(!strchr(cp, '\n'));
+ test_eq(0, crypto_pk_cmp_keys(pk1, pk1));
+ crypto_free_pk_env(pk2);
+ pk2 = crypto_pk_DER64_decode_public_key(cp);
+ test_assert(pk2);
+ test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
+ tor_free(cp);
test_eq(128, crypto_pk_keysize(pk1));
test_eq(128, crypto_pk_keysize(pk2));
// puts("========================== Buffers =========================");
// test_buffers();
puts("\n========================== Crypto ==========================");
+ // add_stream_log(LOG_DEBUG, LOG_ERR, "<stdout>", stdout);
test_crypto();
test_crypto_dh();
puts("\n========================= Util ============================");
test_onion();
test_onion_handshake();
puts("\n========================= Directory Formats ===============");
- /* add_stream_log(LOG_DEBUG, LOG_ERR, "<stdout>", stdout); */
test_dir_format();
puts("\n========================= Rendezvous functionality ========");
test_rend_fns();