arcfour.c revision d3b2efc749bec3b757d5f018cf78c9a09fa29cb3
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* RC4 provider for the Kernel Cryptographic Framework (KCF)
*/
#include <sys/sysmacros.h>
#include <arcfour.h>
extern struct mod_ops mod_cryptoops;
/*
* Module linkage information for the kernel.
*/
static struct modlcrypto modlcrypto = {
"RC4 Kernel SW Provider"
};
static struct modlinkage modlinkage = {
(void *)&modlcrypto,
};
/*
* CSPI information (entry points, provider info, etc.)
*/
#define RC4_MECH_INFO_TYPE 0
/*
* Mechanism info structure passed to KCF during registration.
*/
static crypto_mech_info_t rc4_mech_info_tab[] = {
};
static crypto_control_ops_t rc4_control_ops = {
};
static crypto_cipher_ops_t rc4_cipher_ops = {
};
static int rc4_free_context(crypto_ctx_t *);
static crypto_ctx_ops_t rc4_ctx_ops = {
NULL,
};
static crypto_ops_t rc4_crypto_ops = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
static crypto_provider_info_t rc4_prov_info = {
"RC4 Software Provider",
{&modlinkage},
NULL,
sizeof (rc4_mech_info_tab)/sizeof (crypto_mech_info_t),
};
int);
int
_init(void)
{
int ret;
return (ret);
/* Register with KCF. If the registration fails, remove the module. */
(void) mod_remove(&modlinkage);
return (EACCES);
}
return (0);
}
int
_fini(void)
{
/* Unregister from KCF if module is registered */
if (rc4_prov_handle != NULL) {
return (EBUSY);
}
return (mod_remove(&modlinkage));
}
int
{
}
/*
* KCF software provider control entry points.
*/
/* ARGSUSED */
static void
{
}
/* ARGSUSED */
static int
{
/* EXPORT DELETE START */
return (CRYPTO_MECHANISM_INVALID);
return (CRYPTO_KEY_TYPE_INCONSISTENT);
return (CRYPTO_KEY_SIZE_RANGE);
}
/*
* Allocate an RC4 key stream.
*/
return (CRYPTO_HOST_MEMORY);
/* EXPORT DELETE END */
return (CRYPTO_SUCCESS);
}
static int
{
int ret;
if (ret != CRYPTO_BUFFER_TOO_SMALL)
(void) rc4_free_context(ctx);
return (ret);
}
/* ARGSUSED */
static int
{
int ret = CRYPTO_SUCCESS;
/* EXPORT DELETE START */
else
/* Simple case: in-line encipherment */
case CRYPTO_DATA_RAW: {
return (CRYPTO_DATA_INVALID);
break;
}
case CRYPTO_DATA_MBLK: {
return (CRYPTO_DATA_LEN_RANGE);
return (CRYPTO_DATA_LEN_RANGE);
} else {
}
}
break;
}
case CRYPTO_DATA_UIO: {
/*
* Jump to the first iovec containing data to be
* processed.
*/
;
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now process the iovecs.
*/
vec_idx++;
offset = 0;
}
return (CRYPTO_DATA_LEN_RANGE);
}
break;
}
}
return (CRYPTO_SUCCESS);
}
/*
* We need to just return the length needed to store the output.
* We should not destroy the context for the following case.
*/
return (CRYPTO_BUFFER_TOO_SMALL);
}
case CRYPTO_DATA_RAW: {
return (CRYPTO_DATA_LEN_RANGE);
if (ret != CRYPTO_SUCCESS)
return (ret);
break;
}
case CRYPTO_DATA_MBLK: {
return (CRYPTO_DATA_LEN_RANGE);
&end);
return (CRYPTO_DATA_LEN_RANGE);
len);
if (ret != CRYPTO_SUCCESS)
return (ret);
} else {
len);
if (ret != CRYPTO_SUCCESS)
return (ret);
}
}
break;
}
case CRYPTO_DATA_UIO: {
/*
* Jump to the first iovec containing data to be
* processed.
*/
;
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now process the iovecs.
*/
if (ret != CRYPTO_SUCCESS)
return (ret);
vec_idx++;
offset = 0;
}
return (CRYPTO_DATA_LEN_RANGE);
}
}
}
/* EXPORT DELETE END */
return (ret);
}
/* ARGSUSED */
{
/* No final part for streams ciphers. Just free the context */
return (rc4_free_context(ctx));
}
/* ARGSUSED */
static int
{
int ret;
if (ret != CRYPTO_SUCCESS)
return (ret);
(void) rc4_free_context(&ctx);
return (ret);
}
/* ARGSUSED */
static int
{
/* EXPORT DELETE START */
}
/* EXPORT DELETE END */
return (CRYPTO_SUCCESS);
}
/* Encrypts a contiguous input 'in' into the 'out' crypto_data_t */
static int
int length)
{
case CRYPTO_DATA_RAW: {
return (CRYPTO_DATA_LEN_RANGE);
return (CRYPTO_SUCCESS);
}
case CRYPTO_DATA_MBLK: {
return (CRYPTO_DATA_LEN_RANGE);
return (CRYPTO_DATA_LEN_RANGE);
} else {
}
}
break;
}
case CRYPTO_DATA_UIO: {
/*
* Jump to the first iovec containing data to be
* processed.
*/
;
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now process the iovecs.
*/
vec_idx++;
offset = 0;
}
return (CRYPTO_DATA_LEN_RANGE);
}
break;
}
default:
return (CRYPTO_DATA_INVALID);
}
return (CRYPTO_SUCCESS);
}
/*
* Advances 'offset' bytes from the beginning of the first block in 'mp',
* possibly jumping across b_cont boundary
* '*cpp' is set to the position of the byte we want, and the block where
* 'cpp' is returned.
*/
static mblk_t *
{
size_t l;
if (l <= o) {
o -= l;
} else {
break;
}
}
return (mp1);
}