diff --git a/src/etc/inc/certs.inc b/src/etc/inc/certs.inc
index 4f5bebeed..7c2a67ab9 100644
--- a/src/etc/inc/certs.inc
+++ b/src/etc/inc/certs.inc
@@ -144,16 +144,21 @@ function ca_chain(&$cert)
return str_replace("\n\n", "\n", str_replace("\r", "", $ca));
}
-function ca_create(&$ca, $keylen, $lifetime, $dn, $digest_alg = 'sha256')
+function ca_create(&$ca, $keylen_curve, $lifetime, $dn, $digest_alg)
{
$args = array(
'config' => '/usr/local/etc/ssl/opnsense.cnf',
- 'private_key_type' => OPENSSL_KEYTYPE_RSA,
- 'private_key_bits' => (int)$keylen,
'x509_extensions' => 'v3_ca',
'digest_alg' => $digest_alg,
'encrypt_key' => false
);
+ if (is_numeric($keylen_curve)) {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_RSA;
+ $args['private_key_bits'] = (int)$keylen_curve;
+ } else {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_EC;
+ $args['curve_name'] = $keylen_curve;
+ }
// generate a new key pair
$res_key = openssl_pkey_new($args);
@@ -205,7 +210,7 @@ function cert_import(& $cert, $crt_str, $key_str)
return true;
}
-function cert_create(&$cert, $caref, $keylen, $lifetime, $dn, $digest_alg = 'sha256', $x509_extensions = 'usr_cert')
+function cert_create(&$cert, $caref, $keylen_curve, $lifetime, $dn, $digest_alg, $x509_extensions = 'usr_cert')
{
$ca = &lookup_ca($caref);
if (!$ca) {
@@ -226,12 +231,17 @@ function cert_create(&$cert, $caref, $keylen, $lifetime, $dn, $digest_alg = 'sha
$args = array(
'config' => $config_filename,
- 'private_key_type' => OPENSSL_KEYTYPE_RSA,
- 'private_key_bits' => (int)$keylen,
'x509_extensions' => $x509_extensions,
'digest_alg' => $digest_alg,
'encrypt_key' => false
);
+ if (is_numeric($keylen_curve)) {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_RSA;
+ $args['private_key_bits'] = (int)$keylen_curve;
+ } else {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_EC;
+ $args['curve_name'] = $keylen_curve;
+ }
// generate a new key pair
$res_key = openssl_pkey_new($args);
diff --git a/src/www/system_camanager.php b/src/www/system_camanager.php
index ad98087ae..364dcadc2 100644
--- a/src/www/system_camanager.php
+++ b/src/www/system_camanager.php
@@ -27,10 +27,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-require_once('guiconfig.inc');
+require_once("guiconfig.inc");
require_once("system.inc");
-function ca_import(& $ca, $str, $key="", $serial=0) {
+function ca_import(& $ca, $str, $key="", $serial=0)
+{
global $config;
$ca['crt'] = base64_encode($str);
@@ -71,7 +72,7 @@ function ca_import(& $ca, $str, $key="", $serial=0) {
return true;
}
-function ca_inter_create(&$ca, $keylen, $lifetime, $dn, $caref, $digest_alg = 'sha256')
+function ca_inter_create(&$ca, $keylen_curve, $lifetime, $dn, $caref, $digest_alg = 'sha256')
{
// Create Intermediate Certificate Authority
$signing_ca = &lookup_ca($caref);
@@ -88,12 +89,17 @@ function ca_inter_create(&$ca, $keylen, $lifetime, $dn, $caref, $digest_alg = 's
$args = array(
'config' => '/usr/local/etc/ssl/opnsense.cnf',
- 'private_key_type' => OPENSSL_KEYTYPE_RSA,
- 'private_key_bits' => (int)$keylen,
'x509_extensions' => 'v3_ca',
'digest_alg' => $digest_alg,
'encrypt_key' => false
);
+ if (is_numeric($keylen_curve)) {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_RSA;
+ $args['private_key_bits'] = (int)$keylen_curve;
+ } else {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_EC;
+ $args['curve_name'] = $keylen_curve;
+ }
// generate a new key pair
$res_key = openssl_pkey_new($args);
@@ -128,8 +134,8 @@ function ca_inter_create(&$ca, $keylen, $lifetime, $dn, $caref, $digest_alg = 's
return true;
}
-
$ca_keylens = array( "512", "1024", "2048", "3072", "4096", "8192");
+$ca_curves = array( "prime256v1", "secp384r1", "secp521r1");
$openssl_digest_algs = array("sha1", "sha224", "sha256", "sha384", "sha512");
$a_ca = &config_read_array('ca');
$a_cert = &config_read_array('cert');
@@ -176,6 +182,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig['camethod'] = $_GET['method'];
}
$pconfig['refid'] = null;
+ $pconfig['keytype'] = "RSA";
$pconfig['keylen'] = "2048";
$pconfig['digest_alg'] = "sha256";
$pconfig['lifetime'] = "365";
@@ -264,12 +271,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
} elseif ($pconfig['camethod'] == "internal") {
$reqdfields = explode(
" ",
- "descr keylen lifetime dn_country dn_state dn_city ".
+ "descr keytype keylen curve digest_alg lifetime dn_country dn_state dn_city ".
"dn_organization dn_email dn_commonname"
);
$reqdfieldsn = array(
gettext("Descriptive name"),
+ gettext("Key type"),
gettext("Key length"),
+ gettext("Curve"),
+ gettext("Digest algorithm"),
gettext("Lifetime"),
gettext("Distinguished name Country Code"),
gettext("Distinguished name State or Province"),
@@ -280,13 +290,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
} elseif ($pconfig['camethod'] == "intermediate") {
$reqdfields = explode(
" ",
- "descr caref keylen lifetime dn_country dn_state dn_city ".
+ "descr caref keytype keylen curve digest_alg lifetime dn_country dn_state dn_city ".
"dn_organization dn_email dn_commonname"
);
$reqdfieldsn = array(
gettext("Descriptive name"),
gettext("Signing Certificate Authority"),
+ gettext("Key type"),
gettext("Key length"),
+ gettext("Curve"),
+ gettext("Digest algorithm"),
gettext("Lifetime"),
gettext("Distinguished name Country Code"),
gettext("Distinguished name State or Province"),
@@ -312,9 +325,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$input_errors[] = sprintf(gettext("The field '%s' contains invalid characters."), $reqdfieldsn[$i]);
}
}
- if (!in_array($pconfig["keylen"], $ca_keylens)) {
+ if (!in_array($pconfig["keytype"], array("RSA", "Elliptic Curve"))) {
+ $input_errors[] = gettext("Please select a valid Key Type.");
+ }
+ if (!in_array($pconfig['keylen'], $ca_keylens) && $pconfig["keytype"] == "RSA") {
$input_errors[] = gettext("Please select a valid Key Length.");
}
+ if (!in_array($pconfig['curve'], $ca_curves) && $pconfig["keytype"] == "Elliptic Curve") {
+ $input_errors[] = gettext("Please select a valid Curve.");
+ }
if (!in_array($pconfig["digest_alg"], $openssl_digest_algs)) {
$input_errors[] = gettext("Please select a valid Digest Algorithm.");
}
@@ -353,6 +372,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
}
} else {
$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
+ if ($pconfig['keytype'] == "Elliptic Curve") {
+ $pconfig['keylen_curve'] = $pconfig['curve'];
+ } else {
+ $pconfig['keylen_curve'] = $pconfig['keylen'];
+ }
if ($pconfig['camethod'] == "existing") {
ca_import($ca, $pconfig['cert'], $pconfig['key'], $pconfig['serial']);
} elseif ($pconfig['camethod'] == "internal") {
@@ -363,7 +387,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
'organizationName' => $pconfig['dn_organization'],
'emailAddress' => $pconfig['dn_email'],
'commonName' => $pconfig['dn_commonname']);
- if (!ca_create($ca, $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['digest_alg'])) {
+ if (!ca_create($ca, $pconfig['keylen_curve'], $pconfig['lifetime'], $dn, $pconfig['digest_alg'])) {
$input_errors = array();
while ($ssl_err = openssl_error_string()) {
$input_errors[] = gettext("openssl library returns:") . " " . $ssl_err;
@@ -377,7 +401,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
'organizationName' => $pconfig['dn_organization'],
'emailAddress' => $pconfig['dn_email'],
'commonName' => $pconfig['dn_commonname']);
- if (!ca_inter_create($ca, $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['caref'], $pconfig['digest_alg'])) {
+ if (!ca_inter_create($ca, $pconfig['keylen_curve'], $pconfig['lifetime'], $dn, $pconfig['caref'], $pconfig['digest_alg'])) {
$input_errors = array();
while ($ssl_err = openssl_error_string()) {
$input_errors[] = gettext("openssl library returns:") . " " . $ssl_err;
@@ -453,6 +477,19 @@ $main_buttons = array(
});
$("#camethod").change();
+
+ $("#keytype").change(function(){
+ $("#EC").addClass("hidden");
+ $("#RSA").addClass("hidden");
+ $("#blank").addClass("hidden");
+ if ($(this).val() == "Elliptic Curve") {
+ $("#EC").removeClass("hidden");
+ } else {
+ $("#RSA").removeClass("hidden");
+ }
+ });
+
+ $("#keytype").change();
});
@@ -573,12 +610,38 @@ $main_buttons = array(
+ | =gettext("Key Type");?> |
+
+
+ |
+
+
| =gettext("Key length");?> (=gettext("bits");?>) |
+ |
+
+ |
+
+ | =gettext("Curve");?> |
+
+
diff --git a/src/www/system_certmanager.php b/src/www/system_certmanager.php
index 333b70869..aaec3373c 100644
--- a/src/www/system_certmanager.php
+++ b/src/www/system_certmanager.php
@@ -36,18 +36,24 @@ require_once('phpseclib/File/ASN1/Element.php');
require_once('phpseclib/Crypt/RSA.php');
require_once('phpseclib/Crypt/Hash.php');
-function csr_generate(&$cert, $keylen, $dn, $digest_alg = 'sha256')
+function csr_generate(&$cert, $keylen_curve, $dn, $digest_alg)
{
$configFilename = create_temp_openssl_config($dn);
+
$args = array(
'config' => $configFilename,
- 'private_key_type' => OPENSSL_KEYTYPE_RSA,
- 'private_key_bits' => (int)$keylen,
'req_extensions' => 'v3_req',
'digest_alg' => $digest_alg,
'encrypt_key' => false
);
+ if (is_numeric($keylen_curve)) {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_RSA;
+ $args['private_key_bits'] = (int)$keylen_curve;
+ } else {
+ $args['private_key_type'] = OPENSSL_KEYTYPE_EC;
+ $args['curve_name'] = $keylen_curve;
+ }
// generate a new key pair
$res_key = openssl_pkey_new($args);
@@ -214,6 +220,7 @@ $cert_methods = array(
"sign_cert_csr" => gettext("Sign a Certificate Signing Request"),
);
$cert_keylens = array( "512", "1024", "2048", "3072", "4096", "8192");
+$cert_curves = array( "prime256v1", "secp384r1", "secp521r1");
$openssl_digest_algs = array("sha1", "sha224", "sha256", "sha384", "sha512");
$cert_types = array('usr_cert', 'server_cert', 'combined_server_client', 'v3_ca');
$key_usages = array(
@@ -266,9 +273,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
} else {
$pconfig['certmethod'] = null;
}
+ $pconfig['keytype'] = "RSA";
$pconfig['keylen'] = "2048";
$pconfig['digest_alg'] = "sha256";
$pconfig['digest_alg_sign_csr'] = "sha256";
+ $pconfig['csr_keytype'] = "RSA";
$pconfig['csr_keylen'] = "2048";
$pconfig['csr_digest_alg'] = "sha256";
$pconfig['lifetime'] = "365";
@@ -495,13 +504,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$input_errors[] = gettext("This certificate does not appear to be valid.");
}
} elseif ($pconfig['certmethod'] == "internal") {
- $reqdfields = explode(" ", "descr caref keylen lifetime dn_country dn_state dn_city ".
+ $reqdfields = explode(" ", "descr caref keytype keylen curve digest_alg lifetime dn_country dn_state dn_city ".
"dn_organization dn_email dn_commonname"
);
$reqdfieldsn = array(
gettext("Descriptive name"),
gettext("Certificate authority"),
+ gettext("Key type"),
gettext("Key length"),
+ gettext("Curve"),
+ gettext("Digest algorithm"),
gettext("Lifetime"),
gettext("Distinguished name Country Code"),
gettext("Distinguished name State or Province"),
@@ -510,12 +522,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
gettext("Distinguished name Email Address"),
gettext("Distinguished name Common Name"));
} elseif ($pconfig['certmethod'] == "external") {
- $reqdfields = explode(" ", "descr csr_keylen csr_dn_country csr_dn_state csr_dn_city ".
+ $reqdfields = explode(" ", "descr csr_keytype csr_keylen csr_curve csr_digest_alg csr_dn_country csr_dn_state csr_dn_city ".
"csr_dn_organization csr_dn_email csr_dn_commonname"
);
$reqdfieldsn = array(
gettext("Descriptive name"),
+ gettext("Key type"),
gettext("Key length"),
+ gettext("Curve"),
+ gettext("Digest algorithm"),
gettext("Distinguished name Country Code"),
gettext("Distinguished name State or Province"),
gettext("Distinguished name City"),
@@ -564,20 +579,30 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
}
}
+ if ($pconfig['certmethod'] != "external" && !in_array($pconfig["keytype"], array("RSA", "Elliptic Curve"))) {
+ $input_errors[] = gettext("Please select a valid Key Type.");
+ }
if ($pconfig['certmethod'] == "internal" && !in_array($pconfig["cert_type"], $cert_types)) {
$input_errors[] = gettext("Please select a valid Type.");
}
-
- if ($pconfig['certmethod'] != "external" && isset($pconfig["keylen"]) && !in_array($pconfig["keylen"], $cert_keylens)) {
+ if ($pconfig['certmethod'] != "external" && isset($pconfig["keylen"]) && $pconfig["keytype"] == "RSA" && !in_array($pconfig["keylen"], $cert_keylens)) {
$input_errors[] = gettext("Please select a valid Key Length.");
}
+ if ($pconfig['certmethod'] != "external" && isset($pconfig["curve"]) && $pconfig["keytype"] == "Elliptic Curve" && !in_array($pconfig["curve"], $cert_curves)) {
+ $input_errors[] = gettext("Please select a valid Curve.");
+ }
if ($pconfig['certmethod'] != "external" && !in_array($pconfig["digest_alg"], $openssl_digest_algs)) {
$input_errors[] = gettext("Please select a valid Digest Algorithm.");
}
-
- if ($pconfig['certmethod'] == "external" && isset($pconfig["csr_keylen"]) && !in_array($pconfig["csr_keylen"], $cert_keylens)) {
+ if ($pconfig['certmethod'] == "external" && !in_array($pconfig["keytype"], array("RSA", "Elliptic Curve"))) {
+ $input_errors[] = gettext("Please select a valid Key Type.");
+ }
+ if ($pconfig['certmethod'] == "external" && isset($pconfig["csr_keylen"]) && $pconfig["keytype"] == "RSA" && !in_array($pconfig["csr_keylen"], $cert_keylens)) {
$input_errors[] = gettext("Please select a valid Key Length.");
}
+ if ($pconfig['certmethod'] == "external" && isset($pconfig["csr_curve"]) && $pconfig["keytype"] == "Elliptic Curve" && !in_array($pconfig["csr_curve"], $cert_curves)) {
+ $input_errors[] = gettext("Please select a valid Curve.");
+ }
if ($pconfig['certmethod'] == "external" && !in_array($pconfig["csr_digest_alg"], $openssl_digest_algs)) {
$input_errors[] = gettext("Please select a valid Digest Algorithm.");
}
@@ -667,7 +692,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$cert['descr'] = $pconfig['descr'];
$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warings directly to a page screwing menu tab */
-
+ if ($pconfig['keytype'] == "Elliptic Curve") {
+ $pconfig['keylen_curve'] = $pconfig['curve'];
+ } else {
+ $pconfig['keylen_curve'] = $pconfig['keylen'];
+ }
+ if ($pconfig['csr_keytype'] == "Elliptic Curve") {
+ $pconfig['csr_keylen_curve'] = $pconfig['csr_curve'];
+ } else {
+ $pconfig['csr_keylen_curve'] = $pconfig['csr_keylen'];
+ }
if ($pconfig['certmethod'] == "import") {
cert_import($cert, $pconfig['cert'], $pconfig['key']);
} elseif ($pconfig['certmethod'] == "internal") {
@@ -689,7 +723,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (!cert_create(
$cert,
$pconfig['caref'],
- $pconfig['keylen'],
+ $pconfig['keylen_curve'],
$pconfig['lifetime'],
$dn,
$pconfig['digest_alg'],
@@ -732,7 +766,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
}
$dn['subjectAltName'] = implode(",", $altnames_tmp);
}
- if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['csr_digest_alg'])) {
+ if (!csr_generate($cert, $pconfig['csr_keylen_curve'], $dn, $pconfig['csr_digest_alg'])) {
$input_errors = array();
while ($ssl_err = openssl_error_string()) {
$input_errors[] = gettext("openssl library returns:") . " " . $ssl_err;
@@ -1117,6 +1151,31 @@ if (empty($act)) {
$(".text_download_btn").remove();
}
+$("#keytype").change(function(){
+ $("#EC").addClass("hidden");
+ $("#RSA").addClass("hidden");
+ $("#blank").addClass("hidden");
+ if ($(this).val() == "Elliptic Curve") {
+ $("#EC").removeClass("hidden");
+ } else {
+ $("#RSA").removeClass("hidden");
+ }
+});
+
+$("#keytype").change();
+
+$("#csr_keytype").change(function(){
+ $("#csr_EC").addClass("hidden");
+ $("#csr_RSA").addClass("hidden");
+ $("#csr_blank").addClass("hidden");
+ if ($(this).val() == "Elliptic Curve") {
+ $("#csr_EC").removeClass("hidden");
+ } else {
+ $("#csr_RSA").removeClass("hidden");
+ }
+});
+
+$("#csr_keytype").change();
});
@@ -1474,17 +1533,43 @@ $( document ).ready(function() {
|
+ | =gettext("Key Type");?> |
+
+
+ |
+
+
| =gettext("Key length");?> (=gettext("bits");?>) |
|
+ |
+
+ | =gettext("Curve");?> |
+
+
+ |
+
| =gettext("Digest Algorithm");?> |
@@ -1670,18 +1755,43 @@ $( document ).ready(function() {
|
+ | =gettext("Key Type");?> |
+
+
+ |
+
+
| =gettext("Key length");?> (=gettext("bits");?>) |
-
|
+ |
+
+ | =gettext("Curve");?> |
+
+
+ |
+
| =gettext("Digest Algorithm");?> |
|