crypto.c revision 1.7
1/* $OpenBSD: crypto.c,v 1.7 2000/01/26 15:23:04 niklas Exp $ */ 2/* $EOM: crypto.c,v 1.26 1999/12/08 20:31:02 niklas Exp $ */ 3 4/* 5 * Copyright (c) 1998 Niels Provos. All rights reserved. 6 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Ericsson Radio Systems. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34/* 35 * This code was written under funding by Ericsson Radio Systems. 36 */ 37 38#include <sys/param.h> 39#include <stdlib.h> 40#include <string.h> 41 42#include "sysdep.h" 43 44#include "crypto.h" 45#include "log.h" 46 47enum cryptoerr des1_init (struct keystate *, u_int8_t *, u_int16_t); 48enum cryptoerr des3_init (struct keystate *, u_int8_t *, u_int16_t); 49enum cryptoerr blf_init (struct keystate *, u_int8_t *, u_int16_t); 50enum cryptoerr cast_init (struct keystate *, u_int8_t *, u_int16_t); 51void des1_encrypt (struct keystate *, u_int8_t *, u_int16_t); 52void des1_decrypt (struct keystate *, u_int8_t *, u_int16_t); 53void des3_encrypt (struct keystate *, u_int8_t *, u_int16_t); 54void des3_decrypt (struct keystate *, u_int8_t *, u_int16_t); 55void blf_encrypt (struct keystate *, u_int8_t *, u_int16_t); 56void blf_decrypt (struct keystate *, u_int8_t *, u_int16_t); 57void cast1_encrypt (struct keystate *, u_int8_t *, u_int16_t); 58void cast1_decrypt (struct keystate *, u_int8_t *, u_int16_t); 59 60struct crypto_xf transforms[] = { 61 { 62 DES_CBC, "Data Encryption Standard (CBC-Mode)", 8, 8, BLOCKSIZE, 0, 63 des1_init, 64 des1_encrypt, des1_decrypt 65 }, 66 { 67 TRIPLEDES_CBC, "Triple-DES (CBC-Mode)", 24, 24, BLOCKSIZE, 0, 68 des3_init, 69 des3_encrypt, des3_decrypt 70 }, 71 { 72 BLOWFISH_CBC, "Blowfish (CBC-Mode)", 12, 56, BLOCKSIZE, 0, 73 blf_init, 74 blf_encrypt, blf_decrypt 75 }, 76 { 77 CAST_CBC, "CAST (CBC-Mode)", 12, 16, BLOCKSIZE, 0, 78 cast_init, 79 cast1_encrypt, cast1_decrypt 80 }, 81}; 82 83/* Hmm, the function prototypes for des are really dumb */ 84#ifdef __OpenBSD__ 85#define DC (des_cblock *) 86#else 87#define DC (void *) 88#endif 89 90enum cryptoerr 91des1_init (struct keystate *ks, u_int8_t *key, u_int16_t len) 92{ 93 /* des_set_key returns -1 for parity problems, and -2 for weak keys */ 94 des_set_odd_parity (DC key); 95 switch (des_set_key (DC key, ks->ks_des[0])) 96 { 97 case -2: 98 return EWEAKKEY; 99 default: 100 return EOKAY; 101 } 102} 103 104void 105des1_encrypt (struct keystate *ks, u_int8_t *d, u_int16_t len) 106{ 107 des_cbc_encrypt (DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_ENCRYPT); 108} 109 110void 111des1_decrypt (struct keystate *ks, u_int8_t *d, u_int16_t len) 112{ 113 des_cbc_encrypt (DC d, DC d, len, ks->ks_des[0], DC ks->riv, DES_DECRYPT); 114} 115 116enum cryptoerr 117des3_init (struct keystate *ks, u_int8_t *key, u_int16_t len) 118{ 119 des_set_odd_parity (DC key); 120 des_set_odd_parity (DC key + 1); 121 des_set_odd_parity (DC key + 2); 122 123 /* As of the draft Tripe-DES does not check for weak keys */ 124 des_set_key (DC key, ks->ks_des[0]); 125 des_set_key (DC key + 1, ks->ks_des[1]); 126 des_set_key (DC key + 2, ks->ks_des[2]); 127 128 return EOKAY; 129} 130 131void 132des3_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) 133{ 134 u_int8_t iv[MAXBLK]; 135 136 memcpy (iv, ks->riv, ks->xf->blocksize); 137 des_ede3_cbc_encrypt (DC data, DC data, len, ks->ks_des[0], ks->ks_des[1], 138 ks->ks_des[2], DC iv, DES_ENCRYPT); 139} 140 141void 142des3_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) 143{ 144 u_int8_t iv[MAXBLK]; 145 146 memcpy (iv, ks->riv, ks->xf->blocksize); 147 des_ede3_cbc_encrypt (DC data, DC data, len, ks->ks_des[0], ks->ks_des[1], 148 ks->ks_des[2], DC iv, DES_DECRYPT); 149} 150#undef DC 151 152enum cryptoerr 153blf_init (struct keystate *ks, u_int8_t *key, u_int16_t len) 154{ 155 blf_key (&ks->ks_blf, key, len); 156 157 return EOKAY; 158} 159 160void 161blf_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) 162{ 163 u_int16_t i, blocksize = ks->xf->blocksize; 164 u_int8_t *iv = ks->liv; 165 u_int32_t xl, xr; 166 167 memcpy (iv, ks->riv, blocksize); 168 169 for (i = 0; i < len; data += blocksize, i += blocksize) 170 { 171 XOR64 (data, iv); 172 xl = GET_32BIT_BIG (data); 173 xr = GET_32BIT_BIG (data + 4); 174 Blowfish_encipher (&ks->ks_blf, &xl, &xr); 175 SET_32BIT_BIG (data, xl); 176 SET_32BIT_BIG (data + 4, xr); 177 SET64 (iv, data); 178 } 179} 180 181void 182blf_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) 183{ 184 u_int16_t i, blocksize = ks->xf->blocksize; 185 u_int32_t xl, xr; 186 187 data += len - blocksize; 188 for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize) 189 { 190 xl = GET_32BIT_BIG (data); 191 xr = GET_32BIT_BIG (data + 4); 192 Blowfish_decipher (&ks->ks_blf, &xl, &xr); 193 SET_32BIT_BIG (data, xl); 194 SET_32BIT_BIG (data + 4, xr); 195 XOR64 (data, data - blocksize); 196 197 } 198 xl = GET_32BIT_BIG (data); 199 xr = GET_32BIT_BIG (data + 4); 200 Blowfish_decipher (&ks->ks_blf, &xl, &xr); 201 SET_32BIT_BIG (data, xl); 202 SET_32BIT_BIG (data + 4, xr); 203 XOR64 (data, ks->riv); 204} 205 206enum cryptoerr 207cast_init (struct keystate *ks, u_int8_t *key, u_int16_t len) 208{ 209 cast_setkey (&ks->ks_cast, key, len); 210 return EOKAY; 211} 212 213void 214cast1_encrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) 215{ 216 u_int16_t i, blocksize = ks->xf->blocksize; 217 u_int8_t *iv = ks->liv; 218 219 memcpy (iv, ks->riv, blocksize); 220 221 for (i = 0; i < len; data += blocksize, i += blocksize) 222 { 223 XOR64 (data, iv); 224 cast_encrypt (&ks->ks_cast, data, data); 225 SET64 (iv, data); 226 } 227} 228 229void 230cast1_decrypt (struct keystate *ks, u_int8_t *data, u_int16_t len) 231{ 232 u_int16_t i, blocksize = ks->xf->blocksize; 233 234 data += len - blocksize; 235 for (i = len - blocksize; i >= blocksize; data -= blocksize, i -= blocksize) 236 { 237 cast_decrypt (&ks->ks_cast, data, data); 238 XOR64 (data, data - blocksize); 239 } 240 cast_decrypt (&ks->ks_cast, data, data); 241 XOR64 (data, ks->riv); 242} 243 244struct crypto_xf * 245crypto_get (enum transform id) 246{ 247 int i; 248 249 for (i = 0; i < sizeof transforms / sizeof transforms[0]; i++) 250 if (id == transforms[i].id) 251 return &transforms[i]; 252 253 return 0; 254} 255 256struct keystate * 257crypto_init (struct crypto_xf *xf, u_int8_t *key, u_int16_t len, 258 enum cryptoerr *err) 259{ 260 struct keystate *ks; 261 262 if (len < xf->keymin || len > xf->keymax) 263 { 264 log_debug (LOG_CRYPTO, 10, "crypto_init: invalid key length %d", len); 265 *err = EKEYLEN; 266 return 0; 267 } 268 269 ks = calloc (1, sizeof *ks); 270 if (!ks) 271 { 272 log_error ("crypto_init: calloc (1, %d) failed", sizeof *ks); 273 *err = ENOCRYPTO; 274 return 0; 275 } 276 277 ks->xf = xf; 278 279 /* Setup the IV. */ 280 ks->riv = ks->iv; 281 ks->liv = ks->iv2; 282 283 log_debug_buf (LOG_CRYPTO, 40, "crypto_init: key", key, len); 284 285 *err = xf->init (ks, key, len); 286 if (*err != EOKAY) 287 { 288 log_debug (LOG_CRYPTO, 30, "crypto_init: weak key found for %s", 289 xf->name); 290 free (ks); 291 return 0; 292 } 293 294 return ks; 295} 296 297void 298crypto_update_iv (struct keystate *ks) 299{ 300 u_int8_t *tmp; 301 302 tmp = ks->riv; 303 ks->riv = ks->liv; 304 ks->liv = tmp; 305 306 log_debug_buf (LOG_CRYPTO, 50, "crypto_update_iv: updated IV", ks->riv, 307 ks->xf->blocksize); 308} 309 310void 311crypto_init_iv (struct keystate *ks, u_int8_t *buf, size_t len) 312{ 313 memcpy (ks->riv, buf, len); 314 315 log_debug_buf (LOG_CRYPTO, 50, "crypto_update_iv: initialized IV", ks->riv, 316 len); 317} 318 319void 320crypto_encrypt (struct keystate *ks, u_int8_t *buf, u_int16_t len) 321{ 322 log_debug_buf (LOG_CRYPTO, 10, "crypto_encrypt: before encryption", buf, 323 len); 324 ks->xf->encrypt (ks, buf, len); 325 memcpy (ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize); 326 log_debug_buf (LOG_CRYPTO, 30, "crypto_encrypt: after encryption", buf, 327 len); 328} 329 330void 331crypto_decrypt (struct keystate *ks, u_int8_t *buf, u_int16_t len) 332{ 333 log_debug_buf (LOG_CRYPTO, 10, "crypto_decrypt: before decryption", buf, 334 len); 335 /* 336 * XXX There is controversy about the correctness of updating the IV 337 * like this. 338 */ 339 memcpy (ks->liv, buf + len - ks->xf->blocksize, ks->xf->blocksize); 340 ks->xf->decrypt (ks, buf, len);; 341 log_debug_buf (LOG_CRYPTO, 30, "crypto_decrypt: after decryption", buf, 342 len); 343} 344 345/* Make a copy of the keystate pointed to by OKS. */ 346struct keystate * 347crypto_clone_keystate (struct keystate *oks) 348{ 349 struct keystate *ks; 350 351 ks = malloc (sizeof *ks); 352 if (!ks) 353 { 354 log_error ("crypto_clone_keystate: malloc (%d) failed", sizeof *ks); 355 return 0; 356 } 357 memcpy (ks, oks, sizeof *ks); 358 if (oks->riv == oks->iv) 359 { 360 ks->riv = ks->iv; 361 ks->liv = ks->iv2; 362 } 363 else 364 { 365 ks->riv = ks->iv2; 366 ks->liv = ks->iv; 367 } 368 return ks; 369} 370