Converting int to bytes, with confusion over significant bits and endianness

77 Views Asked by At

I am trying to implement a key derivation function from IEEE 802.11 which is described in pseudocode like this:

result ← ""
iterations ← ⌈Length / Hashlen
do i = 1 to iterations
    resultresult ‖ HMAC-Hash(K, iLabelContextLength)
od
return first Length bits of result, and irretrievably delete the other bits

where

i and Length are encoded as 16-bit unsigned integers, represented using the bit ordering conventions of 9.2.2
K, Label, and Context are bit strings and are represented using the ordering conventions of 9.2.2
Hashlen is the length, in bits, of the digest produced by Hash

And section 9.2.2 says:

In figures, all bits within fields are numbered, from 0 to k, where the length of the field is k + 1 bits. Bits within numeric fields that are longer than a single bit are depicted in increasing order of significance, i.e., with the lowest numbered bit having the least significance. The octet boundaries within a field can be obtained by taking the bit numbers of the field modulo 8. Octets within numeric fields that are longer than a single octet are depicted in increasing order of significance, from lowest numbered bit to highest numbered bit. The octets in fields longer than a single octet are sent to the [physical layer] in order from the octet containing the lowest numbered bits to the octet containing the highest numbered bits.

I think I have written this correctly but a) Perl is not my native language, b) I have trouble getting this endian significant bits stuff, and c) I am not getting expected results. So I wanted to ensure I have properly interpreted the stuff about the unsigned integers and applied it with pack() correctly.

sub kdf {
    my ($self, $K, $Hash, $Context, $Length) = @_;

    my $Label = "Pairwise key expansion";
    my $Hashlen;
    my $result = "";
    my $LengthBytes = pack("S", $Length);
    my $iBytes;

    if ($Hash eq "SHA_256") {
        $Hashlen = 256;
        for (my $i = 1; $i <= ceil($Length / $Hashlen); $i++) {
            $iBytes = pack("S", $i);
            $result .= hmac_sha256($K, $iBytes . $Label . $Context . $LengthBytes);
        }

        return substr($result, 0, $Length / 8);
    }
}

To sum up: based on the text of section 9.2.2, and assuming $Length is set to 384, should printf("%v02X", $LengthBytes) output 01.80, 80.01, or (I hope not) something altogether different?!

0

There are 0 best solutions below