summaryrefslogtreecommitdiff
path: root/usr/src/lib/libkmf
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2018-10-04 12:00:08 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2018-10-04 12:00:08 +0000
commit0cd103a9ea5572c37d728a7d26701a18dc9e3a7f (patch)
treebca6ea57ba1ec3bd68be293a7f0230f45aff5e6c /usr/src/lib/libkmf
parenteee2da8296e69bdb47747ea36f4d186e6a133c96 (diff)
parentaa9ef484c6f8ecee85dfefdb4970c50cfa2db302 (diff)
downloadillumos-joyent-0cd103a9ea5572c37d728a7d26701a18dc9e3a7f.tar.gz
[illumos-gate merge]
commit aa9ef484c6f8ecee85dfefdb4970c50cfa2db302 9128 cw(1onbld) should be able to run multiple shadows 9129 file-locking tests shouldn't build multiple source files in one compiler invocation 9130 DTrace tst.gcc.d isn't useful 9132 cw(1onbld) shouldn't shadow pure preprocessing commit bdc560ab289d67ddebad9a2146fd36c2662d88b1 5159 ipsec_libssl_setup.c loads libcrypto commit 15aeb4d1148772724cf568e1f7a13fbb99f11ab8 9848 libi386: pxe.h cstyle cleanup
Diffstat (limited to 'usr/src/lib/libkmf')
-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
4 files changed, 225 insertions, 2 deletions
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);
+}