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

[Xamarin.Android.Build.Tasks] use CRC64 over SHA1 and MD5 #3649

Merged
merged 2 commits into from Sep 30, 2019

Conversation

jonathanpeppers
Copy link
Member

@jonathanpeppers jonathanpeppers commented Sep 18, 2019

Context: #1580

Bump to xamarin/java.interop@397013ed

Changes: xamarin/java.interop@be6048e...397013e

Use of MD5 results in an inability to use Xamarin.Android on
FIPS-enabled machines, because when the System cryptography:
Use FIPS compliant algorithms for encryption,
hashing, and signing
setting is enabled on Windows:

'Use Fips compliant algorithms' setting

then the System.Security.Cryptography.MD5.Create() method will
throw InvalidOperationException.

In order to support FIPS-enabled machines, use a 64-bit
Cyclic redundancy check algorithm (CRC64) to instead generate
the Java package names, e.g. crc64aae7d955a89b38db.Name and
crc64217c8705f00a5054.Name. A simple implementation using a
lookup table will suffice for our purposes, ported to C# from:

https://github.com/gityf/crc/blob/8045f50ba6e4193d4ee5d2539025fef26e613c9f/crc/crc64.c

The use of CRC64 avoids the use of MD5, thus permitting execution on
FIPS-enabled Windows machines, and also results in shorter
directory names -- as the Java package name is a directory name --
which helps reduce Windows MAX_PATH issues.

Changes so far

All usage of MD5.Create() or new SHA1Managed() have been either:

  • Switched to use new Crc64()
  • Used Files.HashString if more appropriate

Calls to jarsigner now use:

-sigalg SHA256withRSA -digestalg SHA-256

The previous default can be restored via
$(AndroidApkSigningAlgorithm) and $(AndroidApkDigestAlgorithm)
MSBuild properties.

@dellis1972
Copy link
Contributor

We are doing to have to invalidate builds for this upgrade, we somehow need to delete any old files still using the MD5 hash (especially generated Java stuff).

@jonathanpeppers jonathanpeppers force-pushed the java.interop-crc64 branch 2 times, most recently from 495584f to 577e19a Compare September 20, 2019 20:09
@jonathanpeppers
Copy link
Member Author

Still working on how to fix the designer:

[2019-09-20 16:25:40.7] Renderer >> INFO: Trying to load class md5ac80b49d1943cc97166c48330708421e.AvatarView

This would be a crc64 hash now.

@jonathanpeppers jonathanpeppers force-pushed the java.interop-crc64 branch 3 times, most recently from f42733c to de6ded6 Compare September 24, 2019 02:52
@xamarin xamarin deleted a comment from azure-pipelines bot Sep 24, 2019
jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this pull request Sep 24, 2019
Context: https://dev.azure.com/DevDiv/DevDiv/_build/results?buildId=3075928&view=ms.vss-test-web.test-result-details

I was originally using this in xamarin#3649, but it seemed better to do this
in a separate PR.

If a `DeviceTest` fails, it can take a screenshot, add an attachment
to the failed test, and archive it as an artifact. This will help
troubleshoot if things like a button press fails, and if we add more
tests like this down the road.
Context: xamarin#1580

Bump to xamarin/java.interop@cd91e48

Changes: xamarin/java.interop@be6048e...cd91e48

Use of MD5 results in an inability to use Xamarin.Android on
FIPS-enabled machines, because when the **System cryptography:
[Use FIPS compliant algorithms][0] for encryption,
hashing, and signing** setting is enabled on Windows:

!['Use Fips compliant algorithms' setting][1]

then the `System.Security.Cryptography.MD5.Create()` method will
throw `InvalidOperationException`.

In order to support FIPS-enabled machines, use a 64-bit
[Cyclic redundancy check][2] algorithm (CRC64) to instead generate
the Java package names, e.g. `crc64aae7d955a89b38db.Name` and
`crc64217c8705f00a5054.Name`.  A simple implementation using a
lookup table will suffice for our purposes, ported to C# from:

    https://github.com/gityf/crc/blob/8045f50ba6e4193d4ee5d2539025fef26e613c9f/crc/crc64.c

The use of CRC64 avoids the use of MD5, thus permitting execution on
FIPS-enabled Windows machines, and also results in *shorter*
directory names -- as the Java package name is a directory name --
which helps reduce Windows `MAX_PATH` issues.

~~ Changes so far ~~

All usage of `MD5.Create()` or `new SHA1Managed()` have been either:

