SSL_CTX * ssl_ctx_create(const char *pkiname, char *cert, off_t cert_len, const char *ciphers) { SSL_CTX *ctx; size_t pkinamelen = 0; ctx = SSL_CTX_new(SSLv23_method()); if (ctx == NULL) { ssl_error("ssl_ctx_create"); fatal("ssl_ctx_create: could not create SSL context"); } SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_timeout(ctx, SSL_SESSION_TIMEOUT); SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TICKET); SSL_CTX_set_options(ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_CTX_set_options(ctx, SSL_OP_NO_CLIENT_RENEGOTIATION); SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); if (ciphers == NULL) ciphers = SSL_CIPHERS; if (!SSL_CTX_set_cipher_list(ctx, ciphers)) { ssl_error("ssl_ctx_create"); fatal("ssl_ctx_create: could not set cipher list"); } if (cert != NULL) { if (pkiname != NULL) pkinamelen = strlen(pkiname) + 1; if (!SSL_CTX_use_certificate_chain_mem(ctx, cert, cert_len)) { ssl_error("ssl_ctx_create"); fatal("ssl_ctx_create: invalid certificate chain"); } else if (!ssl_ctx_fake_private_key(ctx, pkiname, pkinamelen, cert, cert_len, NULL, NULL)) { ssl_error("ssl_ctx_create"); fatal("ssl_ctx_create: could not fake private key"); } else if (!SSL_CTX_check_private_key(ctx)) { ssl_error("ssl_ctx_create"); fatal("ssl_ctx_create: invalid private key"); } } return (ctx); }
int tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, struct tls_keypair *keypair, int required) { EVP_PKEY *pkey = NULL; BIO *bio = NULL; if (!required && keypair->cert_mem == NULL && keypair->key_mem == NULL) return(0); if (keypair->cert_mem != NULL) { if (keypair->cert_len > INT_MAX) { tls_set_errorx(ctx, "certificate too long"); goto err; } if (SSL_CTX_use_certificate_chain_mem(ssl_ctx, keypair->cert_mem, keypair->cert_len) != 1) { tls_set_errorx(ctx, "failed to load certificate"); goto err; } if (tls_keypair_pubkey_hash(keypair, &keypair->pubkey_hash) == -1) goto err; } if (keypair->key_mem != NULL) { if (keypair->key_len > INT_MAX) { tls_set_errorx(ctx, "key too long"); goto err; } if ((bio = BIO_new_mem_buf(keypair->key_mem, keypair->key_len)) == NULL) { tls_set_errorx(ctx, "failed to create buffer"); goto err; } if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb, NULL)) == NULL) { tls_set_errorx(ctx, "failed to read private key"); goto err; } if (keypair->pubkey_hash != NULL) { RSA *rsa; /* XXX only RSA for now for relayd privsep */ if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) { RSA_set_ex_data(rsa, 0, keypair->pubkey_hash); RSA_free(rsa); } } if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) { tls_set_errorx(ctx, "failed to load private key"); goto err; } BIO_free(bio); bio = NULL; EVP_PKEY_free(pkey); pkey = NULL; } if (!ctx->config->skip_private_key_check && SSL_CTX_check_private_key(ssl_ctx) != 1) { tls_set_errorx(ctx, "private/public key mismatch"); goto err; } return (0); err: EVP_PKEY_free(pkey); BIO_free(bio); return (1); }
int tls_configure_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, struct tls_keypair *keypair, int required) { EVP_PKEY *pkey = NULL; X509 *cert = NULL; BIO *bio = NULL; if (!required && keypair->cert_mem == NULL && keypair->key_mem == NULL && keypair->cert_file == NULL && keypair->key_file == NULL) return(0); if (keypair->cert_mem != NULL) { if (keypair->cert_len > INT_MAX) { tls_set_errorx(ctx, "certificate too long"); goto err; } if (SSL_CTX_use_certificate_chain_mem(ssl_ctx, keypair->cert_mem, keypair->cert_len) != 1) { tls_set_errorx(ctx, "failed to load certificate"); goto err; } cert = NULL; } if (keypair->key_mem != NULL) { if (keypair->key_len > INT_MAX) { tls_set_errorx(ctx, "key too long"); goto err; } if ((bio = BIO_new_mem_buf(keypair->key_mem, keypair->key_len)) == NULL) { tls_set_errorx(ctx, "failed to create buffer"); goto err; } if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) { tls_set_errorx(ctx, "failed to read private key"); goto err; } if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) { tls_set_errorx(ctx, "failed to load private key"); goto err; } BIO_free(bio); bio = NULL; EVP_PKEY_free(pkey); pkey = NULL; } if (keypair->cert_file != NULL) { if (SSL_CTX_use_certificate_chain_file(ssl_ctx, keypair->cert_file) != 1) { tls_set_errorx(ctx, "failed to load certificate file"); goto err; } } if (keypair->key_file != NULL) { if (SSL_CTX_use_PrivateKey_file(ssl_ctx, keypair->key_file, SSL_FILETYPE_PEM) != 1) { tls_set_errorx(ctx, "failed to load private key file"); goto err; } } if (SSL_CTX_check_private_key(ssl_ctx) != 1) { tls_set_errorx(ctx, "private/public key mismatch"); goto err; } return (0); err: EVP_PKEY_free(pkey); X509_free(cert); BIO_free(bio); return (1); }