diff --git a/CHANGELOG.md b/CHANGELOG.md index 88ed3c8..df39dae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.14 + +* Reduce size of SHA3 context instead of allocating all-size fit memory. save + up to 72 bytes of memory per context for SHA3-512. + ## 0.13 * *SECURITY* Fix buffer overflow issue in SHA384, copying 16 extra bytes from diff --git a/Crypto/Hash/Keccak.hs b/Crypto/Hash/Keccak.hs index bd51abd..f632169 100644 --- a/Crypto/Hash/Keccak.hs +++ b/Crypto/Hash/Keccak.hs @@ -25,7 +25,7 @@ data Keccak_224 = Keccak_224 instance HashAlgorithm Keccak_224 where hashBlockSize _ = 144 hashDigestSize _ = 28 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 352 hashInternalInit p = c_keccak_init p 224 hashInternalUpdate = c_keccak_update hashInternalFinalize p = c_keccak_finalize p 224 @@ -37,7 +37,7 @@ data Keccak_256 = Keccak_256 instance HashAlgorithm Keccak_256 where hashBlockSize _ = 136 hashDigestSize _ = 32 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 344 hashInternalInit p = c_keccak_init p 256 hashInternalUpdate = c_keccak_update hashInternalFinalize p = c_keccak_finalize p 256 @@ -49,7 +49,7 @@ data Keccak_384 = Keccak_384 instance HashAlgorithm Keccak_384 where hashBlockSize _ = 104 hashDigestSize _ = 48 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 312 hashInternalInit p = c_keccak_init p 384 hashInternalUpdate = c_keccak_update hashInternalFinalize p = c_keccak_finalize p 384 @@ -61,7 +61,7 @@ data Keccak_512 = Keccak_512 instance HashAlgorithm Keccak_512 where hashBlockSize _ = 72 hashDigestSize _ = 64 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 280 hashInternalInit p = c_keccak_init p 512 hashInternalUpdate = c_keccak_update hashInternalFinalize p = c_keccak_finalize p 512 diff --git a/Crypto/Hash/SHA3.hs b/Crypto/Hash/SHA3.hs index ded49ee..f070dc9 100644 --- a/Crypto/Hash/SHA3.hs +++ b/Crypto/Hash/SHA3.hs @@ -25,7 +25,7 @@ data SHA3_224 = SHA3_224 instance HashAlgorithm SHA3_224 where hashBlockSize _ = 144 hashDigestSize _ = 28 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 352 hashInternalInit p = c_sha3_init p 224 hashInternalUpdate = c_sha3_update hashInternalFinalize p = c_sha3_finalize p 224 @@ -37,7 +37,7 @@ data SHA3_256 = SHA3_256 instance HashAlgorithm SHA3_256 where hashBlockSize _ = 136 hashDigestSize _ = 32 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 344 hashInternalInit p = c_sha3_init p 256 hashInternalUpdate = c_sha3_update hashInternalFinalize p = c_sha3_finalize p 256 @@ -49,7 +49,7 @@ data SHA3_384 = SHA3_384 instance HashAlgorithm SHA3_384 where hashBlockSize _ = 104 hashDigestSize _ = 48 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 312 hashInternalInit p = c_sha3_init p 384 hashInternalUpdate = c_sha3_update hashInternalFinalize p = c_sha3_finalize p 384 @@ -61,7 +61,7 @@ data SHA3_512 = SHA3_512 instance HashAlgorithm SHA3_512 where hashBlockSize _ = 72 hashDigestSize _ = 64 - hashInternalContextSize _ = 360 + hashInternalContextSize _ = 280 hashInternalInit p = c_sha3_init p 512 hashInternalUpdate = c_sha3_update hashInternalFinalize p = c_sha3_finalize p 512 diff --git a/cbits/cryptonite_keccak.c b/cbits/cryptonite_keccak.c index 3a9d0b4..03c2da2 100644 --- a/cbits/cryptonite_keccak.c +++ b/cbits/cryptonite_keccak.c @@ -99,8 +99,9 @@ static inline void keccak_do_chunk(uint64_t state[25], uint64_t buf[], int bufsz void cryptonite_keccak_init(struct keccak_ctx *ctx, uint32_t hashlen) { - memset(ctx, 0, sizeof(*ctx)); - ctx->bufsz = 200 - 2 * (hashlen / 8); + int bufsz = 200 - 2 * (hashlen / 8); + memset(ctx, 0, sizeof(*ctx) + bufsz); + ctx->bufsz = bufsz; } void cryptonite_keccak_update(struct keccak_ctx *ctx, uint8_t *data, uint32_t len) diff --git a/cbits/cryptonite_keccak.h b/cbits/cryptonite_keccak.h index 466b66d..7ac2019 100644 --- a/cbits/cryptonite_keccak.h +++ b/cbits/cryptonite_keccak.h @@ -31,7 +31,7 @@ struct keccak_ctx uint32_t bufindex; uint32_t bufsz; uint64_t state[25]; - uint8_t buf[144]; /* minimum SHA3-224, otherwise buffer need increases */ + uint8_t buf[0]; /* maximum SHA3-224 = 144, otherwise buffer need decrease */ }; #define SHA3_CTX_SIZE sizeof(struct keccak_ctx) diff --git a/cbits/cryptonite_sha3.c b/cbits/cryptonite_sha3.c index 319405e..5605421 100644 --- a/cbits/cryptonite_sha3.c +++ b/cbits/cryptonite_sha3.c @@ -99,8 +99,9 @@ static inline void sha3_do_chunk(uint64_t state[25], uint64_t buf[], int bufsz) void cryptonite_sha3_init(struct sha3_ctx *ctx, uint32_t hashlen) { - memset(ctx, 0, sizeof(*ctx)); - ctx->bufsz = 200 - 2 * (hashlen / 8); + int bufsz = 200 - 2 * (hashlen / 8); + memset(ctx, 0, sizeof(*ctx) + bufsz); + ctx->bufsz = bufsz; } void cryptonite_sha3_update(struct sha3_ctx *ctx, const uint8_t *data, uint32_t len) diff --git a/cbits/cryptonite_sha3.h b/cbits/cryptonite_sha3.h index 83aa731..966f47d 100644 --- a/cbits/cryptonite_sha3.h +++ b/cbits/cryptonite_sha3.h @@ -31,7 +31,7 @@ struct sha3_ctx uint32_t bufindex; uint32_t bufsz; uint64_t state[25]; - uint8_t buf[144]; /* minimum SHA3-224, otherwise buffer need increases */ + uint8_t buf[0]; /* maximum SHA3-224 is 144 bytes, otherwise buffer can be decreases */ }; #define SHA3_CTX_SIZE sizeof(struct sha3_ctx) diff --git a/gen/Gen.hs b/gen/Gen.hs index 1d8a8b2..6b5dd12 100644 --- a/gen/Gen.hs +++ b/gen/Gen.hs @@ -23,6 +23,9 @@ newtype Bits = Bits Int newtype Bytes = Bytes Int deriving (Show,Eq,Num) +bitsToBytes :: Bits -> Bytes +bitsToBytes (Bits b) = Bytes (b `divSafe` 8) + class SizedNum a where showBytes :: a -> String showBits :: a -> String @@ -43,20 +46,22 @@ data GenHashModule = GenHashModule , ghmHashName :: String , ghmContextSize :: Bytes , ghmCustomizable :: HashCustom - } deriving (Show,Eq) + } + +data Prop = + VarCtx (Bits -> Bytes) data HashCustom = HashSimple Bits -- digest size in bits Bytes -- block length in bytes - | HashMulti [(Bits, Bytes)] -- list of (digest output size in *bits*, block size in bytes) - deriving (Show,Eq) + | HashMulti [Prop] [(Bits, Bytes)] -- list of (digest output size in *bits*, block size in bytes) hashModules = -- module header hash ctx dg blk - [ GenHashModule "Blake2s" "blake2.h" "blake2s" 185 (HashMulti [(224,64), (256,64)]) - , GenHashModule "Blake2sp" "blake2.h" "blake2sp" 2185 (HashMulti [(224,64), (256,64)]) - , GenHashModule "Blake2b" "blake2.h" "blake2b" 361 (HashMulti [(512,128)]) - , GenHashModule "Blake2bp" "blake2.h" "blake2sp" 2325 (HashMulti [(512,128)]) + [ GenHashModule "Blake2s" "blake2.h" "blake2s" 185 (HashMulti [] [(224,64), (256,64)]) + , GenHashModule "Blake2sp" "blake2.h" "blake2sp" 2185 (HashMulti [] [(224,64), (256,64)]) + , GenHashModule "Blake2b" "blake2.h" "blake2b" 361 (HashMulti [] [(512,128)]) + , GenHashModule "Blake2bp" "blake2.h" "blake2sp" 2325 (HashMulti [] [(512,128)]) , GenHashModule "MD2" "md2.h" "md2" 96 (HashSimple 128 16) , GenHashModule "MD4" "md4.h" "md4" 96 (HashSimple 128 64) , GenHashModule "MD5" "md5.h" "md5" 96 (HashSimple 128 64) @@ -65,16 +70,23 @@ hashModules = , GenHashModule "SHA256" "sha256.h" "sha256" 192 (HashSimple 256 64) , GenHashModule "SHA384" "sha512.h" "sha384" 256 (HashSimple 384 128) , GenHashModule "SHA512" "sha512.h" "sha512" 256 (HashSimple 512 128) - , GenHashModule "SHA512t" "sha512.h" "sha512t" 256 (HashMulti [(224,128),(256,128)]) - , GenHashModule "Keccak" "keccak.h" "keccak" 352 (HashMulti [(224,144),(256,136),(384,104),(512,72)]) - , GenHashModule "SHA3" "sha3.h" "sha3" 352 (HashMulti [(224,144),(256,136),(384,104),(512,72)]) + , GenHashModule "SHA512t" "sha512.h" "sha512t" 256 (HashMulti [] [(224,128),(256,128)]) + , GenHashModule "Keccak" "keccak.h" "keccak" 352 (HashMulti [VarCtx sha3CtxSize] [(224,144),(256,136),(384,104),(512,72)]) + , GenHashModule "SHA3" "sha3.h" "sha3" 352 (HashMulti [VarCtx sha3CtxSize] [(224,144),(256,136),(384,104),(512,72)]) , GenHashModule "RIPEMD160" "ripemd.h" "ripemd160" 128 (HashSimple 160 64) - , GenHashModule "Skein256" "skein256.h" "skein256" 96 (HashMulti [(224,32),(256,32)]) - , GenHashModule "Skein512" "skein512.h" "skein512" 160 (HashMulti [(224,64),(256,64),(384,64),(512,64)]) + , GenHashModule "Skein256" "skein256.h" "skein256" 96 (HashMulti [] [(224,32),(256,32)]) + , GenHashModule "Skein512" "skein512.h" "skein512" 160 (HashMulti [] [(224,64),(256,64),(384,64),(512,64)]) , GenHashModule "Tiger" "tiger.h" "tiger" 96 (HashSimple 192 64) , GenHashModule "Whirlpool" "whirlpool.h" "whirlpool" 168 (HashSimple 512 64) ] +sha3CtxSize :: Bits -> Bytes +sha3CtxSize bitLen = 4 + 4 + 8 * 25 -- generic context + + sha3BlockSize bitLen -- variable buffer + +sha3BlockSize :: Bits -> Bytes +sha3BlockSize bitLen = 200 - 2 * bitsToBytes bitLen + renderHashModules genOpts = do hashTemplate <- readTemplate "template/hash.hs" hashLenTemplate <- readTemplate "template/hash-len.hs" @@ -101,17 +113,29 @@ renderHashModules genOpts = do ] , [] ) - HashMulti customSizes -> - (hashLenTemplate, [], + HashMulti props customSizes -> + let customCtxSize = + let getVarCtx _ (VarCtx p) = Just p + getVarCtx x _ = x + in case foldl getVarCtx Nothing props of + Nothing -> \_ -> + [ ("CUSTOM_CTX_SIZE_BYTES" , showBytes (ghmContextSize ghm)) + , ("CUSTOM_CTX_SIZE_WORD64" , showW64 (ghmContextSize ghm)) + ] + Just prop -> \outputSize -> + [ ("CUSTOM_CTX_SIZE_BYTES" , showBytes $ prop outputSize) + , ("CUSTOM_CTX_SIZE_WORD64" , showW64 $ prop outputSize) + ] + in (hashLenTemplate, [], [ ("CUSTOMIZABLE", map (\(outputSizeBits, customBlockSize) -> [ ("CUSTOM_BITSIZE", showBits outputSizeBits) , ("CUSTOM_DIGEST_SIZE_BITS", showBits outputSizeBits) , ("CUSTOM_DIGEST_SIZE_BYTES", showBytes outputSizeBits) , ("CUSTOM_BLOCK_SIZE_BYTES", showBytes customBlockSize) - ]) customSizes + ] ++ customCtxSize outputSizeBits) customSizes ) ] - ) + ) writeTemplate mainName (baseVars ++ addVars) multiVars tpl diff --git a/gen/template/hash-len.hs b/gen/template/hash-len.hs index 9f7381d..2d8bc9d 100644 --- a/gen/template/hash-len.hs +++ b/gen/template/hash-len.hs @@ -25,7 +25,7 @@ data %%MODULENAME%%_%%CUSTOM_BITSIZE%% = %%MODULENAME%%_%%CUSTOM_BITSIZE%% instance HashAlgorithm %%MODULENAME%%_%%CUSTOM_BITSIZE%% where hashBlockSize _ = %%CUSTOM_BLOCK_SIZE_BYTES%% hashDigestSize _ = %%CUSTOM_DIGEST_SIZE_BYTES%% - hashInternalContextSize _ = %%CTX_SIZE_BYTES%% + hashInternalContextSize _ = %%CUSTOM_CTX_SIZE_BYTES%% hashInternalInit p = c_%%HASHNAME%%_init p %%CUSTOM_BITSIZE%% hashInternalUpdate = c_%%HASHNAME%%_update hashInternalFinalize p = c_%%HASHNAME%%_finalize p %%CUSTOM_BITSIZE%%