On 19 Jan 2017, at 21:04, William A Rowe Jr <[email protected]> wrote:
> On Thu, Jan 19, 2017 at 1:50 PM, Dirk-Willem van Gulik <[email protected]>
> wrote:
>>
>>> On 19 Jan 2017, at 19:50, Graham Leggett <[email protected]> wrote:
>>> On 19 Jan 2017, at 18:29, Dirk-Willem van Gulik <[email protected]>
>>> 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.