/* check if nonce-count nc w/ index i is expected/valid and if so it * updated the stored nonce-count * returns: 0 - ok, < 0 some error: * NC_INV_POOL (pool number is invalid/corrupted) * NC_ID_OVERFLOW (crt_id has overflowed with partition size since the * id was generated) * NC_TOO_BIG (nc value got too big and cannot be held anymore) * NC_REPLAY (nc value is <= the current stored one) */ enum nc_check_ret nc_check_val(nid_t id, unsigned pool, unsigned int nc) { unsigned int i; unsigned n, r; unsigned int v, crt_nc, new_v; if (unlikely(pool>=nid_pool_no)) return NC_INV_POOL; if (unlikely(nc_id_check_overflow(id, pool))) return NC_ID_OVERFLOW; if (unlikely(nc>=(1U<<(sizeof(nc_t)*8)))) return NC_TOO_BIG; n=get_nc_array_raw_idx(id, pool); /* n-th nc_t */ i=get_nc_array_uint_idx(n); /* aray index i, corresponding to n */ r=get_nc_int_pos(n); /* byte/short inside the uint corresponding to n */ do{ v=atomic_get_int(&nc_array[i]); /* get current (stored) nc value */ crt_nc=(v>>(r*8)) & ((1U<<(sizeof(nc_t)*8))-1); if (crt_nc>=nc) return NC_REPLAY; /* set corresponding array cell byte/short to new nc */ new_v=(v & ~(((1U<<(sizeof(nc_t)*8))-1)<< (r*8)) )| (nc << (r*8)); }while(atomic_cmpxchg_int((int*)&nc_array[i], v, new_v)!=v); return 0; }
/* check if nonce w/ index i is expected/valid and if so marked it "seen" * returns: 0 - ok, < 0 some error: * OTN_INV_POOL (pool number is invalid/corrupted) * OTN_ID_OVERFLOW (crt_id has overflowed with partition size since the * id was generated) * OTN_REPLAY (nonce id seen before => replay ) */ enum otn_check_ret otn_check_id(nid_t id, unsigned pool) { unsigned int i; unsigned n, b; otn_cell_t v, b_mask; if (unlikely(pool>=nid_pool_no)) return OTN_INV_POOL; if (unlikely(otn_id_check_overflow(id, pool))) return OTN_ID_OVERFLOW; n=get_otn_array_bit_idx(id, pool); /* n-th bit */ i=get_otn_array_cell_idx(n); /* aray index i, corresponding to n */ b=get_otn_cell_bit(n); /* bit pos corresponding to n */ b_mask= (otn_cell_t)1<<b; #ifdef OTN_CELL_T_LONG v=atomic_get_long(&oth_array[i]); if (unlikely(v & b_mask)) return OTN_REPLAY; atomic_or_long((long*)&otn_array[i], b_mask); #else v=atomic_get_int(&otn_array[i]); if (unlikely(v & b_mask)) return OTN_REPLAY; atomic_or_int((int*)&otn_array[i], b_mask); #endif /* OTN_CELL_T_LONG */ return 0; }
/* re-init the stored nc for nonce id in pool p */ nid_t nc_new(nid_t id, unsigned char p) { unsigned int i; unsigned n, r; unsigned int v, new_v; n=get_nc_array_raw_idx(id, p); /* n-th nc_t */ i=get_nc_array_uint_idx(n); /* aray index i, corresponding to n */ r=get_nc_int_pos(n); /* byte/short inside the uint corresponding to n */ /* reset corresponding value to 0 */ do{ v=atomic_get_int(&nc_array[i]); /* new_value = old_int with the corresponding byte or short zeroed*/ new_v=v & ~(((1<<(sizeof(nc_t)*8))-1)<< (r*8)); }while(atomic_cmpxchg_int((int*)&nc_array[i], v, new_v)!=v); return id; }