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

@@ -21,12 +21,10 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident   "%Z%%M% %I%     %E% SMI"
-
 #include <sys/types.h>
 #include <sys/systm.h>
 #include <sys/ddi.h>
 #include <sys/sysmacros.h>
 #include <sys/strsun.h>

@@ -37,10 +35,15 @@
 #ifndef _KERNEL
 #include <strings.h>
 #include <stdlib.h>
 #endif  /* !_KERNEL */
 
+#if defined(__i386) || defined(__amd64)
+#include <sys/byteorder.h>
+#define UNALIGNED_POINTERS_PERMITTED
+#endif
+
 /* EXPORT DELETE START */
 
 typedef struct keysched_s {
         uint64_t ksch_encrypt[16];
         uint64_t ksch_decrypt[16];

@@ -516,44 +519,49 @@
         if (IS_P2ALIGNED(block, sizeof (uint64_t)) &&
             IS_P2ALIGNED(out_block, sizeof (uint64_t))) {
                 if (decrypt == B_TRUE)
                         /* LINTED */
                         *(uint64_t *)out_block = des_crypt_impl(
-                            ksch->ksch_decrypt,
-                            /* LINTED */
+                            ksch->ksch_decrypt, /* LINTED */
                             *(uint64_t *)block, 3);
                 else
                         /* LINTED */
                         *(uint64_t *)out_block = des_crypt_impl(
-                            ksch->ksch_encrypt,
-                            /* LINTED */
+                            ksch->ksch_encrypt, /* LINTED */
                             *(uint64_t *)block, 3);
-        } else {
-#endif
+        } else
+#endif  /* _BIG_ENDIAN */
+        {
                 uint64_t tmp;
 
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                tmp = htonll(*(uint64_t *)&block[0]);
+#else
                 tmp = (((uint64_t)block[0] << 56) | ((uint64_t)block[1] << 48) |
                     ((uint64_t)block[2] << 40) | ((uint64_t)block[3] << 32) |
                     ((uint64_t)block[4] << 24) | ((uint64_t)block[5] << 16) |
                     ((uint64_t)block[6] << 8) | (uint64_t)block[7]);
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
 
                 if (decrypt == B_TRUE)
                         tmp = des_crypt_impl(ksch->ksch_decrypt, tmp, 3);
                 else
                         tmp = des_crypt_impl(ksch->ksch_encrypt, tmp, 3);
 
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                *(uint64_t *)&out_block[0] = htonll(tmp);
+#else
                 out_block[0] = tmp >> 56;
                 out_block[1] = tmp >> 48;
                 out_block[2] = tmp >> 40;
                 out_block[3] = tmp >> 32;
                 out_block[4] = tmp >> 24;
                 out_block[5] = tmp >> 16;
                 out_block[6] = tmp >> 8;
                 out_block[7] = (uint8_t)tmp;
-#ifdef _BIG_ENDIAN
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         }
-#endif
 /* EXPORT DELETE END */
         return (CRYPTO_SUCCESS);
 }
 
 int

