From c44016e86ec8dfd9147b2ca58e5277cb03a92561 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 24 Apr 2004 22:17:50 +0000 Subject: Merge flagday into main branch. svn:r1683 --- src/common/crypto.c | 11 +++-- src/common/tortls.c | 140 ++++++++++++++++++++++++++++++---------------------- src/common/tortls.h | 5 +- 3 files changed, 93 insertions(+), 63 deletions(-) (limited to 'src/common') diff --git a/src/common/crypto.c b/src/common/crypto.c index 88330892bc..831aaaa2c2 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -127,13 +127,18 @@ RSA *_crypto_pk_env_get_rsa(crypto_pk_env_t *env) } /* used by tortls.c */ -EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env) +EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private) { RSA *key = NULL; EVP_PKEY *pkey = NULL; assert(env->key); - if (!(key = RSAPrivateKey_dup(env->key))) - goto error; + if (private) { + if (!(key = RSAPrivateKey_dup(env->key))) + goto error; + } else { + if (!(key = RSAPublicKey_dup(env->key))) + goto error; + } if (!(pkey = EVP_PKEY_new())) goto error; if (!(EVP_PKEY_assign_RSA(pkey, key))) diff --git a/src/common/tortls.c b/src/common/tortls.c index 4f6ee2146f..d7f54b4733 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -23,8 +23,8 @@ #include #include -/* How long do certificates live? (sec) */ -#define CERT_LIFETIME (365*24*60*60) +/* How long do identity certificates live? (sec) */ +#define IDENTITY_CERT_LIFETIME (365*24*60*60) /* How much clock skew do we tolerate when checking certificates? (sec) */ #define CERT_ALLOW_SKEW (90*60) @@ -44,7 +44,10 @@ struct tor_tls_st { }; static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, - const char *nickname); + crypto_pk_env_t *rsa_sign, + const char *cname, + const char *cname_sign, + unsigned int lifetime); /* global tls context, keep it here because nobody else needs to touch it */ static tor_tls_context *global_tls_context = NULL; @@ -54,7 +57,7 @@ static int tls_library_is_initialized = 0; #define _TOR_TLS_ZERORETURN -5 /* These functions are declared in crypto.c but not exported. */ -EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env); +EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private); crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa); DH *_crypto_dh_env_get_dh(crypto_dh_env_t *dh); @@ -129,26 +132,32 @@ static int always_accept_verify_cb(int preverify_ok, } /* Generate a self-signed certificate with the private key 'rsa' and - * commonName 'nickname', and write it, PEM-encoded, to the file named - * by 'certfile'. Return 0 on success, -1 for failure. + * identity key 'identity and commonName 'nickname'. Return a certificate + * on success, NULL on failure. + * DOCDOC */ X509 * tor_tls_create_certificate(crypto_pk_env_t *rsa, - const char *nickname) + crypto_pk_env_t *rsa_sign, + const char *cname, + const char *cname_sign, + unsigned int cert_lifetime) { time_t start_time, end_time; - EVP_PKEY *pkey = NULL; + EVP_PKEY *sign_pkey = NULL, *pkey=NULL; X509 *x509 = NULL; - X509_NAME *name = NULL; + X509_NAME *name = NULL, *name_issuer=NULL; int nid; tor_tls_init(); start_time = time(NULL); - assert(rsa && nickname); - if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa))) - return NULL; + assert(rsa && cname && rsa_sign && cname_sign); + if (!(sign_pkey = _crypto_pk_env_get_evp_pkey(rsa_sign,1))) + goto error; + if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,0))) + goto error; if (!(x509 = X509_new())) goto error; if (!(X509_set_version(x509, 2))) @@ -163,20 +172,29 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, "TOR", -1, -1, 0))) goto error; if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error; if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC, - (char*)nickname, -1, -1, 0))) goto error; + (char*)cname, -1, -1, 0))) goto error; + if (!(X509_set_subject_name(x509, name))) + goto error; - if (!(X509_set_issuer_name(x509, name))) + if (!(name_issuer = X509_NAME_new())) goto error; - if (!(X509_set_subject_name(x509, name))) + if ((nid = OBJ_txt2nid("organizationName")) == NID_undef) goto error; + if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC, + "TOR", -1, -1, 0))) goto error; + if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error; + if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC, + (char*)cname_sign, -1, -1, 0))) goto error; + if (!(X509_set_issuer_name(x509, name_issuer))) goto error; + if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time)) goto error; - end_time = start_time + CERT_LIFETIME; + end_time = start_time + cert_lifetime; if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time)) goto error; if (!X509_set_pubkey(x509, pkey)) goto error; - if (!X509_sign(x509, pkey, EVP_sha1())) + if (!X509_sign(x509, sign_pkey, EVP_sha1())) goto error; goto done; @@ -186,10 +204,14 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, x509 = NULL; } done: + if (sign_pkey) + EVP_PKEY_free(sign_pkey); if (pkey) EVP_PKEY_free(pkey); if (name) X509_NAME_free(name); + if (name_issuer) + X509_NAME_free(name_issuer); return x509; } @@ -210,26 +232,37 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, #endif /* Create a new TLS context. If we are going to be using it as a - * server, it must have isServer set to true, certfile set to a - * filename for a certificate file, and RSA set to the private key - * used for that certificate. Return -1 if failure, else 0. + * server, it must have isServer set to true, 'identity' set to the + * identity key used to sign that certificate, and 'nickname' set to + * the server's nickname. Return -1 if failure, else 0. */ int -tor_tls_context_new(crypto_pk_env_t *rsa, - int isServer, const char *nickname) +tor_tls_context_new(crypto_pk_env_t *identity, + int isServer, const char *nickname, + unsigned int key_lifetime) { + crypto_pk_env_t *rsa = NULL; crypto_dh_env_t *dh = NULL; EVP_PKEY *pkey = NULL; - tor_tls_context *result; - X509 *cert = NULL; + tor_tls_context *result = NULL; + X509 *cert = NULL, *idcert = NULL; + char nn2[1024]; + sprintf(nn2, "%s ", nickname); tor_tls_init(); - if (rsa) { - cert = tor_tls_create_certificate(rsa, nickname); - if (!cert) { + if (isServer) { + if (!(rsa = crypto_new_pk_env())) + goto error; + if (crypto_pk_generate_key(rsa)<0) + goto error; + cert = tor_tls_create_certificate(rsa, identity, nickname, nn2, + key_lifetime); + idcert = tor_tls_create_certificate(identity, identity, nn2, nn2, + IDENTITY_CERT_LIFETIME); + if (!cert || !idcert) { log(LOG_WARN, "Error creating certificate"); - return -1; + goto error; } } @@ -249,9 +282,12 @@ tor_tls_context_new(crypto_pk_env_t *rsa, goto error; if (cert && !SSL_CTX_use_certificate(result->ctx,cert)) goto error; + if (idcert && !SSL_CTX_add_extra_chain_cert(result->ctx,idcert)) + goto error; SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); - if (rsa) { - if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa))) + if (isServer) { + assert(rsa); + if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1))) goto error; if (!SSL_CTX_use_PrivateKey(result->ctx, pkey)) goto error; @@ -283,13 +319,15 @@ tor_tls_context_new(crypto_pk_env_t *rsa, error: if (pkey) EVP_PKEY_free(pkey); + if (rsa) + crypto_free_pk_env(rsa); if (dh) crypto_dh_free(dh); if (result && result->ctx) SSL_CTX_free(result->ctx); if (result) free(result); - + /* leak certs XXXX ? */ return -1; } @@ -509,19 +547,19 @@ tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen) } /* If the provided tls connection is authenticated and has a - * certificate that is currently valid and is correctly self-signed, - * return its public key. Otherwise return NULL. + * certificate that is currently valid and is correctly signed by + * identity_key, return 0. Else, return -1. */ -crypto_pk_env_t * -tor_tls_verify(tor_tls *tls) +int +tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity_key) { X509 *cert = NULL; - EVP_PKEY *pkey = NULL; - RSA *rsa = NULL; + EVP_PKEY *id_pkey = NULL; time_t now, t; - crypto_pk_env_t *r = NULL; + int r = -1; + if (!(cert = SSL_get_peer_certificate(tls->ssl))) - return NULL; + return -1; now = time(NULL); t = now + CERT_ALLOW_SKEW; @@ -536,33 +574,19 @@ tor_tls_verify(tor_tls *tls) } /* Get the public key. */ - if (!(pkey = X509_get_pubkey(cert))) { - log_fn(LOG_WARN,"X509_get_pubkey returned null"); - goto done; - } - if (X509_verify(cert, pkey) <= 0) { + if (!(id_pkey = _crypto_pk_env_get_evp_pkey(identity_key,0)) || + X509_verify(cert, id_pkey) <= 0) { log_fn(LOG_WARN,"X509_verify on cert and pkey returned <= 0"); goto done; } - rsa = EVP_PKEY_get1_RSA(pkey); - EVP_PKEY_free(pkey); - pkey = NULL; - if (!rsa) { - log_fn(LOG_WARN,"EVP_PKEY_get1_RSA(pkey) returned null"); - goto done; - } - - r = _crypto_new_pk_env_rsa(rsa); - rsa = NULL; + r = 0; done: if (cert) X509_free(cert); - if (pkey) - EVP_PKEY_free(pkey); - if (rsa) - RSA_free(rsa); + if (id_pkey) + EVP_PKEY_free(id_pkey); return r; } diff --git a/src/common/tortls.h b/src/common/tortls.h index d9e326e55c..da22454f2e 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -17,12 +17,13 @@ typedef struct tor_tls_st tor_tls; #define TOR_TLS_DONE 0 /* X509* tor_tls_write_certificate(char *certfile, crypto_pk_env_t *rsa, char *nickname); */ -int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer, const char *nickname); +int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer, + const char *nickname, unsigned int key_lifetime); tor_tls *tor_tls_new(int sock, int isServer); void tor_tls_free(tor_tls *tls); int tor_tls_peer_has_cert(tor_tls *tls); int tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen); -crypto_pk_env_t *tor_tls_verify(tor_tls *tls); +int tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity); int tor_tls_read(tor_tls *tls, char *cp, int len); int tor_tls_write(tor_tls *tls, char *cp, int n); int tor_tls_handshake(tor_tls *tls); -- cgit v1.2.3-54-g00ecf