int fast_crypto_cipher_decrypt(struct crypto_cipher *ctx, const uint8_t *crypt, uint8_t *plain, size_t len) { size_t i, j, blocks; uint8_t tmp[32]; struct fast_crypto_cipher *fast_ctx; fast_ctx = (struct fast_crypto_cipher *)ctx; switch (fast_ctx->alg) { case CRYPTO_CIPHER_ALG_RC4: if (plain != crypt) { os_memcpy(plain, crypt, len); } rc4_skip(fast_ctx->u.rc4.key, fast_ctx->u.rc4.keylen, fast_ctx->u.rc4.used_bytes, plain, len); fast_ctx->u.rc4.used_bytes += len; break; case CRYPTO_CIPHER_ALG_AES: if (len % AES_BLOCK_SIZE) { return -1; } blocks = len / AES_BLOCK_SIZE; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, AES_BLOCK_SIZE); mbedtls_aes_decrypt(&(fast_ctx->u.aes.ctx_dec), crypt, plain); for (j = 0; j < AES_BLOCK_SIZE; j++) plain[j] ^= fast_ctx->u.aes.cbc[j]; os_memcpy(fast_ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE); plain += AES_BLOCK_SIZE; crypt += AES_BLOCK_SIZE; } break; #ifdef CONFIG_DES3 case CRYPTO_CIPHER_ALG_3DES: if (len % 8) { return -1; } blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des3_decrypt(crypt, &fast_ctx->u.des3.key, plain); for (j = 0; j < 8; j++) { plain[j] ^= fast_ctx->u.des3.cbc[j]; } os_memcpy(fast_ctx->u.des3.cbc, tmp, 8); plain += 8; crypt += 8; } break; #endif #ifdef CONFIG_DES case CRYPTO_CIPHER_ALG_DES: if (len % 8) { return -1; } blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des_block_decrypt(crypt, fast_ctx->u.des.dk, plain); for (j = 0; j < 8; j++) { plain[j] ^= fast_ctx->u.des.cbc[j]; } os_memcpy(fast_ctx->u.des.cbc, tmp, 8); plain += 8; crypt += 8; } break; #endif default: return -1; } return 0; }
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { size_t i, j, blocks; u8 tmp[32]; switch (ctx->alg) { case CRYPTO_CIPHER_ALG_RC4: if (plain != crypt) os_memcpy(plain, crypt, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, plain, len); ctx->u.rc4.used_bytes += len; break; case CRYPTO_CIPHER_ALG_AES: if (len % AES_BLOCK_SIZE) return -1; blocks = len / AES_BLOCK_SIZE; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, AES_BLOCK_SIZE); aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); for (j = 0; j < AES_BLOCK_SIZE; j++) plain[j] ^= ctx->u.aes.cbc[j]; os_memcpy(ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE); plain += AES_BLOCK_SIZE; crypt += AES_BLOCK_SIZE; } break; case CRYPTO_CIPHER_ALG_3DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des3_decrypt(crypt, &ctx->u.des3.key, plain); for (j = 0; j < 8; j++) plain[j] ^= ctx->u.des3.cbc[j]; os_memcpy(ctx->u.des3.cbc, tmp, 8); plain += 8; crypt += 8; } break; case CRYPTO_CIPHER_ALG_DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des_block_decrypt(crypt, ctx->u.des.dk, plain); for (j = 0; j < 8; j++) plain[j] ^= ctx->u.des.cbc[j]; os_memcpy(ctx->u.des.cbc, tmp, 8); plain += 8; crypt += 8; } break; default: return -1; } return 0; }