summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Vrancken <dev@tomvrancken.nl>2019-08-26 17:12:40 +0200
committerTom Vrancken <dev@tomvrancken.nl>2019-10-04 23:33:16 +0200
commit1bdcceac380cbfe4fa78b3dd3dc3513663fab972 (patch)
treef3005c8af7f25b22986e1041b64184f248ec9267 /src
parent5d64441a3f73379c93b65efe69e6e31e830c2d30 (diff)
downloadgnutls-1bdcceac380cbfe4fa78b3dd3dc3513663fab972.tar.gz
Implemented raw public key support for gnutls-cli application.
Signed-off-by: Tom Vrancken <dev@tomvrancken.nl>
Diffstat (limited to 'src')
-rw-r--r--src/cli-args.def49
-rw-r--r--src/cli.c172
-rw-r--r--src/common.c55
3 files changed, 223 insertions, 53 deletions
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;
}