$search
00001 /* 00002 * Crypto wrapper for internal crypto implementation - Cipher wrappers 00003 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto.h" 00019 #include "aes.h" 00020 #include "des_i.h" 00021 00022 00023 struct crypto_cipher { 00024 enum crypto_cipher_alg alg; 00025 union { 00026 struct { 00027 size_t used_bytes; 00028 u8 key[16]; 00029 size_t keylen; 00030 } rc4; 00031 struct { 00032 u8 cbc[32]; 00033 size_t block_size; 00034 void *ctx_enc; 00035 void *ctx_dec; 00036 } aes; 00037 struct { 00038 struct des3_key_s key; 00039 u8 cbc[8]; 00040 } des3; 00041 struct { 00042 u32 ek[32]; 00043 u32 dk[32]; 00044 u8 cbc[8]; 00045 } des; 00046 } u; 00047 }; 00048 00049 00050 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 00051 const u8 *iv, const u8 *key, 00052 size_t key_len) 00053 { 00054 struct crypto_cipher *ctx; 00055 00056 ctx = os_zalloc(sizeof(*ctx)); 00057 if (ctx == NULL) 00058 return NULL; 00059 00060 ctx->alg = alg; 00061 00062 switch (alg) { 00063 case CRYPTO_CIPHER_ALG_RC4: 00064 if (key_len > sizeof(ctx->u.rc4.key)) { 00065 os_free(ctx); 00066 return NULL; 00067 } 00068 ctx->u.rc4.keylen = key_len; 00069 os_memcpy(ctx->u.rc4.key, key, key_len); 00070 break; 00071 case CRYPTO_CIPHER_ALG_AES: 00072 if (key_len > sizeof(ctx->u.aes.cbc)) { 00073 os_free(ctx); 00074 return NULL; 00075 } 00076 ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); 00077 if (ctx->u.aes.ctx_enc == NULL) { 00078 os_free(ctx); 00079 return NULL; 00080 } 00081 ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); 00082 if (ctx->u.aes.ctx_dec == NULL) { 00083 aes_encrypt_deinit(ctx->u.aes.ctx_enc); 00084 os_free(ctx); 00085 return NULL; 00086 } 00087 ctx->u.aes.block_size = key_len; 00088 os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); 00089 break; 00090 case CRYPTO_CIPHER_ALG_3DES: 00091 if (key_len != 24) { 00092 os_free(ctx); 00093 return NULL; 00094 } 00095 des3_key_setup(key, &ctx->u.des3.key); 00096 os_memcpy(ctx->u.des3.cbc, iv, 8); 00097 break; 00098 case CRYPTO_CIPHER_ALG_DES: 00099 if (key_len != 8) { 00100 os_free(ctx); 00101 return NULL; 00102 } 00103 des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); 00104 os_memcpy(ctx->u.des.cbc, iv, 8); 00105 break; 00106 default: 00107 os_free(ctx); 00108 return NULL; 00109 } 00110 00111 return ctx; 00112 } 00113 00114 00115 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 00116 u8 *crypt, size_t len) 00117 { 00118 size_t i, j, blocks; 00119 00120 switch (ctx->alg) { 00121 case CRYPTO_CIPHER_ALG_RC4: 00122 if (plain != crypt) 00123 os_memcpy(crypt, plain, len); 00124 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 00125 ctx->u.rc4.used_bytes, crypt, len); 00126 ctx->u.rc4.used_bytes += len; 00127 break; 00128 case CRYPTO_CIPHER_ALG_AES: 00129 if (len % ctx->u.aes.block_size) 00130 return -1; 00131 blocks = len / ctx->u.aes.block_size; 00132 for (i = 0; i < blocks; i++) { 00133 for (j = 0; j < ctx->u.aes.block_size; j++) 00134 ctx->u.aes.cbc[j] ^= plain[j]; 00135 aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, 00136 ctx->u.aes.cbc); 00137 os_memcpy(crypt, ctx->u.aes.cbc, 00138 ctx->u.aes.block_size); 00139 plain += ctx->u.aes.block_size; 00140 crypt += ctx->u.aes.block_size; 00141 } 00142 break; 00143 case CRYPTO_CIPHER_ALG_3DES: 00144 if (len % 8) 00145 return -1; 00146 blocks = len / 8; 00147 for (i = 0; i < blocks; i++) { 00148 for (j = 0; j < 8; j++) 00149 ctx->u.des3.cbc[j] ^= plain[j]; 00150 des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, 00151 ctx->u.des3.cbc); 00152 os_memcpy(crypt, ctx->u.des3.cbc, 8); 00153 plain += 8; 00154 crypt += 8; 00155 } 00156 break; 00157 case CRYPTO_CIPHER_ALG_DES: 00158 if (len % 8) 00159 return -1; 00160 blocks = len / 8; 00161 for (i = 0; i < blocks; i++) { 00162 for (j = 0; j < 8; j++) 00163 ctx->u.des3.cbc[j] ^= plain[j]; 00164 des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek, 00165 ctx->u.des.cbc); 00166 os_memcpy(crypt, ctx->u.des.cbc, 8); 00167 plain += 8; 00168 crypt += 8; 00169 } 00170 break; 00171 default: 00172 return -1; 00173 } 00174 00175 return 0; 00176 } 00177 00178 00179 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 00180 u8 *plain, size_t len) 00181 { 00182 size_t i, j, blocks; 00183 u8 tmp[32]; 00184 00185 switch (ctx->alg) { 00186 case CRYPTO_CIPHER_ALG_RC4: 00187 if (plain != crypt) 00188 os_memcpy(plain, crypt, len); 00189 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 00190 ctx->u.rc4.used_bytes, plain, len); 00191 ctx->u.rc4.used_bytes += len; 00192 break; 00193 case CRYPTO_CIPHER_ALG_AES: 00194 if (len % ctx->u.aes.block_size) 00195 return -1; 00196 blocks = len / ctx->u.aes.block_size; 00197 for (i = 0; i < blocks; i++) { 00198 os_memcpy(tmp, crypt, ctx->u.aes.block_size); 00199 aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); 00200 for (j = 0; j < ctx->u.aes.block_size; j++) 00201 plain[j] ^= ctx->u.aes.cbc[j]; 00202 os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); 00203 plain += ctx->u.aes.block_size; 00204 crypt += ctx->u.aes.block_size; 00205 } 00206 break; 00207 case CRYPTO_CIPHER_ALG_3DES: 00208 if (len % 8) 00209 return -1; 00210 blocks = len / 8; 00211 for (i = 0; i < blocks; i++) { 00212 os_memcpy(tmp, crypt, 8); 00213 des3_decrypt(crypt, &ctx->u.des3.key, plain); 00214 for (j = 0; j < 8; j++) 00215 plain[j] ^= ctx->u.des3.cbc[j]; 00216 os_memcpy(ctx->u.des3.cbc, tmp, 8); 00217 plain += 8; 00218 crypt += 8; 00219 } 00220 break; 00221 case CRYPTO_CIPHER_ALG_DES: 00222 if (len % 8) 00223 return -1; 00224 blocks = len / 8; 00225 for (i = 0; i < blocks; i++) { 00226 os_memcpy(tmp, crypt, 8); 00227 des_block_decrypt(crypt, ctx->u.des.dk, plain); 00228 for (j = 0; j < 8; j++) 00229 plain[j] ^= ctx->u.des.cbc[j]; 00230 os_memcpy(ctx->u.des.cbc, tmp, 8); 00231 plain += 8; 00232 crypt += 8; 00233 } 00234 break; 00235 default: 00236 return -1; 00237 } 00238 00239 return 0; 00240 } 00241 00242 00243 void crypto_cipher_deinit(struct crypto_cipher *ctx) 00244 { 00245 switch (ctx->alg) { 00246 case CRYPTO_CIPHER_ALG_AES: 00247 aes_encrypt_deinit(ctx->u.aes.ctx_enc); 00248 aes_decrypt_deinit(ctx->u.aes.ctx_dec); 00249 break; 00250 case CRYPTO_CIPHER_ALG_3DES: 00251 break; 00252 default: 00253 break; 00254 } 00255 os_free(ctx); 00256 }