Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infrastructure for Tls #52

Closed
wants to merge 13 commits into from
Closed

Infrastructure for Tls #52

wants to merge 13 commits into from

Conversation

Drawaes
Copy link

@Drawaes Drawaes commented Jan 17, 2020

Includes

  1. Helper for reversing all structs and enums such that you don't have to have ugly casts everywhere and can reverse for network order
  2. Basic enums for TLS (cipher suites etc) all coded to the required values based on RFCs and values that will be sent across the wire
  3. A set of infrastructure for all the basic building blocks of Tls (Hashing, Certs, KeyExchange, BulkCiphers)

I have not included any implementations yet and made all internal for now, this can be reviewed at a later date but none should be used externally for now (except TlsProtocolVersion).

Next there are a few steps

  1. Provide some implementations (or at least one for OpenSsl) that shows how the infrastructure is provided
  2. Provide the upper parts of the protocol (state machines, parsers/writers)

I will probably work on 1 first so that there is something to actually use in 2 when we come to it (and my Tls 1.3 is a little rusty so I need to review so I will work on 1.2 first for part 2).

Cheers
Tim


namespace Bedrock.Framework.Experimental.Infrastructure
{
public static class Endianness
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Internal. Do you need this though?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I don't have this I end up with a lot of (SomeEnum) BinaryPrimatives.Reverse((ushort) someEnum);

Etc it's really ugly and this using generics goes down all the way to basically the bswap in all cases. Also in later code for Tls there are other structs (including int24) that are just unsupported otherwise

namespace Bedrock.Framework.Experimental.Protocols.Tls.BulkCiphers
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct AdditionalInfo
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mutable struct? Why?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a sequence number on this we increased for each message sent. We then feed this into BulkCipher as additional information used during the encryption for AES etc. Also by making the methods convert to the correct bitness in the set it means we can directly blit the struct (by using a pointer)


namespace Bedrock.Framework.Experimental.Protocols.Tls.BulkCiphers
{
internal abstract class BulkCipher : IDisposable
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this type for?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a difference in how TLS 1.2 and TLS 1.3 for instance encrypt each record (different additional info, different IV calculations for each, different headers and footers for the encryption frame) so this way the up level protocol handlers can abstract that detail and not care. They just have a Decrypt/Encrypt. I will upload the TLS 1.2 and TLS 1.3 implementation of each of these next.

{
internal abstract class BulkCipherKey : IDisposable
{
public abstract Memory<byte> IV { get; }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to exist and why isn't it read only

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IV is the initialisation vector that is used by the various symmetrical encryption algos. The spec defines how these are set so the "BulkCipher" will set them before every record that is encrypted (They contain a mixture of random/info from the handshake and counters). They are calculated differently for TLS 1.2 /1.3 etc and therefore cannot be controlled by the key implementation. They are mutated every record so they need to be editable.

{
internal abstract class BulkCipherProvider
{
public abstract BulkCipher GetCipher<T>(BulkCipherType cipherType, Memory<byte> keyStorage) where T : BulkCipher, new();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this memory writable?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally this was "OwnedMemory" because it came from a pool, however the BulkCipher needed to hold it for it's lifetime and then say when it was done. Is there still a concept of this now?


namespace Bedrock.Framework.Experimental.Protocols.Tls.Hashs
{
internal abstract class Hash
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is the same as below the provider below will provide an instance of this (from say OpenSsl or BCrypt)


namespace Bedrock.Framework.Experimental.Protocols.Tls.Hashs
{
internal abstract class HashProvider
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use any of the BCL types?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So Tls during the handshake requires you to keep a running hash of the messages sent/received during the exchange. There is a BCL incremental hash function which is great but....

TLS requires you to grab the hash up until now at various points. This poses a problem as there is only a "gethashandreset" method where as I want to get the hash up to now and continue. Both BCrypt and OpenSsl support that scenario but the BCL does not.

Without this you would have to buffer the messages during the handshake which is significantly worse and the interop for hash isn't a big deal.

@Drawaes
Copy link
Author

Drawaes commented Jan 17, 2020

All changed or answered, read for comment

public abstract int Finish(Span<byte> output);
public abstract HashType HashType { get; }

public void HashData(SequenceReader<byte> reader)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be ref?

Copy link
Collaborator

@jkotalik jkotalik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are a few outstanding comments, but I don't see any reason to block this.

@davidfowl
Copy link
Owner

@Drawaes Can you rebase?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants