/* * Copyright (c) 2013-2016 Galois, Inc. * Distributed under the terms of the BSD3 license (see LICENSE file) */ module PBKDF2 where import SHA256 import HMAC // PBKDF2 specialized to HMAC_SHA256 to avoid monomorphic type issues. pbkdf2 : {pwBytes, saltBytes, dkLenBits, len, C} ( 32 >= width (pwBytes*8), len == (dkLenBits + 255)/256 , len >= 1, 32 >= width len, fin saltBytes, fin dkLenBits, fin pwBytes , 64 >= width (8 * (pwBytes + (4 + saltBytes))) , 64 >= width (8 * (pwBytes + 32)) , C >= 1, fin C, 64 >= width (8*(pwBytes + (2 + saltBytes))), 16 >= width C , 16 >= width len // cryptol < 2.3 can't math! , dkLenBits == 256 * len // Cryptol 2.3 doesn't understand 'take'? , max 6 (width pwBytes) >= width pwBytes , max 6 (width pwBytes) >= 6 , max 7 (width pwBytes) >= 7 , max 7 (width pwBytes) >= width pwBytes , max (width pwBytes) 7 >= 7 , max (width pwBytes) 7 >= width pwBytes , 64 >= width (8 * pwBytes) , 64 >= width (8 * (68 + saltBytes)) , 32 >= width (4 + saltBytes) ) => [pwBytes][8] -> [saltBytes][8] -> [dkLenBits] pbkdf2 P S = take `{dkLenBits} (join Ts) where Ts : [_][256] Ts = [ inner `{C=C} P (split (hmacSHA256 P (S # split i))) | i <- [1..len] : [_][32] ] inner : {pwBytes, C} ( fin pwBytes , 64 >= width (8 * (pwBytes + 32)) , fin C, C >= 1, 16 >= width C // Cryptol < 2.3 can't math , 64 >= width (8 * pwBytes) , max 7 (width pwBytes) >= width pwBytes , max 7 (width pwBytes) >= 7 , max (width pwBytes) 7 >= width pwBytes , max (width pwBytes) 7 >= 7 , max 6 (width pwBytes) >= width pwBytes , max 6 (width pwBytes) >= 6 ) => [pwBytes][8] -> [32][8] -> [256] inner P U0 = (Ts @ 0).0 // XXX should be ! 0 where // Ts : [_][([256],[32][8])] Ts = [(join U0, U0)] # [ F P t u | _ <- [1..C] : [_][16] | (t,u) <- Ts ] F : {pwBytes} (fin pwBytes , 64 >= width (8*(32+pwBytes)) // cryptol < 2.3 can't math , 64 >= width (8 * pwBytes) , max 7 (width pwBytes) >= width pwBytes , max 7 (width pwBytes) >= 7 , max (width pwBytes) 7 >= width pwBytes , max (width pwBytes) 7 >= 7 , max 6 (width pwBytes) >= width pwBytes , max 6 (width pwBytes) >= 6 ) => [pwBytes][8] -> [256] -> [32][8] -> ([256],[32][8]) F P Tprev Uprev = (Tnext,Unext) where Unext = split (hmacSHA256 P Uprev) Tnext = Tprev ^ join Unext test1 : Bit property test1 = pbkdf2 `{C=1,dkLenBits=64*8} "passwd" "salt" == 0x55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783