[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Obvious (?) question about interoperability
On Wed, 1 Apr 1998, Hal Finney wrote:
> > can use ordinary libc calls (fread, fwrite). Otherwise I need a
> > normalization pass. I think implementations SHOULD store anything except
> > compressed, literal, or conventionally encrypted packets in normalized
> > form. Further, the conventionally encrypted packets should not divide the
> > first 10 bytes (actually 11) of the stream.
>
> By "normalization" do you mean the problem of assembling packets which use
> partial-length fields? If so, it was for this reason that I recommended
> adopting a four-byte length field option. I understand this will be
> discussed at the OpenPGP meeting tomorrow.
Exactly, but it doesn't matter the length field. As long as you can have
a valid message of <0xe0>t<0xe0>h<0xe0>i<0x01>s form, evil things happen
to the code.
It is easy to detect, since if the first partial length field is for <4096
I can call a normalizer which would collapse the above to <0x04>this.
> > I would make all of these MUSTs, but embedded applications may have
> > reasons not to, and I can normalize the stream myself.
>
> What exactly would you make MUSTs? Do you mean you would disallow the
> partial-length packets?
Disallow the partial length packets EXCEPT in literal, compressed, and
symmetrically encrypted packets (though if any of the other could exceed
the 8192+192 byte limit I would allow this; I could contrive an exaple but
I don't know if one would exist in the real world since such things might
break other static limits - huge MPIs, excessive hashed subpackets, etc.).
Do not allow the partial length packet to subdivide a literal header or
the first 11 bytes of an encrypted packet (I would say 10 bytes, but this
way I can be sure of one byte to decipher which makes the decryption loop
much nicer, and the partial length would be 16 if it met this).
> > Since I introduced the term normalized, I should define it -
> >
> > packet :- oldCTB-len, datachunk... | newCTB len-stream
> >
> > len-stream :- nontermlen, datachunk, len-stream | termlen, datachunk
> >
> > The len-stream is normal if it does not contain any nontermlen entries
> > indicating the following datachunk is less than 4096 bytes.
>
> I don't understand the significance of this definition. What is it about
> normal vs non-normal streams which requires them to be treated differently?
> I could see a distinction between packets which have the length at the
> beginning vs packets whose length is not known until you have read the
> whole thing. But I don't understand why the issue is whether the
> partial length packets are less than 4096 bytes.
For things like [PS]KESKs, signature packets, key material, they are
normally all under 4096 bytes. They SHOULD all be under the 8192+ size of
the largest terminal packet length. This allows express handling:
Normal stream:
get packet length of L
/* you can allocate an L byte buffer */
fread(buf,1,L,fp);
/* process buf */
Unnormal stream:
/* make buf *big*, or do a lot of reallocs */
bufp = buf;
get length packet L
while( partial )
fread(bufp,1,L,fp);
bufp += L;
get length packet L
fread(bufp,1,L,fp);
/* process buf */
Or:
Len = pgpfread(buf,1,BUFMAX,fp); /* containing the above */
My 5.X implementation handles things by reading the whole thing in (if
there is a sane upper limit on the size), and then processing by moving a
buffer pointer.
If you do a series of pgpfread(..) for every subpacket or atomic data
type, it changes things (and I think this is how PGP5.0 does it), But one
problem with this is that you need state information as to how much data
is left before the next expected packet-length, i.e.
Sub: I want 10 bytes
pgpfread: I have 5 bytes buffered, send them, read next packet length, oh,
it is 0xef, malloc 2147483648 bytes :), read them, return 5 more,
remembering that we have 2147483643 left.
Or:
pgpfread: 0xef, read BUFMAX (4096) bytes, and note there are 2**31-4096
bytes left until the next ctb, send the 5 and note there are 4091 bytes
left in the buffer. pgpfread now has lots of states and if tests to
determine how to respond. This is ugly. Really ugly.
I need to do this anyway for indeterminate length types (SymEncPkt,
Compressed, Literal), but having to handle it withing subfields within the
header is painful. But I can then inline the state info with the
read-decrypt (see my implementation).
--- reply to tzeruch - at - ceddec - dot - com ---