From: Sebastian Siewior <hidden> Date: 2008-02-24 11:01:08
From Sebastian Siewior [off-list ref] # This line is ignored.
Subject: [RFC] padlock aes, unification of setkey()
Hello Herbert,
I sit on those two since November. Back then Michal dropped me an email
and told me that he will test it and get back to me. This didn't happen
so far.
The binary format of the key was the same, the last time I checked, so
the second patch could really work :)
One thing I'm concerned about is the stack utilization. The initial
version had a structure with 256 bytes on the stack. Mine has a bigger
structure with 484 bytes. I'm not sure if it is better to dynamically
allocate it, move it to the private key structure or pad the generic
aes structure in order to enforce the required alignment.
Sebastian
From: Sebastian Siewior <hidden> Date: 2008-02-24 11:01:08
The key expansion routine could be get little more generic, become
a kernel doc entry and then get exported.
Signed-off-by: Sebastian Siewior <redacted>
---
crypto/aes_generic.c | 56 +++++++++++++++++++++++++++++++++++++++++--------
include/crypto/aes.h | 8 +++++-
2 files changed, 53 insertions(+), 11 deletions(-)
@@ -284,6 +295,33 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,}return0;}+EXPORT_SYMBOL_GPL(crypto_aes_expand_key);++/**+*crypto_aes_set_key-SettheAESkey.+*@tfm:The%crypto_tfmthatisusedinthecontext.+*@in_key:Theinputkey.+*@key_len:Thesizeofthekey.+*+*Returns0onsuccess,onfailurethe%CRYPTO_TFM_RES_BAD_KEY_LENflagintfm+*isset.Thefunctionusescrypto_aes_expand_key()toexpandthekey.+*&crypto_aes_ctx_must_betheprivatedataembeddedin@tfmwhichis+*retrievedwithcrypto_tfm_ctx().+*/+intcrypto_aes_set_key(structcrypto_tfm*tfm,constu8*in_key,+unsignedintkey_len)+{+structcrypto_aes_ctx*ctx=crypto_tfm_ctx(tfm);+u32*flags=&tfm->crt_flags;+intret;++ret=crypto_aes_expand_key(ctx,in_key,key_len);+if(!ret)+return0;++*flags|=CRYPTO_TFM_RES_BAD_KEY_LEN;+return-EINVAL;+}EXPORT_SYMBOL_GPL(crypto_aes_set_key);/* encrypt a block of text */
From: Sebastian Siewior <hidden> Date: 2008-02-24 11:01:08
Padlock AES' setkey routine is the same as exported by the generic
implementation. So we could use it.
Cc: Michal Ludvig <redacted>
Signed-off-by: Sebastian Siewior <redacted>
---
drivers/crypto/Kconfig | 1 +
drivers/crypto/padlock-aes.c | 320 +++---------------------------------------
2 files changed, 20 insertions(+), 301 deletions(-)
@@ -54,9 +18,6 @@#include<asm/byteorder.h>#include"padlock.h"-#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */-#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))-/* Control word. */structcword{unsignedint__attribute__((__packed__))
@@ -70,218 +31,23 @@ struct cword {/* Whenever making any changes to the following*structure*makesure*youkeepE,d_data-*andcwordalignedon16Bytesboundaries!!!*/+*andcwordalignedon16Bytesboundariesand+*theHardwarecanaccess16*16bytesofEandd_data+*(onlythefirst15*16bytesmatterbuttheHWreads+*more).+*/structaes_ctx{+u32E[AES_MAX_KEYLENGTH_U32]+__attribute__((__aligned__(PADLOCK_ALIGNMENT)));+u32d_data[AES_MAX_KEYLENGTH_U32]+__attribute__((__aligned__(PADLOCK_ALIGNMENT)));struct{structcwordencrypt;structcworddecrypt;}cword;u32*D;-intkey_length;-u32E[AES_EXTENDED_KEY_SIZE]-__attribute__((__aligned__(PADLOCK_ALIGNMENT)));-u32d_data[AES_EXTENDED_KEY_SIZE]-__attribute__((__aligned__(PADLOCK_ALIGNMENT)));};-/* ====== Key management routines ====== */--staticinlineuint32_t-generic_rotr32(constuint32_tx,constunsignedbits)-{-constunsignedn=bits%32;-return(x>>n)|(x<<(32-n));-}--staticinlineuint32_t-generic_rotl32(constuint32_tx,constunsignedbits)-{-constunsignedn=bits%32;-return(x<<n)|(x>>(32-n));-}--#define rotl generic_rotl32-#define rotr generic_rotr32--/*-*#definebyte(x,nr)((unsignedchar)((x)>>(nr*8)))-*/-staticinlineuint8_t-byte(constuint32_tx,constunsignedn)-{-returnx>>(n<<3);-}--#define E_KEY ctx->E-#define D_KEY ctx->D--staticuint8_tpow_tab[256];-staticuint8_tlog_tab[256];-staticuint8_tsbx_tab[256];-staticuint8_tisb_tab[256];-staticuint32_trco_tab[10];-staticuint32_tft_tab[4][256];-staticuint32_tit_tab[4][256];--staticuint32_tfl_tab[4][256];-staticuint32_til_tab[4][256];--staticinlineuint8_t-f_mult(uint8_ta,uint8_tb)-{-uint8_taa=log_tab[a],cc=aa+log_tab[b];--returnpow_tab[cc+(cc<aa?1:0)];-}--#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0)--#define f_rn(bo, bi, n, k) \-bo[n]=ft_tab[0][byte(bi[n],0)]^\-ft_tab[1][byte(bi[(n+1)&3],1)]^\-ft_tab[2][byte(bi[(n+2)&3],2)]^\-ft_tab[3][byte(bi[(n+3)&3],3)]^*(k+n)--#define i_rn(bo, bi, n, k) \-bo[n]=it_tab[0][byte(bi[n],0)]^\-it_tab[1][byte(bi[(n+3)&3],1)]^\-it_tab[2][byte(bi[(n+2)&3],2)]^\-it_tab[3][byte(bi[(n+1)&3],3)]^*(k+n)--#define ls_box(x) \-(fl_tab[0][byte(x,0)]^\-fl_tab[1][byte(x,1)]^\-fl_tab[2][byte(x,2)]^\-fl_tab[3][byte(x,3)])--#define f_rl(bo, bi, n, k) \-bo[n]=fl_tab[0][byte(bi[n],0)]^\-fl_tab[1][byte(bi[(n+1)&3],1)]^\-fl_tab[2][byte(bi[(n+2)&3],2)]^\-fl_tab[3][byte(bi[(n+3)&3],3)]^*(k+n)--#define i_rl(bo, bi, n, k) \-bo[n]=il_tab[0][byte(bi[n],0)]^\-il_tab[1][byte(bi[(n+3)&3],1)]^\-il_tab[2][byte(bi[(n+2)&3],2)]^\-il_tab[3][byte(bi[(n+1)&3],3)]^*(k+n)--staticvoid-gen_tabs(void)-{-uint32_ti,t;-uint8_tp,q;--/* log and power tables for GF(2**8) finite field with-0x011basmodularpolynomial-thesimplestprmitive-rootis0x03,usedheretogeneratethetables*/--for(i=0,p=1;i<256;++i){-pow_tab[i]=(uint8_t)p;-log_tab[p]=(uint8_t)i;--p^=(p<<1)^(p&0x80?0x01b:0);-}--log_tab[1]=0;--for(i=0,p=1;i<10;++i){-rco_tab[i]=p;--p=(p<<1)^(p&0x80?0x01b:0);-}--for(i=0;i<256;++i){-p=(i?pow_tab[255-log_tab[i]]:0);-q=((p>>7)|(p<<1))^((p>>6)|(p<<2));-p^=0x63^q^((q>>6)|(q<<2));-sbx_tab[i]=p;-isb_tab[p]=(uint8_t)i;-}--for(i=0;i<256;++i){-p=sbx_tab[i];--t=p;-fl_tab[0][i]=t;-fl_tab[1][i]=rotl(t,8);-fl_tab[2][i]=rotl(t,16);-fl_tab[3][i]=rotl(t,24);--t=((uint32_t)ff_mult(2,p))|-((uint32_t)p<<8)|-((uint32_t)p<<16)|((uint32_t)ff_mult(3,p)<<24);--ft_tab[0][i]=t;-ft_tab[1][i]=rotl(t,8);-ft_tab[2][i]=rotl(t,16);-ft_tab[3][i]=rotl(t,24);--p=isb_tab[i];--t=p;-il_tab[0][i]=t;-il_tab[1][i]=rotl(t,8);-il_tab[2][i]=rotl(t,16);-il_tab[3][i]=rotl(t,24);--t=((uint32_t)ff_mult(14,p))|-((uint32_t)ff_mult(9,p)<<8)|-((uint32_t)ff_mult(13,p)<<16)|-((uint32_t)ff_mult(11,p)<<24);--it_tab[0][i]=t;-it_tab[1][i]=rotl(t,8);-it_tab[2][i]=rotl(t,16);-it_tab[3][i]=rotl(t,24);-}-}--#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)--#define imix_col(y,x) \-u=star_x(x);\-v=star_x(u);\-w=star_x(v);\-t=w^(x);\-(y)=u^v^w;\-(y)^=rotr(u^t,8)^\-rotr(v^t,16)^\-rotr(t,24)--/* initialise the key schedule from the user supplied key */--#define loop4(i) \-{t=rotr(t,8);t=ls_box(t)^rco_tab[i];\-t^=E_KEY[4*i];E_KEY[4*i+4]=t;\-t^=E_KEY[4*i+1];E_KEY[4*i+5]=t;\-t^=E_KEY[4*i+2];E_KEY[4*i+6]=t;\-t^=E_KEY[4*i+3];E_KEY[4*i+7]=t;\-}--#define loop6(i) \-{t=rotr(t,8);t=ls_box(t)^rco_tab[i];\-t^=E_KEY[6*i];E_KEY[6*i+6]=t;\-t^=E_KEY[6*i+1];E_KEY[6*i+7]=t;\-t^=E_KEY[6*i+2];E_KEY[6*i+8]=t;\-t^=E_KEY[6*i+3];E_KEY[6*i+9]=t;\-t^=E_KEY[6*i+4];E_KEY[6*i+10]=t;\-t^=E_KEY[6*i+5];E_KEY[6*i+11]=t;\-}--#define loop8(i) \-{t=rotr(t,8);;t=ls_box(t)^rco_tab[i];\-t^=E_KEY[8*i];E_KEY[8*i+8]=t;\-t^=E_KEY[8*i+1];E_KEY[8*i+9]=t;\-t^=E_KEY[8*i+2];E_KEY[8*i+10]=t;\-t^=E_KEY[8*i+3];E_KEY[8*i+11]=t;\-t=E_KEY[8*i+4]^ls_box(t);\-E_KEY[8*i+12]=t;\-t^=E_KEY[8*i+5];E_KEY[8*i+13]=t;\-t^=E_KEY[8*i+6];E_KEY[8*i+14]=t;\-t^=E_KEY[8*i+7];E_KEY[8*i+15]=t;\-}-/* Tells whether the ACE is capable to generatetheextendedkeyforagivenkey_len.*/staticinlineint
@@ -339,10 +101,10 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,*/ctx->D=ctx->E;-E_KEY[0]=le32_to_cpu(key[0]);-E_KEY[1]=le32_to_cpu(key[1]);-E_KEY[2]=le32_to_cpu(key[2]);-E_KEY[3]=le32_to_cpu(key[3]);+ctx->E[0]=le32_to_cpu(key[0]);+ctx->E[1]=le32_to_cpu(key[1]);+ctx->E[2]=le32_to_cpu(key[2]);+ctx->E[3]=le32_to_cpu(key[3]);/* Prepare control words. */memset(&ctx->cword,0,sizeof(ctx->cword));
@@ -361,56 +123,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,ctx->cword.encrypt.keygen=1;ctx->cword.decrypt.keygen=1;-switch(key_len){-case16:-t=E_KEY[3];-for(i=0;i<10;++i)-loop4(i);-break;--case24:-E_KEY[4]=le32_to_cpu(key[4]);-t=E_KEY[5]=le32_to_cpu(key[5]);-for(i=0;i<8;++i)-loop6(i);-break;--case32:-E_KEY[4]=le32_to_cpu(key[4]);-E_KEY[5]=le32_to_cpu(key[5]);-E_KEY[6]=le32_to_cpu(key[6]);-t=E_KEY[7]=le32_to_cpu(key[7]);-for(i=0;i<7;++i)-loop8(i);-break;-}--D_KEY[0]=E_KEY[0];-D_KEY[1]=E_KEY[1];-D_KEY[2]=E_KEY[2];-D_KEY[3]=E_KEY[3];--for(i=4;i<key_len+24;++i){-imix_col(D_KEY[i],E_KEY[i]);-}--/* PadLock needs a different format of the decryption key. */-rounds=10+(key_len-16)/4;--for(i=0;i<rounds;i++){-P[((i+1)*4)+0]=D_KEY[((rounds-i-1)*4)+0];-P[((i+1)*4)+1]=D_KEY[((rounds-i-1)*4)+1];-P[((i+1)*4)+2]=D_KEY[((rounds-i-1)*4)+2];-P[((i+1)*4)+3]=D_KEY[((rounds-i-1)*4)+3];+if(crypto_aes_expand_key(&gen_aes,in_key,key_len)){+*flags|=CRYPTO_TFM_RES_BAD_KEY_LEN;+return-EINVAL;}-P[0]=E_KEY[(rounds*4)+0];-P[1]=E_KEY[(rounds*4)+1];-P[2]=E_KEY[(rounds*4)+2];-P[3]=E_KEY[(rounds*4)+3];--memcpy(D_KEY,P,AES_EXTENDED_KEY_SIZE_B);-+memcpy(ctx->E,gen_aes.key_enc,AES_MAX_KEYLENGTH);+memcpy(ctx->D,gen_aes.key_dec,AES_MAX_KEYLENGTH);return0;}
@@ -677,7 +396,6 @@ static int __init padlock_init(void)return-ENODEV;}-gen_tabs();if((ret=crypto_register_alg(&aes_alg)))gotoaes_err;
From: Stefan Hellermann <hidden> Date: 2008-02-24 12:14:57
Hello,
I'm got my Via Epia SN Board a few days ago and could test everything related to the
padlock engine, I'm especially interested in the aes-{lrw,xts} combo, this doesn't work at
the moment (last tested with 2.6.25-rc1).
Cheers,
Stefan
Sebastian Siewior schrieb:
From Sebastian Siewior [off-list ref] # This line is ignored.
Subject: [RFC] padlock aes, unification of setkey()
Hello Herbert,
I sit on those two since November. Back then Michal dropped me an email
and told me that he will test it and get back to me. This didn't happen
so far.
The binary format of the key was the same, the last time I checked, so
the second patch could really work :)
One thing I'm concerned about is the stack utilization. The initial
version had a structure with 256 bytes on the stack. Mine has a bigger
structure with 484 bytes. I'm not sure if it is better to dynamically
allocate it, move it to the private key structure or pad the generic
aes structure in order to enforce the required alignment.
Sebastian
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Sebastian Siewior <hidden> Date: 2008-02-24 12:51:19
* Stefan Hellermann | 2008-02-24 12:54:20 [+0100]:
Hello,
Hello,
I'm got my Via Epia SN Board a few days ago and could test everything related to the
padlock engine, I'm especially interested in the aes-{lrw,xts} combo, this doesn't work at
Cool,
the moment (last tested with 2.6.25-rc1).
Could you be a little more specific on "it doesn't work"?
Do you pass the tcrypt test at least?
Does it* work without the HW acceleration?
Cheers,
Stefan
*: it means a dm-crypt encrypted partition I guess.
Sebastian
* Stefan Hellermann | 2008-02-24 12:54:20 [+0100]:
quoted
Hello,
Hello,
quoted
I'm got my Via Epia SN Board a few days ago and could test everything related to the
padlock engine, I'm especially interested in the aes-{lrw,xts} combo, this doesn't work at
Cool,
quoted
the moment (last tested with 2.6.25-rc1).
Could you be a little more specific on "it doesn't work"?
Do you pass the tcrypt test at least?
Does it* work without the HW acceleration?
quoted
Cheers,
Stefan
*: it means a dm-crypt encrypted partition I guess.
Sebastian
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
This is exactly the xcrypt instruction. I can reproduce what I thing is
the same bug on my geode board. For some reason the stack gets
overwritten. I will dig later a little more.
Sebastian
From: Sebastian Siewior <hidden> Date: 2008-03-02 11:20:07
The XTS blockmode uses a copy of the IV which is saved on the stack
and may or may not be properly aligned. If it is not, it will break
hardware cipher like the geode or padlock.
This patch moves the copy of IV to the private structre which has the
same aligment as the underlying cipher.
Signed-off-by: Sebastian Siewior <redacted>
---
Stefan, please try the following patch, it should fix your xts problem.
crypto/xts.c | 32 +++++++++++++++++---------------
1 files changed, 17 insertions(+), 15 deletions(-)
@@ -24,7 +24,17 @@#include<crypto/b128ops.h>#include<crypto/gf128mul.h>+structsinfo{+be128t;+structcrypto_tfm*tfm;+void(*fn)(structcrypto_tfm*,u8*,constu8*);+};+structpriv{+/* s.t being the first member in this struct enforces proper alignment+*requiredbytheunderlyingcipherwithoutexplicitknowingtheit.+*/+structsinfos;structcrypto_cipher*child;structcrypto_cipher*tweak;};
@@ -76,12 +86,6 @@ static int setkey(struct crypto_tfm *parent, const u8 *key,return0;}-structsinfo{-be128t;-structcrypto_tfm*tfm;-void(*fn)(structcrypto_tfm*,u8*,constu8*);-};-staticinlinevoidxts_round(structsinfo*s,void*dst,constvoid*src){be128_xor(dst,&s->t,src);/* PP <- T xor P */
@@ -97,13 +101,12 @@ static int crypt(struct blkcipher_desc *d,interr;unsignedintavail;constintbs=crypto_cipher_blocksize(ctx->child);-structsinfos={-.tfm=crypto_cipher_tfm(ctx->child),-.fn=fn-};-be128*iv;u8*wsrc;u8*wdst;+structsinfo*s=&ctx->s;++s->tfm=crypto_cipher_tfm(ctx->child);+s->fn=fn;err=blkcipher_walk_virt(d,w);if(!w->nbytes)
@@ -115,17 +118,16 @@ static int crypt(struct blkcipher_desc *d,wdst=w->dst.virt.addr;/* calculate first value of T */-iv=(be128*)w->iv;-tw(crypto_cipher_tfm(ctx->tweak),(void*)&s.t,w->iv);+tw(crypto_cipher_tfm(ctx->tweak),(void*)&s->t,w->iv);gotofirst;for(;;){do{-gf128mul_x_ble(&s.t,&s.t);+gf128mul_x_ble(&s->t,&s->t);first:-xts_round(&s,wdst,wsrc);+xts_round(s,wdst,wsrc);wsrc+=bs;wdst+=bs;
From: Stefan Hellermann <hidden> Date: 2008-03-02 12:04:53
Sebastian Siewior schrieb:
The XTS blockmode uses a copy of the IV which is saved on the stack
and may or may not be properly aligned. If it is not, it will break
hardware cipher like the geode or padlock.
This patch moves the copy of IV to the private structre which has the
same aligment as the underlying cipher.
Signed-off-by: Sebastian Siewior <redacted>
It works now! Thanks!
But I get much lower speed than with aes-cbc-essiv:sha256.
With xts I get 57MB/s while reading the cryptodev with dd, and >90% sys in top, 0% wait
With cbc-essiv I get about 75MB/s while reading it with dd, 60% sys int top, 30% wait
without cryptodev I get 75MB/s while reading the raw lvm-volume with dd, 40% sys, 50% wait
I do a blockdev --flushbufs beetween each read.
Tested-by: Stefan Hellermann <redacted>
quoted hunk
---
Stefan, please try the following patch, it should fix your xts problem.
crypto/xts.c | 32 +++++++++++++++++---------------
1 files changed, 17 insertions(+), 15 deletions(-)
@@ -24,7 +24,17 @@#include<crypto/b128ops.h>#include<crypto/gf128mul.h>+structsinfo{+be128t;+structcrypto_tfm*tfm;+void(*fn)(structcrypto_tfm*,u8*,constu8*);+};+structpriv{+/* s.t being the first member in this struct enforces proper alignment+*requiredbytheunderlyingcipherwithoutexplicitknowingtheit.+*/+structsinfos;structcrypto_cipher*child;structcrypto_cipher*tweak;};
@@ -76,12 +86,6 @@ static int setkey(struct crypto_tfm *parent, const u8 *key,return0;}-structsinfo{-be128t;-structcrypto_tfm*tfm;-void(*fn)(structcrypto_tfm*,u8*,constu8*);-};-staticinlinevoidxts_round(structsinfo*s,void*dst,constvoid*src){be128_xor(dst,&s->t,src);/* PP <- T xor P */
@@ -97,13 +101,12 @@ static int crypt(struct blkcipher_desc *d,interr;unsignedintavail;constintbs=crypto_cipher_blocksize(ctx->child);-structsinfos={-.tfm=crypto_cipher_tfm(ctx->child),-.fn=fn-};-be128*iv;u8*wsrc;u8*wdst;+structsinfo*s=&ctx->s;++s->tfm=crypto_cipher_tfm(ctx->child);+s->fn=fn;err=blkcipher_walk_virt(d,w);if(!w->nbytes)
@@ -115,17 +118,16 @@ static int crypt(struct blkcipher_desc *d,wdst=w->dst.virt.addr;/* calculate first value of T */-iv=(be128*)w->iv;-tw(crypto_cipher_tfm(ctx->tweak),(void*)&s.t,w->iv);+tw(crypto_cipher_tfm(ctx->tweak),(void*)&s->t,w->iv);gotofirst;for(;;){do{-gf128mul_x_ble(&s.t,&s.t);+gf128mul_x_ble(&s->t,&s->t);first:-xts_round(&s,wdst,wsrc);+xts_round(s,wdst,wsrc);wsrc+=bs;wdst+=bs;
From: Sebastian Siewior <hidden> Date: 2008-03-02 13:22:04
* Stefan Hellermann | 2008-03-02 13:04:37 [+0100]:
But I get much lower speed than with aes-cbc-essiv:sha256.
Yes, I expected this :)
The aes-cbc operation is supported directly in HW. So the
driver just says here is the key, source, destination, length and now do
it. So the HW fetches the key once and is going to process the whole
request (lets say 4 KiB) in one go.
The XTS blockmode on the other hand encrypts encrypts only 16 bytes in
one go and performs some GF operations in between. This is
repeated until we encrypt the whole request. So for a 4 KiB we need here
257 calls to the HW instead of one (the one extra is to encrypt the IV).
For every encryption call we have to reset the HW key. According to the
spec fetching the key from memory takes more time than the whole
encryption process as it (in case of a 16 byte block). This might still
be faster than the pure software solution.
Anyway, XTS is way more complex than CBC and part of it is done in
software what we can't change.
With xts I get 57MB/s while reading the cryptodev with dd, and >90% sys in top, 0% wait
With cbc-essiv I get about 75MB/s while reading it with dd, 60% sys int top, 30% wait
without cryptodev I get 75MB/s while reading the raw lvm-volume with dd, 40% sys, 50% wait
I do a blockdev --flushbufs beetween each read.
According to this numbers I would say in CBC mode the HD is breaking in
XTS the CPU is.
I could try to tune it a little but don't expect much.
Could you please compare xts with and without padlock?
Sebastian
From: Stefan Hellermann <hidden> Date: 2008-03-02 13:50:14
Sebastian Siewior schrieb:
* Stefan Hellermann | 2008-03-02 13:04:37 [+0100]:
quoted
But I get much lower speed than with aes-cbc-essiv:sha256.
Yes, I expected this :)
The aes-cbc operation is supported directly in HW. So the
driver just says here is the key, source, destination, length and now do
it. So the HW fetches the key once and is going to process the whole
request (lets say 4 KiB) in one go.
The XTS blockmode on the other hand encrypts encrypts only 16 bytes in
one go and performs some GF operations in between. This is
repeated until we encrypt the whole request. So for a 4 KiB we need here
257 calls to the HW instead of one (the one extra is to encrypt the IV).
For every encryption call we have to reset the HW key. According to the
spec fetching the key from memory takes more time than the whole
encryption process as it (in case of a 16 byte block). This might still
be faster than the pure software solution.
Anyway, XTS is way more complex than CBC and part of it is done in
software what we can't change.
Ah, good to know! Could this information be placed in the Kconfig-help for padlock_aes?
quoted
With xts I get 57MB/s while reading the cryptodev with dd, and >90% sys in top, 0% wait
With cbc-essiv I get about 75MB/s while reading it with dd, 60% sys int top, 30% wait
without cryptodev I get 75MB/s while reading the raw lvm-volume with dd, 40% sys, 50% wait
I do a blockdev --flushbufs beetween each read.
According to this numbers I would say in CBC mode the HD is breaking in
XTS the CPU is.
I could try to tune it a little but don't expect much.
Could you please compare xts with and without padlock?
Yes, xts with padlock is almost 3 times faster.
20-21MB/s read in dd without padlock_aes, >90% CPU sys, 0% wait
57-58MB/s read in dd with padlock_aes, >90% CPU sys, 0% wait
I tried lrw-benbi/lrw-plain this time, but it doesn't work, with or without padlock_aes.
dmesg logs:
device-mapper: table: 252:6: crypt: Error allocating crypto tfm
device-mapper: ioctl: error adding target to table
device-mapper: ioctl: device doesn't appear to be in the dev hash table
... but I will use cbc-essiv, if I ever need better encryption I can take xts-plain. (no
need for lrw-benbi)
Thanks
Stefan
From: Stefan Hellermann <hidden> Date: 2008-03-02 14:04:43
I tried lrw-benbi/lrw-plain this time, but it doesn't work, with or without padlock_aes.
dmesg logs:
device-mapper: table: 252:6: crypt: Error allocating crypto tfm
device-mapper: ioctl: error adding target to table
device-mapper: ioctl: device doesn't appear to be in the dev hash table
forget this ... with CONFIG_CRYPTO_LRW unset it can't work. But with your new patch it
works even with padlock_aes.
Thanks
Stefan
From: Stefan Hellermann <hidden> Date: 2008-03-13 21:41:49
Sebastian Siewior schrieb:
Padlock AES' setkey routine is the same as exported by the generic
implementation. So we could use it.
I tested this and "[RFC] generic_aes: export generic setkey" on a padlock-enabled Via
board, and did the following test:
Create, open, write to, read from and close a linux dm-crypt device with aes-cbc-essiv,
aes-lrw-benbi and aes-xts-plain.
Then I took a huge encrypted disk-image (encrypted without this patches), opened it with
cryptsetup-luks, booted the OS from the disc over iscsi, started a filesystem-check. The
check completed successful.
So I think this and the other patch are save.
Tested-by: Stefan Hellermann <redacted>
quoted hunk
Cc: Michal Ludvig <redacted>
Signed-off-by: Sebastian Siewior <redacted>
---
drivers/crypto/Kconfig | 1 +
drivers/crypto/padlock-aes.c | 320 +++---------------------------------------
2 files changed, 20 insertions(+), 301 deletions(-)
@@ -54,9 +18,6 @@#include<asm/byteorder.h>#include"padlock.h"-#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */-#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))-/* Control word. */structcword{unsignedint__attribute__((__packed__))
@@ -70,218 +31,23 @@ struct cword {/* Whenever making any changes to the following*structure*makesure*youkeepE,d_data-*andcwordalignedon16Bytesboundaries!!!*/+*andcwordalignedon16Bytesboundariesand+*theHardwarecanaccess16*16bytesofEandd_data+*(onlythefirst15*16bytesmatterbuttheHWreads+*more).+*/structaes_ctx{+u32E[AES_MAX_KEYLENGTH_U32]+__attribute__((__aligned__(PADLOCK_ALIGNMENT)));+u32d_data[AES_MAX_KEYLENGTH_U32]+__attribute__((__aligned__(PADLOCK_ALIGNMENT)));struct{structcwordencrypt;structcworddecrypt;}cword;u32*D;-intkey_length;-u32E[AES_EXTENDED_KEY_SIZE]-__attribute__((__aligned__(PADLOCK_ALIGNMENT)));-u32d_data[AES_EXTENDED_KEY_SIZE]-__attribute__((__aligned__(PADLOCK_ALIGNMENT)));};-/* ====== Key management routines ====== */--staticinlineuint32_t-generic_rotr32(constuint32_tx,constunsignedbits)-{-constunsignedn=bits%32;-return(x>>n)|(x<<(32-n));-}--staticinlineuint32_t-generic_rotl32(constuint32_tx,constunsignedbits)-{-constunsignedn=bits%32;-return(x<<n)|(x>>(32-n));-}--#define rotl generic_rotl32-#define rotr generic_rotr32--/*-*#definebyte(x,nr)((unsignedchar)((x)>>(nr*8)))-*/-staticinlineuint8_t-byte(constuint32_tx,constunsignedn)-{-returnx>>(n<<3);-}--#define E_KEY ctx->E-#define D_KEY ctx->D--staticuint8_tpow_tab[256];-staticuint8_tlog_tab[256];-staticuint8_tsbx_tab[256];-staticuint8_tisb_tab[256];-staticuint32_trco_tab[10];-staticuint32_tft_tab[4][256];-staticuint32_tit_tab[4][256];--staticuint32_tfl_tab[4][256];-staticuint32_til_tab[4][256];--staticinlineuint8_t-f_mult(uint8_ta,uint8_tb)-{-uint8_taa=log_tab[a],cc=aa+log_tab[b];--returnpow_tab[cc+(cc<aa?1:0)];-}--#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0)--#define f_rn(bo, bi, n, k) \-bo[n]=ft_tab[0][byte(bi[n],0)]^\-ft_tab[1][byte(bi[(n+1)&3],1)]^\-ft_tab[2][byte(bi[(n+2)&3],2)]^\-ft_tab[3][byte(bi[(n+3)&3],3)]^*(k+n)--#define i_rn(bo, bi, n, k) \-bo[n]=it_tab[0][byte(bi[n],0)]^\-it_tab[1][byte(bi[(n+3)&3],1)]^\-it_tab[2][byte(bi[(n+2)&3],2)]^\-it_tab[3][byte(bi[(n+1)&3],3)]^*(k+n)--#define ls_box(x) \-(fl_tab[0][byte(x,0)]^\-fl_tab[1][byte(x,1)]^\-fl_tab[2][byte(x,2)]^\-fl_tab[3][byte(x,3)])--#define f_rl(bo, bi, n, k) \-bo[n]=fl_tab[0][byte(bi[n],0)]^\-fl_tab[1][byte(bi[(n+1)&3],1)]^\-fl_tab[2][byte(bi[(n+2)&3],2)]^\-fl_tab[3][byte(bi[(n+3)&3],3)]^*(k+n)--#define i_rl(bo, bi, n, k) \-bo[n]=il_tab[0][byte(bi[n],0)]^\-il_tab[1][byte(bi[(n+3)&3],1)]^\-il_tab[2][byte(bi[(n+2)&3],2)]^\-il_tab[3][byte(bi[(n+1)&3],3)]^*(k+n)--staticvoid-gen_tabs(void)-{-uint32_ti,t;-uint8_tp,q;--/* log and power tables for GF(2**8) finite field with-0x011basmodularpolynomial-thesimplestprmitive-rootis0x03,usedheretogeneratethetables*/--for(i=0,p=1;i<256;++i){-pow_tab[i]=(uint8_t)p;-log_tab[p]=(uint8_t)i;--p^=(p<<1)^(p&0x80?0x01b:0);-}--log_tab[1]=0;--for(i=0,p=1;i<10;++i){-rco_tab[i]=p;--p=(p<<1)^(p&0x80?0x01b:0);-}--for(i=0;i<256;++i){-p=(i?pow_tab[255-log_tab[i]]:0);-q=((p>>7)|(p<<1))^((p>>6)|(p<<2));-p^=0x63^q^((q>>6)|(q<<2));-sbx_tab[i]=p;-isb_tab[p]=(uint8_t)i;-}--for(i=0;i<256;++i){-p=sbx_tab[i];--t=p;-fl_tab[0][i]=t;-fl_tab[1][i]=rotl(t,8);-fl_tab[2][i]=rotl(t,16);-fl_tab[3][i]=rotl(t,24);--t=((uint32_t)ff_mult(2,p))|-((uint32_t)p<<8)|-((uint32_t)p<<16)|((uint32_t)ff_mult(3,p)<<24);--ft_tab[0][i]=t;-ft_tab[1][i]=rotl(t,8);-ft_tab[2][i]=rotl(t,16);-ft_tab[3][i]=rotl(t,24);--p=isb_tab[i];--t=p;-il_tab[0][i]=t;-il_tab[1][i]=rotl(t,8);-il_tab[2][i]=rotl(t,16);-il_tab[3][i]=rotl(t,24);--t=((uint32_t)ff_mult(14,p))|-((uint32_t)ff_mult(9,p)<<8)|-((uint32_t)ff_mult(13,p)<<16)|-((uint32_t)ff_mult(11,p)<<24);--it_tab[0][i]=t;-it_tab[1][i]=rotl(t,8);-it_tab[2][i]=rotl(t,16);-it_tab[3][i]=rotl(t,24);-}-}--#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)--#define imix_col(y,x) \-u=star_x(x);\-v=star_x(u);\-w=star_x(v);\-t=w^(x);\-(y)=u^v^w;\-(y)^=rotr(u^t,8)^\-rotr(v^t,16)^\-rotr(t,24)--/* initialise the key schedule from the user supplied key */--#define loop4(i) \-{t=rotr(t,8);t=ls_box(t)^rco_tab[i];\-t^=E_KEY[4*i];E_KEY[4*i+4]=t;\-t^=E_KEY[4*i+1];E_KEY[4*i+5]=t;\-t^=E_KEY[4*i+2];E_KEY[4*i+6]=t;\-t^=E_KEY[4*i+3];E_KEY[4*i+7]=t;\-}--#define loop6(i) \-{t=rotr(t,8);t=ls_box(t)^rco_tab[i];\-t^=E_KEY[6*i];E_KEY[6*i+6]=t;\-t^=E_KEY[6*i+1];E_KEY[6*i+7]=t;\-t^=E_KEY[6*i+2];E_KEY[6*i+8]=t;\-t^=E_KEY[6*i+3];E_KEY[6*i+9]=t;\-t^=E_KEY[6*i+4];E_KEY[6*i+10]=t;\-t^=E_KEY[6*i+5];E_KEY[6*i+11]=t;\-}--#define loop8(i) \-{t=rotr(t,8);;t=ls_box(t)^rco_tab[i];\-t^=E_KEY[8*i];E_KEY[8*i+8]=t;\-t^=E_KEY[8*i+1];E_KEY[8*i+9]=t;\-t^=E_KEY[8*i+2];E_KEY[8*i+10]=t;\-t^=E_KEY[8*i+3];E_KEY[8*i+11]=t;\-t=E_KEY[8*i+4]^ls_box(t);\-E_KEY[8*i+12]=t;\-t^=E_KEY[8*i+5];E_KEY[8*i+13]=t;\-t^=E_KEY[8*i+6];E_KEY[8*i+14]=t;\-t^=E_KEY[8*i+7];E_KEY[8*i+15]=t;\-}-/* Tells whether the ACE is capable to generatetheextendedkeyforagivenkey_len.*/staticinlineint
@@ -339,10 +101,10 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,*/ctx->D=ctx->E;-E_KEY[0]=le32_to_cpu(key[0]);-E_KEY[1]=le32_to_cpu(key[1]);-E_KEY[2]=le32_to_cpu(key[2]);-E_KEY[3]=le32_to_cpu(key[3]);+ctx->E[0]=le32_to_cpu(key[0]);+ctx->E[1]=le32_to_cpu(key[1]);+ctx->E[2]=le32_to_cpu(key[2]);+ctx->E[3]=le32_to_cpu(key[3]);/* Prepare control words. */memset(&ctx->cword,0,sizeof(ctx->cword));
@@ -361,56 +123,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,ctx->cword.encrypt.keygen=1;ctx->cword.decrypt.keygen=1;-switch(key_len){-case16:-t=E_KEY[3];-for(i=0;i<10;++i)-loop4(i);-break;--case24:-E_KEY[4]=le32_to_cpu(key[4]);-t=E_KEY[5]=le32_to_cpu(key[5]);-for(i=0;i<8;++i)-loop6(i);-break;--case32:-E_KEY[4]=le32_to_cpu(key[4]);-E_KEY[5]=le32_to_cpu(key[5]);-E_KEY[6]=le32_to_cpu(key[6]);-t=E_KEY[7]=le32_to_cpu(key[7]);-for(i=0;i<7;++i)-loop8(i);-break;-}--D_KEY[0]=E_KEY[0];-D_KEY[1]=E_KEY[1];-D_KEY[2]=E_KEY[2];-D_KEY[3]=E_KEY[3];--for(i=4;i<key_len+24;++i){-imix_col(D_KEY[i],E_KEY[i]);-}--/* PadLock needs a different format of the decryption key. */-rounds=10+(key_len-16)/4;--for(i=0;i<rounds;i++){-P[((i+1)*4)+0]=D_KEY[((rounds-i-1)*4)+0];-P[((i+1)*4)+1]=D_KEY[((rounds-i-1)*4)+1];-P[((i+1)*4)+2]=D_KEY[((rounds-i-1)*4)+2];-P[((i+1)*4)+3]=D_KEY[((rounds-i-1)*4)+3];+if(crypto_aes_expand_key(&gen_aes,in_key,key_len)){+*flags|=CRYPTO_TFM_RES_BAD_KEY_LEN;+return-EINVAL;}-P[0]=E_KEY[(rounds*4)+0];-P[1]=E_KEY[(rounds*4)+1];-P[2]=E_KEY[(rounds*4)+2];-P[3]=E_KEY[(rounds*4)+3];--memcpy(D_KEY,P,AES_EXTENDED_KEY_SIZE_B);-+memcpy(ctx->E,gen_aes.key_enc,AES_MAX_KEYLENGTH);+memcpy(ctx->D,gen_aes.key_dec,AES_MAX_KEYLENGTH);return0;}
@@ -677,7 +396,6 @@ static int __init padlock_init(void)return-ENODEV;}-gen_tabs();if((ret=crypto_register_alg(&aes_alg)))gotoaes_err;
From: Stefan Hellermann <hidden> Date: 2008-03-13 21:41:49
Sebastian Siewior schrieb:
The key expansion routine could be get little more generic, become
a kernel doc entry and then get exported.
I tested this and "[RFC] [crypto] padlock-AES, use generic setkey function" on a
padlock-enabled Via board, and did the following test:
Create, open, write to, read from and close a linux dm-crypt device with aes-cbc-essiv,
aes-lrw-benbi and aes-xts-plain.
Then I took a huge encrypted disk-image (encrypted without this patches), opened it with
cryptsetup-luks, booted the OS from the disc over iscsi, started a filesystem-check. The
check completed successful.
So I think this and the other patch are save.
@@ -284,6 +295,33 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,}return0;}+EXPORT_SYMBOL_GPL(crypto_aes_expand_key);++/**+*crypto_aes_set_key-SettheAESkey.+*@tfm:The%crypto_tfmthatisusedinthecontext.+*@in_key:Theinputkey.+*@key_len:Thesizeofthekey.+*+*Returns0onsuccess,onfailurethe%CRYPTO_TFM_RES_BAD_KEY_LENflagintfm+*isset.Thefunctionusescrypto_aes_expand_key()toexpandthekey.+*&crypto_aes_ctx_must_betheprivatedataembeddedin@tfmwhichis+*retrievedwithcrypto_tfm_ctx().+*/+intcrypto_aes_set_key(structcrypto_tfm*tfm,constu8*in_key,+unsignedintkey_len)+{+structcrypto_aes_ctx*ctx=crypto_tfm_ctx(tfm);+u32*flags=&tfm->crt_flags;+intret;++ret=crypto_aes_expand_key(ctx,in_key,key_len);+if(!ret)+return0;++*flags|=CRYPTO_TFM_RES_BAD_KEY_LEN;+return-EINVAL;+}EXPORT_SYMBOL_GPL(crypto_aes_set_key);/* encrypt a block of text */
From: Sebastian Siewior <hidden> Date: 2008-03-14 11:44:12
* Stefan Hellermann | 2008-03-13 22:40:50 [+0100]:
Sebastian Siewior schrieb:
quoted
Padlock AES' setkey routine is the same as exported by the generic
implementation. So we could use it.
I tested this and "[RFC] generic_aes: export generic setkey" on a padlock-enabled Via
board, and did the following test:
Create, open, write to, read from and close a linux dm-crypt device with aes-cbc-essiv,
aes-lrw-benbi and aes-xts-plain.
Then I took a huge encrypted disk-image (encrypted without this patches), opened it with
cryptsetup-luks, booted the OS from the disc over iscsi, started a filesystem-check. The
check completed successful.
Looks like an interresting setup :)
So I think this and the other patch are save.
That patch uses different (but I hope the same) algorithm for key
generation which is only used for keys >128 bit. If your dm-crypt setup
used 192 or 256 bit keys than the test should be valid.
In the other case (or just to be sure) please run
|modprobe tcrypt mode=10
which just does work.
Sebastian
From: Stefan Hellermann <hidden> Date: 2008-03-14 12:49:57
Sebastian Siewior schrieb:
* Stefan Hellermann | 2008-03-13 22:40:50 [+0100]:
quoted
Sebastian Siewior schrieb:
quoted
Padlock AES' setkey routine is the same as exported by the generic
implementation. So we could use it.
I tested this and "[RFC] generic_aes: export generic setkey" on a padlock-enabled Via
board, and did the following test:
Create, open, write to, read from and close a linux dm-crypt device with aes-cbc-essiv,
aes-lrw-benbi and aes-xts-plain.
Then I took a huge encrypted disk-image (encrypted without this patches), opened it with
cryptsetup-luks, booted the OS from the disc over iscsi, started a filesystem-check. The
check completed successful.
Looks like an interresting setup :)
quoted
So I think this and the other patch are save.
That patch uses different (but I hope the same) algorithm for key
generation which is only used for keys >128 bit. If your dm-crypt setup
used 192 or 256 bit keys than the test should be valid.
In the other case (or just to be sure) please run
|modprobe tcrypt mode=10
which just does work.
I used cryptsetup with -s 256, so the cbc and lrw tests should be valid.
The tcrypt test succeeds, there's no difference in the dmesg-output with or without
padlock-aes loaded. I haven't checked the results with an unpatched kernel yet.
From: Sebastian Siewior <hidden> Date: 2008-03-14 14:16:47
* Stefan Hellermann | 2008-03-14 13:49:07 [+0100]:
Sebastian Siewior schrieb:
I used cryptsetup with -s 256, so the cbc and lrw tests should be valid.
The tcrypt test succeeds, there's no difference in the dmesg-output with or without
padlock-aes loaded. I haven't checked the results with an unpatched kernel yet.
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2008-04-01 13:25:55
On Thu, Mar 13, 2008 at 10:40:50PM +0100, Stefan Hellermann wrote:
Sebastian Siewior schrieb:
quoted
Padlock AES' setkey routine is the same as exported by the generic
implementation. So we could use it.
I tested this and "[RFC] generic_aes: export generic setkey" on a padlock-enabled Via
board, and did the following test:
Create, open, write to, read from and close a linux dm-crypt device with aes-cbc-essiv,
aes-lrw-benbi and aes-xts-plain.
Then I took a huge encrypted disk-image (encrypted without this patches), opened it with
cryptsetup-luks, booted the OS from the disc over iscsi, started a filesystem-check. The
check completed successful.
So I think this and the other patch are save.
Tested-by: Stefan Hellermann <redacted>