Norbert Pocs <np...@redhat.com> writes: > My idea about the API was: set up a context, do encryption with the created > context; > as mentioned in the standard [2]. > The documentation was updated to cover all the functions listed in hpke.h > In short: > - hpke_setup_* sets up the encryption context for sender or receiver > in the given mode > - hpke_seal: encryption > - hpke_open: decryption > - export_secret: derives a secret from the internal secret
I've read the spec now, and I think I've have a better understanding of what it's doing, although I don't yet grasp all the details. Let me sketch how I think an api for it could look like. * We need an object responsible for the symmetric encryption/decryption, similar to the Context type in the spec. It's not clear to me if we need separate types for sender and receiver (as suggested in the spec) or if we can use the same type. This one needs to hold a context for an AEAD algorithm initialized with a secret key, function pointers for doing the actual encrypt/decrypt (possibly a const struct nettle_aead*), and the message sequence number (could perhaps be an uin64_t, regardless of algorithm). As far as I see, it doesn't need to know what KDF or KEM was used when the context was created. The context should have associated functions like encrypt_msg/decrypt_message, maybe "streaming" functions like update, encrypt/decrypt/digest, and perhaps some way to access the "export secret" feature. From the docs: : @deftypefun int hpke_seal (struct hpke_ctx @var{ctx}, uint8_t *@var{aad}, size_t @var{aad_len}, uint8_t *@var{pt}, size_t @var{pt_len}, uint8_t **@var{ct}, size_t *@var{ct_len}) : Encrypts a plaintext using an hpke context and an : optional additional authenticated data into ciphertext. : @end deftypefun I take it hpke_ctx argument should be a pointer, right? Is it non-const because it needs to update the sequence number? The aad and pt arguments should be const, I think. pt_len will be known by the caller, but how can it query for the size of the corresponding cipher text? For other aead modes, nettle use a single length argument, and it's the lenght of the destination (ct for encrypto, pt for decrypt), see https://www.lysator.liu.se/~nisse/nettle/nettle.html#Conventions. * Then we need some way(s) way to create/initialize such a context, for sender and receiver. One way would be to have general function, which gets kdf, kem and aead to use as arguments. Or would could take out some or all of that parameterization and have one function for each configuration. E.g., we could have something like hpke_init_curve25519_send(struct hpke_context *ctx, const uint8_t *receiver_pubkey, const struct hkpe_kdf *kdf, const struct nettle_aead *aead); to initialize the sender's context for sending to a receiver with a curve25519 public key. Now there are a few things missing: I think it needs to know the hpke id for the aead, and we should also pass in some parameters to specify how to get randomness for the ephemeral keys. If possible, it's also nice if allocation can be left to the caller, e.g., something like hpke_init_curve25519_send(struct hpke_context *ctx, const struct nettle_aead *aead, void *aead_ctx, const uint8_t *receiver_pubkey, const struct hkpe_kdf *kdf); * It may make sense to have one object that is responsible for a hpke configuration (mainly, which algorithms and which mode to use, maybe randomness source), and have functions which takes such a (const) objects + relevant keys and initializes a context like above. > To narrow the scope of the review I suggest to start with the base mode > and for the algorithms perhaps with one of the FIPS 140-3 approved ones, but > otherwise I have not much preference in the algorithms. I'm afraid I don't know what is or isn't approved in FIPS 140-3. I think point validation might be simpler with curve25519 than with the secp curves. I'd prefer initial algorithm based on what you think is most useful for applications. Starting with base mode only makes sense to me. > I am a bit confused on the external structs. How I understood was that the > users can use it for the context creation - which algorithms they prefer to > use. Therefore it should be public so they can pass it to `hpke_ctx_init` > or do I understand it wrong? I think they should be public in that sense. However, there are some subtle details. Either they are completely public: You declare the types in the public hpke.h, and declare (as const extern struct ...) instances, details becomes part of the nettle ABI. This is like, e.g., const struct nettle_hash nettle_sha256. Or you only forward declare the type in hpke.h, like struct hpke_kem; which actual contents in the private hpke-internal.h. In that case, you cannot publicly declare constants (because in some caes that can result in copy relocations making the size of the struct leak into the abi, even though contents of the struct was intended to be private). Instead, you have to declare accessors, like const struct hpke_kem *hpke_get_curve25519(void); This is like struct ecc_curve is handled. > Is there a function which can clear memory space after a private key? > I see `gmp_free`, but no comments to it. I think you have to just use memset. >> * There's quite a lot in struct hpke_ctx. I think it would be good to >> think about what parts are (i) algorithm parameterization, (ii) >> related to key schedule, (iii) per message state? Can some parts be >> moved from the state to inputs or outputs of relevant functions? > I didn't want to have enormous function parameters everywhere, that's > why I moved the variables there. If you are okay with bulkier function > arguments I'll rework this. Not sure what's the right way. But a context with lots of setter methods is rather different from most other things in Nettle. I often find that it makes things clearer to have separation between the separate stages/layers, e.g.: First do algorithm parameterization, resulting in a struct representing an instantiation of hpke mode. Then use a (const) struct like that + keys to create a session with the result of the key schedule. And then use that to process one or more messages, with another struct representing per-message state. (Not a perfect fit for hpke, but I hope you get the idea. In this case the "session" thing would correspond to the "context" in the spec, and if it is responsible for the message sequence number, it has to be mutable). Regards, /Niels -- Niels Möller. PGP key CB4962D070D77D7FCB8BA36271D8F1FF368C6677. Internet email is subject to wholesale government surveillance. _______________________________________________ nettle-bugs mailing list -- nettle-bugs@lists.lysator.liu.se To unsubscribe send an email to nettle-bugs-le...@lists.lysator.liu.se