mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Make base-64-encoded DER work, including workaround for ugly openssl misfeature that makes base64 decoding fail when you strip out the newlines.
svn:r2423
This commit is contained in:
parent
2bba65148b
commit
ce3162d035
@ -463,48 +463,67 @@ crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env,
|
|||||||
return r;
|
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;
|
int len;
|
||||||
char *s, *sp;
|
char buf[PK_BYTES*2]; /* Too long, but hey, stacks are big. */
|
||||||
tor_assert(env && out);
|
tor_assert(env && out);
|
||||||
len = i2d_RSAPublicKey(env->key, NULL);
|
len = crypto_pk_asn1_encode(env, buf, sizeof(buf));
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s = sp = tor_malloc(len+1);
|
|
||||||
i2d_RSAPublicKey(env->key, &sp); /* modifies sp */
|
|
||||||
*out = tor_malloc(len * 2); /* too long, but safe. */
|
*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");
|
log_fn(LOG_WARN, "Error base64-encoding DER-encoded key");
|
||||||
tor_free(*out);
|
tor_free(*out);
|
||||||
tor_free(s);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
tor_free(s);
|
/* Remove spaces */
|
||||||
return len;
|
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;
|
char buf1[PK_BYTES*2 + PK_BYTES/64 + 2];
|
||||||
RSA *rsa;
|
char buf[PK_BYTES*2];
|
||||||
int len;
|
int len;
|
||||||
tor_assert(env && in);
|
int i;
|
||||||
|
tor_assert(in);
|
||||||
len = strlen(in);
|
len = strlen(in);
|
||||||
buf = bufp = tor_malloc(len+1);
|
|
||||||
if (base64_decode(buf, len+1, in, len)<0) {
|
if (strlen(in) > PK_BYTES*2) {
|
||||||
tor_free(buf);
|
return NULL;
|
||||||
log_fn(LOG_WARN,"Error base-64 decoding key");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
rsa = d2i_RSAPublicKey(NULL, &bufp, strlen(buf));
|
/* base64_decode doesn't work unless we insert linebreaks every 64
|
||||||
tor_free(buf);
|
* characters. how dumb. */
|
||||||
if (!rsa)
|
for(i=0;i*64<len;i+=1) {
|
||||||
return -1;
|
strncpy(buf1+(64+1)*i, in+64*i, 64);
|
||||||
if (env->key) RSA_free(env->key);
|
strcpy(buf1+(64+1)*i + 64, "\n");
|
||||||
env->key = rsa;
|
}
|
||||||
return 0;
|
len = base64_decode(buf, sizeof(buf), buf1, strlen(buf1));
|
||||||
|
if (len<0) {
|
||||||
|
log_fn(LOG_WARN,"Error base-64 decoding key");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return crypto_pk_asn1_decode(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return true iff <b>env</b> has a valid key.
|
/** Return true iff <b>env</b> has a valid key.
|
||||||
|
@ -64,6 +64,9 @@ int crypto_pk_read_public_key_from_string(crypto_pk_env_t *env, const char *src,
|
|||||||
int crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env, const char *fname);
|
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_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_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);
|
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);
|
crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig);
|
||||||
|
@ -87,6 +87,7 @@ char *tor_strndup(const char *s, size_t n);
|
|||||||
#define tor_free(p) do {if(p) {free(p); (p)=NULL;}} while(0)
|
#define tor_free(p) do {if(p) {free(p); (p)=NULL;}} while(0)
|
||||||
void tor_strlower(char *s);
|
void tor_strlower(char *s);
|
||||||
int strcmpstart(const char *s1, const char *s2);
|
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
|
/* 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
|
* that isn't aligned to a word boundary. The macros and/or functions
|
||||||
|
@ -557,7 +557,7 @@ dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
|
|||||||
char signature[128];
|
char signature[128];
|
||||||
char published[33];
|
char published[33];
|
||||||
time_t published_on;
|
time_t published_on;
|
||||||
int i, identity_pkeylen;
|
int i;
|
||||||
eos = s+maxlen;
|
eos = s+maxlen;
|
||||||
|
|
||||||
if (!descriptor_list)
|
if (!descriptor_list)
|
||||||
@ -565,14 +565,15 @@ dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
|
|||||||
|
|
||||||
if (list_running_servers(&cp))
|
if (list_running_servers(&cp))
|
||||||
return -1;
|
return -1;
|
||||||
#if 0
|
|
||||||
/* PEM-encode the identity key key */
|
/* ASN.1-encode the public key. This is a temporary measure; once
|
||||||
if(crypto_pk_write_public_key_to_string(private_key,
|
* everyone is running 0.0.9pre3 or later, we can shift to using a
|
||||||
&identity_pkey,&identity_pkeylen)<0) {
|
* 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!");
|
log_fn(LOG_WARN,"write identity_pkey to string failed!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
dirserv_remove_old_servers(ROUTER_MAX_AGE);
|
dirserv_remove_old_servers(ROUTER_MAX_AGE);
|
||||||
published_on = time(NULL);
|
published_on = time(NULL);
|
||||||
format_iso_time(published, published_on);
|
format_iso_time(published, published_on);
|
||||||
@ -580,8 +581,9 @@ dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
|
|||||||
"signed-directory\n"
|
"signed-directory\n"
|
||||||
"published %s\n"
|
"published %s\n"
|
||||||
"recommended-software %s\n"
|
"recommended-software %s\n"
|
||||||
"running-routers %s\n\n",
|
"running-routers %s\n"
|
||||||
published, options.RecommendedVersions, cp);
|
"opt dir-signing-key %s\n\n",
|
||||||
|
published, options.RecommendedVersions, cp, identity_pkey);
|
||||||
|
|
||||||
tor_free(cp);
|
tor_free(cp);
|
||||||
tor_free(identity_pkey);
|
tor_free(identity_pkey);
|
||||||
|
@ -365,6 +365,20 @@ test_crypto()
|
|||||||
test_assert(! crypto_pk_write_public_key_to_string(pk1, &cp, &i));
|
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_assert(! crypto_pk_read_public_key_from_string(pk2, cp, i));
|
||||||
test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
|
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(pk1));
|
||||||
test_eq(128, crypto_pk_keysize(pk2));
|
test_eq(128, crypto_pk_keysize(pk2));
|
||||||
@ -1095,6 +1109,7 @@ main(int c, char**v){
|
|||||||
// puts("========================== Buffers =========================");
|
// puts("========================== Buffers =========================");
|
||||||
// test_buffers();
|
// test_buffers();
|
||||||
puts("\n========================== Crypto ==========================");
|
puts("\n========================== Crypto ==========================");
|
||||||
|
// add_stream_log(LOG_DEBUG, LOG_ERR, "<stdout>", stdout);
|
||||||
test_crypto();
|
test_crypto();
|
||||||
test_crypto_dh();
|
test_crypto_dh();
|
||||||
puts("\n========================= Util ============================");
|
puts("\n========================= Util ============================");
|
||||||
@ -1105,7 +1120,6 @@ main(int c, char**v){
|
|||||||
test_onion();
|
test_onion();
|
||||||
test_onion_handshake();
|
test_onion_handshake();
|
||||||
puts("\n========================= Directory Formats ===============");
|
puts("\n========================= Directory Formats ===============");
|
||||||
/* add_stream_log(LOG_DEBUG, LOG_ERR, "<stdout>", stdout); */
|
|
||||||
test_dir_format();
|
test_dir_format();
|
||||||
puts("\n========================= Rendezvous functionality ========");
|
puts("\n========================= Rendezvous functionality ========");
|
||||||
test_rend_fns();
|
test_rend_fns();
|
||||||
|
Loading…
Reference in New Issue
Block a user