lopy4/components/hash-sigs-master/hss_param.c
/*
 * This returns the parameter set for a given private key.
 * This is here to solve a chicken-and-egg problem: the hss_working_key
 * must be initialized to the same parameter set as the private key,
 * but (other than this function, or somehow remembering it) there's
 * no way to retreive the parameter set.
 *
 * read_private_key/context will read the private key (if read_private_key is
 * NULL, context is assumed to point to the private key)
 *
 * On success, *levels will be set to the number of levels, and lm_type[]
 * and lm_ots_type[] will be set to the lm/ots parameter sets
 *
 * On success, this returns true; on failure (can't read the private key, or
 * the private key is invalid), returns false 
 */
This returns the parameter set for a given private key.
This is here to solve a chicken-and-egg problem: the hss_working_key
must be initialized to the same parameter set as the private key,
but (other than this function, or somehow remembering it) there's
no way to retreive the parameter set.

read_private_key/context will read the private key (if read_private_key is
NULL, context is assumed to point to the private key)

On success, *levels will be set to the number of levels, and lm_type[]
and lm_ots_type[] will be set to the lm/ots parameter sets

On success, this returns true; on failure (can't read the private key, or
the private key is invalid), returns false
This returns the parameter set for a given private key . This is here to solve a chicken - and - egg problem : the hss_working_key must be initialized to the same parameter set as the private key but ( other than this function or somehow remembering it ) there ' s no way to retreive the parameter set . read_private_key / context will read the private key ( if read_private_key is NULL context is assumed to point to the private key ) On success * levels will be set to the number of levels and lm_type [] and lm_ots_type [] will be set to the lm / ots parameter sets On success this returns true ; on failure ( can ' t read the private key or the private key is invalid ) returns false
bool hss_get_parameter_set( unsigned *levels,
                           param_set_t lm_type[ MAX_HSS_LEVELS ],
                           param_set_t lm_ots_type[ MAX_HSS_LEVELS ],
                           bool (*read_private_key)(unsigned char *private_key,
                                       size_t len_private_key, void *context),
                           void *context) {
    unsigned char private_key[ PRIVATE_KEY_LEN ];
    bool success = false;
    if (read_private_key) {
        if (!read_private_key( private_key, PRIVATE_KEY_SEED, context )) {
            goto failed;
        }
    } else {
        if (!context) return false;
        memcpy( private_key, context, PRIVATE_KEY_SEED );
    }
    unsigned total_height = 0;
    unsigned level;
    for (level=0; level < MAX_HSS_LEVELS; level++) {
        unsigned char c = private_key[PRIVATE_KEY_PARAM_SET + level];
        if (c == PARM_SET_END) break;
        param_set_t lm = (c >> 4);
        param_set_t ots = (c & 0x0f);
        switch (lm) {
        case LMS_SHA256_N32_H5:  total_height += 5; break;
        case LMS_SHA256_N32_H10: total_height += 10; break;
        case LMS_SHA256_N32_H15: total_height += 15; break;
        case LMS_SHA256_N32_H20: total_height += 20; break;
        case LMS_SHA256_N32_H25: total_height += 25; break;
        default: goto failed;
        }
        switch (ots) {
        case LMOTS_SHA256_N32_W1:
        case LMOTS_SHA256_N32_W2:
        case LMOTS_SHA256_N32_W4:
        case LMOTS_SHA256_N32_W8:
            break;
        default: goto failed;
        }
        lm_type[level] = lm;
        lm_ots_type[level] = ots;
    }
    if (level < MIN_HSS_LEVELS || level > MAX_HSS_LEVELS) goto failed;
    *levels = level;
    unsigned i;
    for (i = level+1; i<MAX_HSS_LEVELS; i++) {
        unsigned char c = private_key[PRIVATE_KEY_PARAM_SET + i];
        if (c != PARM_SET_END) goto failed;
    }
    if (total_height > 64) total_height = 64; 
    sequence_t max_count = ((sequence_t)2 << (total_height-1)) - 1;
    if (total_height == 64) max_count--;
    sequence_t current_count = get_bigendian(
                 private_key + PRIVATE_KEY_INDEX, PRIVATE_KEY_INDEX_LEN );
    if (current_count > max_count) goto failed;  
    success = true;   
failed:
    hss_zeroize( private_key, sizeof private_key );
    return success;
}
bool hss_get_parameter_set ( unsigned * levels , param_set_t lm_type [ MAX_HSS_LEVELS ] , param_set_t lm_ots_type [ MAX_HSS_LEVELS ] , bool ( * read_private_key ) ( unsigned char * private_key , size_t len_private_key , void * context ) , void * context ) { unsigned char private_key [ PRIVATE_KEY_LEN ] ; bool success = false ; if ( read_private_key ) { if ( ! read_private_key ( private_key , PRIVATE_KEY_SEED , context ) ) { goto failed ; } } else { if ( ! context ) return false ; memcpy ( private_key , context , PRIVATE_KEY_SEED ) ; } unsigned total_height = 0 ; unsigned level ; for ( level = 0 ; level < MAX_HSS_LEVELS ; level ++ ) { unsigned char c = private_key [ PRIVATE_KEY_PARAM_SET + level ] ; if ( c == PARM_SET_END ) break ; param_set_t lm = ( c >> 4 ) ; param_set_t ots = ( c & 0x0f ) ; switch ( lm ) { case LMS_SHA256_N32_H5 : total_height += 5 ; break ; case LMS_SHA256_N32_H10 : total_height += 10 ; break ; case LMS_SHA256_N32_H15 : total_height += 15 ; break ; case LMS_SHA256_N32_H20 : total_height += 20 ; break ; case LMS_SHA256_N32_H25 : total_height += 25 ; break ; default : goto failed ; } switch ( ots ) { case LMOTS_SHA256_N32_W1 : case LMOTS_SHA256_N32_W2 : case LMOTS_SHA256_N32_W4 : case LMOTS_SHA256_N32_W8 : break ; default : goto failed ; } lm_type [ level ] = lm ; lm_ots_type [ level ] = ots ; } if ( level < MIN_HSS_LEVELS || level > MAX_HSS_LEVELS ) goto failed ; * levels = level ; unsigned i ; for ( i = level + 1 ; i < MAX_HSS_LEVELS ; i ++ ) { unsigned char c = private_key [ PRIVATE_KEY_PARAM_SET + i ] ; if ( c != PARM_SET_END ) goto failed ; } if ( total_height > 64 ) total_height = 64 ; sequence_t max_count = ( ( sequence_t ) 2 << ( total_height - 1 ) ) - 1 ; if ( total_height == 64 ) max_count -- ; sequence_t current_count = get_bigendian ( private_key + PRIVATE_KEY_INDEX , PRIVATE_KEY_INDEX_LEN ) ; if ( current_count > max_count ) goto failed ; success = true ; failed : hss_zeroize ( private_key , sizeof private_key ) ; return success ; }
This returns the parameter set for a given private key.
This returns the parameter set for a given private key .
/* Scan through the private key to recover the parameter sets */ /* Decode this level's parameter set */ /* Make sure both are supported */ /* While we're here, add up the total Merkle height */ /* Make sure that the rest of the private key has PARM_SET_END */ /* One final check; make sure that the sequence number listed in the */ /* private key is in range */ /* (bounded by 2**64) */ /* height-1 so we don't try to shift by 64, and hit U.B. */ /* We use the count 0xffff..ffff to signify 'we've used up all our */ /* signatures'.  Make sure that is above max_count, even for */ /* parameter sets that can literally generate 2**64 signatures (by */ /* letting them generate only 2**64-1) */ /* Private key expired */ /* It worked! */ /* There might be private keying material here */