1214501Srpaulo/* 2214501Srpaulo * Crypto wrapper for internal crypto implementation - Cipher wrappers 3214501Srpaulo * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "includes.h" 10214501Srpaulo 11214501Srpaulo#include "common.h" 12214501Srpaulo#include "crypto.h" 13214501Srpaulo#include "aes.h" 14214501Srpaulo#include "des_i.h" 15214501Srpaulo 16214501Srpaulo 17214501Srpaulostruct crypto_cipher { 18214501Srpaulo enum crypto_cipher_alg alg; 19214501Srpaulo union { 20214501Srpaulo struct { 21214501Srpaulo size_t used_bytes; 22214501Srpaulo u8 key[16]; 23214501Srpaulo size_t keylen; 24214501Srpaulo } rc4; 25214501Srpaulo struct { 26214501Srpaulo u8 cbc[32]; 27214501Srpaulo void *ctx_enc; 28214501Srpaulo void *ctx_dec; 29214501Srpaulo } aes; 30214501Srpaulo struct { 31214501Srpaulo struct des3_key_s key; 32214501Srpaulo u8 cbc[8]; 33214501Srpaulo } des3; 34214501Srpaulo struct { 35214501Srpaulo u32 ek[32]; 36214501Srpaulo u32 dk[32]; 37214501Srpaulo u8 cbc[8]; 38214501Srpaulo } des; 39214501Srpaulo } u; 40214501Srpaulo}; 41214501Srpaulo 42214501Srpaulo 43214501Srpaulostruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 44214501Srpaulo const u8 *iv, const u8 *key, 45214501Srpaulo size_t key_len) 46214501Srpaulo{ 47214501Srpaulo struct crypto_cipher *ctx; 48214501Srpaulo 49214501Srpaulo ctx = os_zalloc(sizeof(*ctx)); 50214501Srpaulo if (ctx == NULL) 51214501Srpaulo return NULL; 52214501Srpaulo 53214501Srpaulo ctx->alg = alg; 54214501Srpaulo 55214501Srpaulo switch (alg) { 56214501Srpaulo case CRYPTO_CIPHER_ALG_RC4: 57214501Srpaulo if (key_len > sizeof(ctx->u.rc4.key)) { 58214501Srpaulo os_free(ctx); 59214501Srpaulo return NULL; 60214501Srpaulo } 61214501Srpaulo ctx->u.rc4.keylen = key_len; 62214501Srpaulo os_memcpy(ctx->u.rc4.key, key, key_len); 63214501Srpaulo break; 64214501Srpaulo case CRYPTO_CIPHER_ALG_AES: 65214501Srpaulo ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); 66214501Srpaulo if (ctx->u.aes.ctx_enc == NULL) { 67214501Srpaulo os_free(ctx); 68214501Srpaulo return NULL; 69214501Srpaulo } 70214501Srpaulo ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); 71214501Srpaulo if (ctx->u.aes.ctx_dec == NULL) { 72214501Srpaulo aes_encrypt_deinit(ctx->u.aes.ctx_enc); 73214501Srpaulo os_free(ctx); 74214501Srpaulo return NULL; 75214501Srpaulo } 76252726Srpaulo os_memcpy(ctx->u.aes.cbc, iv, AES_BLOCK_SIZE); 77214501Srpaulo break; 78214501Srpaulo case CRYPTO_CIPHER_ALG_3DES: 79214501Srpaulo if (key_len != 24) { 80214501Srpaulo os_free(ctx); 81214501Srpaulo return NULL; 82214501Srpaulo } 83214501Srpaulo des3_key_setup(key, &ctx->u.des3.key); 84214501Srpaulo os_memcpy(ctx->u.des3.cbc, iv, 8); 85214501Srpaulo break; 86214501Srpaulo case CRYPTO_CIPHER_ALG_DES: 87214501Srpaulo if (key_len != 8) { 88214501Srpaulo os_free(ctx); 89214501Srpaulo return NULL; 90214501Srpaulo } 91214501Srpaulo des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); 92214501Srpaulo os_memcpy(ctx->u.des.cbc, iv, 8); 93214501Srpaulo break; 94214501Srpaulo default: 95214501Srpaulo os_free(ctx); 96214501Srpaulo return NULL; 97214501Srpaulo } 98214501Srpaulo 99214501Srpaulo return ctx; 100214501Srpaulo} 101214501Srpaulo 102214501Srpaulo 103214501Srpauloint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 104214501Srpaulo u8 *crypt, size_t len) 105214501Srpaulo{ 106214501Srpaulo size_t i, j, blocks; 107214501Srpaulo 108214501Srpaulo switch (ctx->alg) { 109214501Srpaulo case CRYPTO_CIPHER_ALG_RC4: 110214501Srpaulo if (plain != crypt) 111214501Srpaulo os_memcpy(crypt, plain, len); 112214501Srpaulo rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 113214501Srpaulo ctx->u.rc4.used_bytes, crypt, len); 114214501Srpaulo ctx->u.rc4.used_bytes += len; 115214501Srpaulo break; 116214501Srpaulo case CRYPTO_CIPHER_ALG_AES: 117252726Srpaulo if (len % AES_BLOCK_SIZE) 118214501Srpaulo return -1; 119252726Srpaulo blocks = len / AES_BLOCK_SIZE; 120214501Srpaulo for (i = 0; i < blocks; i++) { 121252726Srpaulo for (j = 0; j < AES_BLOCK_SIZE; j++) 122214501Srpaulo ctx->u.aes.cbc[j] ^= plain[j]; 123214501Srpaulo aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, 124214501Srpaulo ctx->u.aes.cbc); 125252726Srpaulo os_memcpy(crypt, ctx->u.aes.cbc, AES_BLOCK_SIZE); 126252726Srpaulo plain += AES_BLOCK_SIZE; 127252726Srpaulo crypt += AES_BLOCK_SIZE; 128214501Srpaulo } 129214501Srpaulo break; 130214501Srpaulo case CRYPTO_CIPHER_ALG_3DES: 131214501Srpaulo if (len % 8) 132214501Srpaulo return -1; 133214501Srpaulo blocks = len / 8; 134214501Srpaulo for (i = 0; i < blocks; i++) { 135214501Srpaulo for (j = 0; j < 8; j++) 136214501Srpaulo ctx->u.des3.cbc[j] ^= plain[j]; 137214501Srpaulo des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, 138214501Srpaulo ctx->u.des3.cbc); 139214501Srpaulo os_memcpy(crypt, ctx->u.des3.cbc, 8); 140214501Srpaulo plain += 8; 141214501Srpaulo crypt += 8; 142214501Srpaulo } 143214501Srpaulo break; 144214501Srpaulo case CRYPTO_CIPHER_ALG_DES: 145214501Srpaulo if (len % 8) 146214501Srpaulo return -1; 147214501Srpaulo blocks = len / 8; 148214501Srpaulo for (i = 0; i < blocks; i++) { 149214501Srpaulo for (j = 0; j < 8; j++) 150214501Srpaulo ctx->u.des3.cbc[j] ^= plain[j]; 151214501Srpaulo des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek, 152214501Srpaulo ctx->u.des.cbc); 153214501Srpaulo os_memcpy(crypt, ctx->u.des.cbc, 8); 154214501Srpaulo plain += 8; 155214501Srpaulo crypt += 8; 156214501Srpaulo } 157214501Srpaulo break; 158214501Srpaulo default: 159214501Srpaulo return -1; 160214501Srpaulo } 161214501Srpaulo 162214501Srpaulo return 0; 163214501Srpaulo} 164214501Srpaulo 165214501Srpaulo 166214501Srpauloint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 167214501Srpaulo u8 *plain, size_t len) 168214501Srpaulo{ 169214501Srpaulo size_t i, j, blocks; 170214501Srpaulo u8 tmp[32]; 171214501Srpaulo 172214501Srpaulo switch (ctx->alg) { 173214501Srpaulo case CRYPTO_CIPHER_ALG_RC4: 174214501Srpaulo if (plain != crypt) 175214501Srpaulo os_memcpy(plain, crypt, len); 176214501Srpaulo rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 177214501Srpaulo ctx->u.rc4.used_bytes, plain, len); 178214501Srpaulo ctx->u.rc4.used_bytes += len; 179214501Srpaulo break; 180214501Srpaulo case CRYPTO_CIPHER_ALG_AES: 181252726Srpaulo if (len % AES_BLOCK_SIZE) 182214501Srpaulo return -1; 183252726Srpaulo blocks = len / AES_BLOCK_SIZE; 184214501Srpaulo for (i = 0; i < blocks; i++) { 185252726Srpaulo os_memcpy(tmp, crypt, AES_BLOCK_SIZE); 186214501Srpaulo aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); 187252726Srpaulo for (j = 0; j < AES_BLOCK_SIZE; j++) 188214501Srpaulo plain[j] ^= ctx->u.aes.cbc[j]; 189252726Srpaulo os_memcpy(ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE); 190252726Srpaulo plain += AES_BLOCK_SIZE; 191252726Srpaulo crypt += AES_BLOCK_SIZE; 192214501Srpaulo } 193214501Srpaulo break; 194214501Srpaulo case CRYPTO_CIPHER_ALG_3DES: 195214501Srpaulo if (len % 8) 196214501Srpaulo return -1; 197214501Srpaulo blocks = len / 8; 198214501Srpaulo for (i = 0; i < blocks; i++) { 199214501Srpaulo os_memcpy(tmp, crypt, 8); 200214501Srpaulo des3_decrypt(crypt, &ctx->u.des3.key, plain); 201214501Srpaulo for (j = 0; j < 8; j++) 202214501Srpaulo plain[j] ^= ctx->u.des3.cbc[j]; 203214501Srpaulo os_memcpy(ctx->u.des3.cbc, tmp, 8); 204214501Srpaulo plain += 8; 205214501Srpaulo crypt += 8; 206214501Srpaulo } 207214501Srpaulo break; 208214501Srpaulo case CRYPTO_CIPHER_ALG_DES: 209214501Srpaulo if (len % 8) 210214501Srpaulo return -1; 211214501Srpaulo blocks = len / 8; 212214501Srpaulo for (i = 0; i < blocks; i++) { 213214501Srpaulo os_memcpy(tmp, crypt, 8); 214214501Srpaulo des_block_decrypt(crypt, ctx->u.des.dk, plain); 215214501Srpaulo for (j = 0; j < 8; j++) 216214501Srpaulo plain[j] ^= ctx->u.des.cbc[j]; 217214501Srpaulo os_memcpy(ctx->u.des.cbc, tmp, 8); 218214501Srpaulo plain += 8; 219214501Srpaulo crypt += 8; 220214501Srpaulo } 221214501Srpaulo break; 222214501Srpaulo default: 223214501Srpaulo return -1; 224214501Srpaulo } 225214501Srpaulo 226214501Srpaulo return 0; 227214501Srpaulo} 228214501Srpaulo 229214501Srpaulo 230214501Srpaulovoid crypto_cipher_deinit(struct crypto_cipher *ctx) 231214501Srpaulo{ 232214501Srpaulo switch (ctx->alg) { 233214501Srpaulo case CRYPTO_CIPHER_ALG_AES: 234214501Srpaulo aes_encrypt_deinit(ctx->u.aes.ctx_enc); 235214501Srpaulo aes_decrypt_deinit(ctx->u.aes.ctx_dec); 236214501Srpaulo break; 237214501Srpaulo case CRYPTO_CIPHER_ALG_3DES: 238214501Srpaulo break; 239214501Srpaulo default: 240214501Srpaulo break; 241214501Srpaulo } 242214501Srpaulo os_free(ctx); 243214501Srpaulo} 244