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 2002-2003 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 <sys/sysmacros.h> 30 #if defined(_KERNEL) && !defined(_BOOT) 31 #include <sys/systm.h> 32 #else 33 #include <strings.h> 34 #endif 35 #include "cbc.h" 36 37 #define CBC_MAX_BLOCK_SIZE 64 38 39 static void 40 cbc_xorblock(uint8_t *lastp, uint8_t *thisp, int blocksize) 41 { 42 uint32_t *this32p; 43 uint32_t *last32p; 44 int i; 45 46 if (IS_P2ALIGNED(thisp, sizeof (uint32_t)) && 47 IS_P2ALIGNED(lastp, sizeof (uint32_t)) && 48 IS_P2ALIGNED(blocksize, sizeof (uint32_t))) { 49 /* LINTED */ 50 this32p = (uint32_t *)thisp; 51 /* LINTED */ 52 last32p = (uint32_t *)lastp; 53 for (i = 0; i < blocksize; i += 4) { 54 *this32p ^= *last32p; 55 this32p++; 56 last32p++; 57 } 58 } else { 59 for (i = 0; i < blocksize; i++) { 60 thisp[i] ^= lastp[i]; 61 } 62 } 63 } 64 65 boolean_t 66 cbc_encrypt(cbc_handle_t *ch, uint8_t *data, size_t datalen, 67 uint8_t *IV) 68 { 69 uint8_t *lastp; 70 uint8_t *thisp; 71 size_t i; 72 73 if (!IS_P2ALIGNED(datalen, ch->blocklen)) { 74 return (B_FALSE); 75 } 76 77 thisp = data; 78 lastp = IV; 79 80 for (i = 0; i < datalen; i += ch->blocklen) { 81 cbc_xorblock(lastp, thisp, ch->blocklen); 82 /* Encrypt the current block. */ 83 ch->encrypt(ch->ks, thisp); 84 lastp = thisp; 85 thisp += ch->blocklen; 86 } 87 88 bcopy(lastp, IV, ch->blocklen); 89 return (B_TRUE); 90 } 91 92 boolean_t 93 cbc_decrypt(cbc_handle_t *ch, uint8_t *data, size_t datalen, 94 uint8_t *IV) 95 { 96 uint8_t cbcblock[CBC_MAX_BLOCK_SIZE]; 97 uint8_t *lastp; 98 uint8_t *thisp; 99 size_t i; 100 101 if (!IS_P2ALIGNED(datalen, ch->blocklen)) { 102 return (B_FALSE); 103 } 104 105 thisp = data; 106 lastp = IV; 107 108 for (i = 0; i < datalen; i += ch->blocklen) { 109 110 /* Copy the current ciphertext block. */ 111 bcopy(thisp, cbcblock, ch->blocklen); 112 113 /* Decrypt the current block. */ 114 ch->decrypt(ch->ks, thisp); 115 116 cbc_xorblock(lastp, thisp, ch->blocklen); 117 118 /* Save the last ciphertext block. */ 119 bcopy(cbcblock, lastp, ch->blocklen); 120 thisp += ch->blocklen; 121 } 122 123 return (B_TRUE); 124 } 125 126 void 127 cbc_makehandle(cbc_handle_t *ch, void *cookie, uint32_t keysize, 128 uint32_t blocksize, uint32_t ivsize, 129 void (*encrypt)(void *, uint8_t *), 130 void (*decrypt)(void *, uint8_t *)) 131 { 132 ch->ks = cookie; 133 ch->keylen = keysize; 134 ch->blocklen = blocksize; 135 ch->ivlen = ivsize; 136 ch->encrypt = encrypt; 137 ch->decrypt = decrypt; 138 } 139