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