Skip to content

Commit

Permalink
Merge branch 'develop' into evp_factory. Picks up 1.6.0 version
Browse files Browse the repository at this point in the history
* develop:
  Remove dead code and bump patch version
  Add logic to generate a classpath file
  Clarify best practices are local to ACCP
  Improve documentation (corretto#151)
  Update CHANGELOG for 1.6.0 (corretto#148)
  Handle RsaCipher#engineDoFinal with no input bytes (corretto#147)
  Validate that AesGcmSpi#engineInit gets non-null key (corretto#146)
  Move to OpenSSL 1.1.1j (corretto#145)
  Add list of known differences (corretto#137)
  Better output size estimates. Fixes corretto#135
  Move to openssl 1.1.1i (corretto#136)
  Initial commit of the development guide (corretto#134)
  • Loading branch information
SalusaSecondus committed Apr 15, 2021
2 parents 1ef9b1a + 93da63c commit 6e67e13
Show file tree
Hide file tree
Showing 14 changed files with 522 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/build
/.gradle
/.project
/.settings/
/.vscode/
/.idea/
Expand All @@ -10,3 +9,4 @@
*.iws
*.iml
*.orig
/.classpath
28 changes: 28 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>AmazonCorrettoCryptoProvider</name>
<comment>Project amazon-corretto-crypto-provider file has been manually crafted.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<filteredResources>
<filter>
<id>0</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
22 changes: 13 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ We're marking this as a major version release due to new implementions of `KeyFa
Though these changes are expected to have no visible impact (other than performance) to consumers,
they do correspond to a significant rearchitecture of ACCP.

### Improvements
* Add `KeyFactory` implementations for RSA, EC, DH, and DSA keys. This also includes our own implementations of keys for the same algorithms. [PR #132](https://github.com/corretto/amazon-corretto-crypto-provider/pull/132)

### Patches
* Correctly reject non-empty `PSource.PSpecified` values for RSA-OAEP.

## 1.6.0
### Breaking Change
In accordance with our [versioning policy](https://github.com/corretto/amazon-corretto-crypto-provider/blob/master/VERSIONING.rst),
this release contains a low-risk breaking change. For details please see the [1.5.0](#150) section of this document.
Expand All @@ -16,18 +23,15 @@ method.
* Stricter guarantees about which curves are used for EC key generation. [PR #127](https://github.com/corretto/amazon-corretto-crypto-provider/pull/127)
* Reduce timing signal from trimming zeros of TLSPremasterSecrets from DH KeyAgreement. [PR #129](https://github.com/corretto/amazon-corretto-crypto-provider/pull/129)
* Reuse state in `MessageDigest` to decrease object allocation rate. [PR #131](https://github.com/corretto/amazon-corretto-crypto-provider/pull/131)
* Add `KeyFactory` implementations for RSA, EC, DH, and DSA keys. This also includes our own implementations of keys for the same algorithms. [PR #132](https://github.com/corretto/amazon-corretto-crypto-provider/pull/132)
* Now uses [OpenSSL 1.1.1j](https://www.openssl.org/source/openssl-1.1.1j.tar.gz). [PR #145](https://github.com/corretto/amazon-corretto-crypto-provider/pull/145)
(ACCP is not impacted by [CVE-2020-1971](https://www.openssl.org/news/secadv/20201208.txt), [CVE-2021-23841](https://www.openssl.org/news/secadv/20210216.txt), or [CVE-2021-23839](https://www.openssl.org/news/secadv/20210216.txt) as ACCP does not use or expose any of the relevant functionality.
ACCP is not impacted by [CVE-2021-23840](https://www.openssl.org/news/secadv/20210216.txt) as ACCP does not use the relevant functionality under the affected conditions.)

### Patches
* Add version gating to some tests introduced in 1.5.0 [PR #128](https://github.com/corretto/amazon-corretto-crypto-provider/pull/128)
* Correctly reject non-empty `PSource.PSpecified` values for RSA-OAEP.

## 1.6.0 (Never Released)
This entry is for the planned, but never released, version 1.6.0 to assist in cross-references from the release notes in 1.5.0.

This version was not released because other changes to ACCP planned for the same time were significant enough to warrant a major version bump.

Please see the release notes for 2.0.0.
* More accurate output size estimates from `Cipher.getOutputSize()` [PR #138](https://github.com/corretto/amazon-corretto-crypto-provider/pull/138)
* Validate that `AesGcmSpi` receives a non-null key on init to prevent unnecessarily late NPE [PR #146](https://github.com/corretto/amazon-corretto-crypto-provider/pull/146)
* Gracefully handle calling `Cipher.doFinal()` without any input bytes in `RsaCipher` [PR #147](https://github.com/corretto/amazon-corretto-crypto-provider/pull/147)

## 1.5.0
### Breaking Change Warning
Expand Down
169 changes: 169 additions & 0 deletions DEVELOPMENT-GUIDE.md

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions DIFFERENCES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Important Differences
The [JCA/JCE](https://docs.oracle.com/en/java/javase/11/security/java-cryptography-architecture-jca-reference-guide.html) specification does not completely define all behaviors of a given provider.
Although the Amazon Corretto Crypto Provider (ACCP) is fully compliant with the JCE, its behavior differs from the behavior of the default Java providers in several ways.
The following list of behavioral differences is not exhaustive, but is intended to capture the most important differences.

Despite these differences, ACCP remains a drop-in replacement for the vast majority of Java applications and doesn't change the application behavior, other than improving its performance.

# Behavior Changes
These differences are those most likely to be noticed by a consuming application. You might need to make minor changes to accommodate them.

## SignatureException
The official documentation does not fully specify when the [Signature](https://docs.oracle.com/javase/8/docs/api/java/security/Signature.html) object is expected to throw a [SignatureException](https://docs.oracle.com/javase/8/docs/api/java/security/SignatureException.html).
Having multiple different ways to reject a signature (such as `signature.verify() == false` and throwing a `SignatureException`) is an anti-pattern and we should try to avoid it.
ACCP throws a `SignatureException` from `Signature.verify()` only when not throwing would introduce compatibility issues (such as with the [JCK](https://en.wikipedia.org/wiki/Technology_Compatibility_Kit#TCK_for_the_Java_platform).)
Currently, ACCP will throw a `SignatureException` only when verifying an EDSA or DSA signature that is not properly encoded.
In all other cases, ACCP will return `false` from `Signature.verify()` when given an invalid signature.
This is different from the default OpenJDK implementation, which also inspects the inner structure of RSA signatures and rejects them with a `SignatureException` if they are improperly encoded.
ACCP follows the guidance provided in [PKCS #1 section 8.2.2](https://tools.ietf.org/html/rfc8017#section-8.2.2) in that it does not parse the inner structure but, instead, does a binary comparison against the expected value.

For this reason, regardless of whether you use ACCP or not, we recommend the following structure for signature verification:
```java
Signature signatureObject = Signature.getInstance(SIGNATURE_ALGORITHM);
signatureObject.initVerify(publicKey);
signatureObject.update(messageToVerify);
boolean signatureValid = false;
try {
signatureValid = signatureObject.verify(signature);
} catch (final SignatureException ex) {
signatureValid = false;
}
```

## Elliptic Curve KeyPairGeneration by curve size
Neither the JCE nor the default OpenJDK provider for Elliptic Curve Cryptography (SunEC) specify the effect of calling `KeyPairGenerator.initialize(int keysize)` with an arbitrary value.
This behavior is fully specified only for values of 192, 224, 256, 384, and 521.
This means that applications cannot depend on receiving a specific curve for any other value. Also, the application might encounter compatibility issues if SunEC ever changes its behavior or if the application changes to a different JCE provider.
In ACCP (after version 1.5.0), the `KeyPairGenerator.initialize(int keysize)` method fails with an `InvalidParameterException` for `keysize` values other than 192, 224, 256, 384, and 521.

For this reason, even if you don't use ACCP, we recommend that you use only the [KeyPairGenerator.initialize(AlgorithmParameterSpec params)](https://docs.oracle.com/javase/8/docs/api/java/security/KeyPairGenerator.html#initialize-java.security.spec.AlgorithmParameterSpec-) method with an [ECGenParameterSpec](https://docs.oracle.com/javase/8/docs/api/java/security/spec/ECGenParameterSpec.html) to generate EC keys.
This construction is safe for all known JCE providers and is expected to remain safe even if the behavior of a provider changes.

For more information, see the [changelog](./CHANGELOG.md) notes for version 1.5.0.

## Cipher.getOutputSize() for AES-GCM
ACCP might overestimate the amount of space needed when encrypted with `AES/GCM/NoPadding` on versions prior to 1.6.0.
While this is compliant with the JCE (which [permits overestimation](https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html#getOutputSize-int-)) it has caused confusion for some developers.


## SecureRandom is never deterministic
Some implementation of `SecureRandom` (such as `SHA1PRNG`, provided by the default OpenJDK cryptographic providers) can operate deterministically if `SecureRandom.setSeed(byte[])` is called prior to any other methods.
This behavior allows for insecure seeding and might make the application less secure if it requires the `SecureRandom` instance to provide secure entropy (such as for cryptographic use).
The `SecureRandom` implementation provided by ACCP automatically seeds itself upon creation and cannot be used in a deterministic manner.
This change is relevant only to systems that need deterministic behavior based on a seed, such as in some simulations.
Systems that need deterministic behavior should not use an ACCP implementation of `SecureRandom`. They should select an implementation/algorithm that specifically meets their needs.

## SecureRandom uses thread local state internally
To avoid the costs of both RNG initialization and thread contention, ACCP maintains a single internal instance of SecureRandom for each thread.
Any time an instance of `SecureRandom` is used, ACCP routes the requests to the appropriate backing instance for the calling thread.
Because the output of calls to `SecureRandom` is computationally indistinguishable from actual random data, this implementation detail has no impact on callers other than improving performance.

# Extensions
Applications are unlikely to directly encounter any of these changes but may choose to take advantage of them.

## AES-GCM supports IvParameterSpec
ACCP allows use of [IvParameterSpec](https://docs.oracle.com/javase/8/docs/api/javax/crypto/spec/IvParameterSpec.html) when calling [Cipher.init()](https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html#init-int-java.security.Key-java.security.spec.AlgorithmParameterSpec-).
This is equivalent to using a [GCMParameterSpec](https://docs.oracle.com/javase/8/docs/api/javax/crypto/spec/GCMParameterSpec.html) with the same IV value and a tag length of 128 bits.
By supporting the same ParameterSpec as other ciphers (such as `AES/CBC/PKCS5Padding`, which should not be used as it is no longer secure), ACCP makes it easier to migrate to the secure choice of `AES/GCM/NoPadding`.
(This behavior is identical to how [BouncyCastle](https://bouncycastle.org/java.html) treats `IvParameterSpec` when used with AES-GCM.)

## KeyAgreement supports reuse without reinitialization
ACCP permits reuse of a [KeyAgreement](https://docs.oracle.com/javase/8/docs/api/javax/crypto/KeyAgreement.html) object without calling `.init()` more than once.
This results in better performance for Static-Ephemeral key agreement protocols.

## AES is supported as a target key type for all KeyAgreement algorithms and supports an explicit size
[KeyAgreement.generateSecret(String)](https://docs.oracle.com/javase/8/docs/api/javax/crypto/KeyAgreement.html#generateSecret-java.lang.String-) can be called with an input of "AES" for all Key Agreement algorithms.
(The default Java implementation does not support "AES" as input with "ECDH" key agreement.)
If "AES" is passed to this method, ACCP returns the largest possible AES key corresponding to the agreed secret.
Alternatively, you can request an AES key of a particular size by appending the size (in bits) surrounded by brackets to this string.
(Ex: "AES[128]" or "AES[256]")
This returns a key of the requested strength or an `InvalidKeyException` if the agreed secret is not long enough for the requested AES key length.
(This method of specifying key size is identical to the way [BouncyCastle](https://bouncycastle.org/java.html) specifies key size for `KeyAgreement.generateSecret(String)`.)
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# Amazon Corretto Crypto Provider
The Amazon Corretto Crypto Provider (ACCP) is a collection of high-performance cryptographic implementations exposed via the standard [JCA/JCE](https://docs.oracle.com/en/java/javase/11/security/java-cryptography-architecture-jca-reference-guide.html) interfaces.
This means that it can be used as a drop in replacement for many different Java applications.
Currently algorithms are primarily backed by OpenSSL's implementations (1.1.1g as of ACCP 1.5.0) but this may change in the future.
(Differences from the default OpenJDK implementations are [documented here](./DIFFERENCES.md).)
Currently algorithms are primarily backed by OpenSSL's implementations (1.1.1j as of ACCP 1.6.0) but this may change in the future.

[Security issue notifications](./CONTRIBUTING.md#security-issue-notifications)


## Build Status
Please be aware that "Overkill" tests are known to be flakey
Please be aware that both "Overkill" and "Dieharder" tests are known to be flakey.
Both of these tests are flakey because they include entropy generation tests
(specificaly, the [Dieharder tests](http://webhome.phy.duke.edu/~rgb/General/dieharder.php)).
Entropy tests are unavoidably flakey because there is always a possibility that a high-quality
random number generator will output data which looks non-random.
(For example, even a fair coin will come up heads ten times in a row about one in a thousand trials.)

| Build Name | master branch | develop branch |
| ---------- | ------------- | -------------- |
Expand Down Expand Up @@ -100,6 +106,8 @@ Whether you're using Maven, Gradle, or some other build system that also pulls
packages from Maven Central, it's important to specify `linux-x86_64` as the
classifier. You'll get an empty package otherwise.

Regardless of how you acquire ACCP (Maven, manual build, etc.) you will still need to follow the guidance in the [Configuration section][#configuration] to enable ACCP in your application.

### Maven
Add the following to your `pom.xml` or wherever you configure your Maven dependencies.
This will instruct it to use the most recent 1.x version of ACCP.
Expand Down Expand Up @@ -166,6 +174,7 @@ Building this provider requires a 64 bit Linux build system with the following p
* coverage: Run target `test` and collect both Java and C++ coverage metrics (saved in `build/reports`)
* release: **Default target** depends on build, test, and coverage
* overkill: Run **all** tests (no coverage)
* generateEclipseClasspath: Generates a `.classpath` file which is understandable by Eclipse and VS Code to make development easier. (This should ideally be run prior to opening ACCP in your IDE.)

## Configuration
There are several ways to configure the ACCP as the highest priority provider in Java.
Expand All @@ -184,13 +193,13 @@ If you want to check to verify that ACCP is properly working on your system, you
1. Verify that the highest priority provider actually is ACCP:
```java
if (Cipher.getInstance("AES/GCM/NoPadding").getProvider().getName().equals(AmazonCorrettoCryptoProvider.PROVIDER_NAME)) {
// Successfully installed
// Successfully installed
}
```
2. Ask ACCP about its health
```java
if (AmazonCorrettoCryptoProvider.INSTANCE.getLoadingError() == null && AmazonCorrettoCryptoProvider.INSTANCE.runSelfTests().equals(SelfTestStatus.PASSED)) {
// Successfully installed
// Successfully installed
}
```
3. Assert that ACCP is healthy and throw a `RuntimeCryptoException` if it isn't.
Expand Down
46 changes: 45 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import groovy.xml.*

plugins {
id 'maven-publish'
id 'signing'
Expand All @@ -9,7 +11,7 @@ plugins {
group = 'software.amazon.cryptools'
version = '2.0.0'

def openssl_version = '1.1.1g'
def openssl_version = '1.1.1j'
def opensslSrcPath = "${buildDir}/openssl/openssl-${openssl_version}"

configurations {
Expand Down Expand Up @@ -462,4 +464,46 @@ task deep_clean(type: Delete) {

task cmake_clean(type: Delete) {
delete "${buildDir}/cmake"
delete "${buildDir}/cmake-coverage"
}
task generateEclipseClasspath {
doLast {
file(".classpath").withWriter { writer ->
// Create MarkupBuilder with 4 space indent
def xml = new MarkupBuilder(new IndentPrinter(writer, " ", true))

xml.doubleQuotes = true
xml.mkp.xmlDeclaration(version: '1.0', encoding: 'utf-8')
xml.classpath {
classpathentry('kind': 'con', 'path': 'org.eclipse.jdt.launching.JRE_CONTAINER') {
attributes {
attribute('name': 'module', 'value': 'true')
}
}
classpathentry('kind': 'src', 'output': 'build/eclipse/src', 'path': 'src')
classpathentry('kind': 'src', 'output': 'build/eclipse/template-src', 'path': 'template-src')
classpathentry('kind': 'src', 'output': 'build/eclipse/tst', 'path': 'tst') {
attributes {
attribute('name': 'test', 'value': 'true')
}
}
classpathentry('kind': 'src', 'output': 'build/eclipse/src', 'path': 'build/cmake/generated-java') {
attributes {
attribute('name': 'optional', 'value': 'true')
}
}
classpathentry('kind': 'src', 'output': 'build/eclipse/src', 'path': 'build/coverage-cmake/generated-java') {
attributes {
attribute('name': 'optional', 'value': 'true')
}
}

configurations.testDep.files.each{f ->
classpathentry('kind': 'lib', 'path': f) {
attribute('name': 'test', 'value': 'true')
}
}
} // xml.classpath
} // file.withWriter
} // doLast
} // generateEclipseClasspath
2 changes: 1 addition & 1 deletion openssl.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz
aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf openssl-1.1.1j.tar.gz
Loading

0 comments on commit 6e67e13

Please sign in to comment.