/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 * or http://www.opensolaris.org/os/licensing. * 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 2002-2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #if defined(_KERNEL) && !defined(_BOOT) #include #else #include #endif #include "cbc.h" #define CBC_MAX_BLOCK_SIZE 64 static void cbc_xorblock(uint8_t *lastp, uint8_t *thisp, int blocksize) { uint32_t *this32p; uint32_t *last32p; int i; if (IS_P2ALIGNED(thisp, sizeof (uint32_t)) && IS_P2ALIGNED(lastp, sizeof (uint32_t)) && IS_P2ALIGNED(blocksize, sizeof (uint32_t))) { /* LINTED */ this32p = (uint32_t *)thisp; /* LINTED */ last32p = (uint32_t *)lastp; for (i = 0; i < blocksize; i += 4) { *this32p ^= *last32p; this32p++; last32p++; } } else { for (i = 0; i < blocksize; i++) { thisp[i] ^= lastp[i]; } } } boolean_t cbc_encrypt(cbc_handle_t *ch, uint8_t *data, size_t datalen, uint8_t *IV) { uint8_t *lastp; uint8_t *thisp; size_t i; if (!IS_P2ALIGNED(datalen, ch->blocklen)) { return (B_FALSE); } thisp = data; lastp = IV; for (i = 0; i < datalen; i += ch->blocklen) { cbc_xorblock(lastp, thisp, ch->blocklen); /* Encrypt the current block. */ ch->encrypt(ch->ks, thisp); lastp = thisp; thisp += ch->blocklen; } bcopy(lastp, IV, ch->blocklen); return (B_TRUE); } boolean_t cbc_decrypt(cbc_handle_t *ch, uint8_t *data, size_t datalen, uint8_t *IV) { uint8_t cbcblock[CBC_MAX_BLOCK_SIZE]; uint8_t *lastp; uint8_t *thisp; size_t i; if (!IS_P2ALIGNED(datalen, ch->blocklen)) { return (B_FALSE); } thisp = data; lastp = IV; for (i = 0; i < datalen; i += ch->blocklen) { /* Copy the current ciphertext block. */ bcopy(thisp, cbcblock, ch->blocklen); /* Decrypt the current block. */ ch->decrypt(ch->ks, thisp); cbc_xorblock(lastp, thisp, ch->blocklen); /* Save the last ciphertext block. */ bcopy(cbcblock, lastp, ch->blocklen); thisp += ch->blocklen; } return (B_TRUE); } void cbc_makehandle(cbc_handle_t *ch, void *cookie, uint32_t keysize, uint32_t blocksize, uint32_t ivsize, void (*encrypt)(void *, uint8_t *), void (*decrypt)(void *, uint8_t *)) { ch->ks = cookie; ch->keylen = keysize; ch->blocklen = blocksize; ch->ivlen = ivsize; ch->encrypt = encrypt; ch->decrypt = decrypt; }