* Switched to use `new Crc64()`
* Used `Files.HashString` if more appropriate
* `<GetAdditionalResourcesFromAssemblies/>` now emits `XA0120` if
  `new SHA1Managed()` fails. We will deprecate this code path.

Calls to `jarsigner` now use:

    -sigalg SHA256withRSA -digestalg SHA-256

The previous default can be restored via
`$(AndroidApkSigningAlgorithm)` and `$(AndroidApkDigestAlgorithm)`
MSBuild properties.

`$(AndroidPackageNamingPolicy)` now defaults to `LowercaseCrc64`. The
previous default can be restored by setting
`AndroidPackageNamingPolicy=LowercaseMD5`.

`JNIEnv.Initialize()` sets `JavaNativeTypeManager.PackageNamingPolicy`
via the `__XA_PACKAGE_NAMING_POLICY__` environment variable.

`@(AndroidEnvironment)` values generated by Xamarin.Android at build
time are now placed in `$(IntermediateOutputPath)__environment__.txt`.

A new `_CleanIntermediateIfPackageNamingPolicyChanges` target will run
`_CleanMonoAndroidIntermediateDir` if `$(AndroidPackageNamingPolicy)`
changes. This is necessary because many Java source files will be
invalid.

[0]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/system-cryptography-use-fips-compliant-algorithms-for-encryption-hashing-and-signing
[1]: https://user-images.githubusercontent.com/24926263/38981221-7e0bf7c4-43dc-11e8-8f16-9b6d284a55fb.PNG
[2]: https://en.wikipedia.org/wiki/Cyclic_redundancy_check
jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this pull request Sep 24, 2019
Context: https://dev.azure.com/DevDiv/DevDiv/_build/results?buildId=3075928&view=ms.vss-test-web.test-result-details

I was originally using this in xamarin#3649, but it seemed better to do this
in a separate PR.

If a `DeviceTest` fails, it can take a screenshot, add an attachment
to the failed test, and archive it as an artifact. This will help
troubleshoot if things like a button press fails, and if we add more
tests like this down the road.

I used `/data/local/tmp/screenshot.png` as this path has been used by
`Fast Deployment` for a long time and Android hasn't changed it.
@jonathanpeppers jonathanpeppers marked this pull request as ready for review September 25, 2019 02:40
@jonathanpeppers
Copy link
Member Author

This is ready to review (I got all the tests to pass), but we still will need to wait on the designer changes before we can merge.

There is only one BCL test failure with the GC that seems unrelated.

@jonpryor
Copy link
Member

jonpryor commented Sep 28, 2019

@garuma: Please let us know when we can merge this PR. I assume that would be once https://github.com/xamarin/designer/pull/2394 is merged.

@jonpryor jonpryor merged commit 88a1d6c into xamarin:master Sep 30, 2019
@jonathanpeppers jonathanpeppers deleted the java.interop-crc64 branch September 30, 2019 16:45
jonpryor pushed a commit that referenced this pull request Sep 30, 2019
Context: #1580

Bump to xamarin/java.interop@b98f4232

Changes: xamarin/java.interop@4fd3539...b98f423

Use of MD5 results in an inability to use Xamarin.Android on FIPS-
enabled machines, because when the **System cryptography:
[Use FIPS compliant algorithms][0] for encryption, hashing, and
signing** setting is enabled on Windows:

!['Use Fips compliant algorithms' setting][1]

then the `System.Security.Cryptography.MD5.Create()` method will
throw `InvalidOperationException`.

In order to support FIPS-enabled machines, use a 64-bit
[Cyclic redundancy check][2] algorithm (CRC64) to instead generate
the Java package names, e.g. `crc64aae7d955a89b38db.Name` and
`crc64217c8705f00a5054.Name`.  A simple implementation using a
lookup table will suffice for our purposes, ported to C# from:

	https://github.com/gityf/crc/blob/8045f50ba6e4193d4ee5d2539025fef26e613c9f/crc/crc64.c

The use of CRC64 avoids the use of MD5, thus permitting execution on
FIPS-enabled Windows machines, and also results in *shorter*
directory names -- as the Java package name is a directory name --
which helps reduce Windows `MAX_PATH` issues.

All usage of `MD5.Create()` or `new SHA1Managed()` have been either:

  * Switched to use `new Crc64()`
  * Used `Files.HashString()` if more appropriate
  * `<GetAdditionalResourcesFromAssemblies/>` now emits warning
    `XA0120` if `new SHA1Managed()` fails.

    We will deprecate this code path.

Calls to `jarsigner` now use:

	-sigalg SHA256withRSA -digestalg SHA-256

