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