@@ -572,45 +580,51 @@
         if (IS_P2ALIGNED(block, sizeof (uint64_t)) &&
             IS_P2ALIGNED(out_block, sizeof (uint64_t))) {
                 if (decrypt == B_TRUE)
                         /* LINTED */
                         *(uint64_t *)out_block = des_crypt_impl(
-                            ksch->ksch_decrypt,
-                            /* LINTED */
+                            ksch->ksch_decrypt, /* LINTED */
                             *(uint64_t *)block, 1);
                 else
                         /* LINTED */
                         *(uint64_t *)out_block = des_crypt_impl(
-                            ksch->ksch_encrypt,
-                            /* LINTED */
+                            ksch->ksch_encrypt, /* LINTED */
                             *(uint64_t *)block, 1);
 
-        } else {
-#endif
+        } else
+#endif  /* _BIG_ENDIAN */
+        {
                 uint64_t tmp;
 
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                tmp = htonll(*(uint64_t *)&block[0]);
+#else
                 tmp = (((uint64_t)block[0] << 56) | ((uint64_t)block[1] << 48) |
                     ((uint64_t)block[2] << 40) | ((uint64_t)block[3] << 32) |
                     ((uint64_t)block[4] << 24) | ((uint64_t)block[5] << 16) |
                     ((uint64_t)block[6] << 8) | (uint64_t)block[7]);
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
 
+
                 if (decrypt == B_TRUE)
                         tmp = des_crypt_impl(ksch->ksch_decrypt, tmp, 1);
                 else
                         tmp = des_crypt_impl(ksch->ksch_encrypt, tmp, 1);
 
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                *(uint64_t *)&out_block[0] = htonll(tmp);
+#else
                 out_block[0] = tmp >> 56;
                 out_block[1] = tmp >> 48;
                 out_block[2] = tmp >> 40;
                 out_block[3] = tmp >> 32;
                 out_block[4] = tmp >> 24;
                 out_block[5] = tmp >> 16;
                 out_block[6] = tmp >> 8;
                 out_block[7] = (uint8_t)tmp;
-#ifdef _BIG_ENDIAN
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         }
-#endif
 /* EXPORT DELETE END */
         return (CRYPTO_SUCCESS);
 }
 
 static boolean_t

@@ -648,27 +662,31 @@
                 0x1fe01fe00ef10ef1ULL,  0xe01fe01ff10ef10eULL,
                 0x01e001e001f101f1ULL,  0xe001e001f101f101ULL,
                 0x1ffe1ffe0efe0efeULL,  0xfe1ffe1ffe0efe0eULL,
                 0x011f011f010e010eULL,  0x1f011f010e010e01ULL,
                 0xe0fee0fef1fef1feULL,  0xfee0fee0fef1fef1ULL,
-#endif
+#endif  /* _LITTLE_ENDIAN */
 
                 /* We'll save the other possibly-weak keys for the future. */
         };
 
         if (key == NULL)
                 return (B_FALSE);
 
+#ifdef UNALIGNED_POINTERS_PERMITTED
+        key_so_far = htonll(*(uint64_t *)&key[0]);
+#else
         /*
          * The code below reverses the bytes on LITTLE_ENDIAN machines.
          * On BIG_ENDIAN, the same code copies without reversing
          * the bytes.
          */
         key_so_far = (((uint64_t)key[0] << 56) | ((uint64_t)key[1] << 48) |
             ((uint64_t)key[2] << 40) | ((uint64_t)key[3] << 32) |
             ((uint64_t)key[4] << 24) | ((uint64_t)key[5] << 16) |
             ((uint64_t)key[6] << 8) | (uint64_t)key[7]);
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
 
         /*
          * Fix parity.
          */
         fix_des_parity(&key_so_far);

@@ -678,10 +696,13 @@
                 if (key_so_far == des_weak_keys[i]) {
                         return (B_FALSE);
                 }
 
         if (corrected_key != NULL) {
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                *(uint64_t *)&corrected_key[0] = htonll(key_so_far);
+#else
                 /*
                  * The code below reverses the bytes on LITTLE_ENDIAN machines.
                  * On BIG_ENDIAN, the same code copies without reversing
                  * the bytes.
                  */

@@ -691,10 +712,11 @@
                 corrected_key[3] = key_so_far >> 32;
                 corrected_key[4] = key_so_far >> 24;
                 corrected_key[5] = key_so_far >> 16;
                 corrected_key[6] = key_so_far >> 8;
                 corrected_key[7] = (uint8_t)key_so_far;
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
         }
 /* EXPORT DELETE END */
         return (B_TRUE);
 }
 