The previous default can be restored via
`$(AndroidApkSigningAlgorithm)` and `$(AndroidApkDigestAlgorithm)`
MSBuild properties.

`$(AndroidPackageNamingPolicy)` now defaults to `LowercaseCrc64`.
The previous default can be restored by setting
`$(AndroidPackageNamingPolicy)=LowercaseMD5`.

`JNIEnv.Initialize()` sets `JavaNativeTypeManager.PackageNamingPolicy`
via the `__XA_PACKAGE_NAMING_POLICY__` environment variable.

`@(AndroidEnvironment)` values generated by Xamarin.Android at build
time are now placed in `$(IntermediateOutputPath)__environment__.txt`.

A new `_CleanIntermediateIfPackageNamingPolicyChanges` target will run
`_CleanMonoAndroidIntermediateDir` if `$(AndroidPackageNamingPolicy)`
changes. This is necessary because many Java source files will be
invalid.

[0]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/system-cryptography-use-fips-compliant-algorithms-for-encryption-hashing-and-signing
[1]: https://user-images.githubusercontent.com/24926263/38981221-7e0bf7c4-43dc-11e8-8f16-9b6d284a55fb.PNG
[2]: https://en.wikipedia.org/wiki/Cyclic_redundancy_check
jonpryor pushed a commit that referenced this pull request Oct 1, 2019
Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3096255&view=ms.vss-test-web.build-test-results-tab&runId=8756400&resultId=100484&paneView=debug

Commit 88a1d6c introduced multiple unit test regressions in e.g.
`ManagedResourceParserTests.GenerateDesignerFileFromRtxt()`:

	…\GenerateDesignerFileFromRtxtTrue Some Space\Resource.designer.cs and …\bin\TestRelease\Expected\GenerateDesignerFileWithLibraryReferenceExpected.cs do not match.
	Expected: True
	 But was: False 

The cause of the breakage is that commit 88a1d6c removed the use of
`BaseTest.ReadAllBytesIgnoringLineEndings()` for file comparisons.
On Windows, the generated `Resource.designer.cs` file contains
Windows line endings (CRLF), while the in-repro copy has Unix (LF)
line endings.  This causes the file comparisons to fail.

The test failures weren't seen on PR #3649 because the test failures
occur on the **MSBuild - Windows** test job added in f91cd2d, which
hadn't yet been merged when PR #3649 was being written.

In exploring these test failures, a usability problem arose: we knew
that the file contents differed, because of the assert message, but
we didn't know *how* the file contents differed, nor *could* we
obtain the files until 936459c, because they weren't uploaded.

Add a `BaseTest.AssertFileContentsMatch()` method, which:

 1. Uses `ReadAllBytesIgnoringLineEndings()`, which fixes the
    regressions introduced in 88a1d6c.

 2. Adds the files as Azure test attachments, so that we can easily
    see their contents from the unit test failure screen.
jonpryor pushed a commit that referenced this pull request Oct 1, 2019
Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3096255&view=ms.vss-test-web.build-test-results-tab&runId=8756400&resultId=100484&paneView=debug

Commit 88a1d6c introduced multiple unit test regressions in e.g.
`ManagedResourceParserTests.GenerateDesignerFileFromRtxt()`:

	…\GenerateDesignerFileFromRtxtTrue Some Space\Resource.designer.cs and …\bin\TestRelease\Expected\GenerateDesignerFileWithLibraryReferenceExpected.cs do not match.
	Expected: True
	 But was: False 

The cause of the breakage is that commit 88a1d6c removed the use of
`BaseTest.ReadAllBytesIgnoringLineEndings()` for file comparisons.
On Windows, the generated `Resource.designer.cs` file contains
Windows line endings (CRLF), while the in-repro copy has Unix (LF)
line endings.  This causes the file comparisons to fail.

The test failures weren't seen on PR #3649 because the test failures
occur on the **MSBuild - Windows** test job added in f91cd2d, which
hadn't yet been merged when PR #3649 was being written.

In exploring these test failures, a usability problem arose: we knew
that the file contents differed, because of the assert message, but
we didn't know *how* the file contents differed, nor *could* we
obtain the files until 936459c, because they weren't uploaded.

Add a `BaseTest.AssertFileContentsMatch()` method, which:

 1. Uses `ReadAllBytesIgnoringLineEndings()`, which fixes the
    regressions introduced in 88a1d6c.

 2. Adds the files as Azure test attachments, so that we can easily
    see their contents from the unit test failure screen.
@github-actions github-actions bot locked and limited conversation to collaborators Jan 29, 2024
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.

None yet

5 participants