Home | History | Annotate | Download | only in crypto
      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