@@ -418,6 +418,11 @@ REG32(LC_STATE, 2008u)
418418#define DAI_DIGEST_DELAY_NS 50000u /* 50us */
419419#define LCI_PROG_SCHED_NS 1000u /* 1us*/
420420
421+ /* The size of keys used for OTP scrambling */
422+ #define OTP_SCRAMBLING_KEY_WIDTH 128u
423+ #define OTP_SCRAMBLING_KEY_BYTES ((OTP_SCRAMBLING_KEY_WIDTH) / 8u)
424+
425+ /* Sizes of constants used for deriving scrambling keys (e.g. flash, SRAM) */
421426#define FLASH_KEY_SEED_WIDTH 256u
422427#define SRAM_KEY_SEED_WIDTH 128u
423428#define KEY_MGR_KEY_WIDTH 256u
@@ -682,6 +687,8 @@ struct OtOTPEgState {
682687 uint8_t flash_data_const [16u ];
683688 uint64_t flash_addr_iv ;
684689 uint8_t flash_addr_const [16u ];
690+ /* OTP scrambling key constants, not constants for deriving other keys */
691+ uint8_t * otp_scramble_keys [ARRAY_SIZE (OtOTPPartDescs )]; /* may be NULL */
685692 uint8_t * inv_default_parts [ARRAY_SIZE (OtOTPPartDescs )]; /* may be NULL */
686693
687694 OtOTPStorage * otp ;
@@ -703,6 +710,7 @@ struct OtOTPEgState {
703710 char * flash_data_const_xstr ;
704711 char * flash_addr_iv_xstr ;
705712 char * flash_addr_const_xstr ;
713+ char * otp_scramble_key_xstrs [ARRAY_SIZE (OtOTPPartDescs )]; /* may be NULL */
706714 char * inv_default_part_xstrs [ARRAY_SIZE (OtOTPPartDescs )]; /* may be NULL */
707715 uint8_t edn_ep ;
708716 bool fatal_escalate ;
@@ -3724,6 +3732,65 @@ static void ot_otp_eg_configure_sram(OtOTPEgState *s)
37243732 s -> sram_iv = ldq_le_p (sram_iv );
37253733}
37263734
3735+ static void ot_otp_eg_configure_part_scramble_keys (OtOTPEgState * s )
3736+ {
3737+ for (unsigned ix = 0u ; ix < ARRAY_SIZE (OtOTPPartDescs ); ix ++ ) {
3738+ if (!s -> otp_scramble_key_xstrs [ix ]) {
3739+ continue ;
3740+ }
3741+
3742+ size_t len = strlen (s -> otp_scramble_key_xstrs [ix ]);
3743+ if (len != OTP_SCRAMBLING_KEY_BYTES * 2u ) {
3744+ error_setg (
3745+ & error_fatal ,
3746+ "%s: %s Invalid OTP scrambling key length %zu for partition %u" ,
3747+ __func__ , s -> ot_id , len , ix );
3748+ return ;
3749+ }
3750+
3751+ g_assert (!s -> otp_scramble_keys [ix ]);
3752+
3753+ s -> otp_scramble_keys [ix ] = g_new0 (uint8_t , OTP_SCRAMBLING_KEY_BYTES );
3754+ if (ot_common_parse_hexa_str (s -> otp_scramble_keys [ix ],
3755+ s -> otp_scramble_key_xstrs [ix ],
3756+ OTP_SCRAMBLING_KEY_BYTES , true, true)) {
3757+ error_setg (& error_fatal ,
3758+ "%s: %s unable to parse otp_scramble_keys[%u]" , __func__ ,
3759+ s -> ot_id , ix );
3760+ return ;
3761+ }
3762+
3763+ TRACE_OTP ("otp_scramble_keys[%s] %s" , PART_NAME (ix ),
3764+ ot_otp_hexdump (s , s -> otp_scramble_keys [ix ],
3765+ OTP_SCRAMBLING_KEY_BYTES ));
3766+ }
3767+ }
3768+
3769+ static void ot_otp_eg_class_add_scramble_key_props (OtOTPClass * odc )
3770+ {
3771+ unsigned secret_ix = 0u ;
3772+ for (unsigned ix = 0u ; ix < ARRAY_SIZE (OtOTPPartDescs ); ix ++ ) {
3773+ if (!OtOTPPartDescs [ix ].secret ) {
3774+ continue ;
3775+ }
3776+
3777+ Property * prop = g_new0 (Property , 1u );
3778+
3779+ /*
3780+ * Assumes secret partitions are sequentially ordered and named
3781+ * SECRET0, SECRET1, SECRET2, etc.
3782+ */
3783+ prop -> name = g_strdup_printf ("secret%u_scramble_key" , secret_ix ++ );
3784+ prop -> info = & qdev_prop_string ;
3785+ prop -> offset = offsetof(OtOTPEgState , otp_scramble_key_xstrs ) +
3786+ sizeof (char * ) * ix ;
3787+
3788+ object_class_property_add (OBJECT_CLASS (odc ), prop -> name ,
3789+ prop -> info -> name , prop -> info -> get ,
3790+ prop -> info -> set , prop -> info -> release , prop );
3791+ }
3792+ }
3793+
37273794static void ot_otp_eg_configure_inv_default_parts (OtOTPEgState * s )
37283795{
37293796 for (unsigned ix = 0 ; ix < ARRAY_SIZE (OtOTPPartDescs ); ix ++ ) {
@@ -3943,6 +4010,7 @@ static void ot_otp_eg_realize(DeviceState *dev, Error **errp)
39434010 ot_otp_eg_configure_digest (s );
39444011 ot_otp_eg_configure_sram (s );
39454012 ot_otp_eg_configure_flash (s );
4013+ ot_otp_eg_configure_part_scramble_keys (s );
39464014 ot_otp_eg_configure_inv_default_parts (s );
39474015}
39484016
@@ -4050,6 +4118,7 @@ static void ot_otp_eg_class_init(ObjectClass *klass, void *data)
40504118 oc -> get_keymgr_secret = & ot_otp_eg_get_keymgr_secret ;
40514119 oc -> program_req = & ot_otp_eg_program_req ;
40524120
4121+ ot_otp_eg_class_add_scramble_key_props (oc );
40534122 ot_otp_eg_class_add_inv_def_props (oc );
40544123}
40554124
0 commit comments