summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2019-10-05 01:25:19 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2019-10-05 01:25:19 +0000
commitb46a7bbb48d08496c4f0cc08983decadca6f8bcb (patch)
treed62b3fdd2024b5aac3815c0123f90153991b4e32
parent5d64441a3f73379c93b65efe69e6e31e830c2d30 (diff)
parentf7729195c286f805b8038520f99f8d39ea8965de (diff)
downloadgnutls-b46a7bbb48d08496c4f0cc08983decadca6f8bcb.tar.gz
Merge branch 'tmp_gnutls-cli/srv_rawpk_support' into 'master'
Support for raw public keys for gnutls-cli and gnutls-serv See merge request gnutls/gnutls!1059
-rw-r--r--NEWS3
-rw-r--r--src/cli-args.def49
-rw-r--r--src/cli.c172
-rw-r--r--src/common.c55
-rw-r--r--src/serv-args.def58
-rw-r--r--src/serv.c49
-rw-r--r--tests/Makefile.am2
-rwxr-xr-xtests/gnutls-cli-rawpk.sh320
8 files changed, 648 insertions, 60 deletions
diff --git a/NEWS b/NEWS
index a175a1eb7f..e2a10e7746 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,9 @@ See the end for copying conditions.
** certtool: when outputting an encrypted private key do not insert the textual description
of it. This fixes a regression since 3.6.5 (#840).
+** gnutls-cli/serv: added raw public-key handling capabilities (RFC7250).
+ Key material can be set via the --rawpkkeyfile and --rawpkfile flags.
+
** API and ABI modifications:
gnutls_aead_cipher_encryptv2: Added
gnutls_aead_cipher_decryptv2: Added
diff --git a/src/cli-args.def b/src/cli-args.def
index 621de61f3c..602eaf9058 100644
--- a/src/cli-args.def
+++ b/src/cli-args.def
@@ -239,6 +239,31 @@ flag = {
};
flag = {
+ name = rawpkkeyfile;
+ arg-type = string;
+ descrip = "Private key file (PKCS #8 or PKCS #12) or PKCS #11 URL to use";
+ doc = "In order to instruct the application to negotiate raw public keys one
+must enable the respective certificate types via the priority strings (i.e. CTYPE-CLI-*
+and CTYPE-SRV-* flags).
+
+Check the GnuTLS manual on section ``Priority strings'' for more
+information on how to set certificate types.";
+};
+
+flag = {
+ name = rawpkfile;
+ arg-type = string;
+ descrip = "Raw public-key file to use";
+ doc = "In order to instruct the application to negotiate raw public keys one
+must enable the respective certificate types via the priority strings (i.e. CTYPE-CLI-*
+and CTYPE-SRV-* flags).
+
+Check the GnuTLS manual on section ``Priority strings'' for more
+information on how to set certificate types.";
+ flags-must = rawpkkeyfile;
+};
+
+flag = {
name = srpusername;
arg-type = string;
descrip = "SRP username to use";
@@ -467,7 +492,29 @@ Connecting to '127.0.0.1:5556'...
- Simple Client Mode:
@end example
-By keeping the --pskusername parameter and removing the --pskkey parameter, it will query only for the password during the handshake.
+By keeping the --pskusername parameter and removing the --pskkey parameter, it will query only for the password during the handshake.
+
+@subheading Connecting using raw public-key authentication
+To connect to a server using raw public-key authentication, you need to enable the option to negotiate raw public-keys via the priority strings such as in the example below.
+@example
+$ ./gnutls-cli -p 5556 localhost --priority NORMAL:-CTYPE-CLI-ALL:+CTYPE-CLI-RAWPK \
+ --rawpkkeyfile cli.key.pem \
+ --rawpkfile cli.rawpk.pem
+Processed 1 client raw public key pair...
+Resolving 'localhost'...
+Connecting to '127.0.0.1:5556'...
+- Successfully sent 1 certificate(s) to server.
+- Server has requested a certificate.
+- Certificate type: X.509
+- Got a certificate list of 1 certificates.
+- Certificate[0] info:
+ - skipped
+- Description: (TLS1.3-Raw Public Key-X.509)-(ECDHE-SECP256R1)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
+- Options:
+- Handshake was completed
+
+- Simple Client Mode:
+@end example
@subheading Connecting to STARTTLS services
diff --git a/src/cli.c b/src/cli.c
index 691eb98c54..b31f43cadb 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -95,9 +95,11 @@ const char *x509_certfile = NULL;
const char *x509_cafile = NULL;
const char *x509_crlfile = NULL;
static int x509ctype;
+const char *rawpk_keyfile = NULL;
+const char *rawpk_file = NULL;
static int disable_extensions;
static int disable_sni;
-static unsigned int init_flags = GNUTLS_CLIENT;
+static unsigned int init_flags = GNUTLS_CLIENT | GNUTLS_ENABLE_RAWPK;
static const char *priorities = NULL;
static const char *inline_commands_prefix;
@@ -121,10 +123,60 @@ static int cert_verify_ocsp(gnutls_session_t session);
static unsigned int x509_crt_size;
static gnutls_pcert_st x509_crt[MAX_CRT];
static gnutls_privkey_t x509_key = NULL;
+static gnutls_pcert_st rawpk;
+static gnutls_privkey_t rawpk_key = NULL;
-/* Load the certificate and the private key.
+
+/* Load a PKCS #8, PKCS #12 private key or PKCS #11 URL
*/
-static void load_keys(void)
+static void load_priv_key(gnutls_privkey_t* privkey, const char* key_source)
+{
+ int ret;
+ gnutls_datum_t data = { NULL, 0 };
+
+ ret = gnutls_privkey_init(privkey);
+
+ if (ret < 0) {
+ fprintf(stderr, "*** Error initializing key: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_privkey_set_pin_function(*privkey, pin_callback,
+ NULL);
+
+ if (gnutls_url_is_supported(key_source) != 0) {
+ ret = gnutls_privkey_import_url(*privkey, key_source, 0);
+ if (ret < 0) {
+ fprintf(stderr,
+ "*** Error loading url: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+ } else {
+ ret = gnutls_load_file(key_source, &data);
+ if (ret < 0) {
+ fprintf(stderr,
+ "*** Error loading key file.\n");
+ exit(1);
+ }
+
+ ret = gnutls_privkey_import_x509_raw(*privkey, &data,
+ x509ctype, NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr,
+ "*** Error importing key: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_free(data.data);
+ }
+}
+
+/* Load the X509 certificate and the private key.
+ */
+static void load_x509_keys(void)
{
unsigned int crt_num;
int ret;
@@ -209,51 +261,45 @@ static void load_keys(void)
gnutls_free(data.data);
- ret = gnutls_privkey_init(&x509_key);
+ load_priv_key(&x509_key, x509_keyfile);
+
+ fprintf(stdout,
+ "Processed %d client X.509 certificates...\n",
+ x509_crt_size);
+ }
+}
+
+/* Load the raw public key and corresponding private key.
+ */
+static void load_rawpk_keys(void)
+{
+ int ret;
+ gnutls_datum_t data = { NULL, 0 };
+
+ if (rawpk_file != NULL && rawpk_keyfile != NULL) {
+ // First we load the raw public key
+ ret = gnutls_load_file(rawpk_file, &data);
if (ret < 0) {
- fprintf(stderr, "*** Error initializing key: %s\n",
- gnutls_strerror(ret));
+ fprintf(stderr,
+ "*** Error loading cert file.\n");
exit(1);
}
- gnutls_privkey_set_pin_function(x509_key, pin_callback,
- NULL);
-
- if (gnutls_url_is_supported(x509_keyfile) != 0) {
- ret =
- gnutls_privkey_import_url(x509_key,
- x509_keyfile, 0);
- if (ret < 0) {
- fprintf(stderr,
- "*** Error loading url: %s\n",
- gnutls_strerror(ret));
- exit(1);
- }
- } else {
- ret = gnutls_load_file(x509_keyfile, &data);
- if (ret < 0) {
- fprintf(stderr,
- "*** Error loading key file.\n");
- exit(1);
- }
+ ret = gnutls_pcert_import_rawpk_raw(&rawpk, &data, x509ctype, 0, 0);
+ if (ret < 0) {
+ fprintf(stderr,
+ "*** Error importing rawpk to pcert: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
- ret =
- gnutls_privkey_import_x509_raw(x509_key, &data,
- x509ctype, NULL,
- 0);
- if (ret < 0) {
- fprintf(stderr,
- "*** Error loading url: %s\n",
- gnutls_strerror(ret));
- exit(1);
- }
+ gnutls_free(data.data);
- gnutls_free(data.data);
- }
+ // Secondly, we load the private key corresponding to the raw pk
+ load_priv_key(&rawpk_key, rawpk_keyfile);
fprintf(stdout,
- "Processed %d client X.509 certificates...\n",
- x509_crt_size);
+ "Processed %d client raw public key pair...\n", 1);
}
}
@@ -541,23 +587,40 @@ cert_callback(gnutls_session_t session,
* supported by the server.
*/
- cert_type = gnutls_certificate_type_get(session);
+ cert_type = gnutls_certificate_type_get2(session, GNUTLS_CTYPE_CLIENT);
*pcert_length = 0;
- if (cert_type == GNUTLS_CRT_X509) {
- if (x509_crt_size > 0) {
- if (x509_key != NULL) {
- *pkey = x509_key;
- } else {
+ switch (cert_type) {
+ case GNUTLS_CRT_X509:
+ if (x509_crt_size > 0) {
+ if (x509_key != NULL) {
+ *pkey = x509_key;
+ } else {
+ log_msg
+ (stdout, "- Could not find a suitable key to send to server\n");
+ return -1;
+ }
+
+ *pcert_length = x509_crt_size;
+ *pcert = x509_crt;
+ }
+ break;
+ case GNUTLS_CRT_RAWPK:
+ if (rawpk_key == NULL || rawpk.type != GNUTLS_CRT_RAWPK) {
log_msg
- (stdout, "- Could not find a suitable key to send to server\n");
+ (stdout, "- Could not find a suitable key to send to server\n");
return -1;
}
- *pcert_length = x509_crt_size;
- *pcert = x509_crt;
- }
+ *pkey = rawpk_key;
+ *pcert = &rawpk;
+ *pcert_length = 1;
+ break;
+ default:
+ log_msg(stdout, "- Could not retrieve unsupported certificate type %s.\n",
+ gnutls_certificate_type_get_name(cert_type));
+ return -1;
}
log_msg(stdout, "- Successfully sent %u certificate(s) to server.\n",
@@ -1570,6 +1633,12 @@ static void cmd_parser(int argc, char **argv)
if (HAVE_OPT(X509CERTFILE))
x509_certfile = OPT_ARG(X509CERTFILE);
+ if (HAVE_OPT(RAWPKKEYFILE))
+ rawpk_keyfile = OPT_ARG(RAWPKKEYFILE);
+
+ if (HAVE_OPT(RAWPKFILE))
+ rawpk_file = OPT_ARG(RAWPKFILE);
+
if (HAVE_OPT(PSKUSERNAME))
psk_username = OPT_ARG(PSKUSERNAME);
@@ -1841,7 +1910,8 @@ static void init_global_tls_stuff(void)
}
}
- load_keys();
+ load_x509_keys();
+ load_rawpk_keys();
#ifdef ENABLE_SRP
if (srp_username && srp_passwd) {
diff --git a/src/common.c b/src/common.c
index 433e31ac90..6a0c00ebaa 100644
--- a/src/common.c
+++ b/src/common.c
@@ -182,6 +182,56 @@ print_x509_info(gnutls_session_t session, FILE *out, int flag, int print_cert, i
}
}
+static void
+print_rawpk_info(gnutls_session_t session, FILE *out, int flag, int print_cert, int print_crt_status)
+{
+ gnutls_pcert_st pk_cert;
+ gnutls_pk_algorithm_t pk_algo;
+ const gnutls_datum_t *cert_list;
+ unsigned int cert_list_size = 0;
+ int ret;
+
+ cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
+ if (cert_list_size == 0) {
+ if (print_crt_status)
+ fprintf(stderr, "No certificates found!\n");
+ return;
+ }
+
+ log_msg(out, "- Certificate type: Raw Public Key\n");
+ log_msg(out, "- Got %d Raw public-key(s).\n",
+ cert_list_size);
+
+
+ ret = gnutls_pcert_import_rawpk_raw(&pk_cert, cert_list, GNUTLS_X509_FMT_DER, 0, 0);
+ if (ret < 0) {
+ fprintf(stderr, "Decoding error: %s\n",
+ gnutls_strerror(ret));
+ return;
+ }
+
+ pk_algo = gnutls_pubkey_get_pk_algorithm(pk_cert.pubkey, NULL);
+
+ log_msg(out, "- Raw pk info:\n");
+ log_msg(out, " - PK algo: %s\n", gnutls_pk_algorithm_get_name(pk_algo));
+
+ if (print_cert) {
+ gnutls_datum_t pem;
+
+ ret = gnutls_pubkey_export2(pk_cert.pubkey, GNUTLS_X509_FMT_PEM, &pem);
+ if (ret < 0) {
+ fprintf(stderr, "Encoding error: %s\n",
+ gnutls_strerror(ret));
+ return;
+ }
+
+ log_msg(out, "\n%s\n", (char*)pem.data);
+
+ gnutls_free(pem.data);
+ }
+
+}
+
/* returns false (0) if not verified, or true (1) otherwise
*/
int cert_verify(gnutls_session_t session, const char *hostname, const char *purpose)
@@ -543,10 +593,13 @@ void print_cert_info2(gnutls_session_t session, int verbose, FILE *out, int prin
print_crt_status = 1;
}
- switch (gnutls_certificate_type_get(session)) {
+ switch (gnutls_certificate_type_get2(session, GNUTLS_CTYPE_PEERS)) {
case GNUTLS_CRT_X509:
print_x509_info(session, out, flag, print_cert, print_crt_status);
break;
+ case GNUTLS_CRT_RAWPK:
+ print_rawpk_info(session, out, flag, print_cert, print_crt_status);
+ break;
default:
break;
}
diff --git a/src/serv-args.def b/src/serv-args.def
index a2e9d1c6f8..996fbe36ba 100644
--- a/src/serv-args.def
+++ b/src/serv-args.def
@@ -250,6 +250,45 @@ flag = {
};
flag = {
+ name = rawpkkeyfile;
+ arg-type = string;
+ descrip = "Private key file (PKCS #8 or PKCS #12) or PKCS #11 URL to use";
+ doc = "Specify the private key file or URI to use; it must correspond to
+the raw public-key specified in --rawpkfile. Multiple key pairs
+can be specified with this option and in that case each occurrence of keyfile
+must be followed by the corresponding rawpkfile or vice-versa.
+
+In order to instruct the application to negotiate raw public keys one
+must enable the respective certificate types via the priority strings (i.e. CTYPE-CLI-*
+and CTYPE-SRV-* flags).
+
+Check the GnuTLS manual on section ``Priority strings'' for more
+information on how to set certificate types.";
+ stack-arg;
+ max = NOLIMIT;
+};
+
+flag = {
+ name = rawpkfile;
+ arg-type = string;
+ descrip = "Raw public-key file to use";
+ doc = "Specify the raw public-key file to use; it must correspond to
+the private key specified in --rawpkkeyfile. Multiple key pairs
+can be specified with this option and in that case each occurrence of keyfile
+must be followed by the corresponding rawpkfile or vice-versa.
+
+In order to instruct the application to negotiate raw public keys one
+must enable the respective certificate types via the priority strings (i.e. CTYPE-CLI-*
+and CTYPE-SRV-* flags).
+
+Check the GnuTLS manual on section ``Priority strings'' for more
+information on how to set certificate types.";
+ stack-arg;
+ max = NOLIMIT;
+ flags-must = rawpkkeyfile;
+};
+
+flag = {
name = srppasswd;
arg-type = file;
file-exists = yes;
@@ -478,11 +517,24 @@ gnutls-serv --http --priority NORMAL:+ECDHE-PSK:+PSK \
--pskpasswd psk-passwd.txt
@end example
+If you want a server with support for raw public-keys we can also add these
+credentials. Note however that there is no identity information linked to these
+keys as is the case with regular x509 certificates. Authentication must be done
+via different means. Also we need to explicitly enable raw public-key certificates
+via the priority strings.
+
+@example
+gnutls-serv --http --priority NORMAL:+CTYPE-CLI-RAWPK:+CTYPE-SRV-RAWPK \
+ --rawpkfile srv.rawpk.pem \
+ --rawpkkeyfile srv.key.pem
+@end example
+
+
Finally, we start the server with all the earlier parameters and you
get this command:
@example
-gnutls-serv --http --priority NORMAL:+PSK:+SRP \
+gnutls-serv --http --priority NORMAL:+PSK:+SRP:+CTYPE-CLI-RAWPK:+CTYPE-SRV-RAWPK \
--x509cafile x509-ca.pem \
--x509keyfile x509-server-key.pem \
--x509certfile x509-server.pem \
@@ -490,7 +542,9 @@ gnutls-serv --http --priority NORMAL:+PSK:+SRP \
--x509certfile x509-server-ecc.pem \
--srppasswdconf srp-tpasswd.conf \
--srppasswd srp-passwd.txt \
- --pskpasswd psk-passwd.txt
+ --pskpasswd psk-passwd.txt \
+ --rawpkfile srv.rawpk.pem \
+ --rawpkkeyfile srv.key.pem
@end example
_EOF_;
};
diff --git a/src/serv.c b/src/serv.c
index cc68abb509..60b02f6983 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -76,6 +76,10 @@ const char *x509_cafile = NULL;
const char *dh_params_file = NULL;
const char *x509_crlfile = NULL;
const char *priorities = NULL;
+const char **rawpk_keyfile = NULL;
+const char **rawpk_file = NULL;
+unsigned rawpk_keyfile_size = 0;
+unsigned rawpk_file_size = 0;
const char **ocsp_responses = NULL;
unsigned ocsp_responses_size = 0;
@@ -382,7 +386,7 @@ gnutls_session_t initialize_session(int dtls)
const char *err;
gnutls_datum_t alpn[MAX_ALPN_PROTOCOLS];
unsigned alpn_size;
- unsigned flags = GNUTLS_SERVER | GNUTLS_POST_HANDSHAKE_AUTH;
+ unsigned flags = GNUTLS_SERVER | GNUTLS_POST_HANDSHAKE_AUTH | GNUTLS_ENABLE_RAWPK;
if (dtls)
flags |= GNUTLS_DATAGRAM;
@@ -556,7 +560,7 @@ static char *peer_print_info(gnutls_session_t session, int *ret_length,
return http_buffer;
}
- if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {
+ if (gnutls_certificate_type_get2(session, GNUTLS_CTYPE_CLIENT) == GNUTLS_CRT_X509) {
const gnutls_datum_t *cert_list;
unsigned int cert_list_size = 0;
@@ -675,10 +679,10 @@ static char *peer_print_info(gnutls_session_t session, int *ret_length,
}
if (gnutls_auth_get_type(session) == GNUTLS_CRD_CERTIFICATE &&
- gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
+ gnutls_certificate_type_get2(session, GNUTLS_CTYPE_CLIENT) != GNUTLS_CRT_X509) {
tmp =
gnutls_certificate_type_get_name
- (gnutls_certificate_type_get(session));
+ (gnutls_certificate_type_get2(session, GNUTLS_CTYPE_CLIENT));
if (tmp == NULL)
tmp = str_unknown;
snprintf(tmp_buffer, tmp_buffer_size,
@@ -1178,6 +1182,7 @@ int main(int argc, char **argv)
exit(1);
}
+ /* X509 credentials */
if (x509_cafile != NULL) {
if ((ret = gnutls_certificate_set_x509_trust_file
(cert_cred, x509_cafile, x509ctype)) < 0) {
@@ -1215,6 +1220,25 @@ int main(int argc, char **argv)
cert_set = 1;
}
}
+
+ /* Raw public-key credentials */
+ if (rawpk_file_size > 0 && rawpk_keyfile_size > 0) {
+ for (i = 0; i < rawpk_keyfile_size; i++) {
+ ret = gnutls_certificate_set_rawpk_key_file(cert_cred, rawpk_file[i],
+ rawpk_keyfile[i],
+ x509ctype,
+ NULL, 0, NULL, 0,
+ 0, 0);
+ if (ret < 0) {
+ fprintf(stderr, "Error reading '%s' or '%s'\n",
+ rawpk_file[i], rawpk_keyfile[i]);
+ GERR(ret);
+ exit(1);
+ } else {
+ cert_set = 1;
+ }
+ }
+ }
if (cert_set == 0) {
fprintf(stderr,
@@ -1808,12 +1832,29 @@ static void cmd_parser(int argc, char **argv)
if (x509_certfile_size != x509_keyfile_size) {
fprintf(stderr, "The certificate number provided (%u) doesn't match the keys (%u)\n",
x509_certfile_size, x509_keyfile_size);
+ exit(1);
}
if (HAVE_OPT(X509CAFILE))
x509_cafile = OPT_ARG(X509CAFILE);
if (HAVE_OPT(X509CRLFILE))
x509_crlfile = OPT_ARG(X509CRLFILE);
+
+ if (HAVE_OPT(RAWPKKEYFILE)) {
+ rawpk_keyfile = STACKLST_OPT(RAWPKKEYFILE);
+ rawpk_keyfile_size = STACKCT_OPT(RAWPKKEYFILE);
+ }
+
+ if (HAVE_OPT(RAWPKFILE)) {
+ rawpk_file = STACKLST_OPT(RAWPKFILE);
+ rawpk_file_size = STACKCT_OPT(RAWPKFILE);
+ }
+
+ if (rawpk_file_size != rawpk_keyfile_size) {
+ fprintf(stderr, "The number of raw public-keys provided (%u) doesn't match the number of corresponding private keys (%u)\n",
+ rawpk_file_size, rawpk_keyfile_size);
+ exit(1);
+ }
if (HAVE_OPT(SRPPASSWD))
srp_passwd = OPT_ARG(SRPPASSWD);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e056e3a951..c462b54e41 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -505,7 +505,7 @@ dist_check_SCRIPTS += system-override-sig-hash.sh system-override-versions.sh sy
system-override-kx.sh
endif
-dist_check_SCRIPTS += gnutls-cli-self-signed.sh gnutls-cli-invalid-crl.sh
+dist_check_SCRIPTS += gnutls-cli-self-signed.sh gnutls-cli-invalid-crl.sh gnutls-cli-rawpk.sh
if ENABLE_PKCS11
dist_check_SCRIPTS += p11-kit-trust.sh testpkcs11.sh certtool-pkcs11.sh
diff --git a/tests/gnutls-cli-rawpk.sh b/tests/gnutls-cli-rawpk.sh
new file mode 100755
index 0000000000..8b60da780e
--- /dev/null
+++ b/tests/gnutls-cli-rawpk.sh
@@ -0,0 +1,320 @@
+#!/bin/sh
+
+# Copyright (C) 2019 Tom Vrancken (dev@tomvrancken.nl)
+#
+# Author: Tom Vrancken
+# Nikos Mavrogiannopoulos
+#
+# This file is part of GnuTLS.
+#
+# GnuTLS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# GnuTLS is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>
+
+srcdir="${srcdir:-.}"
+SERV="${SERV:-../src/gnutls-serv${EXEEXT}}"
+CLI="${CLI:-../src/gnutls-cli${EXEEXT}}"
+unset RETCODE
+CERTFILE1=rawpk-script1.$$.pem.tmp
+CERTFILE2=rawpk-script2.$$.pem.tmp
+
+TMPFILE=rawpk-script.$$.log
+
+if ! test -x "${SERV}"; then
+ exit 77
+fi
+
+if ! test -x "${CLI}"; then
+ exit 77
+fi
+
+if test "${WINDIR}" != ""; then
+ exit 77
+fi
+
+if ! test -z "${VALGRIND}"; then
+ VALGRIND="${LIBTOOL:-libtool} --mode=execute ${VALGRIND} --error-exitcode=15"
+fi
+
+SERV="${SERV} -q"
+
+. "${srcdir}/scripts/common.sh"
+
+echo "Checking whether we can connect with raw public-keys"
+
+cat <<__EOF__ >${CERTFILE1}
+-----BEGIN CERTIFICATE-----
+MIIEXDCCAsSgAwIBAgIIWkcxay17JgYwDQYJKoZIhvcNAQELBQAwQjEaMBgGA1UE
+AxMRdGVzdC1hbGwtZGVmYXVsdHMxCzAJBgNVBAYTAkFUMRcwFQYKCZImiZPyLGQB
+GRYHYmVidC5kZTAeFw0xNzEyMzAwNjI1NDhaFw0xOTEyMjAwNjI1NTFaMEIxGjAY
+BgNVBAMTEXRlc3QtYWxsLWRlZmF1bHRzMQswCQYDVQQGEwJBVDEXMBUGCgmSJomT
+8ixkARkWB2JlYnQuZGUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCv
+M1Y+Q4goCtHi3SLHTBQ14LS6NI4UbEa8YZFfaOfmOOufzwdNUntUkSA2PPS7mQ55
+SN+Sdel1x4f4EjfxCWhj0j0Y26OmJS+wYNz3oOdoKThLq4Mn5SumO7mhU684mZTi
+EP2qrxFeYvQqQBdjv8rfP2LJ+RsB/3CiwWdkx4qeudoSUCqzWo8e6K2ul0JJuk+Z
+fvqkPpDl+cVTikmxNwqjAt4Ef9oiT1YjUIBUae+RCdNZEa6d2AhW+4bD+vl0Pci+
+EBPzhLeR8iYuIEX66Tpv8AUvv412SuvVZbizGP5EDH4gkWtNWem9yNPCHA9rBqrC
+6Nib4TPPLm1aN4mJyLdoQ1gD0STHcFADo+1H0JDywzxlgkks9cj5sQmApO7+AuGs
+JoUDAp4g4LHnBw/H/5esVta5Pn7GThKwu7PRY0Y59ZKQrT5deXm9TeySdav+9wR/
+5aiIZpAsAM5zWnN5qAP58Xl+pa0qN48GPcwmAsa4Zh9ehGhzR00MFHD3V8i0rFcC
+AwEAAaNWMFQwDAYDVR0TAQH/BAIwADAUBgNVHREEDTALgglsb2NhbGhvc3QwDwYD
+VR0PAQH/BAUDAwegADAdBgNVHQ4EFgQU0tGobgnLApQRxvbzIhOT2gAUQAYwDQYJ
+KoZIhvcNAQELBQADggGBAHmqS1jOY5J9ad63aFXaei0lZhTnYCsFOGWuyLqZtz9K
+21n0V8WVXeGmBjXkYNS3LCwPwFqKsp3vhsh4Hw5cyKkfQIri0HlWASYiJCPZxDLH
+odVJSOPV65Q+gmhT/ltHK5CW4DJ2Gy82vPEFqw3+Kca28IJ0m2wr0FlhOCvnHUa7
+GMS/+SdaMbsi1Eui0wUG/xWw8/2kY26IjhDJHrsTUjpYQ+vTy5oOjyq6Yf15Orjw
+tJTwGgRcfoiBGhzMgTbUfFCO33L6f0u/WR/sI7DYDO/6JW1USnTrMuwEL6/jMNAw
+QPl6irVOy/UwcIcLIBw8ta5cR8JVbhYuV7cUT9qDVwCOqotkwjDVsH2aztLLLr5d
+ywMQXvXh2UI4jSujWf9vYY3F7GkDGy/cOwVprZoAe0mXwvuCvDyNZqXJTxKtq/w9
+ZwOveNtNeXHOJljseNXLQPCfCcQ6mEUNjqwo2eDqH0OtJsQRN2CAUsn+YBnAALrv
+P4J46RbB7bnzQ9kHiv6KuA==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4gIBAAKCAYEArzNWPkOIKArR4t0ix0wUNeC0ujSOFGxGvGGRX2jn5jjrn88H
+TVJ7VJEgNjz0u5kOeUjfknXpdceH+BI38QloY9I9GNujpiUvsGDc96DnaCk4S6uD
+J+Urpju5oVOvOJmU4hD9qq8RXmL0KkAXY7/K3z9iyfkbAf9wosFnZMeKnrnaElAq
+s1qPHuitrpdCSbpPmX76pD6Q5fnFU4pJsTcKowLeBH/aIk9WI1CAVGnvkQnTWRGu
+ndgIVvuGw/r5dD3IvhAT84S3kfImLiBF+uk6b/AFL7+Ndkrr1WW4sxj+RAx+IJFr
+TVnpvcjTwhwPawaqwujYm+Ezzy5tWjeJici3aENYA9Ekx3BQA6PtR9CQ8sM8ZYJJ
+LPXI+bEJgKTu/gLhrCaFAwKeIOCx5wcPx/+XrFbWuT5+xk4SsLuz0WNGOfWSkK0+
+XXl5vU3sknWr/vcEf+WoiGaQLADOc1pzeagD+fF5fqWtKjePBj3MJgLGuGYfXoRo
+c0dNDBRw91fItKxXAgMBAAECggGACEz1XBPVApioowf5Gtom5vqTdXMB/EO5AjnZ
+Kl0NB6JQv4yOewJaZ4JMtWUj7zNsNSDXvtepTPQ8I+uxDNF2SaxvSps1YKzIWqHs
+NitAa3Xwfd1NZHl+HO0deWA+n/7ex+soKYsL1p33lXzd3tL6aKNXKdyMhAa3Lm7d
+WDAACE8j3tQ/ganbuAosGGaANIAIP2x9sYRpVwwDZlbZ8PR7o4eCP1JTYmbB3QB2
+ZAl02TlO8xxcWowesQhPtT9RzEkVAqKC8EULvdvY4b5OFQxkmLDQYv/c+HqetKQ7
+/ewkp/PRndGJ+k0Nebr6G2yIj6D3pN1YfquTfwGMi2yTZh4hQgkXi2WP8KRRgpIU
+iUfsSA9wZ4s2WNTMPQANfztP2cUVSPHW8UlTM373qLc3TGDuxmR+h7vqeQ0kVakL
+vhQ+HkEvQ2yrxc3m3g1BDoM3/ShHx7IskBqeX3L3Ad7pZpu/Q+Y/z5tVtDUY42LW
+DTeB/mKZcKZLK0BCz+o4L9KPceQxAoHBANZfiYobRMXmT0yOfTj68JWR/g7B9XBV
+rQ03xKxpI9mVckAT52xPJCUsSRVyUbJDs4hnBOe/y3Uk3jejDoCoI1h8ZyKCwhHq
+Py0GFCmB/AzeYRchD0TY1H69r4PZjloGX6SWlha784ajcJspoV5TYuLkhOVDFsA/
+R4Yu4irkQ2hugPT/q3ysiDXgQSB9+SqCYGUfMbadC+Ppm5+egTF8uyHJeV4YQ/Jr
+CNvsA6wxnONg0gbhsd3wLixjzz8jfJ1N6QKBwQDROIg0JumHkO5pl7wdKUSRx43y
+OOBNOf3KqGsRT8EDnRcepJy1gdg/SIp5/MRi+PJLqDfLNcIr8gQhanJnZ160UFVX
+8IhJ02Of/NGrFvctURJ3Dt63SspIoi6Yt/7Z1IQrvxpHsD3eaNtqywtYF59yhkdB
+hKomPn++LraDyXHqu0xCuO9te61ZP2haHhPsGI1Z2fuep5dnZJRLNR9BZWuqmkv9
+qj34ftm6Np8qSpdp9GotsRL2WIRaNF/sP+Z6gD8CgcAF7VZMLzzTi+6dW0MzFB0a
+xZKUreAvXu8N8oDJk46eMXebNfGsGPQS4wqSQTrpBt4r401Law4hCwfp2eRIwl1X
+0Pi5B4x+Gk/s2sIr86AYav2cOhnF+YjGiFAWASnia1Kxpkg4ELJHArXWVGxVw1B0
+nYTfId+7KQS9PQab0PvcI1IFdBw1sj+B3dVvJIyDFF+97ALf3a+6eXcIDsXbrGsw
+H/XvGBSo2zS/f+MKG8UOtFqaPhtA26crKwdL45tKbiECgcAO468NxxcnhrDw4tOI
+X795gHIhotqTpGTjX0j/WmWqFCvpCl38rNju6AKy28I+KOlVaQtPcuv2pKqWljS+
+FyUuP+lS8NNCLcERSbTCMEg2+WYPAwfmk3QB50jZpX6FkhI16su7/lbo1R2IZBrS
+khvO0q+Pghl5z0jYCAsFJfjtc5bhyLeBWyPjDhgnEazpSHYGxvSZPeQQf5/uGkG3
+LbiT05dE3jC61ow4LFr3b4eHCtXjmo526aXBpaiN754/aZECgcBAK3aOmgwI5vw4
+7a94mWffD0LzHl26D2ayXHvXmzjTOv7hsvilUTitdlqNrlZ3AxOWX1nGUcxdUwPT
+Ri1h4yIi28MvTjBD+wvXOGwmINGkBFWKIzkhh/bvbzQsuRSmG09JF1tBJjE6oCUs
+5ZJ7v0NCtg7yGOY8ciWIpahFc796prk17ZgIn/t0hebc9ZTaIat5QKbr4SWLZJEl
+i2yISkQxkJZp8sTwSlIGZSBpuZcDq9AdUjan1WhGgl4hpHpjr3Y=
+-----END RSA PRIVATE KEY-----
+__EOF__
+
+cat <<__EOF__ >${CERTFILE2}
+-----BEGIN PUBLIC KEY-----
+MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtfCQ/U13p076UUEggNm8
+mI+bEilHrvKiyZpY/NZ2JYhmU+n0ChuH6XweXuiuW2gKR/Fl0vpGAxhugQAR3lMS
+0XJZjg4z1gFP0BMeR0YYQuWe2Gfg24fUNPluHCf+dJMHAadIVKyUvVKFPDTwu6yU
+lVafn0uoMme8b51yAwQAeXGOJnTFHSaRhuDWAokaTsW0kdAr5FSxMadSTVuDNSav
+ic6qSUimJvPjT+URzpIjy/2MG8aj00At1MSj8sC/g5JuBvMKXe4mg6/Xd1YsP9gT
+GhpfuBzwt+H4HDm4MzwNqdWNJ7pAhdcBOztqsScZJUqmGT742Fr0OjYYOFvHYLcx
+SMD65huLlKTiQwg0HocVFA/VilLLV65cW+AUakr0YCXKyucPz4omVy/RINi663Bn
+UyIR3pkOwbr71syuiU1S9cMnG0BxHsPmbvgaYttnCwp0cexB8MrJNJv5FcKLOGUL
+MMCvSIT7elYwGN2p5gtAg1RLmyVvubTmkOAmxAgybgqHAgMBAAE=
+-----END PUBLIC KEY-----
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4gIBAAKCAYEAtfCQ/U13p076UUEggNm8mI+bEilHrvKiyZpY/NZ2JYhmU+n0
+ChuH6XweXuiuW2gKR/Fl0vpGAxhugQAR3lMS0XJZjg4z1gFP0BMeR0YYQuWe2Gfg
+24fUNPluHCf+dJMHAadIVKyUvVKFPDTwu6yUlVafn0uoMme8b51yAwQAeXGOJnTF
+HSaRhuDWAokaTsW0kdAr5FSxMadSTVuDNSavic6qSUimJvPjT+URzpIjy/2MG8aj
+00At1MSj8sC/g5JuBvMKXe4mg6/Xd1YsP9gTGhpfuBzwt+H4HDm4MzwNqdWNJ7pA
+hdcBOztqsScZJUqmGT742Fr0OjYYOFvHYLcxSMD65huLlKTiQwg0HocVFA/VilLL
+V65cW+AUakr0YCXKyucPz4omVy/RINi663BnUyIR3pkOwbr71syuiU1S9cMnG0Bx
+HsPmbvgaYttnCwp0cexB8MrJNJv5FcKLOGULMMCvSIT7elYwGN2p5gtAg1RLmyVv
+ubTmkOAmxAgybgqHAgMBAAECggGAAoHBDaxulKCS9GGoV/4oChYYdeSZt0Bim9KD
+nWA7GoNJnahgk28TrVTnejlMhbfmRF2AIKsQIeTJSP++P0j3vmkL8NgjQLSd6+kH
+hsXhebJ+QM8VmxDBDMXPDZZDfEm2VACBD6GdHwqvCUhVdNCI75HU+zXoqGEjiIor
+0vzQINw+sCr1uFQatzgL2tcWxLUWqteqcyfzlRKQIL69DRNuYcC2OfJFT84WeLhY
+SXdcBOiGcK+I/FUrDH51H9gmC2MOGRnWsB0daTMUraJ2or9TCH3PrULGshlMuMzs
+aMnecKf79DBKj4BO/x2VFo2rq7H2uPczv6+6bHapjagMtxWcogFceUqjNXnnWyiK
+8oH7iin2PnIDUX+ks3YwQ9hpbJIy3V9UF2J6PgyaKDGfyT2mVoLmTbD0IpPlpF7G
+xGdUCEVB3AqB1nA8KE6vim8BKktInVM1fMylR/n0jj7mSK1oqqH76S1kmfH4sla/
+KetthtIy2IVnljsgIbrABp1A5gd5AoHBANnDTBXsDMA9VE+ArOB8WNkzT1gl44QO
+cKHLJQ2sTGNrSA5m9xjGgcmOogJTw5wxz5vPqqKol0xpIEHIAmftREt1qpem7+Gi
+CNslPzHR9PYe5XGAV3bgFe4iL2Q9dD+rOx5/EK9GroqNtNNSEzcckAu414whIazb
+sNhFcsCd1Yn6kadfeMRdt8MQ4sgQWWxON1gjOynbx5lHuLqZs8SYUJ6v3RRn7ZXv
+cGI9NeuAxHDpZPqhnpsFyfWbLFHJIUaaVQKBwQDV4vmL0gpdiBfKPS6D8OkVSayQ
+CBLoaq9sW4VWPpv83lTtB6nf6zfhxs7ho+0aosieV5KQkJho0KY5mHvKfFO5ih1g
+ADtG90X37tVxHyQLXxqBpOBQO12lVsc/ILO6hqDOFoAzGMPpT43CrF2/09GQM/uA
+Uo2s0Z9mvMalybtWcGDrsfGQhuY5soeEho9gziAC3zFMtSZJDBd5pf+Ls2ZcBDFp
+5GrIvVFYGIOqbSheeSuYyhgZGHiAXtibRkroZWsCgcAeCMiisWbk0NCjEn1FjQD4
+HBKSds9VdGRmfE1FAIGcqLxMeDkWarKV6R1BMupkzZ3zwIWpX5VWjZ1MVVi3msrz
+mWwI9JZbSWztRMrdhTbDB2nf6LKni6qaqI5exfcVnPlPcHkNo7MJGxhYmRZbYI4h
+f8IC6sLpQ3e1rIZyOJKuMCgMrKdMdhyVQ+vzagXbYUJS3rEXSd/SrUi2O+LGd7eO
+23Sjjt3+8wJOGmEodR8i753kz4u/l+HOBTPsp8/2G+0CgcBD72Pz1TMVojRsOCKe
+JdbivBPja60VxU0Szb78Nca1+qhe4SBDzyJgxBTR9o9I9otiP859vG+sWxlxEc2/
+8t1lAUlzRJ+PWtsOdP22gH2iXwK8SvI0iaak7Xs7wddUV46b5umxURxo7qvIOZdN
+ZqoZc2leyNnXGn3W0/8EiZ7HRcqDEnH3xeE6UkpY/aRsywu/3cR66M7QRNbv/Jm+
+daz9bReE2thQClHb+W1YpHM+Dp6aWRZuYidkHrwOFbWVOyECgcBSsN2yk6eV9pmQ
+p4yHZcJ6QdCHm1KqdAMK/pSurjSf3+281mkxTAkZBGLl2QwZKEBTapKZhvsoC3+d
+fpk1UZneP1g9PHoRS7rooQV5baUj0sOd3RyD3iylb1soyyEKWxbzdiS/nswYbwCV
+LMvucEsmS5aIfIUo4ntlNs3bVZqLdh0BAG9+WuimpYyp7pxrvuj2FM+gwbwDZvto
+O2/1wSKkPX2klUKg1hNNELJAXfxHLw2+NvV9x4rDiu5xJHgDCD0=
+-----END RSA PRIVATE KEY-----
+__EOF__
+
+trap "cleanup" EXIT QUIT
+
+cleanup()
+{
+ kill ${PID} >/dev/null 2>&1
+ rm -f ${CERTFILE1} ${CERTFILE2}
+
+}
+
+echo " * testing server X.509, client RAW"
+
+eval "${GETPORT}"
+launch_server $$ --echo --x509keyfile ${CERTFILE1} --x509certfile ${CERTFILE1} --priority NORMAL:-CTYPE-CLI-ALL:+CTYPE-CLI-RAWPK --require-client-cert
+PID=$!
+wait_server ${PID}
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:-CTYPE-CLI-ALL:+CTYPE-CLI-RAWPK --no-ca-verification --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:+CTYPE-CLI-ALL --no-ca-verification --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL --no-ca-verification --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} >${TMPFILE} 2>&1 </dev/null
+grep "Certificate is required" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake has unexpectedly succeeded. See ${TMPFILE} for details."
+ exit 1
+fi
+
+kill ${PID}
+wait
+
+echo " * testing server RAW, client none"
+eval "${GETPORT}"
+launch_server $$ --echo --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} --priority NORMAL:+CTYPE-SRV-RAWPK
+PID=$!
+wait_server ${PID}
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:-CTYPE-SRV-ALL:+CTYPE-SRV-RAWPK --no-ca-verification >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:+CTYPE-SRV-ALL --no-ca-verification >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if test $? = 0;then
+ echo "Handshake has unexpectedly succeeded. See ${TMPFILE} for details."
+ exit 1
+fi
+
+
+kill ${PID}
+wait
+
+echo " * testing server RAW, client RAW"
+eval "${GETPORT}"
+launch_server $$ --echo --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} --priority NORMAL:+CTYPE-SRV-RAWPK:-CTYPE-CLI-ALL:+CTYPE-CLI-RAWPK --require-client-cert
+PID=$!
+wait_server ${PID}
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:-CTYPE-ALL:+CTYPE-SRV-RAWPK:+CTYPE-CLI-RAWPK --no-ca-verification --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:+CTYPE-SRV-ALL:+CTYPE-CLI-ALL --no-ca-verification --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if test $? = 0;then
+ echo "Handshake has unexpectedly succeeded. See ${TMPFILE} for details."
+ exit 1
+fi
+
+
+kill ${PID}
+wait
+
+echo " * testing server X.509+RAW, client none"
+
+eval "${GETPORT}"
+launch_server $$ --echo --x509keyfile ${CERTFILE1} --x509certfile ${CERTFILE1} --rawpkkeyfile ${CERTFILE2} --rawpkfile ${CERTFILE2} --priority NORMAL:+CTYPE-SRV-RAWPK
+PID=$!
+wait_server ${PID}
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:-CTYPE-SRV-ALL:+CTYPE-SRV-RAWPK --no-ca-verification >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:-CTYPE-SRV-ALL:+CTYPE-SRV-X509 --no-ca-verification >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL:+CTYPE-SRV-ALL --no-ca-verification >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --priority NORMAL --no-ca-verification >${TMPFILE} 2>&1 </dev/null
+grep "Handshake was completed" ${TMPFILE}
+if ! test $? = 0;then
+ echo "Handshake failed. See ${TMPFILE} for details."
+ exit 1
+fi
+
+kill ${PID}
+wait
+
+
+rm -f ${TMPFILE} ${CERTFILE1} ${CERTFILE2}
+
+exit 0