lopy4/components/hash-sigs-master/hss_verify_inc.c
/*
 * Start the process of validating an HSS signature incrementally. Parameters:
 * ctx - The state we'll use to track the incremental validation
 * public_key - pointer to the public key
 * siganture - the signature we're checking
 * signature_len - the length of the signature
 */
Start the process of validating an HSS signature incrementally. Parameters:
ctx - The state we'll use to track the incremental validation
public_key - pointer to the public key
siganture - the signature we're checking
signature_len - the length of the signature
Start the process of validating an HSS signature incrementally . Parameters : ctx - The state we ' ll use to track the incremental validation public_key - pointer to the public key siganture - the signature we ' re checking signature_len - the length of the signature
bool hss_validate_signature_init(
    struct hss_validate_inc *ctx,
    const unsigned char *public_key,
    const unsigned char *signature, size_t signature_len,
    struct hss_extra_info *info) {
    struct hss_extra_info temp_info = { 0 };
    if (!info) info = &temp_info;
    unsigned i;
    if (!ctx) {
        info->error_code = hss_error_got_null;
        return false;
    }
    ctx->status = hss_error_ctx_uninitialized; 
    const unsigned char *orig_signature = signature;
;
    if (signature_len < 4) {
        ctx->status = info->error_code = hss_error_bad_signature;
        return false;
    }
    uint_fast32_t levels = get_bigendian( signature, 4 ) + 1;
    signature += 4; signature_len -= 4;
    if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS ||
                               levels != get_bigendian( public_key, 4 )) {
        ctx->status = info->error_code = hss_error_bad_signature;
        return false;
    }
    uint_fast32_t pub_levels = get_bigendian( public_key, 4 );
    if (levels != pub_levels) {
        ctx->status = info->error_code = hss_error_bad_signature;
        return false;
    }
    public_key += 4;
    struct thread_collection *col = NULL;
    if (levels > 1) {
        col = hss_thread_init(info->num_threads);
        enum hss_error_code got_error = hss_error_none;
        struct verify_detail detail;
        detail.got_error = &got_error;
        for (i=0; i<levels-1; i++) { 
            param_set_t lm_type = get_bigendian( public_key, 4 );
            param_set_t lm_ots_type = get_bigendian( public_key+4, 4 );
            unsigned l_siglen = lm_get_signature_len(lm_type, lm_ots_type);
            if (l_siglen == 0 || l_siglen > signature_len) goto failed;
            const unsigned char *l_sig = signature;
            signature += l_siglen; signature_len -= l_siglen;
            if (signature_len < 4) goto failed;
            lm_type = get_bigendian( signature, 4 );
            unsigned l_pubkeylen = lm_get_public_key_len(lm_type);
            if (l_pubkeylen == 0 || l_pubkeylen > signature_len) goto failed;
            const unsigned char *l_pubkey = signature;
            signature += l_pubkeylen; signature_len -= l_pubkeylen;
            detail.public_key = public_key;
            detail.message = l_pubkey;
            detail.message_len = l_pubkeylen;
            detail.signature = l_sig;
            detail.signature_len = l_siglen;
            hss_thread_issue_work( col, validate_internal_sig,
                                   &detail, sizeof detail );
            public_key = l_pubkey;
        }
        hss_thread_done(col);
        col = NULL;
        if (got_error != hss_error_none) {
            ctx->status = info->error_code = got_error;
            return false;
        }
    }
    ctx->signature_offset = signature - orig_signature;
    ctx->signature_len = signature_len;
    memcpy( ctx->final_public_key, public_key, 8 + I_LEN + MAX_HASH );
    param_set_t ots_type = get_bigendian( public_key+4, 4 );
    unsigned h, n;
    if (!lm_ots_look_up_parameter_set(ots_type, &h, &n, NULL, NULL, NULL)) {
        ctx->status = info->error_code = hss_error_bad_signature;
        return false;
    }
    ctx->h = h;
    hss_init_hash_context( h, &ctx->hash_ctx );
    {
        unsigned char prefix[ MESG_PREFIX_MAXLEN ];
        memcpy( prefix + MESG_I, ctx->final_public_key+8, I_LEN );
        memcpy( prefix + MESG_Q, signature, 4 ); 
        SET_D( prefix + MESG_D, D_MESG );
        memcpy( prefix + MESG_C, signature+8, n );  
        hss_update_hash_context(h, &ctx->hash_ctx, prefix, MESG_PREFIX_LEN(n) );
    }
    ctx->status = hss_error_none;
    return true;
