In message <1481043672.4406.22.ca...@hansenpartnership.com> on Tue, 06 Dec 2016 09:01:12 -0800, James Bottomley <james.bottom...@hansenpartnership.com> said:
James.Bottomley> On Tue, 2016-12-06 at 17:47 +0100, Richard Levitte wrote: James.Bottomley> > In message <1481042048.4406.14.ca...@hansenpartnership.com> on Tue, James.Bottomley> > 06 Dec 2016 08:34:08 -0800, James Bottomley < James.Bottomley> > james.bottom...@hansenpartnership.com> said: James.Bottomley> > James.Bottomley> > James.Bottomley> On Tue, 2016-12-06 at 15:12 +0100, Richard Levitte James.Bottomley> > wrote: James.Bottomley> > James.Bottomley> > In message < James.Bottomley> > 1480697558.2410.33.ca...@hansenpartnership.com> on Fri, James.Bottomley> > James.Bottomley> > 02 Dec 2016 08:52:38 -0800, James Bottomley < James.Bottomley> > James.Bottomley> > james.bottom...@hansenpartnership.com> said: James.Bottomley> > James.Bottomley> > James.Bottomley> > James.Bottomley> > When I made that argument, I hadn't thought and James.Bottomley> > felt things through James.Bottomley> > James.Bottomley> > entirely. Truth be told, I'm feeling very uneasy James.Bottomley> > handing over the James.Bottomley> > James.Bottomley> > reading and parsing of the PEM file to an engine. James.Bottomley> > However, handing James.Bottomley> > James.Bottomley> > over the decoded data and leaving it to the engine James.Bottomley> > to do something James.Bottomley> > James.Bottomley> > sensible with it, no issues at all. James.Bottomley> > James.Bottomley> James.Bottomley> > James.Bottomley> OK, can I pick on this a bit (I'll look at the store James.Bottomley> > stuff later and James.Bottomley> > James.Bottomley> reply after I've played with it)? What is it that James.Bottomley> > you imagine handing James.Bottomley> > James.Bottomley> to the engine? Some type of buffer that contains James.Bottomley> > the full PEM James.Bottomley> > James.Bottomley> representation? James.Bottomley> > James.Bottomley> > In my STORE branch, you will find this in James.Bottomley> > include/openssl/store_file.h: James.Bottomley> > James.Bottomley> > /* James.Bottomley> > * The try_decode function is called to check if the blob of data James.Bottomley> > can James.Bottomley> > * be used by this handler, and if it can, decodes it into a James.Bottomley> > supported James.Bottomley> > * OpenSSL and returns a STORE_INFO with the recorded data. James.Bottomley> > * Input: James.Bottomley> > * pem_name: If this blob comes from a PEM file, this James.Bottomley> > holds James.Bottomley> > * the PEM name. If it comes from another type James.Bottomley> > of James.Bottomley> > * file, this is NULL. James.Bottomley> > * blob: The blob of data to match with what this James.Bottomley> > handler James.Bottomley> > * can use. James.Bottomley> > * len: The length of the blob. James.Bottomley> > * handler_ctx: For a handler marked repeatable, this pointer James.Bottomley> > can James.Bottomley> > * be used to create a context for the handler. James.Bottomley> > IT IS James.Bottomley> > * THE HANDLER'S RESPONSIBILITY TO CREATE AND James.Bottomley> > DESTROY James.Bottomley> > * THIS CONTEXT APPROPRIATELY, i.e. create on James.Bottomley> > first call James.Bottomley> > * and destroy when about to return NULL. James.Bottomley> > * password_ui: Application UI method for getting a password. James.Bottomley> > * password_ui_data: James.Bottomley> > * Application data to be passed to password_ui James.Bottomley> > when James.Bottomley> > * it's called. James.Bottomley> > * Output: James.Bottomley> > * a STORE_INFO James.Bottomley> > */ James.Bottomley> > typedef STORE_INFO *(*STORE_FILE_try_decode_fn)(const char James.Bottomley> > *pem_name, James.Bottomley> > const unsigned James.Bottomley> > char *blob, James.Bottomley> > size_t len, James.Bottomley> > void James.Bottomley> > **handler_ctx, James.Bottomley> > const UI_METHOD James.Bottomley> > *password_ui, James.Bottomley> > void James.Bottomley> > *password_ui_data); James.Bottomley> > James.Bottomley> > This is the central function that tries to see if it can decode James.Bottomley> > whatever's thrown at it. As you can see, it gets handed the PEM name James.Bottomley> > if it's called as part of a PEM read. The |blob| is the decoded *and James.Bottomley> > decrypted* data. James.Bottomley> > James.Bottomley> > James.Bottomley> The reason I chose a BIO is that it's the basic James.Bottomley> > abstract data handler James.Bottomley> > James.Bottomley> for openssl. I can hand a buffer to the engine, James.Bottomley> > sure, but I'd need to James.Bottomley> > James.Bottomley> transform it to a BIO again (because it would need James.Bottomley> > PEM parsing and all James.Bottomley> > James.Bottomley> the PEM parsers speak BIOs), so it feels suboptimal. James.Bottomley> > James.Bottomley> > With a try_decode function, I really do not see why there's a need to James.Bottomley> > deal with the BIO... James.Bottomley> James.Bottomley> OK, I get what you want. There are two problems with this. The first James.Bottomley> is easy: I'm eventually going to need the BIO header as well because James.Bottomley> TPM2 keys are going to need to describe external things that aren't in James.Bottomley> the key representation (and even TPM1 keys might need to say who their James.Bottomley> parent key is). However, this is fixable by simply expanding your James.Bottomley> prototype above to have const char *pem_name and const char *pem_header James.Bottomley> ... is that OK? James.Bottomley> James.Bottomley> The next problem is that this is slightly harder simply to insert into James.Bottomley> the PEM code. The BIO parsing is done in PEM_bytes_read_bio() not James.Bottomley> PEM_read_bio_PrivateKey(). The easy way to cope with this would be to James.Bottomley> move PEM parsing into the ENGINE_find_engine_load_key() function and James.Bottomley> then hand the name, header, blob to the engine. The disadvantage of James.Bottomley> this is that we'll end up pulling the PEM apart twice: once in James.Bottomley> ENGINE_find_engine_load_key() and then again in PEM_bytes_read_bio(). James.Bottomley> Is this OK? If it is I can code up a v3. If not, I can think about James.Bottomley> how we might integrate this into PEM_bytes_read_bio(). Oh.... I think I aired some thoughts on using PEM headers a very long while ago, but that never came into fruition, among others because I ended up doubting that it would be the best way in the long run. These days, the use of PEM headers is considered old and kinda sorta deprecated, even though OpenSSL still produces encrypted private key PEM files that uses headers for the encryption metadata. It seems that PKCS#8 is prefered "out there". So I have to wonder, is PEM really the right way to go for this? Would it be just as possible to wrap a TSS key with a PKCS#8 container, and use the associated attributes for the external data? Just a thought, though... I can't do more than throw around ideas, considering how little I know about TPM. That being said, it should certainly be easy enough to change the appropriate places to make sure headers are available as well, and I have zero issues adding a header parameter to the try_decode prototype and associated functions. One thing I didn't think of earlier is that PEM_bytes_read_bio() checks the pem name against a known set, *or* in the private key case, that the pem name ends with " PRIVATE KEY" (which "TSS KEY BLOB" does not), so some kind of refactoring is needed to accomodate the store_file_load() call either way. (quite frankly, I'm slowly realising that the STORE_FILE_HANDLER code can replace quite a lot of the discovery code in the PEM module, so refactoring could be in order either way) Cheers, Richard -- Richard Levitte levi...@openssl.org OpenSSL Project http://www.openssl.org/~levitte/ -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev