Skip to content

Commit

Permalink
Merge pull request dotnet#769 from vcsjones/735-fix
Browse files Browse the repository at this point in the history
Preserve HResult for bad password in managed PKCS12 PAL
  • Loading branch information
bartonjs authored Dec 12, 2019
2 parents e8a90ce + 058e5b0 commit f58a38c
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ internal static class CryptoThrowHelper
public static CryptographicException ToCryptographicException(this int hr)
{
string message = Interop.Kernel32.GetMessage(hr);

if ((hr & 0x80000000) != 0x80000000)
hr = (hr & 0x0000FFFF) | unchecked((int)0x80070000);

return new WindowsCryptographicException(hr, message);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace Internal.Cryptography.Pal
internal abstract class UnixPkcs12Reader : IDisposable
{
private const string DecryptedSentinel = nameof(UnixPkcs12Reader);
private const int ErrorInvalidPasswordHResult = unchecked((int)0x80070056);

private PfxAsn _pfxAsn;
private ContentInfoAsn[] _safeContentsValues;
Expand Down Expand Up @@ -190,7 +191,10 @@ public void Decrypt(SafePasswordHandle password)
}
catch (Exception e)
{
throw new CryptographicException(SR.Cryptography_Pfx_BadPassword, e);
throw new CryptographicException(SR.Cryptography_Pfx_BadPassword, e)
{
HResult = ErrorInvalidPasswordHResult
};
}
finally
{
Expand Down Expand Up @@ -225,7 +229,10 @@ private void VerifyAndDecrypt(ReadOnlySpan<char> password, ReadOnlyMemory<byte>
return;
}

throw new CryptographicException(SR.Cryptography_Pfx_BadPassword);
throw new CryptographicException(SR.Cryptography_Pfx_BadPassword)
{
HResult = ErrorInvalidPasswordHResult
};
}

private void Decrypt(ReadOnlySpan<char> password, ReadOnlyMemory<byte> authSafeContents)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public abstract partial class PfxFormatTests
// Use a MAC count of 1 because we're not persisting things, and the password
// is with the test... just save some CPU cycles.
private const int MacCount = 1;
protected const int ErrorInvalidPasswordHResult = unchecked((int)0x80070056);

// Use SHA-1 for Windows 7-8.1 support.
private static readonly HashAlgorithmName s_digestAlgorithm = HashAlgorithmName.SHA1;
Expand Down Expand Up @@ -764,7 +765,7 @@ public void CertAndKeyTwice_KeysUntagged()
cert2.Attributes.Add(id2);
key1.Attributes.Add(id3);
key2.Attributes.Add(id4);

AddContents(keyContents, builder, pw, encrypt: false);
AddContents(certContents, builder, pw, encrypt: true);
builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
Expand Down Expand Up @@ -815,7 +816,7 @@ public void CertTwice_KeyOnce(bool addLocalKeyId)
-2146893819);
}
}

[Theory]
[InlineData(false, false)]
[InlineData(false, true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ protected override void ReadWrongPassword(byte[] pfxBytes, string wrongPassword)
() => coll.Import(pfxBytes, wrongPassword, s_importFlags));

AssertMessageContains("password", ex);
Assert.Equal(ErrorInvalidPasswordHResult, ex.HResult);
}

protected override void ReadUnreadablePfx(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ protected override void ReadWrongPassword(byte[] pfxBytes, string wrongPassword)
() => new X509Certificate2(pfxBytes, wrongPassword, s_importFlags));

AssertMessageContains("password", ex);
Assert.Equal(ErrorInvalidPasswordHResult, ex.HResult);
}

protected override void ReadUnreadablePfx(
Expand Down

0 comments on commit f58a38c

Please sign in to comment.