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