Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Conversation

@filipnavara
Copy link
Member

@filipnavara filipnavara commented Jul 23, 2018

Rationale: In Mono X509Certificate and X509Certificate2 live in different assemblies, the first in mscorlib, the latter in System. Nearly all the other classes from System.Security.Cryptography.X509Certificates live in the System assembly. In order to allow Mono to reuse X509Certificate it is necessary to keep its dependencies as small as possible (no X500DistinguishedName and no ECDsa).

Fortunately, that is easily achieved by splitting the X509Certificate-specific members out of the ICertificatePal interface into ICertificateLegacyPal. Additionally, the legacy GetName and GetIssuerName are now implemented by new LegacySubjectName and LegacyIssuerName properties in ICertificatePal. An optimized version is added for the Windows PAL.

/cc @bartonjs @baulig

@baulig
Copy link

baulig commented Jul 23, 2018

Looks good to me :-)

I wouldn't mind keeping Version and FriendlyName in ICertificatePal.

What's Archived used for - if I see this correctly, then we're throwing PNS everywhere, so we might as well just remove it.

@filipnavara
Copy link
Member Author

I made the split at whatever was used by X509Certificate and nothing more. Both FriendlyName and Version are only exposed through X509Certificate2 and thus not necessary to be available in mscorlib.

Only tested compilation on macOS so far. It's likely that I missed some stuff in the other two implementations and I will fix it as soon as the PR builds finish.

@baulig
Copy link

baulig commented Jul 23, 2018

Okay, makes sense.

namespace Internal.Cryptography
{
/// <summary>Provides specific implementation for X509Certificate.</summary>
internal interface ICertificatePal : IDisposable
Copy link
Member

@bartonjs bartonjs Jul 23, 2018

Choose a reason for hiding this comment

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

Would this be a less noisy change if the base interface name changed instead of the derived one?

Copy link

Choose a reason for hiding this comment

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

I Mono, I'm actually using an abstract class for this - this is from our mono/mono#9650.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure that answers the question.

A whole lot of this change is changing input parameters from ICertificatePal to ICertificatePal2. if the split was ICertificateLegacyPal and ICertificatePal instead of ICertificatePal and ICertificatePal2 the change seems a whole lot smaller. (I'm flexible on the name of the "splitting this off for mscorlib-like separation" version)

Copy link

Choose a reason for hiding this comment

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

Well, I'm still not 100% convinced that we will actually need this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I can split it the other way around and it definitely makes way less noise. That's what I did ~2 weeks ago for my initial quick and dirty attempt to make it all build. I couldn't come up with a good name though, but ICertificateLegacyPal sounds good.

@baulig, I am open to other options, but I know this one is definitely doable since I already have the full macOS CoreFX certificate stack running with it on Mono. I'm still maintaining that to run all the unit tests.

…tificate) and ICertificatePal (consumed by X509Certificate2).
@filipnavara filipnavara changed the title WIP: System.Security: Split ICertificatePal System.Security: Split ICertificatePal Jul 24, 2018
@baulig
Copy link

baulig commented Jul 24, 2018

Well, I strongly dislike the name ICertificateLegacyPal as it gives the false impression that this is somehow "obsolete". And I also wouldn't want this to come up during a git grep for obsolete / legacy code.

How about ICertificatePalV1, ICertificatePal1, ICertificatePalCore or ICertificatePalBase - do you like any of these names?

Could we also possible turn CertificatePal into a singleton instance like X509Pal and make turn its static FromHandle(), FromBlob() etc. into instance methods? And then we also need to split X509Pal.cs and CertificatePal.cs - one file should only contain the Instance property and the private constructor.

@baulig
Copy link

baulig commented Jul 24, 2018

I can take care of the CertificatePal changes and the file split in a separate PR, just wanted to ask you what you think about it.

For Internal/Cryptography/Pal.OSX/X509Pal.cs, I essentially need the following to be moved into a separate file:

   public static IX509Pal Instance = new AppleX509Pal();

   private X509Pal()
   {
   }

@baulig
Copy link

baulig commented Jul 24, 2018

While we at it, does any of you have any strong feelings about IExportPal or this code from X509Certificate.cs:

        public virtual byte[] Export(X509ContentType contentType, string password)
        {
            VerifyContentType(contentType);

            if (Pal == null)
                throw new CryptographicException(ErrorCode.E_POINTER);  // Not the greatest error, but needed for backward compat.

            using (var safePasswordHandle = new SafePasswordHandle(password))
            using (IExportPal storePal = StorePal.FromCertificate(Pal))
            {
                return storePal.Export(contentType, safePasswordHandle);
            }
        }

