1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  25  * Use is subject to license terms.
  26  */
  27 
  28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  29 /* All Rights Reserved */
  30 
  31 /*
  32  * Portions of this source code were derived from Berkeley 4.3 BSD
  33  * under license from the Regents of the University of California.
  34  */
  35 
  36 #pragma ident   "%Z%%M% %I%     %E% SMI"
  37 
  38 /*
  39  * DES encryption library routines
  40  */
  41 
  42 #include "mt.h"
  43 #include <unistd.h>
  44 #include <fcntl.h>
  45 #include <sys/types.h>
  46 #include <rpc/des_crypt.h>
  47 #ifdef sun
  48 #include <sys/ioctl.h>
  49 #include <sys/des.h>
  50 #define getdesfd()      (open("/dev/des", 0, 0))
  51 #else
  52 #include <des/des.h>
  53 #endif
  54 #include <rpc/rpc.h>
  55 
  56 extern int __des_crypt(char *, unsigned, struct desparams *);
  57 
  58 static int common_crypt(char *, char *, unsigned, unsigned, struct desparams *);
  59 
  60 /*
  61  * To see if chip is installed
  62  */
  63 #define UNOPENED (-2)
  64 static int g_desfd = UNOPENED;
  65 
  66 
  67 /*
  68  * Copy 8 bytes
  69  */
  70 #define COPY8(src, dst) { \
  71         char *a = (char *)dst; \
  72         char *b = (char *)src; \
  73         *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
  74         *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
  75 }
  76 
  77 /*
  78  * Copy multiple of 8 bytes
  79  */
  80 #define DESCOPY(src, dst, len) { \
  81         char *a = (char *)dst; \
  82         char *b = (char *)src; \
  83         int i; \
  84         for (i = (int)len; i > 0; i -= 8) { \
  85                 *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
  86                 *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
  87         } \
  88 }
  89 
  90 /*
  91  * CBC mode encryption
  92  */
  93 int
  94 cbc_crypt(char *key, char *buf, size_t len, unsigned int mode, char *ivec)
  95 {
  96         int err;
  97         struct desparams dp;
  98 
  99         dp.des_mode = CBC;
 100         COPY8(ivec, dp.des_ivec);
 101         err = common_crypt(key, buf, len, mode, &dp);
 102         COPY8(dp.des_ivec, ivec);
 103         return (err);
 104 }
 105 
 106 
 107 /*
 108  * ECB mode encryption
 109  */
 110 int
 111 ecb_crypt(char *key, char *buf, size_t len, unsigned int mode)
 112 {
 113         struct desparams dp;
 114 
 115         dp.des_mode = ECB;
 116         return (common_crypt(key, buf, len, mode, &dp));
 117 }
 118 
 119 
 120 
 121 /*
 122  * Common code to cbc_crypt() & ecb_crypt()
 123  */
 124 static int
 125 common_crypt(char *key, char *buf, unsigned len, unsigned mode,
 126                                                         struct desparams *desp)
 127 {
 128         int desdev;
 129         int res;
 130 
 131         if ((len % 8) != 0 || len > DES_MAXDATA)
 132                 return (DESERR_BADPARAM);
 133         desp->des_dir =
 134                 ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT;
 135 
 136         desdev = mode & DES_DEVMASK;
 137         COPY8(key, desp->des_key);
 138 #ifdef sun
 139         if (desdev == DES_HW) {
 140                 if (g_desfd < 0) {
 141                         if (g_desfd == -1 || (g_desfd = getdesfd()) < 0) {
 142                                 goto software;  /* no hardware device */
 143                         }
 144                 }
 145 
 146                 /*
 147                  * hardware
 148                  */
 149                 desp->des_len = len;
 150                 if (len <= DES_QUICKLEN) {
 151                         DESCOPY(buf, desp->des_data, len);
 152                         res = ioctl(g_desfd, DESIOCQUICK, (char *)desp);
 153                         DESCOPY(desp->des_data, buf, len);
 154                 } else {
 155                         desp->des_buf = (uchar_t *)buf;
 156                         res = ioctl(g_desfd, DESIOCBLOCK, (char *)desp);
 157                 }
 158                 return (res == 0 ? DESERR_NONE : DESERR_HWERROR);
 159         }
 160 software:
 161 #endif
 162         /*
 163          * software
 164          */
 165         if (!__des_crypt(buf, len, desp))
 166                 return (DESERR_HWERROR);
 167         return (desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE);
 168 }
 169 
 170 static int
 171 desN_crypt(des_block keys[], int keynum, char *buf, unsigned int len,
 172                 unsigned int mode, char *ivec)
 173 {
 174         unsigned int m = mode & (DES_ENCRYPT | DES_DECRYPT);
 175         unsigned int flags = mode & ~(DES_ENCRYPT | DES_DECRYPT);
 176         des_block svec, dvec;
 177         int i, j, stat;
 178 
 179         if (keynum < 1)
 180                 return (DESERR_BADPARAM);
 181 
 182         (void) memcpy(svec.c, ivec, sizeof (des_block));
 183         for (i = 0; i < keynum; i++) {
 184                 j = (mode & DES_DECRYPT) ? keynum - 1 - i : i;
 185                 stat = cbc_crypt(keys[j].c, buf, len, m | flags, ivec);
 186                 if (mode & DES_DECRYPT && i == 0)
 187                         (void) memcpy(dvec.c, ivec, sizeof (des_block));
 188 
 189                 if (DES_FAILED(stat))
 190                         return (stat);
 191 
 192                 m = (m == DES_ENCRYPT ? DES_DECRYPT : DES_ENCRYPT);
 193 
 194                 if ((mode & DES_DECRYPT) || i != keynum - 1 || i%2)
 195                         (void) memcpy(ivec, svec.c, sizeof (des_block));
 196         }
 197         if (keynum % 2 == 0)
 198                 stat = cbc_crypt(keys[0].c, buf, len, mode, ivec);
 199 
 200         if (mode & DES_DECRYPT)
 201                 (void) memcpy(ivec, dvec.c, sizeof (des_block));
 202 
 203         return (stat);
 204 }
 205 
 206 
 207 
 208 int
 209 __cbc_triple_crypt(des_block keys[], char *buf,  uint_t len,
 210                         uint_t mode, char *ivec)
 211 {
 212         return (desN_crypt(keys, 3, buf, len, mode, ivec));
 213 }