1 /* 2 * Crypto wrapper for internal crypto implementation - Cipher wrappers 3 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "crypto.h" 19 #include "aes.h" 20 #include "des_i.h" 21 22 23 struct crypto_cipher { 24 enum crypto_cipher_alg alg; 25 union { 26 struct { 27 size_t used_bytes; 28 u8 key[16]; 29 size_t keylen; 30 } rc4; 31 struct { 32 u8 cbc[32]; 33 size_t block_size; 34 void *ctx_enc; 35 void *ctx_dec; 36 } aes; 37 struct { 38 struct des3_key_s key; 39 u8 cbc[8]; 40 } des3; 41 struct { 42 u32 ek[32]; 43 u32 dk[32]; 44 u8 cbc[8]; 45 } des; 46 } u; 47 }; 48 49 50 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 51 const u8 *iv, const u8 *key, 52 size_t key_len) 53 { 54 struct crypto_cipher *ctx; 55 56 ctx = os_zalloc(sizeof(*ctx)); 57 if (ctx == NULL) 58 return NULL; 59 60 ctx->alg = alg; 61 62 switch (alg) { 63 case CRYPTO_CIPHER_ALG_RC4: 64 if (key_len > sizeof(ctx->u.rc4.key)) { 65 os_free(ctx); 66 return NULL; 67 } 68 ctx->u.rc4.keylen = key_len; 69 os_memcpy(ctx->u.rc4.key, key, key_len); 70 break; 71 case CRYPTO_CIPHER_ALG_AES: 72 if (key_len > sizeof(ctx->u.aes.cbc)) { 73 os_free(ctx); 74 return NULL; 75 } 76 ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); 77 if (ctx->u.aes.ctx_enc == NULL) { 78 os_free(ctx); 79 return NULL; 80 } 81 ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); 82 if (ctx->u.aes.ctx_dec == NULL) { 83 aes_encrypt_deinit(ctx->u.aes.ctx_enc); 84 os_free(ctx); 85 return NULL; 86 } 87 ctx->u.aes.block_size = key_len; 88 os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); 89 break; 90 case CRYPTO_CIPHER_ALG_3DES: 91 if (key_len != 24) { 92 os_free(ctx); 93 return NULL; 94 } 95 des3_key_setup(key, &ctx->u.des3.key); 96 os_memcpy(ctx->u.des3.cbc, iv, 8); 97 break; 98 case CRYPTO_CIPHER_ALG_DES: 99 if (key_len != 8) { 100 os_free(ctx); 101 return NULL; 102 } 103 des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); 104 os_memcpy(ctx->u.des.cbc, iv, 8); 105 break; 106 default: 107 os_free(ctx); 108 return NULL; 109 } 110 111 return ctx; 112 } 113 114 115 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 116 u8 *crypt, size_t len) 117 { 118 size_t i, j, blocks; 119 120 switch (ctx->alg) { 121 case CRYPTO_CIPHER_ALG_RC4: 122 if (plain != crypt) 123 os_memcpy(crypt, plain, len); 124 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 125 ctx->u.rc4.used_bytes, crypt, len); 126 ctx->u.rc4.used_bytes += len; 127 break; 128 case CRYPTO_CIPHER_ALG_AES: 129 if (len % ctx->u.aes.block_size) 130 return -1; 131 blocks = len / ctx->u.aes.block_size; 132 for (i = 0; i < blocks; i++) { 133 for (j = 0; j < ctx->u.aes.block_size; j++) 134 ctx->u.aes.cbc[j] ^= plain[j]; 135 aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, 136 ctx->u.aes.cbc); 137 os_memcpy(crypt, ctx->u.aes.cbc, 138 ctx->u.aes.block_size); 139 plain += ctx->u.aes.block_size; 140 crypt += ctx->u.aes.block_size; 141 } 142 break; 143 case CRYPTO_CIPHER_ALG_3DES: 144 if (len % 8) 145 return -1; 146 blocks = len / 8; 147 for (i = 0; i < blocks; i++) { 148 for (j = 0; j < 8; j++) 149 ctx->u.des3.cbc[j] ^= plain[j]; 150 des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, 151 ctx->u.des3.cbc); 152 os_memcpy(crypt, ctx->u.des3.cbc, 8); 153 plain += 8; 154 crypt += 8; 155 } 156 break; 157 case CRYPTO_CIPHER_ALG_DES: 158 if (len % 8) 159 return -1; 160 blocks = len / 8; 161 for (i = 0; i < blocks; i++) { 162 for (j = 0; j < 8; j++) 163 ctx->u.des3.cbc[j] ^= plain[j]; 164 des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek, 165 ctx->u.des.cbc); 166 os_memcpy(crypt, ctx->u.des.cbc, 8); 167 plain += 8; 168 crypt += 8; 169 } 170 break; 171 default: 172 return -1; 173 } 174 175 return 0; 176 } 177 178 179 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 180 u8 *plain, size_t len) 181 { 182 size_t i, j, blocks; 183 u8 tmp[32]; 184 185 switch (ctx->alg) { 186 case CRYPTO_CIPHER_ALG_RC4: 187 if (plain != crypt) 188 os_memcpy(plain, crypt, len); 189 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 190 ctx->u.rc4.used_bytes, plain, len); 191 ctx->u.rc4.used_bytes += len; 192 break; 193 case CRYPTO_CIPHER_ALG_AES: 194 if (len % ctx->u.aes.block_size) 195 return -1; 196 blocks = len / ctx->u.aes.block_size; 197 for (i = 0; i < blocks; i++) { 198 os_memcpy(tmp, crypt, ctx->u.aes.block_size); 199 aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); 200 for (j = 0; j < ctx->u.aes.block_size; j++) 201 plain[j] ^= ctx->u.aes.cbc[j]; 202 os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); 203 plain += ctx->u.aes.block_size; 204 crypt += ctx->u.aes.block_size; 205 } 206 break; 207 case CRYPTO_CIPHER_ALG_3DES: 208 if (len % 8) 209 return -1; 210 blocks = len / 8; 211 for (i = 0; i < blocks; i++) { 212 os_memcpy(tmp, crypt, 8); 213 des3_decrypt(crypt, &ctx->u.des3.key, plain); 214 for (j = 0; j < 8; j++) 215 plain[j] ^= ctx->u.des3.cbc[j]; 216 os_memcpy(ctx->u.des3.cbc, tmp, 8); 217 plain += 8; 218 crypt += 8; 219 } 220 break; 221 case CRYPTO_CIPHER_ALG_DES: 222 if (len % 8) 223 return -1; 224 blocks = len / 8; 225 for (i = 0; i < blocks; i++) { 226 os_memcpy(tmp, crypt, 8); 227 des_block_decrypt(crypt, ctx->u.des.dk, plain); 228 for (j = 0; j < 8; j++) 229 plain[j] ^= ctx->u.des.cbc[j]; 230 os_memcpy(ctx->u.des.cbc, tmp, 8); 231 plain += 8; 232 crypt += 8; 233 } 234 break; 235 default: 236 return -1; 237 } 238 239 return 0; 240 } 241 242 243 void crypto_cipher_deinit(struct crypto_cipher *ctx) 244 { 245 switch (ctx->alg) { 246 case CRYPTO_CIPHER_ALG_AES: 247 aes_encrypt_deinit(ctx->u.aes.ctx_enc); 248 aes_decrypt_deinit(ctx->u.aes.ctx_dec); 249 break; 250 case CRYPTO_CIPHER_ALG_3DES: 251 break; 252 default: 253 break; 254 } 255 os_free(ctx); 256 } 257