failed:           
    if (col) hss_thread_done(col);
    ctx->status = info->error_code = hss_error_bad_signature;
    return false;
}
bool hss_validate_signature_init ( struct hss_validate_inc * ctx , const unsigned char * public_key , const unsigned char * signature , size_t signature_len , struct hss_extra_info * info ) { struct hss_extra_info temp_info = { 0 } ; if ( ! info ) info = & temp_info ; unsigned i ; if ( ! ctx ) { info -> error_code = hss_error_got_null ; return false ; } ctx -> status = hss_error_ctx_uninitialized ; const unsigned char * orig_signature = signature ; ; if ( signature_len < 4 ) { ctx -> status = info -> error_code = hss_error_bad_signature ; return false ; } uint_fast32_t levels = get_bigendian ( signature , 4 ) + 1 ; signature += 4 ; signature_len -= 4 ; if ( levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS || levels != get_bigendian ( public_key , 4 ) ) { ctx -> status = info -> error_code = hss_error_bad_signature ; return false ; } uint_fast32_t pub_levels = get_bigendian ( public_key , 4 ) ; if ( levels != pub_levels ) { ctx -> status = info -> error_code = hss_error_bad_signature ; return false ; } public_key += 4 ; struct thread_collection * col = NULL ; if ( levels > 1 ) { col = hss_thread_init ( info -> num_threads ) ; enum hss_error_code got_error = hss_error_none ; struct verify_detail detail ; detail . got_error = & got_error ; for ( i = 0 ; i < levels - 1 ; i ++ ) { param_set_t lm_type = get_bigendian ( public_key , 4 ) ; param_set_t lm_ots_type = get_bigendian ( public_key + 4 , 4 ) ; unsigned l_siglen = lm_get_signature_len ( lm_type , lm_ots_type ) ; if ( l_siglen == 0 || l_siglen > signature_len ) goto failed ; const unsigned char * l_sig = signature ; signature += l_siglen ; signature_len -= l_siglen ; if ( signature_len < 4 ) goto failed ; lm_type = get_bigendian ( signature , 4 ) ; unsigned l_pubkeylen = lm_get_public_key_len ( lm_type ) ; if ( l_pubkeylen == 0 || l_pubkeylen > signature_len ) goto failed ; const unsigned char * l_pubkey = signature ; signature += l_pubkeylen ; signature_len -= l_pubkeylen ; detail . public_key = public_key ; detail . message = l_pubkey ; detail . message_len = l_pubkeylen ; detail . signature = l_sig ; detail . signature_len = l_siglen ; hss_thread_issue_work ( col , validate_internal_sig , & detail , sizeof detail ) ; public_key = l_pubkey ; } hss_thread_done ( col ) ; col = NULL ; if ( got_error != hss_error_none ) { ctx -> status = info -> error_code = got_error ; return false ; } } ctx -> signature_offset = signature - orig_signature ; ctx -> signature_len = signature_len ; memcpy ( ctx -> final_public_key , public_key , 8 + I_LEN + MAX_HASH ) ; param_set_t ots_type = get_bigendian ( public_key + 4 , 4 ) ; unsigned h , n ; if ( ! lm_ots_look_up_parameter_set ( ots_type , & h , & n , NULL , NULL , NULL ) ) { ctx -> status = info -> error_code = hss_error_bad_signature ; return false ; } ctx -> h = h ; hss_init_hash_context ( h , & ctx -> hash_ctx ) ; { unsigned char prefix [ MESG_PREFIX_MAXLEN ] ; memcpy ( prefix + MESG_I , ctx -> final_public_key + 8 , I_LEN ) ; memcpy ( prefix + MESG_Q , signature , 4 ) ; SET_D ( prefix + MESG_D , D_MESG ) ; memcpy ( prefix + MESG_C , signature + 8 , n ) ; hss_update_hash_context ( h , & ctx -> hash_ctx , prefix , MESG_PREFIX_LEN ( n ) ) ; } ctx -> status = hss_error_none ; return true ; failed : if ( col ) hss_thread_done ( col ) ; ctx -> status = info -> error_code = hss_error_bad_signature ; return false ; }
Start the process of validating an HSS signature incrementally.
Start the process of validating an HSS signature incrementally .
/* Until we hear otherwise, */ /* we got a failure */ /* Get the number of levels the signature claims */ /* +1 because what's in the signature is levels-1 */ /* Signature and public key don't agree */ /* Validate the upper levels of the signature */ /* Scan through the signature, kicking off the tasks to validate it */ /* as we go.  Note that we don't validate the bottom level yet */ /* The next thing is the signature of this public key */ /* The next thing is the next level public key (which we need */ /* to validate) */ /* Validate the signature of this level's public key */ /* We validated this level's public key (or, at least, */ /* scheduled it, if it turns out not to validate, we'll catch */ /* it below), use it to validate the next level */ /* Wait for all the threads to complete */ /* We have the public key in front of us; stash a copy */ /* Right now, we have a fixed length public key */ /* If that changes, we'll need to investigate the parmaeter set */ /* Now, initialize the context */ /* Because we're checking in parallel, this may be caused by */ /* a bad signature */ /* q */ /* C */ /* It succeeded so far... */ /* If we get an intermediate failure */