]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Implemented raw public key support for gnutls-serv application.
authorTom Vrancken <dev@tomvrancken.nl>
Tue, 27 Aug 2019 15:10:04 +0000 (17:10 +0200)
committerTom Vrancken <dev@tomvrancken.nl>
Fri, 4 Oct 2019 21:33:16 +0000 (23:33 +0200)
Signed-off-by: Tom Vrancken <dev@tomvrancken.nl>
src/serv-args.def
src/serv.c

index a2e9d1c6f833989f1d29aaba5cff51d322358a5f..996fbe36ba27a46855edf46979edc46f11fdc99c 100644 (file)
@@ -249,6 +249,45 @@ flag = {
     deprecated;
 };
 
+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;
@@ -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_;
 };
index cc68abb5095ea3d46188f932933e49070c948e9d..60b02f69836a0ac6b2fc97ff6206d4d9ab166baa 100644 (file)
@@ -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);