summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/Makefile4
-rw-r--r--usr/src/lib/libipsecutil/Makefile.com9
-rw-r--r--usr/src/lib/libipsecutil/common/ipsec_libssl_setup.c326
-rw-r--r--usr/src/lib/libipsecutil/common/ipsec_util.c28
-rw-r--r--usr/src/lib/libipsecutil/common/ipsec_util.h16
-rw-r--r--usr/src/lib/libkmf/include/kmfapi.h2
-rw-r--r--usr/src/lib/libkmf/libkmf/Makefile.com5
-rw-r--r--usr/src/lib/libkmf/libkmf/common/mapfile-vers2
-rw-r--r--usr/src/lib/libkmf/libkmf/common/rdn_parser.c218
9 files changed, 262 insertions, 348 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 654a35dd5d..bdff519dd6 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -635,9 +635,9 @@ libinetsvc: libscf
libinstzones: libzonecfg libcontract
libipadm: libinetutil libdlpi libdhcpagent libdladm libsecdb libdhcputil
libipmp: libinetutil
-libipsecutil: libtecla libtsol
+libipsecutil: libtecla libtsol libkmf
libiscsit: libstmf libuuid
-libkmf: libcryptoutil pkcs11
+libkmf: libcryptoutil pkcs11 libcustr
libkvm: ../cmd/sgs/libelf
libldap5: libsasl
libmapid: libresolv2 libscf
diff --git a/usr/src/lib/libipsecutil/Makefile.com b/usr/src/lib/libipsecutil/Makefile.com
index de17899c49..aef11c9c76 100644
--- a/usr/src/lib/libipsecutil/Makefile.com
+++ b/usr/src/lib/libipsecutil/Makefile.com
@@ -20,11 +20,12 @@
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+# Copyright 2018, Joyent, Inc.
#
LIBRARY = libipsecutil.a
VERS = .1
-OBJECTS = ipsec_util.o algs.o ipsec_libssl_setup.o
+OBJECTS = ipsec_util.o algs.o
include ../../Makefile.lib
@@ -32,14 +33,16 @@ LIBS += $(DYNLIB) $(LINTLIB)
SRCDIR = ../common
+BERDIR = $(SRC)/lib/libkmf/ber_der/inc
+
$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
-LDLIBS += -ltecla -lsocket -lnsl -lc
+LDLIBS += -ltecla -lsocket -lnsl -lc -lkmf -lkmfberder
LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
lint := LAZYLIBS = -ltsol
LDLIBS += $(LAZYLIBS)
CFLAGS += $(CCVERBOSE)
-CPPFLAGS += -I$(SRCDIR)
+CPPFLAGS += -I$(SRCDIR) -I$(BERDIR)
CERRWARN += -_gcc=-Wno-unused-function
CERRWARN += -_gcc=-Wno-uninitialized
diff --git a/usr/src/lib/libipsecutil/common/ipsec_libssl_setup.c b/usr/src/lib/libipsecutil/common/ipsec_libssl_setup.c
deleted file mode 100644
index e63c1b51be..0000000000
--- a/usr/src/lib/libipsecutil/common/ipsec_libssl_setup.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Thread setup portions of this code derived from
- * OpenSSL 0.9.x file mt/mttest.c examples
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <libintl.h>
-#include <synch.h>
-#include <thread.h>
-#include <dlfcn.h>
-#include <openssl/lhash.h>
-#include <openssl/crypto.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include "ipsec_util.h"
-
-/* OpenSSL function pointers */
-static X509_NAME *(*d2i_X509_NAME_fn)() = NULL;
-static int (*X509_NAME_print_ex_fp_fn)() = NULL;
-static char *(*ERR_get_error_fn)() = NULL;
-static char *(*ERR_error_string_fn)() = NULL;
-static void (*SSL_load_error_strings_fn)() = NULL;
-static void (*ERR_free_strings_fn)() = NULL;
-static void (*CRYPTO_set_locking_callback_fn)() = NULL;
-static void (*CRYPTO_set_id_callback_fn)() = NULL;
-static void (*X509_NAME_free_fn)() = NULL;
-static int (*CRYPTO_num_locks_fn)() = NULL;
-static void *(*OPENSSL_malloc_fn)() = NULL;
-static void (*OPENSSL_free_fn)() = NULL;
-
-static void solaris_locking_callback(int, int, char *, int);
-static unsigned long solaris_thread_id(void);
-static boolean_t thread_setup(void);
-/* LINTED E_STATIC_UNUSED */
-static void thread_cleanup(void);
-
-mutex_t init_lock = DEFAULTMUTEX;
-static mutex_t *lock_cs;
-static long *lock_count;
-
-static boolean_t libssl_loaded = B_FALSE;
-static boolean_t libcrypto_loaded = B_FALSE;
-
-void
-libssl_load()
-{
- void *dldesc;
-
- (void) mutex_lock(&init_lock);
- if (libssl_loaded) {
- (void) mutex_unlock(&init_lock);
- return;
- }
-
- dldesc = dlopen(LIBSSL, RTLD_LAZY);
- if (dldesc != NULL) {
- d2i_X509_NAME_fn = (X509_NAME*(*)())dlsym(dldesc,
- "d2i_X509_NAME");
- if (d2i_X509_NAME_fn == NULL)
- goto libssl_err;
-
- X509_NAME_print_ex_fp_fn = (int(*)())dlsym(dldesc,
- "X509_NAME_print_ex_fp");
- if (X509_NAME_print_ex_fp_fn == NULL)
- goto libssl_err;
-
- ERR_get_error_fn = (char *(*)())dlsym(dldesc,
- "ERR_get_error");
- if (ERR_get_error_fn == NULL)
- goto libssl_err;
-
- ERR_error_string_fn = (char *(*)())dlsym(dldesc,
- "ERR_error_string");
- if (ERR_error_string_fn == NULL)
- goto libssl_err;
-
- SSL_load_error_strings_fn = (void(*)())dlsym(dldesc,
- "SSL_load_error_strings");
- if (SSL_load_error_strings_fn == NULL)
- goto libssl_err;
-
- ERR_free_strings_fn = (void(*)())dlsym(dldesc,
- "ERR_free_strings");
- if (ERR_free_strings_fn == NULL)
- goto libssl_err;
-
- CRYPTO_set_locking_callback_fn = (void(*)())dlsym(dldesc,
- "CRYPTO_set_locking_callback");
- if (CRYPTO_set_locking_callback_fn == NULL)
- goto libssl_err;
-
- CRYPTO_set_id_callback_fn = (void(*)())dlsym(dldesc,
- "CRYPTO_set_id_callback");
- if (CRYPTO_set_id_callback_fn == NULL)
- goto libssl_err;
-
- X509_NAME_free_fn = (void(*)())dlsym(dldesc,
- "X509_NAME_free");
- if (X509_NAME_free_fn == NULL)
- goto libssl_err;
-
- if (thread_setup() == B_FALSE)
- goto libssl_err;
-
- libssl_loaded = B_TRUE;
- }
- (void) mutex_unlock(&init_lock);
- return;
-libssl_err:
- (void) dlclose(dldesc);
- (void) mutex_unlock(&init_lock);
-}
-
-void
-libcrypto_load()
-{
- void *dldesc;
-
- (void) mutex_lock(&init_lock);
- if (libcrypto_loaded) {
- (void) mutex_unlock(&init_lock);
- return;
- }
-
- dldesc = dlopen(LIBCRYPTO, RTLD_LAZY);
- if (dldesc != NULL) {
- CRYPTO_num_locks_fn = (int(*)())dlsym(dldesc,
- "CRYPTO_num_locks");
- if (CRYPTO_num_locks_fn == NULL)
- goto libcrypto_err;
-
- /*
- * OPENSSL_free is really a macro, so we
- * need to reference the actual symbol,
- * which is CRYPTO_free.
- */
- OPENSSL_free_fn = (void(*)())dlsym(dldesc,
- "CRYPTO_free");
- if (OPENSSL_free_fn == NULL)
- goto libcrypto_err;
-
- /*
- * OPENSSL_malloc is really a macro, so we
- * need to reference the actual symbol,
- * which is CRYPTO_malloc.
- */
- OPENSSL_malloc_fn = (void *(*)())dlsym(dldesc,
- "CRYPTO_malloc");
- if (OPENSSL_malloc_fn == NULL)
- goto libcrypto_err;
-
- libcrypto_loaded = B_TRUE;
- }
- (void) mutex_unlock(&init_lock);
- return;
-libcrypto_err:
- (void) dlclose(dldesc);
- (void) mutex_unlock(&init_lock);
-}
-
-static boolean_t
-thread_setup(void)
-{
- int i;
-
- if ((lock_cs = OPENSSL_malloc_fn(CRYPTO_num_locks_fn() *
- sizeof (mutex_t))) == NULL)
- return (B_FALSE);
- if ((lock_count = OPENSSL_malloc_fn(CRYPTO_num_locks_fn() *
- sizeof (long))) == NULL) {
- OPENSSL_free_fn(lock_cs);
- return (B_FALSE);
- }
-
- for (i = 0; i < CRYPTO_num_locks_fn(); i++) {
- lock_count[i] = 0;
- (void) mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL);
- }
-
- CRYPTO_set_id_callback_fn((unsigned long (*)())solaris_thread_id);
- CRYPTO_set_locking_callback_fn((void (*)())solaris_locking_callback);
- return (B_TRUE);
-}
-
-static void
-thread_cleanup(void)
-{
- int i;
-
- (void) mutex_lock(&init_lock);
- CRYPTO_set_locking_callback_fn(NULL);
- CRYPTO_set_id_callback_fn(NULL);
- for (i = 0; i < CRYPTO_num_locks_fn(); i++)
- (void) mutex_destroy(&(lock_cs[i]));
- OPENSSL_free_fn(lock_cs);
- OPENSSL_free_fn(lock_count);
- (void) mutex_unlock(&init_lock);
-}
-
-/* ARGSUSED */
-static void
-solaris_locking_callback(int mode, int type, char *file, int line)
-{
- if (mode & CRYPTO_LOCK) {
- (void) mutex_lock(&(lock_cs[type]));
- lock_count[type]++;
- } else {
- (void) mutex_unlock(&(lock_cs[type]));
- }
-}
-
-static unsigned long
-solaris_thread_id(void)
-{
- unsigned long ret;
-
- ret = (unsigned long)thr_self();
- return (ret);
-}
-
-void
-print_asn1_name(FILE *file, const unsigned char *buf, long buflen)
-{
- libcrypto_load();
- if (libcrypto_loaded)
- libssl_load();
-
- if (libssl_loaded && libcrypto_loaded) {
- X509_NAME *x509name = NULL;
- const unsigned char *p;
-
- /* Make an effort to decode the ASN1 encoded name */
- SSL_load_error_strings_fn();
-
- /*
- * Temporary variable is mandatory per d2i_X509(3). Upcoming
- * call to d2i_X509_NAME_fn() will change the 'p' pointer.
- */
- p = buf;
-
- x509name = d2i_X509_NAME_fn(NULL, &p, buflen);
- if (x509name != NULL) {
- (void) X509_NAME_print_ex_fp_fn(file, x509name, 0,
- (ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE |
- XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN));
- X509_NAME_free_fn(x509name);
- (void) fprintf(file, "\n");
- } else {
- char errbuf[80];
-
- (void) fprintf(file, "\n# %s\n",
- ERR_error_string_fn(ERR_get_error_fn(), errbuf));
- (void) fprintf(file, dgettext(TEXT_DOMAIN,
- "<cannot interpret>\n"));
- }
- ERR_free_strings_fn();
- } else {
- (void) fprintf(file, dgettext(TEXT_DOMAIN, "<cannot print>\n"));
- }
-}
diff --git a/usr/src/lib/libipsecutil/common/ipsec_util.c b/usr/src/lib/libipsecutil/common/ipsec_util.c
index 017259967c..e27a47e63b 100644
--- a/usr/src/lib/libipsecutil/common/ipsec_util.c
+++ b/usr/src/lib/libipsecutil/common/ipsec_util.c
@@ -24,6 +24,7 @@
* Use is subject to license terms.
* Copyright 2012 Milan Juri. All rights reserved.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
*/
#include <unistd.h>
@@ -47,6 +48,8 @@
#include <setjmp.h>
#include <libgen.h>
#include <libscf.h>
+#include <kmfapi.h>
+#include <ber_der.h>
#include "ipsec_util.h"
#include "ikedoor.h"
@@ -3475,3 +3478,28 @@ ipsecutil_exit(exit_type_t type, char *fmri, FILE *fp, const char *fmt, ...)
(void) fclose(fp);
exit(exit_status);
}
+
+void
+print_asn1_name(FILE *file, const unsigned char *buf, long buflen)
+{
+ KMF_X509_NAME name = { 0 };
+ KMF_DATA data = { 0 };
+ char *str = NULL;
+
+ data.Data = (unsigned char *)buf;
+ data.Length = buflen;
+
+ if (DerDecodeName(&data, &name) != KMF_OK)
+ goto fail;
+
+ if (kmf_dn_to_string(&name, &str) != KMF_OK)
+ goto fail;
+
+ (void) fprintf(file, "%s\n", str);
+ kmf_free_dn(&name);
+ free(str);
+ return;
+fail:
+ kmf_free_dn(&name);
+ (void) fprintf(file, dgettext(TEXT_DOMAIN, "<cannot interpret>\n"));
+}
diff --git a/usr/src/lib/libipsecutil/common/ipsec_util.h b/usr/src/lib/libipsecutil/common/ipsec_util.h
index 44154e5c33..7f779bb95f 100644
--- a/usr/src/lib/libipsecutil/common/ipsec_util.h
+++ b/usr/src/lib/libipsecutil/common/ipsec_util.h
@@ -23,7 +23,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#ifndef _IPSEC_UTIL_H
@@ -214,20 +214,6 @@ extern int dbgstr2num(char *);
extern int parsedbgopts(char *);
/*
- * SSL library (OpenSSL)
- */
-#define LIBSSL "libssl.so"
-
-void libssl_load(void);
-
-/*
- * crypto library (OpenSSL)
- */
-#define LIBCRYPTO "libcrypto.so"
-
-void libcrypto_load(void);
-
-/*
* functions to manipulate the IKEv1 kmcookie-label mapping file
*/
diff --git a/usr/src/lib/libkmf/include/kmfapi.h b/usr/src/lib/libkmf/include/kmfapi.h
index 9aeb0ca202..dbe09b2db6 100644
--- a/usr/src/lib/libkmf/include/kmfapi.h
+++ b/usr/src/lib/libkmf/include/kmfapi.h
@@ -19,6 +19,7 @@
* CDDL HEADER END
*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2018, Joyent, Inc.
*
* Constant definitions and function prototypes for the KMF library.
* Commonly used data types are defined in "kmftypes.h".
@@ -275,6 +276,7 @@ extern KMF_RETURN kmf_get_kmf_error_str(KMF_RETURN, char **);
* Miscellaneous
*/
extern KMF_RETURN kmf_dn_parser(char *, KMF_X509_NAME *);
+extern KMF_RETURN kmf_dn_to_string(KMF_X509_NAME *, char **);
extern KMF_RETURN kmf_read_input_file(KMF_HANDLE_T, char *, KMF_DATA *);
extern KMF_RETURN kmf_der_to_pem(KMF_OBJECT_TYPE, unsigned char *,
int, unsigned char **, int *);
diff --git a/usr/src/lib/libkmf/libkmf/Makefile.com b/usr/src/lib/libkmf/libkmf/Makefile.com
index a704d1e5a8..43de43cb1d 100644
--- a/usr/src/lib/libkmf/libkmf/Makefile.com
+++ b/usr/src/lib/libkmf/libkmf/Makefile.com
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2018, Joyent, Inc.
#
LIBRARY= libkmf.a
@@ -56,8 +57,8 @@ LIBS= $(DYNLIB) $(LINTLIB)
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
-LDLIBS += $(BERDERLIB) $(CRYPTOUTILLIB) -lmd -lpkcs11 -lnsl -lsocket -lc
-LDLIBS6 += $(BERDERLIB64) $(CRYPTOUTILLIB64) -lmd -lpkcs11 -lnsl -lsocket -lc
+LDLIBS += $(BERDERLIB) $(CRYPTOUTILLIB) -lmd -lpkcs11 -lnsl -lsocket -lc
+LDLIBS += -lcustr
# DYNLIB libraries do not have lint libs and are not linted
$(DYNLIB) := LDLIBS += -lxml2
diff --git a/usr/src/lib/libkmf/libkmf/common/mapfile-vers b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
index 4e8d0d848d..977112d733 100644
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers
+++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2018, Joyent, Inc.
#
#
# MAPFILE HEADER START
@@ -401,6 +402,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
GetIDFromSPKI;
IsEqualOid;
kmf_create_pk11_session;
+ kmf_dn_to_string;
kmf_select_token;
parsePolicyElement;
PKCS_DigestData;
diff --git a/usr/src/lib/libkmf/libkmf/common/rdn_parser.c b/usr/src/lib/libkmf/libkmf/common/rdn_parser.c
index 5cc22146d8..3e23c0ac56 100644
--- a/usr/src/lib/libkmf/libkmf/common/rdn_parser.c
+++ b/usr/src/lib/libkmf/libkmf/common/rdn_parser.c
@@ -33,6 +33,8 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
+ * Copyright 2018, Joyent, Inc.
+ *
* File: rdn_parser.c
*/
@@ -44,6 +46,7 @@
#include <rdn_parser.h>
#include <stdio.h>
#include <values.h>
+#include <libcustr.h>
/*
* The order here is important. The OIDs are arranged in order of
@@ -535,3 +538,218 @@ kmf_dn_parser(char *string, KMF_X509_NAME *name)
err = ParseDistinguishedName(string, (int)strlen(string), name);
return (err);
}
+
+static const char hexdigits[] = "0123456789abcdef";
+
+static KMF_RETURN
+binvalue_to_string(KMF_DATA *data, custr_t *str)
+{
+ size_t i;
+ uchar_t c;
+
+ if (custr_appendc(str, '#') != 0)
+ return (KMF_ERR_MEMORY);
+
+ for (i = 0; i < data->Length; i++) {
+ c = data->Data[i];
+ if (custr_appendc(str, hexdigits[(c >> 4) & 0xf]) != 0 ||
+ custr_appendc(str, hexdigits[(c & 0xf)]) != 0) {
+ return (KMF_ERR_MEMORY);
+ }
+ }
+
+ return (KMF_OK);
+}
+
+/*
+ * Convert an RDN value into a printable name with appropriate escaping.
+ * The rules are taken from RFC4514. While it is dealing with LDAP
+ * distinguished names, both LDAP and x509 certificates are based on the
+ * same underlying ITU standards, and as far as I can determine, the same
+ * rules apply (or at least the rules for LDAP DNs apply the same to x509
+ * DNs).
+ */
+static KMF_RETURN
+value_to_string(KMF_DATA *data, custr_t *str)
+{
+ size_t i;
+ uchar_t c;
+
+ for (i = 0; i < data->Length; i++) {
+ c = data->Data[i];
+
+ /*
+ * While technically not required, it is suggested that
+ * printable non-ascii characters (e.g. multi-byte UTF-8
+ * characters) are converted as escaped hex (as well as
+ * unprintable characters). AFAIK there is no one canonical
+ * string representation (e.g. attribute names are case
+ * insensitive, so 'CN=foo' and 'cn=foo' convert to the same
+ * binary representation, but there is nothing to say if
+ * either string form is canonical), so this shouldn't
+ * pose a problem.
+ */
+ if (c < ' ' || c >= 0x7f) {
+ /*
+ * RFC4514 specifies the hex form in a DN string as
+ * \{hex}{hex}. OpenSSL uses capitals for A-F so we
+ * do the same.
+ */
+ if (custr_append_printf(str, "\\%02hhX", c) != 0)
+ return (KMF_ERR_MEMORY);
+ continue;
+ }
+
+ switch (c) {
+ case '#':
+ /* Escape # if at the start of a value */
+ if (i != 0)
+ break;
+ /* FALLTHROUGH */
+ case ' ':
+ /* Escape ' ' if at the start or end of a value */
+ if (i != 0 && i + 1 != data->Length)
+ break;
+ /* FALLTHROUGH */
+ case '"':
+ case '+':
+ case ',':
+ case ';':
+ case '<':
+ case '>':
+ case '\\':
+ /* Escape these */
+ if (custr_appendc(str, '\\') != 0)
+ return (KMF_ERR_MEMORY);
+ }
+
+ if (custr_appendc(str, c) != 0)
+ return (KMF_ERR_MEMORY);
+ }
+
+ return (KMF_OK);
+}
+
+/*
+ * Translate an attribute/value pair into a string. If the attribute OID
+ * is a well known OID (in name2kinds) we use the name instead of the OID.
+ */
+static KMF_RETURN
+ava_to_string(KMF_X509_TYPE_VALUE_PAIR *tvp, custr_t *str)
+{
+ KMF_OID *kind_oid;
+ KMF_OID *rdn_oid = &tvp->type;
+ const char *attr = NULL;
+ size_t i;
+ KMF_RETURN ret = KMF_OK;
+ boolean_t found = B_FALSE;
+
+ for (i = 0; name2kinds[i].name != NULL; i++) {
+ kind_oid = name2kinds[i].OID;
+
+ if (!IsEqualOid(kind_oid, rdn_oid))
+ continue;
+
+ attr = name2kinds[i].name;
+ found = B_TRUE;
+ break;
+ }
+
+ if (!found && (attr = kmf_oid_to_string(rdn_oid)) == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto done;
+ }
+ if (custr_append(str, attr) != 0) {
+ ret = KMF_ERR_MEMORY;
+ goto done;
+ }
+ if (custr_appendc(str, '=') != 0) {
+ ret = KMF_ERR_MEMORY;
+ goto done;
+ }
+
+ /*
+ * RFC4514 indicates that an oid=value pair should have the value
+ * printed as #xxxxxx. In addition, we also print as a binary
+ * value if the BER tag does not indicate the value is some sort
+ * of printable string.
+ */
+ switch (tvp->valueType) {
+ case BER_UTF8_STRING:
+ case BER_PRINTABLE_STRING:
+ case BER_T61STRING:
+ case BER_IA5STRING:
+ if (found) {
+ ret = value_to_string(&tvp->value, str);
+ break;
+ }
+ /*FALLTHROUGH*/
+ default:
+ ret = binvalue_to_string(&tvp->value, str);
+ break;
+ }
+
+done:
+ if (!found)
+ free((void *)attr);
+
+ return (ret);
+}
+
+static KMF_RETURN
+rdn_to_string(KMF_X509_RDN *rdn, custr_t *str)
+{
+ KMF_RETURN ret;
+ size_t i;
+
+ for (i = 0; i < rdn->numberOfPairs; i++) {
+ if (i > 0 && custr_appendc(str, '+') != 0)
+ return (KMF_ERR_MEMORY);
+
+ ret = ava_to_string(&rdn->AttributeTypeAndValue[i], str);
+ if (ret != KMF_OK)
+ return (ret);
+ }
+
+ return (KMF_OK);
+}
+
+/*
+ * kmf_dn_to_string
+ *
+ * Take a binary KMF_X509_NAME and convert it into a human readable string.
+ */
+KMF_RETURN
+kmf_dn_to_string(KMF_X509_NAME *name, char **string)
+{
+ custr_t *str = NULL;
+ KMF_RETURN err = KMF_OK;
+ size_t i;
+
+ if (name == NULL || string == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ *string = NULL;
+
+ if (custr_alloc(&str) != 0)
+ return (KMF_ERR_MEMORY);
+
+ for (i = 0; i < name->numberOfRDNs; i++) {
+ KMF_X509_RDN *rdn = &name->RelativeDistinguishedName[i];
+
+ if (i > 0 && custr_append(str, ", ") != 0) {
+ err = KMF_ERR_MEMORY;
+ goto done;
+ }
+
+ if ((err = rdn_to_string(rdn, str)) != KMF_OK)
+ goto done;
+ }
+
+ if ((*string = strdup(custr_cstr(str))) == NULL)
+ err = KMF_ERR_MEMORY;
+
+done:
+ custr_free(str);
+ return (err);
+}