~/bend-docscommunity

proofs/crypto/mac/hmac.bend checks

raw source on the hub · import bend-collections-laws-crypto@1.0.0.0/proofs/crypto/mac/hmac.bend as Hmac

8 imports
import Base
import ../../../src/crypto/mac.bend as MAC
import ../../../src/crypto/sha/sha256.bend as SHA
import ../../../spec/crypto/hmac.bend as Spec
import ../../../spec/crypto/sha.bend as FIPS
import ../sha/laws.bend as ShaLaws
import ../sha/correctness.bend as ShaCorrect
import ../../lib/logic.bend as L

Definitions

def fips_len source · line 19 · raw

@+bytes:List<&2, U32> -> {List.length(&2, U32, 0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/sha.sha256_bytes(bytes)) == 32n : Nat}

def le_of_len source · line 22 · raw

@+xs:List<&2, U32> -> @+n:Nat -> @+k:Nat -> @+e:{List.length(&2, U32, xs) == n : Nat} -> @+h:{Nat.is_le(n, k) == True{} : Bool} -> {Nat.is_le(List.length(&2, U32, xs), k) == True{} : Bool}

def fits_len source · line 29 · raw

@+key:List<&2, U32> -> @+n:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.fits(key, n) == Nat.is_le(List.length(&2, U32, key), n) : Bool}

fits(key, n) looks at most n+1 bytes, and says length(key) <= n.

def mask_nil source · line 41 · raw

@+n:Nat -> @+pad:U32 -> @+hp:{U32.xor(0, pad) == pad : U32} -> {0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.mask([], n, pad) == 0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.xor_pad(List.replicate(U32, n, 0), pad) : List<&2, U32>}

Past the end of the key, mask emits 0 XOR pad.

def mask_pad source · line 51 · raw

@+key:List<&2, U32> -> @+n:Nat -> @+pad:U32 -> @+hp:{U32.xor(0, pad) == pad : U32} -> @+h:{Nat.is_le(List.length(&2, U32, key), n) == True{} : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.mask(key, n, pad) == 0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.xor_pad(List.append(&2, U32, key, List.replicate(U32, Nat.sub(n, List.length(&2, U32, key)), 0)), pad) : List<&2, U32>}

mask is zero padding to n bytes followed by the byte-wise XOR.

def block_mask_if source · line 63 · raw

@+key:List<&2, U32> -> @+pad:U32 -> @+hp:{U32.xor(0, pad) == pad : U32} -> @+b:Bool -> @+eb:{Nat.is_le(List.length(&2, U32, key), 64n) == b : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.mask(0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.block_key_if(key, b), 64n, pad) == 0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.xor_pad(0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.zero_pad(0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.shorten_if(key, b)), pad) : List<&2, U32>}

def block_mask source · line 72 · raw

@+key:List<&2, U32> -> @+pad:U32 -> @+hp:{U32.xor(0, pad) == pad : U32} -> {0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.mask(0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.block_key(key), 64n, pad) == 0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.xor_pad(0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.k0(key), pad) : List<&2, U32>}

The masked key block of the implementation is (K0 XOR pad) of FIPS 198-1.

def inner source · line 78 · raw

@+key:List<&2, U32> -> @msg:List<&2, U32> -> List<&2, U32>

def outer source · line 81 · raw

@+key:List<&2, U32> -> @+msg:List<&2, U32> -> List<&2, U32>

def sign_correct source · line 84 · raw

@+key:List<&2, U32> -> @+msg:List<&2, U32> -> {0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.sign(key, msg) == 0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.hmac(key, msg) : List<&2, U32>}

def hmac_len source · line 91 · raw

@+key:List<&2, U32> -> @+msg:List<&2, U32> -> {List.length(&2, U32, 0xa7e654f9780078ca65bf9e187da99d3e/spec/crypto/hmac.hmac(key, msg)) == 32n : Nat}

Every tag is 32 bytes.

def sign_len source · line 94 · raw

@+key:List<&2, U32> -> @+msg:List<&2, U32> -> {List.length(&2, U32, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/mac.sign(key, msg)) == 32n : Nat}