        [System.CLSCompliantAttribute(false)]
        public virtual byte[] Export(X509ContentType contentType, SecureString password)
        {
            VerifyContentType(contentType);

            if (Pal == null)
                throw new CryptographicException(ErrorCode.E_POINTER);  // Not the greatest error, but needed for backward compat.

            using (var safePasswordHandle = new SafePasswordHandle(password))
            using (IExportPal storePal = StorePal.FromCertificate(Pal))
            {
                return storePal.Export(contentType, safePasswordHandle);
            }
        }

Any objections against either adding byte[] Export(X509ContentType, SecureString) to ICertificatePal or is there a reason why it is a separate thing?

I don't mind about the one-method interface, but the static StorePal.FromCertificate() method in there is likely going to give me another corlib.dll versus System.dll headache.

@baulig
Copy link

baulig commented Jul 24, 2018

Found one more issue, in X509Certificate2.cs there is this piece of code:

       public bool Verify()
        {
            ThrowIfInvalid();

            using (var chain = new X509Chain())
            {
                // Use the default vales of chain.ChainPolicy including:
                //  RevocationMode = X509RevocationMode.Online
                //  RevocationFlag = X509RevocationFlag.ExcludeRoot
                //  VerificationFlags = X509VerificationFlags.NoFlag
                //  VerificationTime = DateTime.Now
                //  UrlRetrievalTimeout = new TimeSpan(0, 0, 0)

                bool verified = chain.Build(this, throwOnException: false);
                return verified;
            }
        }

Any objections against moving this into the PAL layer, so we can use the native validator instead of going through X509Chain?

@bartonjs
Copy link
Member

The ICertificatePal represents the active certificate, not an abstraction over several statics. In particular, the Apple one and the OpenSSL one each hold two pointers internally. So they'd need a very large rewrite to change them to "staticish calls with a context parameter".

Perhaps all this would be easier if Mono just typeforwarded X509Certificate or X509Certificate2 so they can live in the same assembly?

@bartonjs
Copy link
Member

Any changes that need to happen here (which can be more than one) need to be very easy to review. So very minimal changes for each change.

@baulig
Copy link

baulig commented Jul 24, 2018

Sure, I can split it down into small pieces. And the CertificatePal changes that I have in mind will actually be quite tiny.

@baulig
Copy link

baulig commented Jul 25, 2018

For the CertificatePal changes, with a minimum set of changes: #31344.

X509Certificate.Export() is also easy: #31343.

I also had a look a X509Certificate.Verify(), but don't like the result very much because it would mean adding three identical implementations here - I can probably handle that a lot better elsewhere.

@filipnavara
Copy link
Member Author

@baulig As for the static methods - already tracking that in separate issue (https://github.com/dotnet/corefx/issues/30606).

@filipnavara
Copy link
Member Author

I am open to name suggestions as long as we can agree on one.

Type-forwarding was one of the considered options, but there was really no discussion about it AFAIK. At the moment there's no type forwarding from mscorlib in Mono and I am not sure about the possible consequences of introducing a cyclic dependencies between assemblies.

There are generally two issues that we need to deal with.

First, the split between corlib and System. This only affects X509Certificate and couple of utility classes/enums. We already have a mechanism for loading the actual PAL implementation from System, but the interface contract needs to remain small and restricted to types we have available in mscorlib. Hence this patch. This solves the interface itself, but there's still issue with the static methods (CertificatePal.From* and Export mentioned above).

Second, Mono has a requirement that it can be compiled with more than one PAL (like OpenSSL + Apple crypto). Only one PAL would actually be used, but it would be selected at runtime and not compile time. That's what was the point of issue #30606 and @baulig's yesterday PRs for moving some code around.

@filipnavara
Copy link
Member Author

filipnavara commented Jul 25, 2018

Of the proposed names I kinda like ICertificatePalCore (or ICoreCertificatePal or ICertificateCorePal) because it would be in /cor/lib in Mono.

@baulig
Copy link

baulig commented Jul 25, 2018

After thinking about of it, I like ICertificatePalCore most.

@bartonjs
Copy link
Member

I'm fine with ICertificatePalCore

@filipnavara
Copy link
Member Author

Ok, I will update the PR.

@bartonjs bartonjs merged commit 963e4ff into dotnet:master Jul 26, 2018
@filipnavara filipnavara deleted the x509-icert2 branch July 30, 2018 04:59
@karelz karelz added this to the 3.0 milestone Aug 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants