blob: b2bc5afc198833d184da9de848680009487751e6 [file] [log] [blame]
/*
* Compare encryption results with ones from openssl.
*
* Placed under public domain.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <crypto/cryptodev.h>
#include "openssl_wrapper.h"
#define BLOCK_SIZE 16
#define KEY_SIZE 16
#define MAX_DATALEN (64 * 1024)
static int
test_crypto(int cfd, struct session_op *sess, int datalen)
{
char *data, *encrypted;
char *encrypted_comp;
char iv_in[BLOCK_SIZE];
char iv[BLOCK_SIZE];
char iv_comp[BLOCK_SIZE];
struct crypt_op cryp;
int ret = 0, fail = 0;
data = malloc(datalen);
encrypted = malloc(datalen);
encrypted_comp = malloc(datalen);
memset(data, datalen & 0xff, datalen);
memset(encrypted, 0x27, datalen);
memset(encrypted_comp, 0x41, datalen);
memset(iv_in, 0x23, sizeof(iv_in));
memcpy(iv, iv_in, sizeof(iv));
memcpy(iv_comp, iv_in, sizeof(iv_comp));
memset(&cryp, 0, sizeof(cryp));
/* Encrypt data.in to data.encrypted */
cryp.ses = sess->ses;
cryp.len = datalen;
cryp.src = data;
cryp.dst = encrypted;
cryp.iv = iv;
cryp.op = COP_ENCRYPT;
cryp.flags = COP_FLAG_WRITE_IV;
if ((ret = ioctl(cfd, CIOCCRYPT, &cryp))) {
perror("ioctl(CIOCCRYPT)");
goto out;
}
cryp.dst = encrypted_comp;
cryp.iv = iv_comp;
if ((ret = openssl_cioccrypt(sess, &cryp))) {
fprintf(stderr, "openssl_cioccrypt() failed!\n");
goto out;
}
if ((ret = memcmp(encrypted, encrypted_comp, cryp.len))) {
printf("fail for datalen %d, cipher texts do not match!\n", datalen);
}
if ((ret = memcmp(iv, iv_comp, BLOCK_SIZE))) {
printf("fail for datalen %d, IVs do not match!\n", datalen);
}
out:
free(data);
free(encrypted);
free(encrypted_comp);
return ret;
}
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
int
main(int argc, char **argv)
{
int fd;
struct session_op sess;
unsigned char key[KEY_SIZE];
int datalen = BLOCK_SIZE;
int datalen_end = MAX_DATALEN;
int i;
if (argc > 1) {
datalen = min(max(atoi(argv[1]), BLOCK_SIZE), MAX_DATALEN);
datalen_end = datalen;
}
if (argc > 2) {
datalen_end = min(atoi(argv[2]), MAX_DATALEN);
if (datalen_end < datalen)
datalen_end = datalen;
}
/* Open the crypto device */
fd = open("/dev/crypto", O_RDWR, 0);
if (fd < 0) {
perror("open(/dev/crypto)");
return 1;
}
for (i = 0; i < KEY_SIZE; i++)
key[i] = i & 0xff;
memset(&sess, 0, sizeof(sess));
/* encryption test */
sess.cipher = CRYPTO_AES_CBC;
sess.keylen = KEY_SIZE;
sess.key = key;
if (ioctl(fd, CIOCGSESSION, &sess)) {
perror("ioctl(CIOCGSESSION)");
return 1;
}
#ifdef CIOCGSESSINFO
{
struct session_info_op siop = {
.ses = sess.ses,
};
if (ioctl(fd, CIOCGSESSINFO, &siop)) {
perror("ioctl(CIOCGSESSINFO)");
} else {
printf("requested cipher CRYPTO_AES_CBC and mac CRYPTO_SHA1_HMAC,"
" got cipher %s with driver %s and hash %s with driver %s\n",
siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name,
siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
}
}
#endif
for (; datalen <= datalen_end; datalen += BLOCK_SIZE) {
if (test_crypto(fd, &sess, datalen)) {
printf("test_crypto() failed for datalen of %d\n", datalen);
return 1;
}
}
/* Finish crypto session */
if (ioctl(fd, CIOCFSESSION, &sess.ses)) {
perror("ioctl(CIOCFSESSION)");
}
close(fd);
return 0;
}