summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-06-15 18:56:23 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-06-17 20:49:04 +0200
commit775307081d84e0ad390943aa64705280035ac17e (patch)
tree851a4225098a90cde3f3f55e657673e4a0e87de6
parent50ca531fd57d964d9eb3005e59273c6d26c4f277 (diff)
downloadcryptodev-linux-775307081d84e0ad390943aa64705280035ac17e.tar.gz
cryptodev-linux-775307081d84e0ad390943aa64705280035ac17e.tar.xz
cryptodev-linux-775307081d84e0ad390943aa64705280035ac17e.zip
Wrapping/Unwrapping works and tested.
-rw-r--r--examples/new.c94
-rw-r--r--ncr-key-wrap.c66
2 files changed, 137 insertions, 23 deletions
diff --git a/examples/new.c b/examples/new.c
index 65592c4..6709bb1 100644
--- a/examples/new.c
+++ b/examples/new.c
@@ -532,6 +532,11 @@ test_ncr_wrap_key(int cfd)
}
/* now export the unwrapped */
+#if 0
+ /* this cannot be performed like that, because unwrap
+ * always sets keys as unexportable. Maybe we can implement
+ * a data comparison ioctl().
+ */
memset(&keydata, 0, sizeof(keydata));
keydata.key = key2;
keydata.data = kdata.desc;
@@ -556,7 +561,7 @@ test_ncr_wrap_key(int cfd)
fprintf(stderr, "\n");
return 1;
}
-
+#endif
@@ -642,10 +647,8 @@ test_ncr_aes(int cfd)
keydata.algorithm = NCR_ALG_AES_CBC;
keydata.flags = NCR_KEY_FLAG_EXPORTABLE;
- keydata.key = key;
- keydata.data = dd;
- fprintf(stdout, "Tests on AES\n");
+ fprintf(stdout, "Tests on AES Encryption\n");
for (i=0;i<sizeof(aes_vectors)/sizeof(aes_vectors[0]);i++) {
/* import key */
@@ -660,6 +663,8 @@ test_ncr_aes(int cfd)
return 1;
}
+ keydata.key = key;
+ keydata.data = dd;
if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
perror("ioctl(NCRIO_KEY_IMPORT)");
@@ -720,6 +725,84 @@ test_ncr_aes(int cfd)
}
}
+ fprintf(stdout, "Tests on AES Decryption\n");
+ for (i=0;i<sizeof(aes_vectors)/sizeof(aes_vectors[0]);i++) {
+
+ /* import key */
+ kdata.data = (void*)aes_vectors[i].key;
+ kdata.data_size = 16;
+ kdata.desc = dd;
+ kdata.append_flag = 0;
+
+ if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_INIT)");
+ return 1;
+ }
+
+ keydata.key = key;
+ keydata.data = dd;
+ if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_KEY_IMPORT)");
+ return 1;
+ }
+
+ /* import ciphertext */
+
+ kdata.data = (void*)aes_vectors[i].ciphertext;
+ kdata.data_size = 16;
+ kdata.desc = dd;
+ kdata.append_flag = 0;
+
+ if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_INIT)");
+ return 1;
+ }
+
+ /* decrypt */
+ memset(&nop, 0, sizeof(nop));
+ nop.init.algorithm = NCR_ALG_AES_ECB;
+ nop.init.params.key = key;
+ nop.init.op = NCR_OP_DECRYPT;
+ nop.op.data.cipher.ciphertext = dd;
+ nop.op.data.cipher.plaintext = dd2;
+
+ if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_SESSION_ONCE)");
+ return 1;
+ }
+
+ /* verify */
+ kdata.desc = dd2;
+ kdata.data = data;
+ kdata.data_size = sizeof(data);
+ kdata.append_flag = 0;
+
+ if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_GET)");
+ return 1;
+ }
+
+ if (kdata.data_size != 16 || memcmp(kdata.data, aes_vectors[i].plaintext, 16) != 0) {
+ fprintf(stderr, "AES test vector %d failed!\n", i);
+
+ fprintf(stderr, "Plain[%d]: ", (int)kdata.data_size);
+ for(j=0;j<kdata.data_size;j++)
+ fprintf(stderr, "%.2x:", (int)data[j]);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Expected[%d]: ", 16);
+ for(j=0;j<16;j++)
+ fprintf(stderr, "%.2x:", (int)aes_vectors[i].plaintext[j]);
+ fprintf(stderr, "\n");
+// return 1;
+ }
+ }
+
fprintf(stdout, "\n");
@@ -738,7 +821,6 @@ main()
perror("open(/dev/crypto)");
return 1;
}
-#if 0
/* Run the test itself */
if (test_ncr_data(fd))
@@ -763,7 +845,7 @@ main()
if (test_ncr_aes(fd))
return 1;
-#endif
+
if (test_ncr_wrap_key(fd))
return 1;
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c
index 74e1f64..b6987af 100644
--- a/ncr-key-wrap.c
+++ b/ncr-key-wrap.c
@@ -50,7 +50,7 @@ void val64_xor( val64_t * val, uint32_t x)
/* Wraps using the RFC3394 way.
*/
static int wrap_aes(struct key_item_st* tobewrapped, struct key_item_st *kek,
- struct data_item_st* output)
+ struct data_item_st* output, const void* iv, size_t iv_size)
{
size_t key_size, n;
uint8_t *raw_key;
@@ -63,6 +63,11 @@ struct cipher_data ctx;
err();
return -EINVAL;
}
+
+ if (iv_size < sizeof(initA)) {
+ iv_size = sizeof(initA);
+ iv = initA;
+ }
ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
if (ret < 0) {
@@ -96,7 +101,7 @@ struct cipher_data ctx;
memcpy(R[i], &raw_key[i*8], 8);
}
- memcpy(A, initA, sizeof(initA));
+ memcpy(A, iv, 8);
for (i=0;i<6*n;i++) {
memcpy(aes_block, A, 8);
@@ -128,16 +133,34 @@ cleanup:
return ret;
}
+#if 0
+/* for debugging */
+void print_val64(char* str, val64_t val)
+{
+ int i;
+ printk("%s: ",str);
+ for (i=0;i<8;i++)
+ printk("%.2x", val[i]);
+ printk("\n");
+
+}
+#endif
+
static int unwrap_aes(struct key_item_st* output, struct key_item_st *kek,
- struct data_item_st* wrapped)
+ struct data_item_st* wrapped, const void* iv, size_t iv_size)
{
-size_t key_size, n;
-uint8_t *raw_key;
+size_t wrapped_key_size, n;
+uint8_t *wrapped_key;
val64_t A;
int i, j, ret;
uint8_t aes_block[16];
struct cipher_data ctx;
+ if (iv_size < sizeof(initA)) {
+ iv_size = sizeof(initA);
+ iv = initA;
+ }
+
ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
if (ret < 0) {
err();
@@ -146,16 +169,16 @@ struct cipher_data ctx;
output->type = NCR_KEY_TYPE_SECRET;
- raw_key = wrapped->data;
- key_size = wrapped->data_size;
+ wrapped_key = wrapped->data;
+ wrapped_key_size = wrapped->data_size;
- if (key_size % 8 != 0) {
+ if (wrapped_key_size % 8 != 0) {
err();
ret = -EINVAL;
goto cleanup;
}
- n = key_size/8 - 1;
+ n = wrapped_key_size/8 - 1;
if (sizeof(output->key.secret.data) < (n-1)*8) {
err();
@@ -166,10 +189,10 @@ struct cipher_data ctx;
{
val64_t R[n];
- memcpy(A, raw_key, 8); /* A = C[0] */
+ memcpy(A, wrapped_key, 8); /* A = C[0] */
for (i=0;i<n;i++)
- memcpy(R[i], &raw_key[(i+1)*8], 8);
-
+ memcpy(R[i], &wrapped_key[(i+1)*8], 8);
+
for (i=(6*n)-1;i>=0;i--) {
val64_xor(&A, i+1);
@@ -180,22 +203,27 @@ struct cipher_data ctx;
aes_block, sizeof(aes_block));
memcpy(A, aes_block, 8);
- memcpy(R[0], &aes_block[8], 8);
- for (j=1;j<n;j++)
+ for (j=n-1;j>=1;j--)
memcpy(R[j], R[j-1], sizeof(R[j]));
+
+ memcpy(R[0], &aes_block[8], 8);
}
- if (memcmp(A, initA, sizeof(initA))!= 0) {
+
+ if (memcmp(A, iv, 8)!= 0) {
err();
ret = -EINVAL;
goto cleanup;
}
+ memset(&output->key, 0, sizeof(output->key));
for (i=0;i<n;i++) {
memcpy(&output->key.secret.data[i*8], R[i], sizeof(R[i]));
}
output->key.secret.size = n*8;
+ output->flags = NCR_KEY_FLAG_WRAPPABLE;
+ output->type = NCR_KEY_TYPE_SECRET;
}
@@ -229,6 +257,7 @@ int ret;
return -EPERM;
}
+ /* FIXME: allow alternative IV */
key = ncr_key_item_get( key_lst, wrap.key.key);
if (key == NULL) {
err();
@@ -247,7 +276,7 @@ int ret;
switch(wrap.algorithm) {
case NCR_WALG_AES_RFC3394:
- ret = wrap_aes(wkey, key, data);
+ ret = wrap_aes(wkey, key, data, wrap.key.params.cipher.iv, wrap.key.params.cipher.iv_size);
break;
default:
err();
@@ -262,6 +291,9 @@ fail:
return ret;
}
+/* Unwraps keys. All keys unwrapped are not accessible by
+ * userspace.
+ */
int ncr_key_unwrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg)
{
struct ncr_key_wrap_st wrap;
@@ -296,7 +328,7 @@ int ret;
switch(wrap.algorithm) {
case NCR_WALG_AES_RFC3394:
- ret = unwrap_aes(wkey, key, data);
+ ret = unwrap_aes(wkey, key, data, wrap.key.params.cipher.iv, wrap.key.params.cipher.iv_size);
break;
default:
err();