On Dec 23, 2016, at 8:07 AM, Niels Möller <[email protected]> wrote:
> Ron Frederick <[email protected]> writes:
>> [Ron] There are other ways to interface to C code in Python that can
>> auto-generate shims to do something like this, but they would involve
>> actually generating and compiling additional C code at build time and
>> shipping an additional C shared library with the Python code, which
>> means multiple versions of the package are needed to cover each of the
>> supported architectures.
> 
> That's they way I would expect language bindings to work. And I don't
> think any other way can work if one aims to have python glue for
> everything in Nettle.
> 
> That said, for umac and other mac algorithms, I think it would make
> sense to provide structs similar to nettle_hash which includes all needed
> sizes and function pointers. 
> 
> Would that solve your problem? You could try to see if you can make 100%
> python wrapper for the supported hash functions in the nettle_hashes
> list (I think Daniel Kahn Gillmor did something similar in his perl
> bindings). I guess you'd still need to access struct members, though.
> If useful, it's also possible to add accessor functions like
> 
>  size_t nettle_hash_ctx_size(const struct nettle_hash *hash)
>  { return hash->ctx_size; }
> 
>  nettle_hash_init_func *nettle_hash_init(const struct nettle_hash *hash)
>  { return hash->init; }
> 
> etc. (Other variants are possible, if one aims for a function-call-only api).

Thanks - a function-call based API that didn’t rely on the Python code needing 
to access any Nettle-specific structures sounds good, and would be preferred to 
something that involves declaring a struct to access function pointers and 
other static data.

I’ve confirmed that for UMAC the only such function I would need to build a 
Python wrapper is something that returns the context size. In fact, I have a 
first cut of such a module written and working with a “try” clause that shows 
how I could call such a function to request the size if it existed, with a 
fallback which uses a hard-coded size if that’s not present.

Regarding the init function, that shouldn’t be necessary if Nettle guarantees 
that a call to set_key() resets the context structure and performs all 
necessarily initialization. I can see where init() would be needed for the 
key-less hash functions, but it may not be needed here.

That actually leads to one other wrinkle I’ve run into. According to the Nettle 
docs:
> Function: void umac32_digest (struct umac32_ctx *ctx, size_t length, uint8_t 
> *digest)
>  <>Function: void umac64_digest (struct umac64_ctx *ctx, size_t length, 
> uint8_t *digest)
>  <>Function: void umac96_digest (struct umac96_ctx *ctx, size_t length, 
> uint8_t *digest)
>  <>Function: void umac128_digest (struct umac128_ctx *ctx, size_t length, 
> uint8_t *digest)
> Extracts the MAC of the message, writing it to digest. length is usually 
> equal to the specified output size, but if you provide a smaller value, only 
> the first length octets of the MAC are written. These functions reset the 
> context for processing of a new message with the same key. The nonce is 
> incremented as described above, the new value is used unless you call the 
> _set_nonce function explicitly for each message.
> 

While this wouldn’t really be a problem for my use case, the Python 
cryptographic hash standard API (defined in PEP 452) states the following about 
the digest() method:

>     digest()
> 
>         Return the hash value of this hashing object as a bytes
>         containing 8-bit data.  The object is not altered in any way
>         by this function; you can continue updating the object after
>         calling this function.

So, if I wanted to provide a Python module which adhered to this API, the 
automatic reset of the context and increment of the nonce would be a problem. 
Mind you, I think this is a very useful feature in Nettle and wouldn’t want to 
see it go away. However, do you think it would be possible to make this 
configurable? There could be something like a umac32_auto_increment_nonce() 
function that takes a context and a true/false value as an argument to 
determine whether calling digest() does this or not. If it didn’t, you could 
continue to append to a message even after requesting a hash of the data 
provided so far, without the need to make a copy of the context structure first.


> And then there's a known ABI problem with exporting that list, discussed
> in another mail to the list, which needs to be solved in one way or the
> other.

Yeah, I saw the earlier e-mail on that. My vote would be for option 2 in your 
list where a function is defined that returns a pointer to the list, and I 
think that would probably be a good approach for accessing any static data in 
the library.

That said, I like the suggestion in your other e-mail about providing both an 
ABI and API level interface, leaving it up to callers to decide if they’re 
willing to deal with the upgrade/downgrade issues of replacing the libnettle 
library without recompiling the calling code against the latest header file. 
More on that shortly in a follow-up to that other e-mail.


>> [Ron] This is a good point. Based on some simple tests, the returned
>> memory always seems to be at least 16-byte aligned similar to
>> malloc(), but I can’t actually find documentation that explicitly
>> promises this. I’ll have to do more research on this.
> 
> If you don't find any better way, maybe you can use ctype to call
> libc malloc directly?

Yes - this definitely seems like it would work if the Python allocator didn’t 
already provide such a guarantee.
-- 
Ron Frederick
[email protected]



_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to