crypto_internal-cipher.c
Go to the documentation of this file.
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 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:33