components/openssl/openssl-1.0.0/engines/t4/eng_t4.c
changeset 603 1b966e9a6b03
parent 580 abb7ba207fc9
child 682 c6e4f94fd35d
--- a/components/openssl/openssl-1.0.0/engines/t4/eng_t4.c	Tue Nov 29 05:42:26 2011 -0800
+++ b/components/openssl/openssl-1.0.0/engines/t4/eng_t4.c	Tue Nov 29 11:18:53 2011 -0800
@@ -1,22 +1,56 @@
 /*
- * CDDL HEADER START
+ * This product includes cryptographic software developed by the OpenSSL
+ * Project for use in the OpenSSL Toolkit (http://www.openssl.org/).
+ */
+
+/*
+ * ====================================================================
+ * Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    [email protected].
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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.
+ * ====================================================================
  */
 
 /*
@@ -35,10 +69,9 @@
 #include <sys/types.h>
 #include <sys/auxv.h>	/* getisax() */
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <errno.h>
-
-#include <openssl/bio.h>
 #include <openssl/aes.h>
 #include <openssl/engine.h>
 #include "eng_t4_aes_asm.h"
@@ -114,7 +147,7 @@
 void
 ENGINE_load_t4(void)
 {
-#ifdef COMPILE_HW_T4
+#ifdef	COMPILE_HW_T4
 	ENGINE *toadd = ENGINE_new();
 	if (toadd != NULL) {
 		if (t4_bind_helper(toadd, ENGINE_T4_ID) != 0) {
@@ -131,15 +164,14 @@
 
 #ifdef	COMPILE_HW_T4
 static int t4_bind(ENGINE *e);
-#ifndef DYNAMIC_ENGINE
+#ifndef	DYNAMIC_ENGINE
 #pragma inline(t4_bind)
 #endif
 static t4_cipher_id get_cipher_index_by_nid(int nid);
 #pragma inline(get_cipher_index_by_nid)
-static boolean_t t4_aes_instructions_present(void);
-#pragma inline(t4_aes_instructions_present)
-static boolean_t t4_digest_instructions_present(void);
-#pragma inline(t4_digest_instructions_present)
+static void t4_instructions_present(_Bool *aes_present, _Bool *des_present,
+    _Bool *digest_present);
+#pragma inline(t4_instructions_present)
 
 /* Digest registration function. Called by ENGINE_set_ciphers() */
 int t4_get_all_digests(ENGINE *e, const EVP_MD **digest,
@@ -166,27 +198,24 @@
 /* Static variables */
 /* This can't be const as NID*ctr is inserted when the engine is initialized */
 static int t4_cipher_nids[] = {
-	NID_aes_128_cbc,
-	NID_aes_192_cbc,
-	NID_aes_256_cbc,
+	NID_aes_128_cbc, NID_aes_192_cbc, NID_aes_256_cbc,
 #ifndef	SOLARIS_NO_AES_CFB128
-	NID_aes_128_cfb128,
-	NID_aes_192_cfb128,
-	NID_aes_256_cfb128,
+	NID_aes_128_cfb128, NID_aes_192_cfb128, NID_aes_256_cfb128,
 #endif
 #ifndef	SOLARIS_NO_AES_CTR
-	NID_undef, /* NID_t4_aes_128_ctr */
-	NID_undef, /* NID_t4_aes_192_ctr */
-	NID_undef, /* NID_t4_aes_256_ctr */
+	/* NID_t4_aes_128_ctr, NID_t4_aes_192, NID_t4_aes_256 */
+	NID_undef, NID_undef, NID_undef,
 #endif
-	NID_aes_128_ecb,
-	NID_aes_192_ecb,
-	NID_aes_256_ecb,
+	NID_aes_128_ecb, NID_aes_192_ecb, NID_aes_256_ecb,
+#ifndef	OPENSSL_NO_DES
+	/* Must be at end of list (see t4_des_cipher_count in t4_bind() */
+	NID_des_cbc, NID_des_ede3_cbc, NID_des_ecb, NID_des_ede3_ecb,
+#endif
 };
-static const int t4_cipher_count =
+static const int t4_des_cipher_count = 4;
+static int t4_cipher_count =
 	(sizeof (t4_cipher_nids) / sizeof (t4_cipher_nids[0]));
 
-
 /*
  * Cipher Table for all supported symmetric ciphers.
  * Must be in same order as t4_cipher_id.
@@ -260,13 +289,12 @@
  * EVP_CIPHER is defined in evp.h.  To maintain binary compatibility the
  * definition cannot be modified.
  * Stuff specific to the t4 engine is kept in t4_cipher_ctx_t, which is
- * pointed to by the last field, app_data.
+ * pointed to by cipher_data or md_data
  *
  * Fields: nid, block_size, key_len, iv_len, flags,
  *	init(), do_cipher(), cleanup(),
  *	ctx_size,
  *	set_asn1_parameters(), get_asn1_parameters(), ctrl(), app_data
- * For the T4 engine, field app_data points to t4_cipher_ctx_t.
  */
 
 static const EVP_CIPHER t4_aes_128_cbc = {
@@ -393,38 +421,173 @@
 	NULL, NULL, NULL, NULL
 };
 
+#ifndef	OPENSSL_NO_DES
+extern const EVP_CIPHER t4_des_cbc;
+extern const EVP_CIPHER t4_des3_cbc;
+extern const EVP_CIPHER t4_des_ecb;
+extern const EVP_CIPHER t4_des3_ecb;
+#endif	/* OPENSSL_NO_DES */
+
+
+/*
+ * Message Digest variables
+ */
+static const int t4_digest_nids[] = {
+#ifndef	OPENSSL_NO_MD5
+	NID_md5,
+#endif
+#ifndef	OPENSSL_NO_SHA
+#ifndef	OPENSSL_NO_SHA1
+	NID_sha1,
+#endif
+#ifndef	OPENSSL_NO_SHA256
+	NID_sha224,
+	NID_sha256,
+#endif
+#ifndef	OPENSSL_NO_SHA512
+	NID_sha384,
+	NID_sha512,
+#endif
+#endif	/* !OPENSSL_NO_SHA */
+};
+static const int t4_digest_count =
+	(sizeof (t4_digest_nids) / sizeof (t4_digest_nids[0]));
+
+#ifndef	OPENSSL_NO_MD5
+extern const EVP_MD t4_md5;
+#endif
+#ifndef	OPENSSL_NO_SHA
+#ifndef	OPENSSL_NO_SHA1
+extern const EVP_MD t4_sha1;
+#endif
+#ifndef	OPENSSL_NO_SHA256
+extern const EVP_MD t4_sha224;
+extern const EVP_MD t4_sha256;
+#endif
+#ifndef	OPENSSL_NO_SHA512
+extern const EVP_MD t4_sha384;
+extern const EVP_MD t4_sha512;
+#endif
+#endif	/* !OPENSSL_NO_SHA */
+
+/*
+ * Message Digest functions
+ */
 
 /*
- * Return true if executing on a SPARC processor with AES instruction support,
- * such as a T4; otherwise false.
+ * Registered by the ENGINE with ENGINE_set_digests().
+ * Finds out how to deal with a particular digest NID in the ENGINE.
  */
-static boolean_t
-t4_aes_instructions_present(void)
+/* ARGSUSED */
+int
+t4_get_all_digests(ENGINE *e, const EVP_MD **digest,
+    const int **nids, int nid)
 {
-	uint_t ui;
+	if (digest == NULL) { /* return a list of all supported digests */
+		*nids = (t4_digest_count > 0) ? t4_digest_nids : NULL;
+		return (t4_digest_count);
+	}
 
-	(void) getisax(&ui, 1);
-	return ((ui & AV_SPARC_AES) != 0);
+	switch (nid) {
+#ifndef	OPENSSL_NO_MD5
+	case NID_md5:
+		*digest = &t4_md5;
+		break;
+#endif
+#ifndef	OPENSSL_NO_SHA
+#ifndef	OPENSSL_NO_SHA1
+	/*
+	 * A special case. For "openssl dgst -dss1 ...",
+	 * OpenSSL calls EVP_get_digestbyname() on "dss1" which ends up
+	 * calling t4_get_all_digests() for NID_dsa. Internally, if an
+	 * engine is not used, OpenSSL uses SHA1_Init() as expected for
+	 * DSA. So, we must return t4_sha1 for NID_dsa as well. Note
+	 * that this must have changed between 0.9.8 and 1.0.0 since we
+	 * did not have the problem with the 0.9.8 version.
+	 */
+	case NID_dsa:
+	case NID_sha1:
+		*digest = &t4_sha1;
+		break;
+#endif
+#ifndef	OPENSSL_NO_SHA256
+	case NID_sha224:
+		*digest = &t4_sha224;
+		break;
+	case NID_sha256:
+		*digest = &t4_sha256;
+		break;
+#endif
+#ifndef	OPENSSL_NO_SHA512
+	case NID_sha384:
+		*digest = &t4_sha384;
+		break;
+	case NID_sha512:
+		*digest = &t4_sha512;
+		break;
+#endif
+#endif	/* !OPENSSL_NO_SHA */
+	default:
+		/* digest not supported */
+		*digest = NULL;
+		return (0);
+	}
+
+	return (1);
 }
 
 
 /*
- * Return true if executing on a SPARC processor with MD5/SHA1/SHA{1,256,512}
- * instruction support, such as a T4; otherwise false.
+ * Utility Functions
  */
-static boolean_t
-t4_digest_instructions_present(void)
+
+/*
+ * Set aes_present, des_present, and digest_present to 0 or 1 depending on
+ * whether the current SPARC processor supports AES, DES, and
+ * MD5/SHA1/SHA256/SHA512, respectively.
+ */
+static void
+t4_instructions_present(_Bool *aes_present, _Bool *des_present,
+    _Bool *digest_present)
 {
+#ifdef	OPENSSL_NO_DES
+#undef	AV_SPARC_DES
+#define	AV_SPARC_DES	0
+#endif
+#ifdef	OPENSSL_NO_MD5
+#undef	AV_SPARC_MD5
+#define	AV_SPARC_MD5	0
+#endif
 #ifndef	OPENSSL_NO_SHA
-#define	UI_MASK	(AV_SPARC_MD5 | AV_SPARC_SHA1 | AV_SPARC_SHA256 | \
+#ifdef	OPENSSL_NO_SHA1
+#undef	AV_SPARC_SHA1
+#define	AV_SPARC_SHA1	0
+#endif
+#ifdef	OPENSSL_NO_SHA256
+#undef	AV_SPARC_SHA256
+#define	AV_SPARC_SHA256	0
+#endif
+#ifdef	OPENSSL_NO_SHA512
+#undef	AV_SPARC_SHA512
+#define	AV_SPARC_SHA512	0
+#endif
+#else
+#undef	AV_SPARC_SHA1
+#undef	AV_SPARC_SHA256
+#undef	AV_SPARC_SHA512
+#define	AV_SPARC_SHA1	0
+#define	AV_SPARC_SHA256	0
+#define	AV_SPARC_SHA512	0
+#endif	/* !OPENSSL_NO_SHA */
+
+#define	DIGEST_MASK	(AV_SPARC_MD5 | AV_SPARC_SHA1 | AV_SPARC_SHA256 | \
 	AV_SPARC_SHA512)
-#else
-#define	UI_MASK	(AV_SPARC_MD5)
-#endif
 	uint_t		ui;
 
 	(void) getisax(&ui, 1);
-	return ((ui & UI_MASK) == UI_MASK);
+	*aes_present = (ui & AV_SPARC_AES) != 0;
+	*des_present = (ui & AV_SPARC_DES) != 0;
+	*digest_present = (ui & DIGEST_MASK) == DIGEST_MASK;
 }
 
 
@@ -595,6 +758,20 @@
 		*cipher = &t4_aes_256_cfb128;
 		break;
 #endif	/* !SOLARIS_NO_AES_CFB128 */
+#ifndef	OPENSSL_NO_DES
+	case NID_des_cbc:
+		*cipher = &t4_des_cbc;
+		break;
+	case NID_des_ede3_cbc:
+		*cipher = &t4_des3_cbc;
+		break;
+	case NID_des_ecb:
+		*cipher = &t4_des_ecb;
+		break;
+	case NID_des_ede3_ecb:
+		*cipher = &t4_des3_ecb;
+		break;
+#endif	/* !OPENSSL_NO_DES */
 
 	default:
 #ifndef	SOLARIS_NO_AES_CTR
@@ -678,7 +855,7 @@
 	if (((unsigned long)key & 0x7) == 0) /* already aligned */
 		aligned_key = (uint64_t *)key;
 	else { /* key is not 8-byte aligned */
-#ifdef DEBUG_T4
+#ifdef	DEBUG_T4
 		(void) fprintf(stderr, "T4: key is not 8 byte aligned\n");
 #endif
 		(void) memcpy(aligned_key_buffer, key, key_len);
@@ -721,7 +898,7 @@
 	/* Save index to cipher */
 	tctx->index = index;
 
-	/* Process IV */
+	/* Align IV, if needed */
 	if (t4_cipher->iv_len <= 0) { /* no IV (such as with ECB mode) */
 		tctx->iv = NULL;
 	} else if (((unsigned long)ctx->iv & 0x7) == 0) { /* already aligned */
@@ -731,7 +908,7 @@
 		(void) memcpy(tctx->aligned_iv_buffer, ctx->iv,
 		    ctx->cipher->iv_len);
 		tctx->iv = tctx->aligned_iv_buffer;
-#ifdef DEBUG_T4
+#ifdef	DEBUG_T4
 		(void) fprintf(stderr,
 		    "t4_cipher_init_aes: IV is not 8 byte aligned\n");
 		(void) fprintf(stderr,
@@ -806,8 +983,7 @@
 	} else { /* decrypt */						\
 		t4_aes_load_keys_for_decrypt(t4_ks);			\
 		t4_aes_decrypt(t4_ks, (uint64_t *)bufin,		\
-		    (uint64_t *)bufout,					\
-		    (size_t)inl, iv);					\
+		    (uint64_t *)bufout, (size_t)inl, iv);		\
 	}								\
 									\
 	/* Cleanup */							\
@@ -909,21 +1085,21 @@
 static int
 t4_bind(ENGINE *e)
 {
-	static int aes_engage = -1, digest_engage = -1;
+	_Bool aes_engage, digest_engage, des_engage;
 
-	if (aes_engage == -1) {
-		aes_engage = (t4_aes_instructions_present() != 0);
+	t4_instructions_present(&aes_engage, &des_engage, &digest_engage);
+#ifdef	DEBUG_T4
+	(void) fprintf(stderr,
+	    "t4_bind: engage aes=%d, des=%d, digest=%d\n",
+	    aes_engage, des_engage, digest_engage);
+#endif
+#ifndef	OPENSSL_NO_DES
+	if (!des_engage) { /* Remove DES ciphers from list */
+		t4_cipher_count -= t4_des_cipher_count;
 	}
-	if (digest_engage == -1) {
-		digest_engage = (t4_digest_instructions_present() != 0);
-	}
-
-#ifdef DEBUG_T4
-	(void) fprintf(stderr,
-	    "t4_bind: engage aes=%d, digest=%d\n", aes_engage, digest_engage);
 #endif
 
-#ifndef  SOLARIS_NO_AES_CTR
+#ifndef	SOLARIS_NO_AES_CTR
 	/*
 	 * We must do this before we start working with slots since we need all
 	 * NIDs there.
@@ -936,7 +1112,7 @@
 	}
 #endif	/* !SOLARIS_NO_AES_CTR */
 
-#ifdef DEBUG_T4
+#ifdef	DEBUG_T4
 	(void) fprintf(stderr, "t4_cipher_count = %d; t4_cipher_nids[] =\n",
 	    t4_cipher_count);
 	for (int i = 0; i < t4_cipher_count; ++i) {
@@ -982,7 +1158,7 @@
 }
 
 
-#ifdef DYNAMIC_ENGINE
+#ifdef	DYNAMIC_ENGINE
 IMPLEMENT_DYNAMIC_CHECK_FN()
 IMPLEMENT_DYNAMIC_BIND_FN(t4_bind_helper)
 #endif	/* DYNAMIC_ENGINE */