On 19 Jan 2017, at 21:04, William A Rowe Jr <wr...@rowe-clan.net> wrote:
> On Thu, Jan 19, 2017 at 1:50 PM, Dirk-Willem van Gulik <di...@webweaving.org> 
> wrote:
>> 
>>> On 19 Jan 2017, at 19:50, Graham Leggett <minf...@sharp.fm> wrote:
>>> On 19 Jan 2017, at 18:29, Dirk-Willem van Gulik <di...@webweaving.org> 
>>> wrote:
>>> 
>>>> Am wondering now it if makes sense to create a new directory with:
>>>> 
>>>>  hash/*
>>>> 
>>>> section (or something in crypto) where I cull things/move out of the 
>>>> current apr_random, sha256_glue and apr_md4/5 and apr_sha1 - and
>>>> then all give them below treatment.
>>>> 
>>>> It would make wiring them up to OS specific things or to 
>>>> nss/openssl/CommonCrypto also a bit easier.
>>>> 
>>>> And then perhaps come up with a few extra apr_hash things that do a subset 
>>>> of what we currently do in the various apr_sha/md’s.
>>>> 
>>>> Or is that not worth it - as mid to long term md4/md5 and sha1 will 
>>>> evaporate.
>>> 
>>> I've always been keen to create an apr_crypto_hash_*() set of functions 
>>> that do hashing, but guaranteed to be implemented by crypto libraries 
>>> (OpenSSL et al) and therefore secure.
>> 
>> So I guess we could move them in one place - platform neutral (right now 
>> sha256 is unix only).
>> 
>> And then rely on our own md4/5/sha1/256 when APU_HAVE_CRYPTO is not defined; 
>> and when
>> it is - allow a driver to be specified - but if none is yet specified or 
>> loaded - we use the same
>> order as in configure (CommonCrypto, openssl, nss) -- but refuse to fall 
>> back to our 'own'.
>> 
>> And rework the innards of our existing hash functions to that apr_hash_ ctx 
>> form; so they
>> can stay as 'legacy' bridges.
>> 
>> Would that work ?
> 
> Yes. This allows us to have either crypto-authored implementations, or
> even FIPS validated implementations, if we will simply be dispatching.

So turns out where are not using this that much - so retroactively fixing 
things should be easy - and we may be able to deprecate quickly.

As to the selection of the hash - I can see three strategies

A)      current approach (we do this I think only for sha256):

                 apr_crypto_hash_t * ctx = apr_crypto_sha256_new(pool);

        followed by a hash neutral/generic

                apr_hash(sha256_ctx, &buf, &len,  plain, plainlen, pool);

        and then create the the corresponding

                apr_crypto_md4_new(apr_pool_t *);
                apr_crypto_md5_new(apr_pool_t *);
                apr_crypto_sha1_new(apr_pool_t *);
                apr_crypto_sha256_new(apr_pool_t *);
        
        and create new ones (eg. SHA512 etc, etc) as we go along.

B)      more of the ENUM approach as used elsewhere in APR:

                enum {
                        APR_CRYPTO_SANE_DEFAULT = APR_CRYPTO_SHA256, // 
whatever the report of Ecrypt/NIST recommended in the year of the release.
                        APR_CRYPTO_MD4,
                        APR_CRYPTO_MD5,
                        ....

                apr_crypto_hash_t * ctx = apr_crypto_hash_new(pool, 
APR_CRYPTO_MD4);    

        with the goal of deprectating the apr_crypto_sha256_new soon. Which has
        the downside that this ultimately means numbers rather than symbols
        and limiting what you can spot at link time.

C)      something more akin to what I use now (as the code I am trying
        to get under long term maintenance control fudges things a bit
        to deal with hardware base crypto (network HSMs and cheap
        USB chipcards/SIMS):

                #define APR_CRYPTO_MD4 "MD4"
                apr_crypto_hash_t * ctx = apr_crypto_hash_new(pool, 
APR_CRYPTO_MD4);    

        where the strings are picked so that they work with the existing
        char* based pickers of openssl and nss (EVP_get_digestbyname et.al.).

Option A and B have the advantage that with an

        #ifdef APU_HAVE_CRYPTO

one can cleanly add in things like SHA512 -- and option A really locks this 
down (i.e. in A you cannot (dynamically) link and thus run a binary unsafe). 
With option B that becomes a compile time thing and option C - while ultimately 
flexible - would be more prone to fiddling and surprises.

What is the general thought on this ? I am tempted to go for 'A' -- as it gives 
strong guarantees - hard to make things go wrong. And if at some point a paying 
customer or employer of some one needs things like FIPS #ifdefs - these can be 
'strong'.

However I do note that most crypto libraries seem to go for a const char*; and 
that their names are pretty much interoperable. (Though internally most use 
something like A, e.g. openssl its 

        const EVP_MD *EVP_sha512(void) { return (&sha512_md); }

I would have thought this to be an easy choice - but for the fact that I was 
somewhat disheartened by the general state of our hashes - and how far out of 
date we are. And recognize that A and B are more impediments for people who 
want to do the  right thing; than ''C' -- where as long as you link to a 
capable crypto library you automatically get anything new.

Does anyone have any strong opinions ? 

Dw.




Reply via email to