@@ -741,11 +763,11 @@
         }
 
         /*
          * Perform key equivalence checks, now that parity is properly set.
          * 1st and 2nd keys must be unique, the 3rd key can be the same as
-         * the 1st key for the 2 key varient of 3DES.
+         * the 1st key for the 2 key variant of 3DES.
          */
         if (currentkey[0] == currentkey[1] || currentkey[1] == currentkey[2])
                 return (B_FALSE);
 
         if (corrected_key != NULL) {

@@ -783,29 +805,37 @@
                 bcopy(key, aligned_key, DES3_KEYSIZE);
 
         paritied_key = (uint8_t *)aligned_key;
         while (strength > i) {
                 offset = 8 * i;
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                key_so_far = htonll(*(uint64_t *)&paritied_key[offset]);
+#else
                 key_so_far = (((uint64_t)paritied_key[offset + 0] << 56) |
                     ((uint64_t)paritied_key[offset + 1] << 48) |
                     ((uint64_t)paritied_key[offset + 2] << 40) |
                     ((uint64_t)paritied_key[offset + 3] << 32) |
                     ((uint64_t)paritied_key[offset + 4] << 24) |
                     ((uint64_t)paritied_key[offset + 5] << 16) |
                     ((uint64_t)paritied_key[offset + 6] << 8) |
                     (uint64_t)paritied_key[offset + 7]);
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
 
                 fix_des_parity(&key_so_far);
 
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                *(uint64_t *)&paritied_key[offset] = htonll(key_so_far);
+#else
                 paritied_key[offset + 0] = key_so_far >> 56;
                 paritied_key[offset + 1] = key_so_far >> 48;
                 paritied_key[offset + 2] = key_so_far >> 40;
                 paritied_key[offset + 3] = key_so_far >> 32;
                 paritied_key[offset + 4] = key_so_far >> 24;
                 paritied_key[offset + 5] = key_so_far >> 16;
                 paritied_key[offset + 6] = key_so_far >> 8;
                 paritied_key[offset + 7] = (uint8_t)key_so_far;
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
 
                 i++;
         }
 
         bcopy(paritied_key, corrected_key, DES_KEYSIZE * strength);

@@ -853,27 +883,28 @@
         if (IS_P2ALIGNED(cipherKey, sizeof (uint64_t))) {
                 for (i = 0, j = 0; j < keysize; i++, j += 8) {
                         /* LINTED: pointer alignment */
                         key_uint64[i] = *((uint64_t *)&cipherKey[j]);
                 }
-        } else {
-#endif
+        } else
+#endif  /* _BIG_ENDIAN */
         {
                 for (i = 0, j = 0; j < keysize; i++, j += 8) {
+#ifdef UNALIGNED_POINTERS_PERMITTED
+                        key_uint64[i] = htonll(*(uint64_t *)&cipherKey[j]);
+#else
                         key_uint64[i] = (((uint64_t)cipherKey[j] << 56) |
                             ((uint64_t)cipherKey[j + 1] << 48) |
                             ((uint64_t)cipherKey[j + 2] << 40) |
                             ((uint64_t)cipherKey[j + 3] << 32) |
                             ((uint64_t)cipherKey[j + 4] << 24) |
                             ((uint64_t)cipherKey[j + 5] << 16) |
                             ((uint64_t)cipherKey[j + 6] << 8) |
                             (uint64_t)cipherKey[j + 7]);
+#endif  /* UNALIGNED_POINTERS_PERMITTED */
                 }
         }
-#ifdef _BIG_ENDIAN
-        }
-#endif
 
         switch (strength) {
         case DES:
                 des_ks(keysched, key_uint64[0]);
                 break;

@@ -949,11 +980,11 @@
 }
 
 /*
  * Replace the LSB of each byte by the xor of the other
  * 7 bits.  The tricky thing is that the original contents of the LSBs
- * are nullifed by including them twice in the xor computation.
+ * are nullified by including them twice in the xor computation.
  */
 static void
 fix_des_parity(uint64_t *keyp)
 {
 /* EXPORT DELETE START */