@@ -902,38 +902,65 @@ struct wc_swallow_the_semicolon
902902#include <wolfssl/wolfcrypt/random.h>
903903
904904struct wc_linuxkm_drbg_ctx {
905- wolfSSL_Mutex lock ;
906- WC_RNG rng ;
905+ struct wc_rng_inst {
906+ wolfSSL_Mutex lock ;
907+ WC_RNG rng ;
908+ } * rngs ; /* one per CPU ID */
907909};
908910
909911static int wc_linuxkm_drbg_init_tfm (struct crypto_tfm * tfm )
910912{
911913 struct wc_linuxkm_drbg_ctx * ctx = (struct wc_linuxkm_drbg_ctx * )crypto_tfm_ctx (tfm );
914+ unsigned int i ;
912915 int ret ;
913916
914- ret = wc_InitMutex (& ctx -> lock );
915- if (ret != 0 )
916- return - EINVAL ;
917+ ctx -> rngs = (struct wc_rng_inst * )malloc (sizeof (* ctx -> rngs ) * nr_cpu_ids );
918+ if (! ctx -> rngs )
919+ return - ENOMEM ;
920+ XMEMSET (ctx -> rngs , 0 , sizeof (* ctx -> rngs ) * nr_cpu_ids );
921+
922+ for (i = 0 ; i < nr_cpu_ids ; ++ i ) {
923+ ret = wc_InitMutex (& ctx -> rngs [i ].lock );
924+ if (ret != 0 ) {
925+ ret = - EINVAL ;
926+ break ;
927+ }
928+
929+ /* Note the new DRBG instance is seeded, and later reseeded, from system
930+ * get_random_bytes() via wc_GenerateSeed().
931+ */
932+ ret = wc_InitRng (& ctx -> rngs [i ].rng );
933+ if (ret != 0 ) {
934+ ret = - EINVAL ;
935+ break ;
936+ }
937+ }
917938
918- /* Note the new DRBG instance is seeded, and later reseeded, from system
919- * get_random_bytes() via wc_GenerateSeed().
920- */
921- ret = wc_InitRng (& ctx -> rng );
922939 if (ret != 0 ) {
923- (void )wc_FreeMutex (& ctx -> lock );
924- return - EINVAL ;
940+ for (i = 0 ; i < nr_cpu_ids ; ++ i ) {
941+ (void )wc_FreeMutex (& ctx -> rngs [i ].lock );
942+ wc_FreeRng (& ctx -> rngs [i ].rng );
943+ }
944+ free (ctx -> rngs );
945+ ctx -> rngs = NULL ;
925946 }
926947
927- return 0 ;
948+ return ret ;
928949}
929950
930951static void wc_linuxkm_drbg_exit_tfm (struct crypto_tfm * tfm )
931952{
932953 struct wc_linuxkm_drbg_ctx * ctx = (struct wc_linuxkm_drbg_ctx * )crypto_tfm_ctx (tfm );
954+ unsigned int i ;
933955
934- wc_FreeRng (& ctx -> rng );
935-
936- (void )wc_FreeMutex (& ctx -> lock );
956+ if (ctx -> rngs ) {
957+ for (i = 0 ; i < nr_cpu_ids ; ++ i ) {
958+ (void )wc_FreeMutex (& ctx -> rngs [i ].lock );
959+ wc_FreeRng (& ctx -> rngs [i ].rng );
960+ }
961+ free (ctx -> rngs );
962+ ctx -> rngs = NULL ;
963+ }
937964
938965 return ;
939966}
@@ -944,24 +971,33 @@ static int wc_linuxkm_drbg_generate(struct crypto_rng *tfm,
944971{
945972 struct wc_linuxkm_drbg_ctx * ctx = (struct wc_linuxkm_drbg_ctx * )crypto_rng_ctx (tfm );
946973 int ret ;
974+ /* Note, core is not locked, so the actual core ID may change while
975+ * executing, hence the mutex.
976+ * The mutex is also needed to coordinate with wc_linuxkm_drbg_seed(), which
977+ * seeds all instances.
978+ */
979+ int my_cpu = raw_smp_processor_id ();
980+ wolfSSL_Mutex * lock = & ctx -> rngs [my_cpu ].lock ;
981+ WC_RNG * rng = & ctx -> rngs [my_cpu ].rng ;
947982
948- wc_LockMutex (& ctx -> lock );
983+ if (wc_LockMutex (lock ) != 0 )
984+ return - EINVAL ;
949985
950986 if (slen > 0 ) {
951- ret = wc_RNG_DRBG_Reseed (& ctx -> rng , src , slen );
987+ ret = wc_RNG_DRBG_Reseed (rng , src , slen );
952988 if (ret != 0 ) {
953989 ret = - EINVAL ;
954990 goto out ;
955991 }
956992 }
957993
958- ret = wc_RNG_GenerateBlock (& ctx -> rng , dst , dlen );
994+ ret = wc_RNG_GenerateBlock (rng , dst , dlen );
959995 if (ret != 0 )
960996 ret = - EINVAL ;
961997
962998out :
963999
964- wc_UnLockMutex (& ctx -> lock );
1000+ wc_UnLockMutex (lock );
9651001
9661002 return ret ;
9671003}
@@ -970,22 +1006,43 @@ static int wc_linuxkm_drbg_seed(struct crypto_rng *tfm,
9701006 const u8 * seed , unsigned int slen )
9711007{
9721008 struct wc_linuxkm_drbg_ctx * ctx = (struct wc_linuxkm_drbg_ctx * )crypto_rng_ctx (tfm );
1009+ u8 * seed_copy = NULL ;
9731010 int ret ;
1011+ unsigned int i ;
9741012
9751013 if (slen == 0 )
9761014 return 0 ;
9771015
978- wc_LockMutex (& ctx -> lock );
1016+ seed_copy = (u8 * )malloc (slen + 2 );
1017+ if (! seed_copy )
1018+ return - ENOMEM ;
1019+ XMEMCPY (seed_copy + 2 , seed , slen );
9791020
980- ret = wc_RNG_DRBG_Reseed (& ctx -> rng , seed , slen );
981- if (ret != 0 ) {
982- ret = - EINVAL ;
983- goto out ;
984- }
1021+ for (i = 0 ; i < nr_cpu_ids ; ++ i ) {
1022+ wolfSSL_Mutex * lock = & ctx -> rngs [i ].lock ;
1023+ WC_RNG * rng = & ctx -> rngs [i ].rng ;
9851024
986- out :
1025+ /* perturb the seed with the CPU ID, so that no DRBG has the exact same
1026+ * seed.
1027+ */
1028+ seed_copy [0 ] = (u8 )(i >> 8 );
1029+ seed_copy [1 ] = (u8 )i ;
1030+
1031+ if (wc_LockMutex (lock ) != 0 )
1032+ return - EINVAL ;
1033+
1034+ ret = wc_RNG_DRBG_Reseed (rng , seed_copy , slen + 2 );
1035+ if (ret != 0 ) {
1036+ ret = - EINVAL ;
1037+ }
1038+
1039+ wc_UnLockMutex (lock );
1040+
1041+ if (ret != 0 )
1042+ break ;
1043+ }
9871044
988- wc_UnLockMutex ( & ctx -> lock );
1045+ free ( seed_copy );
9891046
9901047 return ret ;
9911048}
0 commit comments