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 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "arcfour.h" 30 31 /* Initialize the key stream 'key' using the key value */ 32 void 33 arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen) 34 { 35 /* EXPORT DELETE START */ 36 37 uchar_t ext_keyval[256]; 38 uchar_t tmp; 39 int i, j; 40 41 for (i = j = 0; i < 256; i++, j++) { 42 if (j == keyvallen) 43 j = 0; 44 45 ext_keyval[i] = keyval[j]; 46 } 47 for (i = 0; i < 256; i++) 48 key->arr[i] = (uchar_t)i; 49 50 j = 0; 51 for (i = 0; i < 256; i++) { 52 j = (j + key->arr[i] + ext_keyval[i]) % 256; 53 tmp = key->arr[i]; 54 key->arr[i] = key->arr[j]; 55 key->arr[j] = tmp; 56 } 57 key->i = 0; 58 key->j = 0; 59 60 /* EXPORT DELETE END */ 61 } 62 63 64 /* 65 * Encipher 'in' using 'key. 66 * in and out can point to the same location 67 */ 68 void 69 arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len) 70 { 71 size_t ii; 72 uchar_t tmp, i, j; 73 74 /* EXPORT DELETE START */ 75 76 /* 77 * The sun4u has a version of arcfour_crypt_aligned() hand-tuned for 78 * the cases where the input and output buffers are aligned on 79 * a multiple of 8-byte boundary. 80 */ 81 #ifdef sun4u 82 int index; 83 84 index = (((uint64_t)(uintptr_t)in) & 0x7); 85 86 /* Get the 'in' on an 8-byte alignment */ 87 if (index > 0) { 88 i = key->i; 89 j = key->j; 90 for (index = 8 - (uint64_t)(uintptr_t)in & 0x7; 91 (index-- > 0) && len > 0; 92 len--, in++, out++) { 93 i = i + 1; 94 j = j + key->arr[i]; 95 tmp = key->arr[i]; 96 key->arr[i] = key->arr[j]; 97 key->arr[j] = tmp; 98 tmp = key->arr[i] + key->arr[j]; 99 *out = *in ^ key->arr[tmp]; 100 } 101 key->i = i; 102 key->j = j; 103 104 } 105 if (len == 0) 106 return; 107 108 /* See if we're fortunate and 'out' got aligned as well */ 109 110 if ((((uint64_t)(uintptr_t)out) & 7) != 0) { 111 #endif /* sun4u */ 112 i = key->i; 113 j = key->j; 114 for (ii = 0; ii < len; ii++) { 115 i = i + 1; 116 j = j + key->arr[i]; 117 tmp = key->arr[i]; 118 key->arr[i] = key->arr[j]; 119 key->arr[j] = tmp; 120 tmp = key->arr[i] + key->arr[j]; 121 out[ii] = in[ii] ^ key->arr[tmp]; 122 } 123 key->i = i; 124 key->j = j; 125 #ifdef sun4u 126 } else { 127 arcfour_crypt_aligned(key, len, in, out); 128 } 129 #endif /* sun4u */ 130 131 /* EXPORT DELETE END */ 132 } 133