25114734 Userland krb should use libucrypto
authorWill Fiveash <will.fiveash@oracle.com>
Fri, 24 Mar 2017 12:29:03 -0500
changeset 7950 50d75ee82dad
parent 7949 e94c44902e51
child 7951 3b581304cb26
25114734 Userland krb should use libucrypto
components/krb5/Makefile
components/krb5/Solaris/ucrypto/Makefile.in
components/krb5/Solaris/ucrypto/aes/Makefile.in
components/krb5/Solaris/ucrypto/aes/deps
components/krb5/Solaris/ucrypto/camellia/Makefile.in
components/krb5/Solaris/ucrypto/camellia/deps
components/krb5/Solaris/ucrypto/crypto_mod.h
components/krb5/Solaris/ucrypto/deps
components/krb5/Solaris/ucrypto/des/Makefile.in
components/krb5/Solaris/ucrypto/des/deps
components/krb5/Solaris/ucrypto/enc_provider/Makefile.in
components/krb5/Solaris/ucrypto/enc_provider/aes.c
components/krb5/Solaris/ucrypto/enc_provider/camellia.c
components/krb5/Solaris/ucrypto/enc_provider/deps
components/krb5/Solaris/ucrypto/enc_provider/des.c
components/krb5/Solaris/ucrypto/enc_provider/des3.c
components/krb5/Solaris/ucrypto/enc_provider/rc4.c
components/krb5/Solaris/ucrypto/hash_provider/Makefile.in
components/krb5/Solaris/ucrypto/hash_provider/deps
components/krb5/Solaris/ucrypto/hash_provider/hash_md4.c
components/krb5/Solaris/ucrypto/hash_provider/hash_ucrypto.c
components/krb5/Solaris/ucrypto/hmac.c
components/krb5/Solaris/ucrypto/init.c
components/krb5/Solaris/ucrypto/md4/Makefile.in
components/krb5/Solaris/ucrypto/md4/deps
components/krb5/Solaris/ucrypto/md5/Makefile.in
components/krb5/Solaris/ucrypto/md5/deps
components/krb5/Solaris/ucrypto/sha1/Makefile.in
components/krb5/Solaris/ucrypto/sha1/deps
components/krb5/Solaris/ucrypto/sha2/Makefile.in
components/krb5/Solaris/ucrypto/sha2/deps
components/krb5/Solaris/ucrypto/stubs.c
components/krb5/patches/079-ucrypto.patch
--- a/components/krb5/Makefile	Wed Apr 26 04:31:59 2017 -0700
+++ b/components/krb5/Makefile	Fri Mar 24 12:29:03 2017 -0500
@@ -96,7 +96,8 @@
 CONFIGURE_OPTIONS.32 += --libexecdir=$(USRLIBDIR)
 CONFIGURE_OPTIONS.64 += --libexecdir=$(USRLIBDIR)/$(MACH64)
 CONFIGURE_OPTIONS += --includedir=$(USRINCDIR)/kerberosv5
-CONFIGURE_OPTIONS += --with-crypto-impl=openssl
+CONFIGURE_OPTIONS += --with-pkinit-crypto-impl=openssl
+CONFIGURE_OPTIONS += --with-crypto-impl=ucrypto
 CONFIGURE_OPTIONS += --with-ldap
 CONFIGURE_OPTIONS += --with-prng-alg=os
 CONFIGURE_OPTIONS += --with-tcl=$(USRDIR)
