Print this page
5007142 Add ntohll and htonll to sys/byteorder.h
6717509 Need to use bswap/bswapq for byte swap of 64-bit integer on x32/x64
PSARC 2008/474

@@ -19,16 +19,14 @@
  *
  * CDDL HEADER END
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident   "%Z%%M% %I%     %E% SMI"
-
 /*
  * Deimos - cryptographic acceleration based upon Broadcom 582x.
  */
 
 #include <sys/types.h>

@@ -38,10 +36,15 @@
 #include <sys/note.h>
 #include <sys/crypto/common.h>
 #include <sys/crypto/spi.h>
 #include <sys/crypto/dca.h>
 
+#if defined(__i386) || defined(__amd64)
+#include <sys/byteorder.h>
+#define UNALIGNED_POINTERS_PERMITTED
+#endif
+
 /*
  * 3DES implementation.
  */
 
 static int dca_3desstart(dca_t *, uint32_t, dca_request_t *);

@@ -72,13 +75,19 @@
 
         /*
          * If cd_miscdata non-null then this contains the IV.
          */
         if (in->cd_miscdata != NULL) {
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                uint32_t        *p = (uint32_t *)in->cd_miscdata;
+                des_ctx->dr_ctx.iv[0] = htonl(p[0]);
+                des_ctx->dr_ctx.iv[1] = htonl(p[1]);
+#else
                 uchar_t *p = (uchar_t *)in->cd_miscdata;
                 des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
                 des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         }
 
         if (len > dca_length(out)) {
                 DBG(dca, DWARN, "inadequate output space (need %d, got %d)",
                     len, dca_length(out));

@@ -166,13 +175,19 @@
         len = ROUNDDOWN(rawlen, DESBLOCK);
         /*
          * If cd_miscdata non-null then this contains the IV.
          */
         if (in->cd_miscdata != NULL) {
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                uint32_t        *p = (uint32_t *)in->cd_miscdata;
+                des_ctx->dr_ctx.iv[0] = htonl(p[0]);
+                des_ctx->dr_ctx.iv[1] = htonl(p[1]);
+#else
                 uchar_t *p = (uchar_t *)in->cd_miscdata;
                 des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
                 des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         }
 
         if (len > dca_length(out)) {
                 DBG(dca, DWARN, "not enough output space (need %d, got %d)",
                     len, dca_length(out));

@@ -390,11 +405,15 @@
          * we will lose it.  (For encrypt, we grab the IV AFTER encryption,
          * in dca_3desdone.
          */
         if (flags & DR_DECRYPT) {
                 uchar_t         ivstore[DESBLOCK];
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                uint32_t        *ivp = (uint32_t *)ivstore;
+#else
                 uchar_t         *ivp = ivstore;
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
 
                 /* get last 8 bytes of ciphertext for IV of next op */
                 /*
                  * If we're processing only a DESBLOCKS worth of data
                  * and there is active residual present then it will be

@@ -418,14 +437,19 @@
                             "dca_3desstart: dca_getbufbytes() failed");
                         return (rv);
                 }
 
                 /* store as a pair of native 32-bit values */
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                ctx->dr_ctx.iv[0] = htonl(ivp[0]);
+                ctx->dr_ctx.iv[1] = htonl(ivp[1]);
+#else
                 ctx->dr_ctx.iv[0] =
                     ivp[0]<<24 | ivp[1]<<16 | ivp[2]<<8 | ivp[3];
                 ctx->dr_ctx.iv[1] =
                     ivp[4]<<24 | ivp[5]<<16 | ivp[6]<<8 | ivp[7];
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         }
 
         /* For now we force a pullup.  Add direct DMA later. */
         reqp->dr_flags &= ~(DR_SCATTER | DR_GATHER);
         if ((len < dca_mindma) || (ctx->dr_ctx.activeresidlen > 0) ||

@@ -548,24 +572,35 @@
                  * For encryption only, we have to grab the IV for the
                  * next pass AFTER encryption.
                  */
                 if (reqp->dr_flags & DR_ENCRYPT) {
                         uchar_t         ivstore[DESBLOCK];
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                        uint32_t        *iv = (uint32_t *)ivstore;
+#else
                         uchar_t         *iv = ivstore;
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
 
                         /* get last 8 bytes for IV of next op */
-                        errno = dca_getbufbytes(out, off, DESBLOCK, iv);
+                        errno = dca_getbufbytes(out, off, DESBLOCK,
+                            (uchar_t *)iv);
                         if (errno != CRYPTO_SUCCESS) {
                                 DBG(NULL, DWARN,
                                     "dca_3desdone: dca_getbufbytes() failed");
                                 goto errout;
                         }
+
                         /* store as a pair of native 32-bit values */
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                        ctx->dr_ctx.iv[0] = htonl(iv[0]);
+                        ctx->dr_ctx.iv[1] = htonl(iv[1]);
+#else
                         ctx->dr_ctx.iv[0] =
                             iv[0]<<24 | iv[1]<<16 | iv[2]<<8 | iv[3];
                         ctx->dr_ctx.iv[1] =
                             iv[4]<<24 | iv[5]<<16 | iv[6]<<8 | iv[7];
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
                 }
 
                 /*
                  * If there is more to do, then reschedule another
                  * pass.

@@ -621,18 +656,28 @@
 dca_3desctxinit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
     crypto_key_t *key, int kmflag, int flags)
 {
         dca_request_t   *des_ctx;
         dca_t           *dca = ctx->cc_provider;
+#ifdef UNALIGNED_POINTERS_PERMITTED
+        uint32_t        *param;
+        uint32_t        *value32;
+#else
         uchar_t         *param;
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         uchar_t         *value;
         size_t          paramsz;
         unsigned        len;
         int             i, j;
 
         paramsz = mechanism->cm_param_len;
+#ifdef UNALIGNED_POINTERS_PERMITTED
+        param = (uint32_t *)mechanism->cm_param;
+#else
         param = (uchar_t *)mechanism->cm_param;
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
+
         if ((paramsz != 0) && (paramsz != DES_IV_LEN)) {
                 DBG(NULL, DWARN,
                     "dca_3desctxinit: parameter(IV) length not %d (%d)",
                     DES_IV_LEN, paramsz);
                 return (CRYPTO_MECHANISM_PARAM_INVALID);

@@ -648,14 +693,19 @@
          * If cm_param == NULL then the IV comes from the cd_miscdata field
          * in the crypto_data structure.
          */
         if (param != NULL) {
                 ASSERT(paramsz == DES_IV_LEN);
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                des_ctx->dr_ctx.iv[0] = htonl(param[0]);
+                des_ctx->dr_ctx.iv[1] = htonl(param[1]);
+#else
                 des_ctx->dr_ctx.iv[0] = param[0]<<24 | param[1]<<16 |
                     param[2]<<8 | param[3];
                 des_ctx->dr_ctx.iv[1] = param[4]<<24 | param[5]<<16 |
                     param[6]<<8 | param[7];
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         }
         des_ctx->dr_ctx.residlen = 0;
         des_ctx->dr_ctx.activeresidlen = 0;
         des_ctx->dr_ctx.ctx_cm_type = mechanism->cm_type;
         ctx->cc_provider_private = des_ctx;

@@ -707,14 +757,22 @@
                 if (len != 64) {
                         DBG(NULL, DWARN, "Incorrect DES keysize (%d)", len);
                         dca_3desctxfree(ctx);
                         return (CRYPTO_KEY_SIZE_RANGE);
                 }
+
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                value32 = (uint32_t *)value;
+                des_ctx->dr_ctx.key[0] = htonl(value32[0]);
+                des_ctx->dr_ctx.key[1] = htonl(value32[1]);
+#else
                 des_ctx->dr_ctx.key[0] =
                     value[0]<<24 | value[1]<<16 | value[2]<<8 | value[3];
                 des_ctx->dr_ctx.key[1] =
                     value[4]<<24 | value[5]<<16 | value[6]<<8 | value[7];
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
+
                 /* for single des just repeat des key */
                 des_ctx->dr_ctx.key[4] =
                     des_ctx->dr_ctx.key[2] = des_ctx->dr_ctx.key[0];
                 des_ctx->dr_ctx.key[5] =
                     des_ctx->dr_ctx.key[3] = des_ctx->dr_ctx.key[1];