arcfour_crypt.c revision 416:6f98fe688e7b
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License, Version 1.0 only 6168404Spjd * (the "License"). You may not use this file except in compliance 7168404Spjd * with the License. 8168404Spjd * 9168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10168404Spjd * or http://www.opensolaris.org/os/licensing. 11168404Spjd * See the License for the specific language governing permissions 12168404Spjd * and limitations under the License. 13168404Spjd * 14168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 15168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16168404Spjd * If applicable, add the following below this CDDL HEADER, with the 17168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 18168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 19168404Spjd * 20168404Spjd * CDDL HEADER END 21263406Sdelphij */ 22168404Spjd/* 23205199Sdelphij * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24168404Spjd * Use is subject to license terms. 25263406Sdelphij */ 26168404Spjd 27168404Spjd#pragma ident "%Z%%M% %I% %E% SMI" 28168404Spjd 29168404Spjd#include "arcfour.h" 30168404Spjd 31168404Spjd/* Initialize the key stream 'key' using the key value */ 32168404Spjdvoid 33168404Spjdarcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen) 34168404Spjd{ 35168404Spjd/* EXPORT DELETE START */ 36168404Spjd 37168404Spjd uchar_t ext_keyval[256]; 38168404Spjd uchar_t tmp; 39168404Spjd int i, j; 40168404Spjd 41168404Spjd for (i = j = 0; i < 256; i++, j++) { 42168404Spjd if (j == keyvallen) 43185029Spjd j = 0; 44185029Spjd 45185029Spjd ext_keyval[i] = keyval[j]; 46205199Sdelphij } 47219089Spjd for (i = 0; i < 256; i++) 48231946Smm key->arr[i] = (uchar_t)i; 49263406Sdelphij 50185029Spjd j = 0; 51185029Spjd for (i = 0; i < 256; i++) { 52205199Sdelphij j = (j + key->arr[i] + ext_keyval[i]) % 256; 53168404Spjd tmp = key->arr[i]; 54168404Spjd key->arr[i] = key->arr[j]; 55231946Smm key->arr[j] = tmp; 56168404Spjd } 57168404Spjd key->i = 0; 58168404Spjd key->j = 0; 59168404Spjd 60168404Spjd/* EXPORT DELETE END */ 61168404Spjd} 62 63 64/* 65 * Encipher 'in' using 'key. 66 * in and out can point to the same location 67 */ 68void 69arcfour_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