2008-07-31 13:08:25 +04:00
/*
* Algorithm testing framework and tests .
*
* Copyright ( c ) 2002 James Morris < jmorris @ intercode . com . au >
* Copyright ( c ) 2002 Jean - Francois Dive < jef @ linuxbe . org >
* Copyright ( c ) 2007 Nokia Siemens Networks
* Copyright ( c ) 2008 Herbert Xu < herbert @ gondor . apana . org . au >
*
2010-11-04 22:02:04 +03:00
* Updated RFC4106 AES - GCM testing .
* Authors : Aidan O ' Mahony ( aidan . o . mahony @ intel . com )
* Adrian Hoban < adrian . hoban @ intel . com >
* Gabriele Paoloni < gabriele . paoloni @ intel . com >
* Tadeusz Struk ( tadeusz . struk @ intel . com )
* Copyright ( c ) 2010 , Intel Corporation .
*
2008-07-31 13:08:25 +04:00
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation ; either version 2 of the License , or ( at your option )
* any later version .
*
*/
# include <crypto/hash.h>
# include <linux/err.h>
# include <linux/module.h>
# include <linux/scatterlist.h>
# include <linux/slab.h>
# include <linux/string.h>
2009-05-04 15:44:50 +04:00
# include <crypto/rng.h>
2008-07-31 13:08:25 +04:00
# include "internal.h"
2010-06-03 14:53:43 +04:00
2010-08-06 05:40:28 +04:00
# ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
2010-06-03 14:53:43 +04:00
/* a perfect nop */
int alg_test ( const char * driver , const char * alg , u32 type , u32 mask )
{
return 0 ;
}
# else
2008-07-31 13:08:25 +04:00
# include "testmgr.h"
/*
* Need slab memory for testing ( size in number of pages ) .
*/
# define XBUFSIZE 8
/*
* Indexes into the xbuf to simulate cross - page access .
*/
# define IDX1 32
# define IDX2 32400
# define IDX3 1
# define IDX4 8193
# define IDX5 22222
# define IDX6 17101
# define IDX7 27333
# define IDX8 3000
/*
* Used by test_cipher ( )
*/
# define ENCRYPT 1
# define DECRYPT 0
struct tcrypt_result {
struct completion completion ;
int err ;
} ;
struct aead_test_suite {
struct {
struct aead_testvec * vecs ;
unsigned int count ;
} enc , dec ;
} ;
struct cipher_test_suite {
struct {
struct cipher_testvec * vecs ;
unsigned int count ;
} enc , dec ;
} ;
struct comp_test_suite {
struct {
struct comp_testvec * vecs ;
unsigned int count ;
} comp , decomp ;
} ;
2009-03-04 10:08:03 +03:00
struct pcomp_test_suite {
struct {
struct pcomp_testvec * vecs ;
unsigned int count ;
} comp , decomp ;
} ;
2008-07-31 13:08:25 +04:00
struct hash_test_suite {
struct hash_testvec * vecs ;
unsigned int count ;
} ;
2009-05-04 15:44:50 +04:00
struct cprng_test_suite {
struct cprng_testvec * vecs ;
unsigned int count ;
} ;
2008-07-31 13:08:25 +04:00
struct alg_test_desc {
const char * alg ;
int ( * test ) ( const struct alg_test_desc * desc , const char * driver ,
u32 type , u32 mask ) ;
2009-05-15 09:16:03 +04:00
int fips_allowed ; /* set if alg is allowed in fips mode */
2008-07-31 13:08:25 +04:00
union {
struct aead_test_suite aead ;
struct cipher_test_suite cipher ;
struct comp_test_suite comp ;
2009-03-04 10:08:03 +03:00
struct pcomp_test_suite pcomp ;
2008-07-31 13:08:25 +04:00
struct hash_test_suite hash ;
2009-05-04 15:44:50 +04:00
struct cprng_test_suite cprng ;
2008-07-31 13:08:25 +04:00
} suite ;
} ;
static unsigned int IDX [ 8 ] = { IDX1 , IDX2 , IDX3 , IDX4 , IDX5 , IDX6 , IDX7 , IDX8 } ;
static void hexdump ( unsigned char * buf , unsigned int len )
{
print_hex_dump ( KERN_CONT , " " , DUMP_PREFIX_OFFSET ,
16 , 1 ,
buf , len , false ) ;
}
static void tcrypt_complete ( struct crypto_async_request * req , int err )
{
struct tcrypt_result * res = req - > data ;
if ( err = = - EINPROGRESS )
return ;
res - > err = err ;
complete ( & res - > completion ) ;
}
2009-05-06 10:15:47 +04:00
static int testmgr_alloc_buf ( char * buf [ XBUFSIZE ] )
{
int i ;
for ( i = 0 ; i < XBUFSIZE ; i + + ) {
buf [ i ] = ( void * ) __get_free_page ( GFP_KERNEL ) ;
if ( ! buf [ i ] )
goto err_free_buf ;
}
return 0 ;
err_free_buf :
while ( i - - > 0 )
free_page ( ( unsigned long ) buf [ i ] ) ;
return - ENOMEM ;
}
static void testmgr_free_buf ( char * buf [ XBUFSIZE ] )
{
int i ;
for ( i = 0 ; i < XBUFSIZE ; i + + )
free_page ( ( unsigned long ) buf [ i ] ) ;
}
2010-05-19 08:12:03 +04:00
static int do_one_async_hash_op ( struct ahash_request * req ,
struct tcrypt_result * tr ,
int ret )
{
if ( ret = = - EINPROGRESS | | ret = = - EBUSY ) {
ret = wait_for_completion_interruptible ( & tr - > completion ) ;
if ( ! ret )
ret = tr - > err ;
INIT_COMPLETION ( tr - > completion ) ;
}
return ret ;
}
2008-07-31 13:08:25 +04:00
static int test_hash ( struct crypto_ahash * tfm , struct hash_testvec * template ,
2010-05-19 08:12:03 +04:00
unsigned int tcount , bool use_digest )
2008-07-31 13:08:25 +04:00
{
const char * algo = crypto_tfm_alg_driver_name ( crypto_ahash_tfm ( tfm ) ) ;
unsigned int i , j , k , temp ;
struct scatterlist sg [ 8 ] ;
char result [ 64 ] ;
struct ahash_request * req ;
struct tcrypt_result tresult ;
void * hash_buff ;
2009-05-06 10:15:47 +04:00
char * xbuf [ XBUFSIZE ] ;
int ret = - ENOMEM ;
if ( testmgr_alloc_buf ( xbuf ) )
goto out_nobuf ;
2008-07-31 13:08:25 +04:00
init_completion ( & tresult . completion ) ;
req = ahash_request_alloc ( tfm , GFP_KERNEL ) ;
if ( ! req ) {
printk ( KERN_ERR " alg: hash: Failed to allocate request for "
" %s \n " , algo ) ;
goto out_noreq ;
}
ahash_request_set_callback ( req , CRYPTO_TFM_REQ_MAY_BACKLOG ,
tcrypt_complete , & tresult ) ;
2009-05-29 10:23:12 +04:00
j = 0 ;
2008-07-31 13:08:25 +04:00
for ( i = 0 ; i < tcount ; i + + ) {
2009-05-29 10:23:12 +04:00
if ( template [ i ] . np )
continue ;
j + + ;
2008-07-31 13:08:25 +04:00
memset ( result , 0 , 64 ) ;
hash_buff = xbuf [ 0 ] ;
memcpy ( hash_buff , template [ i ] . plaintext , template [ i ] . psize ) ;
sg_init_one ( & sg [ 0 ] , hash_buff , template [ i ] . psize ) ;
if ( template [ i ] . ksize ) {
crypto_ahash_clear_flags ( tfm , ~ 0 ) ;
ret = crypto_ahash_setkey ( tfm , template [ i ] . key ,
template [ i ] . ksize ) ;
if ( ret ) {
printk ( KERN_ERR " alg: hash: setkey failed on "
2009-05-29 10:23:12 +04:00
" test %d for %s: ret=%d \n " , j , algo ,
2008-07-31 13:08:25 +04:00
- ret ) ;
goto out ;
}
}
ahash_request_set_crypt ( req , sg , result , template [ i ] . psize ) ;
2010-05-19 08:12:03 +04:00
if ( use_digest ) {
ret = do_one_async_hash_op ( req , & tresult ,
crypto_ahash_digest ( req ) ) ;
if ( ret ) {
pr_err ( " alg: hash: digest failed on test %d "
" for %s: ret=%d \n " , j , algo , - ret ) ;
goto out ;
}
} else {
ret = do_one_async_hash_op ( req , & tresult ,
crypto_ahash_init ( req ) ) ;
if ( ret ) {
pr_err ( " alt: hash: init failed on test %d "
" for %s: ret=%d \n " , j , algo , - ret ) ;
goto out ;
}
ret = do_one_async_hash_op ( req , & tresult ,
crypto_ahash_update ( req ) ) ;
if ( ret ) {
pr_err ( " alt: hash: update failed on test %d "
" for %s: ret=%d \n " , j , algo , - ret ) ;
goto out ;
}
ret = do_one_async_hash_op ( req , & tresult ,
crypto_ahash_final ( req ) ) ;
if ( ret ) {
pr_err ( " alt: hash: final failed on test %d "
" for %s: ret=%d \n " , j , algo , - ret ) ;
goto out ;
2008-07-31 13:08:25 +04:00
}
}
if ( memcmp ( result , template [ i ] . digest ,
crypto_ahash_digestsize ( tfm ) ) ) {
printk ( KERN_ERR " alg: hash: Test %d failed for %s \n " ,
2009-05-29 10:23:12 +04:00
j , algo ) ;
2008-07-31 13:08:25 +04:00
hexdump ( result , crypto_ahash_digestsize ( tfm ) ) ;
ret = - EINVAL ;
goto out ;
}
}
j = 0 ;
for ( i = 0 ; i < tcount ; i + + ) {
if ( template [ i ] . np ) {
j + + ;
memset ( result , 0 , 64 ) ;
temp = 0 ;
sg_init_table ( sg , template [ i ] . np ) ;
2009-05-29 10:05:42 +04:00
ret = - EINVAL ;
2008-07-31 13:08:25 +04:00
for ( k = 0 ; k < template [ i ] . np ; k + + ) {
2009-05-29 10:05:42 +04:00
if ( WARN_ON ( offset_in_page ( IDX [ k ] ) +
template [ i ] . tap [ k ] > PAGE_SIZE ) )
goto out ;
2008-07-31 13:08:25 +04:00
sg_set_buf ( & sg [ k ] ,
memcpy ( xbuf [ IDX [ k ] > > PAGE_SHIFT ] +
offset_in_page ( IDX [ k ] ) ,
template [ i ] . plaintext + temp ,
template [ i ] . tap [ k ] ) ,
template [ i ] . tap [ k ] ) ;
temp + = template [ i ] . tap [ k ] ;
}
if ( template [ i ] . ksize ) {
crypto_ahash_clear_flags ( tfm , ~ 0 ) ;
ret = crypto_ahash_setkey ( tfm , template [ i ] . key ,
template [ i ] . ksize ) ;
if ( ret ) {
printk ( KERN_ERR " alg: hash: setkey "
" failed on chunking test %d "
" for %s: ret=%d \n " , j , algo ,
- ret ) ;
goto out ;
}
}
ahash_request_set_crypt ( req , sg , result ,
template [ i ] . psize ) ;
ret = crypto_ahash_digest ( req ) ;
switch ( ret ) {
case 0 :
break ;
case - EINPROGRESS :
case - EBUSY :
ret = wait_for_completion_interruptible (
& tresult . completion ) ;
if ( ! ret & & ! ( ret = tresult . err ) ) {
INIT_COMPLETION ( tresult . completion ) ;
break ;
}
/* fall through */
default :
printk ( KERN_ERR " alg: hash: digest failed "
" on chunking test %d for %s: "
" ret=%d \n " , j , algo , - ret ) ;
goto out ;
}
if ( memcmp ( result , template [ i ] . digest ,
crypto_ahash_digestsize ( tfm ) ) ) {
printk ( KERN_ERR " alg: hash: Chunking test %d "
" failed for %s \n " , j , algo ) ;
hexdump ( result , crypto_ahash_digestsize ( tfm ) ) ;
ret = - EINVAL ;
goto out ;
}
}
}
ret = 0 ;
out :
ahash_request_free ( req ) ;
out_noreq :
2009-05-06 10:15:47 +04:00
testmgr_free_buf ( xbuf ) ;
out_nobuf :
2008-07-31 13:08:25 +04:00
return ret ;
}
static int test_aead ( struct crypto_aead * tfm , int enc ,
struct aead_testvec * template , unsigned int tcount )
{
const char * algo = crypto_tfm_alg_driver_name ( crypto_aead_tfm ( tfm ) ) ;
unsigned int i , j , k , n , temp ;
2009-05-06 10:15:47 +04:00
int ret = - ENOMEM ;
2008-07-31 13:08:25 +04:00
char * q ;
char * key ;
struct aead_request * req ;
struct scatterlist sg [ 8 ] ;
struct scatterlist asg [ 8 ] ;
const char * e ;
struct tcrypt_result result ;
unsigned int authsize ;
void * input ;
void * assoc ;
char iv [ MAX_IVLEN ] ;
2009-05-06 10:15:47 +04:00
char * xbuf [ XBUFSIZE ] ;
char * axbuf [ XBUFSIZE ] ;
if ( testmgr_alloc_buf ( xbuf ) )
goto out_noxbuf ;
if ( testmgr_alloc_buf ( axbuf ) )
goto out_noaxbuf ;
2008-07-31 13:08:25 +04:00
if ( enc = = ENCRYPT )
e = " encryption " ;
else
e = " decryption " ;
init_completion ( & result . completion ) ;
req = aead_request_alloc ( tfm , GFP_KERNEL ) ;
if ( ! req ) {
printk ( KERN_ERR " alg: aead: Failed to allocate request for "
" %s \n " , algo ) ;
goto out ;
}
aead_request_set_callback ( req , CRYPTO_TFM_REQ_MAY_BACKLOG ,
tcrypt_complete , & result ) ;
for ( i = 0 , j = 0 ; i < tcount ; i + + ) {
if ( ! template [ i ] . np ) {
j + + ;
/* some tepmplates have no input data but they will
* touch input
*/
input = xbuf [ 0 ] ;
assoc = axbuf [ 0 ] ;
2009-05-29 10:05:42 +04:00
ret = - EINVAL ;
if ( WARN_ON ( template [ i ] . ilen > PAGE_SIZE | |
template [ i ] . alen > PAGE_SIZE ) )
goto out ;
2008-07-31 13:08:25 +04:00
memcpy ( input , template [ i ] . input , template [ i ] . ilen ) ;
memcpy ( assoc , template [ i ] . assoc , template [ i ] . alen ) ;
if ( template [ i ] . iv )
memcpy ( iv , template [ i ] . iv , MAX_IVLEN ) ;
else
memset ( iv , 0 , MAX_IVLEN ) ;
crypto_aead_clear_flags ( tfm , ~ 0 ) ;
if ( template [ i ] . wk )
crypto_aead_set_flags (
tfm , CRYPTO_TFM_REQ_WEAK_KEY ) ;
key = template [ i ] . key ;
ret = crypto_aead_setkey ( tfm , key ,
template [ i ] . klen ) ;
if ( ! ret = = template [ i ] . fail ) {
printk ( KERN_ERR " alg: aead: setkey failed on "
" test %d for %s: flags=%x \n " , j , algo ,
crypto_aead_get_flags ( tfm ) ) ;
goto out ;
} else if ( ret )
continue ;
authsize = abs ( template [ i ] . rlen - template [ i ] . ilen ) ;
ret = crypto_aead_setauthsize ( tfm , authsize ) ;
if ( ret ) {
printk ( KERN_ERR " alg: aead: Failed to set "
" authsize to %u on test %d for %s \n " ,
authsize , j , algo ) ;
goto out ;
}
sg_init_one ( & sg [ 0 ] , input ,
template [ i ] . ilen + ( enc ? authsize : 0 ) ) ;
sg_init_one ( & asg [ 0 ] , assoc , template [ i ] . alen ) ;
aead_request_set_crypt ( req , sg , sg ,
template [ i ] . ilen , iv ) ;
aead_request_set_assoc ( req , asg , template [ i ] . alen ) ;
ret = enc ?
crypto_aead_encrypt ( req ) :
crypto_aead_decrypt ( req ) ;
switch ( ret ) {
case 0 :
2009-05-04 15:22:11 +04:00
if ( template [ i ] . novrfy ) {
/* verification was supposed to fail */
printk ( KERN_ERR " alg: aead: %s failed "
" on test %d for %s: ret was 0, "
" expected -EBADMSG \n " ,
e , j , algo ) ;
/* so really, we got a bad message */
ret = - EBADMSG ;
goto out ;
}
2008-07-31 13:08:25 +04:00
break ;
case - EINPROGRESS :
case - EBUSY :
ret = wait_for_completion_interruptible (
& result . completion ) ;
if ( ! ret & & ! ( ret = result . err ) ) {
INIT_COMPLETION ( result . completion ) ;
break ;
}
2009-05-04 15:22:11 +04:00
case - EBADMSG :
if ( template [ i ] . novrfy )
/* verification failure was expected */
continue ;
2008-07-31 13:08:25 +04:00
/* fall through */
default :
printk ( KERN_ERR " alg: aead: %s failed on test "
" %d for %s: ret=%d \n " , e , j , algo , - ret ) ;
goto out ;
}
q = input ;
if ( memcmp ( q , template [ i ] . result , template [ i ] . rlen ) ) {
printk ( KERN_ERR " alg: aead: Test %d failed on "
" %s for %s \n " , j , e , algo ) ;
hexdump ( q , template [ i ] . rlen ) ;
ret = - EINVAL ;
goto out ;
}
}
}
for ( i = 0 , j = 0 ; i < tcount ; i + + ) {
if ( template [ i ] . np ) {
j + + ;
if ( template [ i ] . iv )
memcpy ( iv , template [ i ] . iv , MAX_IVLEN ) ;
else
memset ( iv , 0 , MAX_IVLEN ) ;
crypto_aead_clear_flags ( tfm , ~ 0 ) ;
if ( template [ i ] . wk )
crypto_aead_set_flags (
tfm , CRYPTO_TFM_REQ_WEAK_KEY ) ;
key = template [ i ] . key ;
ret = crypto_aead_setkey ( tfm , key , template [ i ] . klen ) ;
if ( ! ret = = template [ i ] . fail ) {
printk ( KERN_ERR " alg: aead: setkey failed on "
" chunk test %d for %s: flags=%x \n " , j ,
algo , crypto_aead_get_flags ( tfm ) ) ;
goto out ;
} else if ( ret )
continue ;
authsize = abs ( template [ i ] . rlen - template [ i ] . ilen ) ;
ret = - EINVAL ;
sg_init_table ( sg , template [ i ] . np ) ;
for ( k = 0 , temp = 0 ; k < template [ i ] . np ; k + + ) {
if ( WARN_ON ( offset_in_page ( IDX [ k ] ) +
template [ i ] . tap [ k ] > PAGE_SIZE ) )
goto out ;
q = xbuf [ IDX [ k ] > > PAGE_SHIFT ] +
offset_in_page ( IDX [ k ] ) ;
memcpy ( q , template [ i ] . input + temp ,
template [ i ] . tap [ k ] ) ;
n = template [ i ] . tap [ k ] ;
if ( k = = template [ i ] . np - 1 & & enc )
n + = authsize ;
if ( offset_in_page ( q ) + n < PAGE_SIZE )
q [ n ] = 0 ;
sg_set_buf ( & sg [ k ] , q , template [ i ] . tap [ k ] ) ;
temp + = template [ i ] . tap [ k ] ;
}
ret = crypto_aead_setauthsize ( tfm , authsize ) ;
if ( ret ) {
printk ( KERN_ERR " alg: aead: Failed to set "
" authsize to %u on chunk test %d for "
" %s \n " , authsize , j , algo ) ;
goto out ;
}
if ( enc ) {
if ( WARN_ON ( sg [ k - 1 ] . offset +
sg [ k - 1 ] . length + authsize >
PAGE_SIZE ) ) {
ret = - EINVAL ;
goto out ;
}
sg [ k - 1 ] . length + = authsize ;
}
sg_init_table ( asg , template [ i ] . anp ) ;
2009-05-29 10:05:42 +04:00
ret = - EINVAL ;
2008-07-31 13:08:25 +04:00
for ( k = 0 , temp = 0 ; k < template [ i ] . anp ; k + + ) {
2009-05-29 10:05:42 +04:00
if ( WARN_ON ( offset_in_page ( IDX [ k ] ) +
template [ i ] . atap [ k ] > PAGE_SIZE ) )
goto out ;
2008-07-31 13:08:25 +04:00
sg_set_buf ( & asg [ k ] ,
memcpy ( axbuf [ IDX [ k ] > > PAGE_SHIFT ] +
offset_in_page ( IDX [ k ] ) ,
template [ i ] . assoc + temp ,
template [ i ] . atap [ k ] ) ,
template [ i ] . atap [ k ] ) ;
temp + = template [ i ] . atap [ k ] ;
}
aead_request_set_crypt ( req , sg , sg ,
template [ i ] . ilen ,
iv ) ;
aead_request_set_assoc ( req , asg , template [ i ] . alen ) ;
ret = enc ?
crypto_aead_encrypt ( req ) :
crypto_aead_decrypt ( req ) ;
switch ( ret ) {
case 0 :
2009-05-04 15:22:11 +04:00
if ( template [ i ] . novrfy ) {
/* verification was supposed to fail */
printk ( KERN_ERR " alg: aead: %s failed "
" on chunk test %d for %s: ret "
" was 0, expected -EBADMSG \n " ,
e , j , algo ) ;
/* so really, we got a bad message */
ret = - EBADMSG ;
goto out ;
}
2008-07-31 13:08:25 +04:00
break ;
case - EINPROGRESS :
case - EBUSY :
ret = wait_for_completion_interruptible (
& result . completion ) ;
if ( ! ret & & ! ( ret = result . err ) ) {
INIT_COMPLETION ( result . completion ) ;
break ;
}
2009-05-04 15:22:11 +04:00
case - EBADMSG :
if ( template [ i ] . novrfy )
/* verification failure was expected */
continue ;
2008-07-31 13:08:25 +04:00
/* fall through */
default :
printk ( KERN_ERR " alg: aead: %s failed on "
" chunk test %d for %s: ret=%d \n " , e , j ,
algo , - ret ) ;
goto out ;
}
ret = - EINVAL ;
for ( k = 0 , temp = 0 ; k < template [ i ] . np ; k + + ) {
q = xbuf [ IDX [ k ] > > PAGE_SHIFT ] +
offset_in_page ( IDX [ k ] ) ;
n = template [ i ] . tap [ k ] ;
if ( k = = template [ i ] . np - 1 )
n + = enc ? authsize : - authsize ;
if ( memcmp ( q , template [ i ] . result + temp , n ) ) {
printk ( KERN_ERR " alg: aead: Chunk "
" test %d failed on %s at page "
" %u for %s \n " , j , e , k , algo ) ;
hexdump ( q , n ) ;
goto out ;
}
q + = n ;
if ( k = = template [ i ] . np - 1 & & ! enc ) {
if ( memcmp ( q , template [ i ] . input +
temp + n , authsize ) )
n = authsize ;
else
n = 0 ;
} else {
for ( n = 0 ; offset_in_page ( q + n ) & &
q [ n ] ; n + + )
;
}
if ( n ) {
printk ( KERN_ERR " alg: aead: Result "
" buffer corruption in chunk "
" test %d on %s at page %u for "
" %s: %u bytes: \n " , j , e , k ,
algo , n ) ;
hexdump ( q , n ) ;
goto out ;
}
temp + = template [ i ] . tap [ k ] ;
}
}
}
ret = 0 ;
out :
aead_request_free ( req ) ;
2009-05-06 10:15:47 +04:00
testmgr_free_buf ( axbuf ) ;
out_noaxbuf :
testmgr_free_buf ( xbuf ) ;
out_noxbuf :
2008-07-31 13:08:25 +04:00
return ret ;
}
2008-08-17 11:01:56 +04:00
static int test_cipher ( struct crypto_cipher * tfm , int enc ,
2008-07-31 13:08:25 +04:00
struct cipher_testvec * template , unsigned int tcount )
2008-08-17 11:01:56 +04:00
{
const char * algo = crypto_tfm_alg_driver_name ( crypto_cipher_tfm ( tfm ) ) ;
unsigned int i , j , k ;
char * q ;
const char * e ;
void * data ;
2009-05-06 10:15:47 +04:00
char * xbuf [ XBUFSIZE ] ;
int ret = - ENOMEM ;
if ( testmgr_alloc_buf ( xbuf ) )
goto out_nobuf ;
2008-08-17 11:01:56 +04:00
if ( enc = = ENCRYPT )
e = " encryption " ;
else
e = " decryption " ;
j = 0 ;
for ( i = 0 ; i < tcount ; i + + ) {
if ( template [ i ] . np )
continue ;
j + + ;
2009-05-29 10:05:42 +04:00
ret = - EINVAL ;
if ( WARN_ON ( template [ i ] . ilen > PAGE_SIZE ) )
goto out ;
2008-08-17 11:01:56 +04:00
data = xbuf [ 0 ] ;
memcpy ( data , template [ i ] . input , template [ i ] . ilen ) ;
crypto_cipher_clear_flags ( tfm , ~ 0 ) ;
if ( template [ i ] . wk )
crypto_cipher_set_flags ( tfm , CRYPTO_TFM_REQ_WEAK_KEY ) ;
ret = crypto_cipher_setkey ( tfm , template [ i ] . key ,
template [ i ] . klen ) ;
if ( ! ret = = template [ i ] . fail ) {
printk ( KERN_ERR " alg: cipher: setkey failed "
" on test %d for %s: flags=%x \n " , j ,
algo , crypto_cipher_get_flags ( tfm ) ) ;
goto out ;
} else if ( ret )
continue ;
for ( k = 0 ; k < template [ i ] . ilen ;
k + = crypto_cipher_blocksize ( tfm ) ) {
if ( enc )
crypto_cipher_encrypt_one ( tfm , data + k ,
data + k ) ;
else
crypto_cipher_decrypt_one ( tfm , data + k ,
data + k ) ;
}
q = data ;
if ( memcmp ( q , template [ i ] . result , template [ i ] . rlen ) ) {
printk ( KERN_ERR " alg: cipher: Test %d failed "
" on %s for %s \n " , j , e , algo ) ;
hexdump ( q , template [ i ] . rlen ) ;
ret = - EINVAL ;
goto out ;
}
}
ret = 0 ;
out :
2009-05-06 10:15:47 +04:00
testmgr_free_buf ( xbuf ) ;
out_nobuf :
2008-08-17 11:01:56 +04:00
return ret ;
}
static int test_skcipher ( struct crypto_ablkcipher * tfm , int enc ,
struct cipher_testvec * template , unsigned int tcount )
2008-07-31 13:08:25 +04:00
{
const char * algo =
crypto_tfm_alg_driver_name ( crypto_ablkcipher_tfm ( tfm ) ) ;
unsigned int i , j , k , n , temp ;
char * q ;
struct ablkcipher_request * req ;
struct scatterlist sg [ 8 ] ;
const char * e ;
struct tcrypt_result result ;
void * data ;
char iv [ MAX_IVLEN ] ;
2009-05-06 10:15:47 +04:00
char * xbuf [ XBUFSIZE ] ;
int ret = - ENOMEM ;
if ( testmgr_alloc_buf ( xbuf ) )
goto out_nobuf ;
2008-07-31 13:08:25 +04:00
if ( enc = = ENCRYPT )
e = " encryption " ;
else
e = " decryption " ;
init_completion ( & result . completion ) ;
req = ablkcipher_request_alloc ( tfm , GFP_KERNEL ) ;
if ( ! req ) {
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: Failed to allocate request "
" for %s \n " , algo ) ;
2008-07-31 13:08:25 +04:00
goto out ;
}
ablkcipher_request_set_callback ( req , CRYPTO_TFM_REQ_MAY_BACKLOG ,
tcrypt_complete , & result ) ;
j = 0 ;
for ( i = 0 ; i < tcount ; i + + ) {
if ( template [ i ] . iv )
memcpy ( iv , template [ i ] . iv , MAX_IVLEN ) ;
else
memset ( iv , 0 , MAX_IVLEN ) ;
if ( ! ( template [ i ] . np ) ) {
j + + ;
2009-05-29 10:05:42 +04:00
ret = - EINVAL ;
if ( WARN_ON ( template [ i ] . ilen > PAGE_SIZE ) )
goto out ;
2008-07-31 13:08:25 +04:00
data = xbuf [ 0 ] ;
memcpy ( data , template [ i ] . input , template [ i ] . ilen ) ;
crypto_ablkcipher_clear_flags ( tfm , ~ 0 ) ;
if ( template [ i ] . wk )
crypto_ablkcipher_set_flags (
tfm , CRYPTO_TFM_REQ_WEAK_KEY ) ;
ret = crypto_ablkcipher_setkey ( tfm , template [ i ] . key ,
template [ i ] . klen ) ;
if ( ! ret = = template [ i ] . fail ) {
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: setkey failed "
2008-07-31 13:08:25 +04:00
" on test %d for %s: flags=%x \n " , j ,
algo , crypto_ablkcipher_get_flags ( tfm ) ) ;
goto out ;
} else if ( ret )
continue ;
sg_init_one ( & sg [ 0 ] , data , template [ i ] . ilen ) ;
ablkcipher_request_set_crypt ( req , sg , sg ,
template [ i ] . ilen , iv ) ;
ret = enc ?
crypto_ablkcipher_encrypt ( req ) :
crypto_ablkcipher_decrypt ( req ) ;
switch ( ret ) {
case 0 :
break ;
case - EINPROGRESS :
case - EBUSY :
ret = wait_for_completion_interruptible (
& result . completion ) ;
if ( ! ret & & ! ( ( ret = result . err ) ) ) {
INIT_COMPLETION ( result . completion ) ;
break ;
}
/* fall through */
default :
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: %s failed on "
2008-07-31 13:08:25 +04:00
" test %d for %s: ret=%d \n " , e , j , algo ,
- ret ) ;
goto out ;
}
q = data ;
if ( memcmp ( q , template [ i ] . result , template [ i ] . rlen ) ) {
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: Test %d "
" failed on %s for %s \n " , j , e , algo ) ;
2008-07-31 13:08:25 +04:00
hexdump ( q , template [ i ] . rlen ) ;
ret = - EINVAL ;
goto out ;
}
}
}
j = 0 ;
for ( i = 0 ; i < tcount ; i + + ) {
if ( template [ i ] . iv )
memcpy ( iv , template [ i ] . iv , MAX_IVLEN ) ;
else
memset ( iv , 0 , MAX_IVLEN ) ;
if ( template [ i ] . np ) {
j + + ;
crypto_ablkcipher_clear_flags ( tfm , ~ 0 ) ;
if ( template [ i ] . wk )
crypto_ablkcipher_set_flags (
tfm , CRYPTO_TFM_REQ_WEAK_KEY ) ;
ret = crypto_ablkcipher_setkey ( tfm , template [ i ] . key ,
template [ i ] . klen ) ;
if ( ! ret = = template [ i ] . fail ) {
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: setkey failed "
2008-07-31 13:08:25 +04:00
" on chunk test %d for %s: flags=%x \n " ,
j , algo ,
crypto_ablkcipher_get_flags ( tfm ) ) ;
goto out ;
} else if ( ret )
continue ;
temp = 0 ;
ret = - EINVAL ;
sg_init_table ( sg , template [ i ] . np ) ;
for ( k = 0 ; k < template [ i ] . np ; k + + ) {
if ( WARN_ON ( offset_in_page ( IDX [ k ] ) +
template [ i ] . tap [ k ] > PAGE_SIZE ) )
goto out ;
q = xbuf [ IDX [ k ] > > PAGE_SHIFT ] +
offset_in_page ( IDX [ k ] ) ;
memcpy ( q , template [ i ] . input + temp ,
template [ i ] . tap [ k ] ) ;
if ( offset_in_page ( q ) + template [ i ] . tap [ k ] <
PAGE_SIZE )
q [ template [ i ] . tap [ k ] ] = 0 ;
sg_set_buf ( & sg [ k ] , q , template [ i ] . tap [ k ] ) ;
temp + = template [ i ] . tap [ k ] ;
}
ablkcipher_request_set_crypt ( req , sg , sg ,
template [ i ] . ilen , iv ) ;
ret = enc ?
crypto_ablkcipher_encrypt ( req ) :
crypto_ablkcipher_decrypt ( req ) ;
switch ( ret ) {
case 0 :
break ;
case - EINPROGRESS :
case - EBUSY :
ret = wait_for_completion_interruptible (
& result . completion ) ;
if ( ! ret & & ! ( ( ret = result . err ) ) ) {
INIT_COMPLETION ( result . completion ) ;
break ;
}
/* fall through */
default :
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: %s failed on "
2008-07-31 13:08:25 +04:00
" chunk test %d for %s: ret=%d \n " , e , j ,
algo , - ret ) ;
goto out ;
}
temp = 0 ;
ret = - EINVAL ;
for ( k = 0 ; k < template [ i ] . np ; k + + ) {
q = xbuf [ IDX [ k ] > > PAGE_SHIFT ] +
offset_in_page ( IDX [ k ] ) ;
if ( memcmp ( q , template [ i ] . result + temp ,
template [ i ] . tap [ k ] ) ) {
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: Chunk "
2008-07-31 13:08:25 +04:00
" test %d failed on %s at page "
" %u for %s \n " , j , e , k , algo ) ;
hexdump ( q , template [ i ] . tap [ k ] ) ;
goto out ;
}
q + = template [ i ] . tap [ k ] ;
for ( n = 0 ; offset_in_page ( q + n ) & & q [ n ] ; n + + )
;
if ( n ) {
2008-08-17 11:01:56 +04:00
printk ( KERN_ERR " alg: skcipher: "
2008-07-31 13:08:25 +04:00
" Result buffer corruption in "
" chunk test %d on %s at page "
" %u for %s: %u bytes: \n " , j , e ,
k , algo , n ) ;
hexdump ( q , n ) ;
goto out ;
}
temp + = template [ i ] . tap [ k ] ;
}
}
}
ret = 0 ;
out :
ablkcipher_request_free ( req ) ;
2009-05-06 10:15:47 +04:00
testmgr_free_buf ( xbuf ) ;
out_nobuf :
2008-07-31 13:08:25 +04:00
return ret ;
}
static int test_comp ( struct crypto_comp * tfm , struct comp_testvec * ctemplate ,
struct comp_testvec * dtemplate , int ctcount , int dtcount )
{
const char * algo = crypto_tfm_alg_driver_name ( crypto_comp_tfm ( tfm ) ) ;
unsigned int i ;
char result [ COMP_BUF_SIZE ] ;
int ret ;
for ( i = 0 ; i < ctcount ; i + + ) {
2009-03-29 11:44:19 +04:00
int ilen ;
unsigned int dlen = COMP_BUF_SIZE ;
2008-07-31 13:08:25 +04:00
memset ( result , 0 , sizeof ( result ) ) ;
ilen = ctemplate [ i ] . inlen ;
ret = crypto_comp_compress ( tfm , ctemplate [ i ] . input ,
ilen , result , & dlen ) ;
if ( ret ) {
printk ( KERN_ERR " alg: comp: compression failed "
" on test %d for %s: ret=%d \n " , i + 1 , algo ,
- ret ) ;
goto out ;
}
2008-11-28 15:51:28 +03:00
if ( dlen ! = ctemplate [ i ] . outlen ) {
printk ( KERN_ERR " alg: comp: Compression test %d "
" failed for %s: output len = %d \n " , i + 1 , algo ,
dlen ) ;
ret = - EINVAL ;
goto out ;
}
2008-07-31 13:08:25 +04:00
if ( memcmp ( result , ctemplate [ i ] . output , dlen ) ) {
printk ( KERN_ERR " alg: comp: Compression test %d "
" failed for %s \n " , i + 1 , algo ) ;
hexdump ( result , dlen ) ;
ret = - EINVAL ;
goto out ;
}
}
for ( i = 0 ; i < dtcount ; i + + ) {
2009-03-29 11:44:19 +04:00
int ilen ;
unsigned int dlen = COMP_BUF_SIZE ;
2008-07-31 13:08:25 +04:00
memset ( result , 0 , sizeof ( result ) ) ;
ilen = dtemplate [ i ] . inlen ;
ret = crypto_comp_decompress ( tfm , dtemplate [ i ] . input ,
ilen , result , & dlen ) ;
if ( ret ) {
printk ( KERN_ERR " alg: comp: decompression failed "
" on test %d for %s: ret=%d \n " , i + 1 , algo ,
- ret ) ;
goto out ;
}
2008-11-28 15:51:28 +03:00
if ( dlen ! = dtemplate [ i ] . outlen ) {
printk ( KERN_ERR " alg: comp: Decompression test %d "
" failed for %s: output len = %d \n " , i + 1 , algo ,
dlen ) ;
ret = - EINVAL ;
goto out ;
}
2008-07-31 13:08:25 +04:00
if ( memcmp ( result , dtemplate [ i ] . output , dlen ) ) {
printk ( KERN_ERR " alg: comp: Decompression test %d "
" failed for %s \n " , i + 1 , algo ) ;
hexdump ( result , dlen ) ;
ret = - EINVAL ;
goto out ;
}
}
ret = 0 ;
out :
return ret ;
}
2009-03-04 10:08:03 +03:00
static int test_pcomp ( struct crypto_pcomp * tfm ,
struct pcomp_testvec * ctemplate ,
struct pcomp_testvec * dtemplate , int ctcount ,
int dtcount )
{
const char * algo = crypto_tfm_alg_driver_name ( crypto_pcomp_tfm ( tfm ) ) ;
unsigned int i ;
char result [ COMP_BUF_SIZE ] ;
2009-05-27 09:05:02 +04:00
int res ;
2009-03-04 10:08:03 +03:00
for ( i = 0 ; i < ctcount ; i + + ) {
struct comp_request req ;
2009-05-27 09:05:02 +04:00
unsigned int produced = 0 ;
2009-03-04 10:08:03 +03:00
2009-05-27 09:05:02 +04:00
res = crypto_compress_setup ( tfm , ctemplate [ i ] . params ,
ctemplate [ i ] . paramsize ) ;
if ( res ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: compression setup failed on test "
2009-05-27 09:05:02 +04:00
" %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
res = crypto_compress_init ( tfm ) ;
if ( res ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: compression init failed on test "
2009-05-27 09:05:02 +04:00
" %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
memset ( result , 0 , sizeof ( result ) ) ;
req . next_in = ctemplate [ i ] . input ;
req . avail_in = ctemplate [ i ] . inlen / 2 ;
req . next_out = result ;
req . avail_out = ctemplate [ i ] . outlen / 2 ;
2009-05-27 09:05:02 +04:00
res = crypto_compress_update ( tfm , & req ) ;
if ( res < 0 & & ( res ! = - EAGAIN | | req . avail_in ) ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: compression update failed on test "
2009-05-27 09:05:02 +04:00
" %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
if ( res > 0 )
produced + = res ;
2009-03-04 10:08:03 +03:00
/* Add remaining input data */
req . avail_in + = ( ctemplate [ i ] . inlen + 1 ) / 2 ;
2009-05-27 09:05:02 +04:00
res = crypto_compress_update ( tfm , & req ) ;
if ( res < 0 & & ( res ! = - EAGAIN | | req . avail_in ) ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: compression update failed on test "
2009-05-27 09:05:02 +04:00
" %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
if ( res > 0 )
produced + = res ;
2009-03-04 10:08:03 +03:00
/* Provide remaining output space */
req . avail_out + = COMP_BUF_SIZE - ctemplate [ i ] . outlen / 2 ;
2009-05-27 09:05:02 +04:00
res = crypto_compress_final ( tfm , & req ) ;
if ( res < 0 ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: compression final failed on test "
2009-05-27 09:05:02 +04:00
" %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
produced + = res ;
2009-03-04 10:08:03 +03:00
if ( COMP_BUF_SIZE - req . avail_out ! = ctemplate [ i ] . outlen ) {
pr_err ( " alg: comp: Compression test %d failed for %s: "
" output len = %d (expected %d) \n " , i + 1 , algo ,
COMP_BUF_SIZE - req . avail_out ,
ctemplate [ i ] . outlen ) ;
return - EINVAL ;
}
2009-05-27 09:05:02 +04:00
if ( produced ! = ctemplate [ i ] . outlen ) {
pr_err ( " alg: comp: Compression test %d failed for %s: "
" returned len = %u (expected %d) \n " , i + 1 ,
algo , produced , ctemplate [ i ] . outlen ) ;
return - EINVAL ;
}
2009-03-04 10:08:03 +03:00
if ( memcmp ( result , ctemplate [ i ] . output , ctemplate [ i ] . outlen ) ) {
pr_err ( " alg: pcomp: Compression test %d failed for "
" %s \n " , i + 1 , algo ) ;
hexdump ( result , ctemplate [ i ] . outlen ) ;
return - EINVAL ;
}
}
for ( i = 0 ; i < dtcount ; i + + ) {
struct comp_request req ;
2009-05-27 09:05:02 +04:00
unsigned int produced = 0 ;
2009-03-04 10:08:03 +03:00
2009-05-27 09:05:02 +04:00
res = crypto_decompress_setup ( tfm , dtemplate [ i ] . params ,
dtemplate [ i ] . paramsize ) ;
if ( res ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: decompression setup failed on "
2009-05-27 09:05:02 +04:00
" test %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
res = crypto_decompress_init ( tfm ) ;
if ( res ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: decompression init failed on test "
2009-05-27 09:05:02 +04:00
" %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
memset ( result , 0 , sizeof ( result ) ) ;
req . next_in = dtemplate [ i ] . input ;
req . avail_in = dtemplate [ i ] . inlen / 2 ;
req . next_out = result ;
req . avail_out = dtemplate [ i ] . outlen / 2 ;
2009-05-27 09:05:02 +04:00
res = crypto_decompress_update ( tfm , & req ) ;
if ( res < 0 & & ( res ! = - EAGAIN | | req . avail_in ) ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: decompression update failed on "
2009-05-27 09:05:02 +04:00
" test %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
if ( res > 0 )
produced + = res ;
2009-03-04 10:08:03 +03:00
/* Add remaining input data */
req . avail_in + = ( dtemplate [ i ] . inlen + 1 ) / 2 ;
2009-05-27 09:05:02 +04:00
res = crypto_decompress_update ( tfm , & req ) ;
if ( res < 0 & & ( res ! = - EAGAIN | | req . avail_in ) ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: decompression update failed on "
2009-05-27 09:05:02 +04:00
" test %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
if ( res > 0 )
produced + = res ;
2009-03-04 10:08:03 +03:00
/* Provide remaining output space */
req . avail_out + = COMP_BUF_SIZE - dtemplate [ i ] . outlen / 2 ;
2009-05-27 09:05:02 +04:00
res = crypto_decompress_final ( tfm , & req ) ;
if ( res < 0 & & ( res ! = - EAGAIN | | req . avail_in ) ) {
2009-03-04 10:08:03 +03:00
pr_err ( " alg: pcomp: decompression final failed on "
2009-05-27 09:05:02 +04:00
" test %d for %s: error=%d \n " , i + 1 , algo , res ) ;
return res ;
2009-03-04 10:08:03 +03:00
}
2009-05-27 09:05:02 +04:00
if ( res > 0 )
produced + = res ;
2009-03-04 10:08:03 +03:00
if ( COMP_BUF_SIZE - req . avail_out ! = dtemplate [ i ] . outlen ) {
pr_err ( " alg: comp: Decompression test %d failed for "
" %s: output len = %d (expected %d) \n " , i + 1 ,
algo , COMP_BUF_SIZE - req . avail_out ,
dtemplate [ i ] . outlen ) ;
return - EINVAL ;
}
2009-05-27 09:05:02 +04:00
if ( produced ! = dtemplate [ i ] . outlen ) {
pr_err ( " alg: comp: Decompression test %d failed for "
" %s: returned len = %u (expected %d) \n " , i + 1 ,
algo , produced , dtemplate [ i ] . outlen ) ;
return - EINVAL ;
}
2009-03-04 10:08:03 +03:00
if ( memcmp ( result , dtemplate [ i ] . output , dtemplate [ i ] . outlen ) ) {
pr_err ( " alg: pcomp: Decompression test %d failed for "
" %s \n " , i + 1 , algo ) ;
hexdump ( result , dtemplate [ i ] . outlen ) ;
return - EINVAL ;
}
}
return 0 ;
}
2009-05-04 15:44:50 +04:00
static int test_cprng ( struct crypto_rng * tfm , struct cprng_testvec * template ,
unsigned int tcount )
{
const char * algo = crypto_tfm_alg_driver_name ( crypto_rng_tfm ( tfm ) ) ;
2009-10-27 14:04:42 +03:00
int err = 0 , i , j , seedsize ;
2009-05-04 15:44:50 +04:00
u8 * seed ;
char result [ 32 ] ;
seedsize = crypto_rng_seedsize ( tfm ) ;
seed = kmalloc ( seedsize , GFP_KERNEL ) ;
if ( ! seed ) {
printk ( KERN_ERR " alg: cprng: Failed to allocate seed space "
" for %s \n " , algo ) ;
return - ENOMEM ;
}
for ( i = 0 ; i < tcount ; i + + ) {
memset ( result , 0 , 32 ) ;
memcpy ( seed , template [ i ] . v , template [ i ] . vlen ) ;
memcpy ( seed + template [ i ] . vlen , template [ i ] . key ,
template [ i ] . klen ) ;
memcpy ( seed + template [ i ] . vlen + template [ i ] . klen ,
template [ i ] . dt , template [ i ] . dtlen ) ;
err = crypto_rng_reset ( tfm , seed , seedsize ) ;
if ( err ) {
printk ( KERN_ERR " alg: cprng: Failed to reset rng "
" for %s \n " , algo ) ;
goto out ;
}
for ( j = 0 ; j < template [ i ] . loops ; j + + ) {
err = crypto_rng_get_bytes ( tfm , result ,
template [ i ] . rlen ) ;
if ( err ! = template [ i ] . rlen ) {
printk ( KERN_ERR " alg: cprng: Failed to obtain "
" the correct amount of random data for "
" %s (requested %d, got %d) \n " , algo ,
template [ i ] . rlen , err ) ;
goto out ;
}
}
err = memcmp ( result , template [ i ] . result ,
template [ i ] . rlen ) ;
if ( err ) {
printk ( KERN_ERR " alg: cprng: Test %d failed for %s \n " ,
i , algo ) ;
hexdump ( result , template [ i ] . rlen ) ;
err = - EINVAL ;
goto out ;
}
}
out :
kfree ( seed ) ;
return err ;
}
2008-07-31 13:08:25 +04:00
static int alg_test_aead ( const struct alg_test_desc * desc , const char * driver ,
u32 type , u32 mask )
{
struct crypto_aead * tfm ;
int err = 0 ;
tfm = crypto_alloc_aead ( driver , type , mask ) ;
if ( IS_ERR ( tfm ) ) {
printk ( KERN_ERR " alg: aead: Failed to load transform for %s: "
" %ld \n " , driver , PTR_ERR ( tfm ) ) ;
return PTR_ERR ( tfm ) ;
}
if ( desc - > suite . aead . enc . vecs ) {
err = test_aead ( tfm , ENCRYPT , desc - > suite . aead . enc . vecs ,
desc - > suite . aead . enc . count ) ;
if ( err )
goto out ;
}
if ( ! err & & desc - > suite . aead . dec . vecs )
err = test_aead ( tfm , DECRYPT , desc - > suite . aead . dec . vecs ,
desc - > suite . aead . dec . count ) ;
out :
crypto_free_aead ( tfm ) ;
return err ;
}
static int alg_test_cipher ( const struct alg_test_desc * desc ,
const char * driver , u32 type , u32 mask )
{
2008-08-17 11:01:56 +04:00
struct crypto_cipher * tfm ;
2008-07-31 13:08:25 +04:00
int err = 0 ;
2008-08-17 11:01:56 +04:00
tfm = crypto_alloc_cipher ( driver , type , mask ) ;
2008-07-31 13:08:25 +04:00
if ( IS_ERR ( tfm ) ) {
printk ( KERN_ERR " alg: cipher: Failed to load transform for "
" %s: %ld \n " , driver , PTR_ERR ( tfm ) ) ;
return PTR_ERR ( tfm ) ;
}
if ( desc - > suite . cipher . enc . vecs ) {
err = test_cipher ( tfm , ENCRYPT , desc - > suite . cipher . enc . vecs ,
desc - > suite . cipher . enc . count ) ;
if ( err )
goto out ;
}
if ( desc - > suite . cipher . dec . vecs )
err = test_cipher ( tfm , DECRYPT , desc - > suite . cipher . dec . vecs ,
desc - > suite . cipher . dec . count ) ;
2008-08-17 11:01:56 +04:00
out :
crypto_free_cipher ( tfm ) ;
return err ;
}
static int alg_test_skcipher ( const struct alg_test_desc * desc ,
const char * driver , u32 type , u32 mask )
{
struct crypto_ablkcipher * tfm ;
int err = 0 ;
tfm = crypto_alloc_ablkcipher ( driver , type , mask ) ;
if ( IS_ERR ( tfm ) ) {
printk ( KERN_ERR " alg: skcipher: Failed to load transform for "
" %s: %ld \n " , driver , PTR_ERR ( tfm ) ) ;
return PTR_ERR ( tfm ) ;
}
if ( desc - > suite . cipher . enc . vecs ) {
err = test_skcipher ( tfm , ENCRYPT , desc - > suite . cipher . enc . vecs ,
desc - > suite . cipher . enc . count ) ;
if ( err )
goto out ;
}
if ( desc - > suite . cipher . dec . vecs )
err = test_skcipher ( tfm , DECRYPT , desc - > suite . cipher . dec . vecs ,
desc - > suite . cipher . dec . count ) ;
2008-07-31 13:08:25 +04:00
out :
crypto_free_ablkcipher ( tfm ) ;
return err ;
}
static int alg_test_comp ( const struct alg_test_desc * desc , const char * driver ,
u32 type , u32 mask )
{
struct crypto_comp * tfm ;
int err ;
tfm = crypto_alloc_comp ( driver , type , mask ) ;
if ( IS_ERR ( tfm ) ) {
printk ( KERN_ERR " alg: comp: Failed to load transform for %s: "
" %ld \n " , driver , PTR_ERR ( tfm ) ) ;
return PTR_ERR ( tfm ) ;
}
err = test_comp ( tfm , desc - > suite . comp . comp . vecs ,
desc - > suite . comp . decomp . vecs ,
desc - > suite . comp . comp . count ,
desc - > suite . comp . decomp . count ) ;
crypto_free_comp ( tfm ) ;
return err ;
}
2009-03-04 10:08:03 +03:00
static int alg_test_pcomp ( const struct alg_test_desc * desc , const char * driver ,
u32 type , u32 mask )
{
struct crypto_pcomp * tfm ;
int err ;
tfm = crypto_alloc_pcomp ( driver , type , mask ) ;
if ( IS_ERR ( tfm ) ) {
pr_err ( " alg: pcomp: Failed to load transform for %s: %ld \n " ,
driver , PTR_ERR ( tfm ) ) ;
return PTR_ERR ( tfm ) ;
}
err = test_pcomp ( tfm , desc - > suite . pcomp . comp . vecs ,
desc - > suite . pcomp . decomp . vecs ,
desc - > suite . pcomp . comp . count ,
desc - > suite . pcomp . decomp . count ) ;
crypto_free_pcomp ( tfm ) ;
return err ;
}
2008-07-31 13:08:25 +04:00
static int alg_test_hash ( const struct alg_test_desc * desc , const char * driver ,
u32 type , u32 mask )
{
struct crypto_ahash * tfm ;
int err ;
tfm = crypto_alloc_ahash ( driver , type , mask ) ;
if ( IS_ERR ( tfm ) ) {
printk ( KERN_ERR " alg: hash: Failed to load transform for %s: "
" %ld \n " , driver , PTR_ERR ( tfm ) ) ;
return PTR_ERR ( tfm ) ;
}
2010-05-19 08:12:03 +04:00
err = test_hash ( tfm , desc - > suite . hash . vecs ,
desc - > suite . hash . count , true ) ;
if ( ! err )
err = test_hash ( tfm , desc - > suite . hash . vecs ,
desc - > suite . hash . count , false ) ;
2008-07-31 13:08:25 +04:00
crypto_free_ahash ( tfm ) ;
return err ;
}
2008-11-07 09:58:52 +03:00
static int alg_test_crc32c ( const struct alg_test_desc * desc ,
const char * driver , u32 type , u32 mask )
{
struct crypto_shash * tfm ;
u32 val ;
int err ;
err = alg_test_hash ( desc , driver , type , mask ) ;
if ( err )
goto out ;
tfm = crypto_alloc_shash ( driver , type , mask ) ;
if ( IS_ERR ( tfm ) ) {
printk ( KERN_ERR " alg: crc32c: Failed to load transform for %s: "
" %ld \n " , driver , PTR_ERR ( tfm ) ) ;
err = PTR_ERR ( tfm ) ;
goto out ;
}
do {
struct {
struct shash_desc shash ;
char ctx [ crypto_shash_descsize ( tfm ) ] ;
} sdesc ;
sdesc . shash . tfm = tfm ;
sdesc . shash . flags = 0 ;
* ( u32 * ) sdesc . ctx = le32_to_cpu ( 420553207 ) ;
err = crypto_shash_final ( & sdesc . shash , ( u8 * ) & val ) ;
if ( err ) {
printk ( KERN_ERR " alg: crc32c: Operation failed for "
" %s: %d \n " , driver , err ) ;
break ;
}
if ( val ! = ~ 420553207 ) {
printk ( KERN_ERR " alg: crc32c: Test failed for %s: "
" %d \n " , driver , val ) ;
err = - EINVAL ;
}
} while ( 0 ) ;
crypto_free_shash ( tfm ) ;
out :
return err ;
}
2009-05-04 15:44:50 +04:00
static int alg_test_cprng ( const struct alg_test_desc * desc , const char * driver ,
u32 type , u32 mask )
{
struct crypto_rng * rng ;
int err ;
rng = crypto_alloc_rng ( driver , type , mask ) ;
if ( IS_ERR ( rng ) ) {
printk ( KERN_ERR " alg: cprng: Failed to load transform for %s: "
" %ld \n " , driver , PTR_ERR ( rng ) ) ;
return PTR_ERR ( rng ) ;
}
err = test_cprng ( rng , desc - > suite . cprng . vecs , desc - > suite . cprng . count ) ;
crypto_free_rng ( rng ) ;
return err ;
}
2009-12-23 14:45:20 +03:00
static int alg_test_null ( const struct alg_test_desc * desc ,
const char * driver , u32 type , u32 mask )
{
return 0 ;
}
2008-07-31 13:08:25 +04:00
/* Please keep this list sorted by algorithm name. */
static const struct alg_test_desc alg_test_descs [ ] = {
{
2009-12-23 14:45:20 +03:00
. alg = " __driver-cbc-aes-aesni " ,
. test = alg_test_null ,
. suite = {
. cipher = {
. enc = {
. vecs = NULL ,
. count = 0
} ,
. dec = {
. vecs = NULL ,
. count = 0
}
}
}
} , {
. alg = " __driver-ecb-aes-aesni " ,
. test = alg_test_null ,
. suite = {
. cipher = {
. enc = {
. vecs = NULL ,
. count = 0
} ,
. dec = {
. vecs = NULL ,
. count = 0
}
}
}
} , {
. alg = " __ghash-pclmulqdqni " ,
. test = alg_test_null ,
. suite = {
. hash = {
. vecs = NULL ,
. count = 0
}
}
} , {
2009-05-04 15:46:29 +04:00
. alg = " ansi_cprng " ,
. test = alg_test_cprng ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2009-05-04 15:46:29 +04:00
. suite = {
. cprng = {
. vecs = ansi_cprng_aes_tv_template ,
. count = ANSI_CPRNG_AES_TEST_VECTORS
}
}
} , {
2008-07-31 13:08:25 +04:00
. alg = " cbc(aes) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = aes_cbc_enc_tv_template ,
. count = AES_CBC_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_cbc_dec_tv_template ,
. count = AES_CBC_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " cbc(anubis) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = anubis_cbc_enc_tv_template ,
. count = ANUBIS_CBC_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = anubis_cbc_dec_tv_template ,
. count = ANUBIS_CBC_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " cbc(blowfish) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = bf_cbc_enc_tv_template ,
. count = BF_CBC_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = bf_cbc_dec_tv_template ,
. count = BF_CBC_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " cbc(camellia) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = camellia_cbc_enc_tv_template ,
. count = CAMELLIA_CBC_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = camellia_cbc_dec_tv_template ,
. count = CAMELLIA_CBC_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " cbc(des) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = des_cbc_enc_tv_template ,
. count = DES_CBC_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = des_cbc_dec_tv_template ,
. count = DES_CBC_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " cbc(des3_ede) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = des3_ede_cbc_enc_tv_template ,
. count = DES3_EDE_CBC_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = des3_ede_cbc_dec_tv_template ,
. count = DES3_EDE_CBC_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " cbc(twofish) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = tf_cbc_enc_tv_template ,
. count = TF_CBC_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = tf_cbc_dec_tv_template ,
. count = TF_CBC_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ccm(aes) " ,
. test = alg_test_aead ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. aead = {
. enc = {
. vecs = aes_ccm_enc_tv_template ,
. count = AES_CCM_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_ccm_dec_tv_template ,
. count = AES_CCM_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " crc32c " ,
2008-11-07 09:58:52 +03:00
. test = alg_test_crc32c ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = crc32c_tv_template ,
. count = CRC32C_TEST_VECTORS
}
}
2009-12-23 14:45:20 +03:00
} , {
. alg = " cryptd(__driver-ecb-aes-aesni) " ,
. test = alg_test_null ,
. suite = {
. cipher = {
. enc = {
. vecs = NULL ,
. count = 0
} ,
. dec = {
. vecs = NULL ,
. count = 0
}
}
}
} , {
. alg = " cryptd(__ghash-pclmulqdqni) " ,
. test = alg_test_null ,
. suite = {
. hash = {
. vecs = NULL ,
. count = 0
}
}
2009-05-06 13:29:17 +04:00
} , {
. alg = " ctr(aes) " ,
. test = alg_test_skcipher ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2009-05-06 13:29:17 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = aes_ctr_enc_tv_template ,
. count = AES_CTR_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_ctr_dec_tv_template ,
. count = AES_CTR_DEC_TEST_VECTORS
}
}
}
2008-07-31 13:08:25 +04:00
} , {
. alg = " cts(cbc(aes)) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = cts_mode_enc_tv_template ,
. count = CTS_MODE_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = cts_mode_dec_tv_template ,
. count = CTS_MODE_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " deflate " ,
. test = alg_test_comp ,
. suite = {
. comp = {
. comp = {
. vecs = deflate_comp_tv_template ,
. count = DEFLATE_COMP_TEST_VECTORS
} ,
. decomp = {
. vecs = deflate_decomp_tv_template ,
. count = DEFLATE_DECOMP_TEST_VECTORS
}
}
}
2009-12-23 14:45:20 +03:00
} , {
. alg = " ecb(__aes-aesni) " ,
. test = alg_test_null ,
. suite = {
. cipher = {
. enc = {
. vecs = NULL ,
. count = 0
} ,
. dec = {
. vecs = NULL ,
. count = 0
}
}
}
2008-07-31 13:08:25 +04:00
} , {
. alg = " ecb(aes) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = aes_enc_tv_template ,
. count = AES_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_dec_tv_template ,
. count = AES_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(anubis) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = anubis_enc_tv_template ,
. count = ANUBIS_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = anubis_dec_tv_template ,
. count = ANUBIS_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(arc4) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = arc4_enc_tv_template ,
. count = ARC4_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = arc4_dec_tv_template ,
. count = ARC4_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(blowfish) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = bf_enc_tv_template ,
. count = BF_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = bf_dec_tv_template ,
. count = BF_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(camellia) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = camellia_enc_tv_template ,
. count = CAMELLIA_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = camellia_dec_tv_template ,
. count = CAMELLIA_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(cast5) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = cast5_enc_tv_template ,
. count = CAST5_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = cast5_dec_tv_template ,
. count = CAST5_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(cast6) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = cast6_enc_tv_template ,
. count = CAST6_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = cast6_dec_tv_template ,
. count = CAST6_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(des) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = des_enc_tv_template ,
. count = DES_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = des_dec_tv_template ,
. count = DES_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(des3_ede) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = des3_ede_enc_tv_template ,
. count = DES3_EDE_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = des3_ede_dec_tv_template ,
. count = DES3_EDE_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(khazad) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = khazad_enc_tv_template ,
. count = KHAZAD_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = khazad_dec_tv_template ,
. count = KHAZAD_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(seed) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = seed_enc_tv_template ,
. count = SEED_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = seed_dec_tv_template ,
. count = SEED_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(serpent) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = serpent_enc_tv_template ,
. count = SERPENT_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = serpent_dec_tv_template ,
. count = SERPENT_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(tea) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = tea_enc_tv_template ,
. count = TEA_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = tea_dec_tv_template ,
. count = TEA_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(tnepres) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = tnepres_enc_tv_template ,
. count = TNEPRES_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = tnepres_dec_tv_template ,
. count = TNEPRES_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(twofish) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = tf_enc_tv_template ,
. count = TF_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = tf_dec_tv_template ,
. count = TF_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(xeta) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = xeta_enc_tv_template ,
. count = XETA_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = xeta_dec_tv_template ,
. count = XETA_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " ecb(xtea) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = xtea_enc_tv_template ,
. count = XTEA_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = xtea_dec_tv_template ,
. count = XTEA_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " gcm(aes) " ,
. test = alg_test_aead ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. aead = {
. enc = {
. vecs = aes_gcm_enc_tv_template ,
. count = AES_GCM_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_gcm_dec_tv_template ,
. count = AES_GCM_DEC_TEST_VECTORS
}
}
}
2009-11-23 15:23:04 +03:00
} , {
. alg = " ghash " ,
. test = alg_test_hash ,
crypto: testmgr - mark ghash as fips_allowed
A self-test failure in fips mode means a panic. Well, gcm(aes)
self-tests currently fail in fips mode, as gcm is dependent on ghash,
which semi-recently got self-test vectors added, but wasn't marked as a
fips_allowed algorithm. Because of gcm's dependence on what is now seen
as a non-fips_allowed algorithm, its self-tests refuse to run.
Previously, ghash got a pass in fips mode, due to the lack of any test
vectors at all, and thus gcm self-tests were able to run. After this
patch, a 'modprobe tcrypt mode=35' no longer panics in fips mode, and
successful self-test of gcm(aes) is reported.
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2011-01-29 07:14:35 +03:00
. fips_allowed = 1 ,
2009-11-23 15:23:04 +03:00
. suite = {
. hash = {
. vecs = ghash_tv_template ,
. count = GHASH_TEST_VECTORS
}
}
2008-07-31 13:08:25 +04:00
} , {
. alg = " hmac(md5) " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = hmac_md5_tv_template ,
. count = HMAC_MD5_TEST_VECTORS
}
}
} , {
. alg = " hmac(rmd128) " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = hmac_rmd128_tv_template ,
. count = HMAC_RMD128_TEST_VECTORS
}
}
} , {
. alg = " hmac(rmd160) " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = hmac_rmd160_tv_template ,
. count = HMAC_RMD160_TEST_VECTORS
}
}
} , {
. alg = " hmac(sha1) " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = hmac_sha1_tv_template ,
. count = HMAC_SHA1_TEST_VECTORS
}
}
} , {
. alg = " hmac(sha224) " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = hmac_sha224_tv_template ,
. count = HMAC_SHA224_TEST_VECTORS
}
}
} , {
. alg = " hmac(sha256) " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = hmac_sha256_tv_template ,
. count = HMAC_SHA256_TEST_VECTORS
}
}
} , {
. alg = " hmac(sha384) " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = hmac_sha384_tv_template ,
. count = HMAC_SHA384_TEST_VECTORS
}
}
} , {
. alg = " hmac(sha512) " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = hmac_sha512_tv_template ,
. count = HMAC_SHA512_TEST_VECTORS
}
}
} , {
. alg = " lrw(aes) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = aes_lrw_enc_tv_template ,
. count = AES_LRW_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_lrw_dec_tv_template ,
. count = AES_LRW_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " lzo " ,
. test = alg_test_comp ,
. suite = {
. comp = {
. comp = {
. vecs = lzo_comp_tv_template ,
. count = LZO_COMP_TEST_VECTORS
} ,
. decomp = {
. vecs = lzo_decomp_tv_template ,
. count = LZO_DECOMP_TEST_VECTORS
}
}
}
} , {
. alg = " md4 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = md4_tv_template ,
. count = MD4_TEST_VECTORS
}
}
} , {
. alg = " md5 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = md5_tv_template ,
. count = MD5_TEST_VECTORS
}
}
} , {
. alg = " michael_mic " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = michael_mic_tv_template ,
. count = MICHAEL_MIC_TEST_VECTORS
}
}
} , {
. alg = " pcbc(fcrypt) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = fcrypt_pcbc_enc_tv_template ,
. count = FCRYPT_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = fcrypt_pcbc_dec_tv_template ,
. count = FCRYPT_DEC_TEST_VECTORS
}
}
}
} , {
. alg = " rfc3686(ctr(aes)) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
2009-05-06 13:29:17 +04:00
. vecs = aes_ctr_rfc3686_enc_tv_template ,
. count = AES_CTR_3686_ENC_TEST_VECTORS
2008-07-31 13:08:25 +04:00
} ,
. dec = {
2009-05-06 13:29:17 +04:00
. vecs = aes_ctr_rfc3686_dec_tv_template ,
. count = AES_CTR_3686_DEC_TEST_VECTORS
2008-07-31 13:08:25 +04:00
}
}
}
2009-05-04 15:23:40 +04:00
} , {
2010-11-04 22:02:04 +03:00
. alg = " rfc4106(gcm(aes)) " ,
. test = alg_test_aead ,
. suite = {
. aead = {
. enc = {
. vecs = aes_gcm_rfc4106_enc_tv_template ,
. count = AES_GCM_4106_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_gcm_rfc4106_dec_tv_template ,
. count = AES_GCM_4106_DEC_TEST_VECTORS
}
}
}
} , {
2009-05-04 15:23:40 +04:00
. alg = " rfc4309(ccm(aes)) " ,
. test = alg_test_aead ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2009-05-04 15:23:40 +04:00
. suite = {
. aead = {
. enc = {
. vecs = aes_ccm_rfc4309_enc_tv_template ,
. count = AES_CCM_4309_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_ccm_rfc4309_dec_tv_template ,
. count = AES_CCM_4309_DEC_TEST_VECTORS
}
}
}
2008-07-31 13:08:25 +04:00
} , {
. alg = " rmd128 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = rmd128_tv_template ,
. count = RMD128_TEST_VECTORS
}
}
} , {
. alg = " rmd160 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = rmd160_tv_template ,
. count = RMD160_TEST_VECTORS
}
}
} , {
. alg = " rmd256 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = rmd256_tv_template ,
. count = RMD256_TEST_VECTORS
}
}
} , {
. alg = " rmd320 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = rmd320_tv_template ,
. count = RMD320_TEST_VECTORS
}
}
} , {
. alg = " salsa20 " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = salsa20_stream_enc_tv_template ,
. count = SALSA20_STREAM_ENC_TEST_VECTORS
}
}
}
} , {
. alg = " sha1 " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = sha1_tv_template ,
. count = SHA1_TEST_VECTORS
}
}
} , {
. alg = " sha224 " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = sha224_tv_template ,
. count = SHA224_TEST_VECTORS
}
}
} , {
. alg = " sha256 " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = sha256_tv_template ,
. count = SHA256_TEST_VECTORS
}
}
} , {
. alg = " sha384 " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = sha384_tv_template ,
. count = SHA384_TEST_VECTORS
}
}
} , {
. alg = " sha512 " ,
. test = alg_test_hash ,
2009-05-15 09:16:03 +04:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. hash = {
. vecs = sha512_tv_template ,
. count = SHA512_TEST_VECTORS
}
}
} , {
. alg = " tgr128 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = tgr128_tv_template ,
. count = TGR128_TEST_VECTORS
}
}
} , {
. alg = " tgr160 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = tgr160_tv_template ,
. count = TGR160_TEST_VECTORS
}
}
} , {
. alg = " tgr192 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = tgr192_tv_template ,
. count = TGR192_TEST_VECTORS
}
}
2009-09-02 14:05:22 +04:00
} , {
. alg = " vmac(aes) " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = aes_vmac128_tv_template ,
. count = VMAC_AES_TEST_VECTORS
}
}
2008-07-31 13:08:25 +04:00
} , {
. alg = " wp256 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = wp256_tv_template ,
. count = WP256_TEST_VECTORS
}
}
} , {
. alg = " wp384 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = wp384_tv_template ,
. count = WP384_TEST_VECTORS
}
}
} , {
. alg = " wp512 " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = wp512_tv_template ,
. count = WP512_TEST_VECTORS
}
}
} , {
. alg = " xcbc(aes) " ,
. test = alg_test_hash ,
. suite = {
. hash = {
. vecs = aes_xcbc128_tv_template ,
. count = XCBC_AES_TEST_VECTORS
}
}
} , {
. alg = " xts(aes) " ,
2008-08-17 11:01:56 +04:00
. test = alg_test_skcipher ,
2011-01-29 07:14:01 +03:00
. fips_allowed = 1 ,
2008-07-31 13:08:25 +04:00
. suite = {
. cipher = {
. enc = {
. vecs = aes_xts_enc_tv_template ,
. count = AES_XTS_ENC_TEST_VECTORS
} ,
. dec = {
. vecs = aes_xts_dec_tv_template ,
. count = AES_XTS_DEC_TEST_VECTORS
}
}
}
2009-03-04 10:42:15 +03:00
} , {
. alg = " zlib " ,
. test = alg_test_pcomp ,
. suite = {
. pcomp = {
. comp = {
. vecs = zlib_comp_tv_template ,
. count = ZLIB_COMP_TEST_VECTORS
} ,
. decomp = {
. vecs = zlib_decomp_tv_template ,
. count = ZLIB_DECOMP_TEST_VECTORS
}
}
}
2008-07-31 13:08:25 +04:00
}
} ;
2008-08-17 11:01:56 +04:00
static int alg_find_test ( const char * alg )
2008-07-31 13:08:25 +04:00
{
int start = 0 ;
int end = ARRAY_SIZE ( alg_test_descs ) ;
while ( start < end ) {
int i = ( start + end ) / 2 ;
int diff = strcmp ( alg_test_descs [ i ] . alg , alg ) ;
if ( diff > 0 ) {
end = i ;
continue ;
}
if ( diff < 0 ) {
start = i + 1 ;
continue ;
}
2008-08-17 11:01:56 +04:00
return i ;
}
return - 1 ;
}
int alg_test ( const char * driver , const char * alg , u32 type , u32 mask )
{
int i ;
2009-07-02 12:32:12 +04:00
int j ;
2008-10-12 16:36:51 +04:00
int rc ;
2008-08-17 11:01:56 +04:00
if ( ( type & CRYPTO_ALG_TYPE_MASK ) = = CRYPTO_ALG_TYPE_CIPHER ) {
char nalg [ CRYPTO_MAX_ALG_NAME ] ;
if ( snprintf ( nalg , sizeof ( nalg ) , " ecb(%s) " , alg ) > =
sizeof ( nalg ) )
return - ENAMETOOLONG ;
i = alg_find_test ( nalg ) ;
if ( i < 0 )
goto notest ;
2009-05-15 09:17:05 +04:00
if ( fips_enabled & & ! alg_test_descs [ i ] . fips_allowed )
goto non_fips_alg ;
2009-05-04 15:49:23 +04:00
rc = alg_test_cipher ( alg_test_descs + i , driver , type , mask ) ;
goto test_done ;
2008-07-31 13:08:25 +04:00
}
2008-08-17 11:01:56 +04:00
i = alg_find_test ( alg ) ;
2009-07-02 12:32:12 +04:00
j = alg_find_test ( driver ) ;
if ( i < 0 & & j < 0 )
2008-08-17 11:01:56 +04:00
goto notest ;
2009-07-02 12:32:12 +04:00
if ( fips_enabled & & ( ( i > = 0 & & ! alg_test_descs [ i ] . fips_allowed ) | |
( j > = 0 & & ! alg_test_descs [ j ] . fips_allowed ) ) )
2009-05-15 09:17:05 +04:00
goto non_fips_alg ;
2009-07-02 12:32:12 +04:00
rc = 0 ;
if ( i > = 0 )
rc | = alg_test_descs [ i ] . test ( alg_test_descs + i , driver ,
type , mask ) ;
if ( j > = 0 )
rc | = alg_test_descs [ j ] . test ( alg_test_descs + j , driver ,
type , mask ) ;
2009-05-04 15:49:23 +04:00
test_done :
2008-10-12 16:36:51 +04:00
if ( fips_enabled & & rc )
panic ( " %s: %s alg self test failed in fips mode! \n " , driver , alg ) ;
2009-05-04 15:51:17 +04:00
if ( fips_enabled & & ! rc )
printk ( KERN_INFO " alg: self-tests for %s (%s) passed \n " ,
driver , alg ) ;
2008-10-12 16:36:51 +04:00
return rc ;
2008-08-17 11:01:56 +04:00
notest :
2008-07-31 13:08:25 +04:00
printk ( KERN_INFO " alg: No test for %s (%s) \n " , alg , driver ) ;
return 0 ;
2009-05-15 09:17:05 +04:00
non_fips_alg :
return - EINVAL ;
2008-07-31 13:08:25 +04:00
}
2010-06-03 14:53:43 +04:00
2010-08-06 05:40:28 +04:00
# endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
2010-06-03 14:53:43 +04:00
2008-07-31 13:08:25 +04:00
EXPORT_SYMBOL_GPL ( alg_test ) ;