@@ -142,8 +143,10 @@
 	$(MKDIR) -p $(AUDIT_DIR); $(CP) Solaris/audit/* $(AUDIT_DIR); \
 	$(CP) Solaris/audit/kadmind_audit.* $(SOURCE_DIR)/src/kadmin/server;
 
-# We move xdr_alloc.c and supporting dyn code from libgssrpc directly
-# into libkadm5srv_mit. kadmind is the only consumer anyway.
+# We move xdr_alloc.c and supporting dyn code from libgssrpc directly into
+# libkadm5srv_mit. kadmind is the only consumer anyway.  Also setting up the
+# ucrypto provider directory and creating symlinks needed by the ucrypto crypto
+# provider.
 SRCLIB=$(SOURCE_DIR)/src/lib
 COMPONENT_PREP_ACTION += \
 	$(CP) $(SRCLIB)/rpc/xdr_alloc.c $(SRCLIB)/kadm5/srv/; \
@@ -151,6 +154,13 @@
 	$(CP) $(SRCLIB)/rpc/dyn.h $(SRCLIB)/kadm5/srv/; \
 	$(CP) $(SRCLIB)/rpc/dynP.h $(SRCLIB)/kadm5/srv/; \
 	$(CP) $(SRCLIB)/rpc/dyntest.c $(SRCLIB)/kadm5/srv/; \
+	(cd Solaris && $(TAR) -cf - ucrypto) | (cd $(SRCLIB)/crypto && tar -xf -); \
+	$(LN) -s ../../builtin/des/des_keys.c $(SRCLIB)/crypto/ucrypto/des/; \
+	$(LN) -s ../../builtin/des/f_parity.c $(SRCLIB)/crypto/ucrypto/des/; \
+	$(LN) -s ../../builtin/des/weak_key.c $(SRCLIB)/crypto/ucrypto/des/; \
+	$(LN) -s ../../builtin/des/des_int.h $(SRCLIB)/crypto/ucrypto/des/; \
+	$(LN) -s ../../builtin/hash_provider/hash_crc32.c $(SRCLIB)/crypto/ucrypto/hash_provider/; \
+	$(LN) -s ../builtin/pbkdf2.c $(SRCLIB)/crypto/ucrypto/; \
 
 # Common flags used to create the filter libs below
 FILTLIBFLAGS = -G $(LD_B_DIRECT) $(LD_Z_DEFS) $(LD_Z_TEXT)
@@ -213,6 +223,7 @@
 REQUIRED_PACKAGES += shell/ksh93
 REQUIRED_PACKAGES += system/core-os
 REQUIRED_PACKAGES += system/library/math
+REQUIRED_PACKAGES += system/library/security/crypto
 REQUIRED_PACKAGES += system/library/security/gss
 REQUIRED_PACKAGES += system/library/security/sasl/digestmd5
 REQUIRED_PACKAGES += system/network/ldap/openldap
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,46 @@
+mydir=lib$(S)crypto$(S)ucrypto
+BUILDTOP=$(REL)..$(S)..$(S)..
+SUBDIRS=camellia des aes md4 md5 sha1 sha2 enc_provider hash_provider
+LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir)
+
+STLIBOBJS=\
+	hmac.o	\
+	init.o	\
+	pbkdf2.o \
+	stubs.o
+
+OBJS=\
+	$(OUTPRE)hmac.$(OBJEXT)	\
+	$(OUTPRE)init.$(OBJEXT)	\
+	$(OUTPRE)pbkdf2.$(OBJEXT) \
+	$(OUTPRE)stubs.$(OBJEXT)
+
+SRCS=\
+	$(srcdir)/hmac.c	\
+	$(srcdir)/init.c	\
+	$(srcdir)/pbkdf2.c	\
+	$(srcdir)/stubs.c
+
+STOBJLISTS= des/OBJS.ST md4/OBJS.ST 	\
+	md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST 	\
+	enc_provider/OBJS.ST 		\
+	hash_provider/OBJS.ST 		\
+	aes/OBJS.ST 			\
+	OBJS.ST
+
+SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST 	\
+		md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST 	\
+		enc_provider/OBJS.ST 		\
+		hash_provider/OBJS.ST 		\
+		aes/OBJS.ST
+
+all-unix:: all-libobjs
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@lib_frag@
+@libobj_frag@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/aes/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,6 @@
+# Placeholder since all crypto modules must have the same structure.
+mydir=lib$(S)crypto$(S)ucrypto$(S)aes
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/aes/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,1 @@
+# No dependencies here.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/camellia/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,6 @@
+# Placeholder since all crypto modules must have the same structure.
+mydir=lib$(S)crypto$(S)ucrypto$(S)camellia
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/camellia/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,1 @@
+# No dependencies here.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/crypto_mod.h	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,36 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/openssl/crypto_mod.h - OpenSSL crypto module declarations */
+/*
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This header is included from lib/crypto/krb/crypto_int.h to provide
+ * module-specific declarations.  It is not included directly from source
+ * files.
+ */
+
+#ifndef CRYPTO_MOD_H
+#define CRYPTO_MOD_H
+
+#endif /* CRYPTO_MOD_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,46 @@
+#
+# Generated makefile dependencies follow.
+#
+hmac.so hmac.po $(OUTPRE)hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  crypto_mod.h hmac.c
+init.so init.po $(OUTPRE)init.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  crypto_mod.h init.c
+pbkdf2.so pbkdf2.po $(OUTPRE)pbkdf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  crypto_mod.h pbkdf2.c
+stubs.so stubs.po $(OUTPRE)stubs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h stubs.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/des/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,23 @@
+mydir=lib$(S)crypto$(S)ucrypto$(S)des
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+CRYPTO_IMPL_CFLAGS=@CRYPTO_IMPL_CFLAGS@
+LOCALINCLUDES = -I$(srcdir)/../../krb -I$(srcdir)/.. $(CRYPTO_IMPL_CFLAGS)
+
+STLIBOBJS= des_keys.o weak_key.o f_parity.o
+
+OBJS= $(OUTPRE)des_keys.$(OBJEXT) \
+      $(OUTPRE)weak_key.$(OBJEXT) \
+      $(OUTPRE)f_parity.$(OBJEXT)
+
+SRCS= $(srcdir)/des_keys.c $(srcdir)/weak_key.c $(srcdir)/f_parity.c
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/des/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,15 @@
+#
+# Generated makefile dependencies follow.
+#
+des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  des_keys.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/enc_provider/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,38 @@
+mydir=lib$(S)crypto$(S)ucrypto$(S)enc_provider
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+builtinsrcdir = $(top_srcdir)/lib/crypto/builtin
+LOCALINCLUDES = -I$(builtinsrcdir)/des 	\
+		-I$(builtinsrcdir)/camellia \
+		-I$(srcdir)/../../krb 	\
+		-I$(srcdir)/..
+
+STLIBOBJS= \
+	des.o 	\
+	des3.o 	\
+	rc4.o 	\
+	aes.o   \
+	camellia.o
+
+OBJS= \
+	$(OUTPRE)des.$(OBJEXT) 	\
+	$(OUTPRE)des3.$(OBJEXT) 	\
+	$(OUTPRE)aes.$(OBJEXT) 	\
+	$(OUTPRE)camellia.$(OBJEXT) 	\
+	$(OUTPRE)rc4.$(OBJEXT)
+
+SRCS= \
+	$(srcdir)/des.c 	\
+	$(srcdir)/des3.c 	\
+	$(srcdir)/aes.c 	\
+	$(srcdir)/camellia.c 	\
+	$(srcdir)/rc4.c
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/enc_provider/aes.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,253 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/ucrypto/enc_provider/aes.c */
+/*
+ * Copyright (C) 2003, 2007, 2008, 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <libucrypto.h>
+
+#define BLOCK_SIZE 16
+
+#define ENCRYPT_OP 1
+#define DECRYPT_OP 2
+
+/*
+ * The cbc_docrypt function is here to handle the case where there is only 1
+ * block of plain/cipher text to process.
+ */
+static krb5_error_code
+cbc_docrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+            size_t num_data, int op_type)
+{
+    int                    ret = 0;
+    unsigned char          iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
+    size_t                 olen = sizeof (oblock);
+    unsigned char          tmp_iv[BLOCK_SIZE];
+    struct iov_cursor      cursor;
+
+    if (ivec && ivec->data){
+        if (ivec->length != sizeof (tmp_iv))
+            return KRB5_CRYPTO_INTERNAL;
+        memcpy(tmp_iv, ivec->data, ivec->length);
+    } else {
+        memset(tmp_iv, 0, sizeof (tmp_iv));
+    }
+
+    /* Init iovec cursor to gather data for encypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+    k5_iov_cursor_get(&cursor, iblock);
+
+    if (op_type == ENCRYPT_OP) {
+        if (ucrypto_encrypt(CRYPTO_AES_CBC,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            tmp_iv, sizeof (tmp_iv),
+                            iblock, sizeof (iblock),
+                            oblock, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    } else {
+        if (ucrypto_decrypt(CRYPTO_AES_CBC,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            tmp_iv, sizeof (tmp_iv),
+                            iblock, sizeof (iblock),
+                            oblock, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    }
+
+    if (!ret) {
+        assert(olen == BLOCK_SIZE);
+        k5_iov_cursor_put(&cursor, oblock);
+
+        if (ivec && ivec->data) {
+            if (op_type == ENCRYPT_OP)
+                memcpy(ivec->data, oblock, BLOCK_SIZE);
+            else
+                memcpy(ivec->data, iblock, BLOCK_SIZE);
+        }
+    }
+
+    zap(iblock, sizeof (iblock));
+    zap(oblock, sizeof (oblock));
+
+    return ret;
+}
+
+static krb5_error_code
+cts_docrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+            size_t num_data, size_t dlen, size_t dblks, int op_type)
+{
+    int                    ret = 0;
+    size_t                 olen = dlen;
+    unsigned char         *obuf, *dbuf;
+    unsigned char          iv_cts[BLOCK_SIZE];
+    struct iov_cursor      cursor;
+
+    if (ivec && ivec->data){
+        if (ivec->length != sizeof (iv_cts))
+            return KRB5_CRYPTO_INTERNAL;
+        memcpy(iv_cts, ivec->data, ivec->length);
+    } else {
+        memset(iv_cts, 0, sizeof (iv_cts));
+    }
+
+    obuf = malloc(olen);
+    if (!obuf)
+        return ENOMEM;
+
+    dbuf = malloc(dlen);
+    if (!dbuf){
+        free(obuf);
+        return ENOMEM;
+    }
+
+    /* Init iov cursor to gather data for encypting/decrypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+    /* Get all the data to be encrypted/decrypted into dbuf */
+    k5_iov_cursor_get(&cursor, dbuf);
+
+    if (op_type == ENCRYPT_OP) {
+        if (ucrypto_encrypt(CRYPTO_AES_CTS,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            iv_cts, sizeof (iv_cts),
+                            dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    } else {
+        if (ucrypto_decrypt(CRYPTO_AES_CTS,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            iv_cts, sizeof (iv_cts),
+                            dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    }
+
+    if (!ret) {
+        assert(olen == dlen);
+        k5_iov_cursor_put(&cursor, obuf);
+        /*
+         * Updating the ivec arg, if present because of an old/obscure concept
+         * of cipher state that is being used by only BSD rlogin.  See RFCs
+         * 1391 and 1392 in regards to the vague description of cipher state.
+         * For encrypt/decrypt use the second to the last block of ciphertext
+         * if > 1 block.
+         */
+        if (ivec && ivec->data) {
+            unsigned char *bufptr = (op_type == ENCRYPT_OP) ? obuf : dbuf;
+            /*
+             * For encrypt obuf is ciphertext, for decrypt its dbuf which was
+             * input.
+             */
+            memcpy(ivec->data, bufptr + ((dblks - 2) * BLOCK_SIZE),
+                   BLOCK_SIZE);
+        }
+    }
+
+    zapfree(obuf, olen);
+    zapfree(dbuf, dlen);
+
+    return ret;
+}
+
+krb5_error_code
+krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec,
+                    krb5_crypto_iov *data, size_t num_data)
+{
+    size_t input_length, nblocks;
+
+    input_length = iov_total_length(data, num_data, FALSE);
+    nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+    if (nblocks == 1) {
+        if (input_length != BLOCK_SIZE)
+            return KRB5_BAD_MSIZE;
+        /*
+	 * Setting the ivec arg to NULL as a result of MIT bug ticket 8551
+	 * Crypto providers not updating cipher state when 1 block plaintext is
+	 * encrypted.  For now we leave the bug in since it has existed in MIT
+	 * code a long time and the tests need the buggy behavior to pass at
+	 * this point.
+         */
+        return cbc_docrypt(key, NULL, data, num_data, ENCRYPT_OP);
+    } else { /* nblocks > 1 */
+        return cts_docrypt(key, ivec, data, num_data, input_length, nblocks,
+                           ENCRYPT_OP);
+    }
+}
+
+krb5_error_code
+krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec,
+                    krb5_crypto_iov *data, size_t num_data)
+{
+    size_t input_length, nblocks;
+
+    input_length = iov_total_length(data, num_data, FALSE);
+    nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+    if (nblocks == 1) {
+        if (input_length != BLOCK_SIZE)
+            return KRB5_BAD_MSIZE;
+        /* See comment about ivec arg above... */
+        return cbc_docrypt(key, NULL, data, num_data, DECRYPT_OP);
+    } else { /* nblocks > 1 */
+        return cts_docrypt(key, ivec, data, num_data, input_length, nblocks,
+                           DECRYPT_OP);
+    }
+}
+
+static krb5_error_code
+krb5int_aes_init_state (const krb5_keyblock *key, krb5_keyusage usage,
+                        krb5_data *state)
+{
+    state->data = calloc(1, BLOCK_SIZE);
+    if (state->data == NULL)
+        return ENOMEM;
+    state->length = BLOCK_SIZE;
+    return 0;
+}
+
+const struct krb5_enc_provider krb5int_enc_aes128 = {
+    BLOCK_SIZE,
+    16, 16,
+    krb5int_aes_encrypt,
+    krb5int_aes_decrypt,
+    NULL,
+    krb5int_aes_init_state,
+    krb5int_default_free_state
+};
+
+const struct krb5_enc_provider krb5int_enc_aes256 = {
+    BLOCK_SIZE,
+    32, 32,
+    krb5int_aes_encrypt,
+    krb5int_aes_decrypt,
+    NULL,
+    krb5int_aes_init_state,
+    krb5int_default_free_state
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/enc_provider/camellia.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,322 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/ucrypto/enc_provider/aes.c */
+/*
+ * Copyright (C) 2003, 2007, 2008, 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <libucrypto.h>
+
+#define BLOCK_SIZE 16
+
+#define ENCRYPT_OP 1
+#define DECRYPT_OP 2
+
+/*
+ * xorblock is used in the camellia cbc mac fuction, copied from the openssl
+ * camellia.c.
+ */
+static void
+xorblock(unsigned char *out, const unsigned char *in)
+{
+    int z;
+    for (z = 0; z < BLOCK_SIZE / 4; z++) {
+        unsigned char *outptr = &out[z * 4];
+        unsigned char *inptr = (unsigned char *)&in[z * 4];
+        /*
+         * Use unaligned accesses.  On x86, this will probably still be faster
+         * than multiple byte accesses for unaligned data, and for aligned data
+         * should be far better.  (One test indicated about 2.4% faster
+         * encryption for 1024-byte messages.)
+         *
+         * If some other CPU has really slow unaligned-word or byte accesses,
+         * perhaps this function (or the load/store helpers?) should test for
+         * alignment first.
+         *
+         * If byte accesses are faster than unaligned words, we may need to
+         * conditionalize on CPU type, as that may be hard to determine
+         * automatically.
+         */
+        store_32_n(load_32_n(outptr) ^ load_32_n(inptr), outptr);
+    }
+}
+
+/*
+ * The cbc_docrypt function is here to handle the case where there is only 1
+ * block of plain/cipher text to process.
+ */
+static krb5_error_code
+cbc_docrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+            size_t num_data, int op_type)
+{
+    int                    ret = 0;
+    unsigned char          iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
+    size_t                 olen = sizeof (oblock);
+    unsigned char          tmp_iv[BLOCK_SIZE];
+    struct iov_cursor      cursor;
+
+    if (ivec && ivec->data){
+        if (ivec->length != sizeof (tmp_iv))
+            return KRB5_CRYPTO_INTERNAL;
+        memcpy(tmp_iv, ivec->data, ivec->length);
+    } else {
+        memset(tmp_iv, 0, sizeof (tmp_iv));
+    }
+
+    /* Init iovec cursor to gather data for encypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+    k5_iov_cursor_get(&cursor, iblock);
+
+    if (op_type == ENCRYPT_OP) {
+        if (ucrypto_encrypt(CRYPTO_CAMELLIA_CBC,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            tmp_iv, sizeof (tmp_iv),
+                            iblock, sizeof (iblock),
+                            oblock, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    } else {
+        if (ucrypto_decrypt(CRYPTO_CAMELLIA_CBC,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            tmp_iv, sizeof (tmp_iv),
+                            iblock, sizeof (iblock),
+                            oblock, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    }
+
+    if (!ret) {
+        assert(olen == BLOCK_SIZE);
+        k5_iov_cursor_put(&cursor, oblock);
+
+        if (ivec && ivec->data) {
+            if (op_type == ENCRYPT_OP)
+                memcpy(ivec->data, oblock, BLOCK_SIZE);
+            else
+                memcpy(ivec->data, iblock, BLOCK_SIZE);
+        }
+    }
+
+    zap(iblock, sizeof (iblock));
+    zap(oblock, sizeof (oblock));
+
+    return ret;
+}
+
+static krb5_error_code
+cts_docrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+            size_t num_data, size_t dlen, size_t dblks, int op_type)
+{
+    int                    ret = 0;
+    size_t                 olen = dlen;
+    unsigned char         *obuf, *dbuf;
+    unsigned char          iv_cts[BLOCK_SIZE];
+    struct iov_cursor      cursor;
+
+    if (ivec && ivec->data){
+        if (ivec->length != sizeof (iv_cts))
+            return KRB5_CRYPTO_INTERNAL;
+        memcpy(iv_cts, ivec->data, ivec->length);
+    } else {
+        memset(iv_cts, 0, sizeof (iv_cts));
+    }
+
+    obuf = malloc(olen);
+    if (!obuf)
+        return ENOMEM;
+
+    dbuf = malloc(dlen);
+    if (!dbuf){
+        free(obuf);
+        return ENOMEM;
+    }
+
+    /* Init iov cursor to gather data for encypting/decrypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+    /* Get all the data to be encrypted/decrypted into dbuf */
+    k5_iov_cursor_get(&cursor, dbuf);
+
+    if (op_type == ENCRYPT_OP) {
+        if (ucrypto_encrypt(CRYPTO_CAMELLIA_CTS,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            iv_cts, sizeof (iv_cts),
+                            dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    } else {
+        if (ucrypto_decrypt(CRYPTO_CAMELLIA_CTS,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            iv_cts, sizeof (iv_cts),
+                            dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        }
+    }
+
+    if (!ret) {
+        assert(olen == dlen);
+        k5_iov_cursor_put(&cursor, obuf);
+        /*
+         * Updating the ivec arg, if present because of an old/obscure concept
+         * of cipher state that is being used by only BSD rlogin.  See RFCs
+         * 1391 and 1392 in regards to the vague description of cipher state.
+         * For encrypt/decrypt use the second to the last block of ciphertext
+         * if > 1 block.
+         */
+        if (ivec && ivec->data) {
+            unsigned char *bufptr = (op_type == ENCRYPT_OP) ? obuf : dbuf;
+            /*
+             * For encrypt obuf is ciphertext, for decrypt its dbuf which was
+             * input.
+             */
+            memcpy(ivec->data, bufptr + ((dblks - 2) * BLOCK_SIZE),
+                   BLOCK_SIZE);
+        }
+    }
+
+    zapfree(obuf, olen);
+    zapfree(dbuf, dlen);
+
+    return ret;
+}
+
+krb5_error_code
+krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec,
+                    krb5_crypto_iov *data, size_t num_data)
+{
+    size_t input_length, nblocks;
+
+    input_length = iov_total_length(data, num_data, FALSE);
+    nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+    if (nblocks == 1) {
+        if (input_length != BLOCK_SIZE)
+            return KRB5_BAD_MSIZE;
+        /*
+	 * Note, there is bug here (see MIT bug ticket 8551 Crypto providers not
+	 * updating cipher state when 1 block plaintext is encrypted) hence the
+	 * NULL ivec arg.  For now we leave the bug in since it has existed in
+	 * MIT code a long time and the tests need the buggy behavior to pass at
+	 * this point.
+         */
+        return cbc_docrypt(key, NULL, data, num_data, ENCRYPT_OP);
+    } else {  /* nblocks > 1 */
+        return cts_docrypt(key, ivec, data, num_data, input_length, nblocks,
+                           ENCRYPT_OP);
+    }
+}
+
+krb5_error_code
+krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec,
+                    krb5_crypto_iov *data, size_t num_data)
+{
+    size_t input_length, nblocks;
+
+    input_length = iov_total_length(data, num_data, FALSE);
+    nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+    if (nblocks == 1) {
+        if (input_length != BLOCK_SIZE)
+            return KRB5_BAD_MSIZE;
+        return cbc_docrypt(key, NULL, data, num_data, DECRYPT_OP);
+    } else {  /* nblocks > 1 */
+        return cts_docrypt(key, ivec, data, num_data, input_length, nblocks,
+                           DECRYPT_OP);
+    }
+}
+
+/*
+ * This function is based on the openssl enc_provider/camellia.c version.
+ */
+krb5_error_code
+krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
+                         size_t num_data, const krb5_data *ivec,
+                         krb5_data *output)
+{
+    unsigned char blockY[BLOCK_SIZE], blockB[BLOCK_SIZE];
+    size_t        olen = BLOCK_SIZE;
+    struct iov_cursor cursor;
+
+    if (output->length < BLOCK_SIZE)
+        return KRB5_BAD_MSIZE;
+
+    if (ivec != NULL && ivec->data != NULL)
+        memcpy(blockY, ivec->data, BLOCK_SIZE);
+    else
+        memset(blockY, 0, BLOCK_SIZE);
+
+    k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+    while (k5_iov_cursor_get(&cursor, blockB)) {
+        xorblock(blockB, blockY);
+        olen = sizeof(blockY);
+        if (ucrypto_encrypt(CRYPTO_CAMELLIA_ECB,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            NULL, 0,
+                            blockB, sizeof(blockB),
+                            blockY, &olen) != CRYPTO_SUCCESS) {
+            return KRB5_CRYPTO_INTERNAL;
+        }
+    }
+
+    assert(olen == BLOCK_SIZE);
+    output->length = BLOCK_SIZE;
+    memcpy(output->data, blockY, BLOCK_SIZE);
+
+    return 0;
+}
+
+static krb5_error_code
+krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
+                        krb5_data *state)
+{
+    state->data = calloc(1, BLOCK_SIZE);
+    if (state->data == NULL)
+        return ENOMEM;
+    state->length = BLOCK_SIZE;
+    return 0;
+}
+
+const struct krb5_enc_provider krb5int_enc_camellia128 = {
+    BLOCK_SIZE,
+    16, 16,
+    krb5int_camellia_encrypt,
+    krb5int_camellia_decrypt,
+    krb5int_camellia_cbc_mac,
+    krb5int_camellia_init_state,
+    krb5int_default_free_state
+};
+
+const struct krb5_enc_provider krb5int_enc_camellia256 = {
+    BLOCK_SIZE,
+    32, 32,
+    krb5int_camellia_encrypt,
+    krb5int_camellia_decrypt,
+    krb5int_camellia_cbc_mac,
+    krb5int_camellia_init_state,
+    krb5int_default_free_state
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/enc_provider/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,59 @@
+#
+# Generated makefile dependencies follow.
+#
+des.so des.po $(OUTPRE)des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+  $(srcdir)/../crypto_mod.h $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h des.c
+des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+  $(srcdir)/../crypto_mod.h $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h des3.c
+aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+  $(srcdir)/../crypto_mod.h $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h aes.c
+camellia.so camellia.po $(OUTPRE)camellia.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  camellia.c
+rc4.so rc4.po $(OUTPRE)rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \
+  $(srcdir)/../crypto_mod.h $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h rc4.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/enc_provider/des.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,251 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/openssl/enc_provider/des.c */
+/*
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <libucrypto.h>
+
+#define DES_BLOCK_SIZE 8
+#define DES_KEY_SIZE 8
+#define DES_KEY_BYTES 7
+
+static krb5_error_code
+validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data,
+         size_t num_data, size_t *inlen)
+{
+    size_t input_length = iov_total_length(data, num_data, FALSE);
+
+    if (key->keyblock.length != DES_KEY_SIZE)
+        return KRB5_BAD_KEYSIZE;
+    if ((input_length % DES_BLOCK_SIZE) != 0)
+        return KRB5_BAD_MSIZE;
+    if (ivec && (ivec->length != DES_BLOCK_SIZE))
+        return KRB5_BAD_MSIZE;
+
+    if (inlen != NULL)
+        *inlen = input_length;
+
+    return 0;
+}
+
+static krb5_error_code
+k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+               size_t num_data)
+{
+    int ret;
+    size_t  olen, dlen;
+    uchar_t *obuf, *dbuf;
+    uchar_t tmp_iv[DES_BLOCK_SIZE];
+    struct iov_cursor cursor;
+
+    ret = validate(key, ivec, data, num_data, &dlen);
+    if (ret != 0 || dlen == 0)
+        return ret;
+
+    if (ivec && ivec->data)
+        memcpy(tmp_iv, ivec->data, ivec->length);
+    else
+        memset(tmp_iv, 0, sizeof(tmp_iv));
+
+    olen = dlen;
+    obuf = malloc(olen);
+    if (!obuf)
+        return ENOMEM;
+
+    dbuf = malloc(dlen);
+    if (!dbuf){
+        free(obuf);
+        return ENOMEM;
+    }
+
+    /* Init iov cursor to gather data for encypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+    /* Get all that data into dbuf */
+    k5_iov_cursor_get(&cursor, dbuf);
+
+    if (ucrypto_encrypt(CRYPTO_DES_CBC,
+                        key->keyblock.contents,
+                        key->keyblock.length,
+                        tmp_iv, sizeof(tmp_iv),
+                        dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+        ret = KRB5_CRYPTO_INTERNAL;
+    } else {
+        k5_iov_cursor_put(&cursor, obuf);
+    }
+
+    /*
+     * Updating the ivec arg, if present because of an old/obscure concept of
+     * cipher state that is being used by only BSD rlogin.  See RFCs 1391 and
+     * 1392 in regards to the vague description of cipher state.
+     */
+    if (!ret && ivec && ivec->data) {
+        /* Copy last block of cipher text output */
+        memcpy(ivec->data, obuf + (dlen - DES_BLOCK_SIZE), DES_BLOCK_SIZE);
+    }
+
+    zapfree(obuf, olen);
+    zapfree(dbuf, dlen);
+
+    return ret;
+}
+
+static krb5_error_code
+k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+               size_t num_data)
+{
+    int ret;
+    size_t  olen, dlen;
+    uchar_t *obuf, *dbuf;
+    uchar_t tmp_iv[DES_BLOCK_SIZE];
+    struct iov_cursor cursor;
+
+    ret = validate(key, ivec, data, num_data, &dlen);
+    if (ret != 0 || dlen == 0)
+        return ret;
+
+    if (ivec && ivec->data)
+        memcpy(tmp_iv, ivec->data, ivec->length);
+    else
+        memset(tmp_iv, 0, sizeof(tmp_iv));
+
+    olen = dlen;
+    obuf = malloc(olen);
+    if (!obuf)
+        return ENOMEM;
+
+    dbuf = malloc(dlen);
+    if (!dbuf){
+        free(obuf);
+        return ENOMEM;
+    }
+
+    /* Init iov cursor to gather cipher text for decrypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+    /* Gather all that cipher text into dbuf */
+    k5_iov_cursor_get(&cursor, dbuf);
+
+    if (ucrypto_decrypt(CRYPTO_DES_CBC,
+                        key->keyblock.contents,
+                        key->keyblock.length,
+                        tmp_iv, sizeof(tmp_iv),
+                        dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+        ret = KRB5_CRYPTO_INTERNAL;
+    } else {
+        k5_iov_cursor_put(&cursor, obuf);
+    }
+
+    /*
+     * Updating the ivec arg, if present because of an old/obscure concept of
+     * cipher state that is being used by only BSD rlogin.  See RFCs 1391 and
+     * 1392 in regards to the vague description of cipher state.
+     */
+    if (!ret && ivec && ivec->data) {
+        /* Copy last block of cipher text input */
+        memcpy(ivec->data, dbuf + (dlen - DES_BLOCK_SIZE), DES_BLOCK_SIZE);
+    }
+
+    zapfree(obuf, olen);
+    zapfree(dbuf, dlen);
+
+    return ret;
+}
+
+static krb5_error_code
+k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data,
+               const krb5_data *ivec, krb5_data *output)
+{
+    int ret;
+    struct iov_cursor cursor;
+    uchar_t blockY[DES_BLOCK_SIZE], blockB[DES_BLOCK_SIZE];
+    size_t olen;
+
+    ret = validate(key, ivec, data, num_data, NULL);
+    if (ret != 0)
+        return ret;
+
+    if (output->length != DES_BLOCK_SIZE)
+        return KRB5_BAD_MSIZE;
+
+    if (ivec != NULL)
+        memcpy(blockY, ivec->data, DES_BLOCK_SIZE);
+    else
+        memset(blockY, 0, DES_BLOCK_SIZE);
+
+    k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE);
+    while (k5_iov_cursor_get(&cursor, blockB)) {
+        store_64_n(load_64_n(blockB) ^ load_64_n(blockY), blockB);
+        olen = sizeof(blockY);
+        if (ucrypto_encrypt(CRYPTO_DES_ECB,
+                            key->keyblock.contents,
+                            key->keyblock.length,
+                            NULL, 0,
+                            blockB, sizeof(blockB),
+                            blockY, &olen) != CRYPTO_SUCCESS) {
+            return KRB5_CRYPTO_INTERNAL;
+        }
+    }
+
+    memcpy(output->data, blockY, DES_BLOCK_SIZE);
+    return 0;
+}
+
+const struct krb5_enc_provider krb5int_enc_des = {
+    DES_BLOCK_SIZE,
+    DES_KEY_BYTES, DES_KEY_SIZE,
+    k5_des_encrypt,
+    k5_des_decrypt,
+    k5_des_cbc_mac,
+    krb5int_des_init_state,
+    krb5int_default_free_state
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/enc_provider/des3.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,216 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/openssl/enc_provider/des.c */
+/*
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <libucrypto.h>
+
+#define DES3_BLOCK_SIZE 8
+#define DES3_KEY_SIZE 24
+#define DES3_KEY_BYTES 21
+
+static krb5_error_code
+validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data,
+         size_t num_data, size_t *inlen)
+{
+    size_t input_length = iov_total_length(data, num_data, FALSE);
+
+    if (key->keyblock.length != DES3_KEY_SIZE)
+        return KRB5_BAD_KEYSIZE;
+    if ((input_length % DES3_BLOCK_SIZE) != 0)
+        return KRB5_BAD_MSIZE;
+    if (ivec && (ivec->length != DES3_BLOCK_SIZE))
+        return KRB5_BAD_MSIZE;
+
+    if (inlen != NULL)
+        *inlen = input_length;
+
+    return 0;
+}
+
+static krb5_error_code
+k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+               size_t num_data)
+{
+    int ret;
+    size_t  olen, dlen;
+    uchar_t *obuf, *dbuf;
+    uchar_t tmp_iv[DES3_BLOCK_SIZE];
+    struct iov_cursor cursor;
+
+    ret = validate(key, ivec, data, num_data, &dlen);
+    if (ret != 0 || dlen == 0)
+        return ret;
+
+    if (ivec && ivec->data)
+        memcpy(tmp_iv, ivec->data, ivec->length);
+    else
+        memset(tmp_iv, 0, sizeof(tmp_iv));
+
+    olen = dlen;
+    obuf = malloc(olen);
+    if (!obuf)
+        return ENOMEM;
+
+    dbuf = malloc(dlen);
+    if (!dbuf){
+        free(obuf);
+        return ENOMEM;
+    }
+
+    /* Init iov cursor to gather data for encypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+    /* Get all that data into dbuf */
+    k5_iov_cursor_get(&cursor, dbuf);
+
+    if (ucrypto_encrypt(CRYPTO_DES3_CBC,
+                        key->keyblock.contents,
+                        key->keyblock.length,
+                        tmp_iv, sizeof(tmp_iv),
+                        dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+        ret = KRB5_CRYPTO_INTERNAL;
+    } else {
+        k5_iov_cursor_put(&cursor, obuf);
+    }
+
+    /*
+     * Updating the ivec arg, if present because of an old/obscure concept of
+     * cipher state that is being used by only BSD rlogin.  See RFCs 1391 and
+     * 1392 in regards to the vague description of cipher state.
+     */
+    if (!ret && ivec && ivec->data) {
+        /* Copy last block of cipher text output */
+        memcpy(ivec->data, obuf + (dlen - DES3_BLOCK_SIZE), DES3_BLOCK_SIZE);
+    }
+
+    zap(obuf, olen);
+    zap(dbuf, dlen);
+    free(obuf);
+    free(dbuf);
+
+    return ret;
+}
+
+static krb5_error_code
+k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
+               size_t num_data)
+{
+    int ret;
+    size_t  olen, dlen;
+    uchar_t *obuf, *dbuf;
+    uchar_t tmp_iv[DES3_BLOCK_SIZE];
+    struct iov_cursor cursor;
+
+    ret = validate(key, ivec, data, num_data, &dlen);
+    if (ret != 0 || dlen == 0)
+        return ret;
+
+    if (ivec && ivec->data)
+        memcpy(tmp_iv, ivec->data, ivec->length);
+    else
+        memset(tmp_iv, 0, sizeof(tmp_iv));
+
+    olen = dlen;
+    obuf = malloc(olen);
+    if (!obuf)
+        return ENOMEM;
+
+    dbuf = malloc(dlen);
+    if (!dbuf){
+        free(obuf);
+        return ENOMEM;
+    }
+
+    /* Init iov cursor to gather cipher text for decrypting (FALSE) */
+    k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+    /* Gather all that cipher text into dbuf */
+    k5_iov_cursor_get(&cursor, dbuf);
+
+    if (ucrypto_decrypt(CRYPTO_DES3_CBC,
+                        key->keyblock.contents,
+                        key->keyblock.length,
+                        tmp_iv, sizeof(tmp_iv),
+                        dbuf, dlen, obuf, &olen) != CRYPTO_SUCCESS) {
+        ret = KRB5_CRYPTO_INTERNAL;
+    } else {
+        k5_iov_cursor_put(&cursor, obuf);
+    }
+
+    /*
+     * Updating the ivec arg, if present because of an old/obscure concept of
+     * cipher state that is being used by only BSD rlogin.  See RFCs 1391 and
+     * 1392 in regards to the vague description of cipher state.
+     */
+    if (!ret && ivec && ivec->data) {
+        /* Copy last block of cipher text input */
+        memcpy(ivec->data, dbuf + (dlen - DES3_BLOCK_SIZE), DES3_BLOCK_SIZE);
+    }
+
+    zap(obuf, olen);
+    zap(dbuf, dlen);
+    free(obuf);
+    free(dbuf);
+
+    return ret;
+}
+
+const struct krb5_enc_provider krb5int_enc_des3 = {
+    DES3_BLOCK_SIZE,
+    DES3_KEY_BYTES, DES3_KEY_SIZE,
+    k5_des3_encrypt,
+    k5_des3_decrypt,
+    NULL,
+    krb5int_des_init_state,
+    krb5int_default_free_state
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/enc_provider/rc4.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,237 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/openssl/enc_provider/des.c */
+/*
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <libucrypto.h>
+
+/*
+ * The loopback field is NULL if uctx is uninitialized (no encrypt or decrypt
+ * operation has taken place), or is a pointer to the structure address if uctx
+ * is initialized.  If an application copies the state (not a valid operation,
+ * but one which happens to works with some other enc providers), we can detect
+ * it via the loopback field and return a sane error code.
+ */
+struct arcfour_state {
+    struct arcfour_state *loopback;
+    int op_type; /* encrypt, decrypt */
+    crypto_ctx_t uctx; /* ucrypto context */
+};
+#define ENCRYPT_OP 1
+#define DECRYPT_OP 2
+
+#define RC4_KEY_SIZE 16
+#define RC4_BLOCK_SIZE 1
+
+static krb5_error_code
+k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
+                   size_t num_data, int op_type)
+{
+    int ret = 0;
+    crypto_ctx_t local_uctx, *uctx; /* ucrypto context */
+    size_t len, i;
+    struct arcfour_state *arcstate;
+    krb5_boolean do_init = TRUE;
+
+    arcstate = (state != NULL) ? (struct arcfour_state *)state->data : NULL;
+    if (arcstate != NULL) {
+        /*
+         * If loopback points to arcstate we know that uctx has been init'ed
+         * but if it doesn't and it isn't NULL then arcstate has been corrupted
+         * which means we can't trust that uctx is valid.
+         */
+        if (arcstate->loopback == arcstate)
+            do_init = FALSE;
+        else if (arcstate->loopback != NULL)
+            return KRB5_CRYPTO_INTERNAL;
+
+        uctx = &arcstate->uctx;
+    } else {
+        /* Use the local ucrypto context, will need to be cleaned up in this
+         * function. */
+        uctx = &local_uctx;
+    }
+
+    if (do_init) {
+        if (op_type == ENCRYPT_OP) {
+            if (ucrypto_encrypt_init(uctx, CRYPTO_RC4,
+                                     key->keyblock.contents,
+                                     key->keyblock.length,
+                                     NULL, 0) != CRYPTO_SUCCESS) {
+                return KRB5_CRYPTO_INTERNAL;
+            }
+        } else {
+            if (ucrypto_decrypt_init(uctx, CRYPTO_RC4,
+                                     key->keyblock.contents,
+                                     key->keyblock.length,
+                                     NULL, 0) != CRYPTO_SUCCESS) {
+                return KRB5_CRYPTO_INTERNAL;
+            }
+        }
+
+        /* Saved ucrypto context is init'ed, mark as initialized. */
+        if (arcstate) {
+            arcstate->loopback = arcstate;
+            arcstate->op_type = op_type;
+        }
+    }
+
+    for (i = 0; i < num_data; i++) {
+        krb5_crypto_iov *iov = &data[i];
+
+        if (ENCRYPT_IOV(iov)) {
+            len = (size_t)iov->data.length;
+
+            if (op_type == ENCRYPT_OP) {
+                if (ucrypto_encrypt_update(uctx,
+                                           (const uchar_t *)iov->data.data,
+                                           len,
+                                           (uchar_t *)iov->data.data,
+                                           &len) != CRYPTO_SUCCESS) {
+                    ret = KRB5_CRYPTO_INTERNAL;
+                    break;
+                }
+            } else {
+                if (ucrypto_decrypt_update(uctx,
+                                           (const uchar_t *)iov->data.data,
+                                           len,
+                                           (uchar_t *)iov->data.data,
+                                           &len) != CRYPTO_SUCCESS) {
+                    ret = KRB5_CRYPTO_INTERNAL;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (!arcstate) {
+        /* Local ucrypto context is not saved, clean it up now. */
+        len = 0;
+        if (op_type == ENCRYPT_OP)
+            (void)ucrypto_encrypt_final(uctx, NULL, &len);
+        else
+            (void)ucrypto_decrypt_final(uctx, NULL, &len);
+    }
+
+    return ret;
+}
+
+static krb5_error_code
+k5_arcfour_encrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
+                   size_t num_data)
+{
+    return k5_arcfour_docrypt(key, state, data, num_data, ENCRYPT_OP);
+}
+
+static krb5_error_code
+k5_arcfour_decrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
+                   size_t num_data)
+{
+    return k5_arcfour_docrypt(key, state, data, num_data, DECRYPT_OP);
+}
+
+static krb5_error_code
+krb5int_arcfour_init_state(const krb5_keyblock *key, krb5_keyusage usage,
+                           krb5_data *state)
+{
+    struct arcfour_state *arcstate;
+
+    arcstate = calloc(1, sizeof (*arcstate));
+    if (arcstate == NULL)
+        return ENOMEM;
+
+    state->data = (char *)arcstate;
+    state->length = sizeof (*arcstate);
+
+    return 0;
+}
+
+static void
+krb5int_arcfour_free_state(krb5_data *state)
+{
+    struct arcfour_state *arcstate = (struct arcfour_state *)state->data;
+
+    /* If arcstate->loopback == arcstate then the ucrypto context was init'ed
+     * and uctx clean up is required. */
+    if (arcstate && arcstate->loopback == arcstate) {
+        size_t len = 0;
+
+        if (arcstate->op_type == ENCRYPT_OP)
+            (void) ucrypto_encrypt_final(&arcstate->uctx, NULL, &len);
+        else
+            (void) ucrypto_decrypt_final(&arcstate->uctx, NULL, &len);
+    }
+
+    free(arcstate);
+    state->data = NULL;
+    state->length = 0;
+
+    return;
+}
+
+const struct krb5_enc_provider krb5int_enc_arcfour = {
+    /* This seems to work... although I am not sure what the
+       implications are in other places in the kerberos library */
+    RC4_BLOCK_SIZE,
+    /* Keysize is arbitrary in arcfour, but the constraints of the
+       system, and to attempt to work with the MSFT system forces us
+       to 16byte/128bit.  Since there is no parity in the key, the
+       byte and length are the same.  */
+    RC4_KEY_SIZE, RC4_KEY_SIZE,
+    k5_arcfour_encrypt,
+    k5_arcfour_decrypt,
+    NULL,
+    krb5int_arcfour_init_state,
+    krb5int_arcfour_free_state
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/hash_provider/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,27 @@
+mydir=lib$(S)crypto$(S)ucrypto$(S)hash_provider
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../../krb -I$(srcdir)/..
+
+STLIBOBJS= \
+	hash_crc32.o 	\
+	hash_md4.o 	\
+	hash_ucrypto.o
+
+OBJS=   $(OUTPRE)hash_crc32.$(OBJEXT) 	\
+	$(OUTPRE)hash_md4.$(OBJEXT) 	\
+	$(OUTPRE)hash_ucrypto.$(OBJEXT)
+
+SRCS=	$(srcdir)/hash_crc32.c	\
+	$(srcdir)/hash_md4.c 	\
+	$(srcdir)/hash_ucrypto.c
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/hash_provider/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,51 @@
+#
+# Generated makefile dependencies follow.
+#
+hash_crc32.so hash_crc32.po $(OUTPRE)hash_crc32.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  hash_crc32.c
+hash_md4.so hash_md4.po $(OUTPRE)hash_md4.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  hash_md4.c
+hash_md5.so hash_md5.po $(OUTPRE)hash_md5.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  hash_md5.c
+hash_sha1.so hash_sha1.po $(OUTPRE)hash_sha1.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  hash_sha1.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/hash_provider/hash_md4.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,59 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <md4.h>
+
+static krb5_error_code
+k5_md4_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+{
+    MD4_CTX md4ctx;
+    size_t i;
+
+    if (output->length != MD4_DIGEST_LENGTH)
+        return KRB5_CRYPTO_INTERNAL;
+
+    MD4Init(&md4ctx);
+    for (i = 0; i < num_data; i++) {
+        const krb5_data *d = &data[i].data;
+
+        if (SIGN_IOV(&data[i]))
+            MD4Update(&md4ctx, d->data, (size_t)d->length);
+    }
+    MD4Final(output->data, &md4ctx);
+    return 0;
+}
+
+const struct krb5_hash_provider krb5int_hash_md4 = {
+    "MD4",
+    MD4_DIGEST_LENGTH,
+    MD4_HMAC_BLOCK_SIZE,
+    k5_md4_hash
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/hash_provider/hash_ucrypto.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,110 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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
+ * COPYRIGHT HOLDER 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.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <libucrypto.h>
+
+#define MD5_DIGEST_LENGTH 16
+#define MD5_DATASIZE    64
+#define SHA_DIGEST_LENGTH  20
+#define SHA_DATASIZE    64
+
+static krb5_error_code
+hash_ucrypto(int ucrypto_type, size_t digest_size, const krb5_crypto_iov *data,
+             size_t num_data, krb5_data *output)
+{
+    crypto_ctx_t uctx; /* ucrypto context */
+    size_t i;
+    int ret = 0;
+
+    if (output->length != digest_size)
+        return KRB5_CRYPTO_INTERNAL;
+
+    if (ucrypto_digest_init(&uctx, ucrypto_type, NULL, 0) != CRYPTO_SUCCESS)
+        return KRB5_CRYPTO_INTERNAL;
+
+    for (i = 0; i < num_data; i++) {
+        const krb5_data *d = &data[i].data;
+        if (SIGN_IOV(&data[i])) {
+            if (ucrypto_digest_update(&uctx, (uchar_t *)d->data,
+                                      (size_t)d->length) != CRYPTO_SUCCESS) {
+                ret = KRB5_CRYPTO_INTERNAL;
+                break;
+            }
+        }
+    }
+
+    if (ret) {
+        /* error, just clean up ucrypto context */
+        (void)ucrypto_digest_final(&uctx, NULL, 0);
+    } else {
+        size_t outlen = (size_t)output->length;
+
+        if (ucrypto_digest_final(&uctx, (uchar_t *)output->data, &outlen)
+            != CRYPTO_SUCCESS) {
+            ret = KRB5_CRYPTO_INTERNAL;
+        } else {
+            output->length = (uint_t)outlen;
+        }
+    }
+
+    return ret;
+}
+
+static krb5_error_code
+hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+{
+    return hash_ucrypto(CRYPTO_MD5, MD5_DIGEST_LENGTH, data, num_data, output);
+}
+
+static krb5_error_code
+hash_sha1(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+{
+    return hash_ucrypto(CRYPTO_SHA1, SHA_DIGEST_LENGTH, data, num_data,
+                        output);
+}
+
+const struct krb5_hash_provider krb5int_hash_md5 = {
+    "MD5",
+    MD5_DIGEST_LENGTH,
+    MD5_DATASIZE,
+    hash_md5
+};
+
+const struct krb5_hash_provider krb5int_hash_sha1 = {
+    "SHA1",
+    SHA_DIGEST_LENGTH,
+    SHA_DATASIZE,
+    hash_sha1
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/hmac.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,220 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/ucrypto/hmac.c */
+/*
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "crypto_int.h"
+#include <libucrypto.h>
+
+/*
+ * This a copy from the EVP_MAX_MD_SIZE define in /usr/include/openssl/evp.h
+ */
+#define MAX_MAC_SIZE 64
+
+/* ucrypto doesn't support this so creating this define for convenience */
+#define CRYPTO_MD4_HMAC -4
+
+/* Return ucrypto hmac mech type (mostly, see above) */
+static int
+map_digest(const struct krb5_hash_provider *hash)
+{
+    if (!strncmp(hash->hash_name, "SHA1",4))
+        return CRYPTO_SHA1_HMAC;
+    else if (!strncmp(hash->hash_name, "MD5", 3))
+        return CRYPTO_MD5_HMAC;
+    else if (!strncmp(hash->hash_name, "MD4", 3))
+        return CRYPTO_MD4_HMAC;
+    else
+        return -1;
+}
+
+/*
+ * Took this from the MIT builtin hmac.c since libucrypto does not support HMAC
+ * MD4.  This does a HMAC processing using the basic MD4 hash.
+ */
+static krb5_error_code
+krb5int_hmac_keyblock_builtin(const struct krb5_hash_provider *hash,
+                      const krb5_keyblock *keyblock,
+                      const krb5_crypto_iov *data, size_t num_data,
+                      krb5_data *output)
+{
+    unsigned char *xorkey = NULL, *ihash = NULL;
+    unsigned int i;
+    krb5_crypto_iov *ihash_iov = NULL, ohash_iov[2];
+    krb5_data hashout;
+    krb5_error_code ret;
+
+    /* Allocate space for the xor key, hash input vector, and inner hash */
+    xorkey = k5alloc(hash->blocksize, &ret);
+    if (xorkey == NULL)
+        goto cleanup;
+    ihash = k5alloc(hash->hashsize, &ret);
+    if (ihash == NULL)
+        goto cleanup;
+    ihash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret);
+    if (ihash_iov == NULL)
+        goto cleanup;
+
+    /* Create the inner padded key. */
+    memset(xorkey, 0x36, hash->blocksize);
+    for (i = 0; i < keyblock->length; i++)
+        xorkey[i] ^= keyblock->contents[i];
+
+    /* Compute the inner hash over the inner key and input data. */
+    ihash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+    ihash_iov[0].data = make_data(xorkey, hash->blocksize);
+    memcpy(ihash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
+    hashout = make_data(ihash, hash->hashsize);
+    ret = hash->hash(ihash_iov, num_data + 1, &hashout);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Create the outer padded key. */
+    memset(xorkey, 0x5c, hash->blocksize);
+    for (i = 0; i < keyblock->length; i++)
+        xorkey[i] ^= keyblock->contents[i];
+
+    /* Compute the outer hash over the outer key and inner hash value. */
+    ohash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+    ohash_iov[0].data = make_data(xorkey, hash->blocksize);
+    ohash_iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+    ohash_iov[1].data = make_data(ihash, hash->hashsize);
+    output->length = hash->hashsize;
+    ret = hash->hash(ohash_iov, 2, output);
+    if (ret != 0)
+        memset(output->data, 0, output->length);
+
+cleanup:
+    zapfree(xorkey, hash->blocksize);
+    zapfree(ihash, hash->hashsize);
+    free(ihash_iov);
+    return ret;
+}
+
+static krb5_error_code
+krb5int_hmac_keyblock_ucrypto(int ucrypto_hmac_type,
+                              const krb5_keyblock *keyblock,
+                              const krb5_crypto_iov *data, size_t num_data,
+                              krb5_data *output)
+{
+    uchar_t mac[MAX_MAC_SIZE];
+    size_t mac_len = sizeof (mac);
+    uchar_t *dbuf;
+    size_t dlen;
+    struct iov_cursor cursor;
+    int ret = 0;
+
+    /* find total amount/length of signing data (TRUE) */
+    dlen = iov_total_length(data, num_data, TRUE);
+    dbuf = malloc(dlen);
+    if (!dbuf){
+        return ENOMEM;
+    }
+
+    /* Init iovec cursor to gather signing data (TRUE) */
+    k5_iov_cursor_init(&cursor, data, num_data, dlen, TRUE);
+    /* gather all data that the MAC will cover into dbuf */
+    k5_iov_cursor_get(&cursor, dbuf);
+
+    if (ucrypto_mac(ucrypto_hmac_type,
+                    keyblock->contents, keyblock->length,
+                    NULL, 0,
+                    dbuf, dlen,
+                    mac, &mac_len) != CRYPTO_SUCCESS) {
+        ret = KRB5_CRYPTO_INTERNAL;
+        memset(output->data, 0, output->length);
+    } else {
+        if (mac_len <= output->length) {
+            output->length = (uint_t)mac_len;
+            memcpy(output->data, mac, output->length);
+        }
+    }
+
+    free(dbuf);
+    return ret;
+}
+
+krb5_error_code
+krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
+                      const krb5_keyblock *keyblock,
+                      const krb5_crypto_iov *data, size_t num_data,
+                      krb5_data *output)
+{
+    int ucrypto_hmac_type;
+
+    if (keyblock->length > hash->blocksize)
+        return KRB5_CRYPTO_INTERNAL;
+    if (output->length < hash->hashsize)
+        return KRB5_BAD_MSIZE;
+
+    ucrypto_hmac_type = map_digest(hash);
+    switch (ucrypto_hmac_type) {
+    case CRYPTO_SHA1_HMAC:
+    case CRYPTO_MD5_HMAC:
+        return krb5int_hmac_keyblock_ucrypto(ucrypto_hmac_type, keyblock,
+                                             data, num_data, output);
+    case CRYPTO_MD4_HMAC:
+        return krb5int_hmac_keyblock_builtin(hash, keyblock, data, num_data,
+                                             output);
+    default:
+        return (KRB5_CRYPTO_INTERNAL); /* unsupported alg */
+    }
+}
+
+krb5_error_code
+krb5int_hmac(const struct krb5_hash_provider *hash, krb5_key key,
+             const krb5_crypto_iov *data, size_t num_data,
+             krb5_data *output)
+{
+    return krb5int_hmac_keyblock(hash, &key->keyblock, data, num_data, output);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/init.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,38 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/openssl/init.c - Module init and cleanup functions */
+/*
+ * Copyright (C) 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "crypto_int.h"
+
+int
+krb5int_crypto_impl_init(void)
+{
+    return 0;
+}
+
+void
+krb5int_crypto_impl_cleanup(void)
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/md4/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,6 @@
+# Placeholder since all crypto modules must have the same structure.
+mydir=lib$(S)crypto$(S)ucrypto$(S)md4
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/md4/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,1 @@
+# No dependencies here.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/md5/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,6 @@
+# Placeholder since all crypto modules must have the same structure.
+mydir=lib$(S)crypto$(S)ucrypto$(S)md5
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/md5/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,1 @@
+# No dependencies here.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/sha1/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,6 @@
+# Placeholder since all crypto modules must have the same structure.
+mydir=lib$(S)crypto$(S)ucrypto$(S)sha1
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/sha1/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,1 @@
+# No dependencies here.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/sha2/Makefile.in	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,6 @@
+# Placeholder since all crypto modules must have the same structure.
+mydir=lib$(S)crypto$(S)ucrypto$(S)sha2
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+all-unix:: all-libobjs
+clean-unix:: clean-libobjs
+@libobj_frag@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/sha2/deps	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,1 @@
+# No dependencies here.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/Solaris/ucrypto/stubs.c	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,64 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/openssl/stubs.c - OpenSSL stub functions */
+/*
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This file defines symbols which must be exported by libk5crypto because they
+ * are in the export list (for the sake of test programs), but which are not
+ * used when Solaris ucrypto is the back end.
+ */
+
+#include "k5-int.h"
+
+void krb5int_aes_enc_blk(void);
+void krb5int_aes_enc_key(void);
+void k5_sha256_final(void);
+void k5_sha256_init(void);
+void k5_sha256_update(void);
+
+void krb5int_aes_enc_blk(void)
+{
+    abort();
+}
+
+void krb5int_aes_enc_key(void)
+{
+    abort();
+}
+
+void k5_sha256_final(void)
+{
+    abort();
+}
+
+void k5_sha256_init(void)
+{
+    abort();
+}
+
+void k5_sha256_update(void)
+{
+    abort();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/patches/079-ucrypto.patch	Fri Mar 24 12:29:03 2017 -0500
@@ -0,0 +1,22 @@
+#
+# This patch allows krb to be built to use the Solaris libucrypto crypto
+# library to support the enctypes and other users of the krb crypto provider
+# functions.
+#
+# This is Solaris specific behavior that MIT will not take upstream.
+#
+# Patch source: in-house
+#
+
+--- a/src/configure.in
++++ b/src/configure.in
+@@ -250,6 +250,9 @@ nss)
+   ])], [], [AC_MSG_ERROR([NSS version 3.13 or later required.])])
+   CFLAGS=$save_CFLAGS
+   ;;
++ucrypto)
++  CRYPTO_IMPL_LIBS="-lucrypto"
++  ;;
+ *)
+   AC_MSG_ERROR([Unknown crypto implementation $withval])
+   ;;